2 * linux/drivers/message/fusion/mptbase.c
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
5 * For use with LSI Logic PCI chip/adapter(s)
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2005 LSI Logic Corporation
9 * (mailto:mpt_linux_developer@lsil.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
49 #include <linux/config.h>
50 #include <linux/kernel.h>
51 #include <linux/module.h>
52 #include <linux/errno.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/types.h>
56 #include <linux/pci.h>
57 #include <linux/kdev_t.h>
58 #include <linux/blkdev.h>
59 #include <linux/delay.h>
60 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
61 #include <linux/dma-mapping.h>
67 #include <asm/irq.h> /* needed for __irq_itoa() proto */
72 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
73 #define my_NAME "Fusion MPT base driver"
74 #define my_VERSION MPT_LINUX_VERSION_COMMON
75 #define MYNAM "mptbase"
77 MODULE_AUTHOR(MODULEAUTHOR);
78 MODULE_DESCRIPTION(my_NAME);
79 MODULE_LICENSE("GPL");
85 static int mfcounter = 0;
86 #define PRINT_MF_COUNT 20000
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
93 int mpt_lan_index = -1;
94 int mpt_stm_index = -1;
96 struct proc_dir_entry *mpt_proc_root_dir;
98 #define WHOINIT_UNKNOWN 0xAA
100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
104 /* Adapter link list */
106 /* Callback lookup table */
107 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
108 /* Protocol driver class lookup table */
109 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
110 /* Event handler lookup table */
111 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Reset handler lookup table */
113 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
114 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
116 static int mpt_base_index = -1;
117 static int last_drv_idx = -1;
119 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
125 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
126 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
127 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
128 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
130 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
131 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
132 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
133 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
135 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
136 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
137 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
138 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
139 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
140 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
141 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
142 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
143 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
144 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
145 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
146 static int PrimeIocFifos(MPT_ADAPTER *ioc);
147 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
148 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150 static int GetLanConfigPages(MPT_ADAPTER *ioc);
151 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
152 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
153 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
154 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
155 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
156 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
157 static void mpt_timer_expired(unsigned long data);
158 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
159 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
160 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
161 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
163 #ifdef CONFIG_PROC_FS
164 static int procmpt_summary_read(char *buf, char **start, off_t offset,
165 int request, int *eof, void *data);
166 static int procmpt_version_read(char *buf, char **start, off_t offset,
167 int request, int *eof, void *data);
168 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
171 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
173 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
174 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
175 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
176 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
177 static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
178 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
180 /* module entry point */
181 static int __init fusion_init (void);
182 static void __exit fusion_exit (void);
184 #define CHIPREG_READ32(addr) readl_relaxed(addr)
185 #define CHIPREG_READ32_dmasync(addr) readl(addr)
186 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
187 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
188 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
191 pci_disable_io_access(struct pci_dev *pdev)
195 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
197 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
201 pci_enable_io_access(struct pci_dev *pdev)
205 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
207 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
211 * Process turbo (context) reply...
214 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
216 MPT_FRAME_HDR *mf = NULL;
217 MPT_FRAME_HDR *mr = NULL;
221 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
224 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
225 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
226 req_idx = pa & 0x0000FFFF;
227 cb_idx = (pa & 0x00FF0000) >> 16;
228 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
230 case MPI_CONTEXT_REPLY_TYPE_LAN:
231 cb_idx = mpt_lan_index;
233 * Blind set of mf to NULL here was fatal
234 * after lan_reply says "freeme"
235 * Fix sort of combined with an optimization here;
236 * added explicit check for case where lan_reply
237 * was just returning 1 and doing nothing else.
238 * For this case skip the callback, but set up
239 * proper mf value first here:-)
241 if ((pa & 0x58000000) == 0x58000000) {
242 req_idx = pa & 0x0000FFFF;
243 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
244 mpt_free_msg_frame(ioc, mf);
249 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
251 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
252 cb_idx = mpt_stm_index;
253 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
260 /* Check for (valid) IO callback! */
261 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
262 MptCallbacks[cb_idx] == NULL) {
263 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
264 __FUNCTION__, ioc->name, cb_idx);
268 if (MptCallbacks[cb_idx](ioc, mf, mr))
269 mpt_free_msg_frame(ioc, mf);
275 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
286 /* non-TURBO reply! Hmmm, something may be up...
287 * Newest turbo reply mechanism; get address
288 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
291 /* Map DMA address of reply header to cpu address.
292 * pa is 32 bits - but the dma address may be 32 or 64 bits
293 * get offset based only only the low addresses
296 reply_dma_low = (pa <<= 1);
297 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
298 (reply_dma_low - ioc->reply_frames_low_dma));
300 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
301 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
302 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
304 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
305 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
306 DBG_DUMP_REPLY_FRAME(mr)
308 /* Check/log IOC log info
310 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
311 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
312 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
313 if (ioc->bus_type == FC)
314 mpt_fc_log_info(ioc, log_info);
315 else if (ioc->bus_type == SPI)
316 mpt_sp_log_info(ioc, log_info);
317 else if (ioc->bus_type == SAS)
318 mpt_sas_log_info(ioc, log_info);
320 if (ioc_stat & MPI_IOCSTATUS_MASK) {
321 if (ioc->bus_type == SPI &&
322 cb_idx != mpt_stm_index &&
323 cb_idx != mpt_lan_index)
324 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
328 /* Check for (valid) IO callback! */
329 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
330 MptCallbacks[cb_idx] == NULL) {
331 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
332 __FUNCTION__, ioc->name, cb_idx);
337 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
340 /* Flush (non-TURBO) reply with a WRITE! */
341 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
344 mpt_free_msg_frame(ioc, mf);
348 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
350 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
351 * @irq: irq number (not used)
352 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
353 * @r: pt_regs pointer (not used)
355 * This routine is registered via the request_irq() kernel API call,
356 * and handles all interrupts generated from a specific MPT adapter
357 * (also referred to as a IO Controller or IOC).
358 * This routine must clear the interrupt from the adapter and does
359 * so by reading the reply FIFO. Multiple replies may be processed
360 * per single call to this routine.
362 * This routine handles register-level access of the adapter but
363 * dispatches (calls) a protocol-specific callback routine to handle
364 * the protocol-specific details of the MPT request completion.
367 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
369 MPT_ADAPTER *ioc = bus_id;
373 * Drain the reply FIFO!
376 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
377 if (pa == 0xFFFFFFFF)
379 else if (pa & MPI_ADDRESS_REPLY_A_BIT)
382 mpt_turbo_reply(ioc, pa);
388 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
390 * mpt_base_reply - MPT base driver's callback routine; all base driver
391 * "internal" request/reply processing is routed here.
392 * Currently used for EventNotification and EventAck handling.
393 * @ioc: Pointer to MPT_ADAPTER structure
394 * @mf: Pointer to original MPT request frame
395 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
397 * Returns 1 indicating original alloc'd request frame ptr
398 * should be freed, or 0 if it shouldn't.
401 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
406 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
408 #if defined(MPT_DEBUG_MSG_FRAME)
409 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
410 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
411 DBG_DUMP_REQUEST_FRAME_HDR(mf)
415 func = reply->u.hdr.Function;
416 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
419 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
420 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
424 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
425 if (results != evHandlers) {
426 /* CHECKME! Any special handling needed here? */
427 devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
428 ioc->name, evHandlers, results));
432 * Hmmm... It seems that EventNotificationReply is an exception
433 * to the rule of one reply per request.
435 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
437 devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
438 ioc->name, pEvReply));
440 devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
441 ioc->name, pEvReply));
444 #ifdef CONFIG_PROC_FS
445 // LogEvent(ioc, pEvReply);
448 } else if (func == MPI_FUNCTION_EVENT_ACK) {
449 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
451 } else if (func == MPI_FUNCTION_CONFIG ||
452 func == MPI_FUNCTION_TOOLBOX) {
456 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
457 ioc->name, mf, reply));
459 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
462 /* disable timer and remove from linked list */
463 del_timer(&pCfg->timer);
465 spin_lock_irqsave(&ioc->FreeQlock, flags);
466 list_del(&pCfg->linkage);
467 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
470 * If IOC Status is SUCCESS, save the header
471 * and set the status code to GOOD.
473 pCfg->status = MPT_CONFIG_ERROR;
475 ConfigReply_t *pReply = (ConfigReply_t *)reply;
478 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
479 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
480 status, le32_to_cpu(pReply->IOCLogInfo)));
482 pCfg->status = status;
483 if (status == MPI_IOCSTATUS_SUCCESS) {
484 if ((pReply->Header.PageType &
485 MPI_CONFIG_PAGETYPE_MASK) ==
486 MPI_CONFIG_PAGETYPE_EXTENDED) {
487 pCfg->cfghdr.ehdr->ExtPageLength =
488 le16_to_cpu(pReply->ExtPageLength);
489 pCfg->cfghdr.ehdr->ExtPageType =
492 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
494 /* If this is a regular header, save PageLength. */
495 /* LMP Do this better so not using a reserved field! */
496 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
497 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
498 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
503 * Wake up the original calling thread
508 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
509 /* we should be always getting a reply frame */
510 memcpy(ioc->persist_reply_frame, reply,
511 min(MPT_DEFAULT_FRAME_SIZE,
512 4*reply->u.reply.MsgLength));
513 del_timer(&ioc->persist_timer);
514 ioc->persist_wait_done = 1;
517 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
522 * Conditionally tell caller to free the original
523 * EventNotification/EventAck/unexpected request frame!
528 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
530 * mpt_register - Register protocol-specific main callback handler.
531 * @cbfunc: callback function pointer
532 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
534 * This routine is called by a protocol-specific driver (SCSI host,
535 * LAN, SCSI target) to register it's reply callback routine. Each
536 * protocol-specific driver must do this before it will be able to
537 * use any IOC resources, such as obtaining request frames.
539 * NOTES: The SCSI protocol driver currently calls this routine thrice
540 * in order to register separate callbacks; one for "normal" SCSI IO;
541 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
543 * Returns a positive integer valued "handle" in the
544 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
545 * Any non-positive return value (including zero!) should be considered
546 * an error by the caller.
549 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
556 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
557 * (slot/handle 0 is reserved!)
559 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
560 if (MptCallbacks[i] == NULL) {
561 MptCallbacks[i] = cbfunc;
562 MptDriverClass[i] = dclass;
563 MptEvHandlers[i] = NULL;
572 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
574 * mpt_deregister - Deregister a protocol drivers resources.
575 * @cb_idx: previously registered callback handle
577 * Each protocol-specific driver should call this routine when it's
578 * module is unloaded.
581 mpt_deregister(int cb_idx)
583 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
584 MptCallbacks[cb_idx] = NULL;
585 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
586 MptEvHandlers[cb_idx] = NULL;
592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
594 * mpt_event_register - Register protocol-specific event callback
596 * @cb_idx: previously registered (via mpt_register) callback handle
597 * @ev_cbfunc: callback function
599 * This routine can be called by one or more protocol-specific drivers
600 * if/when they choose to be notified of MPT events.
602 * Returns 0 for success.
605 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
607 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
610 MptEvHandlers[cb_idx] = ev_cbfunc;
614 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
616 * mpt_event_deregister - Deregister protocol-specific event callback
618 * @cb_idx: previously registered callback handle
620 * Each protocol-specific driver should call this routine
621 * when it does not (or can no longer) handle events,
622 * or when it's module is unloaded.
625 mpt_event_deregister(int cb_idx)
627 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
630 MptEvHandlers[cb_idx] = NULL;
633 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
635 * mpt_reset_register - Register protocol-specific IOC reset handler.
636 * @cb_idx: previously registered (via mpt_register) callback handle
637 * @reset_func: reset function
639 * This routine can be called by one or more protocol-specific drivers
640 * if/when they choose to be notified of IOC resets.
642 * Returns 0 for success.
645 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
647 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
650 MptResetHandlers[cb_idx] = reset_func;
654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
656 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
657 * @cb_idx: previously registered callback handle
659 * Each protocol-specific driver should call this routine
660 * when it does not (or can no longer) handle IOC reset handling,
661 * or when it's module is unloaded.
664 mpt_reset_deregister(int cb_idx)
666 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
669 MptResetHandlers[cb_idx] = NULL;
672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
674 * mpt_device_driver_register - Register device driver hooks
677 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
681 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
685 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
687 /* call per pci device probe entry point */
688 list_for_each_entry(ioc, &ioc_list, list) {
689 if(dd_cbfunc->probe) {
690 dd_cbfunc->probe(ioc->pcidev,
691 ioc->pcidev->driver->id_table);
698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
700 * mpt_device_driver_deregister - DeRegister device driver hooks
703 mpt_device_driver_deregister(int cb_idx)
705 struct mpt_pci_driver *dd_cbfunc;
708 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
711 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
713 list_for_each_entry(ioc, &ioc_list, list) {
714 if (dd_cbfunc->remove)
715 dd_cbfunc->remove(ioc->pcidev);
718 MptDeviceDriverHandlers[cb_idx] = NULL;
722 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
724 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
725 * allocated per MPT adapter.
726 * @handle: Handle of registered MPT protocol driver
727 * @ioc: Pointer to MPT adapter structure
729 * Returns pointer to a MPT request frame or %NULL if none are available
730 * or IOC is not active.
733 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
737 u16 req_idx; /* Request index */
739 /* validate handle and ioc identifier */
743 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
746 /* If interrupts are not attached, do not return a request frame */
750 spin_lock_irqsave(&ioc->FreeQlock, flags);
751 if (!list_empty(&ioc->FreeQ)) {
754 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
755 u.frame.linkage.list);
756 list_del(&mf->u.frame.linkage.list);
757 mf->u.frame.linkage.arg1 = 0;
758 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
759 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
761 req_idx = req_offset / ioc->req_sz;
762 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
763 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
764 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
771 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
775 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
777 if (mfcounter == PRINT_MF_COUNT)
778 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
781 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
782 ioc->name, handle, ioc->id, mf));
786 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
788 * mpt_put_msg_frame - Send a protocol specific MPT request frame
790 * @handle: Handle of registered MPT protocol driver
791 * @ioc: Pointer to MPT adapter structure
792 * @mf: Pointer to MPT request frame
794 * This routine posts a MPT request frame to the request post FIFO of a
795 * specific MPT adapter.
798 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
802 u16 req_idx; /* Request index */
804 /* ensure values are reset properly! */
805 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
806 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
808 req_idx = req_offset / ioc->req_sz;
809 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
810 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
812 #ifdef MPT_DEBUG_MSG_FRAME
814 u32 *m = mf->u.frame.hwhdr.__hdr;
817 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
819 n = ioc->req_sz/4 - 1;
822 for (ii=0; ii<=n; ii++) {
823 if (ii && ((ii%8)==0))
824 printk("\n" KERN_INFO " ");
825 printk(" %08x", le32_to_cpu(m[ii]));
831 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
832 dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
833 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
838 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
839 * @handle: Handle of registered MPT protocol driver
840 * @ioc: Pointer to MPT adapter structure
841 * @mf: Pointer to MPT request frame
843 * This routine places a MPT request frame back on the MPT adapter's
847 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
851 /* Put Request back on FreeQ! */
852 spin_lock_irqsave(&ioc->FreeQlock, flags);
853 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
854 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
858 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
861 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
863 * mpt_add_sge - Place a simple SGE at address pAddr.
864 * @pAddr: virtual address for SGE
865 * @flagslength: SGE flags and data transfer length
866 * @dma_addr: Physical address
868 * This routine places a MPT request frame back on the MPT adapter's
872 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
874 if (sizeof(dma_addr_t) == sizeof(u64)) {
875 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
876 u32 tmp = dma_addr & 0xFFFFFFFF;
878 pSge->FlagsLength = cpu_to_le32(flagslength);
879 pSge->Address.Low = cpu_to_le32(tmp);
880 tmp = (u32) ((u64)dma_addr >> 32);
881 pSge->Address.High = cpu_to_le32(tmp);
884 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
885 pSge->FlagsLength = cpu_to_le32(flagslength);
886 pSge->Address = cpu_to_le32(dma_addr);
890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
892 * mpt_send_handshake_request - Send MPT request via doorbell
894 * @handle: Handle of registered MPT protocol driver
895 * @ioc: Pointer to MPT adapter structure
896 * @reqBytes: Size of the request in bytes
897 * @req: Pointer to MPT request frame
898 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
900 * This routine is used exclusively to send MptScsiTaskMgmt
901 * requests since they are required to be sent via doorbell handshake.
903 * NOTE: It is the callers responsibility to byte-swap fields in the
904 * request which are greater than 1 byte in size.
906 * Returns 0 for success, non-zero for failure.
909 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
915 /* State is known to be good upon entering
916 * this function so issue the bus reset
921 * Emulate what mpt_put_msg_frame() does /wrt to sanity
922 * setting cb_idx/req_idx. But ONLY if this request
923 * is in proper (pre-alloc'd) request buffer range...
925 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
926 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
927 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
928 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
929 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
932 /* Make sure there are no doorbells */
933 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
935 CHIPREG_WRITE32(&ioc->chip->Doorbell,
936 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
937 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
939 /* Wait for IOC doorbell int */
940 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
944 /* Read doorbell and check for active bit */
945 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
948 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
951 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
953 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
957 /* Send request via doorbell handshake */
958 req_as_bytes = (u8 *) req;
959 for (ii = 0; ii < reqBytes/4; ii++) {
962 word = ((req_as_bytes[(ii*4) + 0] << 0) |
963 (req_as_bytes[(ii*4) + 1] << 8) |
964 (req_as_bytes[(ii*4) + 2] << 16) |
965 (req_as_bytes[(ii*4) + 3] << 24));
966 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
967 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
973 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
978 /* Make sure there are no doorbells */
979 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
986 * mpt_host_page_access_control - provides mechanism for the host
987 * driver to control the IOC's Host Page Buffer access.
988 * @ioc: Pointer to MPT adapter structure
989 * @access_control_value: define bits below
991 * Access Control Value - bits[15:12]
993 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
994 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
995 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
997 * Returns 0 for success, non-zero for failure.
1001 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1005 /* return if in use */
1006 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1007 & MPI_DOORBELL_ACTIVE)
1010 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1012 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1013 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1014 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1015 (access_control_value<<12)));
1017 /* Wait for IOC to clear Doorbell Status bit */
1018 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1024 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1026 * mpt_host_page_alloc - allocate system memory for the fw
1027 * If we already allocated memory in past, then resend the same pointer.
1028 * ioc@: Pointer to pointer to IOC adapter
1029 * ioc_init@: Pointer to ioc init config page
1031 * Returns 0 for success, non-zero for failure.
1034 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1038 u32 host_page_buffer_sz=0;
1040 if(!ioc->HostPageBuffer) {
1042 host_page_buffer_sz =
1043 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1045 if(!host_page_buffer_sz)
1046 return 0; /* fw doesn't need any host buffers */
1048 /* spin till we get enough memory */
1049 while(host_page_buffer_sz > 0) {
1051 if((ioc->HostPageBuffer = pci_alloc_consistent(
1053 host_page_buffer_sz,
1054 &ioc->HostPageBuffer_dma)) != NULL) {
1056 dinitprintk((MYIOC_s_INFO_FMT
1057 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1059 ioc->HostPageBuffer,
1060 ioc->HostPageBuffer_dma,
1061 host_page_buffer_sz));
1062 ioc->alloc_total += host_page_buffer_sz;
1063 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1067 host_page_buffer_sz -= (4*1024);
1071 if(!ioc->HostPageBuffer) {
1072 printk(MYIOC_s_ERR_FMT
1073 "Failed to alloc memory for host_page_buffer!\n",
1078 psge = (char *)&ioc_init->HostPageBufferSGE;
1079 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1080 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1081 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1082 MPI_SGE_FLAGS_HOST_TO_IOC |
1083 MPI_SGE_FLAGS_END_OF_BUFFER;
1084 if (sizeof(dma_addr_t) == sizeof(u64)) {
1085 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1087 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1088 flags_length |= ioc->HostPageBuffer_sz;
1089 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1090 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1097 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1098 * the associated MPT adapter structure.
1099 * @iocid: IOC unique identifier (integer)
1100 * @iocpp: Pointer to pointer to IOC adapter
1102 * Returns iocid and sets iocpp.
1105 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1109 list_for_each_entry(ioc,&ioc_list,list) {
1110 if (ioc->id == iocid) {
1121 mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
1123 int loop_count = 30 * 4; /* Wait 30 seconds */
1124 int status = -1; /* -1 means failed to get board READY */
1127 spin_lock(&ioc->initializing_hba_lock);
1128 if (ioc->initializing_hba_lock_flag == 0) {
1129 ioc->initializing_hba_lock_flag=1;
1130 spin_unlock(&ioc->initializing_hba_lock);
1134 spin_unlock(&ioc->initializing_hba_lock);
1135 set_current_state(TASK_INTERRUPTIBLE);
1136 schedule_timeout(HZ/4);
1137 } while (--loop_count);
1142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1144 * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
1145 * @ioc: Pointer to MPT adapter structure
1146 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1148 * This routine performs all the steps necessary to bring the IOC
1149 * to a OPERATIONAL state.
1151 * Special Note: This function was added with spin lock's so as to allow
1152 * the dv(domain validation) work thread to succeed on the other channel
1153 * that maybe occuring at the same time when this function is called.
1154 * Without this lock, the dv would fail when message frames were
1155 * requested during hba bringup on the alternate ioc.
1158 mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
1163 if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
1167 r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1171 spin_lock(&ioc->alt_ioc->initializing_hba_lock);
1172 ioc->alt_ioc->initializing_hba_lock_flag=0;
1173 spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
1179 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1181 * mpt_attach - Install a PCI intelligent MPT adapter.
1182 * @pdev: Pointer to pci_dev structure
1184 * This routine performs all the steps necessary to bring the IOC of
1185 * a MPT adapter to a OPERATIONAL state. This includes registering
1186 * memory regions, registering the interrupt, and allocating request
1187 * and reply memory pools.
1189 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1192 * Returns 0 for success, non-zero for failure.
1194 * TODO: Add support for polled controllers
1197 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1201 unsigned long mem_phys;
1209 static int mpt_ids = 0;
1210 #ifdef CONFIG_PROC_FS
1211 struct proc_dir_entry *dent, *ent;
1214 if (pci_enable_device(pdev))
1217 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1219 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1220 dprintk((KERN_INFO MYNAM
1221 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1222 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1223 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1227 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1228 dprintk((KERN_INFO MYNAM
1229 ": Using 64 bit consistent mask\n"));
1231 dprintk((KERN_INFO MYNAM
1232 ": Not using 64 bit consistent mask\n"));
1234 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1236 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1239 ioc->alloc_total = sizeof(MPT_ADAPTER);
1240 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1241 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1244 ioc->diagPending = 0;
1245 spin_lock_init(&ioc->diagLock);
1246 spin_lock_init(&ioc->fc_rescan_work_lock);
1247 spin_lock_init(&ioc->fc_rport_lock);
1248 spin_lock_init(&ioc->initializing_hba_lock);
1250 /* Initialize the event logging.
1252 ioc->eventTypes = 0; /* None */
1253 ioc->eventContext = 0;
1254 ioc->eventLogSize = 0;
1261 ioc->cached_fw = NULL;
1263 /* Initilize SCSI Config Data structure
1265 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1267 /* Initialize the running configQ head.
1269 INIT_LIST_HEAD(&ioc->configQ);
1271 /* Initialize the fc rport list head.
1273 INIT_LIST_HEAD(&ioc->fc_rports);
1275 /* Find lookup slot. */
1276 INIT_LIST_HEAD(&ioc->list);
1277 ioc->id = mpt_ids++;
1279 mem_phys = msize = 0;
1281 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1282 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1283 /* Get I/O space! */
1284 port = pci_resource_start(pdev, ii);
1285 psize = pci_resource_len(pdev,ii);
1288 mem_phys = pci_resource_start(pdev, ii);
1289 msize = pci_resource_len(pdev,ii);
1293 ioc->mem_size = msize;
1295 if (ii == DEVICE_COUNT_RESOURCE) {
1296 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1301 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1302 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1305 /* Get logical ptr for PciMem0 space */
1306 /*mem = ioremap(mem_phys, msize);*/
1307 mem = ioremap(mem_phys, 0x100);
1309 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1314 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1316 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1317 &ioc->facts, &ioc->pfacts[0]));
1319 ioc->mem_phys = mem_phys;
1320 ioc->chip = (SYSIF_REGS __iomem *)mem;
1322 /* Save Port IO values in case we need to do downloadboot */
1324 u8 *pmem = (u8*)port;
1325 ioc->pio_mem_phys = port;
1326 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1329 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1330 ioc->prod_name = "LSIFC909";
1333 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1334 ioc->prod_name = "LSIFC929";
1337 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1338 ioc->prod_name = "LSIFC919";
1341 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1342 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1344 if (revision < XL_929) {
1345 ioc->prod_name = "LSIFC929X";
1346 /* 929X Chip Fix. Set Split transactions level
1347 * for PCIX. Set MOST bits to zero.
1349 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1351 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1353 ioc->prod_name = "LSIFC929XL";
1354 /* 929XL Chip Fix. Set MMRBC to 0x08.
1356 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1358 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1361 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1362 ioc->prod_name = "LSIFC919X";
1364 /* 919X Chip Fix. Set Split transactions level
1365 * for PCIX. Set MOST bits to zero.
1367 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1369 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1371 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1372 ioc->prod_name = "LSIFC939X";
1374 ioc->errata_flag_1064 = 1;
1376 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1377 ioc->prod_name = "LSIFC949X";
1379 ioc->errata_flag_1064 = 1;
1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1382 ioc->prod_name = "LSIFC949E";
1385 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1386 ioc->prod_name = "LSI53C1030";
1387 ioc->bus_type = SPI;
1388 /* 1030 Chip Fix. Disable Split transactions
1389 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1391 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1392 if (revision < C0_1030) {
1393 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1395 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1398 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1399 ioc->prod_name = "LSI53C1035";
1400 ioc->bus_type = SPI;
1402 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1403 ioc->prod_name = "LSISAS1064";
1404 ioc->bus_type = SAS;
1405 ioc->errata_flag_1064 = 1;
1407 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1408 ioc->prod_name = "LSISAS1066";
1409 ioc->bus_type = SAS;
1410 ioc->errata_flag_1064 = 1;
1412 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1413 ioc->prod_name = "LSISAS1068";
1414 ioc->bus_type = SAS;
1415 ioc->errata_flag_1064 = 1;
1417 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1418 ioc->prod_name = "LSISAS1064E";
1419 ioc->bus_type = SAS;
1421 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1422 ioc->prod_name = "LSISAS1066E";
1423 ioc->bus_type = SAS;
1425 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1426 ioc->prod_name = "LSISAS1068E";
1427 ioc->bus_type = SAS;
1430 if (ioc->errata_flag_1064)
1431 pci_disable_io_access(pdev);
1433 sprintf(ioc->name, "ioc%d", ioc->id);
1435 spin_lock_init(&ioc->FreeQlock);
1438 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1440 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1442 /* Set lookup ptr. */
1443 list_add_tail(&ioc->list, &ioc_list);
1447 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1451 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1452 ioc->name, pdev->irq);
1454 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1455 ioc->name, __irq_itoa(pdev->irq));
1457 list_del(&ioc->list);
1463 ioc->pci_irq = pdev->irq;
1465 pci_set_master(pdev); /* ?? */
1466 pci_set_drvdata(pdev, ioc);
1469 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1471 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1475 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1477 mpt_detect_bound_ports(ioc, pdev);
1479 if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
1480 printk(KERN_WARNING MYNAM
1481 ": WARNING - %s did not initialize properly! (%d)\n",
1484 list_del(&ioc->list);
1485 free_irq(ioc->pci_irq, ioc);
1488 pci_set_drvdata(pdev, NULL);
1492 /* call per device driver probe entry point */
1493 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1494 if(MptDeviceDriverHandlers[ii] &&
1495 MptDeviceDriverHandlers[ii]->probe) {
1496 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1500 #ifdef CONFIG_PROC_FS
1502 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1504 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1506 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1508 ent->read_proc = procmpt_iocinfo_read;
1511 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1513 ent->read_proc = procmpt_summary_read;
1522 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1524 * mpt_detach - Remove a PCI intelligent MPT adapter.
1525 * @pdev: Pointer to pci_dev structure
1530 mpt_detach(struct pci_dev *pdev)
1532 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1536 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1537 remove_proc_entry(pname, NULL);
1538 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1539 remove_proc_entry(pname, NULL);
1540 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1541 remove_proc_entry(pname, NULL);
1543 /* call per device driver remove entry point */
1544 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1545 if(MptDeviceDriverHandlers[ii] &&
1546 MptDeviceDriverHandlers[ii]->remove) {
1547 MptDeviceDriverHandlers[ii]->remove(pdev);
1551 /* Disable interrupts! */
1552 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1555 synchronize_irq(pdev->irq);
1557 /* Clear any lingering interrupt */
1558 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1560 CHIPREG_READ32(&ioc->chip->IntStatus);
1562 mpt_adapter_dispose(ioc);
1564 pci_set_drvdata(pdev, NULL);
1567 /**************************************************************************
1571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1573 * mpt_suspend - Fusion MPT base driver suspend routine.
1578 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1581 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1583 device_state=pci_choose_state(pdev, state);
1585 printk(MYIOC_s_INFO_FMT
1586 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1587 ioc->name, pdev, pci_name(pdev), device_state);
1589 pci_save_state(pdev);
1591 /* put ioc into READY_STATE */
1592 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1593 printk(MYIOC_s_ERR_FMT
1594 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1597 /* disable interrupts */
1598 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1601 /* Clear any lingering interrupt */
1602 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1604 pci_disable_device(pdev);
1605 pci_set_power_state(pdev, device_state);
1610 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1612 * mpt_resume - Fusion MPT base driver resume routine.
1617 mpt_resume(struct pci_dev *pdev)
1619 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1620 u32 device_state = pdev->current_state;
1624 printk(MYIOC_s_INFO_FMT
1625 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1626 ioc->name, pdev, pci_name(pdev), device_state);
1628 pci_set_power_state(pdev, 0);
1629 pci_restore_state(pdev);
1630 pci_enable_device(pdev);
1632 /* enable interrupts */
1633 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1636 /* F/W not running */
1637 if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1638 /* enable domain validation flags */
1639 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1640 ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1644 printk(MYIOC_s_INFO_FMT
1645 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1647 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1648 CHIPREG_READ32(&ioc->chip->Doorbell));
1650 /* bring ioc to operational state */
1651 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1652 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1653 printk(MYIOC_s_INFO_FMT
1654 "pci-resume: Cannot recover, error:[%x]\n",
1655 ioc->name, recovery_state);
1657 printk(MYIOC_s_INFO_FMT
1658 "pci-resume: success\n", ioc->name);
1665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1667 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1668 * @ioc: Pointer to MPT adapter structure
1669 * @reason: Event word / reason
1670 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1672 * This routine performs all the steps necessary to bring the IOC
1673 * to a OPERATIONAL state.
1675 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1680 * -1 if failed to get board READY
1681 * -2 if READY but IOCFacts Failed
1682 * -3 if READY but PrimeIOCFifos Failed
1683 * -4 if READY but IOCInit Failed
1686 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1688 int hard_reset_done = 0;
1689 int alt_ioc_ready = 0;
1695 int reset_alt_ioc_active = 0;
1697 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1698 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1700 /* Disable reply interrupts (also blocks FreeQ) */
1701 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1705 if (ioc->alt_ioc->active)
1706 reset_alt_ioc_active = 1;
1708 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1709 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1710 ioc->alt_ioc->active = 0;
1714 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1717 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1718 if (hard_reset_done == -4) {
1719 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1722 if (reset_alt_ioc_active && ioc->alt_ioc) {
1723 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1724 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1725 ioc->alt_ioc->name));
1726 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1727 ioc->alt_ioc->active = 1;
1731 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1737 /* hard_reset_done = 0 if a soft reset was performed
1738 * and 1 if a hard reset was performed.
1740 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1741 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1744 printk(KERN_WARNING MYNAM
1745 ": alt-%s: Not ready WARNING!\n",
1746 ioc->alt_ioc->name);
1749 for (ii=0; ii<5; ii++) {
1750 /* Get IOC facts! Allow 5 retries */
1751 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1757 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1759 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1760 MptDisplayIocCapabilities(ioc);
1763 if (alt_ioc_ready) {
1764 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1765 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1766 /* Retry - alt IOC was initialized once
1768 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1771 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1773 reset_alt_ioc_active = 0;
1774 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1775 MptDisplayIocCapabilities(ioc->alt_ioc);
1779 /* Prime reply & request queues!
1780 * (mucho alloc's) Must be done prior to
1781 * init as upper addresses are needed for init.
1782 * If fails, continue with alt-ioc processing
1784 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1787 /* May need to check/upload firmware & data here!
1788 * If fails, continue with alt-ioc processing
1790 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1793 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1794 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1795 ioc->alt_ioc->name, rc);
1797 reset_alt_ioc_active = 0;
1800 if (alt_ioc_ready) {
1801 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1803 reset_alt_ioc_active = 0;
1804 printk(KERN_WARNING MYNAM
1805 ": alt-%s: (%d) init failure WARNING!\n",
1806 ioc->alt_ioc->name, rc);
1810 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1811 if (ioc->upload_fw) {
1812 ddlprintk((MYIOC_s_INFO_FMT
1813 "firmware upload required!\n", ioc->name));
1815 /* Controller is not operational, cannot do upload
1818 rc = mpt_do_upload(ioc, sleepFlag);
1820 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1822 * Maintain only one pointer to FW memory
1823 * so there will not be two attempt to
1824 * downloadboot onboard dual function
1825 * chips (mpt_adapter_disable,
1828 ioc->cached_fw = NULL;
1829 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1830 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1833 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1841 /* Enable! (reply interrupt) */
1842 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1846 if (reset_alt_ioc_active && ioc->alt_ioc) {
1847 /* (re)Enable alt-IOC! (reply interrupt) */
1848 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1849 ioc->alt_ioc->name));
1850 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1851 ioc->alt_ioc->active = 1;
1854 /* Enable MPT base driver management of EventNotification
1855 * and EventAck handling.
1857 if ((ret == 0) && (!ioc->facts.EventState))
1858 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1860 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1861 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1863 /* Add additional "reason" check before call to GetLanConfigPages
1864 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1865 * recursive scenario; GetLanConfigPages times out, timer expired
1866 * routine calls HardResetHandler, which calls into here again,
1867 * and we try GetLanConfigPages again...
1869 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1870 if (ioc->bus_type == SAS) {
1872 /* clear persistency table */
1873 if(ioc->facts.IOCExceptions &
1874 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1875 ret = mptbase_sas_persist_operation(ioc,
1876 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1883 mpt_findImVolumes(ioc);
1885 } else if (ioc->bus_type == FC) {
1887 * Pre-fetch FC port WWN and stuff...
1888 * (FCPortPage0_t stuff)
1890 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1891 (void) mptbase_GetFcPortPage0(ioc, ii);
1894 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1895 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1897 * Pre-fetch the ports LAN MAC address!
1898 * (LANPage1_t stuff)
1900 (void) GetLanConfigPages(ioc);
1903 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1904 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1905 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1910 /* Get NVRAM and adapter maximums from SPP 0 and 2
1912 mpt_GetScsiPortSettings(ioc, 0);
1914 /* Get version and length of SDP 1
1916 mpt_readScsiDevicePageHeaders(ioc, 0);
1920 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1921 mpt_findImVolumes(ioc);
1923 /* Check, and possibly reset, the coalescing value
1925 mpt_read_ioc_pg_1(ioc);
1927 mpt_read_ioc_pg_4(ioc);
1930 GetIoUnitPage2(ioc);
1934 * Call each currently registered protocol IOC reset handler
1935 * with post-reset indication.
1936 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1937 * MptResetHandlers[] registered yet.
1939 if (hard_reset_done) {
1941 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1942 if ((ret == 0) && MptResetHandlers[ii]) {
1943 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1945 rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1949 if (alt_ioc_ready && MptResetHandlers[ii]) {
1950 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1951 ioc->name, ioc->alt_ioc->name, ii));
1952 rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1956 /* FIXME? Examine results here? */
1962 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1964 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1965 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1966 * 929X, 1030 or 1035.
1967 * @ioc: Pointer to MPT adapter structure
1968 * @pdev: Pointer to (struct pci_dev) structure
1970 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1971 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1974 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1976 struct pci_dev *peer=NULL;
1977 unsigned int slot = PCI_SLOT(pdev->devfn);
1978 unsigned int func = PCI_FUNC(pdev->devfn);
1979 MPT_ADAPTER *ioc_srch;
1981 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1982 " searching for devfn match on %x or %x\n",
1983 ioc->name, pci_name(pdev), pdev->bus->number,
1984 pdev->devfn, func-1, func+1));
1986 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1988 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1993 list_for_each_entry(ioc_srch, &ioc_list, list) {
1994 struct pci_dev *_pcidev = ioc_srch->pcidev;
1995 if (_pcidev == peer) {
1996 /* Paranoia checks */
1997 if (ioc->alt_ioc != NULL) {
1998 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1999 ioc->name, ioc->alt_ioc->name);
2001 } else if (ioc_srch->alt_ioc != NULL) {
2002 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
2003 ioc_srch->name, ioc_srch->alt_ioc->name);
2006 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
2007 ioc->name, ioc_srch->name));
2008 ioc_srch->alt_ioc = ioc;
2009 ioc->alt_ioc = ioc_srch;
2015 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2017 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2018 * @this: Pointer to MPT adapter structure
2021 mpt_adapter_disable(MPT_ADAPTER *ioc)
2026 if (ioc->cached_fw != NULL) {
2027 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
2028 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
2029 printk(KERN_WARNING MYNAM
2030 ": firmware downloadboot failure (%d)!\n", ret);
2034 /* Disable adapter interrupts! */
2035 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2037 /* Clear any lingering interrupt */
2038 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2040 if (ioc->alloc != NULL) {
2042 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2043 ioc->name, ioc->alloc, ioc->alloc_sz));
2044 pci_free_consistent(ioc->pcidev, sz,
2045 ioc->alloc, ioc->alloc_dma);
2046 ioc->reply_frames = NULL;
2047 ioc->req_frames = NULL;
2049 ioc->alloc_total -= sz;
2052 if (ioc->sense_buf_pool != NULL) {
2053 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2054 pci_free_consistent(ioc->pcidev, sz,
2055 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2056 ioc->sense_buf_pool = NULL;
2057 ioc->alloc_total -= sz;
2060 if (ioc->events != NULL){
2061 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2064 ioc->alloc_total -= sz;
2067 if (ioc->cached_fw != NULL) {
2068 sz = ioc->facts.FWImageSize;
2069 pci_free_consistent(ioc->pcidev, sz,
2070 ioc->cached_fw, ioc->cached_fw_dma);
2071 ioc->cached_fw = NULL;
2072 ioc->alloc_total -= sz;
2075 kfree(ioc->spi_data.nvram);
2076 kfree(ioc->raid_data.pIocPg3);
2077 ioc->spi_data.nvram = NULL;
2078 ioc->raid_data.pIocPg3 = NULL;
2080 if (ioc->spi_data.pIocPg4 != NULL) {
2081 sz = ioc->spi_data.IocPg4Sz;
2082 pci_free_consistent(ioc->pcidev, sz,
2083 ioc->spi_data.pIocPg4,
2084 ioc->spi_data.IocPg4_dma);
2085 ioc->spi_data.pIocPg4 = NULL;
2086 ioc->alloc_total -= sz;
2089 if (ioc->ReqToChain != NULL) {
2090 kfree(ioc->ReqToChain);
2091 kfree(ioc->RequestNB);
2092 ioc->ReqToChain = NULL;
2095 kfree(ioc->ChainToChain);
2096 ioc->ChainToChain = NULL;
2098 if (ioc->HostPageBuffer != NULL) {
2099 if((ret = mpt_host_page_access_control(ioc,
2100 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2101 printk(KERN_ERR MYNAM
2102 ": %s: host page buffers free failed (%d)!\n",
2105 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2106 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2107 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2108 ioc->HostPageBuffer,
2109 ioc->HostPageBuffer_dma);
2110 ioc->HostPageBuffer = NULL;
2111 ioc->HostPageBuffer_sz = 0;
2112 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2116 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2118 * mpt_adapter_dispose - Free all resources associated with a MPT
2120 * @ioc: Pointer to MPT adapter structure
2122 * This routine unregisters h/w resources and frees all alloc'd memory
2123 * associated with a MPT adapter structure.
2126 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2128 int sz_first, sz_last;
2133 sz_first = ioc->alloc_total;
2135 mpt_adapter_disable(ioc);
2137 if (ioc->pci_irq != -1) {
2138 free_irq(ioc->pci_irq, ioc);
2142 if (ioc->memmap != NULL) {
2143 iounmap(ioc->memmap);
2147 #if defined(CONFIG_MTRR) && 0
2148 if (ioc->mtrr_reg > 0) {
2149 mtrr_del(ioc->mtrr_reg, 0, 0);
2150 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2154 /* Zap the adapter lookup ptr! */
2155 list_del(&ioc->list);
2157 sz_last = ioc->alloc_total;
2158 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2159 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2163 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2165 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2166 * @ioc: Pointer to MPT adapter structure
2169 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2173 printk(KERN_INFO "%s: ", ioc->name);
2174 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2175 printk("%s: ", ioc->prod_name+3);
2176 printk("Capabilities={");
2178 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2179 printk("Initiator");
2183 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2184 printk("%sTarget", i ? "," : "");
2188 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2189 printk("%sLAN", i ? "," : "");
2195 * This would probably evoke more questions than it's worth
2197 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2198 printk("%sLogBusAddr", i ? "," : "");
2206 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2208 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2209 * @ioc: Pointer to MPT_ADAPTER structure
2210 * @force: Force hard KickStart of IOC
2211 * @sleepFlag: Specifies whether the process can sleep
2214 * 1 - DIAG reset and READY
2215 * 0 - READY initially OR soft reset and READY
2216 * -1 - Any failure on KickStart
2217 * -2 - Msg Unit Reset Failed
2218 * -3 - IO Unit Reset Failed
2219 * -4 - IOC owned by a PEER
2222 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2227 int hard_reset_done = 0;
2232 /* Get current [raw] IOC state */
2233 ioc_state = mpt_GetIocState(ioc, 0);
2234 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2237 * Check to see if IOC got left/stuck in doorbell handshake
2238 * grip of death. If so, hard reset the IOC.
2240 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2242 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2246 /* Is it already READY? */
2247 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2251 * Check to see if IOC is in FAULT state.
2253 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2255 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2257 printk(KERN_WARNING " FAULT code = %04xh\n",
2258 ioc_state & MPI_DOORBELL_DATA_MASK);
2262 * Hmmm... Did it get left operational?
2264 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2265 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2269 * If PCI Peer, exit.
2270 * Else, if no fault conditions are present, issue a MessageUnitReset
2271 * Else, fall through to KickStart case
2273 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2274 dinitprintk((KERN_INFO MYNAM
2275 ": whoinit 0x%x statefault %d force %d\n",
2276 whoinit, statefault, force));
2277 if (whoinit == MPI_WHOINIT_PCI_PEER)
2280 if ((statefault == 0 ) && (force == 0)) {
2281 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2288 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2289 if (hard_reset_done < 0)
2293 * Loop here waiting for IOC to come READY.
2296 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2298 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2299 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2301 * BIOS or previous driver load left IOC in OP state.
2302 * Reset messaging FIFOs.
2304 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2305 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2308 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2310 * Something is wrong. Try to get IOC back
2313 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2314 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2321 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2322 ioc->name, (int)((ii+5)/HZ));
2326 if (sleepFlag == CAN_SLEEP) {
2327 msleep_interruptible(1);
2329 mdelay (1); /* 1 msec delay */
2334 if (statefault < 3) {
2335 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2337 statefault==1 ? "stuck handshake" : "IOC FAULT");
2340 return hard_reset_done;
2343 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2345 * mpt_GetIocState - Get the current state of a MPT adapter.
2346 * @ioc: Pointer to MPT_ADAPTER structure
2347 * @cooked: Request raw or cooked IOC state
2349 * Returns all IOC Doorbell register bits if cooked==0, else just the
2350 * Doorbell bits in MPI_IOC_STATE_MASK.
2353 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2358 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2359 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2360 sc = s & MPI_IOC_STATE_MASK;
2363 ioc->last_state = sc;
2365 return cooked ? sc : s;
2368 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2370 * GetIocFacts - Send IOCFacts request to MPT adapter.
2371 * @ioc: Pointer to MPT_ADAPTER structure
2372 * @sleepFlag: Specifies whether the process can sleep
2373 * @reason: If recovery, only update facts.
2375 * Returns 0 for success, non-zero for failure.
2378 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2380 IOCFacts_t get_facts;
2381 IOCFactsReply_t *facts;
2389 /* IOC *must* NOT be in RESET state! */
2390 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2391 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2397 facts = &ioc->facts;
2399 /* Destination (reply area)... */
2400 reply_sz = sizeof(*facts);
2401 memset(facts, 0, reply_sz);
2403 /* Request area (get_facts on the stack right now!) */
2404 req_sz = sizeof(get_facts);
2405 memset(&get_facts, 0, req_sz);
2407 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2408 /* Assert: All other get_facts fields are zero! */
2410 dinitprintk((MYIOC_s_INFO_FMT
2411 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2412 ioc->name, req_sz, reply_sz));
2414 /* No non-zero fields in the get_facts request are greater than
2415 * 1 byte in size, so we can just fire it off as is.
2417 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2418 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2423 * Now byte swap (GRRR) the necessary fields before any further
2424 * inspection of reply contents.
2426 * But need to do some sanity checks on MsgLength (byte) field
2427 * to make sure we don't zero IOC's req_sz!
2429 /* Did we get a valid reply? */
2430 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2431 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2433 * If not been here, done that, save off first WhoInit value
2435 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2436 ioc->FirstWhoInit = facts->WhoInit;
2439 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2440 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2441 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2442 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2443 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2444 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2445 /* CHECKME! IOCStatus, IOCLogInfo */
2447 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2448 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2451 * FC f/w version changed between 1.1 and 1.2
2452 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2453 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2455 if (facts->MsgVersion < 0x0102) {
2457 * Handle old FC f/w style, convert to new...
2459 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2460 facts->FWVersion.Word =
2461 ((oldv<<12) & 0xFF000000) |
2462 ((oldv<<8) & 0x000FFF00);
2464 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2466 facts->ProductID = le16_to_cpu(facts->ProductID);
2467 facts->CurrentHostMfaHighAddr =
2468 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2469 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2470 facts->CurrentSenseBufferHighAddr =
2471 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2472 facts->CurReplyFrameSize =
2473 le16_to_cpu(facts->CurReplyFrameSize);
2474 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2477 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2478 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2479 * to 14 in MPI-1.01.0x.
2481 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2482 facts->MsgVersion > 0x0100) {
2483 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2486 sz = facts->FWImageSize;
2491 facts->FWImageSize = sz;
2493 if (!facts->RequestFrameSize) {
2494 /* Something is wrong! */
2495 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2500 r = sz = facts->BlockSize;
2501 vv = ((63 / (sz * 4)) + 1) & 0x03;
2502 ioc->NB_for_64_byte_frame = vv;
2508 ioc->NBShiftFactor = shiftFactor;
2509 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2510 ioc->name, vv, shiftFactor, r));
2512 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2514 * Set values for this IOC's request & reply frame sizes,
2515 * and request & reply queue depths...
2517 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2518 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2519 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2520 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2522 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2523 ioc->name, ioc->reply_sz, ioc->reply_depth));
2524 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2525 ioc->name, ioc->req_sz, ioc->req_depth));
2527 /* Get port facts! */
2528 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2532 printk(MYIOC_s_ERR_FMT
2533 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2534 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2535 RequestFrameSize)/sizeof(u32)));
2542 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2544 * GetPortFacts - Send PortFacts request to MPT adapter.
2545 * @ioc: Pointer to MPT_ADAPTER structure
2546 * @portnum: Port number
2547 * @sleepFlag: Specifies whether the process can sleep
2549 * Returns 0 for success, non-zero for failure.
2552 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2554 PortFacts_t get_pfacts;
2555 PortFactsReply_t *pfacts;
2560 /* IOC *must* NOT be in RESET state! */
2561 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2562 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2568 pfacts = &ioc->pfacts[portnum];
2570 /* Destination (reply area)... */
2571 reply_sz = sizeof(*pfacts);
2572 memset(pfacts, 0, reply_sz);
2574 /* Request area (get_pfacts on the stack right now!) */
2575 req_sz = sizeof(get_pfacts);
2576 memset(&get_pfacts, 0, req_sz);
2578 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2579 get_pfacts.PortNumber = portnum;
2580 /* Assert: All other get_pfacts fields are zero! */
2582 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2583 ioc->name, portnum));
2585 /* No non-zero fields in the get_pfacts request are greater than
2586 * 1 byte in size, so we can just fire it off as is.
2588 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2589 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2593 /* Did we get a valid reply? */
2595 /* Now byte swap the necessary fields in the response. */
2596 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2597 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2598 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2599 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2600 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2601 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2602 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2603 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2604 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2611 * SendIocInit - Send IOCInit request to MPT adapter.
2612 * @ioc: Pointer to MPT_ADAPTER structure
2613 * @sleepFlag: Specifies whether the process can sleep
2615 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2617 * Returns 0 for success, non-zero for failure.
2620 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2623 MPIDefaultReply_t init_reply;
2629 memset(&ioc_init, 0, sizeof(ioc_init));
2630 memset(&init_reply, 0, sizeof(init_reply));
2632 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2633 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2635 /* If we are in a recovery mode and we uploaded the FW image,
2636 * then this pointer is not NULL. Skip the upload a second time.
2637 * Set this flag if cached_fw set for either IOC.
2639 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2643 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2644 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2646 if(ioc->bus_type == SAS)
2647 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2648 else if(ioc->bus_type == FC)
2649 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2651 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2652 ioc_init.MaxBuses = MPT_MAX_BUS;
2653 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2654 ioc->name, ioc->facts.MsgVersion));
2655 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2656 // set MsgVersion and HeaderVersion host driver was built with
2657 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2658 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2660 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2661 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2662 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2665 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2667 if (sizeof(dma_addr_t) == sizeof(u64)) {
2668 /* Save the upper 32-bits of the request
2669 * (reply) and sense buffers.
2671 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2672 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2674 /* Force 32-bit addressing */
2675 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2676 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2679 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2680 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2681 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2682 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2684 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2685 ioc->name, &ioc_init));
2687 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2688 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2690 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2694 /* No need to byte swap the multibyte fields in the reply
2695 * since we don't even look at it's contents.
2698 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2699 ioc->name, &ioc_init));
2701 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2702 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2706 /* YIKES! SUPER IMPORTANT!!!
2707 * Poll IocState until _OPERATIONAL while IOC is doing
2708 * LoopInit and TargetDiscovery!
2711 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2712 state = mpt_GetIocState(ioc, 1);
2713 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2714 if (sleepFlag == CAN_SLEEP) {
2715 msleep_interruptible(1);
2721 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2722 ioc->name, (int)((count+5)/HZ));
2726 state = mpt_GetIocState(ioc, 1);
2729 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2735 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2737 * SendPortEnable - Send PortEnable request to MPT adapter port.
2738 * @ioc: Pointer to MPT_ADAPTER structure
2739 * @portnum: Port number to enable
2740 * @sleepFlag: Specifies whether the process can sleep
2742 * Send PortEnable to bring IOC to OPERATIONAL state.
2744 * Returns 0 for success, non-zero for failure.
2747 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2749 PortEnable_t port_enable;
2750 MPIDefaultReply_t reply_buf;
2755 /* Destination... */
2756 reply_sz = sizeof(MPIDefaultReply_t);
2757 memset(&reply_buf, 0, reply_sz);
2759 req_sz = sizeof(PortEnable_t);
2760 memset(&port_enable, 0, req_sz);
2762 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2763 port_enable.PortNumber = portnum;
2764 /* port_enable.ChainOffset = 0; */
2765 /* port_enable.MsgFlags = 0; */
2766 /* port_enable.MsgContext = 0; */
2768 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2769 ioc->name, portnum, &port_enable));
2771 /* RAID FW may take a long time to enable
2773 if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2774 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
2775 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2776 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
2778 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2779 reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
2785 * ioc: Pointer to MPT_ADAPTER structure
2786 * size - total FW bytes
2789 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2792 return; /* use already allocated memory */
2793 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2794 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2795 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2797 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2798 ioc->alloc_total += size;
2802 * If alt_img is NULL, delete from ioc structure.
2803 * Else, delete a secondary image in same format.
2806 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2810 sz = ioc->facts.FWImageSize;
2811 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2812 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2813 pci_free_consistent(ioc->pcidev, sz,
2814 ioc->cached_fw, ioc->cached_fw_dma);
2815 ioc->cached_fw = NULL;
2821 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2823 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2824 * @ioc: Pointer to MPT_ADAPTER structure
2825 * @sleepFlag: Specifies whether the process can sleep
2827 * Returns 0 for success, >0 for handshake failure
2828 * <0 for fw upload failure.
2830 * Remark: If bound IOC and a successful FWUpload was performed
2831 * on the bound IOC, the second image is discarded
2832 * and memory is free'd. Both channels must upload to prevent
2833 * IOC from running in degraded mode.
2836 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2838 u8 request[ioc->req_sz];
2839 u8 reply[sizeof(FWUploadReply_t)];
2840 FWUpload_t *prequest;
2841 FWUploadReply_t *preply;
2842 FWUploadTCSGE_t *ptcsge;
2845 int ii, sz, reply_sz;
2848 /* If the image size is 0, we are done.
2850 if ((sz = ioc->facts.FWImageSize) == 0)
2853 mpt_alloc_fw_memory(ioc, sz);
2855 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2856 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2858 if (ioc->cached_fw == NULL) {
2864 prequest = (FWUpload_t *)&request;
2865 preply = (FWUploadReply_t *)&reply;
2867 /* Destination... */
2868 memset(prequest, 0, ioc->req_sz);
2870 reply_sz = sizeof(reply);
2871 memset(preply, 0, reply_sz);
2873 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2874 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2876 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2877 ptcsge->DetailsLength = 12;
2878 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2879 ptcsge->ImageSize = cpu_to_le32(sz);
2881 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2883 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2884 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2886 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2887 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2888 prequest, sgeoffset));
2889 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2891 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2892 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2894 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2896 cmdStatus = -EFAULT;
2898 /* Handshake transfer was complete and successful.
2899 * Check the Reply Frame.
2901 int status, transfer_sz;
2902 status = le16_to_cpu(preply->IOCStatus);
2903 if (status == MPI_IOCSTATUS_SUCCESS) {
2904 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2905 if (transfer_sz == sz)
2909 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2910 ioc->name, cmdStatus));
2915 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2917 mpt_free_fw_memory(ioc);
2923 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2925 * mpt_downloadboot - DownloadBoot code
2926 * @ioc: Pointer to MPT_ADAPTER structure
2927 * @flag: Specify which part of IOC memory is to be uploaded.
2928 * @sleepFlag: Specifies whether the process can sleep
2930 * FwDownloadBoot requires Programmed IO access.
2932 * Returns 0 for success
2933 * -1 FW Image size is 0
2934 * -2 No valid cached_fw Pointer
2935 * <0 for fw upload failure.
2938 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2940 MpiExtImageHeader_t *pExtImage;
2950 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2951 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2953 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2954 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2955 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2956 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2957 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2958 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2960 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2963 if (sleepFlag == CAN_SLEEP) {
2964 msleep_interruptible(1);
2969 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2970 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2972 for (count = 0; count < 30; count ++) {
2973 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2974 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2975 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2980 if (sleepFlag == CAN_SLEEP) {
2981 msleep_interruptible (100);
2987 if ( count == 30 ) {
2988 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2989 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2990 ioc->name, diag0val));
2994 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2995 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2996 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2997 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2998 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2999 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3001 /* Set the DiagRwEn and Disable ARM bits */
3002 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3004 fwSize = (pFwHeader->ImageSize + 3)/4;
3005 ptrFw = (u32 *) pFwHeader;
3007 /* Write the LoadStartAddress to the DiagRw Address Register
3008 * using Programmed IO
3010 if (ioc->errata_flag_1064)
3011 pci_enable_io_access(ioc->pcidev);
3013 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3014 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
3015 ioc->name, pFwHeader->LoadStartAddress));
3017 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
3018 ioc->name, fwSize*4, ptrFw));
3020 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3023 nextImage = pFwHeader->NextImageHeaderOffset;
3025 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3027 load_addr = pExtImage->LoadStartAddress;
3029 fwSize = (pExtImage->ImageSize + 3) >> 2;
3030 ptrFw = (u32 *)pExtImage;
3032 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3033 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3034 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3037 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3039 nextImage = pExtImage->NextImageHeaderOffset;
3042 /* Write the IopResetVectorRegAddr */
3043 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3044 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3046 /* Write the IopResetVectorValue */
3047 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3048 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3050 /* Clear the internal flash bad bit - autoincrementing register,
3051 * so must do two writes.
3053 if (ioc->bus_type == SPI) {
3055 * 1030 and 1035 H/W errata, workaround to access
3056 * the ClearFlashBadSignatureBit
3058 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3059 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3060 diagRwData |= 0x40000000;
3061 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3062 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3064 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3065 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3066 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3067 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3070 if (sleepFlag == CAN_SLEEP) {
3071 msleep_interruptible (1);
3077 if (ioc->errata_flag_1064)
3078 pci_disable_io_access(ioc->pcidev);
3080 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3081 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3082 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3083 ioc->name, diag0val));
3084 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3085 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3086 ioc->name, diag0val));
3087 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3089 /* Write 0xFF to reset the sequencer */
3090 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3092 if (ioc->bus_type == SAS) {
3093 ioc_state = mpt_GetIocState(ioc, 0);
3094 if ( (GetIocFacts(ioc, sleepFlag,
3095 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3096 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3097 ioc->name, ioc_state));
3102 for (count=0; count<HZ*20; count++) {
3103 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3104 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3105 ioc->name, count, ioc_state));
3106 if (ioc->bus_type == SAS) {
3109 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3110 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3114 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3118 if (sleepFlag == CAN_SLEEP) {
3119 msleep_interruptible (10);
3124 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3125 ioc->name, ioc_state));
3129 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3131 * KickStart - Perform hard reset of MPT adapter.
3132 * @ioc: Pointer to MPT_ADAPTER structure
3133 * @force: Force hard reset
3134 * @sleepFlag: Specifies whether the process can sleep
3136 * This routine places MPT adapter in diagnostic mode via the
3137 * WriteSequence register, and then performs a hard reset of adapter
3138 * via the Diagnostic register.
3140 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3141 * or NO_SLEEP (interrupt thread, use mdelay)
3142 * force - 1 if doorbell active, board fault state
3143 * board operational, IOC_RECOVERY or
3144 * IOC_BRINGUP and there is an alt_ioc.
3148 * 1 - hard reset, READY
3149 * 0 - no reset due to History bit, READY
3150 * -1 - no reset due to History bit but not READY
3151 * OR reset but failed to come READY
3152 * -2 - no reset, could not enter DIAG mode
3153 * -3 - reset but bad FW bit
3156 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3158 int hard_reset_done = 0;
3162 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3163 if (ioc->bus_type == SPI) {
3164 /* Always issue a Msg Unit Reset first. This will clear some
3165 * SCSI bus hang conditions.
3167 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3169 if (sleepFlag == CAN_SLEEP) {
3170 msleep_interruptible (1000);
3176 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3177 if (hard_reset_done < 0)
3178 return hard_reset_done;
3180 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3183 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3184 for (cnt=0; cnt<cntdn; cnt++) {
3185 ioc_state = mpt_GetIocState(ioc, 1);
3186 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3187 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3189 return hard_reset_done;
3191 if (sleepFlag == CAN_SLEEP) {
3192 msleep_interruptible (10);
3198 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3199 ioc->name, ioc_state);
3203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3205 * mpt_diag_reset - Perform hard reset of the adapter.
3206 * @ioc: Pointer to MPT_ADAPTER structure
3207 * @ignore: Set if to honor and clear to ignore
3208 * the reset history bit
3209 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3210 * else set to NO_SLEEP (use mdelay instead)
3212 * This routine places the adapter in diagnostic mode via the
3213 * WriteSequence register and then performs a hard reset of adapter
3214 * via the Diagnostic register. Adapter should be in ready state
3215 * upon successful completion.
3217 * Returns: 1 hard reset successful
3218 * 0 no reset performed because reset history bit set
3219 * -2 enabling diagnostic mode failed
3220 * -3 diagnostic reset failed
3223 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3227 int hard_reset_done = 0;
3233 /* Clear any existing interrupts */
3234 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3236 /* Use "Diagnostic reset" method! (only thing available!) */
3237 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3241 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3242 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3243 ioc->name, diag0val, diag1val));
3246 /* Do the reset if we are told to ignore the reset history
3247 * or if the reset history is 0
3249 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3250 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3251 /* Write magic sequence to WriteSequence register
3252 * Loop until in diagnostic mode
3254 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3255 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3256 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3257 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3258 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3259 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3262 if (sleepFlag == CAN_SLEEP) {
3263 msleep_interruptible (100);
3270 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3271 ioc->name, diag0val);
3276 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3278 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3279 ioc->name, diag0val));
3284 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3285 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3286 ioc->name, diag0val, diag1val));
3289 * Disable the ARM (Bug fix)
3292 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3296 * Now hit the reset bit in the Diagnostic register
3297 * (THE BIG HAMMER!) (Clears DRWE bit).
3299 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3300 hard_reset_done = 1;
3301 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3305 * Call each currently registered protocol IOC reset handler
3306 * with pre-reset indication.
3307 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3308 * MptResetHandlers[] registered yet.
3314 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3315 if (MptResetHandlers[ii]) {
3316 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3318 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3320 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3321 ioc->name, ioc->alt_ioc->name, ii));
3322 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3326 /* FIXME? Examine results here? */
3329 if (ioc->cached_fw) {
3330 /* If the DownloadBoot operation fails, the
3331 * IOC will be left unusable. This is a fatal error
3332 * case. _diag_reset will return < 0
3334 for (count = 0; count < 30; count ++) {
3335 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3336 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3341 if (sleepFlag == CAN_SLEEP) {
3342 msleep_interruptible (1000);
3347 if ((count = mpt_downloadboot(ioc,
3348 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3349 printk(KERN_WARNING MYNAM
3350 ": firmware downloadboot failure (%d)!\n", count);
3354 /* Wait for FW to reload and for board
3355 * to go to the READY state.
3356 * Maximum wait is 60 seconds.
3357 * If fail, no error will check again
3358 * with calling program.
3360 for (count = 0; count < 60; count ++) {
3361 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3362 doorbell &= MPI_IOC_STATE_MASK;
3364 if (doorbell == MPI_IOC_STATE_READY) {
3369 if (sleepFlag == CAN_SLEEP) {
3370 msleep_interruptible (1000);
3378 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3381 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3382 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3383 ioc->name, diag0val, diag1val));
3386 /* Clear RESET_HISTORY bit! Place board in the
3387 * diagnostic mode to update the diag register.
3389 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3391 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3392 /* Write magic sequence to WriteSequence register
3393 * Loop until in diagnostic mode
3395 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3396 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3397 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3398 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3399 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3400 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3403 if (sleepFlag == CAN_SLEEP) {
3404 msleep_interruptible (100);
3411 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3412 ioc->name, diag0val);
3415 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3417 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3418 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3419 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3420 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3421 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3425 /* Disable Diagnostic Mode
3427 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3429 /* Check FW reload status flags.
3431 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3432 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3433 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3434 ioc->name, diag0val);
3440 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3441 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3442 ioc->name, diag0val, diag1val));
3446 * Reset flag that says we've enabled event notification
3448 ioc->facts.EventState = 0;
3451 ioc->alt_ioc->facts.EventState = 0;
3453 return hard_reset_done;
3456 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3458 * SendIocReset - Send IOCReset request to MPT adapter.
3459 * @ioc: Pointer to MPT_ADAPTER structure
3460 * @reset_type: reset type, expected values are
3461 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3463 * Send IOCReset request to the MPT adapter.
3465 * Returns 0 for success, non-zero for failure.
3468 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3474 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3475 ioc->name, reset_type));
3476 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3477 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3480 /* FW ACK'd request, wait for READY state
3483 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3485 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3489 if (sleepFlag != CAN_SLEEP)
3492 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3493 ioc->name, (int)((count+5)/HZ));
3497 if (sleepFlag == CAN_SLEEP) {
3498 msleep_interruptible(1);
3500 mdelay (1); /* 1 msec delay */
3505 * Cleanup all event stuff for this IOC; re-issue EventNotification
3506 * request if needed.
3508 if (ioc->facts.Function)
3509 ioc->facts.EventState = 0;
3514 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3516 * initChainBuffers - Allocate memory for and initialize
3517 * chain buffers, chain buffer control arrays and spinlock.
3518 * @hd: Pointer to MPT_SCSI_HOST structure
3519 * @init: If set, initialize the spin lock.
3522 initChainBuffers(MPT_ADAPTER *ioc)
3525 int sz, ii, num_chain;
3526 int scale, num_sge, numSGE;
3528 /* ReqToChain size must equal the req_depth
3531 if (ioc->ReqToChain == NULL) {
3532 sz = ioc->req_depth * sizeof(int);
3533 mem = kmalloc(sz, GFP_ATOMIC);
3537 ioc->ReqToChain = (int *) mem;
3538 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3539 ioc->name, mem, sz));
3540 mem = kmalloc(sz, GFP_ATOMIC);
3544 ioc->RequestNB = (int *) mem;
3545 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3546 ioc->name, mem, sz));
3548 for (ii = 0; ii < ioc->req_depth; ii++) {
3549 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3552 /* ChainToChain size must equal the total number
3553 * of chain buffers to be allocated.
3556 * Calculate the number of chain buffers needed(plus 1) per I/O
3557 * then multiply the the maximum number of simultaneous cmds
3559 * num_sge = num sge in request frame + last chain buffer
3560 * scale = num sge per chain buffer if no chain element
3562 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3563 if (sizeof(dma_addr_t) == sizeof(u64))
3564 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3566 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3568 if (sizeof(dma_addr_t) == sizeof(u64)) {
3569 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3570 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3572 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3573 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3575 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3576 ioc->name, num_sge, numSGE));
3578 if ( numSGE > MPT_SCSI_SG_DEPTH )
3579 numSGE = MPT_SCSI_SG_DEPTH;
3582 while (numSGE - num_sge > 0) {
3584 num_sge += (scale - 1);
3588 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3589 ioc->name, numSGE, num_sge, num_chain));
3591 if (ioc->bus_type == SPI)
3592 num_chain *= MPT_SCSI_CAN_QUEUE;
3594 num_chain *= MPT_FC_CAN_QUEUE;
3596 ioc->num_chain = num_chain;
3598 sz = num_chain * sizeof(int);
3599 if (ioc->ChainToChain == NULL) {
3600 mem = kmalloc(sz, GFP_ATOMIC);
3604 ioc->ChainToChain = (int *) mem;
3605 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3606 ioc->name, mem, sz));
3608 mem = (u8 *) ioc->ChainToChain;
3610 memset(mem, 0xFF, sz);
3614 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3616 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3617 * @ioc: Pointer to MPT_ADAPTER structure
3619 * This routine allocates memory for the MPT reply and request frame
3620 * pools (if necessary), and primes the IOC reply FIFO with
3623 * Returns 0 for success, non-zero for failure.
3626 PrimeIocFifos(MPT_ADAPTER *ioc)
3629 unsigned long flags;
3630 dma_addr_t alloc_dma;
3632 int i, reply_sz, sz, total_size, num_chain;
3634 /* Prime reply FIFO... */
3636 if (ioc->reply_frames == NULL) {
3637 if ( (num_chain = initChainBuffers(ioc)) < 0)
3640 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3641 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3642 ioc->name, ioc->reply_sz, ioc->reply_depth));
3643 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3644 ioc->name, reply_sz, reply_sz));
3646 sz = (ioc->req_sz * ioc->req_depth);
3647 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3648 ioc->name, ioc->req_sz, ioc->req_depth));
3649 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3650 ioc->name, sz, sz));
3653 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3654 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3655 ioc->name, ioc->req_sz, num_chain));
3656 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3657 ioc->name, sz, sz, num_chain));
3660 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3662 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3667 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3668 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3670 memset(mem, 0, total_size);
3671 ioc->alloc_total += total_size;
3673 ioc->alloc_dma = alloc_dma;
3674 ioc->alloc_sz = total_size;
3675 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3676 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3678 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3679 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3681 alloc_dma += reply_sz;
3684 /* Request FIFO - WE manage this! */
3686 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3687 ioc->req_frames_dma = alloc_dma;
3689 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3690 ioc->name, mem, (void *)(ulong)alloc_dma));
3692 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3694 #if defined(CONFIG_MTRR) && 0
3696 * Enable Write Combining MTRR for IOC's memory region.
3697 * (at least as much as we can; "size and base must be
3698 * multiples of 4 kiB"
3700 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3702 MTRR_TYPE_WRCOMB, 1);
3703 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3704 ioc->name, ioc->req_frames_dma, sz));
3707 for (i = 0; i < ioc->req_depth; i++) {
3708 alloc_dma += ioc->req_sz;
3712 ioc->ChainBuffer = mem;
3713 ioc->ChainBufferDMA = alloc_dma;
3715 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3716 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3718 /* Initialize the free chain Q.
3721 INIT_LIST_HEAD(&ioc->FreeChainQ);
3723 /* Post the chain buffers to the FreeChainQ.
3725 mem = (u8 *)ioc->ChainBuffer;
3726 for (i=0; i < num_chain; i++) {
3727 mf = (MPT_FRAME_HDR *) mem;
3728 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3732 /* Initialize Request frames linked list
3734 alloc_dma = ioc->req_frames_dma;
3735 mem = (u8 *) ioc->req_frames;
3737 spin_lock_irqsave(&ioc->FreeQlock, flags);
3738 INIT_LIST_HEAD(&ioc->FreeQ);
3739 for (i = 0; i < ioc->req_depth; i++) {
3740 mf = (MPT_FRAME_HDR *) mem;
3742 /* Queue REQUESTs *internally*! */
3743 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3747 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3749 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3750 ioc->sense_buf_pool =
3751 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3752 if (ioc->sense_buf_pool == NULL) {
3753 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3758 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3759 ioc->alloc_total += sz;
3760 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3761 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3765 /* Post Reply frames to FIFO
3767 alloc_dma = ioc->alloc_dma;
3768 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3769 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3771 for (i = 0; i < ioc->reply_depth; i++) {
3772 /* Write each address to the IOC! */
3773 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3774 alloc_dma += ioc->reply_sz;
3780 if (ioc->alloc != NULL) {
3782 pci_free_consistent(ioc->pcidev,
3784 ioc->alloc, ioc->alloc_dma);
3785 ioc->reply_frames = NULL;
3786 ioc->req_frames = NULL;
3787 ioc->alloc_total -= sz;
3789 if (ioc->sense_buf_pool != NULL) {
3790 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3791 pci_free_consistent(ioc->pcidev,
3793 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3794 ioc->sense_buf_pool = NULL;
3799 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3801 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3802 * from IOC via doorbell handshake method.
3803 * @ioc: Pointer to MPT_ADAPTER structure
3804 * @reqBytes: Size of the request in bytes
3805 * @req: Pointer to MPT request frame
3806 * @replyBytes: Expected size of the reply in bytes
3807 * @u16reply: Pointer to area where reply should be written
3808 * @maxwait: Max wait time for a reply (in seconds)
3809 * @sleepFlag: Specifies whether the process can sleep
3811 * NOTES: It is the callers responsibility to byte-swap fields in the
3812 * request which are greater than 1 byte in size. It is also the
3813 * callers responsibility to byte-swap response fields which are
3814 * greater than 1 byte in size.
3816 * Returns 0 for success, non-zero for failure.
3819 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3820 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3822 MPIDefaultReply_t *mptReply;
3827 * Get ready to cache a handshake reply
3829 ioc->hs_reply_idx = 0;
3830 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3831 mptReply->MsgLength = 0;
3834 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3835 * then tell IOC that we want to handshake a request of N words.
3836 * (WRITE u32val to Doorbell reg).
3838 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3839 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3840 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3841 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3844 * Wait for IOC's doorbell handshake int
3846 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3849 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3850 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3852 /* Read doorbell and check for active bit */
3853 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3857 * Clear doorbell int (WRITE 0 to IntStatus reg),
3858 * then wait for IOC to ACKnowledge that it's ready for
3859 * our handshake request.
3861 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3862 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3867 u8 *req_as_bytes = (u8 *) req;
3870 * Stuff request words via doorbell handshake,
3871 * with ACK from IOC for each.
3873 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3874 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3875 (req_as_bytes[(ii*4) + 1] << 8) |
3876 (req_as_bytes[(ii*4) + 2] << 16) |
3877 (req_as_bytes[(ii*4) + 3] << 24));
3879 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3880 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3884 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3885 DBG_DUMP_REQUEST_FRAME_HDR(req)
3887 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3888 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3891 * Wait for completion of doorbell handshake reply from the IOC
3893 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3896 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3897 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3900 * Copy out the cached reply...
3902 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3903 u16reply[ii] = ioc->hs_reply[ii];
3911 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3913 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3914 * in it's IntStatus register.
3915 * @ioc: Pointer to MPT_ADAPTER structure
3916 * @howlong: How long to wait (in seconds)
3917 * @sleepFlag: Specifies whether the process can sleep
3919 * This routine waits (up to ~2 seconds max) for IOC doorbell
3920 * handshake ACKnowledge.
3922 * Returns a negative value on failure, else wait loop count.
3925 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3931 cntdn = 1000 * howlong;
3933 if (sleepFlag == CAN_SLEEP) {
3935 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3936 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3938 msleep_interruptible (1);
3943 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3944 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3952 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3957 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3958 ioc->name, count, intstat);
3962 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3964 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3965 * in it's IntStatus register.
3966 * @ioc: Pointer to MPT_ADAPTER structure
3967 * @howlong: How long to wait (in seconds)
3968 * @sleepFlag: Specifies whether the process can sleep
3970 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3972 * Returns a negative value on failure, else wait loop count.
3975 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3981 cntdn = 1000 * howlong;
3982 if (sleepFlag == CAN_SLEEP) {
3984 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3985 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3987 msleep_interruptible(1);
3992 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3993 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4001 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4002 ioc->name, count, howlong));
4006 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4007 ioc->name, count, intstat);
4011 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4013 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
4014 * @ioc: Pointer to MPT_ADAPTER structure
4015 * @howlong: How long to wait (in seconds)
4016 * @sleepFlag: Specifies whether the process can sleep
4018 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4019 * Reply is cached to IOC private area large enough to hold a maximum
4020 * of 128 bytes of reply data.
4022 * Returns a negative value on failure, else size of reply in WORDS.
4025 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4030 u16 *hs_reply = ioc->hs_reply;
4031 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4034 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4037 * Get first two u16's so we can look at IOC's intended reply MsgLength
4040 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4043 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4044 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4045 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4048 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4049 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4053 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4054 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4055 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4058 * If no error (and IOC said MsgLength is > 0), piece together
4059 * reply 16 bits at a time.
4061 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4062 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4064 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4065 /* don't overflow our IOC hs_reply[] buffer! */
4066 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4067 hs_reply[u16cnt] = hword;
4068 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4071 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4073 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4076 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4081 else if (u16cnt != (2 * mptReply->MsgLength)) {
4084 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4089 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4090 DBG_DUMP_REPLY_FRAME(mptReply)
4092 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4093 ioc->name, t, u16cnt/2));
4097 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4099 * GetLanConfigPages - Fetch LANConfig pages.
4100 * @ioc: Pointer to MPT_ADAPTER structure
4102 * Return: 0 for success
4103 * -ENOMEM if no memory available
4104 * -EPERM if not allowed due to ISR context
4105 * -EAGAIN if no msg frames currently available
4106 * -EFAULT for non-successful reply or no reply (timeout)
4109 GetLanConfigPages(MPT_ADAPTER *ioc)
4111 ConfigPageHeader_t hdr;
4113 LANPage0_t *ppage0_alloc;
4114 dma_addr_t page0_dma;
4115 LANPage1_t *ppage1_alloc;
4116 dma_addr_t page1_dma;
4121 /* Get LAN Page 0 header */
4122 hdr.PageVersion = 0;
4125 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4126 cfg.cfghdr.hdr = &hdr;
4128 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4133 if ((rc = mpt_config(ioc, &cfg)) != 0)
4136 if (hdr.PageLength > 0) {
4137 data_sz = hdr.PageLength * 4;
4138 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4141 memset((u8 *)ppage0_alloc, 0, data_sz);
4142 cfg.physAddr = page0_dma;
4143 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4145 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4147 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4148 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4152 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4155 * Normalize endianness of structure data,
4156 * by byte-swapping all > 1 byte fields!
4165 /* Get LAN Page 1 header */
4166 hdr.PageVersion = 0;
4169 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4170 cfg.cfghdr.hdr = &hdr;
4172 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4176 if ((rc = mpt_config(ioc, &cfg)) != 0)
4179 if (hdr.PageLength == 0)
4182 data_sz = hdr.PageLength * 4;
4184 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4186 memset((u8 *)ppage1_alloc, 0, data_sz);
4187 cfg.physAddr = page1_dma;
4188 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4190 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4192 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4193 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4196 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4199 * Normalize endianness of structure data,
4200 * by byte-swapping all > 1 byte fields!
4208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4210 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4211 * @ioc: Pointer to MPT_ADAPTER structure
4212 * @portnum: IOC Port number
4214 * Return: 0 for success
4215 * -ENOMEM if no memory available
4216 * -EPERM if not allowed due to ISR context
4217 * -EAGAIN if no msg frames currently available
4218 * -EFAULT for non-successful reply or no reply (timeout)
4221 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4223 ConfigPageHeader_t hdr;
4225 FCPortPage0_t *ppage0_alloc;
4226 FCPortPage0_t *pp0dest;
4227 dma_addr_t page0_dma;
4234 /* Get FCPort Page 0 header */
4235 hdr.PageVersion = 0;
4238 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4239 cfg.cfghdr.hdr = &hdr;
4241 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4243 cfg.pageAddr = portnum;
4246 if ((rc = mpt_config(ioc, &cfg)) != 0)
4249 if (hdr.PageLength == 0)
4252 data_sz = hdr.PageLength * 4;
4254 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4258 memset((u8 *)ppage0_alloc, 0, data_sz);
4259 cfg.physAddr = page0_dma;
4260 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4262 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4264 pp0dest = &ioc->fc_port_page0[portnum];
4265 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4266 memcpy(pp0dest, ppage0_alloc, copy_sz);
4269 * Normalize endianness of structure data,
4270 * by byte-swapping all > 1 byte fields!
4272 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4273 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4274 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4275 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4276 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4277 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4278 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4279 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4280 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4281 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4282 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4283 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4284 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4285 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4286 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4287 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4290 * if still doing discovery,
4291 * hang loose a while until finished
4293 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4295 msleep_interruptible(100);
4298 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4304 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4310 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4312 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4313 * @ioc: Pointer to MPT_ADAPTER structure
4314 * @sas_address: 64bit SAS Address for operation.
4315 * @target_id: specified target for operation
4316 * @bus: specified bus for operation
4317 * @persist_opcode: see below
4319 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4320 * devices not currently present.
4321 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4323 * NOTE: Don't use not this function during interrupt time.
4325 * Returns: 0 for success, non-zero error
4328 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4330 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4332 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4333 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4334 MPT_FRAME_HDR *mf = NULL;
4335 MPIHeader_t *mpi_hdr;
4338 /* insure garbage is not sent to fw */
4339 switch(persist_opcode) {
4341 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4342 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4350 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4352 /* Get a MF for this command.
4354 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4355 printk("%s: no msg frames!\n",__FUNCTION__);
4359 mpi_hdr = (MPIHeader_t *) mf;
4360 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4361 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4362 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4363 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4364 sasIoUnitCntrReq->Operation = persist_opcode;
4366 init_timer(&ioc->persist_timer);
4367 ioc->persist_timer.data = (unsigned long) ioc;
4368 ioc->persist_timer.function = mpt_timer_expired;
4369 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4370 ioc->persist_wait_done=0;
4371 add_timer(&ioc->persist_timer);
4372 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4373 wait_event(mpt_waitq, ioc->persist_wait_done);
4375 sasIoUnitCntrReply =
4376 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4377 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4378 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4380 sasIoUnitCntrReply->IOCStatus,
4381 sasIoUnitCntrReply->IOCLogInfo);
4385 printk("%s: success\n",__FUNCTION__);
4389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4391 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4392 * @ioc: Pointer to MPT_ADAPTER structure
4394 * Returns: 0 for success
4395 * -ENOMEM if no memory available
4396 * -EPERM if not allowed due to ISR context
4397 * -EAGAIN if no msg frames currently available
4398 * -EFAULT for non-successful reply or no reply (timeout)
4401 GetIoUnitPage2(MPT_ADAPTER *ioc)
4403 ConfigPageHeader_t hdr;
4405 IOUnitPage2_t *ppage_alloc;
4406 dma_addr_t page_dma;
4410 /* Get the page header */
4411 hdr.PageVersion = 0;
4414 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4415 cfg.cfghdr.hdr = &hdr;
4417 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4422 if ((rc = mpt_config(ioc, &cfg)) != 0)
4425 if (hdr.PageLength == 0)
4428 /* Read the config page */
4429 data_sz = hdr.PageLength * 4;
4431 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4433 memset((u8 *)ppage_alloc, 0, data_sz);
4434 cfg.physAddr = page_dma;
4435 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4437 /* If Good, save data */
4438 if ((rc = mpt_config(ioc, &cfg)) == 0)
4439 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4441 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4447 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4448 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4449 * @ioc: Pointer to a Adapter Strucutre
4450 * @portnum: IOC port number
4452 * Return: -EFAULT if read of config page header fails
4454 * If read of SCSI Port Page 0 fails,
4455 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4456 * Adapter settings: async, narrow
4458 * If read of SCSI Port Page 2 fails,
4459 * Adapter settings valid
4460 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4465 * CHECK - what type of locking mechanisms should be used????
4468 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4473 ConfigPageHeader_t header;
4479 if (!ioc->spi_data.nvram) {
4482 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4483 mem = kmalloc(sz, GFP_ATOMIC);
4487 ioc->spi_data.nvram = (int *) mem;
4489 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4490 ioc->name, ioc->spi_data.nvram, sz));
4493 /* Invalidate NVRAM information
4495 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4496 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4499 /* Read SPP0 header, allocate memory, then read page.
4501 header.PageVersion = 0;
4502 header.PageLength = 0;
4503 header.PageNumber = 0;
4504 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4505 cfg.cfghdr.hdr = &header;
4507 cfg.pageAddr = portnum;
4508 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4510 cfg.timeout = 0; /* use default */
4511 if (mpt_config(ioc, &cfg) != 0)
4514 if (header.PageLength > 0) {
4515 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4517 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4518 cfg.physAddr = buf_dma;
4519 if (mpt_config(ioc, &cfg) != 0) {
4520 ioc->spi_data.maxBusWidth = MPT_NARROW;
4521 ioc->spi_data.maxSyncOffset = 0;
4522 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4523 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4525 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4526 ioc->name, ioc->spi_data.minSyncFactor));
4528 /* Save the Port Page 0 data
4530 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4531 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4532 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4534 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4535 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4536 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4537 ioc->name, pPP0->Capabilities));
4539 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4540 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4542 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4543 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4544 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4545 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4546 ioc->name, ioc->spi_data.minSyncFactor));
4548 ioc->spi_data.maxSyncOffset = 0;
4549 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4552 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4554 /* Update the minSyncFactor based on bus type.
4556 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4557 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4559 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4560 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4561 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4562 ioc->name, ioc->spi_data.minSyncFactor));
4567 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4572 /* SCSI Port Page 2 - Read the header then the page.
4574 header.PageVersion = 0;
4575 header.PageLength = 0;
4576 header.PageNumber = 2;
4577 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4578 cfg.cfghdr.hdr = &header;
4580 cfg.pageAddr = portnum;
4581 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4583 if (mpt_config(ioc, &cfg) != 0)
4586 if (header.PageLength > 0) {
4587 /* Allocate memory and read SCSI Port Page 2
4589 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4591 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4592 cfg.physAddr = buf_dma;
4593 if (mpt_config(ioc, &cfg) != 0) {
4594 /* Nvram data is left with INVALID mark
4598 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4599 MpiDeviceInfo_t *pdevice = NULL;
4602 * Save "Set to Avoid SCSI Bus Resets" flag
4604 ioc->spi_data.bus_reset =
4605 (le32_to_cpu(pPP2->PortFlags) &
4606 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4609 /* Save the Port Page 2 data
4610 * (reformat into a 32bit quantity)
4612 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4613 ioc->spi_data.PortFlags = data;
4614 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4615 pdevice = &pPP2->DeviceSettings[ii];
4616 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4617 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4618 ioc->spi_data.nvram[ii] = data;
4622 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4626 /* Update Adapter limits with those from NVRAM
4627 * Comment: Don't need to do this. Target performance
4628 * parameters will never exceed the adapters limits.
4634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4635 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4636 * @ioc: Pointer to a Adapter Strucutre
4637 * @portnum: IOC port number
4639 * Return: -EFAULT if read of config page header fails
4643 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4646 ConfigPageHeader_t header;
4648 /* Read the SCSI Device Page 1 header
4650 header.PageVersion = 0;
4651 header.PageLength = 0;
4652 header.PageNumber = 1;
4653 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4654 cfg.cfghdr.hdr = &header;
4656 cfg.pageAddr = portnum;
4657 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4660 if (mpt_config(ioc, &cfg) != 0)
4663 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4664 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4666 header.PageVersion = 0;
4667 header.PageLength = 0;
4668 header.PageNumber = 0;
4669 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4670 if (mpt_config(ioc, &cfg) != 0)
4673 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4674 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4676 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4677 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4679 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4680 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4686 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4687 * @ioc: Pointer to a Adapter Strucutre
4688 * @portnum: IOC port number
4692 * -EFAULT if read of config page header fails or data pointer not NULL
4693 * -ENOMEM if pci_alloc failed
4696 mpt_findImVolumes(MPT_ADAPTER *ioc)
4700 ConfigPageIoc2RaidVol_t *pIocRv;
4701 dma_addr_t ioc2_dma;
4703 ConfigPageHeader_t header;
4710 /* Read IOCP2 header then the page.
4712 header.PageVersion = 0;
4713 header.PageLength = 0;
4714 header.PageNumber = 2;
4715 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4716 cfg.cfghdr.hdr = &header;
4719 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4722 if (mpt_config(ioc, &cfg) != 0)
4725 if (header.PageLength == 0)
4728 iocpage2sz = header.PageLength * 4;
4729 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4733 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4734 cfg.physAddr = ioc2_dma;
4735 if (mpt_config(ioc, &cfg) != 0)
4738 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4739 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4741 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4746 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4748 /* Identify RAID Volume Id's */
4749 nVols = pIoc2->NumActiveVolumes;
4755 /* At least 1 RAID Volume
4757 pIocRv = pIoc2->RaidVolume;
4758 ioc->raid_data.isRaid = 0;
4759 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4760 vid = pIocRv->VolumeID;
4761 vbus = pIocRv->VolumeBus;
4762 vioc = pIocRv->VolumeIOC;
4767 ioc->raid_data.isRaid |= (1 << vid);
4769 /* Error! Always bus 0
4775 /* Identify Hidden Physical Disk Id's */
4776 nPhys = pIoc2->NumActivePhysDisks;
4778 /* No physical disks.
4781 mpt_read_ioc_pg_3(ioc);
4785 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4791 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4796 ConfigPageHeader_t header;
4797 dma_addr_t ioc3_dma;
4800 /* Free the old page
4802 kfree(ioc->raid_data.pIocPg3);
4803 ioc->raid_data.pIocPg3 = NULL;
4805 /* There is at least one physical disk.
4806 * Read and save IOC Page 3
4808 header.PageVersion = 0;
4809 header.PageLength = 0;
4810 header.PageNumber = 3;
4811 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4812 cfg.cfghdr.hdr = &header;
4815 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4818 if (mpt_config(ioc, &cfg) != 0)
4821 if (header.PageLength == 0)
4824 /* Read Header good, alloc memory
4826 iocpage3sz = header.PageLength * 4;
4827 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4831 /* Read the Page and save the data
4832 * into malloc'd memory.
4834 cfg.physAddr = ioc3_dma;
4835 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4836 if (mpt_config(ioc, &cfg) == 0) {
4837 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4839 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4840 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4844 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4850 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4854 ConfigPageHeader_t header;
4855 dma_addr_t ioc4_dma;
4858 /* Read and save IOC Page 4
4860 header.PageVersion = 0;
4861 header.PageLength = 0;
4862 header.PageNumber = 4;
4863 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4864 cfg.cfghdr.hdr = &header;
4867 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4870 if (mpt_config(ioc, &cfg) != 0)
4873 if (header.PageLength == 0)
4876 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4877 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4878 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4882 ioc4_dma = ioc->spi_data.IocPg4_dma;
4883 iocpage4sz = ioc->spi_data.IocPg4Sz;
4886 /* Read the Page into dma memory.
4888 cfg.physAddr = ioc4_dma;
4889 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4890 if (mpt_config(ioc, &cfg) == 0) {
4891 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4892 ioc->spi_data.IocPg4_dma = ioc4_dma;
4893 ioc->spi_data.IocPg4Sz = iocpage4sz;
4895 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4896 ioc->spi_data.pIocPg4 = NULL;
4901 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4905 ConfigPageHeader_t header;
4906 dma_addr_t ioc1_dma;
4910 /* Check the Coalescing Timeout in IOC Page 1
4912 header.PageVersion = 0;
4913 header.PageLength = 0;
4914 header.PageNumber = 1;
4915 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4916 cfg.cfghdr.hdr = &header;
4919 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4922 if (mpt_config(ioc, &cfg) != 0)
4925 if (header.PageLength == 0)
4928 /* Read Header good, alloc memory
4930 iocpage1sz = header.PageLength * 4;
4931 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4935 /* Read the Page and check coalescing timeout
4937 cfg.physAddr = ioc1_dma;
4938 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4939 if (mpt_config(ioc, &cfg) == 0) {
4941 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4942 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4943 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4945 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4948 if (tmp > MPT_COALESCING_TIMEOUT) {
4949 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4951 /* Write NVRAM and current
4954 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4955 if (mpt_config(ioc, &cfg) == 0) {
4956 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4957 ioc->name, MPT_COALESCING_TIMEOUT));
4959 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4960 if (mpt_config(ioc, &cfg) == 0) {
4961 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4962 ioc->name, MPT_COALESCING_TIMEOUT));
4964 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4969 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4975 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4979 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4986 * SendEventNotification - Send EventNotification (on or off) request
4988 * @ioc: Pointer to MPT_ADAPTER structure
4989 * @EvSwitch: Event switch flags
4992 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4994 EventNotification_t *evnp;
4996 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
4998 devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5002 memset(evnp, 0, sizeof(*evnp));
5004 devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5006 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5007 evnp->ChainOffset = 0;
5009 evnp->Switch = EvSwitch;
5011 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5016 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5018 * SendEventAck - Send EventAck request to MPT adapter.
5019 * @ioc: Pointer to MPT_ADAPTER structure
5020 * @evnp: Pointer to original EventNotification request
5023 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5027 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5028 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5029 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5030 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5031 le32_to_cpu(evnp->Data[0]));
5034 memset(pAck, 0, sizeof(*pAck));
5036 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5038 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5039 pAck->ChainOffset = 0;
5041 pAck->Event = evnp->Event;
5042 pAck->EventContext = evnp->EventContext;
5044 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5051 * mpt_config - Generic function to issue config message
5052 * @ioc - Pointer to an adapter structure
5053 * @cfg - Pointer to a configuration structure. Struct contains
5054 * action, page address, direction, physical address
5055 * and pointer to a configuration page header
5056 * Page header is updated.
5058 * Returns 0 for success
5059 * -EPERM if not allowed due to ISR context
5060 * -EAGAIN if no msg frames currently available
5061 * -EFAULT for non-successful reply or no reply (timeout)
5064 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5067 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5069 unsigned long flags;
5074 /* Prevent calling wait_event() (below), if caller happens
5075 * to be in ISR context, because that is fatal!
5077 in_isr = in_interrupt();
5079 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5084 /* Get and Populate a free Frame
5086 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5087 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5091 pReq = (Config_t *)mf;
5092 pReq->Action = pCfg->action;
5094 pReq->ChainOffset = 0;
5095 pReq->Function = MPI_FUNCTION_CONFIG;
5097 /* Assume page type is not extended and clear "reserved" fields. */
5098 pReq->ExtPageLength = 0;
5099 pReq->ExtPageType = 0;
5102 for (ii=0; ii < 8; ii++)
5103 pReq->Reserved2[ii] = 0;
5105 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5106 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5107 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5108 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5110 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5111 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5112 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5113 pReq->ExtPageType = pExtHdr->ExtPageType;
5114 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5116 /* Page Length must be treated as a reserved field for the extended header. */
5117 pReq->Header.PageLength = 0;
5120 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5122 /* Add a SGE to the config request.
5125 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5127 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5129 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5130 flagsLength |= pExtHdr->ExtPageLength * 4;
5132 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5133 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5136 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5138 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5139 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5142 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5144 /* Append pCfg pointer to end of mf
5146 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5148 /* Initalize the timer
5150 init_timer(&pCfg->timer);
5151 pCfg->timer.data = (unsigned long) ioc;
5152 pCfg->timer.function = mpt_timer_expired;
5153 pCfg->wait_done = 0;
5155 /* Set the timer; ensure 10 second minimum */
5156 if (pCfg->timeout < 10)
5157 pCfg->timer.expires = jiffies + HZ*10;
5159 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5161 /* Add to end of Q, set timer and then issue this command */
5162 spin_lock_irqsave(&ioc->FreeQlock, flags);
5163 list_add_tail(&pCfg->linkage, &ioc->configQ);
5164 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5166 add_timer(&pCfg->timer);
5167 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5168 wait_event(mpt_waitq, pCfg->wait_done);
5170 /* mf has been freed - do not access */
5177 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5179 * mpt_toolbox - Generic function to issue toolbox message
5180 * @ioc - Pointer to an adapter structure
5181 * @cfg - Pointer to a toolbox structure. Struct contains
5182 * action, page address, direction, physical address
5183 * and pointer to a configuration page header
5184 * Page header is updated.
5186 * Returns 0 for success
5187 * -EPERM if not allowed due to ISR context
5188 * -EAGAIN if no msg frames currently available
5189 * -EFAULT for non-successful reply or no reply (timeout)
5192 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5194 ToolboxIstwiReadWriteRequest_t *pReq;
5196 struct pci_dev *pdev;
5197 unsigned long flags;
5202 /* Prevent calling wait_event() (below), if caller happens
5203 * to be in ISR context, because that is fatal!
5205 in_isr = in_interrupt();
5207 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
5212 /* Get and Populate a free Frame
5214 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5215 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
5219 pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
5220 pReq->Tool = pCfg->action;
5222 pReq->ChainOffset = 0;
5223 pReq->Function = MPI_FUNCTION_TOOLBOX;
5224 pReq->Reserved1 = 0;
5225 pReq->Reserved2 = 0;
5227 pReq->Flags = pCfg->dir;
5229 pReq->Reserved3 = 0;
5230 pReq->NumAddressBytes = 0x01;
5231 pReq->Reserved4 = 0;
5232 pReq->DataLength = cpu_to_le16(0x04);
5234 if (pdev->devfn & 1)
5235 pReq->DeviceAddr = 0xB2;
5237 pReq->DeviceAddr = 0xB0;
5241 pReq->Reserved5 = 0;
5243 /* Add a SGE to the config request.
5246 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5248 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5250 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5251 ioc->name, pReq->Tool));
5253 /* Append pCfg pointer to end of mf
5255 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5257 /* Initalize the timer
5259 init_timer(&pCfg->timer);
5260 pCfg->timer.data = (unsigned long) ioc;
5261 pCfg->timer.function = mpt_timer_expired;
5262 pCfg->wait_done = 0;
5264 /* Set the timer; ensure 10 second minimum */
5265 if (pCfg->timeout < 10)
5266 pCfg->timer.expires = jiffies + HZ*10;
5268 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5270 /* Add to end of Q, set timer and then issue this command */
5271 spin_lock_irqsave(&ioc->FreeQlock, flags);
5272 list_add_tail(&pCfg->linkage, &ioc->configQ);
5273 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5275 add_timer(&pCfg->timer);
5276 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5277 wait_event(mpt_waitq, pCfg->wait_done);
5279 /* mf has been freed - do not access */
5286 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5288 * mpt_timer_expired - Call back for timer process.
5289 * Used only internal config functionality.
5290 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5293 mpt_timer_expired(unsigned long data)
5295 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5297 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5299 /* Perform a FW reload */
5300 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5301 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5303 /* No more processing.
5304 * Hard reset clean-up will wake up
5305 * process and free all resources.
5307 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5312 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5314 * mpt_ioc_reset - Base cleanup for hard reset
5315 * @ioc: Pointer to the adapter structure
5316 * @reset_phase: Indicates pre- or post-reset functionality
5318 * Remark: Free's resources with internally generated commands.
5321 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5324 unsigned long flags;
5326 dprintk((KERN_WARNING MYNAM
5327 ": IOC %s_reset routed to MPT base driver!\n",
5328 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5329 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5331 if (reset_phase == MPT_IOC_SETUP_RESET) {
5333 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5334 /* If the internal config Q is not empty -
5335 * delete timer. MF resources will be freed when
5336 * the FIFO's are primed.
5338 spin_lock_irqsave(&ioc->FreeQlock, flags);
5339 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5340 del_timer(&pCfg->timer);
5341 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5346 /* Search the configQ for internal commands.
5347 * Flush the Q, and wake up all suspended threads.
5349 spin_lock_irqsave(&ioc->FreeQlock, flags);
5350 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5351 list_del(&pCfg->linkage);
5353 pCfg->status = MPT_CONFIG_ERROR;
5354 pCfg->wait_done = 1;
5355 wake_up(&mpt_waitq);
5357 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5360 return 1; /* currently means nothing really */
5364 #ifdef CONFIG_PROC_FS /* { */
5365 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5367 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5369 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5371 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5373 * Returns 0 for success, non-zero for failure.
5376 procmpt_create(void)
5378 struct proc_dir_entry *ent;
5380 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5381 if (mpt_proc_root_dir == NULL)
5384 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5386 ent->read_proc = procmpt_summary_read;
5388 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5390 ent->read_proc = procmpt_version_read;
5395 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5397 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5399 * Returns 0 for success, non-zero for failure.
5402 procmpt_destroy(void)
5404 remove_proc_entry("version", mpt_proc_root_dir);
5405 remove_proc_entry("summary", mpt_proc_root_dir);
5406 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5409 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5411 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5412 * or from /proc/mpt/iocN/summary.
5413 * @buf: Pointer to area to write information
5414 * @start: Pointer to start pointer
5415 * @offset: Offset to start writing
5417 * @eof: Pointer to EOF integer
5420 * Returns number of characters written to process performing the read.
5423 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5433 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5437 list_for_each_entry(ioc, &ioc_list, list) {
5440 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5443 if ((out-buf) >= request)
5450 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5453 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5455 * procmpt_version_read - Handle read request from /proc/mpt/version.
5456 * @buf: Pointer to area to write information
5457 * @start: Pointer to start pointer
5458 * @offset: Offset to start writing
5460 * @eof: Pointer to EOF integer
5463 * Returns number of characters written to process performing the read.
5466 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5469 int scsi, fc, sas, lan, ctl, targ, dmp;
5473 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5474 len += sprintf(buf+len, " Fusion MPT base driver\n");
5476 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5477 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5479 if (MptCallbacks[ii]) {
5480 switch (MptDriverClass[ii]) {
5482 if (!scsi++) drvname = "SPI host";
5485 if (!fc++) drvname = "FC host";
5488 if (!sas++) drvname = "SAS host";
5491 if (!lan++) drvname = "LAN";
5494 if (!targ++) drvname = "SCSI target";
5497 if (!ctl++) drvname = "ioctl";
5502 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5506 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5509 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5511 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5512 * @buf: Pointer to area to write information
5513 * @start: Pointer to start pointer
5514 * @offset: Offset to start writing
5516 * @eof: Pointer to EOF integer
5519 * Returns number of characters written to process performing the read.
5522 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5524 MPT_ADAPTER *ioc = data;
5530 mpt_get_fw_exp_ver(expVer, ioc);
5532 len = sprintf(buf, "%s:", ioc->name);
5533 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5534 len += sprintf(buf+len, " (f/w download boot flag set)");
5535 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5536 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5538 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5539 ioc->facts.ProductID,
5541 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5542 if (ioc->facts.FWImageSize)
5543 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5544 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5545 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5546 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5548 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5549 ioc->facts.CurrentHostMfaHighAddr);
5550 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5551 ioc->facts.CurrentSenseBufferHighAddr);
5553 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5554 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5556 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5557 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5559 * Rounding UP to nearest 4-kB boundary here...
5561 sz = (ioc->req_sz * ioc->req_depth) + 128;
5562 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5563 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5564 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5565 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5566 4*ioc->facts.RequestFrameSize,
5567 ioc->facts.GlobalCredits);
5569 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5570 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5571 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5572 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5573 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5574 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5575 ioc->facts.CurReplyFrameSize,
5576 ioc->facts.ReplyQueueDepth);
5578 len += sprintf(buf+len, " MaxDevices = %d\n",
5579 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5580 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5583 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5584 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5586 ioc->facts.NumberOfPorts);
5587 if (ioc->bus_type == FC) {
5588 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5589 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5590 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5591 a[5], a[4], a[3], a[2], a[1], a[0]);
5593 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5594 ioc->fc_port_page0[p].WWNN.High,
5595 ioc->fc_port_page0[p].WWNN.Low,
5596 ioc->fc_port_page0[p].WWPN.High,
5597 ioc->fc_port_page0[p].WWPN.Low);
5601 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5604 #endif /* CONFIG_PROC_FS } */
5606 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5608 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5611 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5612 sprintf(buf, " (Exp %02d%02d)",
5613 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5614 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5617 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5618 strcat(buf, " [MDBG]");
5622 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5624 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5625 * @ioc: Pointer to MPT_ADAPTER structure
5626 * @buffer: Pointer to buffer where IOC summary info should be written
5627 * @size: Pointer to number of bytes we wrote (set by this routine)
5628 * @len: Offset at which to start writing in buffer
5629 * @showlan: Display LAN stuff?
5631 * This routine writes (english readable) ASCII text, which represents
5632 * a summary of IOC information, to a buffer.
5635 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5640 mpt_get_fw_exp_ver(expVer, ioc);
5643 * Shorter summary of attached ioc's...
5645 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5648 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5649 ioc->facts.FWVersion.Word,
5651 ioc->facts.NumberOfPorts,
5654 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5655 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5656 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5657 a[5], a[4], a[3], a[2], a[1], a[0]);
5661 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5663 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5667 y += sprintf(buffer+len+y, " (disabled)");
5669 y += sprintf(buffer+len+y, "\n");
5674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5678 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5680 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5681 * Management call based on input arg values. If TaskMgmt fails,
5682 * return associated SCSI request.
5683 * @ioc: Pointer to MPT_ADAPTER structure
5684 * @sleepFlag: Indicates if sleep or schedule must be called.
5686 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5687 * or a non-interrupt thread. In the former, must not call schedule().
5689 * Remark: A return of -1 is a FATAL error case, as it means a
5690 * FW reload/initialization failed.
5692 * Returns 0 for SUCCESS or -1 if FAILED.
5695 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5698 unsigned long flags;
5700 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5702 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5703 printk("MF count 0x%x !\n", ioc->mfcnt);
5706 /* Reset the adapter. Prevent more than 1 call to
5707 * mpt_do_ioc_recovery at any instant in time.
5709 spin_lock_irqsave(&ioc->diagLock, flags);
5710 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5711 spin_unlock_irqrestore(&ioc->diagLock, flags);
5714 ioc->diagPending = 1;
5716 spin_unlock_irqrestore(&ioc->diagLock, flags);
5718 /* FIXME: If do_ioc_recovery fails, repeat....
5721 /* The SCSI driver needs to adjust timeouts on all current
5722 * commands prior to the diagnostic reset being issued.
5723 * Prevents timeouts occuring during a diagnostic reset...very bad.
5724 * For all other protocol drivers, this is a no-op.
5730 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5731 if (MptResetHandlers[ii]) {
5732 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5734 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5736 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5737 ioc->name, ioc->alt_ioc->name, ii));
5738 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5744 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5745 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5750 ioc->alt_ioc->reload_fw = 0;
5752 spin_lock_irqsave(&ioc->diagLock, flags);
5753 ioc->diagPending = 0;
5755 ioc->alt_ioc->diagPending = 0;
5756 spin_unlock_irqrestore(&ioc->diagLock, flags);
5758 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5763 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5765 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5770 case MPI_EVENT_NONE:
5773 case MPI_EVENT_LOG_DATA:
5776 case MPI_EVENT_STATE_CHANGE:
5777 ds = "State Change";
5779 case MPI_EVENT_UNIT_ATTENTION:
5780 ds = "Unit Attention";
5782 case MPI_EVENT_IOC_BUS_RESET:
5783 ds = "IOC Bus Reset";
5785 case MPI_EVENT_EXT_BUS_RESET:
5786 ds = "External Bus Reset";
5788 case MPI_EVENT_RESCAN:
5789 ds = "Bus Rescan Event";
5790 /* Ok, do we need to do anything here? As far as
5791 I can tell, this is when a new device gets added
5794 case MPI_EVENT_LINK_STATUS_CHANGE:
5795 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5796 ds = "Link Status(FAILURE) Change";
5798 ds = "Link Status(ACTIVE) Change";
5800 case MPI_EVENT_LOOP_STATE_CHANGE:
5801 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5802 ds = "Loop State(LIP) Change";
5803 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5804 ds = "Loop State(LPE) Change"; /* ??? */
5806 ds = "Loop State(LPB) Change"; /* ??? */
5808 case MPI_EVENT_LOGOUT:
5811 case MPI_EVENT_EVENT_CHANGE:
5813 ds = "Events(ON) Change";
5815 ds = "Events(OFF) Change";
5817 case MPI_EVENT_INTEGRATED_RAID:
5819 u8 ReasonCode = (u8)(evData0 >> 16);
5820 switch (ReasonCode) {
5821 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5822 ds = "Integrated Raid: Volume Created";
5824 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5825 ds = "Integrated Raid: Volume Deleted";
5827 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5828 ds = "Integrated Raid: Volume Settings Changed";
5830 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5831 ds = "Integrated Raid: Volume Status Changed";
5833 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5834 ds = "Integrated Raid: Volume Physdisk Changed";
5836 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5837 ds = "Integrated Raid: Physdisk Created";
5839 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5840 ds = "Integrated Raid: Physdisk Deleted";
5842 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5843 ds = "Integrated Raid: Physdisk Settings Changed";
5845 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5846 ds = "Integrated Raid: Physdisk Status Changed";
5848 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5849 ds = "Integrated Raid: Domain Validation Needed";
5851 case MPI_EVENT_RAID_RC_SMART_DATA :
5852 ds = "Integrated Raid; Smart Data";
5854 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5855 ds = "Integrated Raid: Replace Action Started";
5858 ds = "Integrated Raid";
5863 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5864 ds = "SCSI Device Status Change";
5866 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5868 u8 ReasonCode = (u8)(evData0 >> 16);
5869 switch (ReasonCode) {
5870 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5871 ds = "SAS Device Status Change: Added";
5873 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5874 ds = "SAS Device Status Change: Deleted";
5876 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5877 ds = "SAS Device Status Change: SMART Data";
5879 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5880 ds = "SAS Device Status Change: No Persistancy Added";
5883 ds = "SAS Device Status Change: Unknown";
5888 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5889 ds = "Bus Timer Expired";
5891 case MPI_EVENT_QUEUE_FULL:
5894 case MPI_EVENT_SAS_SES:
5895 ds = "SAS SES Event";
5897 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5898 ds = "Persistent Table Full";
5900 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5901 ds = "SAS PHY Link Status";
5903 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5904 ds = "SAS Discovery Error";
5908 * MPT base "custom" events may be added here...
5917 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5919 * ProcessEventNotification - Route a received EventNotificationReply to
5920 * all currently regeistered event handlers.
5921 * @ioc: Pointer to MPT_ADAPTER structure
5922 * @pEventReply: Pointer to EventNotification reply frame
5923 * @evHandlers: Pointer to integer, number of event handlers
5925 * Returns sum of event handlers return values.
5928 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5940 * Do platform normalization of values
5942 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5943 // evCtx = le32_to_cpu(pEventReply->EventContext);
5944 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5946 evData0 = le32_to_cpu(pEventReply->Data[0]);
5949 EventDescriptionStr(event, evData0, evStr);
5950 devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5955 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5956 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5957 for (ii = 0; ii < evDataLen; ii++)
5958 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5963 * Do general / base driver event processing
5966 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5968 u8 evState = evData0 & 0xFF;
5970 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5972 /* Update EventState field in cached IocFacts */
5973 if (ioc->facts.Function) {
5974 ioc->facts.EventState = evState;
5983 * Should this event be logged? Events are written sequentially.
5984 * When buffer is full, start again at the top.
5986 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5989 idx = ioc->eventContext % ioc->eventLogSize;
5991 ioc->events[idx].event = event;
5992 ioc->events[idx].eventContext = ioc->eventContext;
5994 for (ii = 0; ii < 2; ii++) {
5996 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5998 ioc->events[idx].data[ii] = 0;
6001 ioc->eventContext++;
6006 * Call each currently registered protocol event handler.
6008 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6009 if (MptEvHandlers[ii]) {
6010 devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6012 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6016 /* FIXME? Examine results here? */
6019 * If needed, send (a single) EventAck.
6021 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6022 devtprintk((MYIOC_s_WARN_FMT
6023 "EventAck required\n",ioc->name));
6024 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6025 devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6030 *evHandlers = handlers;
6034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6036 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6037 * @ioc: Pointer to MPT_ADAPTER structure
6038 * @log_info: U32 LogInfo reply word from the IOC
6040 * Refer to lsi/fc_log.h.
6043 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6045 static char *subcl_str[8] = {
6046 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6047 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6049 u8 subcl = (log_info >> 24) & 0x7;
6051 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6052 ioc->name, log_info, subcl_str[subcl]);
6055 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6057 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
6058 * @ioc: Pointer to MPT_ADAPTER structure
6059 * @mr: Pointer to MPT reply frame
6060 * @log_info: U32 LogInfo word from the IOC
6062 * Refer to lsi/sp_log.h.
6065 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
6067 u32 info = log_info & 0x00FF0000;
6068 char *desc = "unknown";
6072 desc = "bug! MID not found";
6073 if (ioc->reload_fw == 0)
6078 desc = "Parity Error";
6082 desc = "ASYNC Outbound Overrun";
6086 desc = "SYNC Offset Error";
6094 desc = "Msg In Overflow";
6102 desc = "Outbound DMA Overrun";
6106 desc = "Task Management";
6110 desc = "Device Problem";
6114 desc = "Invalid Phase Change";
6118 desc = "Untagged Table Size";
6123 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6126 /* strings for sas loginfo */
6127 static char *originator_str[] = {
6132 static char *iop_code_str[] = {
6134 "Invalid SAS Address", /* 01h */
6136 "Invalid Page", /* 03h */
6138 "Task Terminated" /* 05h */
6140 static char *pl_code_str[] = {
6142 "Open Failure", /* 01h */
6143 "Invalid Scatter Gather List", /* 02h */
6144 "Wrong Relative Offset or Frame Length", /* 03h */
6145 "Frame Transfer Error", /* 04h */
6146 "Transmit Frame Connected Low", /* 05h */
6147 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6148 "SATA Read Log Receive Data Error", /* 07h */
6149 "SATA NCQ Fail All Commands After Error", /* 08h */
6150 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6151 "Receive Frame Invalid Message", /* 0Ah */
6152 "Receive Context Message Valid Error", /* 0Bh */
6153 "Receive Frame Current Frame Error", /* 0Ch */
6154 "SATA Link Down", /* 0Dh */
6155 "Discovery SATA Init W IOS", /* 0Eh */
6156 "Config Invalid Page", /* 0Fh */
6157 "Discovery SATA Init Timeout", /* 10h */
6160 "IO Not Yet Executed", /* 13h */
6161 "IO Executed", /* 14h */
6173 "Enclosure Management" /* 20h */
6176 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6178 * mpt_sas_log_info - Log information returned from SAS IOC.
6179 * @ioc: Pointer to MPT_ADAPTER structure
6180 * @log_info: U32 LogInfo reply word from the IOC
6182 * Refer to lsi/mpi_log_sas.h.
6185 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6187 union loginfo_type {
6196 union loginfo_type sas_loginfo;
6197 char *code_desc = NULL;
6199 sas_loginfo.loginfo = log_info;
6200 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6201 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6203 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6204 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6205 code_desc = iop_code_str[sas_loginfo.dw.code];
6206 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6207 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6208 code_desc = pl_code_str[sas_loginfo.dw.code];
6211 if (code_desc != NULL)
6212 printk(MYIOC_s_INFO_FMT
6213 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6214 " SubCode(0x%04x)\n",
6217 originator_str[sas_loginfo.dw.originator],
6219 sas_loginfo.dw.subcode);
6221 printk(MYIOC_s_INFO_FMT
6222 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6223 " SubCode(0x%04x)\n",
6226 originator_str[sas_loginfo.dw.originator],
6227 sas_loginfo.dw.code,
6228 sas_loginfo.dw.subcode);
6231 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6233 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6234 * @ioc: Pointer to MPT_ADAPTER structure
6235 * @ioc_status: U32 IOCStatus word from IOC
6236 * @mf: Pointer to MPT request frame
6238 * Refer to lsi/mpi.h.
6241 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6243 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6247 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6248 desc = "Invalid Function";
6251 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6255 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6256 desc = "Invalid SGL";
6259 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6260 desc = "Internal Error";
6263 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6267 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6268 desc = "Insufficient Resources";
6271 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6272 desc = "Invalid Field";
6275 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6276 desc = "Invalid State";
6279 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6280 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6281 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6282 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6283 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6284 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6285 /* No message for Config IOCStatus values */
6288 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6289 /* No message for recovered error
6290 desc = "SCSI Recovered Error";
6294 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6295 desc = "SCSI Invalid Bus";
6298 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6299 desc = "SCSI Invalid TargetID";
6302 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6304 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6305 U8 cdb = pScsiReq->CDB[0];
6306 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6307 desc = "SCSI Device Not There";
6312 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6313 desc = "SCSI Data Overrun";
6316 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6317 /* This error is checked in scsi_io_done(). Skip.
6318 desc = "SCSI Data Underrun";
6322 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6323 desc = "SCSI I/O Data Error";
6326 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6327 desc = "SCSI Protocol Error";
6330 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6331 desc = "SCSI Task Terminated";
6334 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6335 desc = "SCSI Residual Mismatch";
6338 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6339 desc = "SCSI Task Management Failed";
6342 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6343 desc = "SCSI IOC Terminated";
6346 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6347 desc = "SCSI Ext Terminated";
6355 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6358 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6359 EXPORT_SYMBOL(mpt_attach);
6360 EXPORT_SYMBOL(mpt_detach);
6362 EXPORT_SYMBOL(mpt_resume);
6363 EXPORT_SYMBOL(mpt_suspend);
6365 EXPORT_SYMBOL(ioc_list);
6366 EXPORT_SYMBOL(mpt_proc_root_dir);
6367 EXPORT_SYMBOL(mpt_register);
6368 EXPORT_SYMBOL(mpt_deregister);
6369 EXPORT_SYMBOL(mpt_event_register);
6370 EXPORT_SYMBOL(mpt_event_deregister);
6371 EXPORT_SYMBOL(mpt_reset_register);
6372 EXPORT_SYMBOL(mpt_reset_deregister);
6373 EXPORT_SYMBOL(mpt_device_driver_register);
6374 EXPORT_SYMBOL(mpt_device_driver_deregister);
6375 EXPORT_SYMBOL(mpt_get_msg_frame);
6376 EXPORT_SYMBOL(mpt_put_msg_frame);
6377 EXPORT_SYMBOL(mpt_free_msg_frame);
6378 EXPORT_SYMBOL(mpt_add_sge);
6379 EXPORT_SYMBOL(mpt_send_handshake_request);
6380 EXPORT_SYMBOL(mpt_verify_adapter);
6381 EXPORT_SYMBOL(mpt_GetIocState);
6382 EXPORT_SYMBOL(mpt_print_ioc_summary);
6383 EXPORT_SYMBOL(mpt_lan_index);
6384 EXPORT_SYMBOL(mpt_stm_index);
6385 EXPORT_SYMBOL(mpt_HardResetHandler);
6386 EXPORT_SYMBOL(mpt_config);
6387 EXPORT_SYMBOL(mpt_toolbox);
6388 EXPORT_SYMBOL(mpt_findImVolumes);
6389 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
6390 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6391 EXPORT_SYMBOL(mpt_free_fw_memory);
6392 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6393 EXPORT_SYMBOL(mpt_alt_ioc_wait);
6394 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6397 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6399 * fusion_init - Fusion MPT base driver initialization routine.
6401 * Returns 0 for success, non-zero for failure.
6408 show_mptmod_ver(my_NAME, my_VERSION);
6409 printk(KERN_INFO COPYRIGHT "\n");
6411 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6412 MptCallbacks[i] = NULL;
6413 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6414 MptEvHandlers[i] = NULL;
6415 MptResetHandlers[i] = NULL;
6418 /* Register ourselves (mptbase) in order to facilitate
6419 * EventNotification handling.
6421 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6423 /* Register for hard reset handling callbacks.
6425 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6426 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6431 #ifdef CONFIG_PROC_FS
6432 (void) procmpt_create();
6437 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6439 * fusion_exit - Perform driver unload cleanup.
6441 * This routine frees all resources associated with each MPT adapter
6442 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6448 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6450 mpt_reset_deregister(mpt_base_index);
6452 #ifdef CONFIG_PROC_FS
6457 module_init(fusion_init);
6458 module_exit(fusion_exit);