2 * linux/drivers/message/fusion/mptbase.c
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
5 * For use with LSI Logic PCI chip/adapter(s)
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2005 LSI Logic Corporation
9 * (mailto:mpt_linux_developer@lsil.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
49 #include <linux/config.h>
50 #include <linux/kernel.h>
51 #include <linux/module.h>
52 #include <linux/errno.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/types.h>
56 #include <linux/pci.h>
57 #include <linux/kdev_t.h>
58 #include <linux/blkdev.h>
59 #include <linux/delay.h>
60 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
61 #include <linux/dma-mapping.h>
67 #include <asm/irq.h> /* needed for __irq_itoa() proto */
72 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
73 #define my_NAME "Fusion MPT base driver"
74 #define my_VERSION MPT_LINUX_VERSION_COMMON
75 #define MYNAM "mptbase"
77 MODULE_AUTHOR(MODULEAUTHOR);
78 MODULE_DESCRIPTION(my_NAME);
79 MODULE_LICENSE("GPL");
80 MODULE_VERSION(MPT_LINUX_VERSION_COMMON);
85 static int mpt_msi_enable;
86 module_param(mpt_msi_enable, int, 0);
87 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
90 static int mfcounter = 0;
91 #define PRINT_MF_COUNT 20000
94 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
98 int mpt_lan_index = -1;
99 int mpt_stm_index = -1;
101 struct proc_dir_entry *mpt_proc_root_dir;
103 #define WHOINIT_UNKNOWN 0xAA
105 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
109 /* Adapter link list */
111 /* Callback lookup table */
112 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
113 /* Protocol driver class lookup table */
114 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
115 /* Event handler lookup table */
116 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
117 /* Reset handler lookup table */
118 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
119 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
121 static int mpt_base_index = -1;
122 static int last_drv_idx = -1;
124 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
130 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
131 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
132 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
133 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
135 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
136 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
137 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
138 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
140 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
141 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
142 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
143 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
144 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
145 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
146 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
147 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
148 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
149 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
150 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
151 static int PrimeIocFifos(MPT_ADAPTER *ioc);
152 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
153 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
154 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
155 static int GetLanConfigPages(MPT_ADAPTER *ioc);
156 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
157 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
158 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
159 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
160 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
161 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
162 static void mpt_timer_expired(unsigned long data);
163 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
164 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
165 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
166 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
168 #ifdef CONFIG_PROC_FS
169 static int procmpt_summary_read(char *buf, char **start, off_t offset,
170 int request, int *eof, void *data);
171 static int procmpt_version_read(char *buf, char **start, off_t offset,
172 int request, int *eof, void *data);
173 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
174 int request, int *eof, void *data);
176 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
178 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
179 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
180 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
181 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
182 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
183 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
184 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
186 /* module entry point */
187 static int __init fusion_init (void);
188 static void __exit fusion_exit (void);
190 #define CHIPREG_READ32(addr) readl_relaxed(addr)
191 #define CHIPREG_READ32_dmasync(addr) readl(addr)
192 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
193 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
194 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
197 pci_disable_io_access(struct pci_dev *pdev)
201 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
203 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
207 pci_enable_io_access(struct pci_dev *pdev)
211 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
213 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
217 * Process turbo (context) reply...
220 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
222 MPT_FRAME_HDR *mf = NULL;
223 MPT_FRAME_HDR *mr = NULL;
227 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
230 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
231 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
232 req_idx = pa & 0x0000FFFF;
233 cb_idx = (pa & 0x00FF0000) >> 16;
234 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
236 case MPI_CONTEXT_REPLY_TYPE_LAN:
237 cb_idx = mpt_lan_index;
239 * Blind set of mf to NULL here was fatal
240 * after lan_reply says "freeme"
241 * Fix sort of combined with an optimization here;
242 * added explicit check for case where lan_reply
243 * was just returning 1 and doing nothing else.
244 * For this case skip the callback, but set up
245 * proper mf value first here:-)
247 if ((pa & 0x58000000) == 0x58000000) {
248 req_idx = pa & 0x0000FFFF;
249 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
250 mpt_free_msg_frame(ioc, mf);
255 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
257 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
258 cb_idx = mpt_stm_index;
259 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
266 /* Check for (valid) IO callback! */
267 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
268 MptCallbacks[cb_idx] == NULL) {
269 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
270 __FUNCTION__, ioc->name, cb_idx);
274 if (MptCallbacks[cb_idx](ioc, mf, mr))
275 mpt_free_msg_frame(ioc, mf);
281 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
292 /* non-TURBO reply! Hmmm, something may be up...
293 * Newest turbo reply mechanism; get address
294 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
297 /* Map DMA address of reply header to cpu address.
298 * pa is 32 bits - but the dma address may be 32 or 64 bits
299 * get offset based only only the low addresses
302 reply_dma_low = (pa <<= 1);
303 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
304 (reply_dma_low - ioc->reply_frames_low_dma));
306 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
307 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
308 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
310 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
311 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
312 DBG_DUMP_REPLY_FRAME(mr)
314 /* Check/log IOC log info
316 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
317 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
318 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
319 if (ioc->bus_type == FC)
320 mpt_fc_log_info(ioc, log_info);
321 else if (ioc->bus_type == SPI)
322 mpt_spi_log_info(ioc, log_info);
323 else if (ioc->bus_type == SAS)
324 mpt_sas_log_info(ioc, log_info);
326 if (ioc_stat & MPI_IOCSTATUS_MASK) {
327 if (ioc->bus_type == SPI &&
328 cb_idx != mpt_stm_index &&
329 cb_idx != mpt_lan_index)
330 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
334 /* Check for (valid) IO callback! */
335 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
336 MptCallbacks[cb_idx] == NULL) {
337 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
338 __FUNCTION__, ioc->name, cb_idx);
343 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
346 /* Flush (non-TURBO) reply with a WRITE! */
347 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
350 mpt_free_msg_frame(ioc, mf);
354 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
356 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
357 * @irq: irq number (not used)
358 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
359 * @r: pt_regs pointer (not used)
361 * This routine is registered via the request_irq() kernel API call,
362 * and handles all interrupts generated from a specific MPT adapter
363 * (also referred to as a IO Controller or IOC).
364 * This routine must clear the interrupt from the adapter and does
365 * so by reading the reply FIFO. Multiple replies may be processed
366 * per single call to this routine.
368 * This routine handles register-level access of the adapter but
369 * dispatches (calls) a protocol-specific callback routine to handle
370 * the protocol-specific details of the MPT request completion.
373 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
375 MPT_ADAPTER *ioc = bus_id;
379 * Drain the reply FIFO!
382 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
383 if (pa == 0xFFFFFFFF)
385 else if (pa & MPI_ADDRESS_REPLY_A_BIT)
388 mpt_turbo_reply(ioc, pa);
394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
396 * mpt_base_reply - MPT base driver's callback routine; all base driver
397 * "internal" request/reply processing is routed here.
398 * Currently used for EventNotification and EventAck handling.
399 * @ioc: Pointer to MPT_ADAPTER structure
400 * @mf: Pointer to original MPT request frame
401 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
403 * Returns 1 indicating original alloc'd request frame ptr
404 * should be freed, or 0 if it shouldn't.
407 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
412 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
414 #if defined(MPT_DEBUG_MSG_FRAME)
415 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
416 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
417 DBG_DUMP_REQUEST_FRAME_HDR(mf)
421 func = reply->u.hdr.Function;
422 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
425 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
426 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
430 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
431 if (results != evHandlers) {
432 /* CHECKME! Any special handling needed here? */
433 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
434 ioc->name, evHandlers, results));
438 * Hmmm... It seems that EventNotificationReply is an exception
439 * to the rule of one reply per request.
441 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
443 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
444 ioc->name, pEvReply));
446 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
447 ioc->name, pEvReply));
450 #ifdef CONFIG_PROC_FS
451 // LogEvent(ioc, pEvReply);
454 } else if (func == MPI_FUNCTION_EVENT_ACK) {
455 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
457 } else if (func == MPI_FUNCTION_CONFIG) {
461 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
462 ioc->name, mf, reply));
464 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
467 /* disable timer and remove from linked list */
468 del_timer(&pCfg->timer);
470 spin_lock_irqsave(&ioc->FreeQlock, flags);
471 list_del(&pCfg->linkage);
472 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
475 * If IOC Status is SUCCESS, save the header
476 * and set the status code to GOOD.
478 pCfg->status = MPT_CONFIG_ERROR;
480 ConfigReply_t *pReply = (ConfigReply_t *)reply;
483 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
484 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
485 status, le32_to_cpu(pReply->IOCLogInfo)));
487 pCfg->status = status;
488 if (status == MPI_IOCSTATUS_SUCCESS) {
489 if ((pReply->Header.PageType &
490 MPI_CONFIG_PAGETYPE_MASK) ==
491 MPI_CONFIG_PAGETYPE_EXTENDED) {
492 pCfg->cfghdr.ehdr->ExtPageLength =
493 le16_to_cpu(pReply->ExtPageLength);
494 pCfg->cfghdr.ehdr->ExtPageType =
497 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
499 /* If this is a regular header, save PageLength. */
500 /* LMP Do this better so not using a reserved field! */
501 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
502 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
503 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
508 * Wake up the original calling thread
513 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
514 /* we should be always getting a reply frame */
515 memcpy(ioc->persist_reply_frame, reply,
516 min(MPT_DEFAULT_FRAME_SIZE,
517 4*reply->u.reply.MsgLength));
518 del_timer(&ioc->persist_timer);
519 ioc->persist_wait_done = 1;
522 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
527 * Conditionally tell caller to free the original
528 * EventNotification/EventAck/unexpected request frame!
533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
535 * mpt_register - Register protocol-specific main callback handler.
536 * @cbfunc: callback function pointer
537 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
539 * This routine is called by a protocol-specific driver (SCSI host,
540 * LAN, SCSI target) to register it's reply callback routine. Each
541 * protocol-specific driver must do this before it will be able to
542 * use any IOC resources, such as obtaining request frames.
544 * NOTES: The SCSI protocol driver currently calls this routine thrice
545 * in order to register separate callbacks; one for "normal" SCSI IO;
546 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
548 * Returns a positive integer valued "handle" in the
549 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
550 * Any non-positive return value (including zero!) should be considered
551 * an error by the caller.
554 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
561 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
562 * (slot/handle 0 is reserved!)
564 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
565 if (MptCallbacks[i] == NULL) {
566 MptCallbacks[i] = cbfunc;
567 MptDriverClass[i] = dclass;
568 MptEvHandlers[i] = NULL;
577 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
579 * mpt_deregister - Deregister a protocol drivers resources.
580 * @cb_idx: previously registered callback handle
582 * Each protocol-specific driver should call this routine when it's
583 * module is unloaded.
586 mpt_deregister(int cb_idx)
588 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
589 MptCallbacks[cb_idx] = NULL;
590 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
591 MptEvHandlers[cb_idx] = NULL;
597 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
599 * mpt_event_register - Register protocol-specific event callback
601 * @cb_idx: previously registered (via mpt_register) callback handle
602 * @ev_cbfunc: callback function
604 * This routine can be called by one or more protocol-specific drivers
605 * if/when they choose to be notified of MPT events.
607 * Returns 0 for success.
610 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
612 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
615 MptEvHandlers[cb_idx] = ev_cbfunc;
619 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
621 * mpt_event_deregister - Deregister protocol-specific event callback
623 * @cb_idx: previously registered callback handle
625 * Each protocol-specific driver should call this routine
626 * when it does not (or can no longer) handle events,
627 * or when it's module is unloaded.
630 mpt_event_deregister(int cb_idx)
632 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
635 MptEvHandlers[cb_idx] = NULL;
638 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
640 * mpt_reset_register - Register protocol-specific IOC reset handler.
641 * @cb_idx: previously registered (via mpt_register) callback handle
642 * @reset_func: reset function
644 * This routine can be called by one or more protocol-specific drivers
645 * if/when they choose to be notified of IOC resets.
647 * Returns 0 for success.
650 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
652 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
655 MptResetHandlers[cb_idx] = reset_func;
659 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
661 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
662 * @cb_idx: previously registered callback handle
664 * Each protocol-specific driver should call this routine
665 * when it does not (or can no longer) handle IOC reset handling,
666 * or when it's module is unloaded.
669 mpt_reset_deregister(int cb_idx)
671 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
674 MptResetHandlers[cb_idx] = NULL;
677 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
679 * mpt_device_driver_register - Register device driver hooks
682 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
686 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
690 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
692 /* call per pci device probe entry point */
693 list_for_each_entry(ioc, &ioc_list, list) {
694 if(dd_cbfunc->probe) {
695 dd_cbfunc->probe(ioc->pcidev,
696 ioc->pcidev->driver->id_table);
703 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
705 * mpt_device_driver_deregister - DeRegister device driver hooks
708 mpt_device_driver_deregister(int cb_idx)
710 struct mpt_pci_driver *dd_cbfunc;
713 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
716 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
718 list_for_each_entry(ioc, &ioc_list, list) {
719 if (dd_cbfunc->remove)
720 dd_cbfunc->remove(ioc->pcidev);
723 MptDeviceDriverHandlers[cb_idx] = NULL;
727 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
729 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
730 * allocated per MPT adapter.
731 * @handle: Handle of registered MPT protocol driver
732 * @ioc: Pointer to MPT adapter structure
734 * Returns pointer to a MPT request frame or %NULL if none are available
735 * or IOC is not active.
738 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
742 u16 req_idx; /* Request index */
744 /* validate handle and ioc identifier */
748 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
751 /* If interrupts are not attached, do not return a request frame */
755 spin_lock_irqsave(&ioc->FreeQlock, flags);
756 if (!list_empty(&ioc->FreeQ)) {
759 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
760 u.frame.linkage.list);
761 list_del(&mf->u.frame.linkage.list);
762 mf->u.frame.linkage.arg1 = 0;
763 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
764 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
766 req_idx = req_offset / ioc->req_sz;
767 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
768 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
769 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
776 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
780 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
782 if (mfcounter == PRINT_MF_COUNT)
783 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
786 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
787 ioc->name, handle, ioc->id, mf));
791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
793 * mpt_put_msg_frame - Send a protocol specific MPT request frame
795 * @handle: Handle of registered MPT protocol driver
796 * @ioc: Pointer to MPT adapter structure
797 * @mf: Pointer to MPT request frame
799 * This routine posts a MPT request frame to the request post FIFO of a
800 * specific MPT adapter.
803 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
807 u16 req_idx; /* Request index */
809 /* ensure values are reset properly! */
810 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
811 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
813 req_idx = req_offset / ioc->req_sz;
814 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
815 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
817 #ifdef MPT_DEBUG_MSG_FRAME
819 u32 *m = mf->u.frame.hwhdr.__hdr;
822 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
824 n = ioc->req_sz/4 - 1;
827 for (ii=0; ii<=n; ii++) {
828 if (ii && ((ii%8)==0))
829 printk("\n" KERN_INFO " ");
830 printk(" %08x", le32_to_cpu(m[ii]));
836 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
837 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]));
838 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
841 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
843 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
844 * @handle: Handle of registered MPT protocol driver
845 * @ioc: Pointer to MPT adapter structure
846 * @mf: Pointer to MPT request frame
848 * This routine places a MPT request frame back on the MPT adapter's
852 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
856 /* Put Request back on FreeQ! */
857 spin_lock_irqsave(&ioc->FreeQlock, flags);
858 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
859 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
863 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
866 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
868 * mpt_add_sge - Place a simple SGE at address pAddr.
869 * @pAddr: virtual address for SGE
870 * @flagslength: SGE flags and data transfer length
871 * @dma_addr: Physical address
873 * This routine places a MPT request frame back on the MPT adapter's
877 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
879 if (sizeof(dma_addr_t) == sizeof(u64)) {
880 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
881 u32 tmp = dma_addr & 0xFFFFFFFF;
883 pSge->FlagsLength = cpu_to_le32(flagslength);
884 pSge->Address.Low = cpu_to_le32(tmp);
885 tmp = (u32) ((u64)dma_addr >> 32);
886 pSge->Address.High = cpu_to_le32(tmp);
889 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
890 pSge->FlagsLength = cpu_to_le32(flagslength);
891 pSge->Address = cpu_to_le32(dma_addr);
895 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
897 * mpt_send_handshake_request - Send MPT request via doorbell
899 * @handle: Handle of registered MPT protocol driver
900 * @ioc: Pointer to MPT adapter structure
901 * @reqBytes: Size of the request in bytes
902 * @req: Pointer to MPT request frame
903 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
905 * This routine is used exclusively to send MptScsiTaskMgmt
906 * requests since they are required to be sent via doorbell handshake.
908 * NOTE: It is the callers responsibility to byte-swap fields in the
909 * request which are greater than 1 byte in size.
911 * Returns 0 for success, non-zero for failure.
914 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
920 /* State is known to be good upon entering
921 * this function so issue the bus reset
926 * Emulate what mpt_put_msg_frame() does /wrt to sanity
927 * setting cb_idx/req_idx. But ONLY if this request
928 * is in proper (pre-alloc'd) request buffer range...
930 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
931 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
932 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
933 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
934 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
937 /* Make sure there are no doorbells */
938 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
940 CHIPREG_WRITE32(&ioc->chip->Doorbell,
941 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
942 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
944 /* Wait for IOC doorbell int */
945 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
949 /* Read doorbell and check for active bit */
950 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
953 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
956 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
958 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
962 /* Send request via doorbell handshake */
963 req_as_bytes = (u8 *) req;
964 for (ii = 0; ii < reqBytes/4; ii++) {
967 word = ((req_as_bytes[(ii*4) + 0] << 0) |
968 (req_as_bytes[(ii*4) + 1] << 8) |
969 (req_as_bytes[(ii*4) + 2] << 16) |
970 (req_as_bytes[(ii*4) + 3] << 24));
971 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
972 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
978 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
983 /* Make sure there are no doorbells */
984 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
991 * mpt_host_page_access_control - provides mechanism for the host
992 * driver to control the IOC's Host Page Buffer access.
993 * @ioc: Pointer to MPT adapter structure
994 * @access_control_value: define bits below
996 * Access Control Value - bits[15:12]
998 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
999 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1000 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1002 * Returns 0 for success, non-zero for failure.
1006 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1010 /* return if in use */
1011 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1012 & MPI_DOORBELL_ACTIVE)
1015 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1017 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1018 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1019 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1020 (access_control_value<<12)));
1022 /* Wait for IOC to clear Doorbell Status bit */
1023 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1029 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1031 * mpt_host_page_alloc - allocate system memory for the fw
1032 * If we already allocated memory in past, then resend the same pointer.
1033 * ioc@: Pointer to pointer to IOC adapter
1034 * ioc_init@: Pointer to ioc init config page
1036 * Returns 0 for success, non-zero for failure.
1039 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1043 u32 host_page_buffer_sz=0;
1045 if(!ioc->HostPageBuffer) {
1047 host_page_buffer_sz =
1048 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1050 if(!host_page_buffer_sz)
1051 return 0; /* fw doesn't need any host buffers */
1053 /* spin till we get enough memory */
1054 while(host_page_buffer_sz > 0) {
1056 if((ioc->HostPageBuffer = pci_alloc_consistent(
1058 host_page_buffer_sz,
1059 &ioc->HostPageBuffer_dma)) != NULL) {
1061 dinitprintk((MYIOC_s_INFO_FMT
1062 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1064 ioc->HostPageBuffer,
1065 ioc->HostPageBuffer_dma,
1066 host_page_buffer_sz));
1067 ioc->alloc_total += host_page_buffer_sz;
1068 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1072 host_page_buffer_sz -= (4*1024);
1076 if(!ioc->HostPageBuffer) {
1077 printk(MYIOC_s_ERR_FMT
1078 "Failed to alloc memory for host_page_buffer!\n",
1083 psge = (char *)&ioc_init->HostPageBufferSGE;
1084 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1085 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1086 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1087 MPI_SGE_FLAGS_HOST_TO_IOC |
1088 MPI_SGE_FLAGS_END_OF_BUFFER;
1089 if (sizeof(dma_addr_t) == sizeof(u64)) {
1090 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1092 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1093 flags_length |= ioc->HostPageBuffer_sz;
1094 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1095 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1102 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1103 * the associated MPT adapter structure.
1104 * @iocid: IOC unique identifier (integer)
1105 * @iocpp: Pointer to pointer to IOC adapter
1107 * Returns iocid and sets iocpp.
1110 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1114 list_for_each_entry(ioc,&ioc_list,list) {
1115 if (ioc->id == iocid) {
1125 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1127 * mpt_attach - Install a PCI intelligent MPT adapter.
1128 * @pdev: Pointer to pci_dev structure
1130 * This routine performs all the steps necessary to bring the IOC of
1131 * a MPT adapter to a OPERATIONAL state. This includes registering
1132 * memory regions, registering the interrupt, and allocating request
1133 * and reply memory pools.
1135 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1138 * Returns 0 for success, non-zero for failure.
1140 * TODO: Add support for polled controllers
1143 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1147 unsigned long mem_phys;
1155 static int mpt_ids = 0;
1156 #ifdef CONFIG_PROC_FS
1157 struct proc_dir_entry *dent, *ent;
1160 if (pci_enable_device(pdev))
1163 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1165 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1166 dprintk((KERN_INFO MYNAM
1167 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1168 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1169 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1173 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1174 dprintk((KERN_INFO MYNAM
1175 ": Using 64 bit consistent mask\n"));
1177 dprintk((KERN_INFO MYNAM
1178 ": Not using 64 bit consistent mask\n"));
1180 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1182 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1185 ioc->alloc_total = sizeof(MPT_ADAPTER);
1186 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1187 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1190 ioc->diagPending = 0;
1191 spin_lock_init(&ioc->diagLock);
1192 spin_lock_init(&ioc->fc_rescan_work_lock);
1193 spin_lock_init(&ioc->initializing_hba_lock);
1195 /* Initialize the event logging.
1197 ioc->eventTypes = 0; /* None */
1198 ioc->eventContext = 0;
1199 ioc->eventLogSize = 0;
1206 ioc->cached_fw = NULL;
1208 /* Initilize SCSI Config Data structure
1210 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1212 /* Initialize the running configQ head.
1214 INIT_LIST_HEAD(&ioc->configQ);
1216 /* Initialize the fc rport list head.
1218 INIT_LIST_HEAD(&ioc->fc_rports);
1220 /* Find lookup slot. */
1221 INIT_LIST_HEAD(&ioc->list);
1222 ioc->id = mpt_ids++;
1224 mem_phys = msize = 0;
1226 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1227 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1228 /* Get I/O space! */
1229 port = pci_resource_start(pdev, ii);
1230 psize = pci_resource_len(pdev,ii);
1233 mem_phys = pci_resource_start(pdev, ii);
1234 msize = pci_resource_len(pdev,ii);
1238 ioc->mem_size = msize;
1240 if (ii == DEVICE_COUNT_RESOURCE) {
1241 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1246 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1247 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1250 /* Get logical ptr for PciMem0 space */
1251 /*mem = ioremap(mem_phys, msize);*/
1252 mem = ioremap(mem_phys, 0x100);
1254 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1259 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1261 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1262 &ioc->facts, &ioc->pfacts[0]));
1264 ioc->mem_phys = mem_phys;
1265 ioc->chip = (SYSIF_REGS __iomem *)mem;
1267 /* Save Port IO values in case we need to do downloadboot */
1269 u8 *pmem = (u8*)port;
1270 ioc->pio_mem_phys = port;
1271 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1274 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1275 ioc->prod_name = "LSIFC909";
1278 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1279 ioc->prod_name = "LSIFC929";
1282 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1283 ioc->prod_name = "LSIFC919";
1286 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1287 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1289 if (revision < XL_929) {
1290 ioc->prod_name = "LSIFC929X";
1291 /* 929X Chip Fix. Set Split transactions level
1292 * for PCIX. Set MOST bits to zero.
1294 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1296 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1298 ioc->prod_name = "LSIFC929XL";
1299 /* 929XL Chip Fix. Set MMRBC to 0x08.
1301 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1303 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1306 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1307 ioc->prod_name = "LSIFC919X";
1309 /* 919X Chip Fix. Set Split transactions level
1310 * for PCIX. Set MOST bits to zero.
1312 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1314 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1316 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1317 ioc->prod_name = "LSIFC939X";
1319 ioc->errata_flag_1064 = 1;
1321 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1322 ioc->prod_name = "LSIFC949X";
1324 ioc->errata_flag_1064 = 1;
1326 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1327 ioc->prod_name = "LSIFC949E";
1330 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1331 ioc->prod_name = "LSI53C1030";
1332 ioc->bus_type = SPI;
1333 /* 1030 Chip Fix. Disable Split transactions
1334 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1336 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1337 if (revision < C0_1030) {
1338 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1340 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1343 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1344 ioc->prod_name = "LSI53C1035";
1345 ioc->bus_type = SPI;
1347 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1348 ioc->prod_name = "LSISAS1064";
1349 ioc->bus_type = SAS;
1350 ioc->errata_flag_1064 = 1;
1352 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1353 ioc->prod_name = "LSISAS1066";
1354 ioc->bus_type = SAS;
1355 ioc->errata_flag_1064 = 1;
1357 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1358 ioc->prod_name = "LSISAS1068";
1359 ioc->bus_type = SAS;
1360 ioc->errata_flag_1064 = 1;
1362 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1363 ioc->prod_name = "LSISAS1064E";
1364 ioc->bus_type = SAS;
1366 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1367 ioc->prod_name = "LSISAS1066E";
1368 ioc->bus_type = SAS;
1370 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1371 ioc->prod_name = "LSISAS1068E";
1372 ioc->bus_type = SAS;
1375 if (ioc->errata_flag_1064)
1376 pci_disable_io_access(pdev);
1378 sprintf(ioc->name, "ioc%d", ioc->id);
1380 spin_lock_init(&ioc->FreeQlock);
1383 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1385 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1387 /* Set lookup ptr. */
1388 list_add_tail(&ioc->list, &ioc_list);
1392 if (mpt_msi_enable && !pci_enable_msi(pdev))
1393 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
1395 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1399 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1400 ioc->name, pdev->irq);
1402 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1403 ioc->name, __irq_itoa(pdev->irq));
1405 list_del(&ioc->list);
1411 ioc->pci_irq = pdev->irq;
1413 pci_set_master(pdev); /* ?? */
1414 pci_set_drvdata(pdev, ioc);
1417 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1419 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1423 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1425 mpt_detect_bound_ports(ioc, pdev);
1427 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1429 printk(KERN_WARNING MYNAM
1430 ": WARNING - %s did not initialize properly! (%d)\n",
1433 list_del(&ioc->list);
1434 free_irq(ioc->pci_irq, ioc);
1436 pci_disable_msi(pdev);
1438 ioc->alt_ioc->alt_ioc = NULL;
1441 pci_set_drvdata(pdev, NULL);
1445 /* call per device driver probe entry point */
1446 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1447 if(MptDeviceDriverHandlers[ii] &&
1448 MptDeviceDriverHandlers[ii]->probe) {
1449 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1453 #ifdef CONFIG_PROC_FS
1455 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1457 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1459 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1461 ent->read_proc = procmpt_iocinfo_read;
1464 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1466 ent->read_proc = procmpt_summary_read;
1475 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1477 * mpt_detach - Remove a PCI intelligent MPT adapter.
1478 * @pdev: Pointer to pci_dev structure
1483 mpt_detach(struct pci_dev *pdev)
1485 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1489 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1490 remove_proc_entry(pname, NULL);
1491 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1492 remove_proc_entry(pname, NULL);
1493 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1494 remove_proc_entry(pname, NULL);
1496 /* call per device driver remove entry point */
1497 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1498 if(MptDeviceDriverHandlers[ii] &&
1499 MptDeviceDriverHandlers[ii]->remove) {
1500 MptDeviceDriverHandlers[ii]->remove(pdev);
1504 /* Disable interrupts! */
1505 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1508 synchronize_irq(pdev->irq);
1510 /* Clear any lingering interrupt */
1511 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1513 CHIPREG_READ32(&ioc->chip->IntStatus);
1515 mpt_adapter_dispose(ioc);
1517 pci_set_drvdata(pdev, NULL);
1520 /**************************************************************************
1524 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526 * mpt_suspend - Fusion MPT base driver suspend routine.
1531 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1534 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1536 device_state=pci_choose_state(pdev, state);
1538 printk(MYIOC_s_INFO_FMT
1539 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1540 ioc->name, pdev, pci_name(pdev), device_state);
1542 pci_save_state(pdev);
1544 /* put ioc into READY_STATE */
1545 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1546 printk(MYIOC_s_ERR_FMT
1547 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1550 /* disable interrupts */
1551 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1554 /* Clear any lingering interrupt */
1555 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1557 pci_disable_device(pdev);
1558 pci_set_power_state(pdev, device_state);
1563 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1565 * mpt_resume - Fusion MPT base driver resume routine.
1570 mpt_resume(struct pci_dev *pdev)
1572 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1573 u32 device_state = pdev->current_state;
1576 printk(MYIOC_s_INFO_FMT
1577 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1578 ioc->name, pdev, pci_name(pdev), device_state);
1580 pci_set_power_state(pdev, 0);
1581 pci_restore_state(pdev);
1582 pci_enable_device(pdev);
1584 /* enable interrupts */
1585 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1588 printk(MYIOC_s_INFO_FMT
1589 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1591 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1592 CHIPREG_READ32(&ioc->chip->Doorbell));
1594 /* bring ioc to operational state */
1595 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1596 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1597 printk(MYIOC_s_INFO_FMT
1598 "pci-resume: Cannot recover, error:[%x]\n",
1599 ioc->name, recovery_state);
1601 printk(MYIOC_s_INFO_FMT
1602 "pci-resume: success\n", ioc->name);
1610 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1612 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1613 ioc->bus_type != SPI) ||
1614 (MptDriverClass[index] == MPTFC_DRIVER &&
1615 ioc->bus_type != FC) ||
1616 (MptDriverClass[index] == MPTSAS_DRIVER &&
1617 ioc->bus_type != SAS))
1618 /* make sure we only call the relevant reset handler
1621 return (MptResetHandlers[index])(ioc, reset_phase);
1624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1626 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1627 * @ioc: Pointer to MPT adapter structure
1628 * @reason: Event word / reason
1629 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1631 * This routine performs all the steps necessary to bring the IOC
1632 * to a OPERATIONAL state.
1634 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1639 * -1 if failed to get board READY
1640 * -2 if READY but IOCFacts Failed
1641 * -3 if READY but PrimeIOCFifos Failed
1642 * -4 if READY but IOCInit Failed
1645 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1647 int hard_reset_done = 0;
1648 int alt_ioc_ready = 0;
1654 int reset_alt_ioc_active = 0;
1656 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1657 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1659 /* Disable reply interrupts (also blocks FreeQ) */
1660 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1664 if (ioc->alt_ioc->active)
1665 reset_alt_ioc_active = 1;
1667 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1668 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1669 ioc->alt_ioc->active = 0;
1673 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1676 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1677 if (hard_reset_done == -4) {
1678 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1681 if (reset_alt_ioc_active && ioc->alt_ioc) {
1682 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1683 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1684 ioc->alt_ioc->name));
1685 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1686 ioc->alt_ioc->active = 1;
1690 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1696 /* hard_reset_done = 0 if a soft reset was performed
1697 * and 1 if a hard reset was performed.
1699 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1700 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1703 printk(KERN_WARNING MYNAM
1704 ": alt-%s: Not ready WARNING!\n",
1705 ioc->alt_ioc->name);
1708 for (ii=0; ii<5; ii++) {
1709 /* Get IOC facts! Allow 5 retries */
1710 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1716 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1718 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1719 MptDisplayIocCapabilities(ioc);
1722 if (alt_ioc_ready) {
1723 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1724 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1725 /* Retry - alt IOC was initialized once
1727 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1730 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1732 reset_alt_ioc_active = 0;
1733 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1734 MptDisplayIocCapabilities(ioc->alt_ioc);
1738 /* Prime reply & request queues!
1739 * (mucho alloc's) Must be done prior to
1740 * init as upper addresses are needed for init.
1741 * If fails, continue with alt-ioc processing
1743 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1746 /* May need to check/upload firmware & data here!
1747 * If fails, continue with alt-ioc processing
1749 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1752 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1753 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1754 ioc->alt_ioc->name, rc);
1756 reset_alt_ioc_active = 0;
1759 if (alt_ioc_ready) {
1760 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1762 reset_alt_ioc_active = 0;
1763 printk(KERN_WARNING MYNAM
1764 ": alt-%s: (%d) init failure WARNING!\n",
1765 ioc->alt_ioc->name, rc);
1769 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1770 if (ioc->upload_fw) {
1771 ddlprintk((MYIOC_s_INFO_FMT
1772 "firmware upload required!\n", ioc->name));
1774 /* Controller is not operational, cannot do upload
1777 rc = mpt_do_upload(ioc, sleepFlag);
1779 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1781 * Maintain only one pointer to FW memory
1782 * so there will not be two attempt to
1783 * downloadboot onboard dual function
1784 * chips (mpt_adapter_disable,
1787 ioc->cached_fw = NULL;
1788 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1789 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1792 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1800 /* Enable! (reply interrupt) */
1801 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1805 if (reset_alt_ioc_active && ioc->alt_ioc) {
1806 /* (re)Enable alt-IOC! (reply interrupt) */
1807 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1808 ioc->alt_ioc->name));
1809 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1810 ioc->alt_ioc->active = 1;
1813 /* Enable MPT base driver management of EventNotification
1814 * and EventAck handling.
1816 if ((ret == 0) && (!ioc->facts.EventState))
1817 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1819 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1820 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1822 /* Add additional "reason" check before call to GetLanConfigPages
1823 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1824 * recursive scenario; GetLanConfigPages times out, timer expired
1825 * routine calls HardResetHandler, which calls into here again,
1826 * and we try GetLanConfigPages again...
1828 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1829 if (ioc->bus_type == SAS) {
1831 /* clear persistency table */
1832 if(ioc->facts.IOCExceptions &
1833 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1834 ret = mptbase_sas_persist_operation(ioc,
1835 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1842 mpt_findImVolumes(ioc);
1844 } else if (ioc->bus_type == FC) {
1846 * Pre-fetch FC port WWN and stuff...
1847 * (FCPortPage0_t stuff)
1849 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1850 (void) mptbase_GetFcPortPage0(ioc, ii);
1853 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1854 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1856 * Pre-fetch the ports LAN MAC address!
1857 * (LANPage1_t stuff)
1859 (void) GetLanConfigPages(ioc);
1862 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1863 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1864 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1869 /* Get NVRAM and adapter maximums from SPP 0 and 2
1871 mpt_GetScsiPortSettings(ioc, 0);
1873 /* Get version and length of SDP 1
1875 mpt_readScsiDevicePageHeaders(ioc, 0);
1879 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1880 mpt_findImVolumes(ioc);
1882 /* Check, and possibly reset, the coalescing value
1884 mpt_read_ioc_pg_1(ioc);
1886 mpt_read_ioc_pg_4(ioc);
1889 GetIoUnitPage2(ioc);
1893 * Call each currently registered protocol IOC reset handler
1894 * with post-reset indication.
1895 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1896 * MptResetHandlers[] registered yet.
1898 if (hard_reset_done) {
1900 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1901 if ((ret == 0) && MptResetHandlers[ii]) {
1902 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1904 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1908 if (alt_ioc_ready && MptResetHandlers[ii]) {
1909 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1910 ioc->name, ioc->alt_ioc->name, ii));
1911 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1915 /* FIXME? Examine results here? */
1921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1923 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1924 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1925 * 929X, 1030 or 1035.
1926 * @ioc: Pointer to MPT adapter structure
1927 * @pdev: Pointer to (struct pci_dev) structure
1929 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1930 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1933 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1935 struct pci_dev *peer=NULL;
1936 unsigned int slot = PCI_SLOT(pdev->devfn);
1937 unsigned int func = PCI_FUNC(pdev->devfn);
1938 MPT_ADAPTER *ioc_srch;
1940 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1941 " searching for devfn match on %x or %x\n",
1942 ioc->name, pci_name(pdev), pdev->bus->number,
1943 pdev->devfn, func-1, func+1));
1945 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1947 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1952 list_for_each_entry(ioc_srch, &ioc_list, list) {
1953 struct pci_dev *_pcidev = ioc_srch->pcidev;
1954 if (_pcidev == peer) {
1955 /* Paranoia checks */
1956 if (ioc->alt_ioc != NULL) {
1957 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1958 ioc->name, ioc->alt_ioc->name);
1960 } else if (ioc_srch->alt_ioc != NULL) {
1961 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1962 ioc_srch->name, ioc_srch->alt_ioc->name);
1965 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1966 ioc->name, ioc_srch->name));
1967 ioc_srch->alt_ioc = ioc;
1968 ioc->alt_ioc = ioc_srch;
1974 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1976 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1977 * @this: Pointer to MPT adapter structure
1980 mpt_adapter_disable(MPT_ADAPTER *ioc)
1985 if (ioc->cached_fw != NULL) {
1986 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1987 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1988 printk(KERN_WARNING MYNAM
1989 ": firmware downloadboot failure (%d)!\n", ret);
1993 /* Disable adapter interrupts! */
1994 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1996 /* Clear any lingering interrupt */
1997 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1999 if (ioc->alloc != NULL) {
2001 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2002 ioc->name, ioc->alloc, ioc->alloc_sz));
2003 pci_free_consistent(ioc->pcidev, sz,
2004 ioc->alloc, ioc->alloc_dma);
2005 ioc->reply_frames = NULL;
2006 ioc->req_frames = NULL;
2008 ioc->alloc_total -= sz;
2011 if (ioc->sense_buf_pool != NULL) {
2012 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2013 pci_free_consistent(ioc->pcidev, sz,
2014 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2015 ioc->sense_buf_pool = NULL;
2016 ioc->alloc_total -= sz;
2019 if (ioc->events != NULL){
2020 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2023 ioc->alloc_total -= sz;
2026 if (ioc->cached_fw != NULL) {
2027 sz = ioc->facts.FWImageSize;
2028 pci_free_consistent(ioc->pcidev, sz,
2029 ioc->cached_fw, ioc->cached_fw_dma);
2030 ioc->cached_fw = NULL;
2031 ioc->alloc_total -= sz;
2034 kfree(ioc->spi_data.nvram);
2035 kfree(ioc->raid_data.pIocPg3);
2036 ioc->spi_data.nvram = NULL;
2037 ioc->raid_data.pIocPg3 = NULL;
2039 if (ioc->spi_data.pIocPg4 != NULL) {
2040 sz = ioc->spi_data.IocPg4Sz;
2041 pci_free_consistent(ioc->pcidev, sz,
2042 ioc->spi_data.pIocPg4,
2043 ioc->spi_data.IocPg4_dma);
2044 ioc->spi_data.pIocPg4 = NULL;
2045 ioc->alloc_total -= sz;
2048 if (ioc->ReqToChain != NULL) {
2049 kfree(ioc->ReqToChain);
2050 kfree(ioc->RequestNB);
2051 ioc->ReqToChain = NULL;
2054 kfree(ioc->ChainToChain);
2055 ioc->ChainToChain = NULL;
2057 if (ioc->HostPageBuffer != NULL) {
2058 if((ret = mpt_host_page_access_control(ioc,
2059 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2060 printk(KERN_ERR MYNAM
2061 ": %s: host page buffers free failed (%d)!\n",
2064 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2065 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2066 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2067 ioc->HostPageBuffer,
2068 ioc->HostPageBuffer_dma);
2069 ioc->HostPageBuffer = NULL;
2070 ioc->HostPageBuffer_sz = 0;
2071 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2075 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2077 * mpt_adapter_dispose - Free all resources associated with a MPT
2079 * @ioc: Pointer to MPT adapter structure
2081 * This routine unregisters h/w resources and frees all alloc'd memory
2082 * associated with a MPT adapter structure.
2085 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2087 int sz_first, sz_last;
2092 sz_first = ioc->alloc_total;
2094 mpt_adapter_disable(ioc);
2096 if (ioc->pci_irq != -1) {
2097 free_irq(ioc->pci_irq, ioc);
2099 pci_disable_msi(ioc->pcidev);
2103 if (ioc->memmap != NULL) {
2104 iounmap(ioc->memmap);
2108 #if defined(CONFIG_MTRR) && 0
2109 if (ioc->mtrr_reg > 0) {
2110 mtrr_del(ioc->mtrr_reg, 0, 0);
2111 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2115 /* Zap the adapter lookup ptr! */
2116 list_del(&ioc->list);
2118 sz_last = ioc->alloc_total;
2119 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2120 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2123 ioc->alt_ioc->alt_ioc = NULL;
2128 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2130 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2131 * @ioc: Pointer to MPT adapter structure
2134 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2138 printk(KERN_INFO "%s: ", ioc->name);
2139 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2140 printk("%s: ", ioc->prod_name+3);
2141 printk("Capabilities={");
2143 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2144 printk("Initiator");
2148 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2149 printk("%sTarget", i ? "," : "");
2153 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2154 printk("%sLAN", i ? "," : "");
2160 * This would probably evoke more questions than it's worth
2162 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2163 printk("%sLogBusAddr", i ? "," : "");
2171 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2173 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2174 * @ioc: Pointer to MPT_ADAPTER structure
2175 * @force: Force hard KickStart of IOC
2176 * @sleepFlag: Specifies whether the process can sleep
2179 * 1 - DIAG reset and READY
2180 * 0 - READY initially OR soft reset and READY
2181 * -1 - Any failure on KickStart
2182 * -2 - Msg Unit Reset Failed
2183 * -3 - IO Unit Reset Failed
2184 * -4 - IOC owned by a PEER
2187 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2192 int hard_reset_done = 0;
2197 /* Get current [raw] IOC state */
2198 ioc_state = mpt_GetIocState(ioc, 0);
2199 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2202 * Check to see if IOC got left/stuck in doorbell handshake
2203 * grip of death. If so, hard reset the IOC.
2205 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2207 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2211 /* Is it already READY? */
2212 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2216 * Check to see if IOC is in FAULT state.
2218 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2220 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2222 printk(KERN_WARNING " FAULT code = %04xh\n",
2223 ioc_state & MPI_DOORBELL_DATA_MASK);
2227 * Hmmm... Did it get left operational?
2229 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2230 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2234 * If PCI Peer, exit.
2235 * Else, if no fault conditions are present, issue a MessageUnitReset
2236 * Else, fall through to KickStart case
2238 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2239 dinitprintk((KERN_INFO MYNAM
2240 ": whoinit 0x%x statefault %d force %d\n",
2241 whoinit, statefault, force));
2242 if (whoinit == MPI_WHOINIT_PCI_PEER)
2245 if ((statefault == 0 ) && (force == 0)) {
2246 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2253 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2254 if (hard_reset_done < 0)
2258 * Loop here waiting for IOC to come READY.
2261 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2263 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2264 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2266 * BIOS or previous driver load left IOC in OP state.
2267 * Reset messaging FIFOs.
2269 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2270 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2273 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2275 * Something is wrong. Try to get IOC back
2278 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2279 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2286 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2287 ioc->name, (int)((ii+5)/HZ));
2291 if (sleepFlag == CAN_SLEEP) {
2292 msleep_interruptible(1);
2294 mdelay (1); /* 1 msec delay */
2299 if (statefault < 3) {
2300 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2302 statefault==1 ? "stuck handshake" : "IOC FAULT");
2305 return hard_reset_done;
2308 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2310 * mpt_GetIocState - Get the current state of a MPT adapter.
2311 * @ioc: Pointer to MPT_ADAPTER structure
2312 * @cooked: Request raw or cooked IOC state
2314 * Returns all IOC Doorbell register bits if cooked==0, else just the
2315 * Doorbell bits in MPI_IOC_STATE_MASK.
2318 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2323 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2324 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2325 sc = s & MPI_IOC_STATE_MASK;
2328 ioc->last_state = sc;
2330 return cooked ? sc : s;
2333 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2335 * GetIocFacts - Send IOCFacts request to MPT adapter.
2336 * @ioc: Pointer to MPT_ADAPTER structure
2337 * @sleepFlag: Specifies whether the process can sleep
2338 * @reason: If recovery, only update facts.
2340 * Returns 0 for success, non-zero for failure.
2343 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2345 IOCFacts_t get_facts;
2346 IOCFactsReply_t *facts;
2354 /* IOC *must* NOT be in RESET state! */
2355 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2356 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2362 facts = &ioc->facts;
2364 /* Destination (reply area)... */
2365 reply_sz = sizeof(*facts);
2366 memset(facts, 0, reply_sz);
2368 /* Request area (get_facts on the stack right now!) */
2369 req_sz = sizeof(get_facts);
2370 memset(&get_facts, 0, req_sz);
2372 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2373 /* Assert: All other get_facts fields are zero! */
2375 dinitprintk((MYIOC_s_INFO_FMT
2376 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2377 ioc->name, req_sz, reply_sz));
2379 /* No non-zero fields in the get_facts request are greater than
2380 * 1 byte in size, so we can just fire it off as is.
2382 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2383 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2388 * Now byte swap (GRRR) the necessary fields before any further
2389 * inspection of reply contents.
2391 * But need to do some sanity checks on MsgLength (byte) field
2392 * to make sure we don't zero IOC's req_sz!
2394 /* Did we get a valid reply? */
2395 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2396 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2398 * If not been here, done that, save off first WhoInit value
2400 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2401 ioc->FirstWhoInit = facts->WhoInit;
2404 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2405 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2406 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2407 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2408 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2409 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2410 /* CHECKME! IOCStatus, IOCLogInfo */
2412 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2413 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2416 * FC f/w version changed between 1.1 and 1.2
2417 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2418 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2420 if (facts->MsgVersion < 0x0102) {
2422 * Handle old FC f/w style, convert to new...
2424 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2425 facts->FWVersion.Word =
2426 ((oldv<<12) & 0xFF000000) |
2427 ((oldv<<8) & 0x000FFF00);
2429 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2431 facts->ProductID = le16_to_cpu(facts->ProductID);
2432 facts->CurrentHostMfaHighAddr =
2433 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2434 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2435 facts->CurrentSenseBufferHighAddr =
2436 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2437 facts->CurReplyFrameSize =
2438 le16_to_cpu(facts->CurReplyFrameSize);
2439 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2442 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2443 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2444 * to 14 in MPI-1.01.0x.
2446 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2447 facts->MsgVersion > 0x0100) {
2448 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2451 sz = facts->FWImageSize;
2456 facts->FWImageSize = sz;
2458 if (!facts->RequestFrameSize) {
2459 /* Something is wrong! */
2460 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2465 r = sz = facts->BlockSize;
2466 vv = ((63 / (sz * 4)) + 1) & 0x03;
2467 ioc->NB_for_64_byte_frame = vv;
2473 ioc->NBShiftFactor = shiftFactor;
2474 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2475 ioc->name, vv, shiftFactor, r));
2477 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2479 * Set values for this IOC's request & reply frame sizes,
2480 * and request & reply queue depths...
2482 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2483 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2484 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2485 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2487 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2488 ioc->name, ioc->reply_sz, ioc->reply_depth));
2489 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2490 ioc->name, ioc->req_sz, ioc->req_depth));
2492 /* Get port facts! */
2493 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2497 printk(MYIOC_s_ERR_FMT
2498 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2499 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2500 RequestFrameSize)/sizeof(u32)));
2507 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2509 * GetPortFacts - Send PortFacts request to MPT adapter.
2510 * @ioc: Pointer to MPT_ADAPTER structure
2511 * @portnum: Port number
2512 * @sleepFlag: Specifies whether the process can sleep
2514 * Returns 0 for success, non-zero for failure.
2517 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2519 PortFacts_t get_pfacts;
2520 PortFactsReply_t *pfacts;
2525 /* IOC *must* NOT be in RESET state! */
2526 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2527 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2533 pfacts = &ioc->pfacts[portnum];
2535 /* Destination (reply area)... */
2536 reply_sz = sizeof(*pfacts);
2537 memset(pfacts, 0, reply_sz);
2539 /* Request area (get_pfacts on the stack right now!) */
2540 req_sz = sizeof(get_pfacts);
2541 memset(&get_pfacts, 0, req_sz);
2543 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2544 get_pfacts.PortNumber = portnum;
2545 /* Assert: All other get_pfacts fields are zero! */
2547 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2548 ioc->name, portnum));
2550 /* No non-zero fields in the get_pfacts request are greater than
2551 * 1 byte in size, so we can just fire it off as is.
2553 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2554 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2558 /* Did we get a valid reply? */
2560 /* Now byte swap the necessary fields in the response. */
2561 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2562 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2563 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2564 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2565 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2566 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2567 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2568 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2569 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2576 * SendIocInit - Send IOCInit request to MPT adapter.
2577 * @ioc: Pointer to MPT_ADAPTER structure
2578 * @sleepFlag: Specifies whether the process can sleep
2580 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2582 * Returns 0 for success, non-zero for failure.
2585 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2588 MPIDefaultReply_t init_reply;
2594 memset(&ioc_init, 0, sizeof(ioc_init));
2595 memset(&init_reply, 0, sizeof(init_reply));
2597 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2598 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2600 /* If we are in a recovery mode and we uploaded the FW image,
2601 * then this pointer is not NULL. Skip the upload a second time.
2602 * Set this flag if cached_fw set for either IOC.
2604 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2608 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2609 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2611 if(ioc->bus_type == SAS)
2612 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2613 else if(ioc->bus_type == FC)
2614 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2616 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2617 ioc_init.MaxBuses = MPT_MAX_BUS;
2618 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2619 ioc->name, ioc->facts.MsgVersion));
2620 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2621 // set MsgVersion and HeaderVersion host driver was built with
2622 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2623 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2625 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2626 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2627 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2630 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2632 if (sizeof(dma_addr_t) == sizeof(u64)) {
2633 /* Save the upper 32-bits of the request
2634 * (reply) and sense buffers.
2636 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2637 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2639 /* Force 32-bit addressing */
2640 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2641 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2644 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2645 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2646 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2647 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2649 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2650 ioc->name, &ioc_init));
2652 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2653 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2655 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2659 /* No need to byte swap the multibyte fields in the reply
2660 * since we don't even look at it's contents.
2663 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2664 ioc->name, &ioc_init));
2666 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2667 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2671 /* YIKES! SUPER IMPORTANT!!!
2672 * Poll IocState until _OPERATIONAL while IOC is doing
2673 * LoopInit and TargetDiscovery!
2676 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2677 state = mpt_GetIocState(ioc, 1);
2678 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2679 if (sleepFlag == CAN_SLEEP) {
2680 msleep_interruptible(1);
2686 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2687 ioc->name, (int)((count+5)/HZ));
2691 state = mpt_GetIocState(ioc, 1);
2694 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2702 * SendPortEnable - Send PortEnable request to MPT adapter port.
2703 * @ioc: Pointer to MPT_ADAPTER structure
2704 * @portnum: Port number to enable
2705 * @sleepFlag: Specifies whether the process can sleep
2707 * Send PortEnable to bring IOC to OPERATIONAL state.
2709 * Returns 0 for success, non-zero for failure.
2712 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2714 PortEnable_t port_enable;
2715 MPIDefaultReply_t reply_buf;
2720 /* Destination... */
2721 reply_sz = sizeof(MPIDefaultReply_t);
2722 memset(&reply_buf, 0, reply_sz);
2724 req_sz = sizeof(PortEnable_t);
2725 memset(&port_enable, 0, req_sz);
2727 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2728 port_enable.PortNumber = portnum;
2729 /* port_enable.ChainOffset = 0; */
2730 /* port_enable.MsgFlags = 0; */
2731 /* port_enable.MsgContext = 0; */
2733 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2734 ioc->name, portnum, &port_enable));
2736 /* RAID FW may take a long time to enable
2738 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2739 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2740 (ioc->bus_type == SAS)) {
2741 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2742 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2743 300 /*seconds*/, sleepFlag);
2745 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2746 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2747 30 /*seconds*/, sleepFlag);
2753 * ioc: Pointer to MPT_ADAPTER structure
2754 * size - total FW bytes
2757 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2760 return; /* use already allocated memory */
2761 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2762 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2763 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2765 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2766 ioc->alloc_total += size;
2770 * If alt_img is NULL, delete from ioc structure.
2771 * Else, delete a secondary image in same format.
2774 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2778 sz = ioc->facts.FWImageSize;
2779 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2780 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2781 pci_free_consistent(ioc->pcidev, sz,
2782 ioc->cached_fw, ioc->cached_fw_dma);
2783 ioc->cached_fw = NULL;
2789 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2791 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2792 * @ioc: Pointer to MPT_ADAPTER structure
2793 * @sleepFlag: Specifies whether the process can sleep
2795 * Returns 0 for success, >0 for handshake failure
2796 * <0 for fw upload failure.
2798 * Remark: If bound IOC and a successful FWUpload was performed
2799 * on the bound IOC, the second image is discarded
2800 * and memory is free'd. Both channels must upload to prevent
2801 * IOC from running in degraded mode.
2804 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2806 u8 request[ioc->req_sz];
2807 u8 reply[sizeof(FWUploadReply_t)];
2808 FWUpload_t *prequest;
2809 FWUploadReply_t *preply;
2810 FWUploadTCSGE_t *ptcsge;
2813 int ii, sz, reply_sz;
2816 /* If the image size is 0, we are done.
2818 if ((sz = ioc->facts.FWImageSize) == 0)
2821 mpt_alloc_fw_memory(ioc, sz);
2823 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2824 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2826 if (ioc->cached_fw == NULL) {
2832 prequest = (FWUpload_t *)&request;
2833 preply = (FWUploadReply_t *)&reply;
2835 /* Destination... */
2836 memset(prequest, 0, ioc->req_sz);
2838 reply_sz = sizeof(reply);
2839 memset(preply, 0, reply_sz);
2841 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2842 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2844 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2845 ptcsge->DetailsLength = 12;
2846 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2847 ptcsge->ImageSize = cpu_to_le32(sz);
2849 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2851 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2852 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2854 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2855 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2856 prequest, sgeoffset));
2857 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2859 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2860 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2862 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2864 cmdStatus = -EFAULT;
2866 /* Handshake transfer was complete and successful.
2867 * Check the Reply Frame.
2869 int status, transfer_sz;
2870 status = le16_to_cpu(preply->IOCStatus);
2871 if (status == MPI_IOCSTATUS_SUCCESS) {
2872 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2873 if (transfer_sz == sz)
2877 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2878 ioc->name, cmdStatus));
2883 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2885 mpt_free_fw_memory(ioc);
2891 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2893 * mpt_downloadboot - DownloadBoot code
2894 * @ioc: Pointer to MPT_ADAPTER structure
2895 * @flag: Specify which part of IOC memory is to be uploaded.
2896 * @sleepFlag: Specifies whether the process can sleep
2898 * FwDownloadBoot requires Programmed IO access.
2900 * Returns 0 for success
2901 * -1 FW Image size is 0
2902 * -2 No valid cached_fw Pointer
2903 * <0 for fw upload failure.
2906 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2908 MpiExtImageHeader_t *pExtImage;
2918 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2919 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2921 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2922 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2923 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2924 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2925 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2926 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2928 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2931 if (sleepFlag == CAN_SLEEP) {
2932 msleep_interruptible(1);
2937 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2938 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2940 for (count = 0; count < 30; count ++) {
2941 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2942 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2943 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2948 if (sleepFlag == CAN_SLEEP) {
2949 msleep_interruptible (100);
2955 if ( count == 30 ) {
2956 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2957 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2958 ioc->name, diag0val));
2962 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2963 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2964 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2965 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2966 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2967 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2969 /* Set the DiagRwEn and Disable ARM bits */
2970 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2972 fwSize = (pFwHeader->ImageSize + 3)/4;
2973 ptrFw = (u32 *) pFwHeader;
2975 /* Write the LoadStartAddress to the DiagRw Address Register
2976 * using Programmed IO
2978 if (ioc->errata_flag_1064)
2979 pci_enable_io_access(ioc->pcidev);
2981 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2982 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2983 ioc->name, pFwHeader->LoadStartAddress));
2985 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2986 ioc->name, fwSize*4, ptrFw));
2988 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2991 nextImage = pFwHeader->NextImageHeaderOffset;
2993 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2995 load_addr = pExtImage->LoadStartAddress;
2997 fwSize = (pExtImage->ImageSize + 3) >> 2;
2998 ptrFw = (u32 *)pExtImage;
3000 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3001 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3002 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3005 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3007 nextImage = pExtImage->NextImageHeaderOffset;
3010 /* Write the IopResetVectorRegAddr */
3011 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3012 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3014 /* Write the IopResetVectorValue */
3015 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3016 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3018 /* Clear the internal flash bad bit - autoincrementing register,
3019 * so must do two writes.
3021 if (ioc->bus_type == SPI) {
3023 * 1030 and 1035 H/W errata, workaround to access
3024 * the ClearFlashBadSignatureBit
3026 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3027 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3028 diagRwData |= 0x40000000;
3029 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3030 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3032 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3033 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3034 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3035 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3038 if (sleepFlag == CAN_SLEEP) {
3039 msleep_interruptible (1);
3045 if (ioc->errata_flag_1064)
3046 pci_disable_io_access(ioc->pcidev);
3048 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3049 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3050 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3051 ioc->name, diag0val));
3052 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3053 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3054 ioc->name, diag0val));
3055 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3057 /* Write 0xFF to reset the sequencer */
3058 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3060 if (ioc->bus_type == SAS) {
3061 ioc_state = mpt_GetIocState(ioc, 0);
3062 if ( (GetIocFacts(ioc, sleepFlag,
3063 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3064 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3065 ioc->name, ioc_state));
3070 for (count=0; count<HZ*20; count++) {
3071 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3072 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3073 ioc->name, count, ioc_state));
3074 if (ioc->bus_type == SAS) {
3077 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3078 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3082 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3086 if (sleepFlag == CAN_SLEEP) {
3087 msleep_interruptible (10);
3092 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3093 ioc->name, ioc_state));
3097 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3099 * KickStart - Perform hard reset of MPT adapter.
3100 * @ioc: Pointer to MPT_ADAPTER structure
3101 * @force: Force hard reset
3102 * @sleepFlag: Specifies whether the process can sleep
3104 * This routine places MPT adapter in diagnostic mode via the
3105 * WriteSequence register, and then performs a hard reset of adapter
3106 * via the Diagnostic register.
3108 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3109 * or NO_SLEEP (interrupt thread, use mdelay)
3110 * force - 1 if doorbell active, board fault state
3111 * board operational, IOC_RECOVERY or
3112 * IOC_BRINGUP and there is an alt_ioc.
3116 * 1 - hard reset, READY
3117 * 0 - no reset due to History bit, READY
3118 * -1 - no reset due to History bit but not READY
3119 * OR reset but failed to come READY
3120 * -2 - no reset, could not enter DIAG mode
3121 * -3 - reset but bad FW bit
3124 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3126 int hard_reset_done = 0;
3130 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3131 if (ioc->bus_type == SPI) {
3132 /* Always issue a Msg Unit Reset first. This will clear some
3133 * SCSI bus hang conditions.
3135 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3137 if (sleepFlag == CAN_SLEEP) {
3138 msleep_interruptible (1000);
3144 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3145 if (hard_reset_done < 0)
3146 return hard_reset_done;
3148 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3151 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3152 for (cnt=0; cnt<cntdn; cnt++) {
3153 ioc_state = mpt_GetIocState(ioc, 1);
3154 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3155 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3157 return hard_reset_done;
3159 if (sleepFlag == CAN_SLEEP) {
3160 msleep_interruptible (10);
3166 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3167 ioc->name, ioc_state);
3171 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3173 * mpt_diag_reset - Perform hard reset of the adapter.
3174 * @ioc: Pointer to MPT_ADAPTER structure
3175 * @ignore: Set if to honor and clear to ignore
3176 * the reset history bit
3177 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3178 * else set to NO_SLEEP (use mdelay instead)
3180 * This routine places the adapter in diagnostic mode via the
3181 * WriteSequence register and then performs a hard reset of adapter
3182 * via the Diagnostic register. Adapter should be in ready state
3183 * upon successful completion.
3185 * Returns: 1 hard reset successful
3186 * 0 no reset performed because reset history bit set
3187 * -2 enabling diagnostic mode failed
3188 * -3 diagnostic reset failed
3191 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3195 int hard_reset_done = 0;
3201 /* Clear any existing interrupts */
3202 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3204 /* Use "Diagnostic reset" method! (only thing available!) */
3205 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3209 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3210 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3211 ioc->name, diag0val, diag1val));
3214 /* Do the reset if we are told to ignore the reset history
3215 * or if the reset history is 0
3217 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3218 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3219 /* Write magic sequence to WriteSequence register
3220 * Loop until in diagnostic mode
3222 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3223 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3224 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3225 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3226 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3227 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3230 if (sleepFlag == CAN_SLEEP) {
3231 msleep_interruptible (100);
3238 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3239 ioc->name, diag0val);
3244 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3246 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3247 ioc->name, diag0val));
3252 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3253 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3254 ioc->name, diag0val, diag1val));
3257 * Disable the ARM (Bug fix)
3260 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3264 * Now hit the reset bit in the Diagnostic register
3265 * (THE BIG HAMMER!) (Clears DRWE bit).
3267 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3268 hard_reset_done = 1;
3269 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3273 * Call each currently registered protocol IOC reset handler
3274 * with pre-reset indication.
3275 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3276 * MptResetHandlers[] registered yet.
3282 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3283 if (MptResetHandlers[ii]) {
3284 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3286 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3288 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3289 ioc->name, ioc->alt_ioc->name, ii));
3290 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3294 /* FIXME? Examine results here? */
3297 if (ioc->cached_fw) {
3298 /* If the DownloadBoot operation fails, the
3299 * IOC will be left unusable. This is a fatal error
3300 * case. _diag_reset will return < 0
3302 for (count = 0; count < 30; count ++) {
3303 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3304 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3309 if (sleepFlag == CAN_SLEEP) {
3310 msleep_interruptible (1000);
3315 if ((count = mpt_downloadboot(ioc,
3316 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3317 printk(KERN_WARNING MYNAM
3318 ": firmware downloadboot failure (%d)!\n", count);
3322 /* Wait for FW to reload and for board
3323 * to go to the READY state.
3324 * Maximum wait is 60 seconds.
3325 * If fail, no error will check again
3326 * with calling program.
3328 for (count = 0; count < 60; count ++) {
3329 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3330 doorbell &= MPI_IOC_STATE_MASK;
3332 if (doorbell == MPI_IOC_STATE_READY) {
3337 if (sleepFlag == CAN_SLEEP) {
3338 msleep_interruptible (1000);
3346 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3349 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3350 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3351 ioc->name, diag0val, diag1val));
3354 /* Clear RESET_HISTORY bit! Place board in the
3355 * diagnostic mode to update the diag register.
3357 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3359 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3360 /* Write magic sequence to WriteSequence register
3361 * Loop until in diagnostic mode
3363 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3364 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3365 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3366 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3367 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3368 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3371 if (sleepFlag == CAN_SLEEP) {
3372 msleep_interruptible (100);
3379 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3380 ioc->name, diag0val);
3383 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3385 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3386 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3387 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3388 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3389 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3393 /* Disable Diagnostic Mode
3395 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3397 /* Check FW reload status flags.
3399 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3400 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3401 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3402 ioc->name, diag0val);
3408 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3409 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3410 ioc->name, diag0val, diag1val));
3414 * Reset flag that says we've enabled event notification
3416 ioc->facts.EventState = 0;
3419 ioc->alt_ioc->facts.EventState = 0;
3421 return hard_reset_done;
3424 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3426 * SendIocReset - Send IOCReset request to MPT adapter.
3427 * @ioc: Pointer to MPT_ADAPTER structure
3428 * @reset_type: reset type, expected values are
3429 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3431 * Send IOCReset request to the MPT adapter.
3433 * Returns 0 for success, non-zero for failure.
3436 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3442 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3443 ioc->name, reset_type));
3444 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3445 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3448 /* FW ACK'd request, wait for READY state
3451 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3453 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3457 if (sleepFlag != CAN_SLEEP)
3460 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3461 ioc->name, (int)((count+5)/HZ));
3465 if (sleepFlag == CAN_SLEEP) {
3466 msleep_interruptible(1);
3468 mdelay (1); /* 1 msec delay */
3473 * Cleanup all event stuff for this IOC; re-issue EventNotification
3474 * request if needed.
3476 if (ioc->facts.Function)
3477 ioc->facts.EventState = 0;
3482 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3484 * initChainBuffers - Allocate memory for and initialize
3485 * chain buffers, chain buffer control arrays and spinlock.
3486 * @hd: Pointer to MPT_SCSI_HOST structure
3487 * @init: If set, initialize the spin lock.
3490 initChainBuffers(MPT_ADAPTER *ioc)
3493 int sz, ii, num_chain;
3494 int scale, num_sge, numSGE;
3496 /* ReqToChain size must equal the req_depth
3499 if (ioc->ReqToChain == NULL) {
3500 sz = ioc->req_depth * sizeof(int);
3501 mem = kmalloc(sz, GFP_ATOMIC);
3505 ioc->ReqToChain = (int *) mem;
3506 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3507 ioc->name, mem, sz));
3508 mem = kmalloc(sz, GFP_ATOMIC);
3512 ioc->RequestNB = (int *) mem;
3513 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3514 ioc->name, mem, sz));
3516 for (ii = 0; ii < ioc->req_depth; ii++) {
3517 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3520 /* ChainToChain size must equal the total number
3521 * of chain buffers to be allocated.
3524 * Calculate the number of chain buffers needed(plus 1) per I/O
3525 * then multiply the the maximum number of simultaneous cmds
3527 * num_sge = num sge in request frame + last chain buffer
3528 * scale = num sge per chain buffer if no chain element
3530 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3531 if (sizeof(dma_addr_t) == sizeof(u64))
3532 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3534 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3536 if (sizeof(dma_addr_t) == sizeof(u64)) {
3537 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3538 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3540 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3541 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3543 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3544 ioc->name, num_sge, numSGE));
3546 if ( numSGE > MPT_SCSI_SG_DEPTH )
3547 numSGE = MPT_SCSI_SG_DEPTH;
3550 while (numSGE - num_sge > 0) {
3552 num_sge += (scale - 1);
3556 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3557 ioc->name, numSGE, num_sge, num_chain));
3559 if (ioc->bus_type == SPI)
3560 num_chain *= MPT_SCSI_CAN_QUEUE;
3562 num_chain *= MPT_FC_CAN_QUEUE;
3564 ioc->num_chain = num_chain;
3566 sz = num_chain * sizeof(int);
3567 if (ioc->ChainToChain == NULL) {
3568 mem = kmalloc(sz, GFP_ATOMIC);
3572 ioc->ChainToChain = (int *) mem;
3573 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3574 ioc->name, mem, sz));
3576 mem = (u8 *) ioc->ChainToChain;
3578 memset(mem, 0xFF, sz);
3582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3584 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3585 * @ioc: Pointer to MPT_ADAPTER structure
3587 * This routine allocates memory for the MPT reply and request frame
3588 * pools (if necessary), and primes the IOC reply FIFO with
3591 * Returns 0 for success, non-zero for failure.
3594 PrimeIocFifos(MPT_ADAPTER *ioc)
3597 unsigned long flags;
3598 dma_addr_t alloc_dma;
3600 int i, reply_sz, sz, total_size, num_chain;
3602 /* Prime reply FIFO... */
3604 if (ioc->reply_frames == NULL) {
3605 if ( (num_chain = initChainBuffers(ioc)) < 0)
3608 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3609 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3610 ioc->name, ioc->reply_sz, ioc->reply_depth));
3611 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3612 ioc->name, reply_sz, reply_sz));
3614 sz = (ioc->req_sz * ioc->req_depth);
3615 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3616 ioc->name, ioc->req_sz, ioc->req_depth));
3617 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3618 ioc->name, sz, sz));
3621 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3622 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3623 ioc->name, ioc->req_sz, num_chain));
3624 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3625 ioc->name, sz, sz, num_chain));
3628 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3630 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3635 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3636 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3638 memset(mem, 0, total_size);
3639 ioc->alloc_total += total_size;
3641 ioc->alloc_dma = alloc_dma;
3642 ioc->alloc_sz = total_size;
3643 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3644 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3646 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3647 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3649 alloc_dma += reply_sz;
3652 /* Request FIFO - WE manage this! */
3654 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3655 ioc->req_frames_dma = alloc_dma;
3657 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3658 ioc->name, mem, (void *)(ulong)alloc_dma));
3660 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3662 #if defined(CONFIG_MTRR) && 0
3664 * Enable Write Combining MTRR for IOC's memory region.
3665 * (at least as much as we can; "size and base must be
3666 * multiples of 4 kiB"
3668 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3670 MTRR_TYPE_WRCOMB, 1);
3671 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3672 ioc->name, ioc->req_frames_dma, sz));
3675 for (i = 0; i < ioc->req_depth; i++) {
3676 alloc_dma += ioc->req_sz;
3680 ioc->ChainBuffer = mem;
3681 ioc->ChainBufferDMA = alloc_dma;
3683 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3684 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3686 /* Initialize the free chain Q.
3689 INIT_LIST_HEAD(&ioc->FreeChainQ);
3691 /* Post the chain buffers to the FreeChainQ.
3693 mem = (u8 *)ioc->ChainBuffer;
3694 for (i=0; i < num_chain; i++) {
3695 mf = (MPT_FRAME_HDR *) mem;
3696 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3700 /* Initialize Request frames linked list
3702 alloc_dma = ioc->req_frames_dma;
3703 mem = (u8 *) ioc->req_frames;
3705 spin_lock_irqsave(&ioc->FreeQlock, flags);
3706 INIT_LIST_HEAD(&ioc->FreeQ);
3707 for (i = 0; i < ioc->req_depth; i++) {
3708 mf = (MPT_FRAME_HDR *) mem;
3710 /* Queue REQUESTs *internally*! */
3711 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3715 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3717 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3718 ioc->sense_buf_pool =
3719 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3720 if (ioc->sense_buf_pool == NULL) {
3721 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3726 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3727 ioc->alloc_total += sz;
3728 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3729 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3733 /* Post Reply frames to FIFO
3735 alloc_dma = ioc->alloc_dma;
3736 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3737 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3739 for (i = 0; i < ioc->reply_depth; i++) {
3740 /* Write each address to the IOC! */
3741 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3742 alloc_dma += ioc->reply_sz;
3748 if (ioc->alloc != NULL) {
3750 pci_free_consistent(ioc->pcidev,
3752 ioc->alloc, ioc->alloc_dma);
3753 ioc->reply_frames = NULL;
3754 ioc->req_frames = NULL;
3755 ioc->alloc_total -= sz;
3757 if (ioc->sense_buf_pool != NULL) {
3758 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3759 pci_free_consistent(ioc->pcidev,
3761 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3762 ioc->sense_buf_pool = NULL;
3767 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3769 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3770 * from IOC via doorbell handshake method.
3771 * @ioc: Pointer to MPT_ADAPTER structure
3772 * @reqBytes: Size of the request in bytes
3773 * @req: Pointer to MPT request frame
3774 * @replyBytes: Expected size of the reply in bytes
3775 * @u16reply: Pointer to area where reply should be written
3776 * @maxwait: Max wait time for a reply (in seconds)
3777 * @sleepFlag: Specifies whether the process can sleep
3779 * NOTES: It is the callers responsibility to byte-swap fields in the
3780 * request which are greater than 1 byte in size. It is also the
3781 * callers responsibility to byte-swap response fields which are
3782 * greater than 1 byte in size.
3784 * Returns 0 for success, non-zero for failure.
3787 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3788 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3790 MPIDefaultReply_t *mptReply;
3795 * Get ready to cache a handshake reply
3797 ioc->hs_reply_idx = 0;
3798 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3799 mptReply->MsgLength = 0;
3802 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3803 * then tell IOC that we want to handshake a request of N words.
3804 * (WRITE u32val to Doorbell reg).
3806 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3807 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3808 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3809 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3812 * Wait for IOC's doorbell handshake int
3814 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3817 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3818 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3820 /* Read doorbell and check for active bit */
3821 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3825 * Clear doorbell int (WRITE 0 to IntStatus reg),
3826 * then wait for IOC to ACKnowledge that it's ready for
3827 * our handshake request.
3829 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3830 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3835 u8 *req_as_bytes = (u8 *) req;
3838 * Stuff request words via doorbell handshake,
3839 * with ACK from IOC for each.
3841 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3842 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3843 (req_as_bytes[(ii*4) + 1] << 8) |
3844 (req_as_bytes[(ii*4) + 2] << 16) |
3845 (req_as_bytes[(ii*4) + 3] << 24));
3847 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3848 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3852 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3853 DBG_DUMP_REQUEST_FRAME_HDR(req)
3855 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3856 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3859 * Wait for completion of doorbell handshake reply from the IOC
3861 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3864 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3865 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3868 * Copy out the cached reply...
3870 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3871 u16reply[ii] = ioc->hs_reply[ii];
3879 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3881 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3882 * in it's IntStatus register.
3883 * @ioc: Pointer to MPT_ADAPTER structure
3884 * @howlong: How long to wait (in seconds)
3885 * @sleepFlag: Specifies whether the process can sleep
3887 * This routine waits (up to ~2 seconds max) for IOC doorbell
3888 * handshake ACKnowledge.
3890 * Returns a negative value on failure, else wait loop count.
3893 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3899 cntdn = 1000 * howlong;
3901 if (sleepFlag == CAN_SLEEP) {
3903 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3904 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3906 msleep_interruptible (1);
3911 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3912 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3920 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3925 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3926 ioc->name, count, intstat);
3930 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3932 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3933 * in it's IntStatus register.
3934 * @ioc: Pointer to MPT_ADAPTER structure
3935 * @howlong: How long to wait (in seconds)
3936 * @sleepFlag: Specifies whether the process can sleep
3938 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3940 * Returns a negative value on failure, else wait loop count.
3943 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3949 cntdn = 1000 * howlong;
3950 if (sleepFlag == CAN_SLEEP) {
3952 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3953 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3955 msleep_interruptible(1);
3960 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3961 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3969 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3970 ioc->name, count, howlong));
3974 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3975 ioc->name, count, intstat);
3979 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3981 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3982 * @ioc: Pointer to MPT_ADAPTER structure
3983 * @howlong: How long to wait (in seconds)
3984 * @sleepFlag: Specifies whether the process can sleep
3986 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3987 * Reply is cached to IOC private area large enough to hold a maximum
3988 * of 128 bytes of reply data.
3990 * Returns a negative value on failure, else size of reply in WORDS.
3993 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3998 u16 *hs_reply = ioc->hs_reply;
3999 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4002 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4005 * Get first two u16's so we can look at IOC's intended reply MsgLength
4008 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4011 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4012 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4013 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4016 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4017 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4021 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4022 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4023 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4026 * If no error (and IOC said MsgLength is > 0), piece together
4027 * reply 16 bits at a time.
4029 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4030 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4032 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4033 /* don't overflow our IOC hs_reply[] buffer! */
4034 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4035 hs_reply[u16cnt] = hword;
4036 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4039 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4041 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4044 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4049 else if (u16cnt != (2 * mptReply->MsgLength)) {
4052 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4057 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4058 DBG_DUMP_REPLY_FRAME(mptReply)
4060 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4061 ioc->name, t, u16cnt/2));
4065 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4067 * GetLanConfigPages - Fetch LANConfig pages.
4068 * @ioc: Pointer to MPT_ADAPTER structure
4070 * Return: 0 for success
4071 * -ENOMEM if no memory available
4072 * -EPERM if not allowed due to ISR context
4073 * -EAGAIN if no msg frames currently available
4074 * -EFAULT for non-successful reply or no reply (timeout)
4077 GetLanConfigPages(MPT_ADAPTER *ioc)
4079 ConfigPageHeader_t hdr;
4081 LANPage0_t *ppage0_alloc;
4082 dma_addr_t page0_dma;
4083 LANPage1_t *ppage1_alloc;
4084 dma_addr_t page1_dma;
4089 /* Get LAN Page 0 header */
4090 hdr.PageVersion = 0;
4093 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4094 cfg.cfghdr.hdr = &hdr;
4096 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4101 if ((rc = mpt_config(ioc, &cfg)) != 0)
4104 if (hdr.PageLength > 0) {
4105 data_sz = hdr.PageLength * 4;
4106 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4109 memset((u8 *)ppage0_alloc, 0, data_sz);
4110 cfg.physAddr = page0_dma;
4111 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4113 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4115 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4116 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4120 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4123 * Normalize endianness of structure data,
4124 * by byte-swapping all > 1 byte fields!
4133 /* Get LAN Page 1 header */
4134 hdr.PageVersion = 0;
4137 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4138 cfg.cfghdr.hdr = &hdr;
4140 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4144 if ((rc = mpt_config(ioc, &cfg)) != 0)
4147 if (hdr.PageLength == 0)
4150 data_sz = hdr.PageLength * 4;
4152 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4154 memset((u8 *)ppage1_alloc, 0, data_sz);
4155 cfg.physAddr = page1_dma;
4156 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4158 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4160 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4161 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4164 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4167 * Normalize endianness of structure data,
4168 * by byte-swapping all > 1 byte fields!
4176 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4178 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4179 * @ioc: Pointer to MPT_ADAPTER structure
4180 * @portnum: IOC Port number
4182 * Return: 0 for success
4183 * -ENOMEM if no memory available
4184 * -EPERM if not allowed due to ISR context
4185 * -EAGAIN if no msg frames currently available
4186 * -EFAULT for non-successful reply or no reply (timeout)
4189 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4191 ConfigPageHeader_t hdr;
4193 FCPortPage0_t *ppage0_alloc;
4194 FCPortPage0_t *pp0dest;
4195 dma_addr_t page0_dma;
4202 /* Get FCPort Page 0 header */
4203 hdr.PageVersion = 0;
4206 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4207 cfg.cfghdr.hdr = &hdr;
4209 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4211 cfg.pageAddr = portnum;
4214 if ((rc = mpt_config(ioc, &cfg)) != 0)
4217 if (hdr.PageLength == 0)
4220 data_sz = hdr.PageLength * 4;
4222 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4226 memset((u8 *)ppage0_alloc, 0, data_sz);
4227 cfg.physAddr = page0_dma;
4228 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4230 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4232 pp0dest = &ioc->fc_port_page0[portnum];
4233 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4234 memcpy(pp0dest, ppage0_alloc, copy_sz);
4237 * Normalize endianness of structure data,
4238 * by byte-swapping all > 1 byte fields!
4240 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4241 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4242 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4243 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4244 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4245 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4246 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4247 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4248 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4249 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4250 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4251 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4252 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4253 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4254 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4255 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4258 * if still doing discovery,
4259 * hang loose a while until finished
4261 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4263 msleep_interruptible(100);
4266 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4272 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4280 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4281 * @ioc: Pointer to MPT_ADAPTER structure
4282 * @sas_address: 64bit SAS Address for operation.
4283 * @target_id: specified target for operation
4284 * @bus: specified bus for operation
4285 * @persist_opcode: see below
4287 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4288 * devices not currently present.
4289 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4291 * NOTE: Don't use not this function during interrupt time.
4293 * Returns: 0 for success, non-zero error
4296 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4298 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4300 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4301 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4302 MPT_FRAME_HDR *mf = NULL;
4303 MPIHeader_t *mpi_hdr;
4306 /* insure garbage is not sent to fw */
4307 switch(persist_opcode) {
4309 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4310 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4318 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4320 /* Get a MF for this command.
4322 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4323 printk("%s: no msg frames!\n",__FUNCTION__);
4327 mpi_hdr = (MPIHeader_t *) mf;
4328 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4329 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4330 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4331 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4332 sasIoUnitCntrReq->Operation = persist_opcode;
4334 init_timer(&ioc->persist_timer);
4335 ioc->persist_timer.data = (unsigned long) ioc;
4336 ioc->persist_timer.function = mpt_timer_expired;
4337 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4338 ioc->persist_wait_done=0;
4339 add_timer(&ioc->persist_timer);
4340 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4341 wait_event(mpt_waitq, ioc->persist_wait_done);
4343 sasIoUnitCntrReply =
4344 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4345 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4346 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4348 sasIoUnitCntrReply->IOCStatus,
4349 sasIoUnitCntrReply->IOCLogInfo);
4353 printk("%s: success\n",__FUNCTION__);
4357 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4360 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4361 MpiEventDataRaid_t * pRaidEventData)
4370 volume = pRaidEventData->VolumeID;
4371 reason = pRaidEventData->ReasonCode;
4372 disk = pRaidEventData->PhysDiskNum;
4373 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4374 flags = (status >> 0) & 0xff;
4375 state = (status >> 8) & 0xff;
4377 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4381 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4382 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4383 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4384 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4387 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4392 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4393 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4397 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4399 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4403 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4404 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4408 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4409 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4411 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4413 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4415 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4418 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4420 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4421 ? ", quiesced" : "",
4422 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4423 ? ", resync in progress" : "" );
4426 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4427 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4431 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4432 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4436 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4437 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4441 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4442 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4446 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4447 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4449 state == MPI_PHYSDISK0_STATUS_ONLINE
4451 : state == MPI_PHYSDISK0_STATUS_MISSING
4453 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4455 : state == MPI_PHYSDISK0_STATUS_FAILED
4457 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4459 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4460 ? "offline requested"
4461 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4462 ? "failed requested"
4463 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4466 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4467 ? ", out of sync" : "",
4468 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4469 ? ", quiesced" : "" );
4472 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4473 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4477 case MPI_EVENT_RAID_RC_SMART_DATA:
4478 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4479 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4482 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4483 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4491 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4492 * @ioc: Pointer to MPT_ADAPTER structure
4494 * Returns: 0 for success
4495 * -ENOMEM if no memory available
4496 * -EPERM if not allowed due to ISR context
4497 * -EAGAIN if no msg frames currently available
4498 * -EFAULT for non-successful reply or no reply (timeout)
4501 GetIoUnitPage2(MPT_ADAPTER *ioc)
4503 ConfigPageHeader_t hdr;
4505 IOUnitPage2_t *ppage_alloc;
4506 dma_addr_t page_dma;
4510 /* Get the page header */
4511 hdr.PageVersion = 0;
4514 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4515 cfg.cfghdr.hdr = &hdr;
4517 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4522 if ((rc = mpt_config(ioc, &cfg)) != 0)
4525 if (hdr.PageLength == 0)
4528 /* Read the config page */
4529 data_sz = hdr.PageLength * 4;
4531 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4533 memset((u8 *)ppage_alloc, 0, data_sz);
4534 cfg.physAddr = page_dma;
4535 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4537 /* If Good, save data */
4538 if ((rc = mpt_config(ioc, &cfg)) == 0)
4539 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4541 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4547 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4548 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4549 * @ioc: Pointer to a Adapter Strucutre
4550 * @portnum: IOC port number
4552 * Return: -EFAULT if read of config page header fails
4554 * If read of SCSI Port Page 0 fails,
4555 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4556 * Adapter settings: async, narrow
4558 * If read of SCSI Port Page 2 fails,
4559 * Adapter settings valid
4560 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4565 * CHECK - what type of locking mechanisms should be used????
4568 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4573 ConfigPageHeader_t header;
4579 if (!ioc->spi_data.nvram) {
4582 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4583 mem = kmalloc(sz, GFP_ATOMIC);
4587 ioc->spi_data.nvram = (int *) mem;
4589 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4590 ioc->name, ioc->spi_data.nvram, sz));
4593 /* Invalidate NVRAM information
4595 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4596 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4599 /* Read SPP0 header, allocate memory, then read page.
4601 header.PageVersion = 0;
4602 header.PageLength = 0;
4603 header.PageNumber = 0;
4604 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4605 cfg.cfghdr.hdr = &header;
4607 cfg.pageAddr = portnum;
4608 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4610 cfg.timeout = 0; /* use default */
4611 if (mpt_config(ioc, &cfg) != 0)
4614 if (header.PageLength > 0) {
4615 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4617 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4618 cfg.physAddr = buf_dma;
4619 if (mpt_config(ioc, &cfg) != 0) {
4620 ioc->spi_data.maxBusWidth = MPT_NARROW;
4621 ioc->spi_data.maxSyncOffset = 0;
4622 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4623 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4625 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4626 ioc->name, ioc->spi_data.minSyncFactor));
4628 /* Save the Port Page 0 data
4630 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4631 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4632 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4634 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4635 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4636 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4637 ioc->name, pPP0->Capabilities));
4639 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4640 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4642 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4643 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4644 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4645 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4646 ioc->name, ioc->spi_data.minSyncFactor));
4648 ioc->spi_data.maxSyncOffset = 0;
4649 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4652 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4654 /* Update the minSyncFactor based on bus type.
4656 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4657 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4659 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4660 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4661 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4662 ioc->name, ioc->spi_data.minSyncFactor));
4667 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4672 /* SCSI Port Page 2 - Read the header then the page.
4674 header.PageVersion = 0;
4675 header.PageLength = 0;
4676 header.PageNumber = 2;
4677 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4678 cfg.cfghdr.hdr = &header;
4680 cfg.pageAddr = portnum;
4681 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4683 if (mpt_config(ioc, &cfg) != 0)
4686 if (header.PageLength > 0) {
4687 /* Allocate memory and read SCSI Port Page 2
4689 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4691 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4692 cfg.physAddr = buf_dma;
4693 if (mpt_config(ioc, &cfg) != 0) {
4694 /* Nvram data is left with INVALID mark
4698 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4699 MpiDeviceInfo_t *pdevice = NULL;
4702 * Save "Set to Avoid SCSI Bus Resets" flag
4704 ioc->spi_data.bus_reset =
4705 (le32_to_cpu(pPP2->PortFlags) &
4706 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4709 /* Save the Port Page 2 data
4710 * (reformat into a 32bit quantity)
4712 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4713 ioc->spi_data.PortFlags = data;
4714 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4715 pdevice = &pPP2->DeviceSettings[ii];
4716 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4717 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4718 ioc->spi_data.nvram[ii] = data;
4722 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4726 /* Update Adapter limits with those from NVRAM
4727 * Comment: Don't need to do this. Target performance
4728 * parameters will never exceed the adapters limits.
4734 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4735 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4736 * @ioc: Pointer to a Adapter Strucutre
4737 * @portnum: IOC port number
4739 * Return: -EFAULT if read of config page header fails
4743 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4746 ConfigPageHeader_t header;
4748 /* Read the SCSI Device Page 1 header
4750 header.PageVersion = 0;
4751 header.PageLength = 0;
4752 header.PageNumber = 1;
4753 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4754 cfg.cfghdr.hdr = &header;
4756 cfg.pageAddr = portnum;
4757 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4760 if (mpt_config(ioc, &cfg) != 0)
4763 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4764 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4766 header.PageVersion = 0;
4767 header.PageLength = 0;
4768 header.PageNumber = 0;
4769 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4770 if (mpt_config(ioc, &cfg) != 0)
4773 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4774 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4776 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4777 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4779 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4780 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4786 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4787 * @ioc: Pointer to a Adapter Strucutre
4788 * @portnum: IOC port number
4792 * -EFAULT if read of config page header fails or data pointer not NULL
4793 * -ENOMEM if pci_alloc failed
4796 mpt_findImVolumes(MPT_ADAPTER *ioc)
4800 ConfigPageIoc2RaidVol_t *pIocRv;
4801 dma_addr_t ioc2_dma;
4803 ConfigPageHeader_t header;
4810 /* Read IOCP2 header then the page.
4812 header.PageVersion = 0;
4813 header.PageLength = 0;
4814 header.PageNumber = 2;
4815 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4816 cfg.cfghdr.hdr = &header;
4819 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4822 if (mpt_config(ioc, &cfg) != 0)
4825 if (header.PageLength == 0)
4828 iocpage2sz = header.PageLength * 4;
4829 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4833 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4834 cfg.physAddr = ioc2_dma;
4835 if (mpt_config(ioc, &cfg) != 0)
4838 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4839 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4841 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4846 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4848 /* Identify RAID Volume Id's */
4849 nVols = pIoc2->NumActiveVolumes;
4855 /* At least 1 RAID Volume
4857 pIocRv = pIoc2->RaidVolume;
4858 ioc->raid_data.isRaid = 0;
4859 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4860 vid = pIocRv->VolumeID;
4861 vbus = pIocRv->VolumeBus;
4862 vioc = pIocRv->VolumeIOC;
4867 ioc->raid_data.isRaid |= (1 << vid);
4869 /* Error! Always bus 0
4875 /* Identify Hidden Physical Disk Id's */
4876 nPhys = pIoc2->NumActivePhysDisks;
4878 /* No physical disks.
4881 mpt_read_ioc_pg_3(ioc);
4885 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4891 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4896 ConfigPageHeader_t header;
4897 dma_addr_t ioc3_dma;
4900 /* Free the old page
4902 kfree(ioc->raid_data.pIocPg3);
4903 ioc->raid_data.pIocPg3 = NULL;
4905 /* There is at least one physical disk.
4906 * Read and save IOC Page 3
4908 header.PageVersion = 0;
4909 header.PageLength = 0;
4910 header.PageNumber = 3;
4911 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4912 cfg.cfghdr.hdr = &header;
4915 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4918 if (mpt_config(ioc, &cfg) != 0)
4921 if (header.PageLength == 0)
4924 /* Read Header good, alloc memory
4926 iocpage3sz = header.PageLength * 4;
4927 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4931 /* Read the Page and save the data
4932 * into malloc'd memory.
4934 cfg.physAddr = ioc3_dma;
4935 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4936 if (mpt_config(ioc, &cfg) == 0) {
4937 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4939 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4940 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4944 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4950 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4954 ConfigPageHeader_t header;
4955 dma_addr_t ioc4_dma;
4958 /* Read and save IOC Page 4
4960 header.PageVersion = 0;
4961 header.PageLength = 0;
4962 header.PageNumber = 4;
4963 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4964 cfg.cfghdr.hdr = &header;
4967 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4970 if (mpt_config(ioc, &cfg) != 0)
4973 if (header.PageLength == 0)
4976 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4977 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4978 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4982 ioc4_dma = ioc->spi_data.IocPg4_dma;
4983 iocpage4sz = ioc->spi_data.IocPg4Sz;
4986 /* Read the Page into dma memory.
4988 cfg.physAddr = ioc4_dma;
4989 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4990 if (mpt_config(ioc, &cfg) == 0) {
4991 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4992 ioc->spi_data.IocPg4_dma = ioc4_dma;
4993 ioc->spi_data.IocPg4Sz = iocpage4sz;
4995 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4996 ioc->spi_data.pIocPg4 = NULL;
5001 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5005 ConfigPageHeader_t header;
5006 dma_addr_t ioc1_dma;
5010 /* Check the Coalescing Timeout in IOC Page 1
5012 header.PageVersion = 0;
5013 header.PageLength = 0;
5014 header.PageNumber = 1;
5015 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5016 cfg.cfghdr.hdr = &header;
5019 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5022 if (mpt_config(ioc, &cfg) != 0)
5025 if (header.PageLength == 0)
5028 /* Read Header good, alloc memory
5030 iocpage1sz = header.PageLength * 4;
5031 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5035 /* Read the Page and check coalescing timeout
5037 cfg.physAddr = ioc1_dma;
5038 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5039 if (mpt_config(ioc, &cfg) == 0) {
5041 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5042 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5043 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5045 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
5048 if (tmp > MPT_COALESCING_TIMEOUT) {
5049 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5051 /* Write NVRAM and current
5054 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5055 if (mpt_config(ioc, &cfg) == 0) {
5056 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
5057 ioc->name, MPT_COALESCING_TIMEOUT));
5059 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5060 if (mpt_config(ioc, &cfg) == 0) {
5061 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
5062 ioc->name, MPT_COALESCING_TIMEOUT));
5064 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
5069 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
5075 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5079 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5084 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5086 * SendEventNotification - Send EventNotification (on or off) request
5088 * @ioc: Pointer to MPT_ADAPTER structure
5089 * @EvSwitch: Event switch flags
5092 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5094 EventNotification_t *evnp;
5096 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5098 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5102 memset(evnp, 0, sizeof(*evnp));
5104 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5106 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5107 evnp->ChainOffset = 0;
5109 evnp->Switch = EvSwitch;
5111 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5116 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5118 * SendEventAck - Send EventAck request to MPT adapter.
5119 * @ioc: Pointer to MPT_ADAPTER structure
5120 * @evnp: Pointer to original EventNotification request
5123 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5127 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5128 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5129 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5130 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5131 le32_to_cpu(evnp->Data[0]));
5134 memset(pAck, 0, sizeof(*pAck));
5136 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5138 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5139 pAck->ChainOffset = 0;
5141 pAck->Event = evnp->Event;
5142 pAck->EventContext = evnp->EventContext;
5144 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5151 * mpt_config - Generic function to issue config message
5152 * @ioc - Pointer to an adapter structure
5153 * @cfg - Pointer to a configuration structure. Struct contains
5154 * action, page address, direction, physical address
5155 * and pointer to a configuration page header
5156 * Page header is updated.
5158 * Returns 0 for success
5159 * -EPERM if not allowed due to ISR context
5160 * -EAGAIN if no msg frames currently available
5161 * -EFAULT for non-successful reply or no reply (timeout)
5164 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5167 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5169 unsigned long flags;
5174 /* Prevent calling wait_event() (below), if caller happens
5175 * to be in ISR context, because that is fatal!
5177 in_isr = in_interrupt();
5179 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5184 /* Get and Populate a free Frame
5186 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5187 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5191 pReq = (Config_t *)mf;
5192 pReq->Action = pCfg->action;
5194 pReq->ChainOffset = 0;
5195 pReq->Function = MPI_FUNCTION_CONFIG;
5197 /* Assume page type is not extended and clear "reserved" fields. */
5198 pReq->ExtPageLength = 0;
5199 pReq->ExtPageType = 0;
5202 for (ii=0; ii < 8; ii++)
5203 pReq->Reserved2[ii] = 0;
5205 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5206 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5207 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5208 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5210 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5211 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5212 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5213 pReq->ExtPageType = pExtHdr->ExtPageType;
5214 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5216 /* Page Length must be treated as a reserved field for the extended header. */
5217 pReq->Header.PageLength = 0;
5220 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5222 /* Add a SGE to the config request.
5225 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5227 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5229 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5230 flagsLength |= pExtHdr->ExtPageLength * 4;
5232 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5233 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5236 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5238 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5239 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5242 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5244 /* Append pCfg pointer to end of mf
5246 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5248 /* Initalize the timer
5250 init_timer(&pCfg->timer);
5251 pCfg->timer.data = (unsigned long) ioc;
5252 pCfg->timer.function = mpt_timer_expired;
5253 pCfg->wait_done = 0;
5255 /* Set the timer; ensure 10 second minimum */
5256 if (pCfg->timeout < 10)
5257 pCfg->timer.expires = jiffies + HZ*10;
5259 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5261 /* Add to end of Q, set timer and then issue this command */
5262 spin_lock_irqsave(&ioc->FreeQlock, flags);
5263 list_add_tail(&pCfg->linkage, &ioc->configQ);
5264 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5266 add_timer(&pCfg->timer);
5267 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5268 wait_event(mpt_waitq, pCfg->wait_done);
5270 /* mf has been freed - do not access */
5277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5279 * mpt_timer_expired - Call back for timer process.
5280 * Used only internal config functionality.
5281 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5284 mpt_timer_expired(unsigned long data)
5286 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5288 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5290 /* Perform a FW reload */
5291 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5292 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5294 /* No more processing.
5295 * Hard reset clean-up will wake up
5296 * process and free all resources.
5298 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5303 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5305 * mpt_ioc_reset - Base cleanup for hard reset
5306 * @ioc: Pointer to the adapter structure
5307 * @reset_phase: Indicates pre- or post-reset functionality
5309 * Remark: Free's resources with internally generated commands.
5312 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5315 unsigned long flags;
5317 dprintk((KERN_WARNING MYNAM
5318 ": IOC %s_reset routed to MPT base driver!\n",
5319 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5320 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5322 if (reset_phase == MPT_IOC_SETUP_RESET) {
5324 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5325 /* If the internal config Q is not empty -
5326 * delete timer. MF resources will be freed when
5327 * the FIFO's are primed.
5329 spin_lock_irqsave(&ioc->FreeQlock, flags);
5330 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5331 del_timer(&pCfg->timer);
5332 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5337 /* Search the configQ for internal commands.
5338 * Flush the Q, and wake up all suspended threads.
5340 spin_lock_irqsave(&ioc->FreeQlock, flags);
5341 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5342 list_del(&pCfg->linkage);
5344 pCfg->status = MPT_CONFIG_ERROR;
5345 pCfg->wait_done = 1;
5346 wake_up(&mpt_waitq);
5348 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5351 return 1; /* currently means nothing really */
5355 #ifdef CONFIG_PROC_FS /* { */
5356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5358 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5362 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5364 * Returns 0 for success, non-zero for failure.
5367 procmpt_create(void)
5369 struct proc_dir_entry *ent;
5371 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5372 if (mpt_proc_root_dir == NULL)
5375 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5377 ent->read_proc = procmpt_summary_read;
5379 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5381 ent->read_proc = procmpt_version_read;
5386 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5388 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5390 * Returns 0 for success, non-zero for failure.
5393 procmpt_destroy(void)
5395 remove_proc_entry("version", mpt_proc_root_dir);
5396 remove_proc_entry("summary", mpt_proc_root_dir);
5397 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5402 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5403 * or from /proc/mpt/iocN/summary.
5404 * @buf: Pointer to area to write information
5405 * @start: Pointer to start pointer
5406 * @offset: Offset to start writing
5408 * @eof: Pointer to EOF integer
5411 * Returns number of characters written to process performing the read.
5414 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5424 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5428 list_for_each_entry(ioc, &ioc_list, list) {
5431 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5434 if ((out-buf) >= request)
5441 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5444 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5446 * procmpt_version_read - Handle read request from /proc/mpt/version.
5447 * @buf: Pointer to area to write information
5448 * @start: Pointer to start pointer
5449 * @offset: Offset to start writing
5451 * @eof: Pointer to EOF integer
5454 * Returns number of characters written to process performing the read.
5457 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5460 int scsi, fc, sas, lan, ctl, targ, dmp;
5464 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5465 len += sprintf(buf+len, " Fusion MPT base driver\n");
5467 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5468 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5470 if (MptCallbacks[ii]) {
5471 switch (MptDriverClass[ii]) {
5473 if (!scsi++) drvname = "SPI host";
5476 if (!fc++) drvname = "FC host";
5479 if (!sas++) drvname = "SAS host";
5482 if (!lan++) drvname = "LAN";
5485 if (!targ++) drvname = "SCSI target";
5488 if (!ctl++) drvname = "ioctl";
5493 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5497 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5500 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5502 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5503 * @buf: Pointer to area to write information
5504 * @start: Pointer to start pointer
5505 * @offset: Offset to start writing
5507 * @eof: Pointer to EOF integer
5510 * Returns number of characters written to process performing the read.
5513 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5515 MPT_ADAPTER *ioc = data;
5521 mpt_get_fw_exp_ver(expVer, ioc);
5523 len = sprintf(buf, "%s:", ioc->name);
5524 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5525 len += sprintf(buf+len, " (f/w download boot flag set)");
5526 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5527 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5529 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5530 ioc->facts.ProductID,
5532 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5533 if (ioc->facts.FWImageSize)
5534 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5535 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5536 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5537 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5539 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5540 ioc->facts.CurrentHostMfaHighAddr);
5541 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5542 ioc->facts.CurrentSenseBufferHighAddr);
5544 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5545 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5547 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5548 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5550 * Rounding UP to nearest 4-kB boundary here...
5552 sz = (ioc->req_sz * ioc->req_depth) + 128;
5553 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5554 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5555 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5556 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5557 4*ioc->facts.RequestFrameSize,
5558 ioc->facts.GlobalCredits);
5560 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5561 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5562 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5563 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5564 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5565 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5566 ioc->facts.CurReplyFrameSize,
5567 ioc->facts.ReplyQueueDepth);
5569 len += sprintf(buf+len, " MaxDevices = %d\n",
5570 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5571 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5574 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5575 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5577 ioc->facts.NumberOfPorts);
5578 if (ioc->bus_type == FC) {
5579 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5580 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5581 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5582 a[5], a[4], a[3], a[2], a[1], a[0]);
5584 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5585 ioc->fc_port_page0[p].WWNN.High,
5586 ioc->fc_port_page0[p].WWNN.Low,
5587 ioc->fc_port_page0[p].WWPN.High,
5588 ioc->fc_port_page0[p].WWPN.Low);
5592 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5595 #endif /* CONFIG_PROC_FS } */
5597 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5599 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5602 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5603 sprintf(buf, " (Exp %02d%02d)",
5604 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5605 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5608 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5609 strcat(buf, " [MDBG]");
5613 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5615 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5616 * @ioc: Pointer to MPT_ADAPTER structure
5617 * @buffer: Pointer to buffer where IOC summary info should be written
5618 * @size: Pointer to number of bytes we wrote (set by this routine)
5619 * @len: Offset at which to start writing in buffer
5620 * @showlan: Display LAN stuff?
5622 * This routine writes (english readable) ASCII text, which represents
5623 * a summary of IOC information, to a buffer.
5626 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5631 mpt_get_fw_exp_ver(expVer, ioc);
5634 * Shorter summary of attached ioc's...
5636 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5639 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5640 ioc->facts.FWVersion.Word,
5642 ioc->facts.NumberOfPorts,
5645 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5646 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5647 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5648 a[5], a[4], a[3], a[2], a[1], a[0]);
5652 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5654 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5658 y += sprintf(buffer+len+y, " (disabled)");
5660 y += sprintf(buffer+len+y, "\n");
5665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5669 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5671 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5672 * Management call based on input arg values. If TaskMgmt fails,
5673 * return associated SCSI request.
5674 * @ioc: Pointer to MPT_ADAPTER structure
5675 * @sleepFlag: Indicates if sleep or schedule must be called.
5677 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5678 * or a non-interrupt thread. In the former, must not call schedule().
5680 * Remark: A return of -1 is a FATAL error case, as it means a
5681 * FW reload/initialization failed.
5683 * Returns 0 for SUCCESS or -1 if FAILED.
5686 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5689 unsigned long flags;
5691 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5693 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5694 printk("MF count 0x%x !\n", ioc->mfcnt);
5697 /* Reset the adapter. Prevent more than 1 call to
5698 * mpt_do_ioc_recovery at any instant in time.
5700 spin_lock_irqsave(&ioc->diagLock, flags);
5701 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5702 spin_unlock_irqrestore(&ioc->diagLock, flags);
5705 ioc->diagPending = 1;
5707 spin_unlock_irqrestore(&ioc->diagLock, flags);
5709 /* FIXME: If do_ioc_recovery fails, repeat....
5712 /* The SCSI driver needs to adjust timeouts on all current
5713 * commands prior to the diagnostic reset being issued.
5714 * Prevents timeouts occuring during a diagnostic reset...very bad.
5715 * For all other protocol drivers, this is a no-op.
5721 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5722 if (MptResetHandlers[ii]) {
5723 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5725 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5727 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5728 ioc->name, ioc->alt_ioc->name, ii));
5729 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5735 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5736 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5741 ioc->alt_ioc->reload_fw = 0;
5743 spin_lock_irqsave(&ioc->diagLock, flags);
5744 ioc->diagPending = 0;
5746 ioc->alt_ioc->diagPending = 0;
5747 spin_unlock_irqrestore(&ioc->diagLock, flags);
5749 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5754 # define EVENT_DESCR_STR_SZ 100
5756 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5758 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5763 case MPI_EVENT_NONE:
5766 case MPI_EVENT_LOG_DATA:
5769 case MPI_EVENT_STATE_CHANGE:
5770 ds = "State Change";
5772 case MPI_EVENT_UNIT_ATTENTION:
5773 ds = "Unit Attention";
5775 case MPI_EVENT_IOC_BUS_RESET:
5776 ds = "IOC Bus Reset";
5778 case MPI_EVENT_EXT_BUS_RESET:
5779 ds = "External Bus Reset";
5781 case MPI_EVENT_RESCAN:
5782 ds = "Bus Rescan Event";
5783 /* Ok, do we need to do anything here? As far as
5784 I can tell, this is when a new device gets added
5787 case MPI_EVENT_LINK_STATUS_CHANGE:
5788 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5789 ds = "Link Status(FAILURE) Change";
5791 ds = "Link Status(ACTIVE) Change";
5793 case MPI_EVENT_LOOP_STATE_CHANGE:
5794 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5795 ds = "Loop State(LIP) Change";
5796 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5797 ds = "Loop State(LPE) Change"; /* ??? */
5799 ds = "Loop State(LPB) Change"; /* ??? */
5801 case MPI_EVENT_LOGOUT:
5804 case MPI_EVENT_EVENT_CHANGE:
5806 ds = "Events(ON) Change";
5808 ds = "Events(OFF) Change";
5810 case MPI_EVENT_INTEGRATED_RAID:
5812 u8 ReasonCode = (u8)(evData0 >> 16);
5813 switch (ReasonCode) {
5814 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5815 ds = "Integrated Raid: Volume Created";
5817 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5818 ds = "Integrated Raid: Volume Deleted";
5820 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5821 ds = "Integrated Raid: Volume Settings Changed";
5823 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5824 ds = "Integrated Raid: Volume Status Changed";
5826 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5827 ds = "Integrated Raid: Volume Physdisk Changed";
5829 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5830 ds = "Integrated Raid: Physdisk Created";
5832 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5833 ds = "Integrated Raid: Physdisk Deleted";
5835 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5836 ds = "Integrated Raid: Physdisk Settings Changed";
5838 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5839 ds = "Integrated Raid: Physdisk Status Changed";
5841 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5842 ds = "Integrated Raid: Domain Validation Needed";
5844 case MPI_EVENT_RAID_RC_SMART_DATA :
5845 ds = "Integrated Raid; Smart Data";
5847 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5848 ds = "Integrated Raid: Replace Action Started";
5851 ds = "Integrated Raid";
5856 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5857 ds = "SCSI Device Status Change";
5859 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5861 u8 id = (u8)(evData0);
5862 u8 ReasonCode = (u8)(evData0 >> 16);
5863 switch (ReasonCode) {
5864 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5865 snprintf(evStr, EVENT_DESCR_STR_SZ,
5866 "SAS Device Status Change: Added: id=%d", id);
5868 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5869 snprintf(evStr, EVENT_DESCR_STR_SZ,
5870 "SAS Device Status Change: Deleted: id=%d", id);
5872 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5873 snprintf(evStr, EVENT_DESCR_STR_SZ,
5874 "SAS Device Status Change: SMART Data: id=%d",
5877 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5878 snprintf(evStr, EVENT_DESCR_STR_SZ,
5879 "SAS Device Status Change: No Persistancy "
5880 "Added: id=%d", id);
5883 snprintf(evStr, EVENT_DESCR_STR_SZ,
5884 "SAS Device Status Change: Unknown: id=%d", id);
5889 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5890 ds = "Bus Timer Expired";
5892 case MPI_EVENT_QUEUE_FULL:
5895 case MPI_EVENT_SAS_SES:
5896 ds = "SAS SES Event";
5898 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5899 ds = "Persistent Table Full";
5901 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5903 u8 LinkRates = (u8)(evData0 >> 8);
5904 u8 PhyNumber = (u8)(evData0);
5905 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5906 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5907 switch (LinkRates) {
5908 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5909 snprintf(evStr, EVENT_DESCR_STR_SZ,
5910 "SAS PHY Link Status: Phy=%d:"
5911 " Rate Unknown",PhyNumber);
5913 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5914 snprintf(evStr, EVENT_DESCR_STR_SZ,
5915 "SAS PHY Link Status: Phy=%d:"
5916 " Phy Disabled",PhyNumber);
5918 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5919 snprintf(evStr, EVENT_DESCR_STR_SZ,
5920 "SAS PHY Link Status: Phy=%d:"
5921 " Failed Speed Nego",PhyNumber);
5923 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5924 snprintf(evStr, EVENT_DESCR_STR_SZ,
5925 "SAS PHY Link Status: Phy=%d:"
5926 " Sata OOB Completed",PhyNumber);
5928 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5929 snprintf(evStr, EVENT_DESCR_STR_SZ,
5930 "SAS PHY Link Status: Phy=%d:"
5931 " Rate 1.5 Gbps",PhyNumber);
5933 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5934 snprintf(evStr, EVENT_DESCR_STR_SZ,
5935 "SAS PHY Link Status: Phy=%d:"
5936 " Rate 3.0 Gpbs",PhyNumber);
5939 snprintf(evStr, EVENT_DESCR_STR_SZ,
5940 "SAS PHY Link Status: Phy=%d", PhyNumber);
5945 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5946 ds = "SAS Discovery Error";
5948 case MPI_EVENT_IR_RESYNC_UPDATE:
5950 u8 resync_complete = (u8)(evData0 >> 16);
5951 snprintf(evStr, EVENT_DESCR_STR_SZ,
5952 "IR Resync Update: Complete = %d:",resync_complete);
5957 u8 ReasonCode = (u8)(evData0 >> 16);
5958 switch (ReasonCode) {
5959 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5960 ds = "IR2: LD State Changed";
5962 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5963 ds = "IR2: PD State Changed";
5965 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5966 ds = "IR2: Bad Block Table Full";
5968 case MPI_EVENT_IR2_RC_PD_INSERTED:
5969 ds = "IR2: PD Inserted";
5971 case MPI_EVENT_IR2_RC_PD_REMOVED:
5972 ds = "IR2: PD Removed";
5974 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5975 ds = "IR2: Foreign CFG Detected";
5977 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5978 ds = "IR2: Rebuild Medium Error";
5986 case MPI_EVENT_SAS_DISCOVERY:
5989 ds = "SAS Discovery: Start";
5991 ds = "SAS Discovery: Stop";
5994 case MPI_EVENT_LOG_ENTRY_ADDED:
5995 ds = "SAS Log Entry Added";
5999 * MPT base "custom" events may be added here...
6006 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6009 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6011 * ProcessEventNotification - Route a received EventNotificationReply to
6012 * all currently regeistered event handlers.
6013 * @ioc: Pointer to MPT_ADAPTER structure
6014 * @pEventReply: Pointer to EventNotification reply frame
6015 * @evHandlers: Pointer to integer, number of event handlers
6017 * Returns sum of event handlers return values.
6020 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6028 char evStr[EVENT_DESCR_STR_SZ];
6032 * Do platform normalization of values
6034 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6035 // evCtx = le32_to_cpu(pEventReply->EventContext);
6036 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6038 evData0 = le32_to_cpu(pEventReply->Data[0]);
6041 EventDescriptionStr(event, evData0, evStr);
6042 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
6047 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
6048 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
6049 for (ii = 0; ii < evDataLen; ii++)
6050 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
6055 * Do general / base driver event processing
6058 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6060 u8 evState = evData0 & 0xFF;
6062 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6064 /* Update EventState field in cached IocFacts */
6065 if (ioc->facts.Function) {
6066 ioc->facts.EventState = evState;
6070 case MPI_EVENT_INTEGRATED_RAID:
6071 mptbase_raid_process_event_data(ioc,
6072 (MpiEventDataRaid_t *)pEventReply->Data);
6079 * Should this event be logged? Events are written sequentially.
6080 * When buffer is full, start again at the top.
6082 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6085 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6087 ioc->events[idx].event = event;
6088 ioc->events[idx].eventContext = ioc->eventContext;
6090 for (ii = 0; ii < 2; ii++) {
6092 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6094 ioc->events[idx].data[ii] = 0;
6097 ioc->eventContext++;
6102 * Call each currently registered protocol event handler.
6104 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6105 if (MptEvHandlers[ii]) {
6106 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6108 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6112 /* FIXME? Examine results here? */
6115 * If needed, send (a single) EventAck.
6117 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6118 devtverboseprintk((MYIOC_s_WARN_FMT
6119 "EventAck required\n",ioc->name));
6120 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6121 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6126 *evHandlers = handlers;
6130 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6132 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6133 * @ioc: Pointer to MPT_ADAPTER structure
6134 * @log_info: U32 LogInfo reply word from the IOC
6136 * Refer to lsi/fc_log.h.
6139 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6141 static char *subcl_str[8] = {
6142 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6143 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6145 u8 subcl = (log_info >> 24) & 0x7;
6147 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6148 ioc->name, log_info, subcl_str[subcl]);
6151 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6153 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6154 * @ioc: Pointer to MPT_ADAPTER structure
6155 * @mr: Pointer to MPT reply frame
6156 * @log_info: U32 LogInfo word from the IOC
6158 * Refer to lsi/sp_log.h.
6161 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6163 u32 info = log_info & 0x00FF0000;
6164 char *desc = "unknown";
6168 desc = "bug! MID not found";
6169 if (ioc->reload_fw == 0)
6174 desc = "Parity Error";
6178 desc = "ASYNC Outbound Overrun";
6182 desc = "SYNC Offset Error";
6190 desc = "Msg In Overflow";
6198 desc = "Outbound DMA Overrun";
6202 desc = "Task Management";
6206 desc = "Device Problem";
6210 desc = "Invalid Phase Change";
6214 desc = "Untagged Table Size";
6219 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6222 /* strings for sas loginfo */
6223 static char *originator_str[] = {
6228 static char *iop_code_str[] = {
6230 "Invalid SAS Address", /* 01h */
6232 "Invalid Page", /* 03h */
6234 "Task Terminated" /* 05h */
6236 static char *pl_code_str[] = {
6238 "Open Failure", /* 01h */
6239 "Invalid Scatter Gather List", /* 02h */
6240 "Wrong Relative Offset or Frame Length", /* 03h */
6241 "Frame Transfer Error", /* 04h */
6242 "Transmit Frame Connected Low", /* 05h */
6243 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6244 "SATA Read Log Receive Data Error", /* 07h */
6245 "SATA NCQ Fail All Commands After Error", /* 08h */
6246 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6247 "Receive Frame Invalid Message", /* 0Ah */
6248 "Receive Context Message Valid Error", /* 0Bh */
6249 "Receive Frame Current Frame Error", /* 0Ch */
6250 "SATA Link Down", /* 0Dh */
6251 "Discovery SATA Init W IOS", /* 0Eh */
6252 "Config Invalid Page", /* 0Fh */
6253 "Discovery SATA Init Timeout", /* 10h */
6256 "IO Not Yet Executed", /* 13h */
6257 "IO Executed", /* 14h */
6258 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6259 "Open Transmit DMA Abort", /* 16h */
6269 "Enclosure Management" /* 20h */
6272 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6274 * mpt_sas_log_info - Log information returned from SAS IOC.
6275 * @ioc: Pointer to MPT_ADAPTER structure
6276 * @log_info: U32 LogInfo reply word from the IOC
6278 * Refer to lsi/mpi_log_sas.h.
6281 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6283 union loginfo_type {
6292 union loginfo_type sas_loginfo;
6293 char *code_desc = NULL;
6295 sas_loginfo.loginfo = log_info;
6296 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6297 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6299 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6300 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6301 code_desc = iop_code_str[sas_loginfo.dw.code];
6302 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6303 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6304 code_desc = pl_code_str[sas_loginfo.dw.code];
6307 if (code_desc != NULL)
6308 printk(MYIOC_s_INFO_FMT
6309 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6310 " SubCode(0x%04x)\n",
6313 originator_str[sas_loginfo.dw.originator],
6315 sas_loginfo.dw.subcode);
6317 printk(MYIOC_s_INFO_FMT
6318 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6319 " SubCode(0x%04x)\n",
6322 originator_str[sas_loginfo.dw.originator],
6323 sas_loginfo.dw.code,
6324 sas_loginfo.dw.subcode);
6327 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6329 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6330 * @ioc: Pointer to MPT_ADAPTER structure
6331 * @ioc_status: U32 IOCStatus word from IOC
6332 * @mf: Pointer to MPT request frame
6334 * Refer to lsi/mpi.h.
6337 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6339 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6343 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6344 desc = "Invalid Function";
6347 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6351 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6352 desc = "Invalid SGL";
6355 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6356 desc = "Internal Error";
6359 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6363 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6364 desc = "Insufficient Resources";
6367 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6368 desc = "Invalid Field";
6371 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6372 desc = "Invalid State";
6375 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6376 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6377 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6378 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6379 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6380 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6381 /* No message for Config IOCStatus values */
6384 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6385 /* No message for recovered error
6386 desc = "SCSI Recovered Error";
6390 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6391 desc = "SCSI Invalid Bus";
6394 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6395 desc = "SCSI Invalid TargetID";
6398 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6400 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6401 U8 cdb = pScsiReq->CDB[0];
6402 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6403 desc = "SCSI Device Not There";
6408 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6409 desc = "SCSI Data Overrun";
6412 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6413 /* This error is checked in scsi_io_done(). Skip.
6414 desc = "SCSI Data Underrun";
6418 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6419 desc = "SCSI I/O Data Error";
6422 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6423 desc = "SCSI Protocol Error";
6426 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6427 desc = "SCSI Task Terminated";
6430 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6431 desc = "SCSI Residual Mismatch";
6434 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6435 desc = "SCSI Task Management Failed";
6438 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6439 desc = "SCSI IOC Terminated";
6442 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6443 desc = "SCSI Ext Terminated";
6451 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6455 EXPORT_SYMBOL(mpt_attach);
6456 EXPORT_SYMBOL(mpt_detach);
6458 EXPORT_SYMBOL(mpt_resume);
6459 EXPORT_SYMBOL(mpt_suspend);
6461 EXPORT_SYMBOL(ioc_list);
6462 EXPORT_SYMBOL(mpt_proc_root_dir);
6463 EXPORT_SYMBOL(mpt_register);
6464 EXPORT_SYMBOL(mpt_deregister);
6465 EXPORT_SYMBOL(mpt_event_register);
6466 EXPORT_SYMBOL(mpt_event_deregister);
6467 EXPORT_SYMBOL(mpt_reset_register);
6468 EXPORT_SYMBOL(mpt_reset_deregister);
6469 EXPORT_SYMBOL(mpt_device_driver_register);
6470 EXPORT_SYMBOL(mpt_device_driver_deregister);
6471 EXPORT_SYMBOL(mpt_get_msg_frame);
6472 EXPORT_SYMBOL(mpt_put_msg_frame);
6473 EXPORT_SYMBOL(mpt_free_msg_frame);
6474 EXPORT_SYMBOL(mpt_add_sge);
6475 EXPORT_SYMBOL(mpt_send_handshake_request);
6476 EXPORT_SYMBOL(mpt_verify_adapter);
6477 EXPORT_SYMBOL(mpt_GetIocState);
6478 EXPORT_SYMBOL(mpt_print_ioc_summary);
6479 EXPORT_SYMBOL(mpt_lan_index);
6480 EXPORT_SYMBOL(mpt_stm_index);
6481 EXPORT_SYMBOL(mpt_HardResetHandler);
6482 EXPORT_SYMBOL(mpt_config);
6483 EXPORT_SYMBOL(mpt_findImVolumes);
6484 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6485 EXPORT_SYMBOL(mpt_free_fw_memory);
6486 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6487 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6490 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6492 * fusion_init - Fusion MPT base driver initialization routine.
6494 * Returns 0 for success, non-zero for failure.
6501 show_mptmod_ver(my_NAME, my_VERSION);
6502 printk(KERN_INFO COPYRIGHT "\n");
6504 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6505 MptCallbacks[i] = NULL;
6506 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6507 MptEvHandlers[i] = NULL;
6508 MptResetHandlers[i] = NULL;
6511 /* Register ourselves (mptbase) in order to facilitate
6512 * EventNotification handling.
6514 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6516 /* Register for hard reset handling callbacks.
6518 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6519 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6524 #ifdef CONFIG_PROC_FS
6525 (void) procmpt_create();
6530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6532 * fusion_exit - Perform driver unload cleanup.
6534 * This routine frees all resources associated with each MPT adapter
6535 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6541 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6543 mpt_reset_deregister(mpt_base_index);
6545 #ifdef CONFIG_PROC_FS
6550 module_init(fusion_init);
6551 module_exit(fusion_exit);