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/kernel.h>
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/types.h>
55 #include <linux/pci.h>
56 #include <linux/kdev_t.h>
57 #include <linux/blkdev.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
60 #include <linux/dma-mapping.h>
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT base driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
71 #define MYNAM "mptbase"
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
80 static int mpt_msi_enable;
81 module_param(mpt_msi_enable, int, 0);
82 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
85 static int mfcounter = 0;
86 #define PRINT_MF_COUNT 20000
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
93 int mpt_lan_index = -1;
94 int mpt_stm_index = -1;
96 struct proc_dir_entry *mpt_proc_root_dir;
98 #define WHOINIT_UNKNOWN 0xAA
100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
104 /* Adapter link list */
106 /* Callback lookup table */
107 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
108 /* Protocol driver class lookup table */
109 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
110 /* Event handler lookup table */
111 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Reset handler lookup table */
113 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
114 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
116 static int mpt_base_index = -1;
117 static int last_drv_idx = -1;
119 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
125 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
126 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
127 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
128 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
130 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
131 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
132 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
133 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
135 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
136 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
137 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
138 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
139 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
140 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
141 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
142 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
143 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
144 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
145 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
146 static int PrimeIocFifos(MPT_ADAPTER *ioc);
147 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
148 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150 static int GetLanConfigPages(MPT_ADAPTER *ioc);
151 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
152 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
153 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
154 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
155 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
156 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
157 static void mpt_timer_expired(unsigned long data);
158 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
159 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
160 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
161 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
163 #ifdef CONFIG_PROC_FS
164 static int procmpt_summary_read(char *buf, char **start, off_t offset,
165 int request, int *eof, void *data);
166 static int procmpt_version_read(char *buf, char **start, off_t offset,
167 int request, int *eof, void *data);
168 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
171 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
173 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
174 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
175 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
176 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
177 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
178 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
179 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
181 /* module entry point */
182 static int __init fusion_init (void);
183 static void __exit fusion_exit (void);
185 #define CHIPREG_READ32(addr) readl_relaxed(addr)
186 #define CHIPREG_READ32_dmasync(addr) readl(addr)
187 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
188 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
189 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
192 pci_disable_io_access(struct pci_dev *pdev)
196 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
198 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
202 pci_enable_io_access(struct pci_dev *pdev)
206 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
208 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
212 * Process turbo (context) reply...
215 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
217 MPT_FRAME_HDR *mf = NULL;
218 MPT_FRAME_HDR *mr = NULL;
222 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
225 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
226 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
227 req_idx = pa & 0x0000FFFF;
228 cb_idx = (pa & 0x00FF0000) >> 16;
229 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
231 case MPI_CONTEXT_REPLY_TYPE_LAN:
232 cb_idx = mpt_lan_index;
234 * Blind set of mf to NULL here was fatal
235 * after lan_reply says "freeme"
236 * Fix sort of combined with an optimization here;
237 * added explicit check for case where lan_reply
238 * was just returning 1 and doing nothing else.
239 * For this case skip the callback, but set up
240 * proper mf value first here:-)
242 if ((pa & 0x58000000) == 0x58000000) {
243 req_idx = pa & 0x0000FFFF;
244 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
245 mpt_free_msg_frame(ioc, mf);
250 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
252 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
253 cb_idx = mpt_stm_index;
254 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
261 /* Check for (valid) IO callback! */
262 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
263 MptCallbacks[cb_idx] == NULL) {
264 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
265 __FUNCTION__, ioc->name, cb_idx);
269 if (MptCallbacks[cb_idx](ioc, mf, mr))
270 mpt_free_msg_frame(ioc, mf);
276 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
287 /* non-TURBO reply! Hmmm, something may be up...
288 * Newest turbo reply mechanism; get address
289 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
292 /* Map DMA address of reply header to cpu address.
293 * pa is 32 bits - but the dma address may be 32 or 64 bits
294 * get offset based only only the low addresses
297 reply_dma_low = (pa <<= 1);
298 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
299 (reply_dma_low - ioc->reply_frames_low_dma));
301 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
302 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
303 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
305 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
306 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
307 DBG_DUMP_REPLY_FRAME(mr)
309 /* Check/log IOC log info
311 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
312 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
313 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
314 if (ioc->bus_type == FC)
315 mpt_fc_log_info(ioc, log_info);
316 else if (ioc->bus_type == SPI)
317 mpt_spi_log_info(ioc, log_info);
318 else if (ioc->bus_type == SAS)
319 mpt_sas_log_info(ioc, log_info);
321 if (ioc_stat & MPI_IOCSTATUS_MASK) {
322 if (ioc->bus_type == SPI &&
323 cb_idx != mpt_stm_index &&
324 cb_idx != mpt_lan_index)
325 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
329 /* Check for (valid) IO callback! */
330 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
331 MptCallbacks[cb_idx] == NULL) {
332 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
333 __FUNCTION__, ioc->name, cb_idx);
338 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
341 /* Flush (non-TURBO) reply with a WRITE! */
342 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
345 mpt_free_msg_frame(ioc, mf);
349 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
351 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
352 * @irq: irq number (not used)
353 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
354 * @r: pt_regs pointer (not used)
356 * This routine is registered via the request_irq() kernel API call,
357 * and handles all interrupts generated from a specific MPT adapter
358 * (also referred to as a IO Controller or IOC).
359 * This routine must clear the interrupt from the adapter and does
360 * so by reading the reply FIFO. Multiple replies may be processed
361 * per single call to this routine.
363 * This routine handles register-level access of the adapter but
364 * dispatches (calls) a protocol-specific callback routine to handle
365 * the protocol-specific details of the MPT request completion.
368 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
370 MPT_ADAPTER *ioc = bus_id;
371 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
373 if (pa == 0xFFFFFFFF)
377 * Drain the reply FIFO!
380 if (pa & MPI_ADDRESS_REPLY_A_BIT)
383 mpt_turbo_reply(ioc, pa);
384 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
385 } while (pa != 0xFFFFFFFF);
390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
392 * mpt_base_reply - MPT base driver's callback routine; all base driver
393 * "internal" request/reply processing is routed here.
394 * Currently used for EventNotification and EventAck handling.
395 * @ioc: Pointer to MPT_ADAPTER structure
396 * @mf: Pointer to original MPT request frame
397 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
399 * Returns 1 indicating original alloc'd request frame ptr
400 * should be freed, or 0 if it shouldn't.
403 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
408 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
410 #if defined(MPT_DEBUG_MSG_FRAME)
411 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
412 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
413 DBG_DUMP_REQUEST_FRAME_HDR(mf)
417 func = reply->u.hdr.Function;
418 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
421 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
422 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
426 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
427 if (results != evHandlers) {
428 /* CHECKME! Any special handling needed here? */
429 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
430 ioc->name, evHandlers, results));
434 * Hmmm... It seems that EventNotificationReply is an exception
435 * to the rule of one reply per request.
437 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
440 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
441 ioc->name, pEvReply));
444 #ifdef CONFIG_PROC_FS
445 // LogEvent(ioc, pEvReply);
448 } else if (func == MPI_FUNCTION_EVENT_ACK) {
449 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
451 } else if (func == MPI_FUNCTION_CONFIG) {
455 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
456 ioc->name, mf, reply));
458 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
461 /* disable timer and remove from linked list */
462 del_timer(&pCfg->timer);
464 spin_lock_irqsave(&ioc->FreeQlock, flags);
465 list_del(&pCfg->linkage);
466 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
469 * If IOC Status is SUCCESS, save the header
470 * and set the status code to GOOD.
472 pCfg->status = MPT_CONFIG_ERROR;
474 ConfigReply_t *pReply = (ConfigReply_t *)reply;
477 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
478 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
479 status, le32_to_cpu(pReply->IOCLogInfo)));
481 pCfg->status = status;
482 if (status == MPI_IOCSTATUS_SUCCESS) {
483 if ((pReply->Header.PageType &
484 MPI_CONFIG_PAGETYPE_MASK) ==
485 MPI_CONFIG_PAGETYPE_EXTENDED) {
486 pCfg->cfghdr.ehdr->ExtPageLength =
487 le16_to_cpu(pReply->ExtPageLength);
488 pCfg->cfghdr.ehdr->ExtPageType =
491 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
493 /* If this is a regular header, save PageLength. */
494 /* LMP Do this better so not using a reserved field! */
495 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
496 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
497 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
502 * Wake up the original calling thread
507 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
508 /* we should be always getting a reply frame */
509 memcpy(ioc->persist_reply_frame, reply,
510 min(MPT_DEFAULT_FRAME_SIZE,
511 4*reply->u.reply.MsgLength));
512 del_timer(&ioc->persist_timer);
513 ioc->persist_wait_done = 1;
516 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
521 * Conditionally tell caller to free the original
522 * EventNotification/EventAck/unexpected request frame!
527 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
529 * mpt_register - Register protocol-specific main callback handler.
530 * @cbfunc: callback function pointer
531 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
533 * This routine is called by a protocol-specific driver (SCSI host,
534 * LAN, SCSI target) to register it's reply callback routine. Each
535 * protocol-specific driver must do this before it will be able to
536 * use any IOC resources, such as obtaining request frames.
538 * NOTES: The SCSI protocol driver currently calls this routine thrice
539 * in order to register separate callbacks; one for "normal" SCSI IO;
540 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
542 * Returns a positive integer valued "handle" in the
543 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
544 * Any non-positive return value (including zero!) should be considered
545 * an error by the caller.
548 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
555 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
556 * (slot/handle 0 is reserved!)
558 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
559 if (MptCallbacks[i] == NULL) {
560 MptCallbacks[i] = cbfunc;
561 MptDriverClass[i] = dclass;
562 MptEvHandlers[i] = NULL;
571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
573 * mpt_deregister - Deregister a protocol drivers resources.
574 * @cb_idx: previously registered callback handle
576 * Each protocol-specific driver should call this routine when it's
577 * module is unloaded.
580 mpt_deregister(int cb_idx)
582 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
583 MptCallbacks[cb_idx] = NULL;
584 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
585 MptEvHandlers[cb_idx] = NULL;
591 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
593 * mpt_event_register - Register protocol-specific event callback
595 * @cb_idx: previously registered (via mpt_register) callback handle
596 * @ev_cbfunc: callback function
598 * This routine can be called by one or more protocol-specific drivers
599 * if/when they choose to be notified of MPT events.
601 * Returns 0 for success.
604 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
606 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
609 MptEvHandlers[cb_idx] = ev_cbfunc;
613 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
615 * mpt_event_deregister - Deregister protocol-specific event callback
617 * @cb_idx: previously registered callback handle
619 * Each protocol-specific driver should call this routine
620 * when it does not (or can no longer) handle events,
621 * or when it's module is unloaded.
624 mpt_event_deregister(int cb_idx)
626 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
629 MptEvHandlers[cb_idx] = NULL;
632 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
634 * mpt_reset_register - Register protocol-specific IOC reset handler.
635 * @cb_idx: previously registered (via mpt_register) callback handle
636 * @reset_func: reset function
638 * This routine can be called by one or more protocol-specific drivers
639 * if/when they choose to be notified of IOC resets.
641 * Returns 0 for success.
644 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
646 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
649 MptResetHandlers[cb_idx] = reset_func;
653 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
655 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
656 * @cb_idx: previously registered callback handle
658 * Each protocol-specific driver should call this routine
659 * when it does not (or can no longer) handle IOC reset handling,
660 * or when it's module is unloaded.
663 mpt_reset_deregister(int cb_idx)
665 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
668 MptResetHandlers[cb_idx] = NULL;
671 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
673 * mpt_device_driver_register - Register device driver hooks
676 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
679 const struct pci_device_id *id;
681 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
684 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
686 /* call per pci device probe entry point */
687 list_for_each_entry(ioc, &ioc_list, list) {
688 id = ioc->pcidev->driver ?
689 ioc->pcidev->driver->id_table : NULL;
690 if (dd_cbfunc->probe)
691 dd_cbfunc->probe(ioc->pcidev, id);
697 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
699 * mpt_device_driver_deregister - DeRegister device driver hooks
702 mpt_device_driver_deregister(int cb_idx)
704 struct mpt_pci_driver *dd_cbfunc;
707 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
710 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
712 list_for_each_entry(ioc, &ioc_list, list) {
713 if (dd_cbfunc->remove)
714 dd_cbfunc->remove(ioc->pcidev);
717 MptDeviceDriverHandlers[cb_idx] = NULL;
721 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
723 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
724 * allocated per MPT adapter.
725 * @handle: Handle of registered MPT protocol driver
726 * @ioc: Pointer to MPT adapter structure
728 * Returns pointer to a MPT request frame or %NULL if none are available
729 * or IOC is not active.
732 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
736 u16 req_idx; /* Request index */
738 /* validate handle and ioc identifier */
742 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
745 /* If interrupts are not attached, do not return a request frame */
749 spin_lock_irqsave(&ioc->FreeQlock, flags);
750 if (!list_empty(&ioc->FreeQ)) {
753 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
754 u.frame.linkage.list);
755 list_del(&mf->u.frame.linkage.list);
756 mf->u.frame.linkage.arg1 = 0;
757 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
758 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
760 req_idx = req_offset / ioc->req_sz;
761 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
762 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
763 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
770 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
774 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
776 if (mfcounter == PRINT_MF_COUNT)
777 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
780 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
781 ioc->name, handle, ioc->id, mf));
785 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
787 * mpt_put_msg_frame - Send a protocol specific MPT request frame
789 * @handle: Handle of registered MPT protocol driver
790 * @ioc: Pointer to MPT adapter structure
791 * @mf: Pointer to MPT request frame
793 * This routine posts a MPT request frame to the request post FIFO of a
794 * specific MPT adapter.
797 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
801 u16 req_idx; /* Request index */
803 /* ensure values are reset properly! */
804 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
805 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
807 req_idx = req_offset / ioc->req_sz;
808 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
809 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
811 #ifdef MPT_DEBUG_MSG_FRAME
813 u32 *m = mf->u.frame.hwhdr.__hdr;
816 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
818 n = ioc->req_sz/4 - 1;
821 for (ii=0; ii<=n; ii++) {
822 if (ii && ((ii%8)==0))
823 printk("\n" KERN_INFO " ");
824 printk(" %08x", le32_to_cpu(m[ii]));
830 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
831 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]));
832 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
835 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
837 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
838 * @handle: Handle of registered MPT protocol driver
839 * @ioc: Pointer to MPT adapter structure
840 * @mf: Pointer to MPT request frame
842 * This routine places a MPT request frame back on the MPT adapter's
846 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
850 /* Put Request back on FreeQ! */
851 spin_lock_irqsave(&ioc->FreeQlock, flags);
852 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
853 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
857 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
860 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
862 * mpt_add_sge - Place a simple SGE at address pAddr.
863 * @pAddr: virtual address for SGE
864 * @flagslength: SGE flags and data transfer length
865 * @dma_addr: Physical address
867 * This routine places a MPT request frame back on the MPT adapter's
871 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
873 if (sizeof(dma_addr_t) == sizeof(u64)) {
874 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
875 u32 tmp = dma_addr & 0xFFFFFFFF;
877 pSge->FlagsLength = cpu_to_le32(flagslength);
878 pSge->Address.Low = cpu_to_le32(tmp);
879 tmp = (u32) ((u64)dma_addr >> 32);
880 pSge->Address.High = cpu_to_le32(tmp);
883 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
884 pSge->FlagsLength = cpu_to_le32(flagslength);
885 pSge->Address = cpu_to_le32(dma_addr);
889 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
891 * mpt_send_handshake_request - Send MPT request via doorbell
893 * @handle: Handle of registered MPT protocol driver
894 * @ioc: Pointer to MPT adapter structure
895 * @reqBytes: Size of the request in bytes
896 * @req: Pointer to MPT request frame
897 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
899 * This routine is used exclusively to send MptScsiTaskMgmt
900 * requests since they are required to be sent via doorbell handshake.
902 * NOTE: It is the callers responsibility to byte-swap fields in the
903 * request which are greater than 1 byte in size.
905 * Returns 0 for success, non-zero for failure.
908 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
914 /* State is known to be good upon entering
915 * this function so issue the bus reset
920 * Emulate what mpt_put_msg_frame() does /wrt to sanity
921 * setting cb_idx/req_idx. But ONLY if this request
922 * is in proper (pre-alloc'd) request buffer range...
924 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
925 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
926 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
927 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
928 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
931 /* Make sure there are no doorbells */
932 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
934 CHIPREG_WRITE32(&ioc->chip->Doorbell,
935 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
936 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
938 /* Wait for IOC doorbell int */
939 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
943 /* Read doorbell and check for active bit */
944 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
947 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
950 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
952 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
956 /* Send request via doorbell handshake */
957 req_as_bytes = (u8 *) req;
958 for (ii = 0; ii < reqBytes/4; ii++) {
961 word = ((req_as_bytes[(ii*4) + 0] << 0) |
962 (req_as_bytes[(ii*4) + 1] << 8) |
963 (req_as_bytes[(ii*4) + 2] << 16) |
964 (req_as_bytes[(ii*4) + 3] << 24));
965 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
966 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
972 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
977 /* Make sure there are no doorbells */
978 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
983 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
985 * mpt_host_page_access_control - provides mechanism for the host
986 * driver to control the IOC's Host Page Buffer access.
987 * @ioc: Pointer to MPT adapter structure
988 * @access_control_value: define bits below
990 * Access Control Value - bits[15:12]
992 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
993 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
994 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
996 * Returns 0 for success, non-zero for failure.
1000 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1004 /* return if in use */
1005 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1006 & MPI_DOORBELL_ACTIVE)
1009 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1011 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1012 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1013 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1014 (access_control_value<<12)));
1016 /* Wait for IOC to clear Doorbell Status bit */
1017 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1025 * mpt_host_page_alloc - allocate system memory for the fw
1026 * If we already allocated memory in past, then resend the same pointer.
1027 * ioc@: Pointer to pointer to IOC adapter
1028 * ioc_init@: Pointer to ioc init config page
1030 * Returns 0 for success, non-zero for failure.
1033 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1037 u32 host_page_buffer_sz=0;
1039 if(!ioc->HostPageBuffer) {
1041 host_page_buffer_sz =
1042 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1044 if(!host_page_buffer_sz)
1045 return 0; /* fw doesn't need any host buffers */
1047 /* spin till we get enough memory */
1048 while(host_page_buffer_sz > 0) {
1050 if((ioc->HostPageBuffer = pci_alloc_consistent(
1052 host_page_buffer_sz,
1053 &ioc->HostPageBuffer_dma)) != NULL) {
1055 dinitprintk((MYIOC_s_INFO_FMT
1056 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1058 ioc->HostPageBuffer,
1059 ioc->HostPageBuffer_dma,
1060 host_page_buffer_sz));
1061 ioc->alloc_total += host_page_buffer_sz;
1062 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1066 host_page_buffer_sz -= (4*1024);
1070 if(!ioc->HostPageBuffer) {
1071 printk(MYIOC_s_ERR_FMT
1072 "Failed to alloc memory for host_page_buffer!\n",
1077 psge = (char *)&ioc_init->HostPageBufferSGE;
1078 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1079 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1080 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1081 MPI_SGE_FLAGS_HOST_TO_IOC |
1082 MPI_SGE_FLAGS_END_OF_BUFFER;
1083 if (sizeof(dma_addr_t) == sizeof(u64)) {
1084 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1086 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1087 flags_length |= ioc->HostPageBuffer_sz;
1088 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1089 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1094 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1097 * the associated MPT adapter structure.
1098 * @iocid: IOC unique identifier (integer)
1099 * @iocpp: Pointer to pointer to IOC adapter
1101 * Returns iocid and sets iocpp.
1104 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1108 list_for_each_entry(ioc,&ioc_list,list) {
1109 if (ioc->id == iocid) {
1119 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1121 * mpt_attach - Install a PCI intelligent MPT adapter.
1122 * @pdev: Pointer to pci_dev structure
1124 * This routine performs all the steps necessary to bring the IOC of
1125 * a MPT adapter to a OPERATIONAL state. This includes registering
1126 * memory regions, registering the interrupt, and allocating request
1127 * and reply memory pools.
1129 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1132 * Returns 0 for success, non-zero for failure.
1134 * TODO: Add support for polled controllers
1137 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1141 unsigned long mem_phys;
1149 static int mpt_ids = 0;
1150 #ifdef CONFIG_PROC_FS
1151 struct proc_dir_entry *dent, *ent;
1154 if (pci_enable_device(pdev))
1157 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1159 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1160 dprintk((KERN_INFO MYNAM
1161 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1162 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1163 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1167 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1168 dprintk((KERN_INFO MYNAM
1169 ": Using 64 bit consistent mask\n"));
1171 dprintk((KERN_INFO MYNAM
1172 ": Not using 64 bit consistent mask\n"));
1174 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1176 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1179 ioc->alloc_total = sizeof(MPT_ADAPTER);
1180 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1181 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1184 ioc->diagPending = 0;
1185 spin_lock_init(&ioc->diagLock);
1186 spin_lock_init(&ioc->initializing_hba_lock);
1188 /* Initialize the event logging.
1190 ioc->eventTypes = 0; /* None */
1191 ioc->eventContext = 0;
1192 ioc->eventLogSize = 0;
1199 ioc->cached_fw = NULL;
1201 /* Initilize SCSI Config Data structure
1203 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1205 /* Initialize the running configQ head.
1207 INIT_LIST_HEAD(&ioc->configQ);
1209 /* Initialize the fc rport list head.
1211 INIT_LIST_HEAD(&ioc->fc_rports);
1213 /* Find lookup slot. */
1214 INIT_LIST_HEAD(&ioc->list);
1215 ioc->id = mpt_ids++;
1217 mem_phys = msize = 0;
1219 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1220 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1223 /* Get I/O space! */
1224 port = pci_resource_start(pdev, ii);
1225 psize = pci_resource_len(pdev,ii);
1230 mem_phys = pci_resource_start(pdev, ii);
1231 msize = pci_resource_len(pdev,ii);
1234 ioc->mem_size = msize;
1237 /* Get logical ptr for PciMem0 space */
1238 /*mem = ioremap(mem_phys, msize);*/
1239 mem = ioremap(mem_phys, msize);
1241 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1246 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1248 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1249 &ioc->facts, &ioc->pfacts[0]));
1251 ioc->mem_phys = mem_phys;
1252 ioc->chip = (SYSIF_REGS __iomem *)mem;
1254 /* Save Port IO values in case we need to do downloadboot */
1256 u8 *pmem = (u8*)port;
1257 ioc->pio_mem_phys = port;
1258 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1261 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1262 ioc->prod_name = "LSIFC909";
1265 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1266 ioc->prod_name = "LSIFC929";
1269 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1270 ioc->prod_name = "LSIFC919";
1273 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1274 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1276 if (revision < XL_929) {
1277 ioc->prod_name = "LSIFC929X";
1278 /* 929X Chip Fix. Set Split transactions level
1279 * for PCIX. Set MOST bits to zero.
1281 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1283 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1285 ioc->prod_name = "LSIFC929XL";
1286 /* 929XL Chip Fix. Set MMRBC to 0x08.
1288 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1290 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1293 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1294 ioc->prod_name = "LSIFC919X";
1296 /* 919X Chip Fix. Set Split transactions level
1297 * for PCIX. Set MOST bits to zero.
1299 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1301 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1303 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1304 ioc->prod_name = "LSIFC939X";
1306 ioc->errata_flag_1064 = 1;
1308 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1309 ioc->prod_name = "LSIFC949X";
1311 ioc->errata_flag_1064 = 1;
1313 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1314 ioc->prod_name = "LSIFC949E";
1317 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1318 ioc->prod_name = "LSI53C1030";
1319 ioc->bus_type = SPI;
1320 /* 1030 Chip Fix. Disable Split transactions
1321 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1323 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1324 if (revision < C0_1030) {
1325 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1327 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1330 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1331 ioc->prod_name = "LSI53C1035";
1332 ioc->bus_type = SPI;
1334 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1335 ioc->prod_name = "LSISAS1064";
1336 ioc->bus_type = SAS;
1337 ioc->errata_flag_1064 = 1;
1339 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1340 ioc->prod_name = "LSISAS1068";
1341 ioc->bus_type = SAS;
1342 ioc->errata_flag_1064 = 1;
1344 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1345 ioc->prod_name = "LSISAS1064E";
1346 ioc->bus_type = SAS;
1348 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1349 ioc->prod_name = "LSISAS1068E";
1350 ioc->bus_type = SAS;
1352 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
1353 ioc->prod_name = "LSISAS1078";
1354 ioc->bus_type = SAS;
1357 if (ioc->errata_flag_1064)
1358 pci_disable_io_access(pdev);
1360 sprintf(ioc->name, "ioc%d", ioc->id);
1362 spin_lock_init(&ioc->FreeQlock);
1365 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1367 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1369 /* Set lookup ptr. */
1370 list_add_tail(&ioc->list, &ioc_list);
1372 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1374 mpt_detect_bound_ports(ioc, pdev);
1376 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1378 printk(KERN_WARNING MYNAM
1379 ": WARNING - %s did not initialize properly! (%d)\n",
1381 list_del(&ioc->list);
1383 ioc->alt_ioc->alt_ioc = NULL;
1386 pci_set_drvdata(pdev, NULL);
1390 /* call per device driver probe entry point */
1391 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1392 if(MptDeviceDriverHandlers[ii] &&
1393 MptDeviceDriverHandlers[ii]->probe) {
1394 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1398 #ifdef CONFIG_PROC_FS
1400 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1402 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1404 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1406 ent->read_proc = procmpt_iocinfo_read;
1409 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1411 ent->read_proc = procmpt_summary_read;
1420 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1422 * mpt_detach - Remove a PCI intelligent MPT adapter.
1423 * @pdev: Pointer to pci_dev structure
1428 mpt_detach(struct pci_dev *pdev)
1430 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1434 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1435 remove_proc_entry(pname, NULL);
1436 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1437 remove_proc_entry(pname, NULL);
1438 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1439 remove_proc_entry(pname, NULL);
1441 /* call per device driver remove entry point */
1442 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1443 if(MptDeviceDriverHandlers[ii] &&
1444 MptDeviceDriverHandlers[ii]->remove) {
1445 MptDeviceDriverHandlers[ii]->remove(pdev);
1449 /* Disable interrupts! */
1450 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1453 synchronize_irq(pdev->irq);
1455 /* Clear any lingering interrupt */
1456 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1458 CHIPREG_READ32(&ioc->chip->IntStatus);
1460 mpt_adapter_dispose(ioc);
1462 pci_set_drvdata(pdev, NULL);
1465 /**************************************************************************
1469 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1471 * mpt_suspend - Fusion MPT base driver suspend routine.
1476 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1479 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1481 device_state=pci_choose_state(pdev, state);
1483 printk(MYIOC_s_INFO_FMT
1484 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1485 ioc->name, pdev, pci_name(pdev), device_state);
1487 pci_save_state(pdev);
1489 /* put ioc into READY_STATE */
1490 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1491 printk(MYIOC_s_ERR_FMT
1492 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1495 /* disable interrupts */
1496 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1499 /* Clear any lingering interrupt */
1500 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1502 pci_disable_device(pdev);
1503 pci_set_power_state(pdev, device_state);
1508 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1510 * mpt_resume - Fusion MPT base driver resume routine.
1515 mpt_resume(struct pci_dev *pdev)
1517 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1518 u32 device_state = pdev->current_state;
1521 printk(MYIOC_s_INFO_FMT
1522 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1523 ioc->name, pdev, pci_name(pdev), device_state);
1525 pci_set_power_state(pdev, 0);
1526 pci_restore_state(pdev);
1527 pci_enable_device(pdev);
1529 /* enable interrupts */
1530 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1533 printk(MYIOC_s_INFO_FMT
1534 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1536 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1537 CHIPREG_READ32(&ioc->chip->Doorbell));
1539 /* bring ioc to operational state */
1540 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1541 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1542 printk(MYIOC_s_INFO_FMT
1543 "pci-resume: Cannot recover, error:[%x]\n",
1544 ioc->name, recovery_state);
1546 printk(MYIOC_s_INFO_FMT
1547 "pci-resume: success\n", ioc->name);
1555 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1557 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1558 ioc->bus_type != SPI) ||
1559 (MptDriverClass[index] == MPTFC_DRIVER &&
1560 ioc->bus_type != FC) ||
1561 (MptDriverClass[index] == MPTSAS_DRIVER &&
1562 ioc->bus_type != SAS))
1563 /* make sure we only call the relevant reset handler
1566 return (MptResetHandlers[index])(ioc, reset_phase);
1569 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1571 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1572 * @ioc: Pointer to MPT adapter structure
1573 * @reason: Event word / reason
1574 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1576 * This routine performs all the steps necessary to bring the IOC
1577 * to a OPERATIONAL state.
1579 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1584 * -1 if failed to get board READY
1585 * -2 if READY but IOCFacts Failed
1586 * -3 if READY but PrimeIOCFifos Failed
1587 * -4 if READY but IOCInit Failed
1590 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1592 int hard_reset_done = 0;
1593 int alt_ioc_ready = 0;
1599 int reset_alt_ioc_active = 0;
1600 int irq_allocated = 0;
1602 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1603 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1605 /* Disable reply interrupts (also blocks FreeQ) */
1606 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1610 if (ioc->alt_ioc->active)
1611 reset_alt_ioc_active = 1;
1613 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1614 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1615 ioc->alt_ioc->active = 0;
1619 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1622 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1623 if (hard_reset_done == -4) {
1624 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1627 if (reset_alt_ioc_active && ioc->alt_ioc) {
1628 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1629 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1630 ioc->alt_ioc->name));
1631 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1632 ioc->alt_ioc->active = 1;
1636 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1642 /* hard_reset_done = 0 if a soft reset was performed
1643 * and 1 if a hard reset was performed.
1645 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1646 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1649 printk(KERN_WARNING MYNAM
1650 ": alt-%s: Not ready WARNING!\n",
1651 ioc->alt_ioc->name);
1654 for (ii=0; ii<5; ii++) {
1655 /* Get IOC facts! Allow 5 retries */
1656 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1662 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1664 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1665 MptDisplayIocCapabilities(ioc);
1668 if (alt_ioc_ready) {
1669 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1670 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1671 /* Retry - alt IOC was initialized once
1673 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1676 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1678 reset_alt_ioc_active = 0;
1679 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1680 MptDisplayIocCapabilities(ioc->alt_ioc);
1685 * Device is reset now. It must have de-asserted the interrupt line
1686 * (if it was asserted) and it should be safe to register for the
1689 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1691 if (ioc->pcidev->irq) {
1692 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1693 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1695 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1696 IRQF_SHARED, ioc->name, ioc);
1698 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1699 "interrupt %d!\n", ioc->name,
1702 pci_disable_msi(ioc->pcidev);
1706 ioc->pci_irq = ioc->pcidev->irq;
1707 pci_set_master(ioc->pcidev); /* ?? */
1708 pci_set_drvdata(ioc->pcidev, ioc);
1709 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1710 "%d\n", ioc->name, ioc->pcidev->irq));
1714 /* Prime reply & request queues!
1715 * (mucho alloc's) Must be done prior to
1716 * init as upper addresses are needed for init.
1717 * If fails, continue with alt-ioc processing
1719 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1722 /* May need to check/upload firmware & data here!
1723 * If fails, continue with alt-ioc processing
1725 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1728 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1729 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1730 ioc->alt_ioc->name, rc);
1732 reset_alt_ioc_active = 0;
1735 if (alt_ioc_ready) {
1736 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1738 reset_alt_ioc_active = 0;
1739 printk(KERN_WARNING MYNAM
1740 ": alt-%s: (%d) init failure WARNING!\n",
1741 ioc->alt_ioc->name, rc);
1745 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1746 if (ioc->upload_fw) {
1747 ddlprintk((MYIOC_s_INFO_FMT
1748 "firmware upload required!\n", ioc->name));
1750 /* Controller is not operational, cannot do upload
1753 rc = mpt_do_upload(ioc, sleepFlag);
1755 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1757 * Maintain only one pointer to FW memory
1758 * so there will not be two attempt to
1759 * downloadboot onboard dual function
1760 * chips (mpt_adapter_disable,
1763 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1764 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1765 ioc->alt_ioc->cached_fw = NULL;
1768 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1776 /* Enable! (reply interrupt) */
1777 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1781 if (reset_alt_ioc_active && ioc->alt_ioc) {
1782 /* (re)Enable alt-IOC! (reply interrupt) */
1783 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1784 ioc->alt_ioc->name));
1785 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1786 ioc->alt_ioc->active = 1;
1789 /* Enable MPT base driver management of EventNotification
1790 * and EventAck handling.
1792 if ((ret == 0) && (!ioc->facts.EventState))
1793 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1795 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1796 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1798 /* Add additional "reason" check before call to GetLanConfigPages
1799 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1800 * recursive scenario; GetLanConfigPages times out, timer expired
1801 * routine calls HardResetHandler, which calls into here again,
1802 * and we try GetLanConfigPages again...
1804 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1805 if (ioc->bus_type == SAS) {
1807 /* clear persistency table */
1808 if(ioc->facts.IOCExceptions &
1809 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1810 ret = mptbase_sas_persist_operation(ioc,
1811 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1818 mpt_findImVolumes(ioc);
1820 } else if (ioc->bus_type == FC) {
1821 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1822 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1824 * Pre-fetch the ports LAN MAC address!
1825 * (LANPage1_t stuff)
1827 (void) GetLanConfigPages(ioc);
1830 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1831 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1832 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1837 /* Get NVRAM and adapter maximums from SPP 0 and 2
1839 mpt_GetScsiPortSettings(ioc, 0);
1841 /* Get version and length of SDP 1
1843 mpt_readScsiDevicePageHeaders(ioc, 0);
1847 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1848 mpt_findImVolumes(ioc);
1850 /* Check, and possibly reset, the coalescing value
1852 mpt_read_ioc_pg_1(ioc);
1854 mpt_read_ioc_pg_4(ioc);
1857 GetIoUnitPage2(ioc);
1861 * Call each currently registered protocol IOC reset handler
1862 * with post-reset indication.
1863 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1864 * MptResetHandlers[] registered yet.
1866 if (hard_reset_done) {
1868 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1869 if ((ret == 0) && MptResetHandlers[ii]) {
1870 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1872 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1876 if (alt_ioc_ready && MptResetHandlers[ii]) {
1877 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1878 ioc->name, ioc->alt_ioc->name, ii));
1879 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1883 /* FIXME? Examine results here? */
1887 if ((ret != 0) && irq_allocated) {
1888 free_irq(ioc->pci_irq, ioc);
1890 pci_disable_msi(ioc->pcidev);
1895 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1897 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1898 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1899 * 929X, 1030 or 1035.
1900 * @ioc: Pointer to MPT adapter structure
1901 * @pdev: Pointer to (struct pci_dev) structure
1903 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1904 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1907 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1909 struct pci_dev *peer=NULL;
1910 unsigned int slot = PCI_SLOT(pdev->devfn);
1911 unsigned int func = PCI_FUNC(pdev->devfn);
1912 MPT_ADAPTER *ioc_srch;
1914 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1915 " searching for devfn match on %x or %x\n",
1916 ioc->name, pci_name(pdev), pdev->bus->number,
1917 pdev->devfn, func-1, func+1));
1919 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1921 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1926 list_for_each_entry(ioc_srch, &ioc_list, list) {
1927 struct pci_dev *_pcidev = ioc_srch->pcidev;
1928 if (_pcidev == peer) {
1929 /* Paranoia checks */
1930 if (ioc->alt_ioc != NULL) {
1931 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1932 ioc->name, ioc->alt_ioc->name);
1934 } else if (ioc_srch->alt_ioc != NULL) {
1935 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1936 ioc_srch->name, ioc_srch->alt_ioc->name);
1939 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1940 ioc->name, ioc_srch->name));
1941 ioc_srch->alt_ioc = ioc;
1942 ioc->alt_ioc = ioc_srch;
1948 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1950 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1951 * @this: Pointer to MPT adapter structure
1954 mpt_adapter_disable(MPT_ADAPTER *ioc)
1959 if (ioc->cached_fw != NULL) {
1960 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1961 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1962 printk(KERN_WARNING MYNAM
1963 ": firmware downloadboot failure (%d)!\n", ret);
1967 /* Disable adapter interrupts! */
1968 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1970 /* Clear any lingering interrupt */
1971 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1973 if (ioc->alloc != NULL) {
1975 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1976 ioc->name, ioc->alloc, ioc->alloc_sz));
1977 pci_free_consistent(ioc->pcidev, sz,
1978 ioc->alloc, ioc->alloc_dma);
1979 ioc->reply_frames = NULL;
1980 ioc->req_frames = NULL;
1982 ioc->alloc_total -= sz;
1985 if (ioc->sense_buf_pool != NULL) {
1986 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1987 pci_free_consistent(ioc->pcidev, sz,
1988 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
1989 ioc->sense_buf_pool = NULL;
1990 ioc->alloc_total -= sz;
1993 if (ioc->events != NULL){
1994 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1997 ioc->alloc_total -= sz;
2000 if (ioc->cached_fw != NULL) {
2001 sz = ioc->facts.FWImageSize;
2002 pci_free_consistent(ioc->pcidev, sz,
2003 ioc->cached_fw, ioc->cached_fw_dma);
2004 ioc->cached_fw = NULL;
2005 ioc->alloc_total -= sz;
2008 kfree(ioc->spi_data.nvram);
2009 kfree(ioc->raid_data.pIocPg3);
2010 ioc->spi_data.nvram = NULL;
2011 ioc->raid_data.pIocPg3 = NULL;
2013 if (ioc->spi_data.pIocPg4 != NULL) {
2014 sz = ioc->spi_data.IocPg4Sz;
2015 pci_free_consistent(ioc->pcidev, sz,
2016 ioc->spi_data.pIocPg4,
2017 ioc->spi_data.IocPg4_dma);
2018 ioc->spi_data.pIocPg4 = NULL;
2019 ioc->alloc_total -= sz;
2022 if (ioc->ReqToChain != NULL) {
2023 kfree(ioc->ReqToChain);
2024 kfree(ioc->RequestNB);
2025 ioc->ReqToChain = NULL;
2028 kfree(ioc->ChainToChain);
2029 ioc->ChainToChain = NULL;
2031 if (ioc->HostPageBuffer != NULL) {
2032 if((ret = mpt_host_page_access_control(ioc,
2033 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2034 printk(KERN_ERR MYNAM
2035 ": %s: host page buffers free failed (%d)!\n",
2038 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2039 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2040 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2041 ioc->HostPageBuffer,
2042 ioc->HostPageBuffer_dma);
2043 ioc->HostPageBuffer = NULL;
2044 ioc->HostPageBuffer_sz = 0;
2045 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2051 * mpt_adapter_dispose - Free all resources associated with a MPT
2053 * @ioc: Pointer to MPT adapter structure
2055 * This routine unregisters h/w resources and frees all alloc'd memory
2056 * associated with a MPT adapter structure.
2059 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2061 int sz_first, sz_last;
2066 sz_first = ioc->alloc_total;
2068 mpt_adapter_disable(ioc);
2070 if (ioc->pci_irq != -1) {
2071 free_irq(ioc->pci_irq, ioc);
2073 pci_disable_msi(ioc->pcidev);
2077 if (ioc->memmap != NULL) {
2078 iounmap(ioc->memmap);
2082 #if defined(CONFIG_MTRR) && 0
2083 if (ioc->mtrr_reg > 0) {
2084 mtrr_del(ioc->mtrr_reg, 0, 0);
2085 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2089 /* Zap the adapter lookup ptr! */
2090 list_del(&ioc->list);
2092 sz_last = ioc->alloc_total;
2093 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2094 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2097 ioc->alt_ioc->alt_ioc = NULL;
2102 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2104 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2105 * @ioc: Pointer to MPT adapter structure
2108 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2112 printk(KERN_INFO "%s: ", ioc->name);
2113 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2114 printk("%s: ", ioc->prod_name+3);
2115 printk("Capabilities={");
2117 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2118 printk("Initiator");
2122 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2123 printk("%sTarget", i ? "," : "");
2127 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2128 printk("%sLAN", i ? "," : "");
2134 * This would probably evoke more questions than it's worth
2136 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2137 printk("%sLogBusAddr", i ? "," : "");
2145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2147 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2148 * @ioc: Pointer to MPT_ADAPTER structure
2149 * @force: Force hard KickStart of IOC
2150 * @sleepFlag: Specifies whether the process can sleep
2153 * 1 - DIAG reset and READY
2154 * 0 - READY initially OR soft reset and READY
2155 * -1 - Any failure on KickStart
2156 * -2 - Msg Unit Reset Failed
2157 * -3 - IO Unit Reset Failed
2158 * -4 - IOC owned by a PEER
2161 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2166 int hard_reset_done = 0;
2171 /* Get current [raw] IOC state */
2172 ioc_state = mpt_GetIocState(ioc, 0);
2173 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2176 * Check to see if IOC got left/stuck in doorbell handshake
2177 * grip of death. If so, hard reset the IOC.
2179 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2181 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2185 /* Is it already READY? */
2186 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2190 * Check to see if IOC is in FAULT state.
2192 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2194 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2196 printk(KERN_WARNING " FAULT code = %04xh\n",
2197 ioc_state & MPI_DOORBELL_DATA_MASK);
2201 * Hmmm... Did it get left operational?
2203 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2204 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2208 * If PCI Peer, exit.
2209 * Else, if no fault conditions are present, issue a MessageUnitReset
2210 * Else, fall through to KickStart case
2212 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2213 dinitprintk((KERN_INFO MYNAM
2214 ": whoinit 0x%x statefault %d force %d\n",
2215 whoinit, statefault, force));
2216 if (whoinit == MPI_WHOINIT_PCI_PEER)
2219 if ((statefault == 0 ) && (force == 0)) {
2220 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2227 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2228 if (hard_reset_done < 0)
2232 * Loop here waiting for IOC to come READY.
2235 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2237 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2238 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2240 * BIOS or previous driver load left IOC in OP state.
2241 * Reset messaging FIFOs.
2243 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2244 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2247 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2249 * Something is wrong. Try to get IOC back
2252 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2253 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2260 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2261 ioc->name, (int)((ii+5)/HZ));
2265 if (sleepFlag == CAN_SLEEP) {
2268 mdelay (1); /* 1 msec delay */
2273 if (statefault < 3) {
2274 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2276 statefault==1 ? "stuck handshake" : "IOC FAULT");
2279 return hard_reset_done;
2282 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2284 * mpt_GetIocState - Get the current state of a MPT adapter.
2285 * @ioc: Pointer to MPT_ADAPTER structure
2286 * @cooked: Request raw or cooked IOC state
2288 * Returns all IOC Doorbell register bits if cooked==0, else just the
2289 * Doorbell bits in MPI_IOC_STATE_MASK.
2292 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2297 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2298 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2299 sc = s & MPI_IOC_STATE_MASK;
2302 ioc->last_state = sc;
2304 return cooked ? sc : s;
2307 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2309 * GetIocFacts - Send IOCFacts request to MPT adapter.
2310 * @ioc: Pointer to MPT_ADAPTER structure
2311 * @sleepFlag: Specifies whether the process can sleep
2312 * @reason: If recovery, only update facts.
2314 * Returns 0 for success, non-zero for failure.
2317 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2319 IOCFacts_t get_facts;
2320 IOCFactsReply_t *facts;
2328 /* IOC *must* NOT be in RESET state! */
2329 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2330 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2336 facts = &ioc->facts;
2338 /* Destination (reply area)... */
2339 reply_sz = sizeof(*facts);
2340 memset(facts, 0, reply_sz);
2342 /* Request area (get_facts on the stack right now!) */
2343 req_sz = sizeof(get_facts);
2344 memset(&get_facts, 0, req_sz);
2346 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2347 /* Assert: All other get_facts fields are zero! */
2349 dinitprintk((MYIOC_s_INFO_FMT
2350 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2351 ioc->name, req_sz, reply_sz));
2353 /* No non-zero fields in the get_facts request are greater than
2354 * 1 byte in size, so we can just fire it off as is.
2356 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2357 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2362 * Now byte swap (GRRR) the necessary fields before any further
2363 * inspection of reply contents.
2365 * But need to do some sanity checks on MsgLength (byte) field
2366 * to make sure we don't zero IOC's req_sz!
2368 /* Did we get a valid reply? */
2369 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2370 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2372 * If not been here, done that, save off first WhoInit value
2374 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2375 ioc->FirstWhoInit = facts->WhoInit;
2378 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2379 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2380 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2381 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2382 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2383 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2384 /* CHECKME! IOCStatus, IOCLogInfo */
2386 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2387 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2390 * FC f/w version changed between 1.1 and 1.2
2391 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2392 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2394 if (facts->MsgVersion < 0x0102) {
2396 * Handle old FC f/w style, convert to new...
2398 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2399 facts->FWVersion.Word =
2400 ((oldv<<12) & 0xFF000000) |
2401 ((oldv<<8) & 0x000FFF00);
2403 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2405 facts->ProductID = le16_to_cpu(facts->ProductID);
2406 facts->CurrentHostMfaHighAddr =
2407 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2408 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2409 facts->CurrentSenseBufferHighAddr =
2410 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2411 facts->CurReplyFrameSize =
2412 le16_to_cpu(facts->CurReplyFrameSize);
2413 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2416 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2417 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2418 * to 14 in MPI-1.01.0x.
2420 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2421 facts->MsgVersion > 0x0100) {
2422 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2425 sz = facts->FWImageSize;
2430 facts->FWImageSize = sz;
2432 if (!facts->RequestFrameSize) {
2433 /* Something is wrong! */
2434 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2439 r = sz = facts->BlockSize;
2440 vv = ((63 / (sz * 4)) + 1) & 0x03;
2441 ioc->NB_for_64_byte_frame = vv;
2447 ioc->NBShiftFactor = shiftFactor;
2448 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2449 ioc->name, vv, shiftFactor, r));
2451 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2453 * Set values for this IOC's request & reply frame sizes,
2454 * and request & reply queue depths...
2456 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2457 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2458 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2459 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2461 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2462 ioc->name, ioc->reply_sz, ioc->reply_depth));
2463 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2464 ioc->name, ioc->req_sz, ioc->req_depth));
2466 /* Get port facts! */
2467 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2471 printk(MYIOC_s_ERR_FMT
2472 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2473 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2474 RequestFrameSize)/sizeof(u32)));
2481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2483 * GetPortFacts - Send PortFacts request to MPT adapter.
2484 * @ioc: Pointer to MPT_ADAPTER structure
2485 * @portnum: Port number
2486 * @sleepFlag: Specifies whether the process can sleep
2488 * Returns 0 for success, non-zero for failure.
2491 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2493 PortFacts_t get_pfacts;
2494 PortFactsReply_t *pfacts;
2499 /* IOC *must* NOT be in RESET state! */
2500 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2501 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2507 pfacts = &ioc->pfacts[portnum];
2509 /* Destination (reply area)... */
2510 reply_sz = sizeof(*pfacts);
2511 memset(pfacts, 0, reply_sz);
2513 /* Request area (get_pfacts on the stack right now!) */
2514 req_sz = sizeof(get_pfacts);
2515 memset(&get_pfacts, 0, req_sz);
2517 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2518 get_pfacts.PortNumber = portnum;
2519 /* Assert: All other get_pfacts fields are zero! */
2521 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2522 ioc->name, portnum));
2524 /* No non-zero fields in the get_pfacts request are greater than
2525 * 1 byte in size, so we can just fire it off as is.
2527 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2528 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2532 /* Did we get a valid reply? */
2534 /* Now byte swap the necessary fields in the response. */
2535 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2536 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2537 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2538 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2539 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2540 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2541 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2542 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2543 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2548 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2550 * SendIocInit - Send IOCInit request to MPT adapter.
2551 * @ioc: Pointer to MPT_ADAPTER structure
2552 * @sleepFlag: Specifies whether the process can sleep
2554 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2556 * Returns 0 for success, non-zero for failure.
2559 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2562 MPIDefaultReply_t init_reply;
2568 memset(&ioc_init, 0, sizeof(ioc_init));
2569 memset(&init_reply, 0, sizeof(init_reply));
2571 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2572 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2574 /* If we are in a recovery mode and we uploaded the FW image,
2575 * then this pointer is not NULL. Skip the upload a second time.
2576 * Set this flag if cached_fw set for either IOC.
2578 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2582 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2583 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2585 if(ioc->bus_type == SAS)
2586 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2587 else if(ioc->bus_type == FC)
2588 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2590 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2591 ioc_init.MaxBuses = MPT_MAX_BUS;
2592 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2593 ioc->name, ioc->facts.MsgVersion));
2594 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2595 // set MsgVersion and HeaderVersion host driver was built with
2596 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2597 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2599 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2600 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2601 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2604 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2606 if (sizeof(dma_addr_t) == sizeof(u64)) {
2607 /* Save the upper 32-bits of the request
2608 * (reply) and sense buffers.
2610 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2611 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2613 /* Force 32-bit addressing */
2614 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2615 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2618 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2619 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2620 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2621 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2623 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2624 ioc->name, &ioc_init));
2626 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2627 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2629 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2633 /* No need to byte swap the multibyte fields in the reply
2634 * since we don't even look at it's contents.
2637 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2638 ioc->name, &ioc_init));
2640 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2641 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2645 /* YIKES! SUPER IMPORTANT!!!
2646 * Poll IocState until _OPERATIONAL while IOC is doing
2647 * LoopInit and TargetDiscovery!
2650 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2651 state = mpt_GetIocState(ioc, 1);
2652 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2653 if (sleepFlag == CAN_SLEEP) {
2660 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2661 ioc->name, (int)((count+5)/HZ));
2665 state = mpt_GetIocState(ioc, 1);
2668 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2676 * SendPortEnable - Send PortEnable request to MPT adapter port.
2677 * @ioc: Pointer to MPT_ADAPTER structure
2678 * @portnum: Port number to enable
2679 * @sleepFlag: Specifies whether the process can sleep
2681 * Send PortEnable to bring IOC to OPERATIONAL state.
2683 * Returns 0 for success, non-zero for failure.
2686 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2688 PortEnable_t port_enable;
2689 MPIDefaultReply_t reply_buf;
2694 /* Destination... */
2695 reply_sz = sizeof(MPIDefaultReply_t);
2696 memset(&reply_buf, 0, reply_sz);
2698 req_sz = sizeof(PortEnable_t);
2699 memset(&port_enable, 0, req_sz);
2701 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2702 port_enable.PortNumber = portnum;
2703 /* port_enable.ChainOffset = 0; */
2704 /* port_enable.MsgFlags = 0; */
2705 /* port_enable.MsgContext = 0; */
2707 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2708 ioc->name, portnum, &port_enable));
2710 /* RAID FW may take a long time to enable
2712 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2713 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2714 (ioc->bus_type == SAS)) {
2715 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2716 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2717 300 /*seconds*/, sleepFlag);
2719 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2720 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2721 30 /*seconds*/, sleepFlag);
2727 * ioc: Pointer to MPT_ADAPTER structure
2728 * size - total FW bytes
2731 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2734 return; /* use already allocated memory */
2735 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2736 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2737 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2738 ioc->alloc_total += size;
2739 ioc->alt_ioc->alloc_total -= size;
2741 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2742 ioc->alloc_total += size;
2746 * If alt_img is NULL, delete from ioc structure.
2747 * Else, delete a secondary image in same format.
2750 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2754 sz = ioc->facts.FWImageSize;
2755 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2756 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2757 pci_free_consistent(ioc->pcidev, sz,
2758 ioc->cached_fw, ioc->cached_fw_dma);
2759 ioc->cached_fw = NULL;
2765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2767 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2768 * @ioc: Pointer to MPT_ADAPTER structure
2769 * @sleepFlag: Specifies whether the process can sleep
2771 * Returns 0 for success, >0 for handshake failure
2772 * <0 for fw upload failure.
2774 * Remark: If bound IOC and a successful FWUpload was performed
2775 * on the bound IOC, the second image is discarded
2776 * and memory is free'd. Both channels must upload to prevent
2777 * IOC from running in degraded mode.
2780 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2782 u8 request[ioc->req_sz];
2783 u8 reply[sizeof(FWUploadReply_t)];
2784 FWUpload_t *prequest;
2785 FWUploadReply_t *preply;
2786 FWUploadTCSGE_t *ptcsge;
2789 int ii, sz, reply_sz;
2792 /* If the image size is 0, we are done.
2794 if ((sz = ioc->facts.FWImageSize) == 0)
2797 mpt_alloc_fw_memory(ioc, sz);
2799 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2800 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2802 if (ioc->cached_fw == NULL) {
2808 prequest = (FWUpload_t *)&request;
2809 preply = (FWUploadReply_t *)&reply;
2811 /* Destination... */
2812 memset(prequest, 0, ioc->req_sz);
2814 reply_sz = sizeof(reply);
2815 memset(preply, 0, reply_sz);
2817 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2818 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2820 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2821 ptcsge->DetailsLength = 12;
2822 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2823 ptcsge->ImageSize = cpu_to_le32(sz);
2825 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2827 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2828 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2830 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2831 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2832 prequest, sgeoffset));
2833 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2835 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2836 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2838 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2840 cmdStatus = -EFAULT;
2842 /* Handshake transfer was complete and successful.
2843 * Check the Reply Frame.
2845 int status, transfer_sz;
2846 status = le16_to_cpu(preply->IOCStatus);
2847 if (status == MPI_IOCSTATUS_SUCCESS) {
2848 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2849 if (transfer_sz == sz)
2853 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2854 ioc->name, cmdStatus));
2859 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2861 mpt_free_fw_memory(ioc);
2867 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2869 * mpt_downloadboot - DownloadBoot code
2870 * @ioc: Pointer to MPT_ADAPTER structure
2871 * @flag: Specify which part of IOC memory is to be uploaded.
2872 * @sleepFlag: Specifies whether the process can sleep
2874 * FwDownloadBoot requires Programmed IO access.
2876 * Returns 0 for success
2877 * -1 FW Image size is 0
2878 * -2 No valid cached_fw Pointer
2879 * <0 for fw upload failure.
2882 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2884 MpiExtImageHeader_t *pExtImage;
2894 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2895 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2897 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2898 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2899 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2900 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2901 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2902 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2904 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2907 if (sleepFlag == CAN_SLEEP) {
2913 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2914 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2916 for (count = 0; count < 30; count ++) {
2917 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2918 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2919 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2924 if (sleepFlag == CAN_SLEEP) {
2931 if ( count == 30 ) {
2932 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2933 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2934 ioc->name, diag0val));
2938 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2939 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2940 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2941 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2942 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2943 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2945 /* Set the DiagRwEn and Disable ARM bits */
2946 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2948 fwSize = (pFwHeader->ImageSize + 3)/4;
2949 ptrFw = (u32 *) pFwHeader;
2951 /* Write the LoadStartAddress to the DiagRw Address Register
2952 * using Programmed IO
2954 if (ioc->errata_flag_1064)
2955 pci_enable_io_access(ioc->pcidev);
2957 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2958 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2959 ioc->name, pFwHeader->LoadStartAddress));
2961 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2962 ioc->name, fwSize*4, ptrFw));
2964 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2967 nextImage = pFwHeader->NextImageHeaderOffset;
2969 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2971 load_addr = pExtImage->LoadStartAddress;
2973 fwSize = (pExtImage->ImageSize + 3) >> 2;
2974 ptrFw = (u32 *)pExtImage;
2976 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
2977 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
2978 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2981 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2983 nextImage = pExtImage->NextImageHeaderOffset;
2986 /* Write the IopResetVectorRegAddr */
2987 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2988 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2990 /* Write the IopResetVectorValue */
2991 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
2992 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
2994 /* Clear the internal flash bad bit - autoincrementing register,
2995 * so must do two writes.
2997 if (ioc->bus_type == SPI) {
2999 * 1030 and 1035 H/W errata, workaround to access
3000 * the ClearFlashBadSignatureBit
3002 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3003 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3004 diagRwData |= 0x40000000;
3005 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3006 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3008 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3009 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3010 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3011 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3014 if (sleepFlag == CAN_SLEEP) {
3021 if (ioc->errata_flag_1064)
3022 pci_disable_io_access(ioc->pcidev);
3024 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3025 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3026 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3027 ioc->name, diag0val));
3028 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3029 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3030 ioc->name, diag0val));
3031 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3033 /* Write 0xFF to reset the sequencer */
3034 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3036 if (ioc->bus_type == SAS) {
3037 ioc_state = mpt_GetIocState(ioc, 0);
3038 if ( (GetIocFacts(ioc, sleepFlag,
3039 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3040 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3041 ioc->name, ioc_state));
3046 for (count=0; count<HZ*20; count++) {
3047 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3048 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3049 ioc->name, count, ioc_state));
3050 if (ioc->bus_type == SAS) {
3053 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3054 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3058 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3062 if (sleepFlag == CAN_SLEEP) {
3068 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3069 ioc->name, ioc_state));
3073 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3075 * KickStart - Perform hard reset of MPT adapter.
3076 * @ioc: Pointer to MPT_ADAPTER structure
3077 * @force: Force hard reset
3078 * @sleepFlag: Specifies whether the process can sleep
3080 * This routine places MPT adapter in diagnostic mode via the
3081 * WriteSequence register, and then performs a hard reset of adapter
3082 * via the Diagnostic register.
3084 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3085 * or NO_SLEEP (interrupt thread, use mdelay)
3086 * force - 1 if doorbell active, board fault state
3087 * board operational, IOC_RECOVERY or
3088 * IOC_BRINGUP and there is an alt_ioc.
3092 * 1 - hard reset, READY
3093 * 0 - no reset due to History bit, READY
3094 * -1 - no reset due to History bit but not READY
3095 * OR reset but failed to come READY
3096 * -2 - no reset, could not enter DIAG mode
3097 * -3 - reset but bad FW bit
3100 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3102 int hard_reset_done = 0;
3106 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3107 if (ioc->bus_type == SPI) {
3108 /* Always issue a Msg Unit Reset first. This will clear some
3109 * SCSI bus hang conditions.
3111 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3113 if (sleepFlag == CAN_SLEEP) {
3120 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3121 if (hard_reset_done < 0)
3122 return hard_reset_done;
3124 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3127 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3128 for (cnt=0; cnt<cntdn; cnt++) {
3129 ioc_state = mpt_GetIocState(ioc, 1);
3130 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3131 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3133 return hard_reset_done;
3135 if (sleepFlag == CAN_SLEEP) {
3142 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3143 ioc->name, ioc_state);
3147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3149 * mpt_diag_reset - Perform hard reset of the adapter.
3150 * @ioc: Pointer to MPT_ADAPTER structure
3151 * @ignore: Set if to honor and clear to ignore
3152 * the reset history bit
3153 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3154 * else set to NO_SLEEP (use mdelay instead)
3156 * This routine places the adapter in diagnostic mode via the
3157 * WriteSequence register and then performs a hard reset of adapter
3158 * via the Diagnostic register. Adapter should be in ready state
3159 * upon successful completion.
3161 * Returns: 1 hard reset successful
3162 * 0 no reset performed because reset history bit set
3163 * -2 enabling diagnostic mode failed
3164 * -3 diagnostic reset failed
3167 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3169 MPT_ADAPTER *iocp=NULL;
3172 int hard_reset_done = 0;
3178 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3179 drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3180 "address=%p\n", ioc->name, __FUNCTION__,
3181 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3182 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3183 if (sleepFlag == CAN_SLEEP)
3188 for (count = 0; count < 60; count ++) {
3189 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3190 doorbell &= MPI_IOC_STATE_MASK;
3192 drsprintk((MYIOC_s_INFO_FMT
3193 "looking for READY STATE: doorbell=%x"
3195 ioc->name, doorbell, count));
3196 if (doorbell == MPI_IOC_STATE_READY) {
3201 if (sleepFlag == CAN_SLEEP)
3209 /* Clear any existing interrupts */
3210 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3212 /* Use "Diagnostic reset" method! (only thing available!) */
3213 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3217 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3218 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3219 ioc->name, diag0val, diag1val));
3222 /* Do the reset if we are told to ignore the reset history
3223 * or if the reset history is 0
3225 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3226 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3227 /* Write magic sequence to WriteSequence register
3228 * Loop until in diagnostic mode
3230 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3231 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3232 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3233 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3234 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3235 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3238 if (sleepFlag == CAN_SLEEP) {
3246 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3247 ioc->name, diag0val);
3252 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3254 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3255 ioc->name, diag0val));
3260 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3261 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3262 ioc->name, diag0val, diag1val));
3265 * Disable the ARM (Bug fix)
3268 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3272 * Now hit the reset bit in the Diagnostic register
3273 * (THE BIG HAMMER!) (Clears DRWE bit).
3275 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3276 hard_reset_done = 1;
3277 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3281 * Call each currently registered protocol IOC reset handler
3282 * with pre-reset indication.
3283 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3284 * MptResetHandlers[] registered yet.
3290 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3291 if (MptResetHandlers[ii]) {
3292 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3294 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3296 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3297 ioc->name, ioc->alt_ioc->name, ii));
3298 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3302 /* FIXME? Examine results here? */
3307 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3308 iocp = ioc->alt_ioc;
3310 /* If the DownloadBoot operation fails, the
3311 * IOC will be left unusable. This is a fatal error
3312 * case. _diag_reset will return < 0
3314 for (count = 0; count < 30; count ++) {
3315 diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
3316 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3320 dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
3321 iocp->name, diag0val, count));
3323 if (sleepFlag == CAN_SLEEP) {
3329 if ((count = mpt_downloadboot(ioc,
3330 (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
3331 printk(KERN_WARNING MYNAM
3332 ": firmware downloadboot failure (%d)!\n", count);
3336 /* Wait for FW to reload and for board
3337 * to go to the READY state.
3338 * Maximum wait is 60 seconds.
3339 * If fail, no error will check again
3340 * with calling program.
3342 for (count = 0; count < 60; count ++) {
3343 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3344 doorbell &= MPI_IOC_STATE_MASK;
3346 if (doorbell == MPI_IOC_STATE_READY) {
3351 if (sleepFlag == CAN_SLEEP) {
3360 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3363 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3364 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3365 ioc->name, diag0val, diag1val));
3368 /* Clear RESET_HISTORY bit! Place board in the
3369 * diagnostic mode to update the diag register.
3371 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3373 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3374 /* Write magic sequence to WriteSequence register
3375 * Loop until in diagnostic mode
3377 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3378 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3379 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3380 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3381 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3382 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3385 if (sleepFlag == CAN_SLEEP) {
3393 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3394 ioc->name, diag0val);
3397 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3399 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3400 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3401 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3402 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3403 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3407 /* Disable Diagnostic Mode
3409 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3411 /* Check FW reload status flags.
3413 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3414 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3415 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3416 ioc->name, diag0val);
3422 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3423 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3424 ioc->name, diag0val, diag1val));
3428 * Reset flag that says we've enabled event notification
3430 ioc->facts.EventState = 0;
3433 ioc->alt_ioc->facts.EventState = 0;
3435 return hard_reset_done;
3438 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3440 * SendIocReset - Send IOCReset request to MPT adapter.
3441 * @ioc: Pointer to MPT_ADAPTER structure
3442 * @reset_type: reset type, expected values are
3443 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3445 * Send IOCReset request to the MPT adapter.
3447 * Returns 0 for success, non-zero for failure.
3450 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3456 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3457 ioc->name, reset_type));
3458 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3459 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3462 /* FW ACK'd request, wait for READY state
3465 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3467 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3471 if (sleepFlag != CAN_SLEEP)
3474 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3475 ioc->name, (int)((count+5)/HZ));
3479 if (sleepFlag == CAN_SLEEP) {
3482 mdelay (1); /* 1 msec delay */
3487 * Cleanup all event stuff for this IOC; re-issue EventNotification
3488 * request if needed.
3490 if (ioc->facts.Function)
3491 ioc->facts.EventState = 0;
3496 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3498 * initChainBuffers - Allocate memory for and initialize
3499 * chain buffers, chain buffer control arrays and spinlock.
3500 * @hd: Pointer to MPT_SCSI_HOST structure
3501 * @init: If set, initialize the spin lock.
3504 initChainBuffers(MPT_ADAPTER *ioc)
3507 int sz, ii, num_chain;
3508 int scale, num_sge, numSGE;
3510 /* ReqToChain size must equal the req_depth
3513 if (ioc->ReqToChain == NULL) {
3514 sz = ioc->req_depth * sizeof(int);
3515 mem = kmalloc(sz, GFP_ATOMIC);
3519 ioc->ReqToChain = (int *) mem;
3520 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3521 ioc->name, mem, sz));
3522 mem = kmalloc(sz, GFP_ATOMIC);
3526 ioc->RequestNB = (int *) mem;
3527 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3528 ioc->name, mem, sz));
3530 for (ii = 0; ii < ioc->req_depth; ii++) {
3531 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3534 /* ChainToChain size must equal the total number
3535 * of chain buffers to be allocated.
3538 * Calculate the number of chain buffers needed(plus 1) per I/O
3539 * then multiply the the maximum number of simultaneous cmds
3541 * num_sge = num sge in request frame + last chain buffer
3542 * scale = num sge per chain buffer if no chain element
3544 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3545 if (sizeof(dma_addr_t) == sizeof(u64))
3546 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3548 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3550 if (sizeof(dma_addr_t) == sizeof(u64)) {
3551 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3552 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3554 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3555 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3557 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3558 ioc->name, num_sge, numSGE));
3560 if ( numSGE > MPT_SCSI_SG_DEPTH )
3561 numSGE = MPT_SCSI_SG_DEPTH;
3564 while (numSGE - num_sge > 0) {
3566 num_sge += (scale - 1);
3570 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3571 ioc->name, numSGE, num_sge, num_chain));
3573 if (ioc->bus_type == SPI)
3574 num_chain *= MPT_SCSI_CAN_QUEUE;
3576 num_chain *= MPT_FC_CAN_QUEUE;
3578 ioc->num_chain = num_chain;
3580 sz = num_chain * sizeof(int);
3581 if (ioc->ChainToChain == NULL) {
3582 mem = kmalloc(sz, GFP_ATOMIC);
3586 ioc->ChainToChain = (int *) mem;
3587 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3588 ioc->name, mem, sz));
3590 mem = (u8 *) ioc->ChainToChain;
3592 memset(mem, 0xFF, sz);
3596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3598 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3599 * @ioc: Pointer to MPT_ADAPTER structure
3601 * This routine allocates memory for the MPT reply and request frame
3602 * pools (if necessary), and primes the IOC reply FIFO with
3605 * Returns 0 for success, non-zero for failure.
3608 PrimeIocFifos(MPT_ADAPTER *ioc)
3611 unsigned long flags;
3612 dma_addr_t alloc_dma;
3614 int i, reply_sz, sz, total_size, num_chain;
3616 /* Prime reply FIFO... */
3618 if (ioc->reply_frames == NULL) {
3619 if ( (num_chain = initChainBuffers(ioc)) < 0)
3622 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3623 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3624 ioc->name, ioc->reply_sz, ioc->reply_depth));
3625 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3626 ioc->name, reply_sz, reply_sz));
3628 sz = (ioc->req_sz * ioc->req_depth);
3629 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3630 ioc->name, ioc->req_sz, ioc->req_depth));
3631 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3632 ioc->name, sz, sz));
3635 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3636 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3637 ioc->name, ioc->req_sz, num_chain));
3638 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3639 ioc->name, sz, sz, num_chain));
3642 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3644 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3649 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3650 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3652 memset(mem, 0, total_size);
3653 ioc->alloc_total += total_size;
3655 ioc->alloc_dma = alloc_dma;
3656 ioc->alloc_sz = total_size;
3657 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3658 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3660 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3661 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3663 alloc_dma += reply_sz;
3666 /* Request FIFO - WE manage this! */
3668 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3669 ioc->req_frames_dma = alloc_dma;
3671 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3672 ioc->name, mem, (void *)(ulong)alloc_dma));
3674 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3676 #if defined(CONFIG_MTRR) && 0
3678 * Enable Write Combining MTRR for IOC's memory region.
3679 * (at least as much as we can; "size and base must be
3680 * multiples of 4 kiB"
3682 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3684 MTRR_TYPE_WRCOMB, 1);
3685 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3686 ioc->name, ioc->req_frames_dma, sz));
3689 for (i = 0; i < ioc->req_depth; i++) {
3690 alloc_dma += ioc->req_sz;
3694 ioc->ChainBuffer = mem;
3695 ioc->ChainBufferDMA = alloc_dma;
3697 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3698 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3700 /* Initialize the free chain Q.
3703 INIT_LIST_HEAD(&ioc->FreeChainQ);
3705 /* Post the chain buffers to the FreeChainQ.
3707 mem = (u8 *)ioc->ChainBuffer;
3708 for (i=0; i < num_chain; i++) {
3709 mf = (MPT_FRAME_HDR *) mem;
3710 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3714 /* Initialize Request frames linked list
3716 alloc_dma = ioc->req_frames_dma;
3717 mem = (u8 *) ioc->req_frames;
3719 spin_lock_irqsave(&ioc->FreeQlock, flags);
3720 INIT_LIST_HEAD(&ioc->FreeQ);
3721 for (i = 0; i < ioc->req_depth; i++) {
3722 mf = (MPT_FRAME_HDR *) mem;
3724 /* Queue REQUESTs *internally*! */
3725 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3729 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3731 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3732 ioc->sense_buf_pool =
3733 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3734 if (ioc->sense_buf_pool == NULL) {
3735 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3740 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3741 ioc->alloc_total += sz;
3742 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3743 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3747 /* Post Reply frames to FIFO
3749 alloc_dma = ioc->alloc_dma;
3750 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3751 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3753 for (i = 0; i < ioc->reply_depth; i++) {
3754 /* Write each address to the IOC! */
3755 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3756 alloc_dma += ioc->reply_sz;
3762 if (ioc->alloc != NULL) {
3764 pci_free_consistent(ioc->pcidev,
3766 ioc->alloc, ioc->alloc_dma);
3767 ioc->reply_frames = NULL;
3768 ioc->req_frames = NULL;
3769 ioc->alloc_total -= sz;
3771 if (ioc->sense_buf_pool != NULL) {
3772 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3773 pci_free_consistent(ioc->pcidev,
3775 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3776 ioc->sense_buf_pool = NULL;
3781 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3783 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3784 * from IOC via doorbell handshake method.
3785 * @ioc: Pointer to MPT_ADAPTER structure
3786 * @reqBytes: Size of the request in bytes
3787 * @req: Pointer to MPT request frame
3788 * @replyBytes: Expected size of the reply in bytes
3789 * @u16reply: Pointer to area where reply should be written
3790 * @maxwait: Max wait time for a reply (in seconds)
3791 * @sleepFlag: Specifies whether the process can sleep
3793 * NOTES: It is the callers responsibility to byte-swap fields in the
3794 * request which are greater than 1 byte in size. It is also the
3795 * callers responsibility to byte-swap response fields which are
3796 * greater than 1 byte in size.
3798 * Returns 0 for success, non-zero for failure.
3801 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3802 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3804 MPIDefaultReply_t *mptReply;
3809 * Get ready to cache a handshake reply
3811 ioc->hs_reply_idx = 0;
3812 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3813 mptReply->MsgLength = 0;
3816 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3817 * then tell IOC that we want to handshake a request of N words.
3818 * (WRITE u32val to Doorbell reg).
3820 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3821 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3822 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3823 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3826 * Wait for IOC's doorbell handshake int
3828 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3831 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3832 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3834 /* Read doorbell and check for active bit */
3835 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3839 * Clear doorbell int (WRITE 0 to IntStatus reg),
3840 * then wait for IOC to ACKnowledge that it's ready for
3841 * our handshake request.
3843 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3844 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3849 u8 *req_as_bytes = (u8 *) req;
3852 * Stuff request words via doorbell handshake,
3853 * with ACK from IOC for each.
3855 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3856 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3857 (req_as_bytes[(ii*4) + 1] << 8) |
3858 (req_as_bytes[(ii*4) + 2] << 16) |
3859 (req_as_bytes[(ii*4) + 3] << 24));
3861 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3862 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3866 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3867 DBG_DUMP_REQUEST_FRAME_HDR(req)
3869 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3870 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3873 * Wait for completion of doorbell handshake reply from the IOC
3875 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3878 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3879 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3882 * Copy out the cached reply...
3884 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3885 u16reply[ii] = ioc->hs_reply[ii];
3893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3895 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3896 * in it's IntStatus register.
3897 * @ioc: Pointer to MPT_ADAPTER structure
3898 * @howlong: How long to wait (in seconds)
3899 * @sleepFlag: Specifies whether the process can sleep
3901 * This routine waits (up to ~2 seconds max) for IOC doorbell
3902 * handshake ACKnowledge.
3904 * Returns a negative value on failure, else wait loop count.
3907 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3913 cntdn = 1000 * howlong;
3915 if (sleepFlag == CAN_SLEEP) {
3918 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3919 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3926 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3927 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3934 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3939 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3940 ioc->name, count, intstat);
3944 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3946 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3947 * in it's IntStatus register.
3948 * @ioc: Pointer to MPT_ADAPTER structure
3949 * @howlong: How long to wait (in seconds)
3950 * @sleepFlag: Specifies whether the process can sleep
3952 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3954 * Returns a negative value on failure, else wait loop count.
3957 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3963 cntdn = 1000 * howlong;
3964 if (sleepFlag == CAN_SLEEP) {
3966 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3967 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3974 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3975 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3983 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3984 ioc->name, count, howlong));
3988 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3989 ioc->name, count, intstat);
3993 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3995 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3996 * @ioc: Pointer to MPT_ADAPTER structure
3997 * @howlong: How long to wait (in seconds)
3998 * @sleepFlag: Specifies whether the process can sleep
4000 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4001 * Reply is cached to IOC private area large enough to hold a maximum
4002 * of 128 bytes of reply data.
4004 * Returns a negative value on failure, else size of reply in WORDS.
4007 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4012 u16 *hs_reply = ioc->hs_reply;
4013 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4016 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4019 * Get first two u16's so we can look at IOC's intended reply MsgLength
4022 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4025 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4026 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4027 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4030 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4031 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4035 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4036 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4037 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4040 * If no error (and IOC said MsgLength is > 0), piece together
4041 * reply 16 bits at a time.
4043 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4044 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4046 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4047 /* don't overflow our IOC hs_reply[] buffer! */
4048 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4049 hs_reply[u16cnt] = hword;
4050 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4053 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4055 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4058 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4063 else if (u16cnt != (2 * mptReply->MsgLength)) {
4066 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4071 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4072 DBG_DUMP_REPLY_FRAME(mptReply)
4074 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4075 ioc->name, t, u16cnt/2));
4079 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4081 * GetLanConfigPages - Fetch LANConfig pages.
4082 * @ioc: Pointer to MPT_ADAPTER structure
4084 * Return: 0 for success
4085 * -ENOMEM if no memory available
4086 * -EPERM if not allowed due to ISR context
4087 * -EAGAIN if no msg frames currently available
4088 * -EFAULT for non-successful reply or no reply (timeout)
4091 GetLanConfigPages(MPT_ADAPTER *ioc)
4093 ConfigPageHeader_t hdr;
4095 LANPage0_t *ppage0_alloc;
4096 dma_addr_t page0_dma;
4097 LANPage1_t *ppage1_alloc;
4098 dma_addr_t page1_dma;
4103 /* Get LAN Page 0 header */
4104 hdr.PageVersion = 0;
4107 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4108 cfg.cfghdr.hdr = &hdr;
4110 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4115 if ((rc = mpt_config(ioc, &cfg)) != 0)
4118 if (hdr.PageLength > 0) {
4119 data_sz = hdr.PageLength * 4;
4120 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4123 memset((u8 *)ppage0_alloc, 0, data_sz);
4124 cfg.physAddr = page0_dma;
4125 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4127 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4129 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4130 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4134 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4137 * Normalize endianness of structure data,
4138 * by byte-swapping all > 1 byte fields!
4147 /* Get LAN Page 1 header */
4148 hdr.PageVersion = 0;
4151 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4152 cfg.cfghdr.hdr = &hdr;
4154 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4158 if ((rc = mpt_config(ioc, &cfg)) != 0)
4161 if (hdr.PageLength == 0)
4164 data_sz = hdr.PageLength * 4;
4166 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4168 memset((u8 *)ppage1_alloc, 0, data_sz);
4169 cfg.physAddr = page1_dma;
4170 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4172 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4174 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4175 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4178 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4181 * Normalize endianness of structure data,
4182 * by byte-swapping all > 1 byte fields!
4190 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4192 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4193 * @ioc: Pointer to MPT_ADAPTER structure
4194 * @sas_address: 64bit SAS Address for operation.
4195 * @target_id: specified target for operation
4196 * @bus: specified bus for operation
4197 * @persist_opcode: see below
4199 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4200 * devices not currently present.
4201 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4203 * NOTE: Don't use not this function during interrupt time.
4205 * Returns: 0 for success, non-zero error
4208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4210 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4212 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4213 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4214 MPT_FRAME_HDR *mf = NULL;
4215 MPIHeader_t *mpi_hdr;
4218 /* insure garbage is not sent to fw */
4219 switch(persist_opcode) {
4221 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4222 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4230 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4232 /* Get a MF for this command.
4234 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4235 printk("%s: no msg frames!\n",__FUNCTION__);
4239 mpi_hdr = (MPIHeader_t *) mf;
4240 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4241 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4242 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4243 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4244 sasIoUnitCntrReq->Operation = persist_opcode;
4246 init_timer(&ioc->persist_timer);
4247 ioc->persist_timer.data = (unsigned long) ioc;
4248 ioc->persist_timer.function = mpt_timer_expired;
4249 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4250 ioc->persist_wait_done=0;
4251 add_timer(&ioc->persist_timer);
4252 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4253 wait_event(mpt_waitq, ioc->persist_wait_done);
4255 sasIoUnitCntrReply =
4256 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4257 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4258 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4260 sasIoUnitCntrReply->IOCStatus,
4261 sasIoUnitCntrReply->IOCLogInfo);
4265 printk("%s: success\n",__FUNCTION__);
4269 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4272 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4273 MpiEventDataRaid_t * pRaidEventData)
4282 volume = pRaidEventData->VolumeID;
4283 reason = pRaidEventData->ReasonCode;
4284 disk = pRaidEventData->PhysDiskNum;
4285 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4286 flags = (status >> 0) & 0xff;
4287 state = (status >> 8) & 0xff;
4289 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4293 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4294 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4295 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4296 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4299 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4304 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4305 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4309 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4311 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4315 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4316 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4320 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4321 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4323 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4325 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4327 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4330 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4332 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4333 ? ", quiesced" : "",
4334 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4335 ? ", resync in progress" : "" );
4338 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4339 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4343 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4344 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4348 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4349 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4353 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4354 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4358 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4359 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4361 state == MPI_PHYSDISK0_STATUS_ONLINE
4363 : state == MPI_PHYSDISK0_STATUS_MISSING
4365 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4367 : state == MPI_PHYSDISK0_STATUS_FAILED
4369 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4371 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4372 ? "offline requested"
4373 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4374 ? "failed requested"
4375 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4378 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4379 ? ", out of sync" : "",
4380 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4381 ? ", quiesced" : "" );
4384 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4385 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4389 case MPI_EVENT_RAID_RC_SMART_DATA:
4390 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4391 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4394 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4395 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4401 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4403 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4404 * @ioc: Pointer to MPT_ADAPTER structure
4406 * Returns: 0 for success
4407 * -ENOMEM if no memory available
4408 * -EPERM if not allowed due to ISR context
4409 * -EAGAIN if no msg frames currently available
4410 * -EFAULT for non-successful reply or no reply (timeout)
4413 GetIoUnitPage2(MPT_ADAPTER *ioc)
4415 ConfigPageHeader_t hdr;
4417 IOUnitPage2_t *ppage_alloc;
4418 dma_addr_t page_dma;
4422 /* Get the page header */
4423 hdr.PageVersion = 0;
4426 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4427 cfg.cfghdr.hdr = &hdr;
4429 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4434 if ((rc = mpt_config(ioc, &cfg)) != 0)
4437 if (hdr.PageLength == 0)
4440 /* Read the config page */
4441 data_sz = hdr.PageLength * 4;
4443 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4445 memset((u8 *)ppage_alloc, 0, data_sz);
4446 cfg.physAddr = page_dma;
4447 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4449 /* If Good, save data */
4450 if ((rc = mpt_config(ioc, &cfg)) == 0)
4451 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4453 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4459 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4460 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4461 * @ioc: Pointer to a Adapter Strucutre
4462 * @portnum: IOC port number
4464 * Return: -EFAULT if read of config page header fails
4466 * If read of SCSI Port Page 0 fails,
4467 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4468 * Adapter settings: async, narrow
4470 * If read of SCSI Port Page 2 fails,
4471 * Adapter settings valid
4472 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4477 * CHECK - what type of locking mechanisms should be used????
4480 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4485 ConfigPageHeader_t header;
4491 if (!ioc->spi_data.nvram) {
4494 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4495 mem = kmalloc(sz, GFP_ATOMIC);
4499 ioc->spi_data.nvram = (int *) mem;
4501 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4502 ioc->name, ioc->spi_data.nvram, sz));
4505 /* Invalidate NVRAM information
4507 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4508 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4511 /* Read SPP0 header, allocate memory, then read page.
4513 header.PageVersion = 0;
4514 header.PageLength = 0;
4515 header.PageNumber = 0;
4516 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4517 cfg.cfghdr.hdr = &header;
4519 cfg.pageAddr = portnum;
4520 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4522 cfg.timeout = 0; /* use default */
4523 if (mpt_config(ioc, &cfg) != 0)
4526 if (header.PageLength > 0) {
4527 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4529 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4530 cfg.physAddr = buf_dma;
4531 if (mpt_config(ioc, &cfg) != 0) {
4532 ioc->spi_data.maxBusWidth = MPT_NARROW;
4533 ioc->spi_data.maxSyncOffset = 0;
4534 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4535 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4537 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4538 ioc->name, ioc->spi_data.minSyncFactor));
4540 /* Save the Port Page 0 data
4542 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4543 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4544 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4546 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4547 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4548 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4549 ioc->name, pPP0->Capabilities));
4551 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4552 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4554 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4555 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4556 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4557 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4558 ioc->name, ioc->spi_data.minSyncFactor));
4560 ioc->spi_data.maxSyncOffset = 0;
4561 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4564 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4566 /* Update the minSyncFactor based on bus type.
4568 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4569 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4571 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4572 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4573 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4574 ioc->name, ioc->spi_data.minSyncFactor));
4579 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4584 /* SCSI Port Page 2 - Read the header then the page.
4586 header.PageVersion = 0;
4587 header.PageLength = 0;
4588 header.PageNumber = 2;
4589 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4590 cfg.cfghdr.hdr = &header;
4592 cfg.pageAddr = portnum;
4593 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4595 if (mpt_config(ioc, &cfg) != 0)
4598 if (header.PageLength > 0) {
4599 /* Allocate memory and read SCSI Port Page 2
4601 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4603 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4604 cfg.physAddr = buf_dma;
4605 if (mpt_config(ioc, &cfg) != 0) {
4606 /* Nvram data is left with INVALID mark
4610 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4611 MpiDeviceInfo_t *pdevice = NULL;
4614 * Save "Set to Avoid SCSI Bus Resets" flag
4616 ioc->spi_data.bus_reset =
4617 (le32_to_cpu(pPP2->PortFlags) &
4618 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4621 /* Save the Port Page 2 data
4622 * (reformat into a 32bit quantity)
4624 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4625 ioc->spi_data.PortFlags = data;
4626 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4627 pdevice = &pPP2->DeviceSettings[ii];
4628 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4629 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4630 ioc->spi_data.nvram[ii] = data;
4634 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4638 /* Update Adapter limits with those from NVRAM
4639 * Comment: Don't need to do this. Target performance
4640 * parameters will never exceed the adapters limits.
4646 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4647 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4648 * @ioc: Pointer to a Adapter Strucutre
4649 * @portnum: IOC port number
4651 * Return: -EFAULT if read of config page header fails
4655 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4658 ConfigPageHeader_t header;
4660 /* Read the SCSI Device Page 1 header
4662 header.PageVersion = 0;
4663 header.PageLength = 0;
4664 header.PageNumber = 1;
4665 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4666 cfg.cfghdr.hdr = &header;
4668 cfg.pageAddr = portnum;
4669 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4672 if (mpt_config(ioc, &cfg) != 0)
4675 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4676 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4678 header.PageVersion = 0;
4679 header.PageLength = 0;
4680 header.PageNumber = 0;
4681 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4682 if (mpt_config(ioc, &cfg) != 0)
4685 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4686 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4688 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4689 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4691 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4692 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4696 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4698 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4699 * @ioc: Pointer to a Adapter Strucutre
4700 * @portnum: IOC port number
4704 * -EFAULT if read of config page header fails or data pointer not NULL
4705 * -ENOMEM if pci_alloc failed
4708 mpt_findImVolumes(MPT_ADAPTER *ioc)
4712 ConfigPageIoc2RaidVol_t *pIocRv;
4713 dma_addr_t ioc2_dma;
4715 ConfigPageHeader_t header;
4722 /* Read IOCP2 header then the page.
4724 header.PageVersion = 0;
4725 header.PageLength = 0;
4726 header.PageNumber = 2;
4727 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4728 cfg.cfghdr.hdr = &header;
4731 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4734 if (mpt_config(ioc, &cfg) != 0)
4737 if (header.PageLength == 0)
4740 iocpage2sz = header.PageLength * 4;
4741 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4745 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4746 cfg.physAddr = ioc2_dma;
4747 if (mpt_config(ioc, &cfg) != 0)
4750 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4751 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4753 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4758 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4760 /* Identify RAID Volume Id's */
4761 nVols = pIoc2->NumActiveVolumes;
4767 /* At least 1 RAID Volume
4769 pIocRv = pIoc2->RaidVolume;
4770 ioc->raid_data.isRaid = 0;
4771 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4772 vid = pIocRv->VolumeID;
4773 vbus = pIocRv->VolumeBus;
4774 vioc = pIocRv->VolumeIOC;
4779 ioc->raid_data.isRaid |= (1 << vid);
4781 /* Error! Always bus 0
4787 /* Identify Hidden Physical Disk Id's */
4788 nPhys = pIoc2->NumActivePhysDisks;
4790 /* No physical disks.
4793 mpt_read_ioc_pg_3(ioc);
4797 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4803 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4808 ConfigPageHeader_t header;
4809 dma_addr_t ioc3_dma;
4812 /* Free the old page
4814 kfree(ioc->raid_data.pIocPg3);
4815 ioc->raid_data.pIocPg3 = NULL;
4817 /* There is at least one physical disk.
4818 * Read and save IOC Page 3
4820 header.PageVersion = 0;
4821 header.PageLength = 0;
4822 header.PageNumber = 3;
4823 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4824 cfg.cfghdr.hdr = &header;
4827 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4830 if (mpt_config(ioc, &cfg) != 0)
4833 if (header.PageLength == 0)
4836 /* Read Header good, alloc memory
4838 iocpage3sz = header.PageLength * 4;
4839 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4843 /* Read the Page and save the data
4844 * into malloc'd memory.
4846 cfg.physAddr = ioc3_dma;
4847 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4848 if (mpt_config(ioc, &cfg) == 0) {
4849 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4851 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4852 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4856 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4862 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4866 ConfigPageHeader_t header;
4867 dma_addr_t ioc4_dma;
4870 /* Read and save IOC Page 4
4872 header.PageVersion = 0;
4873 header.PageLength = 0;
4874 header.PageNumber = 4;
4875 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4876 cfg.cfghdr.hdr = &header;
4879 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4882 if (mpt_config(ioc, &cfg) != 0)
4885 if (header.PageLength == 0)
4888 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4889 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4890 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4893 ioc->alloc_total += iocpage4sz;
4895 ioc4_dma = ioc->spi_data.IocPg4_dma;
4896 iocpage4sz = ioc->spi_data.IocPg4Sz;
4899 /* Read the Page into dma memory.
4901 cfg.physAddr = ioc4_dma;
4902 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4903 if (mpt_config(ioc, &cfg) == 0) {
4904 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4905 ioc->spi_data.IocPg4_dma = ioc4_dma;
4906 ioc->spi_data.IocPg4Sz = iocpage4sz;
4908 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4909 ioc->spi_data.pIocPg4 = NULL;
4910 ioc->alloc_total -= iocpage4sz;
4915 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4919 ConfigPageHeader_t header;
4920 dma_addr_t ioc1_dma;
4924 /* Check the Coalescing Timeout in IOC Page 1
4926 header.PageVersion = 0;
4927 header.PageLength = 0;
4928 header.PageNumber = 1;
4929 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4930 cfg.cfghdr.hdr = &header;
4933 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4936 if (mpt_config(ioc, &cfg) != 0)
4939 if (header.PageLength == 0)
4942 /* Read Header good, alloc memory
4944 iocpage1sz = header.PageLength * 4;
4945 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4949 /* Read the Page and check coalescing timeout
4951 cfg.physAddr = ioc1_dma;
4952 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4953 if (mpt_config(ioc, &cfg) == 0) {
4955 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4956 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4957 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4959 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4962 if (tmp > MPT_COALESCING_TIMEOUT) {
4963 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4965 /* Write NVRAM and current
4968 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4969 if (mpt_config(ioc, &cfg) == 0) {
4970 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4971 ioc->name, MPT_COALESCING_TIMEOUT));
4973 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4974 if (mpt_config(ioc, &cfg) == 0) {
4975 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4976 ioc->name, MPT_COALESCING_TIMEOUT));
4978 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4983 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4989 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4993 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4998 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5000 * SendEventNotification - Send EventNotification (on or off) request
5002 * @ioc: Pointer to MPT_ADAPTER structure
5003 * @EvSwitch: Event switch flags
5006 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5008 EventNotification_t *evnp;
5010 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5012 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5016 memset(evnp, 0, sizeof(*evnp));
5018 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5020 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5021 evnp->ChainOffset = 0;
5023 evnp->Switch = EvSwitch;
5025 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5032 * SendEventAck - Send EventAck request to MPT adapter.
5033 * @ioc: Pointer to MPT_ADAPTER structure
5034 * @evnp: Pointer to original EventNotification request
5037 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5041 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5042 dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5043 ioc->name,__FUNCTION__));
5047 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5049 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5050 pAck->ChainOffset = 0;
5051 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5053 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5054 pAck->Event = evnp->Event;
5055 pAck->EventContext = evnp->EventContext;
5057 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5062 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5064 * mpt_config - Generic function to issue config message
5065 * @ioc - Pointer to an adapter structure
5066 * @cfg - Pointer to a configuration structure. Struct contains
5067 * action, page address, direction, physical address
5068 * and pointer to a configuration page header
5069 * Page header is updated.
5071 * Returns 0 for success
5072 * -EPERM if not allowed due to ISR context
5073 * -EAGAIN if no msg frames currently available
5074 * -EFAULT for non-successful reply or no reply (timeout)
5077 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5080 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5082 unsigned long flags;
5087 /* Prevent calling wait_event() (below), if caller happens
5088 * to be in ISR context, because that is fatal!
5090 in_isr = in_interrupt();
5092 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5097 /* Get and Populate a free Frame
5099 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5100 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5104 pReq = (Config_t *)mf;
5105 pReq->Action = pCfg->action;
5107 pReq->ChainOffset = 0;
5108 pReq->Function = MPI_FUNCTION_CONFIG;
5110 /* Assume page type is not extended and clear "reserved" fields. */
5111 pReq->ExtPageLength = 0;
5112 pReq->ExtPageType = 0;
5115 for (ii=0; ii < 8; ii++)
5116 pReq->Reserved2[ii] = 0;
5118 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5119 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5120 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5121 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5123 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5124 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5125 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5126 pReq->ExtPageType = pExtHdr->ExtPageType;
5127 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5129 /* Page Length must be treated as a reserved field for the extended header. */
5130 pReq->Header.PageLength = 0;
5133 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5135 /* Add a SGE to the config request.
5138 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5140 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5142 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5143 flagsLength |= pExtHdr->ExtPageLength * 4;
5145 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5146 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5149 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5151 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5152 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5155 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5157 /* Append pCfg pointer to end of mf
5159 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5161 /* Initalize the timer
5163 init_timer(&pCfg->timer);
5164 pCfg->timer.data = (unsigned long) ioc;
5165 pCfg->timer.function = mpt_timer_expired;
5166 pCfg->wait_done = 0;
5168 /* Set the timer; ensure 10 second minimum */
5169 if (pCfg->timeout < 10)
5170 pCfg->timer.expires = jiffies + HZ*10;
5172 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5174 /* Add to end of Q, set timer and then issue this command */
5175 spin_lock_irqsave(&ioc->FreeQlock, flags);
5176 list_add_tail(&pCfg->linkage, &ioc->configQ);
5177 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5179 add_timer(&pCfg->timer);
5180 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5181 wait_event(mpt_waitq, pCfg->wait_done);
5183 /* mf has been freed - do not access */
5190 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5192 * mpt_timer_expired - Call back for timer process.
5193 * Used only internal config functionality.
5194 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5197 mpt_timer_expired(unsigned long data)
5199 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5201 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5203 /* Perform a FW reload */
5204 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5205 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5207 /* No more processing.
5208 * Hard reset clean-up will wake up
5209 * process and free all resources.
5211 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5216 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5218 * mpt_ioc_reset - Base cleanup for hard reset
5219 * @ioc: Pointer to the adapter structure
5220 * @reset_phase: Indicates pre- or post-reset functionality
5222 * Remark: Free's resources with internally generated commands.
5225 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5228 unsigned long flags;
5230 dprintk((KERN_WARNING MYNAM
5231 ": IOC %s_reset routed to MPT base driver!\n",
5232 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5233 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5235 if (reset_phase == MPT_IOC_SETUP_RESET) {
5237 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5238 /* If the internal config Q is not empty -
5239 * delete timer. MF resources will be freed when
5240 * the FIFO's are primed.
5242 spin_lock_irqsave(&ioc->FreeQlock, flags);
5243 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5244 del_timer(&pCfg->timer);
5245 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5250 /* Search the configQ for internal commands.
5251 * Flush the Q, and wake up all suspended threads.
5253 spin_lock_irqsave(&ioc->FreeQlock, flags);
5254 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5255 list_del(&pCfg->linkage);
5257 pCfg->status = MPT_CONFIG_ERROR;
5258 pCfg->wait_done = 1;
5259 wake_up(&mpt_waitq);
5261 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5264 return 1; /* currently means nothing really */
5268 #ifdef CONFIG_PROC_FS /* { */
5269 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5271 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5273 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5275 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5277 * Returns 0 for success, non-zero for failure.
5280 procmpt_create(void)
5282 struct proc_dir_entry *ent;
5284 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5285 if (mpt_proc_root_dir == NULL)
5288 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5290 ent->read_proc = procmpt_summary_read;
5292 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5294 ent->read_proc = procmpt_version_read;
5299 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5301 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5303 * Returns 0 for success, non-zero for failure.
5306 procmpt_destroy(void)
5308 remove_proc_entry("version", mpt_proc_root_dir);
5309 remove_proc_entry("summary", mpt_proc_root_dir);
5310 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5313 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5315 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5316 * or from /proc/mpt/iocN/summary.
5317 * @buf: Pointer to area to write information
5318 * @start: Pointer to start pointer
5319 * @offset: Offset to start writing
5321 * @eof: Pointer to EOF integer
5324 * Returns number of characters written to process performing the read.
5327 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5337 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5341 list_for_each_entry(ioc, &ioc_list, list) {
5344 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5347 if ((out-buf) >= request)
5354 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5357 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5359 * procmpt_version_read - Handle read request from /proc/mpt/version.
5360 * @buf: Pointer to area to write information
5361 * @start: Pointer to start pointer
5362 * @offset: Offset to start writing
5364 * @eof: Pointer to EOF integer
5367 * Returns number of characters written to process performing the read.
5370 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5373 int scsi, fc, sas, lan, ctl, targ, dmp;
5377 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5378 len += sprintf(buf+len, " Fusion MPT base driver\n");
5380 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5381 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5383 if (MptCallbacks[ii]) {
5384 switch (MptDriverClass[ii]) {
5386 if (!scsi++) drvname = "SPI host";
5389 if (!fc++) drvname = "FC host";
5392 if (!sas++) drvname = "SAS host";
5395 if (!lan++) drvname = "LAN";
5398 if (!targ++) drvname = "SCSI target";
5401 if (!ctl++) drvname = "ioctl";
5406 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5410 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5413 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5415 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5416 * @buf: Pointer to area to write information
5417 * @start: Pointer to start pointer
5418 * @offset: Offset to start writing
5420 * @eof: Pointer to EOF integer
5423 * Returns number of characters written to process performing the read.
5426 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5428 MPT_ADAPTER *ioc = data;
5434 mpt_get_fw_exp_ver(expVer, ioc);
5436 len = sprintf(buf, "%s:", ioc->name);
5437 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5438 len += sprintf(buf+len, " (f/w download boot flag set)");
5439 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5440 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5442 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5443 ioc->facts.ProductID,
5445 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5446 if (ioc->facts.FWImageSize)
5447 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5448 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5449 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5450 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5452 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5453 ioc->facts.CurrentHostMfaHighAddr);
5454 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5455 ioc->facts.CurrentSenseBufferHighAddr);
5457 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5458 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5460 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5461 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5463 * Rounding UP to nearest 4-kB boundary here...
5465 sz = (ioc->req_sz * ioc->req_depth) + 128;
5466 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5467 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5468 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5469 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5470 4*ioc->facts.RequestFrameSize,
5471 ioc->facts.GlobalCredits);
5473 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5474 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5475 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5476 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5477 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5478 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5479 ioc->facts.CurReplyFrameSize,
5480 ioc->facts.ReplyQueueDepth);
5482 len += sprintf(buf+len, " MaxDevices = %d\n",
5483 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5484 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5487 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5488 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5490 ioc->facts.NumberOfPorts);
5491 if (ioc->bus_type == FC) {
5492 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5493 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5494 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5495 a[5], a[4], a[3], a[2], a[1], a[0]);
5497 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5498 ioc->fc_port_page0[p].WWNN.High,
5499 ioc->fc_port_page0[p].WWNN.Low,
5500 ioc->fc_port_page0[p].WWPN.High,
5501 ioc->fc_port_page0[p].WWPN.Low);
5505 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5508 #endif /* CONFIG_PROC_FS } */
5510 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5512 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5515 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5516 sprintf(buf, " (Exp %02d%02d)",
5517 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5518 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5521 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5522 strcat(buf, " [MDBG]");
5526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5528 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5529 * @ioc: Pointer to MPT_ADAPTER structure
5530 * @buffer: Pointer to buffer where IOC summary info should be written
5531 * @size: Pointer to number of bytes we wrote (set by this routine)
5532 * @len: Offset at which to start writing in buffer
5533 * @showlan: Display LAN stuff?
5535 * This routine writes (english readable) ASCII text, which represents
5536 * a summary of IOC information, to a buffer.
5539 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5544 mpt_get_fw_exp_ver(expVer, ioc);
5547 * Shorter summary of attached ioc's...
5549 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5552 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5553 ioc->facts.FWVersion.Word,
5555 ioc->facts.NumberOfPorts,
5558 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5559 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5560 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5561 a[5], a[4], a[3], a[2], a[1], a[0]);
5564 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5567 y += sprintf(buffer+len+y, " (disabled)");
5569 y += sprintf(buffer+len+y, "\n");
5574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5578 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5580 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5581 * Management call based on input arg values. If TaskMgmt fails,
5582 * return associated SCSI request.
5583 * @ioc: Pointer to MPT_ADAPTER structure
5584 * @sleepFlag: Indicates if sleep or schedule must be called.
5586 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5587 * or a non-interrupt thread. In the former, must not call schedule().
5589 * Remark: A return of -1 is a FATAL error case, as it means a
5590 * FW reload/initialization failed.
5592 * Returns 0 for SUCCESS or -1 if FAILED.
5595 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5598 unsigned long flags;
5600 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5602 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5603 printk("MF count 0x%x !\n", ioc->mfcnt);
5606 /* Reset the adapter. Prevent more than 1 call to
5607 * mpt_do_ioc_recovery at any instant in time.
5609 spin_lock_irqsave(&ioc->diagLock, flags);
5610 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5611 spin_unlock_irqrestore(&ioc->diagLock, flags);
5614 ioc->diagPending = 1;
5616 spin_unlock_irqrestore(&ioc->diagLock, flags);
5618 /* FIXME: If do_ioc_recovery fails, repeat....
5621 /* The SCSI driver needs to adjust timeouts on all current
5622 * commands prior to the diagnostic reset being issued.
5623 * Prevents timeouts occurring during a diagnostic reset...very bad.
5624 * For all other protocol drivers, this is a no-op.
5630 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5631 if (MptResetHandlers[ii]) {
5632 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5634 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5636 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5637 ioc->name, ioc->alt_ioc->name, ii));
5638 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5644 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5645 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5650 ioc->alt_ioc->reload_fw = 0;
5652 spin_lock_irqsave(&ioc->diagLock, flags);
5653 ioc->diagPending = 0;
5655 ioc->alt_ioc->diagPending = 0;
5656 spin_unlock_irqrestore(&ioc->diagLock, flags);
5658 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5663 # define EVENT_DESCR_STR_SZ 100
5665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5667 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5672 case MPI_EVENT_NONE:
5675 case MPI_EVENT_LOG_DATA:
5678 case MPI_EVENT_STATE_CHANGE:
5679 ds = "State Change";
5681 case MPI_EVENT_UNIT_ATTENTION:
5682 ds = "Unit Attention";
5684 case MPI_EVENT_IOC_BUS_RESET:
5685 ds = "IOC Bus Reset";
5687 case MPI_EVENT_EXT_BUS_RESET:
5688 ds = "External Bus Reset";
5690 case MPI_EVENT_RESCAN:
5691 ds = "Bus Rescan Event";
5692 /* Ok, do we need to do anything here? As far as
5693 I can tell, this is when a new device gets added
5696 case MPI_EVENT_LINK_STATUS_CHANGE:
5697 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5698 ds = "Link Status(FAILURE) Change";
5700 ds = "Link Status(ACTIVE) Change";
5702 case MPI_EVENT_LOOP_STATE_CHANGE:
5703 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5704 ds = "Loop State(LIP) Change";
5705 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5706 ds = "Loop State(LPE) Change"; /* ??? */
5708 ds = "Loop State(LPB) Change"; /* ??? */
5710 case MPI_EVENT_LOGOUT:
5713 case MPI_EVENT_EVENT_CHANGE:
5719 case MPI_EVENT_INTEGRATED_RAID:
5721 u8 ReasonCode = (u8)(evData0 >> 16);
5722 switch (ReasonCode) {
5723 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5724 ds = "Integrated Raid: Volume Created";
5726 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5727 ds = "Integrated Raid: Volume Deleted";
5729 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5730 ds = "Integrated Raid: Volume Settings Changed";
5732 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5733 ds = "Integrated Raid: Volume Status Changed";
5735 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5736 ds = "Integrated Raid: Volume Physdisk Changed";
5738 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5739 ds = "Integrated Raid: Physdisk Created";
5741 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5742 ds = "Integrated Raid: Physdisk Deleted";
5744 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5745 ds = "Integrated Raid: Physdisk Settings Changed";
5747 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5748 ds = "Integrated Raid: Physdisk Status Changed";
5750 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5751 ds = "Integrated Raid: Domain Validation Needed";
5753 case MPI_EVENT_RAID_RC_SMART_DATA :
5754 ds = "Integrated Raid; Smart Data";
5756 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5757 ds = "Integrated Raid: Replace Action Started";
5760 ds = "Integrated Raid";
5765 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5766 ds = "SCSI Device Status Change";
5768 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5770 u8 id = (u8)(evData0);
5771 u8 ReasonCode = (u8)(evData0 >> 16);
5772 switch (ReasonCode) {
5773 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5774 snprintf(evStr, EVENT_DESCR_STR_SZ,
5775 "SAS Device Status Change: Added: id=%d", id);
5777 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5778 snprintf(evStr, EVENT_DESCR_STR_SZ,
5779 "SAS Device Status Change: Deleted: id=%d", id);
5781 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5782 snprintf(evStr, EVENT_DESCR_STR_SZ,
5783 "SAS Device Status Change: SMART Data: id=%d",
5786 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5787 snprintf(evStr, EVENT_DESCR_STR_SZ,
5788 "SAS Device Status Change: No Persistancy: id=%d", id);
5790 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5791 snprintf(evStr, EVENT_DESCR_STR_SZ,
5792 "SAS Device Status Change: Internal Device Reset : id=%d", id);
5794 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5795 snprintf(evStr, EVENT_DESCR_STR_SZ,
5796 "SAS Device Status Change: Internal Task Abort : id=%d", id);
5798 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5799 snprintf(evStr, EVENT_DESCR_STR_SZ,
5800 "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
5802 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5803 snprintf(evStr, EVENT_DESCR_STR_SZ,
5804 "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
5806 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5807 snprintf(evStr, EVENT_DESCR_STR_SZ,
5808 "SAS Device Status Change: Internal Query Task : id=%d", id);
5811 snprintf(evStr, EVENT_DESCR_STR_SZ,
5812 "SAS Device Status Change: Unknown: id=%d", id);
5817 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5818 ds = "Bus Timer Expired";
5820 case MPI_EVENT_QUEUE_FULL:
5823 case MPI_EVENT_SAS_SES:
5824 ds = "SAS SES Event";
5826 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5827 ds = "Persistent Table Full";
5829 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5831 u8 LinkRates = (u8)(evData0 >> 8);
5832 u8 PhyNumber = (u8)(evData0);
5833 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5834 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5835 switch (LinkRates) {
5836 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5837 snprintf(evStr, EVENT_DESCR_STR_SZ,
5838 "SAS PHY Link Status: Phy=%d:"
5839 " Rate Unknown",PhyNumber);
5841 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5842 snprintf(evStr, EVENT_DESCR_STR_SZ,
5843 "SAS PHY Link Status: Phy=%d:"
5844 " Phy Disabled",PhyNumber);
5846 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5847 snprintf(evStr, EVENT_DESCR_STR_SZ,
5848 "SAS PHY Link Status: Phy=%d:"
5849 " Failed Speed Nego",PhyNumber);
5851 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5852 snprintf(evStr, EVENT_DESCR_STR_SZ,
5853 "SAS PHY Link Status: Phy=%d:"
5854 " Sata OOB Completed",PhyNumber);
5856 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5857 snprintf(evStr, EVENT_DESCR_STR_SZ,
5858 "SAS PHY Link Status: Phy=%d:"
5859 " Rate 1.5 Gbps",PhyNumber);
5861 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5862 snprintf(evStr, EVENT_DESCR_STR_SZ,
5863 "SAS PHY Link Status: Phy=%d:"
5864 " Rate 3.0 Gpbs",PhyNumber);
5867 snprintf(evStr, EVENT_DESCR_STR_SZ,
5868 "SAS PHY Link Status: Phy=%d", PhyNumber);
5873 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5874 ds = "SAS Discovery Error";
5876 case MPI_EVENT_IR_RESYNC_UPDATE:
5878 u8 resync_complete = (u8)(evData0 >> 16);
5879 snprintf(evStr, EVENT_DESCR_STR_SZ,
5880 "IR Resync Update: Complete = %d:",resync_complete);
5885 u8 ReasonCode = (u8)(evData0 >> 16);
5886 switch (ReasonCode) {
5887 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5888 ds = "IR2: LD State Changed";
5890 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5891 ds = "IR2: PD State Changed";
5893 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5894 ds = "IR2: Bad Block Table Full";
5896 case MPI_EVENT_IR2_RC_PD_INSERTED:
5897 ds = "IR2: PD Inserted";
5899 case MPI_EVENT_IR2_RC_PD_REMOVED:
5900 ds = "IR2: PD Removed";
5902 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5903 ds = "IR2: Foreign CFG Detected";
5905 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5906 ds = "IR2: Rebuild Medium Error";
5914 case MPI_EVENT_SAS_DISCOVERY:
5917 ds = "SAS Discovery: Start";
5919 ds = "SAS Discovery: Stop";
5922 case MPI_EVENT_LOG_ENTRY_ADDED:
5923 ds = "SAS Log Entry Added";
5927 * MPT base "custom" events may be added here...
5934 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
5937 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5939 * ProcessEventNotification - Route a received EventNotificationReply to
5940 * all currently regeistered event handlers.
5941 * @ioc: Pointer to MPT_ADAPTER structure
5942 * @pEventReply: Pointer to EventNotification reply frame
5943 * @evHandlers: Pointer to integer, number of event handlers
5945 * Returns sum of event handlers return values.
5948 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5956 char evStr[EVENT_DESCR_STR_SZ];
5960 * Do platform normalization of values
5962 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5963 // evCtx = le32_to_cpu(pEventReply->EventContext);
5964 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5966 evData0 = le32_to_cpu(pEventReply->Data[0]);
5969 EventDescriptionStr(event, evData0, evStr);
5970 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
5975 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
5976 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5977 for (ii = 0; ii < evDataLen; ii++)
5978 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5983 * Do general / base driver event processing
5986 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5988 u8 evState = evData0 & 0xFF;
5990 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5992 /* Update EventState field in cached IocFacts */
5993 if (ioc->facts.Function) {
5994 ioc->facts.EventState = evState;
5998 case MPI_EVENT_INTEGRATED_RAID:
5999 mptbase_raid_process_event_data(ioc,
6000 (MpiEventDataRaid_t *)pEventReply->Data);
6007 * Should this event be logged? Events are written sequentially.
6008 * When buffer is full, start again at the top.
6010 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6013 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6015 ioc->events[idx].event = event;
6016 ioc->events[idx].eventContext = ioc->eventContext;
6018 for (ii = 0; ii < 2; ii++) {
6020 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6022 ioc->events[idx].data[ii] = 0;
6025 ioc->eventContext++;
6030 * Call each currently registered protocol event handler.
6032 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6033 if (MptEvHandlers[ii]) {
6034 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6036 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6040 /* FIXME? Examine results here? */
6043 * If needed, send (a single) EventAck.
6045 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6046 devtverboseprintk((MYIOC_s_WARN_FMT
6047 "EventAck required\n",ioc->name));
6048 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6049 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6054 *evHandlers = handlers;
6058 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6060 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6061 * @ioc: Pointer to MPT_ADAPTER structure
6062 * @log_info: U32 LogInfo reply word from the IOC
6064 * Refer to lsi/mpi_log_fc.h.
6067 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6069 static char *subcl_str[8] = {
6070 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6071 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6073 u8 subcl = (log_info >> 24) & 0x7;
6075 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6076 ioc->name, log_info, subcl_str[subcl]);
6079 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6081 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6082 * @ioc: Pointer to MPT_ADAPTER structure
6083 * @mr: Pointer to MPT reply frame
6084 * @log_info: U32 LogInfo word from the IOC
6086 * Refer to lsi/sp_log.h.
6089 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6091 u32 info = log_info & 0x00FF0000;
6092 char *desc = "unknown";
6096 desc = "bug! MID not found";
6097 if (ioc->reload_fw == 0)
6102 desc = "Parity Error";
6106 desc = "ASYNC Outbound Overrun";
6110 desc = "SYNC Offset Error";
6118 desc = "Msg In Overflow";
6126 desc = "Outbound DMA Overrun";
6130 desc = "Task Management";
6134 desc = "Device Problem";
6138 desc = "Invalid Phase Change";
6142 desc = "Untagged Table Size";
6147 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6150 /* strings for sas loginfo */
6151 static char *originator_str[] = {
6156 static char *iop_code_str[] = {
6158 "Invalid SAS Address", /* 01h */
6160 "Invalid Page", /* 03h */
6161 "Diag Message Error", /* 04h */
6162 "Task Terminated", /* 05h */
6163 "Enclosure Management", /* 06h */
6164 "Target Mode" /* 07h */
6166 static char *pl_code_str[] = {
6168 "Open Failure", /* 01h */
6169 "Invalid Scatter Gather List", /* 02h */
6170 "Wrong Relative Offset or Frame Length", /* 03h */
6171 "Frame Transfer Error", /* 04h */
6172 "Transmit Frame Connected Low", /* 05h */
6173 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6174 "SATA Read Log Receive Data Error", /* 07h */
6175 "SATA NCQ Fail All Commands After Error", /* 08h */
6176 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6177 "Receive Frame Invalid Message", /* 0Ah */
6178 "Receive Context Message Valid Error", /* 0Bh */
6179 "Receive Frame Current Frame Error", /* 0Ch */
6180 "SATA Link Down", /* 0Dh */
6181 "Discovery SATA Init W IOS", /* 0Eh */
6182 "Config Invalid Page", /* 0Fh */
6183 "Discovery SATA Init Timeout", /* 10h */
6186 "IO Not Yet Executed", /* 13h */
6187 "IO Executed", /* 14h */
6188 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6189 "Open Transmit DMA Abort", /* 16h */
6190 "IO Device Missing Delay Retry", /* 17h */
6199 "Enclosure Management" /* 20h */
6202 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6204 * mpt_sas_log_info - Log information returned from SAS IOC.
6205 * @ioc: Pointer to MPT_ADAPTER structure
6206 * @log_info: U32 LogInfo reply word from the IOC
6208 * Refer to lsi/mpi_log_sas.h.
6211 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6213 union loginfo_type {
6222 union loginfo_type sas_loginfo;
6223 char *code_desc = NULL;
6225 sas_loginfo.loginfo = log_info;
6226 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6227 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6229 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6230 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6231 code_desc = iop_code_str[sas_loginfo.dw.code];
6232 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6233 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6234 code_desc = pl_code_str[sas_loginfo.dw.code];
6237 if (code_desc != NULL)
6238 printk(MYIOC_s_INFO_FMT
6239 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6240 " SubCode(0x%04x)\n",
6243 originator_str[sas_loginfo.dw.originator],
6245 sas_loginfo.dw.subcode);
6247 printk(MYIOC_s_INFO_FMT
6248 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6249 " SubCode(0x%04x)\n",
6252 originator_str[sas_loginfo.dw.originator],
6253 sas_loginfo.dw.code,
6254 sas_loginfo.dw.subcode);
6257 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6259 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6260 * @ioc: Pointer to MPT_ADAPTER structure
6261 * @ioc_status: U32 IOCStatus word from IOC
6262 * @mf: Pointer to MPT request frame
6264 * Refer to lsi/mpi.h.
6267 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6269 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6273 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6274 desc = "Invalid Function";
6277 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6281 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6282 desc = "Invalid SGL";
6285 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6286 desc = "Internal Error";
6289 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6293 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6294 desc = "Insufficient Resources";
6297 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6298 desc = "Invalid Field";
6301 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6302 desc = "Invalid State";
6305 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6306 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6307 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6308 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6309 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6310 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6311 /* No message for Config IOCStatus values */
6314 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6315 /* No message for recovered error
6316 desc = "SCSI Recovered Error";
6320 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6321 desc = "SCSI Invalid Bus";
6324 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6325 desc = "SCSI Invalid TargetID";
6328 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6330 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6331 U8 cdb = pScsiReq->CDB[0];
6332 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6333 desc = "SCSI Device Not There";
6338 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6339 desc = "SCSI Data Overrun";
6342 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6343 /* This error is checked in scsi_io_done(). Skip.
6344 desc = "SCSI Data Underrun";
6348 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6349 desc = "SCSI I/O Data Error";
6352 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6353 desc = "SCSI Protocol Error";
6356 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6357 desc = "SCSI Task Terminated";
6360 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6361 desc = "SCSI Residual Mismatch";
6364 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6365 desc = "SCSI Task Management Failed";
6368 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6369 desc = "SCSI IOC Terminated";
6372 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6373 desc = "SCSI Ext Terminated";
6381 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6384 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6385 EXPORT_SYMBOL(mpt_attach);
6386 EXPORT_SYMBOL(mpt_detach);
6388 EXPORT_SYMBOL(mpt_resume);
6389 EXPORT_SYMBOL(mpt_suspend);
6391 EXPORT_SYMBOL(ioc_list);
6392 EXPORT_SYMBOL(mpt_proc_root_dir);
6393 EXPORT_SYMBOL(mpt_register);
6394 EXPORT_SYMBOL(mpt_deregister);
6395 EXPORT_SYMBOL(mpt_event_register);
6396 EXPORT_SYMBOL(mpt_event_deregister);
6397 EXPORT_SYMBOL(mpt_reset_register);
6398 EXPORT_SYMBOL(mpt_reset_deregister);
6399 EXPORT_SYMBOL(mpt_device_driver_register);
6400 EXPORT_SYMBOL(mpt_device_driver_deregister);
6401 EXPORT_SYMBOL(mpt_get_msg_frame);
6402 EXPORT_SYMBOL(mpt_put_msg_frame);
6403 EXPORT_SYMBOL(mpt_free_msg_frame);
6404 EXPORT_SYMBOL(mpt_add_sge);
6405 EXPORT_SYMBOL(mpt_send_handshake_request);
6406 EXPORT_SYMBOL(mpt_verify_adapter);
6407 EXPORT_SYMBOL(mpt_GetIocState);
6408 EXPORT_SYMBOL(mpt_print_ioc_summary);
6409 EXPORT_SYMBOL(mpt_lan_index);
6410 EXPORT_SYMBOL(mpt_stm_index);
6411 EXPORT_SYMBOL(mpt_HardResetHandler);
6412 EXPORT_SYMBOL(mpt_config);
6413 EXPORT_SYMBOL(mpt_findImVolumes);
6414 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6415 EXPORT_SYMBOL(mpt_free_fw_memory);
6416 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6418 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6420 * fusion_init - Fusion MPT base driver initialization routine.
6422 * Returns 0 for success, non-zero for failure.
6429 show_mptmod_ver(my_NAME, my_VERSION);
6430 printk(KERN_INFO COPYRIGHT "\n");
6432 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6433 MptCallbacks[i] = NULL;
6434 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6435 MptEvHandlers[i] = NULL;
6436 MptResetHandlers[i] = NULL;
6439 /* Register ourselves (mptbase) in order to facilitate
6440 * EventNotification handling.
6442 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6444 /* Register for hard reset handling callbacks.
6446 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6447 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6452 #ifdef CONFIG_PROC_FS
6453 (void) procmpt_create();
6458 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6460 * fusion_exit - Perform driver unload cleanup.
6462 * This routine frees all resources associated with each MPT adapter
6463 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6469 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6471 mpt_reset_deregister(mpt_base_index);
6473 #ifdef CONFIG_PROC_FS
6478 module_init(fusion_init);
6479 module_exit(fusion_exit);