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/version.h>
51 #include <linux/kernel.h>
52 #include <linux/module.h>
53 #include <linux/errno.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <linux/types.h>
57 #include <linux/pci.h>
58 #include <linux/kdev_t.h>
59 #include <linux/blkdev.h>
60 #include <linux/delay.h>
61 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
62 #include <linux/dma-mapping.h>
68 #include <asm/irq.h> /* needed for __irq_itoa() proto */
73 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
74 #define my_NAME "Fusion MPT base driver"
75 #define my_VERSION MPT_LINUX_VERSION_COMMON
76 #define MYNAM "mptbase"
78 MODULE_AUTHOR(MODULEAUTHOR);
79 MODULE_DESCRIPTION(my_NAME);
80 MODULE_LICENSE("GPL");
86 static int mfcounter = 0;
87 #define PRINT_MF_COUNT 20000
90 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
94 int mpt_lan_index = -1;
95 int mpt_stm_index = -1;
97 struct proc_dir_entry *mpt_proc_root_dir;
99 #define WHOINIT_UNKNOWN 0xAA
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
105 /* Adapter link list */
107 /* Callback lookup table */
108 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
109 /* Protocol driver class lookup table */
110 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
111 /* Event handler lookup table */
112 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
113 /* Reset handler lookup table */
114 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
115 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
117 static int mpt_base_index = -1;
118 static int last_drv_idx = -1;
120 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
126 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
127 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
128 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
129 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
131 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
132 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
133 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
134 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
136 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
137 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
138 //static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
139 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
140 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
141 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
142 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
143 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
144 static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
145 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
146 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
147 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
148 static int PrimeIocFifos(MPT_ADAPTER *ioc);
149 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
151 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
152 static int GetLanConfigPages(MPT_ADAPTER *ioc);
153 static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
154 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
155 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
156 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
157 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
158 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
159 static void mpt_timer_expired(unsigned long data);
160 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
161 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
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);
179 /* module entry point */
180 static int __init fusion_init (void);
181 static void __exit fusion_exit (void);
183 #define CHIPREG_READ32(addr) readl_relaxed(addr)
184 #define CHIPREG_READ32_dmasync(addr) readl(addr)
185 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
186 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
187 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
190 pci_disable_io_access(struct pci_dev *pdev)
194 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
196 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
200 pci_enable_io_access(struct pci_dev *pdev)
204 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
206 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
209 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
211 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
212 * @irq: irq number (not used)
213 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
214 * @r: pt_regs pointer (not used)
216 * This routine is registered via the request_irq() kernel API call,
217 * and handles all interrupts generated from a specific MPT adapter
218 * (also referred to as a IO Controller or IOC).
219 * This routine must clear the interrupt from the adapter and does
220 * so by reading the reply FIFO. Multiple replies may be processed
221 * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
222 * which is currently set to 32 in mptbase.h.
224 * This routine handles register-level access of the adapter but
225 * dispatches (calls) a protocol-specific callback routine to handle
226 * the protocol-specific details of the MPT request completion.
229 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
240 ioc = (MPT_ADAPTER *)bus_id;
243 * Drain the reply FIFO!
245 * NOTES: I've seen up to 10 replies processed in this loop, so far...
246 * Update: I've seen up to 9182 replies processed in this loop! ??
247 * Update: Limit ourselves to processing max of N replies
252 if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
259 * Check for non-TURBO reply!
261 if (pa & MPI_ADDRESS_REPLY_A_BIT) {
265 /* non-TURBO reply! Hmmm, something may be up...
266 * Newest turbo reply mechanism; get address
267 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
270 /* Map DMA address of reply header to cpu address.
271 * pa is 32 bits - but the dma address may be 32 or 64 bits
272 * get offset based only only the low addresses
274 reply_dma_low = (pa = (pa << 1));
275 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
276 (reply_dma_low - ioc->reply_frames_low_dma));
278 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
279 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
280 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
282 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
283 ioc->name, mr, req_idx));
284 DBG_DUMP_REPLY_FRAME(mr)
286 /* Check/log IOC log info
288 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
289 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
290 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
291 if (ioc->bus_type == FC)
292 mpt_fc_log_info(ioc, log_info);
293 else if (ioc->bus_type == SCSI)
294 mpt_sp_log_info(ioc, log_info);
296 if (ioc_stat & MPI_IOCSTATUS_MASK) {
297 if (ioc->bus_type == SCSI)
298 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
302 * Process turbo (context) reply...
304 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
305 type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
306 if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
307 cb_idx = mpt_stm_index;
309 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
310 } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
311 cb_idx = mpt_lan_index;
312 /* Blind set of mf to NULL here was fatal
313 * after lan_reply says "freeme"
314 * Fix sort of combined with an optimization here;
315 * added explicit check for case where lan_reply
316 * was just returning 1 and doing nothing else.
317 * For this case skip the callback, but set up
318 * proper mf value first here:-)
320 if ((pa & 0x58000000) == 0x58000000) {
321 req_idx = pa & 0x0000FFFF;
322 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
325 * IMPORTANT! Invalidate the callback!
331 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
333 req_idx = pa & 0x0000FFFF;
334 cb_idx = (pa & 0x00FF0000) >> 16;
335 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
338 pa = 0; /* No reply flush! */
342 if (ioc->bus_type == SCSI) {
343 /* Verify mf, mr are reasonable.
345 if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
346 || (mf < ioc->req_frames)) ) {
347 printk(MYIOC_s_WARN_FMT
348 "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
353 if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
354 || (mr < ioc->reply_frames)) ) {
355 printk(MYIOC_s_WARN_FMT
356 "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
361 if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
362 printk(MYIOC_s_WARN_FMT
363 "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
371 /* Check for (valid) IO callback! */
373 /* Do the callback! */
374 freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
378 /* Flush (non-TURBO) reply with a WRITE! */
379 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
383 /* Put Request back on FreeQ! */
384 mpt_free_msg_frame(ioc, mf);
388 } /* drain reply FIFO */
393 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
395 * mpt_base_reply - MPT base driver's callback routine; all base driver
396 * "internal" request/reply processing is routed here.
397 * Currently used for EventNotification and EventAck handling.
398 * @ioc: Pointer to MPT_ADAPTER structure
399 * @mf: Pointer to original MPT request frame
400 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
402 * Returns 1 indicating original alloc'd request frame ptr
403 * should be freed, or 0 if it shouldn't.
406 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
411 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
414 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
415 printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
416 ioc->name, (void *)mf);
421 dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
426 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
427 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
428 DBG_DUMP_REQUEST_FRAME_HDR(mf)
431 func = reply->u.hdr.Function;
432 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
435 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
436 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
440 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
441 if (results != evHandlers) {
442 /* CHECKME! Any special handling needed here? */
443 devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
444 ioc->name, evHandlers, results));
448 * Hmmm... It seems that EventNotificationReply is an exception
449 * to the rule of one reply per request.
451 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
454 #ifdef CONFIG_PROC_FS
455 // LogEvent(ioc, pEvReply);
458 } else if (func == MPI_FUNCTION_EVENT_ACK) {
459 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
461 } else if (func == MPI_FUNCTION_CONFIG ||
462 func == MPI_FUNCTION_TOOLBOX) {
466 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
467 ioc->name, mf, reply));
469 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
472 /* disable timer and remove from linked list */
473 del_timer(&pCfg->timer);
475 spin_lock_irqsave(&ioc->FreeQlock, flags);
476 list_del(&pCfg->linkage);
477 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
480 * If IOC Status is SUCCESS, save the header
481 * and set the status code to GOOD.
483 pCfg->status = MPT_CONFIG_ERROR;
485 ConfigReply_t *pReply = (ConfigReply_t *)reply;
488 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
489 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
490 status, le32_to_cpu(pReply->IOCLogInfo)));
492 pCfg->status = status;
493 if (status == MPI_IOCSTATUS_SUCCESS) {
494 if ((pReply->Header.PageType &
495 MPI_CONFIG_PAGETYPE_MASK) ==
496 MPI_CONFIG_PAGETYPE_EXTENDED) {
497 pCfg->cfghdr.ehdr->ExtPageLength =
498 le16_to_cpu(pReply->ExtPageLength);
499 pCfg->cfghdr.ehdr->ExtPageType =
502 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
504 /* If this is a regular header, save PageLength. */
505 /* LMP Do this better so not using a reserved field! */
506 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
507 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
508 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
513 * Wake up the original calling thread
519 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
524 * Conditionally tell caller to free the original
525 * EventNotification/EventAck/unexpected request frame!
530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
532 * mpt_register - Register protocol-specific main callback handler.
533 * @cbfunc: callback function pointer
534 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
536 * This routine is called by a protocol-specific driver (SCSI host,
537 * LAN, SCSI target) to register it's reply callback routine. Each
538 * protocol-specific driver must do this before it will be able to
539 * use any IOC resources, such as obtaining request frames.
541 * NOTES: The SCSI protocol driver currently calls this routine thrice
542 * in order to register separate callbacks; one for "normal" SCSI IO;
543 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
545 * Returns a positive integer valued "handle" in the
546 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
547 * Any non-positive return value (including zero!) should be considered
548 * an error by the caller.
551 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
558 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
559 * (slot/handle 0 is reserved!)
561 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
562 if (MptCallbacks[i] == NULL) {
563 MptCallbacks[i] = cbfunc;
564 MptDriverClass[i] = dclass;
565 MptEvHandlers[i] = NULL;
574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
576 * mpt_deregister - Deregister a protocol drivers resources.
577 * @cb_idx: previously registered callback handle
579 * Each protocol-specific driver should call this routine when it's
580 * module is unloaded.
583 mpt_deregister(int cb_idx)
585 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
586 MptCallbacks[cb_idx] = NULL;
587 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
588 MptEvHandlers[cb_idx] = NULL;
594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
596 * mpt_event_register - Register protocol-specific event callback
598 * @cb_idx: previously registered (via mpt_register) callback handle
599 * @ev_cbfunc: callback function
601 * This routine can be called by one or more protocol-specific drivers
602 * if/when they choose to be notified of MPT events.
604 * Returns 0 for success.
607 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
609 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
612 MptEvHandlers[cb_idx] = ev_cbfunc;
616 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
618 * mpt_event_deregister - Deregister protocol-specific event callback
620 * @cb_idx: previously registered callback handle
622 * Each protocol-specific driver should call this routine
623 * when it does not (or can no longer) handle events,
624 * or when it's module is unloaded.
627 mpt_event_deregister(int cb_idx)
629 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
632 MptEvHandlers[cb_idx] = NULL;
635 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
637 * mpt_reset_register - Register protocol-specific IOC reset handler.
638 * @cb_idx: previously registered (via mpt_register) callback handle
639 * @reset_func: reset function
641 * This routine can be called by one or more protocol-specific drivers
642 * if/when they choose to be notified of IOC resets.
644 * Returns 0 for success.
647 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
649 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
652 MptResetHandlers[cb_idx] = reset_func;
656 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
658 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
659 * @cb_idx: previously registered callback handle
661 * Each protocol-specific driver should call this routine
662 * when it does not (or can no longer) handle IOC reset handling,
663 * or when it's module is unloaded.
666 mpt_reset_deregister(int cb_idx)
668 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
671 MptResetHandlers[cb_idx] = NULL;
674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
676 * mpt_device_driver_register - Register device driver hooks
679 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
683 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
687 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
689 /* call per pci device probe entry point */
690 list_for_each_entry(ioc, &ioc_list, list) {
691 if(dd_cbfunc->probe) {
692 dd_cbfunc->probe(ioc->pcidev,
693 ioc->pcidev->driver->id_table);
700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
702 * mpt_device_driver_deregister - DeRegister device driver hooks
705 mpt_device_driver_deregister(int cb_idx)
707 struct mpt_pci_driver *dd_cbfunc;
710 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
713 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
715 list_for_each_entry(ioc, &ioc_list, list) {
716 if (dd_cbfunc->remove)
717 dd_cbfunc->remove(ioc->pcidev);
720 MptDeviceDriverHandlers[cb_idx] = NULL;
724 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
726 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
727 * allocated per MPT adapter.
728 * @handle: Handle of registered MPT protocol driver
729 * @ioc: Pointer to MPT adapter structure
731 * Returns pointer to a MPT request frame or %NULL if none are available
732 * or IOC is not active.
735 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
739 u16 req_idx; /* Request index */
741 /* validate handle and ioc identifier */
745 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
748 /* If interrupts are not attached, do not return a request frame */
752 spin_lock_irqsave(&ioc->FreeQlock, flags);
753 if (!list_empty(&ioc->FreeQ)) {
756 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
757 u.frame.linkage.list);
758 list_del(&mf->u.frame.linkage.list);
759 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
760 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
762 req_idx = req_offset / ioc->req_sz;
763 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
764 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
765 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
772 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
776 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
778 if (mfcounter == PRINT_MF_COUNT)
779 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
782 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
783 ioc->name, handle, ioc->id, mf));
787 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
789 * mpt_put_msg_frame - Send a protocol specific MPT request frame
791 * @handle: Handle of registered MPT protocol driver
792 * @ioc: Pointer to MPT adapter structure
793 * @mf: Pointer to MPT request frame
795 * This routine posts a MPT request frame to the request post FIFO of a
796 * specific MPT adapter.
799 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
803 u16 req_idx; /* Request index */
805 /* ensure values are reset properly! */
806 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
807 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
809 req_idx = req_offset / ioc->req_sz;
810 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
811 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
813 #ifdef MPT_DEBUG_MSG_FRAME
815 u32 *m = mf->u.frame.hwhdr.__hdr;
818 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
820 n = ioc->req_sz/4 - 1;
823 for (ii=0; ii<=n; ii++) {
824 if (ii && ((ii%8)==0))
825 printk("\n" KERN_INFO " ");
826 printk(" %08x", le32_to_cpu(m[ii]));
832 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
833 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]));
834 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
839 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
840 * @handle: Handle of registered MPT protocol driver
841 * @ioc: Pointer to MPT adapter structure
842 * @mf: Pointer to MPT request frame
844 * This routine places a MPT request frame back on the MPT adapter's
848 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
852 /* Put Request back on FreeQ! */
853 spin_lock_irqsave(&ioc->FreeQlock, flags);
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_verify_adapter - Given a unique IOC identifier, set pointer to
987 * the associated MPT adapter structure.
988 * @iocid: IOC unique identifier (integer)
989 * @iocpp: Pointer to pointer to IOC adapter
991 * Returns iocid and sets iocpp.
994 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
998 list_for_each_entry(ioc,&ioc_list,list) {
999 if (ioc->id == iocid) {
1009 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1011 * mpt_attach - Install a PCI intelligent MPT adapter.
1012 * @pdev: Pointer to pci_dev structure
1014 * This routine performs all the steps necessary to bring the IOC of
1015 * a MPT adapter to a OPERATIONAL state. This includes registering
1016 * memory regions, registering the interrupt, and allocating request
1017 * and reply memory pools.
1019 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1022 * Returns 0 for success, non-zero for failure.
1024 * TODO: Add support for polled controllers
1027 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1031 unsigned long mem_phys;
1039 static int mpt_ids = 0;
1040 #ifdef CONFIG_PROC_FS
1041 struct proc_dir_entry *dent, *ent;
1044 if (pci_enable_device(pdev))
1047 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1049 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1050 dprintk((KERN_INFO MYNAM
1051 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1052 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1053 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1057 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1058 dprintk((KERN_INFO MYNAM
1059 ": Using 64 bit consistent mask\n"));
1061 dprintk((KERN_INFO MYNAM
1062 ": Not using 64 bit consistent mask\n"));
1064 ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1066 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1069 memset(ioc, 0, sizeof(MPT_ADAPTER));
1070 ioc->alloc_total = sizeof(MPT_ADAPTER);
1071 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1072 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1075 ioc->diagPending = 0;
1076 spin_lock_init(&ioc->diagLock);
1078 /* Initialize the event logging.
1080 ioc->eventTypes = 0; /* None */
1081 ioc->eventContext = 0;
1082 ioc->eventLogSize = 0;
1089 ioc->cached_fw = NULL;
1091 /* Initilize SCSI Config Data structure
1093 memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
1095 /* Initialize the running configQ head.
1097 INIT_LIST_HEAD(&ioc->configQ);
1099 /* Find lookup slot. */
1100 INIT_LIST_HEAD(&ioc->list);
1101 ioc->id = mpt_ids++;
1103 mem_phys = msize = 0;
1105 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1106 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1107 /* Get I/O space! */
1108 port = pci_resource_start(pdev, ii);
1109 psize = pci_resource_len(pdev,ii);
1112 mem_phys = pci_resource_start(pdev, ii);
1113 msize = pci_resource_len(pdev,ii);
1117 ioc->mem_size = msize;
1119 if (ii == DEVICE_COUNT_RESOURCE) {
1120 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1125 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1126 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1129 /* Get logical ptr for PciMem0 space */
1130 /*mem = ioremap(mem_phys, msize);*/
1131 mem = ioremap(mem_phys, 0x100);
1133 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1138 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1140 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1141 &ioc->facts, &ioc->pfacts[0]));
1143 ioc->mem_phys = mem_phys;
1144 ioc->chip = (SYSIF_REGS __iomem *)mem;
1146 /* Save Port IO values in case we need to do downloadboot */
1148 u8 *pmem = (u8*)port;
1149 ioc->pio_mem_phys = port;
1150 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1153 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1154 ioc->prod_name = "LSIFC909";
1157 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1158 ioc->prod_name = "LSIFC929";
1161 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1162 ioc->prod_name = "LSIFC919";
1165 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1166 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1168 if (revision < XL_929) {
1169 ioc->prod_name = "LSIFC929X";
1170 /* 929X Chip Fix. Set Split transactions level
1171 * for PCIX. Set MOST bits to zero.
1173 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1175 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1177 ioc->prod_name = "LSIFC929XL";
1178 /* 929XL Chip Fix. Set MMRBC to 0x08.
1180 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1182 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1185 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1186 ioc->prod_name = "LSIFC919X";
1188 /* 919X Chip Fix. Set Split transactions level
1189 * for PCIX. Set MOST bits to zero.
1191 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1193 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1195 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1196 ioc->prod_name = "LSIFC939X";
1198 ioc->errata_flag_1064 = 1;
1200 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1201 ioc->prod_name = "LSIFC949X";
1203 ioc->errata_flag_1064 = 1;
1205 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1206 ioc->prod_name = "LSI53C1030";
1207 ioc->bus_type = SCSI;
1208 /* 1030 Chip Fix. Disable Split transactions
1209 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1211 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1212 if (revision < C0_1030) {
1213 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1215 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1218 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1219 ioc->prod_name = "LSI53C1035";
1220 ioc->bus_type = SCSI;
1223 if (ioc->errata_flag_1064)
1224 pci_disable_io_access(pdev);
1226 sprintf(ioc->name, "ioc%d", ioc->id);
1228 spin_lock_init(&ioc->FreeQlock);
1231 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1233 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1235 /* Set lookup ptr. */
1236 list_add_tail(&ioc->list, &ioc_list);
1240 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1244 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1245 ioc->name, pdev->irq);
1247 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1248 ioc->name, __irq_itoa(pdev->irq));
1250 list_del(&ioc->list);
1256 ioc->pci_irq = pdev->irq;
1258 pci_set_master(pdev); /* ?? */
1259 pci_set_drvdata(pdev, ioc);
1262 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1264 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1268 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1270 mpt_detect_bound_ports(ioc, pdev);
1272 if ((r = mpt_do_ioc_recovery(ioc,
1273 MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
1274 printk(KERN_WARNING MYNAM
1275 ": WARNING - %s did not initialize properly! (%d)\n",
1278 list_del(&ioc->list);
1279 free_irq(ioc->pci_irq, ioc);
1282 pci_set_drvdata(pdev, NULL);
1286 /* call per device driver probe entry point */
1287 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1288 if(MptDeviceDriverHandlers[ii] &&
1289 MptDeviceDriverHandlers[ii]->probe) {
1290 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1294 #ifdef CONFIG_PROC_FS
1296 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1298 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1300 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1302 ent->read_proc = procmpt_iocinfo_read;
1305 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1307 ent->read_proc = procmpt_summary_read;
1316 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1318 * mpt_detach - Remove a PCI intelligent MPT adapter.
1319 * @pdev: Pointer to pci_dev structure
1324 mpt_detach(struct pci_dev *pdev)
1326 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1330 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1331 remove_proc_entry(pname, NULL);
1332 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1333 remove_proc_entry(pname, NULL);
1334 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1335 remove_proc_entry(pname, NULL);
1337 /* call per device driver remove entry point */
1338 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1339 if(MptDeviceDriverHandlers[ii] &&
1340 MptDeviceDriverHandlers[ii]->remove) {
1341 MptDeviceDriverHandlers[ii]->remove(pdev);
1345 /* Disable interrupts! */
1346 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1349 synchronize_irq(pdev->irq);
1351 /* Clear any lingering interrupt */
1352 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1354 CHIPREG_READ32(&ioc->chip->IntStatus);
1356 mpt_adapter_dispose(ioc);
1358 pci_set_drvdata(pdev, NULL);
1361 /**************************************************************************
1365 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1367 * mpt_suspend - Fusion MPT base driver suspend routine.
1372 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1375 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1377 device_state=pci_choose_state(pdev, state);
1379 printk(MYIOC_s_INFO_FMT
1380 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1381 ioc->name, pdev, pci_name(pdev), device_state);
1383 pci_save_state(pdev);
1385 /* put ioc into READY_STATE */
1386 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1387 printk(MYIOC_s_ERR_FMT
1388 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1391 /* disable interrupts */
1392 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1395 /* Clear any lingering interrupt */
1396 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1398 pci_disable_device(pdev);
1399 pci_set_power_state(pdev, device_state);
1404 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1406 * mpt_resume - Fusion MPT base driver resume routine.
1411 mpt_resume(struct pci_dev *pdev)
1413 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1414 u32 device_state = pdev->current_state;
1418 printk(MYIOC_s_INFO_FMT
1419 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1420 ioc->name, pdev, pci_name(pdev), device_state);
1422 pci_set_power_state(pdev, 0);
1423 pci_restore_state(pdev);
1424 pci_enable_device(pdev);
1426 /* enable interrupts */
1427 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1430 /* F/W not running */
1431 if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1432 /* enable domain validation flags */
1433 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1434 ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1438 printk(MYIOC_s_INFO_FMT
1439 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1441 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1442 CHIPREG_READ32(&ioc->chip->Doorbell));
1444 /* bring ioc to operational state */
1445 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1446 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1447 printk(MYIOC_s_INFO_FMT
1448 "pci-resume: Cannot recover, error:[%x]\n",
1449 ioc->name, recovery_state);
1451 printk(MYIOC_s_INFO_FMT
1452 "pci-resume: success\n", ioc->name);
1459 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1461 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1462 * @ioc: Pointer to MPT adapter structure
1463 * @reason: Event word / reason
1464 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1466 * This routine performs all the steps necessary to bring the IOC
1467 * to a OPERATIONAL state.
1469 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1474 * -1 if failed to get board READY
1475 * -2 if READY but IOCFacts Failed
1476 * -3 if READY but PrimeIOCFifos Failed
1477 * -4 if READY but IOCInit Failed
1480 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1482 int hard_reset_done = 0;
1483 int alt_ioc_ready = 0;
1489 int reset_alt_ioc_active = 0;
1491 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1492 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1494 /* Disable reply interrupts (also blocks FreeQ) */
1495 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1499 if (ioc->alt_ioc->active)
1500 reset_alt_ioc_active = 1;
1502 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1503 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1504 ioc->alt_ioc->active = 0;
1508 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1511 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1512 if (hard_reset_done == -4) {
1513 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1516 if (reset_alt_ioc_active && ioc->alt_ioc) {
1517 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1518 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1519 ioc->alt_ioc->name));
1520 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1521 ioc->alt_ioc->active = 1;
1525 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1531 /* hard_reset_done = 0 if a soft reset was performed
1532 * and 1 if a hard reset was performed.
1534 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1535 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1538 printk(KERN_WARNING MYNAM
1539 ": alt-%s: Not ready WARNING!\n",
1540 ioc->alt_ioc->name);
1543 for (ii=0; ii<5; ii++) {
1544 /* Get IOC facts! Allow 5 retries */
1545 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1551 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1553 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1554 MptDisplayIocCapabilities(ioc);
1557 if (alt_ioc_ready) {
1558 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1559 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1560 /* Retry - alt IOC was initialized once
1562 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1565 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1567 reset_alt_ioc_active = 0;
1568 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1569 MptDisplayIocCapabilities(ioc->alt_ioc);
1573 /* Prime reply & request queues!
1574 * (mucho alloc's) Must be done prior to
1575 * init as upper addresses are needed for init.
1576 * If fails, continue with alt-ioc processing
1578 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1581 /* May need to check/upload firmware & data here!
1582 * If fails, continue with alt-ioc processing
1584 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1587 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1588 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1589 ioc->alt_ioc->name, rc);
1591 reset_alt_ioc_active = 0;
1594 if (alt_ioc_ready) {
1595 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1597 reset_alt_ioc_active = 0;
1598 printk(KERN_WARNING MYNAM
1599 ": alt-%s: (%d) init failure WARNING!\n",
1600 ioc->alt_ioc->name, rc);
1604 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1605 if (ioc->upload_fw) {
1606 ddlprintk((MYIOC_s_INFO_FMT
1607 "firmware upload required!\n", ioc->name));
1609 /* Controller is not operational, cannot do upload
1612 rc = mpt_do_upload(ioc, sleepFlag);
1614 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1620 /* Enable! (reply interrupt) */
1621 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1625 if (reset_alt_ioc_active && ioc->alt_ioc) {
1626 /* (re)Enable alt-IOC! (reply interrupt) */
1627 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1628 ioc->alt_ioc->name));
1629 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1630 ioc->alt_ioc->active = 1;
1633 /* Enable MPT base driver management of EventNotification
1634 * and EventAck handling.
1636 if ((ret == 0) && (!ioc->facts.EventState))
1637 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1639 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1640 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1642 /* Add additional "reason" check before call to GetLanConfigPages
1643 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1644 * recursive scenario; GetLanConfigPages times out, timer expired
1645 * routine calls HardResetHandler, which calls into here again,
1646 * and we try GetLanConfigPages again...
1648 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1649 if (ioc->bus_type == FC) {
1651 * Pre-fetch FC port WWN and stuff...
1652 * (FCPortPage0_t stuff)
1654 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1655 (void) GetFcPortPage0(ioc, ii);
1658 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1659 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1661 * Pre-fetch the ports LAN MAC address!
1662 * (LANPage1_t stuff)
1664 (void) GetLanConfigPages(ioc);
1667 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1668 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1669 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1674 /* Get NVRAM and adapter maximums from SPP 0 and 2
1676 mpt_GetScsiPortSettings(ioc, 0);
1678 /* Get version and length of SDP 1
1680 mpt_readScsiDevicePageHeaders(ioc, 0);
1684 if (ioc->facts.MsgVersion >= 0x0102)
1685 mpt_findImVolumes(ioc);
1687 /* Check, and possibly reset, the coalescing value
1689 mpt_read_ioc_pg_1(ioc);
1691 mpt_read_ioc_pg_4(ioc);
1694 GetIoUnitPage2(ioc);
1698 * Call each currently registered protocol IOC reset handler
1699 * with post-reset indication.
1700 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1701 * MptResetHandlers[] registered yet.
1703 if (hard_reset_done) {
1705 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1706 if ((ret == 0) && MptResetHandlers[ii]) {
1707 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1709 rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1713 if (alt_ioc_ready && MptResetHandlers[ii]) {
1714 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1715 ioc->name, ioc->alt_ioc->name, ii));
1716 rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1720 /* FIXME? Examine results here? */
1726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1728 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1729 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1730 * 929X, 1030 or 1035.
1731 * @ioc: Pointer to MPT adapter structure
1732 * @pdev: Pointer to (struct pci_dev) structure
1734 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1735 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1738 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1740 struct pci_dev *peer=NULL;
1741 unsigned int slot = PCI_SLOT(pdev->devfn);
1742 unsigned int func = PCI_FUNC(pdev->devfn);
1743 MPT_ADAPTER *ioc_srch;
1745 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1746 " searching for devfn match on %x or %x\n",
1747 ioc->name, pci_name(pdev), pdev->devfn,
1750 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1752 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1757 list_for_each_entry(ioc_srch, &ioc_list, list) {
1758 struct pci_dev *_pcidev = ioc_srch->pcidev;
1759 if (_pcidev == peer) {
1760 /* Paranoia checks */
1761 if (ioc->alt_ioc != NULL) {
1762 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1763 ioc->name, ioc->alt_ioc->name);
1765 } else if (ioc_srch->alt_ioc != NULL) {
1766 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1767 ioc_srch->name, ioc_srch->alt_ioc->name);
1770 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1771 ioc->name, ioc_srch->name));
1772 ioc_srch->alt_ioc = ioc;
1773 ioc->alt_ioc = ioc_srch;
1779 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1781 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1782 * @this: Pointer to MPT adapter structure
1785 mpt_adapter_disable(MPT_ADAPTER *ioc)
1790 if (ioc->cached_fw != NULL) {
1791 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1792 if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
1793 printk(KERN_WARNING MYNAM
1794 ": firmware downloadboot failure (%d)!\n", ret);
1798 /* Disable adapter interrupts! */
1799 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1801 /* Clear any lingering interrupt */
1802 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1804 if (ioc->alloc != NULL) {
1806 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1807 ioc->name, ioc->alloc, ioc->alloc_sz));
1808 pci_free_consistent(ioc->pcidev, sz,
1809 ioc->alloc, ioc->alloc_dma);
1810 ioc->reply_frames = NULL;
1811 ioc->req_frames = NULL;
1813 ioc->alloc_total -= sz;
1816 if (ioc->sense_buf_pool != NULL) {
1817 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1818 pci_free_consistent(ioc->pcidev, sz,
1819 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
1820 ioc->sense_buf_pool = NULL;
1821 ioc->alloc_total -= sz;
1824 if (ioc->events != NULL){
1825 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1828 ioc->alloc_total -= sz;
1831 if (ioc->cached_fw != NULL) {
1832 sz = ioc->facts.FWImageSize;
1833 pci_free_consistent(ioc->pcidev, sz,
1834 ioc->cached_fw, ioc->cached_fw_dma);
1835 ioc->cached_fw = NULL;
1836 ioc->alloc_total -= sz;
1839 kfree(ioc->spi_data.nvram);
1840 kfree(ioc->spi_data.pIocPg3);
1841 ioc->spi_data.nvram = NULL;
1842 ioc->spi_data.pIocPg3 = NULL;
1844 if (ioc->spi_data.pIocPg4 != NULL) {
1845 sz = ioc->spi_data.IocPg4Sz;
1846 pci_free_consistent(ioc->pcidev, sz,
1847 ioc->spi_data.pIocPg4,
1848 ioc->spi_data.IocPg4_dma);
1849 ioc->spi_data.pIocPg4 = NULL;
1850 ioc->alloc_total -= sz;
1853 if (ioc->ReqToChain != NULL) {
1854 kfree(ioc->ReqToChain);
1855 kfree(ioc->RequestNB);
1856 ioc->ReqToChain = NULL;
1859 kfree(ioc->ChainToChain);
1860 ioc->ChainToChain = NULL;
1863 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1865 * mpt_adapter_dispose - Free all resources associated with a MPT
1867 * @ioc: Pointer to MPT adapter structure
1869 * This routine unregisters h/w resources and frees all alloc'd memory
1870 * associated with a MPT adapter structure.
1873 mpt_adapter_dispose(MPT_ADAPTER *ioc)
1876 int sz_first, sz_last;
1878 sz_first = ioc->alloc_total;
1880 mpt_adapter_disable(ioc);
1882 if (ioc->pci_irq != -1) {
1883 free_irq(ioc->pci_irq, ioc);
1887 if (ioc->memmap != NULL)
1888 iounmap(ioc->memmap);
1890 #if defined(CONFIG_MTRR) && 0
1891 if (ioc->mtrr_reg > 0) {
1892 mtrr_del(ioc->mtrr_reg, 0, 0);
1893 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
1897 /* Zap the adapter lookup ptr! */
1898 list_del(&ioc->list);
1900 sz_last = ioc->alloc_total;
1901 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
1902 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
1907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1909 * MptDisplayIocCapabilities - Disply IOC's capacilities.
1910 * @ioc: Pointer to MPT adapter structure
1913 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
1917 printk(KERN_INFO "%s: ", ioc->name);
1918 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
1919 printk("%s: ", ioc->prod_name+3);
1920 printk("Capabilities={");
1922 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
1923 printk("Initiator");
1927 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1928 printk("%sTarget", i ? "," : "");
1932 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
1933 printk("%sLAN", i ? "," : "");
1939 * This would probably evoke more questions than it's worth
1941 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1942 printk("%sLogBusAddr", i ? "," : "");
1950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1952 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
1953 * @ioc: Pointer to MPT_ADAPTER structure
1954 * @force: Force hard KickStart of IOC
1955 * @sleepFlag: Specifies whether the process can sleep
1958 * 1 - DIAG reset and READY
1959 * 0 - READY initially OR soft reset and READY
1960 * -1 - Any failure on KickStart
1961 * -2 - Msg Unit Reset Failed
1962 * -3 - IO Unit Reset Failed
1963 * -4 - IOC owned by a PEER
1966 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
1971 int hard_reset_done = 0;
1976 /* Get current [raw] IOC state */
1977 ioc_state = mpt_GetIocState(ioc, 0);
1978 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
1981 * Check to see if IOC got left/stuck in doorbell handshake
1982 * grip of death. If so, hard reset the IOC.
1984 if (ioc_state & MPI_DOORBELL_ACTIVE) {
1986 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
1990 /* Is it already READY? */
1991 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
1995 * Check to see if IOC is in FAULT state.
1997 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
1999 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2001 printk(KERN_WARNING " FAULT code = %04xh\n",
2002 ioc_state & MPI_DOORBELL_DATA_MASK);
2006 * Hmmm... Did it get left operational?
2008 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2009 dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
2013 * If PCI Peer, exit.
2014 * Else, if no fault conditions are present, issue a MessageUnitReset
2015 * Else, fall through to KickStart case
2017 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2018 dprintk((KERN_WARNING MYNAM
2019 ": whoinit 0x%x\n statefault %d force %d\n",
2020 whoinit, statefault, force));
2021 if (whoinit == MPI_WHOINIT_PCI_PEER)
2024 if ((statefault == 0 ) && (force == 0)) {
2025 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2032 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2033 if (hard_reset_done < 0)
2037 * Loop here waiting for IOC to come READY.
2040 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
2042 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2043 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2045 * BIOS or previous driver load left IOC in OP state.
2046 * Reset messaging FIFOs.
2048 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2049 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2052 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2054 * Something is wrong. Try to get IOC back
2057 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2058 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2065 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2066 ioc->name, (int)((ii+5)/HZ));
2070 if (sleepFlag == CAN_SLEEP) {
2071 msleep_interruptible(1);
2073 mdelay (1); /* 1 msec delay */
2078 if (statefault < 3) {
2079 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2081 statefault==1 ? "stuck handshake" : "IOC FAULT");
2084 return hard_reset_done;
2087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2089 * mpt_GetIocState - Get the current state of a MPT adapter.
2090 * @ioc: Pointer to MPT_ADAPTER structure
2091 * @cooked: Request raw or cooked IOC state
2093 * Returns all IOC Doorbell register bits if cooked==0, else just the
2094 * Doorbell bits in MPI_IOC_STATE_MASK.
2097 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2102 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2103 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2104 sc = s & MPI_IOC_STATE_MASK;
2107 ioc->last_state = sc;
2109 return cooked ? sc : s;
2112 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2114 * GetIocFacts - Send IOCFacts request to MPT adapter.
2115 * @ioc: Pointer to MPT_ADAPTER structure
2116 * @sleepFlag: Specifies whether the process can sleep
2117 * @reason: If recovery, only update facts.
2119 * Returns 0 for success, non-zero for failure.
2122 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2124 IOCFacts_t get_facts;
2125 IOCFactsReply_t *facts;
2133 /* IOC *must* NOT be in RESET state! */
2134 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2135 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2141 facts = &ioc->facts;
2143 /* Destination (reply area)... */
2144 reply_sz = sizeof(*facts);
2145 memset(facts, 0, reply_sz);
2147 /* Request area (get_facts on the stack right now!) */
2148 req_sz = sizeof(get_facts);
2149 memset(&get_facts, 0, req_sz);
2151 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2152 /* Assert: All other get_facts fields are zero! */
2154 dinitprintk((MYIOC_s_INFO_FMT
2155 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2156 ioc->name, req_sz, reply_sz));
2158 /* No non-zero fields in the get_facts request are greater than
2159 * 1 byte in size, so we can just fire it off as is.
2161 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2162 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2167 * Now byte swap (GRRR) the necessary fields before any further
2168 * inspection of reply contents.
2170 * But need to do some sanity checks on MsgLength (byte) field
2171 * to make sure we don't zero IOC's req_sz!
2173 /* Did we get a valid reply? */
2174 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2175 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2177 * If not been here, done that, save off first WhoInit value
2179 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2180 ioc->FirstWhoInit = facts->WhoInit;
2183 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2184 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2185 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2186 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2187 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2188 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2189 /* CHECKME! IOCStatus, IOCLogInfo */
2191 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2192 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2195 * FC f/w version changed between 1.1 and 1.2
2196 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2197 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2199 if (facts->MsgVersion < 0x0102) {
2201 * Handle old FC f/w style, convert to new...
2203 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2204 facts->FWVersion.Word =
2205 ((oldv<<12) & 0xFF000000) |
2206 ((oldv<<8) & 0x000FFF00);
2208 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2210 facts->ProductID = le16_to_cpu(facts->ProductID);
2211 facts->CurrentHostMfaHighAddr =
2212 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2213 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2214 facts->CurrentSenseBufferHighAddr =
2215 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2216 facts->CurReplyFrameSize =
2217 le16_to_cpu(facts->CurReplyFrameSize);
2220 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2221 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2222 * to 14 in MPI-1.01.0x.
2224 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2225 facts->MsgVersion > 0x0100) {
2226 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2229 sz = facts->FWImageSize;
2234 facts->FWImageSize = sz;
2236 if (!facts->RequestFrameSize) {
2237 /* Something is wrong! */
2238 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2243 r = sz = facts->BlockSize;
2244 vv = ((63 / (sz * 4)) + 1) & 0x03;
2245 ioc->NB_for_64_byte_frame = vv;
2251 ioc->NBShiftFactor = shiftFactor;
2252 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2253 ioc->name, vv, shiftFactor, r));
2255 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2257 * Set values for this IOC's request & reply frame sizes,
2258 * and request & reply queue depths...
2260 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2261 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2262 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2263 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2265 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2266 ioc->name, ioc->reply_sz, ioc->reply_depth));
2267 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2268 ioc->name, ioc->req_sz, ioc->req_depth));
2270 /* Get port facts! */
2271 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2275 printk(MYIOC_s_ERR_FMT
2276 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2277 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2278 RequestFrameSize)/sizeof(u32)));
2285 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2287 * GetPortFacts - Send PortFacts request to MPT adapter.
2288 * @ioc: Pointer to MPT_ADAPTER structure
2289 * @portnum: Port number
2290 * @sleepFlag: Specifies whether the process can sleep
2292 * Returns 0 for success, non-zero for failure.
2295 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2297 PortFacts_t get_pfacts;
2298 PortFactsReply_t *pfacts;
2303 /* IOC *must* NOT be in RESET state! */
2304 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2305 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2311 pfacts = &ioc->pfacts[portnum];
2313 /* Destination (reply area)... */
2314 reply_sz = sizeof(*pfacts);
2315 memset(pfacts, 0, reply_sz);
2317 /* Request area (get_pfacts on the stack right now!) */
2318 req_sz = sizeof(get_pfacts);
2319 memset(&get_pfacts, 0, req_sz);
2321 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2322 get_pfacts.PortNumber = portnum;
2323 /* Assert: All other get_pfacts fields are zero! */
2325 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2326 ioc->name, portnum));
2328 /* No non-zero fields in the get_pfacts request are greater than
2329 * 1 byte in size, so we can just fire it off as is.
2331 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2332 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2336 /* Did we get a valid reply? */
2338 /* Now byte swap the necessary fields in the response. */
2339 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2340 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2341 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2342 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2343 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2344 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2345 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2346 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2347 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2352 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2354 * SendIocInit - Send IOCInit request to MPT adapter.
2355 * @ioc: Pointer to MPT_ADAPTER structure
2356 * @sleepFlag: Specifies whether the process can sleep
2358 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2360 * Returns 0 for success, non-zero for failure.
2363 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2366 MPIDefaultReply_t init_reply;
2372 memset(&ioc_init, 0, sizeof(ioc_init));
2373 memset(&init_reply, 0, sizeof(init_reply));
2375 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2376 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2378 /* If we are in a recovery mode and we uploaded the FW image,
2379 * then this pointer is not NULL. Skip the upload a second time.
2380 * Set this flag if cached_fw set for either IOC.
2382 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2386 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2387 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2389 if (ioc->bus_type == FC)
2390 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2392 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2394 ioc_init.MaxBuses = MPT_MAX_BUS;
2396 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2398 if (sizeof(dma_addr_t) == sizeof(u64)) {
2399 /* Save the upper 32-bits of the request
2400 * (reply) and sense buffers.
2402 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2403 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2405 /* Force 32-bit addressing */
2406 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2407 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2410 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2411 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2413 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2414 ioc->name, &ioc_init));
2416 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2417 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2421 /* No need to byte swap the multibyte fields in the reply
2422 * since we don't even look at it's contents.
2425 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2426 ioc->name, &ioc_init));
2428 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
2431 /* YIKES! SUPER IMPORTANT!!!
2432 * Poll IocState until _OPERATIONAL while IOC is doing
2433 * LoopInit and TargetDiscovery!
2436 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2437 state = mpt_GetIocState(ioc, 1);
2438 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2439 if (sleepFlag == CAN_SLEEP) {
2440 msleep_interruptible(1);
2446 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2447 ioc->name, (int)((count+5)/HZ));
2451 state = mpt_GetIocState(ioc, 1);
2454 dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2460 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2462 * SendPortEnable - Send PortEnable request to MPT adapter port.
2463 * @ioc: Pointer to MPT_ADAPTER structure
2464 * @portnum: Port number to enable
2465 * @sleepFlag: Specifies whether the process can sleep
2467 * Send PortEnable to bring IOC to OPERATIONAL state.
2469 * Returns 0 for success, non-zero for failure.
2472 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2474 PortEnable_t port_enable;
2475 MPIDefaultReply_t reply_buf;
2480 /* Destination... */
2481 reply_sz = sizeof(MPIDefaultReply_t);
2482 memset(&reply_buf, 0, reply_sz);
2484 req_sz = sizeof(PortEnable_t);
2485 memset(&port_enable, 0, req_sz);
2487 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2488 port_enable.PortNumber = portnum;
2489 /* port_enable.ChainOffset = 0; */
2490 /* port_enable.MsgFlags = 0; */
2491 /* port_enable.MsgContext = 0; */
2493 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2494 ioc->name, portnum, &port_enable));
2496 /* RAID FW may take a long time to enable
2498 if (ioc->bus_type == FC) {
2499 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2500 reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
2502 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2503 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
2509 /* We do not even look at the reply, so we need not
2510 * swap the multi-byte fields.
2517 * ioc: Pointer to MPT_ADAPTER structure
2518 * size - total FW bytes
2521 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2524 return; /* use already allocated memory */
2525 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2526 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2527 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2529 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2530 ioc->alloc_total += size;
2534 * If alt_img is NULL, delete from ioc structure.
2535 * Else, delete a secondary image in same format.
2538 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2542 sz = ioc->facts.FWImageSize;
2543 dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2544 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2545 pci_free_consistent(ioc->pcidev, sz,
2546 ioc->cached_fw, ioc->cached_fw_dma);
2547 ioc->cached_fw = NULL;
2553 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2555 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2556 * @ioc: Pointer to MPT_ADAPTER structure
2557 * @sleepFlag: Specifies whether the process can sleep
2559 * Returns 0 for success, >0 for handshake failure
2560 * <0 for fw upload failure.
2562 * Remark: If bound IOC and a successful FWUpload was performed
2563 * on the bound IOC, the second image is discarded
2564 * and memory is free'd. Both channels must upload to prevent
2565 * IOC from running in degraded mode.
2568 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2570 u8 request[ioc->req_sz];
2571 u8 reply[sizeof(FWUploadReply_t)];
2572 FWUpload_t *prequest;
2573 FWUploadReply_t *preply;
2574 FWUploadTCSGE_t *ptcsge;
2577 int ii, sz, reply_sz;
2580 /* If the image size is 0, we are done.
2582 if ((sz = ioc->facts.FWImageSize) == 0)
2585 mpt_alloc_fw_memory(ioc, sz);
2587 dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2588 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2590 if (ioc->cached_fw == NULL) {
2596 prequest = (FWUpload_t *)&request;
2597 preply = (FWUploadReply_t *)&reply;
2599 /* Destination... */
2600 memset(prequest, 0, ioc->req_sz);
2602 reply_sz = sizeof(reply);
2603 memset(preply, 0, reply_sz);
2605 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2606 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2608 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2609 ptcsge->DetailsLength = 12;
2610 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2611 ptcsge->ImageSize = cpu_to_le32(sz);
2613 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2615 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2616 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2618 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2619 dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
2620 prequest, sgeoffset));
2621 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2623 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2624 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2626 dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
2628 cmdStatus = -EFAULT;
2630 /* Handshake transfer was complete and successful.
2631 * Check the Reply Frame.
2633 int status, transfer_sz;
2634 status = le16_to_cpu(preply->IOCStatus);
2635 if (status == MPI_IOCSTATUS_SUCCESS) {
2636 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2637 if (transfer_sz == sz)
2641 dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
2642 ioc->name, cmdStatus));
2647 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2649 mpt_free_fw_memory(ioc);
2655 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2657 * mpt_downloadboot - DownloadBoot code
2658 * @ioc: Pointer to MPT_ADAPTER structure
2659 * @flag: Specify which part of IOC memory is to be uploaded.
2660 * @sleepFlag: Specifies whether the process can sleep
2662 * FwDownloadBoot requires Programmed IO access.
2664 * Returns 0 for success
2665 * -1 FW Image size is 0
2666 * -2 No valid cached_fw Pointer
2667 * <0 for fw upload failure.
2670 mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
2672 MpiFwHeader_t *pFwHeader;
2673 MpiExtImageHeader_t *pExtImage;
2683 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
2684 ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
2686 if ( ioc->facts.FWImageSize == 0 )
2689 if (ioc->cached_fw == NULL)
2692 /* prevent a second downloadboot and memory free with alt_ioc */
2693 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
2694 ioc->alt_ioc->cached_fw = NULL;
2696 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2697 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2698 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2699 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2700 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2701 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2703 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2706 if (sleepFlag == CAN_SLEEP) {
2707 msleep_interruptible(1);
2712 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2713 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2715 for (count = 0; count < 30; count ++) {
2716 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2717 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2718 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2723 if (sleepFlag == CAN_SLEEP) {
2724 msleep_interruptible (1000);
2730 if ( count == 30 ) {
2731 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n",
2732 ioc->name, diag0val));
2736 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2737 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2738 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2739 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2740 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2741 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2743 /* Set the DiagRwEn and Disable ARM bits */
2744 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2746 pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
2747 fwSize = (pFwHeader->ImageSize + 3)/4;
2748 ptrFw = (u32 *) pFwHeader;
2750 /* Write the LoadStartAddress to the DiagRw Address Register
2751 * using Programmed IO
2753 if (ioc->errata_flag_1064)
2754 pci_enable_io_access(ioc->pcidev);
2756 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2757 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2758 ioc->name, pFwHeader->LoadStartAddress));
2760 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2761 ioc->name, fwSize*4, ptrFw));
2763 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2766 nextImage = pFwHeader->NextImageHeaderOffset;
2768 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2770 load_addr = pExtImage->LoadStartAddress;
2772 fwSize = (pExtImage->ImageSize + 3) >> 2;
2773 ptrFw = (u32 *)pExtImage;
2775 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
2776 ioc->name, fwSize*4, ptrFw, load_addr));
2777 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2780 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2782 nextImage = pExtImage->NextImageHeaderOffset;
2785 /* Write the IopResetVectorRegAddr */
2786 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2787 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2789 /* Write the IopResetVectorValue */
2790 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
2791 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
2793 /* Clear the internal flash bad bit - autoincrementing register,
2794 * so must do two writes.
2796 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
2797 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
2798 diagRwData |= 0x4000000;
2799 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
2800 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
2802 if (ioc->errata_flag_1064)
2803 pci_disable_io_access(ioc->pcidev);
2805 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2806 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
2807 ioc->name, diag0val));
2808 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
2809 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
2810 ioc->name, diag0val));
2811 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
2813 /* Write 0xFF to reset the sequencer */
2814 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2816 for (count=0; count<HZ*20; count++) {
2817 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
2818 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
2819 ioc->name, count, ioc_state));
2820 if ((SendIocInit(ioc, sleepFlag)) != 0) {
2821 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
2825 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
2829 if (sleepFlag == CAN_SLEEP) {
2830 msleep_interruptible (10);
2835 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
2836 ioc->name, ioc_state));
2840 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2842 * KickStart - Perform hard reset of MPT adapter.
2843 * @ioc: Pointer to MPT_ADAPTER structure
2844 * @force: Force hard reset
2845 * @sleepFlag: Specifies whether the process can sleep
2847 * This routine places MPT adapter in diagnostic mode via the
2848 * WriteSequence register, and then performs a hard reset of adapter
2849 * via the Diagnostic register.
2851 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
2852 * or NO_SLEEP (interrupt thread, use mdelay)
2853 * force - 1 if doorbell active, board fault state
2854 * board operational, IOC_RECOVERY or
2855 * IOC_BRINGUP and there is an alt_ioc.
2859 * 1 - hard reset, READY
2860 * 0 - no reset due to History bit, READY
2861 * -1 - no reset due to History bit but not READY
2862 * OR reset but failed to come READY
2863 * -2 - no reset, could not enter DIAG mode
2864 * -3 - reset but bad FW bit
2867 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
2869 int hard_reset_done = 0;
2873 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
2874 if (ioc->bus_type == SCSI) {
2875 /* Always issue a Msg Unit Reset first. This will clear some
2876 * SCSI bus hang conditions.
2878 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
2880 if (sleepFlag == CAN_SLEEP) {
2881 msleep_interruptible (1000);
2887 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
2888 if (hard_reset_done < 0)
2889 return hard_reset_done;
2891 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
2894 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
2895 for (cnt=0; cnt<cntdn; cnt++) {
2896 ioc_state = mpt_GetIocState(ioc, 1);
2897 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
2898 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
2900 return hard_reset_done;
2902 if (sleepFlag == CAN_SLEEP) {
2903 msleep_interruptible (10);
2909 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
2910 ioc->name, ioc_state);
2914 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2916 * mpt_diag_reset - Perform hard reset of the adapter.
2917 * @ioc: Pointer to MPT_ADAPTER structure
2918 * @ignore: Set if to honor and clear to ignore
2919 * the reset history bit
2920 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
2921 * else set to NO_SLEEP (use mdelay instead)
2923 * This routine places the adapter in diagnostic mode via the
2924 * WriteSequence register and then performs a hard reset of adapter
2925 * via the Diagnostic register. Adapter should be in ready state
2926 * upon successful completion.
2928 * Returns: 1 hard reset successful
2929 * 0 no reset performed because reset history bit set
2930 * -2 enabling diagnostic mode failed
2931 * -3 diagnostic reset failed
2934 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
2938 int hard_reset_done = 0;
2944 /* Clear any existing interrupts */
2945 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2947 /* Use "Diagnostic reset" method! (only thing available!) */
2948 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2952 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2953 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
2954 ioc->name, diag0val, diag1val));
2957 /* Do the reset if we are told to ignore the reset history
2958 * or if the reset history is 0
2960 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
2961 while ((diag0val & MPI_DIAG_DRWE) == 0) {
2962 /* Write magic sequence to WriteSequence register
2963 * Loop until in diagnostic mode
2965 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2966 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2967 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2968 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2969 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2970 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2973 if (sleepFlag == CAN_SLEEP) {
2974 msleep_interruptible (100);
2981 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
2982 ioc->name, diag0val);
2987 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2989 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
2990 ioc->name, diag0val));
2995 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2996 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
2997 ioc->name, diag0val, diag1val));
3000 * Disable the ARM (Bug fix)
3003 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3007 * Now hit the reset bit in the Diagnostic register
3008 * (THE BIG HAMMER!) (Clears DRWE bit).
3010 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3011 hard_reset_done = 1;
3012 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3016 * Call each currently registered protocol IOC reset handler
3017 * with pre-reset indication.
3018 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3019 * MptResetHandlers[] registered yet.
3025 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3026 if (MptResetHandlers[ii]) {
3027 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3029 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3031 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3032 ioc->name, ioc->alt_ioc->name, ii));
3033 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3037 /* FIXME? Examine results here? */
3040 if (ioc->cached_fw) {
3041 /* If the DownloadBoot operation fails, the
3042 * IOC will be left unusable. This is a fatal error
3043 * case. _diag_reset will return < 0
3045 for (count = 0; count < 30; count ++) {
3046 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3047 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3052 if (sleepFlag == CAN_SLEEP) {
3058 if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
3059 printk(KERN_WARNING MYNAM
3060 ": firmware downloadboot failure (%d)!\n", count);
3064 /* Wait for FW to reload and for board
3065 * to go to the READY state.
3066 * Maximum wait is 60 seconds.
3067 * If fail, no error will check again
3068 * with calling program.
3070 for (count = 0; count < 60; count ++) {
3071 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3072 doorbell &= MPI_IOC_STATE_MASK;
3074 if (doorbell == MPI_IOC_STATE_READY) {
3079 if (sleepFlag == CAN_SLEEP) {
3080 msleep_interruptible (1000);
3088 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3091 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3092 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3093 ioc->name, diag0val, diag1val));
3096 /* Clear RESET_HISTORY bit! Place board in the
3097 * diagnostic mode to update the diag register.
3099 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3101 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3102 /* Write magic sequence to WriteSequence register
3103 * Loop until in diagnostic mode
3105 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3106 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3107 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3108 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3109 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3110 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3113 if (sleepFlag == CAN_SLEEP) {
3114 msleep_interruptible (100);
3121 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3122 ioc->name, diag0val);
3125 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3127 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3128 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3129 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3130 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3131 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3135 /* Disable Diagnostic Mode
3137 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3139 /* Check FW reload status flags.
3141 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3142 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3143 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3144 ioc->name, diag0val);
3150 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3151 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3152 ioc->name, diag0val, diag1val));
3156 * Reset flag that says we've enabled event notification
3158 ioc->facts.EventState = 0;
3161 ioc->alt_ioc->facts.EventState = 0;
3163 return hard_reset_done;
3166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3168 * SendIocReset - Send IOCReset request to MPT adapter.
3169 * @ioc: Pointer to MPT_ADAPTER structure
3170 * @reset_type: reset type, expected values are
3171 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3173 * Send IOCReset request to the MPT adapter.
3175 * Returns 0 for success, non-zero for failure.
3178 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3184 drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3185 ioc->name, reset_type));
3186 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3187 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3190 /* FW ACK'd request, wait for READY state
3193 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3195 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3199 if (sleepFlag != CAN_SLEEP)
3202 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3203 ioc->name, (int)((count+5)/HZ));
3207 if (sleepFlag == CAN_SLEEP) {
3208 msleep_interruptible(1);
3210 mdelay (1); /* 1 msec delay */
3215 * Cleanup all event stuff for this IOC; re-issue EventNotification
3216 * request if needed.
3218 if (ioc->facts.Function)
3219 ioc->facts.EventState = 0;
3224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3226 * initChainBuffers - Allocate memory for and initialize
3227 * chain buffers, chain buffer control arrays and spinlock.
3228 * @hd: Pointer to MPT_SCSI_HOST structure
3229 * @init: If set, initialize the spin lock.
3232 initChainBuffers(MPT_ADAPTER *ioc)
3235 int sz, ii, num_chain;
3236 int scale, num_sge, numSGE;
3238 /* ReqToChain size must equal the req_depth
3241 if (ioc->ReqToChain == NULL) {
3242 sz = ioc->req_depth * sizeof(int);
3243 mem = kmalloc(sz, GFP_ATOMIC);
3247 ioc->ReqToChain = (int *) mem;
3248 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3249 ioc->name, mem, sz));
3250 mem = kmalloc(sz, GFP_ATOMIC);
3254 ioc->RequestNB = (int *) mem;
3255 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3256 ioc->name, mem, sz));
3258 for (ii = 0; ii < ioc->req_depth; ii++) {
3259 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3262 /* ChainToChain size must equal the total number
3263 * of chain buffers to be allocated.
3266 * Calculate the number of chain buffers needed(plus 1) per I/O
3267 * then multiply the the maximum number of simultaneous cmds
3269 * num_sge = num sge in request frame + last chain buffer
3270 * scale = num sge per chain buffer if no chain element
3272 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3273 if (sizeof(dma_addr_t) == sizeof(u64))
3274 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3276 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3278 if (sizeof(dma_addr_t) == sizeof(u64)) {
3279 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3280 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3282 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3283 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3285 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3286 ioc->name, num_sge, numSGE));
3288 if ( numSGE > MPT_SCSI_SG_DEPTH )
3289 numSGE = MPT_SCSI_SG_DEPTH;
3292 while (numSGE - num_sge > 0) {
3294 num_sge += (scale - 1);
3298 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3299 ioc->name, numSGE, num_sge, num_chain));
3301 if (ioc->bus_type == SCSI)
3302 num_chain *= MPT_SCSI_CAN_QUEUE;
3304 num_chain *= MPT_FC_CAN_QUEUE;
3306 ioc->num_chain = num_chain;
3308 sz = num_chain * sizeof(int);
3309 if (ioc->ChainToChain == NULL) {
3310 mem = kmalloc(sz, GFP_ATOMIC);
3314 ioc->ChainToChain = (int *) mem;
3315 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3316 ioc->name, mem, sz));
3318 mem = (u8 *) ioc->ChainToChain;
3320 memset(mem, 0xFF, sz);
3324 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3326 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3327 * @ioc: Pointer to MPT_ADAPTER structure
3329 * This routine allocates memory for the MPT reply and request frame
3330 * pools (if necessary), and primes the IOC reply FIFO with
3333 * Returns 0 for success, non-zero for failure.
3336 PrimeIocFifos(MPT_ADAPTER *ioc)
3339 unsigned long flags;
3340 dma_addr_t alloc_dma;
3342 int i, reply_sz, sz, total_size, num_chain;
3344 /* Prime reply FIFO... */
3346 if (ioc->reply_frames == NULL) {
3347 if ( (num_chain = initChainBuffers(ioc)) < 0)
3350 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3351 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3352 ioc->name, ioc->reply_sz, ioc->reply_depth));
3353 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3354 ioc->name, reply_sz, reply_sz));
3356 sz = (ioc->req_sz * ioc->req_depth);
3357 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3358 ioc->name, ioc->req_sz, ioc->req_depth));
3359 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3360 ioc->name, sz, sz));
3363 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3364 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3365 ioc->name, ioc->req_sz, num_chain));
3366 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3367 ioc->name, sz, sz, num_chain));
3370 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3372 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3377 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3378 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3380 memset(mem, 0, total_size);
3381 ioc->alloc_total += total_size;
3383 ioc->alloc_dma = alloc_dma;
3384 ioc->alloc_sz = total_size;
3385 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3386 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3388 alloc_dma += reply_sz;
3391 /* Request FIFO - WE manage this! */
3393 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3394 ioc->req_frames_dma = alloc_dma;
3396 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
3397 ioc->name, mem, (void *)(ulong)alloc_dma));
3399 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3401 #if defined(CONFIG_MTRR) && 0
3403 * Enable Write Combining MTRR for IOC's memory region.
3404 * (at least as much as we can; "size and base must be
3405 * multiples of 4 kiB"
3407 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3409 MTRR_TYPE_WRCOMB, 1);
3410 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3411 ioc->name, ioc->req_frames_dma, sz));
3414 for (i = 0; i < ioc->req_depth; i++) {
3415 alloc_dma += ioc->req_sz;
3419 ioc->ChainBuffer = mem;
3420 ioc->ChainBufferDMA = alloc_dma;
3422 dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
3423 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3425 /* Initialize the free chain Q.
3428 INIT_LIST_HEAD(&ioc->FreeChainQ);
3430 /* Post the chain buffers to the FreeChainQ.
3432 mem = (u8 *)ioc->ChainBuffer;
3433 for (i=0; i < num_chain; i++) {
3434 mf = (MPT_FRAME_HDR *) mem;
3435 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3439 /* Initialize Request frames linked list
3441 alloc_dma = ioc->req_frames_dma;
3442 mem = (u8 *) ioc->req_frames;
3444 spin_lock_irqsave(&ioc->FreeQlock, flags);
3445 INIT_LIST_HEAD(&ioc->FreeQ);
3446 for (i = 0; i < ioc->req_depth; i++) {
3447 mf = (MPT_FRAME_HDR *) mem;
3449 /* Queue REQUESTs *internally*! */
3450 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3454 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3456 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3457 ioc->sense_buf_pool =
3458 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3459 if (ioc->sense_buf_pool == NULL) {
3460 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3465 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3466 ioc->alloc_total += sz;
3467 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3468 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3472 /* Post Reply frames to FIFO
3474 alloc_dma = ioc->alloc_dma;
3475 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3476 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3478 for (i = 0; i < ioc->reply_depth; i++) {
3479 /* Write each address to the IOC! */
3480 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3481 alloc_dma += ioc->reply_sz;
3487 if (ioc->alloc != NULL) {
3489 pci_free_consistent(ioc->pcidev,
3491 ioc->alloc, ioc->alloc_dma);
3492 ioc->reply_frames = NULL;
3493 ioc->req_frames = NULL;
3494 ioc->alloc_total -= sz;
3496 if (ioc->sense_buf_pool != NULL) {
3497 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3498 pci_free_consistent(ioc->pcidev,
3500 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3501 ioc->sense_buf_pool = NULL;
3506 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3508 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3509 * from IOC via doorbell handshake method.
3510 * @ioc: Pointer to MPT_ADAPTER structure
3511 * @reqBytes: Size of the request in bytes
3512 * @req: Pointer to MPT request frame
3513 * @replyBytes: Expected size of the reply in bytes
3514 * @u16reply: Pointer to area where reply should be written
3515 * @maxwait: Max wait time for a reply (in seconds)
3516 * @sleepFlag: Specifies whether the process can sleep
3518 * NOTES: It is the callers responsibility to byte-swap fields in the
3519 * request which are greater than 1 byte in size. It is also the
3520 * callers responsibility to byte-swap response fields which are
3521 * greater than 1 byte in size.
3523 * Returns 0 for success, non-zero for failure.
3526 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3527 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3529 MPIDefaultReply_t *mptReply;
3534 * Get ready to cache a handshake reply
3536 ioc->hs_reply_idx = 0;
3537 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3538 mptReply->MsgLength = 0;
3541 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3542 * then tell IOC that we want to handshake a request of N words.
3543 * (WRITE u32val to Doorbell reg).
3545 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3546 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3547 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3548 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3551 * Wait for IOC's doorbell handshake int
3553 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3556 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3557 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3559 /* Read doorbell and check for active bit */
3560 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3564 * Clear doorbell int (WRITE 0 to IntStatus reg),
3565 * then wait for IOC to ACKnowledge that it's ready for
3566 * our handshake request.
3568 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3569 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3574 u8 *req_as_bytes = (u8 *) req;
3577 * Stuff request words via doorbell handshake,
3578 * with ACK from IOC for each.
3580 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3581 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3582 (req_as_bytes[(ii*4) + 1] << 8) |
3583 (req_as_bytes[(ii*4) + 2] << 16) |
3584 (req_as_bytes[(ii*4) + 3] << 24));
3586 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3587 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3591 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3592 DBG_DUMP_REQUEST_FRAME_HDR(req)
3594 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3595 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3598 * Wait for completion of doorbell handshake reply from the IOC
3600 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3603 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3604 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3607 * Copy out the cached reply...
3609 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3610 u16reply[ii] = ioc->hs_reply[ii];
3618 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3620 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3621 * in it's IntStatus register.
3622 * @ioc: Pointer to MPT_ADAPTER structure
3623 * @howlong: How long to wait (in seconds)
3624 * @sleepFlag: Specifies whether the process can sleep
3626 * This routine waits (up to ~2 seconds max) for IOC doorbell
3627 * handshake ACKnowledge.
3629 * Returns a negative value on failure, else wait loop count.
3632 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3638 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
3640 if (sleepFlag == CAN_SLEEP) {
3642 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3643 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3645 msleep_interruptible (1);
3650 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3651 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3659 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3664 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3665 ioc->name, count, intstat);
3669 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3671 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3672 * in it's IntStatus register.
3673 * @ioc: Pointer to MPT_ADAPTER structure
3674 * @howlong: How long to wait (in seconds)
3675 * @sleepFlag: Specifies whether the process can sleep
3677 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3679 * Returns a negative value on failure, else wait loop count.
3682 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3688 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
3689 if (sleepFlag == CAN_SLEEP) {
3691 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3692 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3694 msleep_interruptible(1);
3699 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3700 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3708 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3709 ioc->name, count, howlong));
3713 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3714 ioc->name, count, intstat);
3718 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3720 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3721 * @ioc: Pointer to MPT_ADAPTER structure
3722 * @howlong: How long to wait (in seconds)
3723 * @sleepFlag: Specifies whether the process can sleep
3725 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3726 * Reply is cached to IOC private area large enough to hold a maximum
3727 * of 128 bytes of reply data.
3729 * Returns a negative value on failure, else size of reply in WORDS.
3732 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3737 u16 *hs_reply = ioc->hs_reply;
3738 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3741 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
3744 * Get first two u16's so we can look at IOC's intended reply MsgLength
3747 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
3750 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3751 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3752 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3755 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3756 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3760 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
3761 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
3762 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3765 * If no error (and IOC said MsgLength is > 0), piece together
3766 * reply 16 bits at a time.
3768 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
3769 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3771 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3772 /* don't overflow our IOC hs_reply[] buffer! */
3773 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
3774 hs_reply[u16cnt] = hword;
3775 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3778 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3780 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3783 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
3788 else if (u16cnt != (2 * mptReply->MsgLength)) {
3791 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
3796 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
3797 DBG_DUMP_REPLY_FRAME(mptReply)
3799 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
3800 ioc->name, t, u16cnt/2));
3804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3806 * GetLanConfigPages - Fetch LANConfig pages.
3807 * @ioc: Pointer to MPT_ADAPTER structure
3809 * Return: 0 for success
3810 * -ENOMEM if no memory available
3811 * -EPERM if not allowed due to ISR context
3812 * -EAGAIN if no msg frames currently available
3813 * -EFAULT for non-successful reply or no reply (timeout)
3816 GetLanConfigPages(MPT_ADAPTER *ioc)
3818 ConfigPageHeader_t hdr;
3820 LANPage0_t *ppage0_alloc;
3821 dma_addr_t page0_dma;
3822 LANPage1_t *ppage1_alloc;
3823 dma_addr_t page1_dma;
3828 /* Get LAN Page 0 header */
3829 hdr.PageVersion = 0;
3832 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
3833 cfg.cfghdr.hdr = &hdr;
3835 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3840 if ((rc = mpt_config(ioc, &cfg)) != 0)
3843 if (hdr.PageLength > 0) {
3844 data_sz = hdr.PageLength * 4;
3845 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
3848 memset((u8 *)ppage0_alloc, 0, data_sz);
3849 cfg.physAddr = page0_dma;
3850 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3852 if ((rc = mpt_config(ioc, &cfg)) == 0) {
3854 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
3855 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
3859 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
3862 * Normalize endianness of structure data,
3863 * by byte-swapping all > 1 byte fields!
3872 /* Get LAN Page 1 header */
3873 hdr.PageVersion = 0;
3876 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
3877 cfg.cfghdr.hdr = &hdr;
3879 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3883 if ((rc = mpt_config(ioc, &cfg)) != 0)
3886 if (hdr.PageLength == 0)
3889 data_sz = hdr.PageLength * 4;
3891 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
3893 memset((u8 *)ppage1_alloc, 0, data_sz);
3894 cfg.physAddr = page1_dma;
3895 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3897 if ((rc = mpt_config(ioc, &cfg)) == 0) {
3899 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
3900 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
3903 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
3906 * Normalize endianness of structure data,
3907 * by byte-swapping all > 1 byte fields!
3915 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3917 * GetFcPortPage0 - Fetch FCPort config Page0.
3918 * @ioc: Pointer to MPT_ADAPTER structure
3919 * @portnum: IOC Port number
3921 * Return: 0 for success
3922 * -ENOMEM if no memory available
3923 * -EPERM if not allowed due to ISR context
3924 * -EAGAIN if no msg frames currently available
3925 * -EFAULT for non-successful reply or no reply (timeout)
3928 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
3930 ConfigPageHeader_t hdr;
3932 FCPortPage0_t *ppage0_alloc;
3933 FCPortPage0_t *pp0dest;
3934 dma_addr_t page0_dma;
3939 /* Get FCPort Page 0 header */
3940 hdr.PageVersion = 0;
3943 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
3944 cfg.cfghdr.hdr = &hdr;
3946 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3948 cfg.pageAddr = portnum;
3951 if ((rc = mpt_config(ioc, &cfg)) != 0)
3954 if (hdr.PageLength == 0)
3957 data_sz = hdr.PageLength * 4;
3959 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
3961 memset((u8 *)ppage0_alloc, 0, data_sz);
3962 cfg.physAddr = page0_dma;
3963 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3965 if ((rc = mpt_config(ioc, &cfg)) == 0) {
3967 pp0dest = &ioc->fc_port_page0[portnum];
3968 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
3969 memcpy(pp0dest, ppage0_alloc, copy_sz);
3972 * Normalize endianness of structure data,
3973 * by byte-swapping all > 1 byte fields!
3975 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
3976 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
3977 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
3978 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
3979 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
3980 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
3981 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
3982 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
3983 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
3984 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
3985 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
3986 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
3987 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
3988 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
3989 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
3990 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
3994 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4000 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4002 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4003 * @ioc: Pointer to MPT_ADAPTER structure
4005 * Returns: 0 for success
4006 * -ENOMEM if no memory available
4007 * -EPERM if not allowed due to ISR context
4008 * -EAGAIN if no msg frames currently available
4009 * -EFAULT for non-successful reply or no reply (timeout)
4012 GetIoUnitPage2(MPT_ADAPTER *ioc)
4014 ConfigPageHeader_t hdr;
4016 IOUnitPage2_t *ppage_alloc;
4017 dma_addr_t page_dma;
4021 /* Get the page header */
4022 hdr.PageVersion = 0;
4025 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4026 cfg.cfghdr.hdr = &hdr;
4028 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4033 if ((rc = mpt_config(ioc, &cfg)) != 0)
4036 if (hdr.PageLength == 0)
4039 /* Read the config page */
4040 data_sz = hdr.PageLength * 4;
4042 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4044 memset((u8 *)ppage_alloc, 0, data_sz);
4045 cfg.physAddr = page_dma;
4046 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4048 /* If Good, save data */
4049 if ((rc = mpt_config(ioc, &cfg)) == 0)
4050 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4052 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4058 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4059 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4060 * @ioc: Pointer to a Adapter Strucutre
4061 * @portnum: IOC port number
4063 * Return: -EFAULT if read of config page header fails
4065 * If read of SCSI Port Page 0 fails,
4066 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4067 * Adapter settings: async, narrow
4069 * If read of SCSI Port Page 2 fails,
4070 * Adapter settings valid
4071 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4076 * CHECK - what type of locking mechanisms should be used????
4079 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4084 ConfigPageHeader_t header;
4090 if (!ioc->spi_data.nvram) {
4093 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4094 mem = kmalloc(sz, GFP_ATOMIC);
4098 ioc->spi_data.nvram = (int *) mem;
4100 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4101 ioc->name, ioc->spi_data.nvram, sz));
4104 /* Invalidate NVRAM information
4106 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4107 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4110 /* Read SPP0 header, allocate memory, then read page.
4112 header.PageVersion = 0;
4113 header.PageLength = 0;
4114 header.PageNumber = 0;
4115 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4116 cfg.cfghdr.hdr = &header;
4118 cfg.pageAddr = portnum;
4119 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4121 cfg.timeout = 0; /* use default */
4122 if (mpt_config(ioc, &cfg) != 0)
4125 if (header.PageLength > 0) {
4126 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4128 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4129 cfg.physAddr = buf_dma;
4130 if (mpt_config(ioc, &cfg) != 0) {
4131 ioc->spi_data.maxBusWidth = MPT_NARROW;
4132 ioc->spi_data.maxSyncOffset = 0;
4133 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4134 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4137 /* Save the Port Page 0 data
4139 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4140 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4141 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4143 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4144 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4145 dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4146 ioc->name, pPP0->Capabilities));
4148 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4149 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4151 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4152 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4153 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4155 ioc->spi_data.maxSyncOffset = 0;
4156 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4159 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4161 /* Update the minSyncFactor based on bus type.
4163 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4164 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4166 if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
4167 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4171 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4176 /* SCSI Port Page 2 - Read the header then the page.
4178 header.PageVersion = 0;
4179 header.PageLength = 0;
4180 header.PageNumber = 2;
4181 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4182 cfg.cfghdr.hdr = &header;
4184 cfg.pageAddr = portnum;
4185 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4187 if (mpt_config(ioc, &cfg) != 0)
4190 if (header.PageLength > 0) {
4191 /* Allocate memory and read SCSI Port Page 2
4193 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4195 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4196 cfg.physAddr = buf_dma;
4197 if (mpt_config(ioc, &cfg) != 0) {
4198 /* Nvram data is left with INVALID mark
4202 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4203 MpiDeviceInfo_t *pdevice = NULL;
4205 /* Save the Port Page 2 data
4206 * (reformat into a 32bit quantity)
4208 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4209 ioc->spi_data.PortFlags = data;
4210 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4211 pdevice = &pPP2->DeviceSettings[ii];
4212 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4213 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4214 ioc->spi_data.nvram[ii] = data;
4218 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4222 /* Update Adapter limits with those from NVRAM
4223 * Comment: Don't need to do this. Target performance
4224 * parameters will never exceed the adapters limits.
4230 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4231 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4232 * @ioc: Pointer to a Adapter Strucutre
4233 * @portnum: IOC port number
4235 * Return: -EFAULT if read of config page header fails
4239 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4242 ConfigPageHeader_t header;
4244 /* Read the SCSI Device Page 1 header
4246 header.PageVersion = 0;
4247 header.PageLength = 0;
4248 header.PageNumber = 1;
4249 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4250 cfg.cfghdr.hdr = &header;
4252 cfg.pageAddr = portnum;
4253 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4256 if (mpt_config(ioc, &cfg) != 0)
4259 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4260 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4262 header.PageVersion = 0;
4263 header.PageLength = 0;
4264 header.PageNumber = 0;
4265 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4266 if (mpt_config(ioc, &cfg) != 0)
4269 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4270 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4272 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4273 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4275 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4276 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4282 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4283 * @ioc: Pointer to a Adapter Strucutre
4284 * @portnum: IOC port number
4288 * -EFAULT if read of config page header fails or data pointer not NULL
4289 * -ENOMEM if pci_alloc failed
4292 mpt_findImVolumes(MPT_ADAPTER *ioc)
4296 ConfigPageIoc2RaidVol_t *pIocRv;
4297 dma_addr_t ioc2_dma;
4299 ConfigPageHeader_t header;
4306 /* Read IOCP2 header then the page.
4308 header.PageVersion = 0;
4309 header.PageLength = 0;
4310 header.PageNumber = 2;
4311 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4312 cfg.cfghdr.hdr = &header;
4315 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4318 if (mpt_config(ioc, &cfg) != 0)
4321 if (header.PageLength == 0)
4324 iocpage2sz = header.PageLength * 4;
4325 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4329 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4330 cfg.physAddr = ioc2_dma;
4331 if (mpt_config(ioc, &cfg) != 0)
4334 if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
4335 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4337 ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
4342 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4344 /* Identify RAID Volume Id's */
4345 nVols = pIoc2->NumActiveVolumes;
4351 /* At least 1 RAID Volume
4353 pIocRv = pIoc2->RaidVolume;
4354 ioc->spi_data.isRaid = 0;
4355 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4356 vid = pIocRv->VolumeID;
4357 vbus = pIocRv->VolumeBus;
4358 vioc = pIocRv->VolumeIOC;
4363 ioc->spi_data.isRaid |= (1 << vid);
4365 /* Error! Always bus 0
4371 /* Identify Hidden Physical Disk Id's */
4372 nPhys = pIoc2->NumActivePhysDisks;
4374 /* No physical disks.
4377 mpt_read_ioc_pg_3(ioc);
4381 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4387 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4392 ConfigPageHeader_t header;
4393 dma_addr_t ioc3_dma;
4396 /* Free the old page
4398 kfree(ioc->spi_data.pIocPg3);
4399 ioc->spi_data.pIocPg3 = NULL;
4401 /* There is at least one physical disk.
4402 * Read and save IOC Page 3
4404 header.PageVersion = 0;
4405 header.PageLength = 0;
4406 header.PageNumber = 3;
4407 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4408 cfg.cfghdr.hdr = &header;
4411 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4414 if (mpt_config(ioc, &cfg) != 0)
4417 if (header.PageLength == 0)
4420 /* Read Header good, alloc memory
4422 iocpage3sz = header.PageLength * 4;
4423 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4427 /* Read the Page and save the data
4428 * into malloc'd memory.
4430 cfg.physAddr = ioc3_dma;
4431 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4432 if (mpt_config(ioc, &cfg) == 0) {
4433 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4435 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4436 ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
4440 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4446 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4450 ConfigPageHeader_t header;
4451 dma_addr_t ioc4_dma;
4454 /* Read and save IOC Page 4
4456 header.PageVersion = 0;
4457 header.PageLength = 0;
4458 header.PageNumber = 4;
4459 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4460 cfg.cfghdr.hdr = &header;
4463 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4466 if (mpt_config(ioc, &cfg) != 0)
4469 if (header.PageLength == 0)
4472 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4473 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4474 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4478 ioc4_dma = ioc->spi_data.IocPg4_dma;
4479 iocpage4sz = ioc->spi_data.IocPg4Sz;
4482 /* Read the Page into dma memory.
4484 cfg.physAddr = ioc4_dma;
4485 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4486 if (mpt_config(ioc, &cfg) == 0) {
4487 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4488 ioc->spi_data.IocPg4_dma = ioc4_dma;
4489 ioc->spi_data.IocPg4Sz = iocpage4sz;
4491 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4492 ioc->spi_data.pIocPg4 = NULL;
4497 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4501 ConfigPageHeader_t header;
4502 dma_addr_t ioc1_dma;
4506 /* Check the Coalescing Timeout in IOC Page 1
4508 header.PageVersion = 0;
4509 header.PageLength = 0;
4510 header.PageNumber = 1;
4511 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4512 cfg.cfghdr.hdr = &header;
4515 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4518 if (mpt_config(ioc, &cfg) != 0)
4521 if (header.PageLength == 0)
4524 /* Read Header good, alloc memory
4526 iocpage1sz = header.PageLength * 4;
4527 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4531 /* Read the Page and check coalescing timeout
4533 cfg.physAddr = ioc1_dma;
4534 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4535 if (mpt_config(ioc, &cfg) == 0) {
4537 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4538 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4539 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4541 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4544 if (tmp > MPT_COALESCING_TIMEOUT) {
4545 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4547 /* Write NVRAM and current
4550 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4551 if (mpt_config(ioc, &cfg) == 0) {
4552 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4553 ioc->name, MPT_COALESCING_TIMEOUT));
4555 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4556 if (mpt_config(ioc, &cfg) == 0) {
4557 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4558 ioc->name, MPT_COALESCING_TIMEOUT));
4560 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4565 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4571 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4575 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4580 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4582 * SendEventNotification - Send EventNotification (on or off) request
4584 * @ioc: Pointer to MPT_ADAPTER structure
4585 * @EvSwitch: Event switch flags
4588 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4590 EventNotification_t *evnp;
4592 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
4594 dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
4598 memset(evnp, 0, sizeof(*evnp));
4600 dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
4602 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
4603 evnp->ChainOffset = 0;
4605 evnp->Switch = EvSwitch;
4607 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
4612 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4614 * SendEventAck - Send EventAck request to MPT adapter.
4615 * @ioc: Pointer to MPT_ADAPTER structure
4616 * @evnp: Pointer to original EventNotification request
4619 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
4623 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4624 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
4628 memset(pAck, 0, sizeof(*pAck));
4630 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
4632 pAck->Function = MPI_FUNCTION_EVENT_ACK;
4633 pAck->ChainOffset = 0;
4635 pAck->Event = evnp->Event;
4636 pAck->EventContext = evnp->EventContext;
4638 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
4643 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4645 * mpt_config - Generic function to issue config message
4646 * @ioc - Pointer to an adapter structure
4647 * @cfg - Pointer to a configuration structure. Struct contains
4648 * action, page address, direction, physical address
4649 * and pointer to a configuration page header
4650 * Page header is updated.
4652 * Returns 0 for success
4653 * -EPERM if not allowed due to ISR context
4654 * -EAGAIN if no msg frames currently available
4655 * -EFAULT for non-successful reply or no reply (timeout)
4658 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
4661 ConfigExtendedPageHeader_t *pExtHdr = NULL;
4663 unsigned long flags;
4668 /* Prevent calling wait_event() (below), if caller happens
4669 * to be in ISR context, because that is fatal!
4671 in_isr = in_interrupt();
4673 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
4678 /* Get and Populate a free Frame
4680 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4681 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
4685 pReq = (Config_t *)mf;
4686 pReq->Action = pCfg->action;
4688 pReq->ChainOffset = 0;
4689 pReq->Function = MPI_FUNCTION_CONFIG;
4691 /* Assume page type is not extended and clear "reserved" fields. */
4692 pReq->ExtPageLength = 0;
4693 pReq->ExtPageType = 0;
4696 for (ii=0; ii < 8; ii++)
4697 pReq->Reserved2[ii] = 0;
4699 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
4700 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
4701 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
4702 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
4704 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
4705 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
4706 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
4707 pReq->ExtPageType = pExtHdr->ExtPageType;
4708 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
4710 /* Page Length must be treated as a reserved field for the extended header. */
4711 pReq->Header.PageLength = 0;
4714 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
4716 /* Add a SGE to the config request.
4719 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
4721 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
4723 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
4724 flagsLength |= pExtHdr->ExtPageLength * 4;
4726 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
4727 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
4730 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
4732 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
4733 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
4736 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
4738 /* Append pCfg pointer to end of mf
4740 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
4742 /* Initalize the timer
4744 init_timer(&pCfg->timer);
4745 pCfg->timer.data = (unsigned long) ioc;
4746 pCfg->timer.function = mpt_timer_expired;
4747 pCfg->wait_done = 0;
4749 /* Set the timer; ensure 10 second minimum */
4750 if (pCfg->timeout < 10)
4751 pCfg->timer.expires = jiffies + HZ*10;
4753 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
4755 /* Add to end of Q, set timer and then issue this command */
4756 spin_lock_irqsave(&ioc->FreeQlock, flags);
4757 list_add_tail(&pCfg->linkage, &ioc->configQ);
4758 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4760 add_timer(&pCfg->timer);
4761 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4762 wait_event(mpt_waitq, pCfg->wait_done);
4764 /* mf has been freed - do not access */
4771 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4773 * mpt_toolbox - Generic function to issue toolbox message
4774 * @ioc - Pointer to an adapter structure
4775 * @cfg - Pointer to a toolbox structure. Struct contains
4776 * action, page address, direction, physical address
4777 * and pointer to a configuration page header
4778 * Page header is updated.
4780 * Returns 0 for success
4781 * -EPERM if not allowed due to ISR context
4782 * -EAGAIN if no msg frames currently available
4783 * -EFAULT for non-successful reply or no reply (timeout)
4786 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
4788 ToolboxIstwiReadWriteRequest_t *pReq;
4790 struct pci_dev *pdev;
4791 unsigned long flags;
4796 /* Prevent calling wait_event() (below), if caller happens
4797 * to be in ISR context, because that is fatal!
4799 in_isr = in_interrupt();
4801 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
4806 /* Get and Populate a free Frame
4808 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4809 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
4813 pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
4814 pReq->Tool = pCfg->action;
4816 pReq->ChainOffset = 0;
4817 pReq->Function = MPI_FUNCTION_TOOLBOX;
4818 pReq->Reserved1 = 0;
4819 pReq->Reserved2 = 0;
4821 pReq->Flags = pCfg->dir;
4823 pReq->Reserved3 = 0;
4824 pReq->NumAddressBytes = 0x01;
4825 pReq->Reserved4 = 0;
4826 pReq->DataLength = cpu_to_le16(0x04);
4828 if (pdev->devfn & 1)
4829 pReq->DeviceAddr = 0xB2;
4831 pReq->DeviceAddr = 0xB0;
4835 pReq->Reserved5 = 0;
4837 /* Add a SGE to the config request.
4840 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
4842 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
4844 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
4845 ioc->name, pReq->Tool));
4847 /* Append pCfg pointer to end of mf
4849 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
4851 /* Initalize the timer
4853 init_timer(&pCfg->timer);
4854 pCfg->timer.data = (unsigned long) ioc;
4855 pCfg->timer.function = mpt_timer_expired;
4856 pCfg->wait_done = 0;
4858 /* Set the timer; ensure 10 second minimum */
4859 if (pCfg->timeout < 10)
4860 pCfg->timer.expires = jiffies + HZ*10;
4862 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
4864 /* Add to end of Q, set timer and then issue this command */
4865 spin_lock_irqsave(&ioc->FreeQlock, flags);
4866 list_add_tail(&pCfg->linkage, &ioc->configQ);
4867 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4869 add_timer(&pCfg->timer);
4870 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4871 wait_event(mpt_waitq, pCfg->wait_done);
4873 /* mf has been freed - do not access */
4880 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4882 * mpt_timer_expired - Call back for timer process.
4883 * Used only internal config functionality.
4884 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4887 mpt_timer_expired(unsigned long data)
4889 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
4891 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
4893 /* Perform a FW reload */
4894 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
4895 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
4897 /* No more processing.
4898 * Hard reset clean-up will wake up
4899 * process and free all resources.
4901 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
4906 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4908 * mpt_ioc_reset - Base cleanup for hard reset
4909 * @ioc: Pointer to the adapter structure
4910 * @reset_phase: Indicates pre- or post-reset functionality
4912 * Remark: Free's resources with internally generated commands.
4915 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
4918 unsigned long flags;
4920 dprintk((KERN_WARNING MYNAM
4921 ": IOC %s_reset routed to MPT base driver!\n",
4922 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
4923 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
4925 if (reset_phase == MPT_IOC_SETUP_RESET) {
4927 } else if (reset_phase == MPT_IOC_PRE_RESET) {
4928 /* If the internal config Q is not empty -
4929 * delete timer. MF resources will be freed when
4930 * the FIFO's are primed.
4932 spin_lock_irqsave(&ioc->FreeQlock, flags);
4933 list_for_each_entry(pCfg, &ioc->configQ, linkage)
4934 del_timer(&pCfg->timer);
4935 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4940 /* Search the configQ for internal commands.
4941 * Flush the Q, and wake up all suspended threads.
4943 spin_lock_irqsave(&ioc->FreeQlock, flags);
4944 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
4945 list_del(&pCfg->linkage);
4947 pCfg->status = MPT_CONFIG_ERROR;
4948 pCfg->wait_done = 1;
4949 wake_up(&mpt_waitq);
4951 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4954 return 1; /* currently means nothing really */
4958 #ifdef CONFIG_PROC_FS /* { */
4959 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4961 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
4963 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4965 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
4967 * Returns 0 for success, non-zero for failure.
4970 procmpt_create(void)
4972 struct proc_dir_entry *ent;
4974 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
4975 if (mpt_proc_root_dir == NULL)
4978 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
4980 ent->read_proc = procmpt_summary_read;
4982 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
4984 ent->read_proc = procmpt_version_read;
4989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4991 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
4993 * Returns 0 for success, non-zero for failure.
4996 procmpt_destroy(void)
4998 remove_proc_entry("version", mpt_proc_root_dir);
4999 remove_proc_entry("summary", mpt_proc_root_dir);
5000 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5003 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5005 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5006 * or from /proc/mpt/iocN/summary.
5007 * @buf: Pointer to area to write information
5008 * @start: Pointer to start pointer
5009 * @offset: Offset to start writing
5011 * @eof: Pointer to EOF integer
5014 * Returns number of characters written to process performing the read.
5017 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5027 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5031 list_for_each_entry(ioc, &ioc_list, list) {
5034 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5037 if ((out-buf) >= request)
5044 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5047 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5049 * procmpt_version_read - Handle read request from /proc/mpt/version.
5050 * @buf: Pointer to area to write information
5051 * @start: Pointer to start pointer
5052 * @offset: Offset to start writing
5054 * @eof: Pointer to EOF integer
5057 * Returns number of characters written to process performing the read.
5060 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5063 int scsi, fc, sas, lan, ctl, targ, dmp;
5067 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5068 len += sprintf(buf+len, " Fusion MPT base driver\n");
5070 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5071 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5073 if (MptCallbacks[ii]) {
5074 switch (MptDriverClass[ii]) {
5076 if (!scsi++) drvname = "SPI host";
5079 if (!fc++) drvname = "FC host";
5082 if (!sas++) drvname = "SAS host";
5085 if (!lan++) drvname = "LAN";
5088 if (!targ++) drvname = "SCSI target";
5091 if (!ctl++) drvname = "ioctl";
5096 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5100 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5105 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5106 * @buf: Pointer to area to write information
5107 * @start: Pointer to start pointer
5108 * @offset: Offset to start writing
5110 * @eof: Pointer to EOF integer
5113 * Returns number of characters written to process performing the read.
5116 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5118 MPT_ADAPTER *ioc = data;
5124 mpt_get_fw_exp_ver(expVer, ioc);
5126 len = sprintf(buf, "%s:", ioc->name);
5127 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5128 len += sprintf(buf+len, " (f/w download boot flag set)");
5129 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5130 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5132 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5133 ioc->facts.ProductID,
5135 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5136 if (ioc->facts.FWImageSize)
5137 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5138 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5139 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5140 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5142 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5143 ioc->facts.CurrentHostMfaHighAddr);
5144 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5145 ioc->facts.CurrentSenseBufferHighAddr);
5147 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5148 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5150 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5151 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5153 * Rounding UP to nearest 4-kB boundary here...
5155 sz = (ioc->req_sz * ioc->req_depth) + 128;
5156 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5157 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5158 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5159 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5160 4*ioc->facts.RequestFrameSize,
5161 ioc->facts.GlobalCredits);
5163 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5164 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5165 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5166 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5167 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5168 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5169 ioc->facts.CurReplyFrameSize,
5170 ioc->facts.ReplyQueueDepth);
5172 len += sprintf(buf+len, " MaxDevices = %d\n",
5173 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5174 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5177 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5178 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5180 ioc->facts.NumberOfPorts);
5181 if (ioc->bus_type == FC) {
5182 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5183 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5184 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5185 a[5], a[4], a[3], a[2], a[1], a[0]);
5187 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5188 ioc->fc_port_page0[p].WWNN.High,
5189 ioc->fc_port_page0[p].WWNN.Low,
5190 ioc->fc_port_page0[p].WWPN.High,
5191 ioc->fc_port_page0[p].WWPN.Low);
5195 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5198 #endif /* CONFIG_PROC_FS } */
5200 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5202 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5205 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5206 sprintf(buf, " (Exp %02d%02d)",
5207 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5208 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5211 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5212 strcat(buf, " [MDBG]");
5216 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5218 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5219 * @ioc: Pointer to MPT_ADAPTER structure
5220 * @buffer: Pointer to buffer where IOC summary info should be written
5221 * @size: Pointer to number of bytes we wrote (set by this routine)
5222 * @len: Offset at which to start writing in buffer
5223 * @showlan: Display LAN stuff?
5225 * This routine writes (english readable) ASCII text, which represents
5226 * a summary of IOC information, to a buffer.
5229 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5234 mpt_get_fw_exp_ver(expVer, ioc);
5237 * Shorter summary of attached ioc's...
5239 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5242 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5243 ioc->facts.FWVersion.Word,
5245 ioc->facts.NumberOfPorts,
5248 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5249 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5250 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5251 a[5], a[4], a[3], a[2], a[1], a[0]);
5255 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5257 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5261 y += sprintf(buffer+len+y, " (disabled)");
5263 y += sprintf(buffer+len+y, "\n");
5268 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5272 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5274 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5275 * Management call based on input arg values. If TaskMgmt fails,
5276 * return associated SCSI request.
5277 * @ioc: Pointer to MPT_ADAPTER structure
5278 * @sleepFlag: Indicates if sleep or schedule must be called.
5280 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5281 * or a non-interrupt thread. In the former, must not call schedule().
5283 * Remark: A return of -1 is a FATAL error case, as it means a
5284 * FW reload/initialization failed.
5286 * Returns 0 for SUCCESS or -1 if FAILED.
5289 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5292 unsigned long flags;
5294 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5296 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5297 printk("MF count 0x%x !\n", ioc->mfcnt);
5300 /* Reset the adapter. Prevent more than 1 call to
5301 * mpt_do_ioc_recovery at any instant in time.
5303 spin_lock_irqsave(&ioc->diagLock, flags);
5304 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5305 spin_unlock_irqrestore(&ioc->diagLock, flags);
5308 ioc->diagPending = 1;
5310 spin_unlock_irqrestore(&ioc->diagLock, flags);
5312 /* FIXME: If do_ioc_recovery fails, repeat....
5315 /* The SCSI driver needs to adjust timeouts on all current
5316 * commands prior to the diagnostic reset being issued.
5317 * Prevents timeouts occuring during a diagnostic reset...very bad.
5318 * For all other protocol drivers, this is a no-op.
5324 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5325 if (MptResetHandlers[ii]) {
5326 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5328 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5330 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5331 ioc->name, ioc->alt_ioc->name, ii));
5332 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5338 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5339 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5344 ioc->alt_ioc->reload_fw = 0;
5346 spin_lock_irqsave(&ioc->diagLock, flags);
5347 ioc->diagPending = 0;
5349 ioc->alt_ioc->diagPending = 0;
5350 spin_unlock_irqrestore(&ioc->diagLock, flags);
5352 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5357 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5359 EventDescriptionStr(u8 event, u32 evData0)
5364 case MPI_EVENT_NONE:
5367 case MPI_EVENT_LOG_DATA:
5370 case MPI_EVENT_STATE_CHANGE:
5371 ds = "State Change";
5373 case MPI_EVENT_UNIT_ATTENTION:
5374 ds = "Unit Attention";
5376 case MPI_EVENT_IOC_BUS_RESET:
5377 ds = "IOC Bus Reset";
5379 case MPI_EVENT_EXT_BUS_RESET:
5380 ds = "External Bus Reset";
5382 case MPI_EVENT_RESCAN:
5383 ds = "Bus Rescan Event";
5384 /* Ok, do we need to do anything here? As far as
5385 I can tell, this is when a new device gets added
5388 case MPI_EVENT_LINK_STATUS_CHANGE:
5389 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5390 ds = "Link Status(FAILURE) Change";
5392 ds = "Link Status(ACTIVE) Change";
5394 case MPI_EVENT_LOOP_STATE_CHANGE:
5395 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5396 ds = "Loop State(LIP) Change";
5397 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5398 ds = "Loop State(LPE) Change"; /* ??? */
5400 ds = "Loop State(LPB) Change"; /* ??? */
5402 case MPI_EVENT_LOGOUT:
5405 case MPI_EVENT_EVENT_CHANGE:
5407 ds = "Events(ON) Change";
5409 ds = "Events(OFF) Change";
5411 case MPI_EVENT_INTEGRATED_RAID:
5412 ds = "Integrated Raid";
5415 * MPT base "custom" events may be added here...
5424 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5426 * ProcessEventNotification - Route a received EventNotificationReply to
5427 * all currently regeistered event handlers.
5428 * @ioc: Pointer to MPT_ADAPTER structure
5429 * @pEventReply: Pointer to EventNotification reply frame
5430 * @evHandlers: Pointer to integer, number of event handlers
5432 * Returns sum of event handlers return values.
5435 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5447 * Do platform normalization of values
5449 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5450 // evCtx = le32_to_cpu(pEventReply->EventContext);
5451 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5453 evData0 = le32_to_cpu(pEventReply->Data[0]);
5456 evStr = EventDescriptionStr(event, evData0);
5457 devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5462 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5463 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5464 for (ii = 0; ii < evDataLen; ii++)
5465 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5470 * Do general / base driver event processing
5473 case MPI_EVENT_NONE: /* 00 */
5474 case MPI_EVENT_LOG_DATA: /* 01 */
5475 case MPI_EVENT_STATE_CHANGE: /* 02 */
5476 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
5477 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
5478 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
5479 case MPI_EVENT_RESCAN: /* 06 */
5480 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
5481 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
5482 case MPI_EVENT_LOGOUT: /* 09 */
5483 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
5484 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */
5487 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5489 u8 evState = evData0 & 0xFF;
5491 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5493 /* Update EventState field in cached IocFacts */
5494 if (ioc->facts.Function) {
5495 ioc->facts.EventState = evState;
5502 * Should this event be logged? Events are written sequentially.
5503 * When buffer is full, start again at the top.
5505 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5508 idx = ioc->eventContext % ioc->eventLogSize;
5510 ioc->events[idx].event = event;
5511 ioc->events[idx].eventContext = ioc->eventContext;
5513 for (ii = 0; ii < 2; ii++) {
5515 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5517 ioc->events[idx].data[ii] = 0;
5520 ioc->eventContext++;
5525 * Call each currently registered protocol event handler.
5527 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5528 if (MptEvHandlers[ii]) {
5529 devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
5531 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
5535 /* FIXME? Examine results here? */
5538 * If needed, send (a single) EventAck.
5540 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
5541 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
5542 devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
5547 *evHandlers = handlers;
5551 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5553 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
5554 * @ioc: Pointer to MPT_ADAPTER structure
5555 * @log_info: U32 LogInfo reply word from the IOC
5557 * Refer to lsi/fc_log.h.
5560 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
5562 static char *subcl_str[8] = {
5563 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
5564 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
5566 u8 subcl = (log_info >> 24) & 0x7;
5568 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
5569 ioc->name, log_info, subcl_str[subcl]);
5572 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5574 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
5575 * @ioc: Pointer to MPT_ADAPTER structure
5576 * @mr: Pointer to MPT reply frame
5577 * @log_info: U32 LogInfo word from the IOC
5579 * Refer to lsi/sp_log.h.
5582 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
5584 u32 info = log_info & 0x00FF0000;
5585 char *desc = "unknown";
5589 desc = "bug! MID not found";
5590 if (ioc->reload_fw == 0)
5595 desc = "Parity Error";
5599 desc = "ASYNC Outbound Overrun";
5603 desc = "SYNC Offset Error";
5611 desc = "Msg In Overflow";
5619 desc = "Outbound DMA Overrun";
5623 desc = "Task Management";
5627 desc = "Device Problem";
5631 desc = "Invalid Phase Change";
5635 desc = "Untagged Table Size";
5640 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
5643 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5645 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
5646 * @ioc: Pointer to MPT_ADAPTER structure
5647 * @ioc_status: U32 IOCStatus word from IOC
5648 * @mf: Pointer to MPT request frame
5650 * Refer to lsi/mpi.h.
5653 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
5655 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
5659 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
5660 desc = "Invalid Function";
5663 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
5667 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
5668 desc = "Invalid SGL";
5671 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
5672 desc = "Internal Error";
5675 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
5679 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
5680 desc = "Insufficient Resources";
5683 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
5684 desc = "Invalid Field";
5687 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
5688 desc = "Invalid State";
5691 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
5692 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
5693 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
5694 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
5695 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
5696 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
5697 /* No message for Config IOCStatus values */
5700 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5701 /* No message for recovered error
5702 desc = "SCSI Recovered Error";
5706 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
5707 desc = "SCSI Invalid Bus";
5710 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
5711 desc = "SCSI Invalid TargetID";
5714 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5716 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
5717 U8 cdb = pScsiReq->CDB[0];
5718 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
5719 desc = "SCSI Device Not There";
5724 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
5725 desc = "SCSI Data Overrun";
5728 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5729 /* This error is checked in scsi_io_done(). Skip.
5730 desc = "SCSI Data Underrun";
5734 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5735 desc = "SCSI I/O Data Error";
5738 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5739 desc = "SCSI Protocol Error";
5742 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5743 desc = "SCSI Task Terminated";
5746 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
5747 desc = "SCSI Residual Mismatch";
5750 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
5751 desc = "SCSI Task Management Failed";
5754 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5755 desc = "SCSI IOC Terminated";
5758 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5759 desc = "SCSI Ext Terminated";
5767 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
5770 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5771 EXPORT_SYMBOL(mpt_attach);
5772 EXPORT_SYMBOL(mpt_detach);
5774 EXPORT_SYMBOL(mpt_resume);
5775 EXPORT_SYMBOL(mpt_suspend);
5777 EXPORT_SYMBOL(ioc_list);
5778 EXPORT_SYMBOL(mpt_proc_root_dir);
5779 EXPORT_SYMBOL(mpt_register);
5780 EXPORT_SYMBOL(mpt_deregister);
5781 EXPORT_SYMBOL(mpt_event_register);
5782 EXPORT_SYMBOL(mpt_event_deregister);
5783 EXPORT_SYMBOL(mpt_reset_register);
5784 EXPORT_SYMBOL(mpt_reset_deregister);
5785 EXPORT_SYMBOL(mpt_device_driver_register);
5786 EXPORT_SYMBOL(mpt_device_driver_deregister);
5787 EXPORT_SYMBOL(mpt_get_msg_frame);
5788 EXPORT_SYMBOL(mpt_put_msg_frame);
5789 EXPORT_SYMBOL(mpt_free_msg_frame);
5790 EXPORT_SYMBOL(mpt_add_sge);
5791 EXPORT_SYMBOL(mpt_send_handshake_request);
5792 EXPORT_SYMBOL(mpt_verify_adapter);
5793 EXPORT_SYMBOL(mpt_GetIocState);
5794 EXPORT_SYMBOL(mpt_print_ioc_summary);
5795 EXPORT_SYMBOL(mpt_lan_index);
5796 EXPORT_SYMBOL(mpt_stm_index);
5797 EXPORT_SYMBOL(mpt_HardResetHandler);
5798 EXPORT_SYMBOL(mpt_config);
5799 EXPORT_SYMBOL(mpt_toolbox);
5800 EXPORT_SYMBOL(mpt_findImVolumes);
5801 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
5802 EXPORT_SYMBOL(mpt_alloc_fw_memory);
5803 EXPORT_SYMBOL(mpt_free_fw_memory);
5806 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5808 * fusion_init - Fusion MPT base driver initialization routine.
5810 * Returns 0 for success, non-zero for failure.
5817 show_mptmod_ver(my_NAME, my_VERSION);
5818 printk(KERN_INFO COPYRIGHT "\n");
5820 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
5821 MptCallbacks[i] = NULL;
5822 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
5823 MptEvHandlers[i] = NULL;
5824 MptResetHandlers[i] = NULL;
5827 /* Register ourselves (mptbase) in order to facilitate
5828 * EventNotification handling.
5830 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
5832 /* Register for hard reset handling callbacks.
5834 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
5835 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
5840 #ifdef CONFIG_PROC_FS
5841 (void) procmpt_create();
5846 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5848 * fusion_exit - Perform driver unload cleanup.
5850 * This routine frees all resources associated with each MPT adapter
5851 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
5857 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
5859 mpt_reset_deregister(mpt_base_index);
5861 #ifdef CONFIG_PROC_FS
5866 module_init(fusion_init);
5867 module_exit(fusion_exit);