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");
84 static int mpt_msi_enable;
85 module_param(mpt_msi_enable, int, 0);
86 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
89 static int mfcounter = 0;
90 #define PRINT_MF_COUNT 20000
93 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
97 int mpt_lan_index = -1;
98 int mpt_stm_index = -1;
100 struct proc_dir_entry *mpt_proc_root_dir;
102 #define WHOINIT_UNKNOWN 0xAA
104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
108 /* Adapter link list */
110 /* Callback lookup table */
111 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Protocol driver class lookup table */
113 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
114 /* Event handler lookup table */
115 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
116 /* Reset handler lookup table */
117 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
118 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
120 static int mpt_base_index = -1;
121 static int last_drv_idx = -1;
123 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
125 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
129 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
130 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
131 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
132 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
134 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
135 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
136 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
137 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
139 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
140 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
141 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
142 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
143 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
144 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
145 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
146 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
147 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
148 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
149 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
150 static int PrimeIocFifos(MPT_ADAPTER *ioc);
151 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
152 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
153 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
154 static int GetLanConfigPages(MPT_ADAPTER *ioc);
155 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
156 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
157 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
158 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
159 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
160 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
161 static void mpt_timer_expired(unsigned long data);
162 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
163 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
164 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
165 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
167 #ifdef CONFIG_PROC_FS
168 static int procmpt_summary_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
170 static int procmpt_version_read(char *buf, char **start, off_t offset,
171 int request, int *eof, void *data);
172 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
173 int request, int *eof, void *data);
175 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
177 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
178 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
179 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
180 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
181 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
182 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
183 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
185 /* module entry point */
186 static int __init fusion_init (void);
187 static void __exit fusion_exit (void);
189 #define CHIPREG_READ32(addr) readl_relaxed(addr)
190 #define CHIPREG_READ32_dmasync(addr) readl(addr)
191 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
192 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
193 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
196 pci_disable_io_access(struct pci_dev *pdev)
200 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
202 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
206 pci_enable_io_access(struct pci_dev *pdev)
210 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
212 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
216 * Process turbo (context) reply...
219 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
221 MPT_FRAME_HDR *mf = NULL;
222 MPT_FRAME_HDR *mr = NULL;
226 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
229 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
230 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
231 req_idx = pa & 0x0000FFFF;
232 cb_idx = (pa & 0x00FF0000) >> 16;
233 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
235 case MPI_CONTEXT_REPLY_TYPE_LAN:
236 cb_idx = mpt_lan_index;
238 * Blind set of mf to NULL here was fatal
239 * after lan_reply says "freeme"
240 * Fix sort of combined with an optimization here;
241 * added explicit check for case where lan_reply
242 * was just returning 1 and doing nothing else.
243 * For this case skip the callback, but set up
244 * proper mf value first here:-)
246 if ((pa & 0x58000000) == 0x58000000) {
247 req_idx = pa & 0x0000FFFF;
248 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
249 mpt_free_msg_frame(ioc, mf);
254 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
256 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
257 cb_idx = mpt_stm_index;
258 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
265 /* Check for (valid) IO callback! */
266 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
267 MptCallbacks[cb_idx] == NULL) {
268 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
269 __FUNCTION__, ioc->name, cb_idx);
273 if (MptCallbacks[cb_idx](ioc, mf, mr))
274 mpt_free_msg_frame(ioc, mf);
280 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
291 /* non-TURBO reply! Hmmm, something may be up...
292 * Newest turbo reply mechanism; get address
293 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
296 /* Map DMA address of reply header to cpu address.
297 * pa is 32 bits - but the dma address may be 32 or 64 bits
298 * get offset based only only the low addresses
301 reply_dma_low = (pa <<= 1);
302 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
303 (reply_dma_low - ioc->reply_frames_low_dma));
305 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
306 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
307 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
309 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
310 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
311 DBG_DUMP_REPLY_FRAME(mr)
313 /* Check/log IOC log info
315 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
316 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
317 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
318 if (ioc->bus_type == FC)
319 mpt_fc_log_info(ioc, log_info);
320 else if (ioc->bus_type == SPI)
321 mpt_spi_log_info(ioc, log_info);
322 else if (ioc->bus_type == SAS)
323 mpt_sas_log_info(ioc, log_info);
325 if (ioc_stat & MPI_IOCSTATUS_MASK) {
326 if (ioc->bus_type == SPI &&
327 cb_idx != mpt_stm_index &&
328 cb_idx != mpt_lan_index)
329 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
333 /* Check for (valid) IO callback! */
334 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
335 MptCallbacks[cb_idx] == NULL) {
336 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
337 __FUNCTION__, ioc->name, cb_idx);
342 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
345 /* Flush (non-TURBO) reply with a WRITE! */
346 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
349 mpt_free_msg_frame(ioc, mf);
353 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
355 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
356 * @irq: irq number (not used)
357 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
358 * @r: pt_regs pointer (not used)
360 * This routine is registered via the request_irq() kernel API call,
361 * and handles all interrupts generated from a specific MPT adapter
362 * (also referred to as a IO Controller or IOC).
363 * This routine must clear the interrupt from the adapter and does
364 * so by reading the reply FIFO. Multiple replies may be processed
365 * per single call to this routine.
367 * This routine handles register-level access of the adapter but
368 * dispatches (calls) a protocol-specific callback routine to handle
369 * the protocol-specific details of the MPT request completion.
372 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
374 MPT_ADAPTER *ioc = bus_id;
378 * Drain the reply FIFO!
381 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
382 if (pa == 0xFFFFFFFF)
384 else if (pa & MPI_ADDRESS_REPLY_A_BIT)
387 mpt_turbo_reply(ioc, pa);
393 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
395 * mpt_base_reply - MPT base driver's callback routine; all base driver
396 * "internal" request/reply processing is routed here.
397 * Currently used for EventNotification and EventAck handling.
398 * @ioc: Pointer to MPT_ADAPTER structure
399 * @mf: Pointer to original MPT request frame
400 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
402 * Returns 1 indicating original alloc'd request frame ptr
403 * should be freed, or 0 if it shouldn't.
406 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
411 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
413 #if defined(MPT_DEBUG_MSG_FRAME)
414 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
415 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
416 DBG_DUMP_REQUEST_FRAME_HDR(mf)
420 func = reply->u.hdr.Function;
421 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
424 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
425 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
429 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
430 if (results != evHandlers) {
431 /* CHECKME! Any special handling needed here? */
432 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
433 ioc->name, evHandlers, results));
437 * Hmmm... It seems that EventNotificationReply is an exception
438 * to the rule of one reply per request.
440 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
442 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
443 ioc->name, pEvReply));
445 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
446 ioc->name, pEvReply));
449 #ifdef CONFIG_PROC_FS
450 // LogEvent(ioc, pEvReply);
453 } else if (func == MPI_FUNCTION_EVENT_ACK) {
454 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
456 } else if (func == MPI_FUNCTION_CONFIG) {
460 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
461 ioc->name, mf, reply));
463 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
466 /* disable timer and remove from linked list */
467 del_timer(&pCfg->timer);
469 spin_lock_irqsave(&ioc->FreeQlock, flags);
470 list_del(&pCfg->linkage);
471 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
474 * If IOC Status is SUCCESS, save the header
475 * and set the status code to GOOD.
477 pCfg->status = MPT_CONFIG_ERROR;
479 ConfigReply_t *pReply = (ConfigReply_t *)reply;
482 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
483 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
484 status, le32_to_cpu(pReply->IOCLogInfo)));
486 pCfg->status = status;
487 if (status == MPI_IOCSTATUS_SUCCESS) {
488 if ((pReply->Header.PageType &
489 MPI_CONFIG_PAGETYPE_MASK) ==
490 MPI_CONFIG_PAGETYPE_EXTENDED) {
491 pCfg->cfghdr.ehdr->ExtPageLength =
492 le16_to_cpu(pReply->ExtPageLength);
493 pCfg->cfghdr.ehdr->ExtPageType =
496 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
498 /* If this is a regular header, save PageLength. */
499 /* LMP Do this better so not using a reserved field! */
500 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
501 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
502 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
507 * Wake up the original calling thread
512 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
513 /* we should be always getting a reply frame */
514 memcpy(ioc->persist_reply_frame, reply,
515 min(MPT_DEFAULT_FRAME_SIZE,
516 4*reply->u.reply.MsgLength));
517 del_timer(&ioc->persist_timer);
518 ioc->persist_wait_done = 1;
521 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
526 * Conditionally tell caller to free the original
527 * EventNotification/EventAck/unexpected request frame!
532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
534 * mpt_register - Register protocol-specific main callback handler.
535 * @cbfunc: callback function pointer
536 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
538 * This routine is called by a protocol-specific driver (SCSI host,
539 * LAN, SCSI target) to register it's reply callback routine. Each
540 * protocol-specific driver must do this before it will be able to
541 * use any IOC resources, such as obtaining request frames.
543 * NOTES: The SCSI protocol driver currently calls this routine thrice
544 * in order to register separate callbacks; one for "normal" SCSI IO;
545 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
547 * Returns a positive integer valued "handle" in the
548 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
549 * Any non-positive return value (including zero!) should be considered
550 * an error by the caller.
553 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
560 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
561 * (slot/handle 0 is reserved!)
563 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
564 if (MptCallbacks[i] == NULL) {
565 MptCallbacks[i] = cbfunc;
566 MptDriverClass[i] = dclass;
567 MptEvHandlers[i] = NULL;
576 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
578 * mpt_deregister - Deregister a protocol drivers resources.
579 * @cb_idx: previously registered callback handle
581 * Each protocol-specific driver should call this routine when it's
582 * module is unloaded.
585 mpt_deregister(int cb_idx)
587 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
588 MptCallbacks[cb_idx] = NULL;
589 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
590 MptEvHandlers[cb_idx] = NULL;
596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
598 * mpt_event_register - Register protocol-specific event callback
600 * @cb_idx: previously registered (via mpt_register) callback handle
601 * @ev_cbfunc: callback function
603 * This routine can be called by one or more protocol-specific drivers
604 * if/when they choose to be notified of MPT events.
606 * Returns 0 for success.
609 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
611 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
614 MptEvHandlers[cb_idx] = ev_cbfunc;
618 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
620 * mpt_event_deregister - Deregister protocol-specific event callback
622 * @cb_idx: previously registered callback handle
624 * Each protocol-specific driver should call this routine
625 * when it does not (or can no longer) handle events,
626 * or when it's module is unloaded.
629 mpt_event_deregister(int cb_idx)
631 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
634 MptEvHandlers[cb_idx] = NULL;
637 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
639 * mpt_reset_register - Register protocol-specific IOC reset handler.
640 * @cb_idx: previously registered (via mpt_register) callback handle
641 * @reset_func: reset function
643 * This routine can be called by one or more protocol-specific drivers
644 * if/when they choose to be notified of IOC resets.
646 * Returns 0 for success.
649 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
651 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
654 MptResetHandlers[cb_idx] = reset_func;
658 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
660 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
661 * @cb_idx: previously registered callback handle
663 * Each protocol-specific driver should call this routine
664 * when it does not (or can no longer) handle IOC reset handling,
665 * or when it's module is unloaded.
668 mpt_reset_deregister(int cb_idx)
670 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
673 MptResetHandlers[cb_idx] = NULL;
676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
678 * mpt_device_driver_register - Register device driver hooks
681 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
685 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
689 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
691 /* call per pci device probe entry point */
692 list_for_each_entry(ioc, &ioc_list, list) {
693 if(dd_cbfunc->probe) {
694 dd_cbfunc->probe(ioc->pcidev,
695 ioc->pcidev->driver->id_table);
702 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
704 * mpt_device_driver_deregister - DeRegister device driver hooks
707 mpt_device_driver_deregister(int cb_idx)
709 struct mpt_pci_driver *dd_cbfunc;
712 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
715 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
717 list_for_each_entry(ioc, &ioc_list, list) {
718 if (dd_cbfunc->remove)
719 dd_cbfunc->remove(ioc->pcidev);
722 MptDeviceDriverHandlers[cb_idx] = NULL;
726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
728 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
729 * allocated per MPT adapter.
730 * @handle: Handle of registered MPT protocol driver
731 * @ioc: Pointer to MPT adapter structure
733 * Returns pointer to a MPT request frame or %NULL if none are available
734 * or IOC is not active.
737 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
741 u16 req_idx; /* Request index */
743 /* validate handle and ioc identifier */
747 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
750 /* If interrupts are not attached, do not return a request frame */
754 spin_lock_irqsave(&ioc->FreeQlock, flags);
755 if (!list_empty(&ioc->FreeQ)) {
758 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
759 u.frame.linkage.list);
760 list_del(&mf->u.frame.linkage.list);
761 mf->u.frame.linkage.arg1 = 0;
762 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
763 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
765 req_idx = req_offset / ioc->req_sz;
766 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
767 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
768 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
775 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
779 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
781 if (mfcounter == PRINT_MF_COUNT)
782 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
785 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
786 ioc->name, handle, ioc->id, mf));
790 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
792 * mpt_put_msg_frame - Send a protocol specific MPT request frame
794 * @handle: Handle of registered MPT protocol driver
795 * @ioc: Pointer to MPT adapter structure
796 * @mf: Pointer to MPT request frame
798 * This routine posts a MPT request frame to the request post FIFO of a
799 * specific MPT adapter.
802 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
806 u16 req_idx; /* Request index */
808 /* ensure values are reset properly! */
809 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
810 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
812 req_idx = req_offset / ioc->req_sz;
813 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
814 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
816 #ifdef MPT_DEBUG_MSG_FRAME
818 u32 *m = mf->u.frame.hwhdr.__hdr;
821 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
823 n = ioc->req_sz/4 - 1;
826 for (ii=0; ii<=n; ii++) {
827 if (ii && ((ii%8)==0))
828 printk("\n" KERN_INFO " ");
829 printk(" %08x", le32_to_cpu(m[ii]));
835 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
836 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]));
837 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
840 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
842 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
843 * @handle: Handle of registered MPT protocol driver
844 * @ioc: Pointer to MPT adapter structure
845 * @mf: Pointer to MPT request frame
847 * This routine places a MPT request frame back on the MPT adapter's
851 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
855 /* Put Request back on FreeQ! */
856 spin_lock_irqsave(&ioc->FreeQlock, flags);
857 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
858 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
862 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
865 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
867 * mpt_add_sge - Place a simple SGE at address pAddr.
868 * @pAddr: virtual address for SGE
869 * @flagslength: SGE flags and data transfer length
870 * @dma_addr: Physical address
872 * This routine places a MPT request frame back on the MPT adapter's
876 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
878 if (sizeof(dma_addr_t) == sizeof(u64)) {
879 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
880 u32 tmp = dma_addr & 0xFFFFFFFF;
882 pSge->FlagsLength = cpu_to_le32(flagslength);
883 pSge->Address.Low = cpu_to_le32(tmp);
884 tmp = (u32) ((u64)dma_addr >> 32);
885 pSge->Address.High = cpu_to_le32(tmp);
888 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
889 pSge->FlagsLength = cpu_to_le32(flagslength);
890 pSge->Address = cpu_to_le32(dma_addr);
894 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
896 * mpt_send_handshake_request - Send MPT request via doorbell
898 * @handle: Handle of registered MPT protocol driver
899 * @ioc: Pointer to MPT adapter structure
900 * @reqBytes: Size of the request in bytes
901 * @req: Pointer to MPT request frame
902 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
904 * This routine is used exclusively to send MptScsiTaskMgmt
905 * requests since they are required to be sent via doorbell handshake.
907 * NOTE: It is the callers responsibility to byte-swap fields in the
908 * request which are greater than 1 byte in size.
910 * Returns 0 for success, non-zero for failure.
913 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
919 /* State is known to be good upon entering
920 * this function so issue the bus reset
925 * Emulate what mpt_put_msg_frame() does /wrt to sanity
926 * setting cb_idx/req_idx. But ONLY if this request
927 * is in proper (pre-alloc'd) request buffer range...
929 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
930 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
931 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
932 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
933 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
936 /* Make sure there are no doorbells */
937 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
939 CHIPREG_WRITE32(&ioc->chip->Doorbell,
940 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
941 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
943 /* Wait for IOC doorbell int */
944 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
948 /* Read doorbell and check for active bit */
949 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
952 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
955 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
957 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
961 /* Send request via doorbell handshake */
962 req_as_bytes = (u8 *) req;
963 for (ii = 0; ii < reqBytes/4; ii++) {
966 word = ((req_as_bytes[(ii*4) + 0] << 0) |
967 (req_as_bytes[(ii*4) + 1] << 8) |
968 (req_as_bytes[(ii*4) + 2] << 16) |
969 (req_as_bytes[(ii*4) + 3] << 24));
970 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
971 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
977 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
982 /* Make sure there are no doorbells */
983 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
988 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
990 * mpt_host_page_access_control - provides mechanism for the host
991 * driver to control the IOC's Host Page Buffer access.
992 * @ioc: Pointer to MPT adapter structure
993 * @access_control_value: define bits below
995 * Access Control Value - bits[15:12]
997 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
998 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
999 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1001 * Returns 0 for success, non-zero for failure.
1005 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1009 /* return if in use */
1010 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1011 & MPI_DOORBELL_ACTIVE)
1014 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1016 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1017 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1018 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1019 (access_control_value<<12)));
1021 /* Wait for IOC to clear Doorbell Status bit */
1022 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1030 * mpt_host_page_alloc - allocate system memory for the fw
1031 * If we already allocated memory in past, then resend the same pointer.
1032 * ioc@: Pointer to pointer to IOC adapter
1033 * ioc_init@: Pointer to ioc init config page
1035 * Returns 0 for success, non-zero for failure.
1038 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1042 u32 host_page_buffer_sz=0;
1044 if(!ioc->HostPageBuffer) {
1046 host_page_buffer_sz =
1047 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1049 if(!host_page_buffer_sz)
1050 return 0; /* fw doesn't need any host buffers */
1052 /* spin till we get enough memory */
1053 while(host_page_buffer_sz > 0) {
1055 if((ioc->HostPageBuffer = pci_alloc_consistent(
1057 host_page_buffer_sz,
1058 &ioc->HostPageBuffer_dma)) != NULL) {
1060 dinitprintk((MYIOC_s_INFO_FMT
1061 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1063 ioc->HostPageBuffer,
1064 ioc->HostPageBuffer_dma,
1065 host_page_buffer_sz));
1066 ioc->alloc_total += host_page_buffer_sz;
1067 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1071 host_page_buffer_sz -= (4*1024);
1075 if(!ioc->HostPageBuffer) {
1076 printk(MYIOC_s_ERR_FMT
1077 "Failed to alloc memory for host_page_buffer!\n",
1082 psge = (char *)&ioc_init->HostPageBufferSGE;
1083 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1084 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1085 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1086 MPI_SGE_FLAGS_HOST_TO_IOC |
1087 MPI_SGE_FLAGS_END_OF_BUFFER;
1088 if (sizeof(dma_addr_t) == sizeof(u64)) {
1089 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1091 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1092 flags_length |= ioc->HostPageBuffer_sz;
1093 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1094 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1101 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1102 * the associated MPT adapter structure.
1103 * @iocid: IOC unique identifier (integer)
1104 * @iocpp: Pointer to pointer to IOC adapter
1106 * Returns iocid and sets iocpp.
1109 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1113 list_for_each_entry(ioc,&ioc_list,list) {
1114 if (ioc->id == iocid) {
1124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1126 * mpt_attach - Install a PCI intelligent MPT adapter.
1127 * @pdev: Pointer to pci_dev structure
1129 * This routine performs all the steps necessary to bring the IOC of
1130 * a MPT adapter to a OPERATIONAL state. This includes registering
1131 * memory regions, registering the interrupt, and allocating request
1132 * and reply memory pools.
1134 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1137 * Returns 0 for success, non-zero for failure.
1139 * TODO: Add support for polled controllers
1142 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1146 unsigned long mem_phys;
1154 static int mpt_ids = 0;
1155 #ifdef CONFIG_PROC_FS
1156 struct proc_dir_entry *dent, *ent;
1159 if (pci_enable_device(pdev))
1162 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1164 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1165 dprintk((KERN_INFO MYNAM
1166 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1167 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1168 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1172 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1173 dprintk((KERN_INFO MYNAM
1174 ": Using 64 bit consistent mask\n"));
1176 dprintk((KERN_INFO MYNAM
1177 ": Not using 64 bit consistent mask\n"));
1179 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1181 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1184 ioc->alloc_total = sizeof(MPT_ADAPTER);
1185 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1186 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1189 ioc->diagPending = 0;
1190 spin_lock_init(&ioc->diagLock);
1191 spin_lock_init(&ioc->fc_rescan_work_lock);
1192 spin_lock_init(&ioc->initializing_hba_lock);
1194 /* Initialize the event logging.
1196 ioc->eventTypes = 0; /* None */
1197 ioc->eventContext = 0;
1198 ioc->eventLogSize = 0;
1205 ioc->cached_fw = NULL;
1207 /* Initilize SCSI Config Data structure
1209 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1211 /* Initialize the running configQ head.
1213 INIT_LIST_HEAD(&ioc->configQ);
1215 /* Initialize the fc rport list head.
1217 INIT_LIST_HEAD(&ioc->fc_rports);
1219 /* Find lookup slot. */
1220 INIT_LIST_HEAD(&ioc->list);
1221 ioc->id = mpt_ids++;
1223 mem_phys = msize = 0;
1225 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1226 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1227 /* Get I/O space! */
1228 port = pci_resource_start(pdev, ii);
1229 psize = pci_resource_len(pdev,ii);
1232 mem_phys = pci_resource_start(pdev, ii);
1233 msize = pci_resource_len(pdev,ii);
1237 ioc->mem_size = msize;
1239 if (ii == DEVICE_COUNT_RESOURCE) {
1240 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1245 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1246 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1249 /* Get logical ptr for PciMem0 space */
1250 /*mem = ioremap(mem_phys, msize);*/
1251 mem = ioremap(mem_phys, 0x100);
1253 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1258 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1260 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1261 &ioc->facts, &ioc->pfacts[0]));
1263 ioc->mem_phys = mem_phys;
1264 ioc->chip = (SYSIF_REGS __iomem *)mem;
1266 /* Save Port IO values in case we need to do downloadboot */
1268 u8 *pmem = (u8*)port;
1269 ioc->pio_mem_phys = port;
1270 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1273 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1274 ioc->prod_name = "LSIFC909";
1277 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1278 ioc->prod_name = "LSIFC929";
1281 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1282 ioc->prod_name = "LSIFC919";
1285 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1286 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1288 if (revision < XL_929) {
1289 ioc->prod_name = "LSIFC929X";
1290 /* 929X Chip Fix. Set Split transactions level
1291 * for PCIX. Set MOST bits to zero.
1293 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1295 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1297 ioc->prod_name = "LSIFC929XL";
1298 /* 929XL Chip Fix. Set MMRBC to 0x08.
1300 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1302 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1305 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1306 ioc->prod_name = "LSIFC919X";
1308 /* 919X Chip Fix. Set Split transactions level
1309 * for PCIX. Set MOST bits to zero.
1311 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1313 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1315 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1316 ioc->prod_name = "LSIFC939X";
1318 ioc->errata_flag_1064 = 1;
1320 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1321 ioc->prod_name = "LSIFC949X";
1323 ioc->errata_flag_1064 = 1;
1325 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1326 ioc->prod_name = "LSIFC949E";
1329 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1330 ioc->prod_name = "LSI53C1030";
1331 ioc->bus_type = SPI;
1332 /* 1030 Chip Fix. Disable Split transactions
1333 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1335 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1336 if (revision < C0_1030) {
1337 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1339 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1342 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1343 ioc->prod_name = "LSI53C1035";
1344 ioc->bus_type = SPI;
1346 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1347 ioc->prod_name = "LSISAS1064";
1348 ioc->bus_type = SAS;
1349 ioc->errata_flag_1064 = 1;
1351 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1352 ioc->prod_name = "LSISAS1066";
1353 ioc->bus_type = SAS;
1354 ioc->errata_flag_1064 = 1;
1356 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1357 ioc->prod_name = "LSISAS1068";
1358 ioc->bus_type = SAS;
1359 ioc->errata_flag_1064 = 1;
1361 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1362 ioc->prod_name = "LSISAS1064E";
1363 ioc->bus_type = SAS;
1365 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1366 ioc->prod_name = "LSISAS1066E";
1367 ioc->bus_type = SAS;
1369 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1370 ioc->prod_name = "LSISAS1068E";
1371 ioc->bus_type = SAS;
1374 if (ioc->errata_flag_1064)
1375 pci_disable_io_access(pdev);
1377 sprintf(ioc->name, "ioc%d", ioc->id);
1379 spin_lock_init(&ioc->FreeQlock);
1382 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1384 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1386 /* Set lookup ptr. */
1387 list_add_tail(&ioc->list, &ioc_list);
1389 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1391 mpt_detect_bound_ports(ioc, pdev);
1393 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1395 printk(KERN_WARNING MYNAM
1396 ": WARNING - %s did not initialize properly! (%d)\n",
1398 list_del(&ioc->list);
1400 ioc->alt_ioc->alt_ioc = NULL;
1403 pci_set_drvdata(pdev, NULL);
1407 /* call per device driver probe entry point */
1408 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1409 if(MptDeviceDriverHandlers[ii] &&
1410 MptDeviceDriverHandlers[ii]->probe) {
1411 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1415 #ifdef CONFIG_PROC_FS
1417 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1419 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1421 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1423 ent->read_proc = procmpt_iocinfo_read;
1426 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1428 ent->read_proc = procmpt_summary_read;
1437 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1439 * mpt_detach - Remove a PCI intelligent MPT adapter.
1440 * @pdev: Pointer to pci_dev structure
1445 mpt_detach(struct pci_dev *pdev)
1447 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1451 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1452 remove_proc_entry(pname, NULL);
1453 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1454 remove_proc_entry(pname, NULL);
1455 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1456 remove_proc_entry(pname, NULL);
1458 /* call per device driver remove entry point */
1459 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1460 if(MptDeviceDriverHandlers[ii] &&
1461 MptDeviceDriverHandlers[ii]->remove) {
1462 MptDeviceDriverHandlers[ii]->remove(pdev);
1466 /* Disable interrupts! */
1467 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1470 synchronize_irq(pdev->irq);
1472 /* Clear any lingering interrupt */
1473 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1475 CHIPREG_READ32(&ioc->chip->IntStatus);
1477 mpt_adapter_dispose(ioc);
1479 pci_set_drvdata(pdev, NULL);
1482 /**************************************************************************
1486 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1488 * mpt_suspend - Fusion MPT base driver suspend routine.
1493 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1496 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1498 device_state=pci_choose_state(pdev, state);
1500 printk(MYIOC_s_INFO_FMT
1501 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1502 ioc->name, pdev, pci_name(pdev), device_state);
1504 pci_save_state(pdev);
1506 /* put ioc into READY_STATE */
1507 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1508 printk(MYIOC_s_ERR_FMT
1509 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1512 /* disable interrupts */
1513 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1516 /* Clear any lingering interrupt */
1517 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1519 pci_disable_device(pdev);
1520 pci_set_power_state(pdev, device_state);
1525 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1527 * mpt_resume - Fusion MPT base driver resume routine.
1532 mpt_resume(struct pci_dev *pdev)
1534 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1535 u32 device_state = pdev->current_state;
1538 printk(MYIOC_s_INFO_FMT
1539 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1540 ioc->name, pdev, pci_name(pdev), device_state);
1542 pci_set_power_state(pdev, 0);
1543 pci_restore_state(pdev);
1544 pci_enable_device(pdev);
1546 /* enable interrupts */
1547 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1550 printk(MYIOC_s_INFO_FMT
1551 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1553 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1554 CHIPREG_READ32(&ioc->chip->Doorbell));
1556 /* bring ioc to operational state */
1557 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1558 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1559 printk(MYIOC_s_INFO_FMT
1560 "pci-resume: Cannot recover, error:[%x]\n",
1561 ioc->name, recovery_state);
1563 printk(MYIOC_s_INFO_FMT
1564 "pci-resume: success\n", ioc->name);
1572 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1574 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1575 ioc->bus_type != SPI) ||
1576 (MptDriverClass[index] == MPTFC_DRIVER &&
1577 ioc->bus_type != FC) ||
1578 (MptDriverClass[index] == MPTSAS_DRIVER &&
1579 ioc->bus_type != SAS))
1580 /* make sure we only call the relevant reset handler
1583 return (MptResetHandlers[index])(ioc, reset_phase);
1586 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1588 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1589 * @ioc: Pointer to MPT adapter structure
1590 * @reason: Event word / reason
1591 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1593 * This routine performs all the steps necessary to bring the IOC
1594 * to a OPERATIONAL state.
1596 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1601 * -1 if failed to get board READY
1602 * -2 if READY but IOCFacts Failed
1603 * -3 if READY but PrimeIOCFifos Failed
1604 * -4 if READY but IOCInit Failed
1607 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1609 int hard_reset_done = 0;
1610 int alt_ioc_ready = 0;
1616 int reset_alt_ioc_active = 0;
1617 int irq_allocated = 0;
1619 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1620 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1622 /* Disable reply interrupts (also blocks FreeQ) */
1623 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1627 if (ioc->alt_ioc->active)
1628 reset_alt_ioc_active = 1;
1630 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1631 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1632 ioc->alt_ioc->active = 0;
1636 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1639 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1640 if (hard_reset_done == -4) {
1641 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1644 if (reset_alt_ioc_active && ioc->alt_ioc) {
1645 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1646 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1647 ioc->alt_ioc->name));
1648 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1649 ioc->alt_ioc->active = 1;
1653 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1659 /* hard_reset_done = 0 if a soft reset was performed
1660 * and 1 if a hard reset was performed.
1662 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1663 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1666 printk(KERN_WARNING MYNAM
1667 ": alt-%s: Not ready WARNING!\n",
1668 ioc->alt_ioc->name);
1671 for (ii=0; ii<5; ii++) {
1672 /* Get IOC facts! Allow 5 retries */
1673 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1679 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1681 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1682 MptDisplayIocCapabilities(ioc);
1685 if (alt_ioc_ready) {
1686 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1687 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1688 /* Retry - alt IOC was initialized once
1690 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1693 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1695 reset_alt_ioc_active = 0;
1696 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1697 MptDisplayIocCapabilities(ioc->alt_ioc);
1702 * Device is reset now. It must have de-asserted the interrupt line
1703 * (if it was asserted) and it should be safe to register for the
1706 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1708 if (ioc->pcidev->irq) {
1709 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1710 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1712 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1713 SA_SHIRQ, ioc->name, ioc);
1716 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1717 "interrupt %d!\n", ioc->name,
1720 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1721 "interrupt %s!\n", ioc->name,
1722 __irq_itoa(ioc->pcidev->irq));
1725 pci_disable_msi(ioc->pcidev);
1729 ioc->pci_irq = ioc->pcidev->irq;
1730 pci_set_master(ioc->pcidev); /* ?? */
1731 pci_set_drvdata(ioc->pcidev, ioc);
1733 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1734 "%d\n", ioc->name, ioc->pcidev->irq));
1736 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1738 __irq_itoa(ioc->pcidev->irq)));
1743 /* Prime reply & request queues!
1744 * (mucho alloc's) Must be done prior to
1745 * init as upper addresses are needed for init.
1746 * If fails, continue with alt-ioc processing
1748 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1751 /* May need to check/upload firmware & data here!
1752 * If fails, continue with alt-ioc processing
1754 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1757 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1758 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1759 ioc->alt_ioc->name, rc);
1761 reset_alt_ioc_active = 0;
1764 if (alt_ioc_ready) {
1765 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1767 reset_alt_ioc_active = 0;
1768 printk(KERN_WARNING MYNAM
1769 ": alt-%s: (%d) init failure WARNING!\n",
1770 ioc->alt_ioc->name, rc);
1774 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1775 if (ioc->upload_fw) {
1776 ddlprintk((MYIOC_s_INFO_FMT
1777 "firmware upload required!\n", ioc->name));
1779 /* Controller is not operational, cannot do upload
1782 rc = mpt_do_upload(ioc, sleepFlag);
1784 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1786 * Maintain only one pointer to FW memory
1787 * so there will not be two attempt to
1788 * downloadboot onboard dual function
1789 * chips (mpt_adapter_disable,
1792 ioc->cached_fw = NULL;
1793 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1794 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1797 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1805 /* Enable! (reply interrupt) */
1806 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1810 if (reset_alt_ioc_active && ioc->alt_ioc) {
1811 /* (re)Enable alt-IOC! (reply interrupt) */
1812 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1813 ioc->alt_ioc->name));
1814 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1815 ioc->alt_ioc->active = 1;
1818 /* Enable MPT base driver management of EventNotification
1819 * and EventAck handling.
1821 if ((ret == 0) && (!ioc->facts.EventState))
1822 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1824 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1825 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1827 /* Add additional "reason" check before call to GetLanConfigPages
1828 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1829 * recursive scenario; GetLanConfigPages times out, timer expired
1830 * routine calls HardResetHandler, which calls into here again,
1831 * and we try GetLanConfigPages again...
1833 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1834 if (ioc->bus_type == SAS) {
1836 /* clear persistency table */
1837 if(ioc->facts.IOCExceptions &
1838 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1839 ret = mptbase_sas_persist_operation(ioc,
1840 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1847 mpt_findImVolumes(ioc);
1849 } else if (ioc->bus_type == FC) {
1851 * Pre-fetch FC port WWN and stuff...
1852 * (FCPortPage0_t stuff)
1854 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1855 (void) mptbase_GetFcPortPage0(ioc, ii);
1858 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1859 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1861 * Pre-fetch the ports LAN MAC address!
1862 * (LANPage1_t stuff)
1864 (void) GetLanConfigPages(ioc);
1867 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1868 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1869 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1874 /* Get NVRAM and adapter maximums from SPP 0 and 2
1876 mpt_GetScsiPortSettings(ioc, 0);
1878 /* Get version and length of SDP 1
1880 mpt_readScsiDevicePageHeaders(ioc, 0);
1884 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1885 mpt_findImVolumes(ioc);
1887 /* Check, and possibly reset, the coalescing value
1889 mpt_read_ioc_pg_1(ioc);
1891 mpt_read_ioc_pg_4(ioc);
1894 GetIoUnitPage2(ioc);
1898 * Call each currently registered protocol IOC reset handler
1899 * with post-reset indication.
1900 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1901 * MptResetHandlers[] registered yet.
1903 if (hard_reset_done) {
1905 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1906 if ((ret == 0) && MptResetHandlers[ii]) {
1907 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1909 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1913 if (alt_ioc_ready && MptResetHandlers[ii]) {
1914 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1915 ioc->name, ioc->alt_ioc->name, ii));
1916 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1920 /* FIXME? Examine results here? */
1924 if ((ret != 0) && irq_allocated) {
1925 free_irq(ioc->pci_irq, ioc);
1927 pci_disable_msi(ioc->pcidev);
1932 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1934 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1935 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1936 * 929X, 1030 or 1035.
1937 * @ioc: Pointer to MPT adapter structure
1938 * @pdev: Pointer to (struct pci_dev) structure
1940 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1941 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1944 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1946 struct pci_dev *peer=NULL;
1947 unsigned int slot = PCI_SLOT(pdev->devfn);
1948 unsigned int func = PCI_FUNC(pdev->devfn);
1949 MPT_ADAPTER *ioc_srch;
1951 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1952 " searching for devfn match on %x or %x\n",
1953 ioc->name, pci_name(pdev), pdev->bus->number,
1954 pdev->devfn, func-1, func+1));
1956 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1958 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1963 list_for_each_entry(ioc_srch, &ioc_list, list) {
1964 struct pci_dev *_pcidev = ioc_srch->pcidev;
1965 if (_pcidev == peer) {
1966 /* Paranoia checks */
1967 if (ioc->alt_ioc != NULL) {
1968 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1969 ioc->name, ioc->alt_ioc->name);
1971 } else if (ioc_srch->alt_ioc != NULL) {
1972 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1973 ioc_srch->name, ioc_srch->alt_ioc->name);
1976 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1977 ioc->name, ioc_srch->name));
1978 ioc_srch->alt_ioc = ioc;
1979 ioc->alt_ioc = ioc_srch;
1985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1987 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1988 * @this: Pointer to MPT adapter structure
1991 mpt_adapter_disable(MPT_ADAPTER *ioc)
1996 if (ioc->cached_fw != NULL) {
1997 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1998 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1999 printk(KERN_WARNING MYNAM
2000 ": firmware downloadboot failure (%d)!\n", ret);
2004 /* Disable adapter interrupts! */
2005 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2007 /* Clear any lingering interrupt */
2008 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2010 if (ioc->alloc != NULL) {
2012 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2013 ioc->name, ioc->alloc, ioc->alloc_sz));
2014 pci_free_consistent(ioc->pcidev, sz,
2015 ioc->alloc, ioc->alloc_dma);
2016 ioc->reply_frames = NULL;
2017 ioc->req_frames = NULL;
2019 ioc->alloc_total -= sz;
2022 if (ioc->sense_buf_pool != NULL) {
2023 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2024 pci_free_consistent(ioc->pcidev, sz,
2025 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2026 ioc->sense_buf_pool = NULL;
2027 ioc->alloc_total -= sz;
2030 if (ioc->events != NULL){
2031 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2034 ioc->alloc_total -= sz;
2037 if (ioc->cached_fw != NULL) {
2038 sz = ioc->facts.FWImageSize;
2039 pci_free_consistent(ioc->pcidev, sz,
2040 ioc->cached_fw, ioc->cached_fw_dma);
2041 ioc->cached_fw = NULL;
2042 ioc->alloc_total -= sz;
2045 kfree(ioc->spi_data.nvram);
2046 kfree(ioc->raid_data.pIocPg3);
2047 ioc->spi_data.nvram = NULL;
2048 ioc->raid_data.pIocPg3 = NULL;
2050 if (ioc->spi_data.pIocPg4 != NULL) {
2051 sz = ioc->spi_data.IocPg4Sz;
2052 pci_free_consistent(ioc->pcidev, sz,
2053 ioc->spi_data.pIocPg4,
2054 ioc->spi_data.IocPg4_dma);
2055 ioc->spi_data.pIocPg4 = NULL;
2056 ioc->alloc_total -= sz;
2059 if (ioc->ReqToChain != NULL) {
2060 kfree(ioc->ReqToChain);
2061 kfree(ioc->RequestNB);
2062 ioc->ReqToChain = NULL;
2065 kfree(ioc->ChainToChain);
2066 ioc->ChainToChain = NULL;
2068 if (ioc->HostPageBuffer != NULL) {
2069 if((ret = mpt_host_page_access_control(ioc,
2070 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2071 printk(KERN_ERR MYNAM
2072 ": %s: host page buffers free failed (%d)!\n",
2075 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2076 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2077 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2078 ioc->HostPageBuffer,
2079 ioc->HostPageBuffer_dma);
2080 ioc->HostPageBuffer = NULL;
2081 ioc->HostPageBuffer_sz = 0;
2082 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2086 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2088 * mpt_adapter_dispose - Free all resources associated with a MPT
2090 * @ioc: Pointer to MPT adapter structure
2092 * This routine unregisters h/w resources and frees all alloc'd memory
2093 * associated with a MPT adapter structure.
2096 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2098 int sz_first, sz_last;
2103 sz_first = ioc->alloc_total;
2105 mpt_adapter_disable(ioc);
2107 if (ioc->pci_irq != -1) {
2108 free_irq(ioc->pci_irq, ioc);
2110 pci_disable_msi(ioc->pcidev);
2114 if (ioc->memmap != NULL) {
2115 iounmap(ioc->memmap);
2119 #if defined(CONFIG_MTRR) && 0
2120 if (ioc->mtrr_reg > 0) {
2121 mtrr_del(ioc->mtrr_reg, 0, 0);
2122 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2126 /* Zap the adapter lookup ptr! */
2127 list_del(&ioc->list);
2129 sz_last = ioc->alloc_total;
2130 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2131 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2134 ioc->alt_ioc->alt_ioc = NULL;
2139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2141 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2142 * @ioc: Pointer to MPT adapter structure
2145 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2149 printk(KERN_INFO "%s: ", ioc->name);
2150 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2151 printk("%s: ", ioc->prod_name+3);
2152 printk("Capabilities={");
2154 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2155 printk("Initiator");
2159 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2160 printk("%sTarget", i ? "," : "");
2164 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2165 printk("%sLAN", i ? "," : "");
2171 * This would probably evoke more questions than it's worth
2173 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2174 printk("%sLogBusAddr", i ? "," : "");
2182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2184 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2185 * @ioc: Pointer to MPT_ADAPTER structure
2186 * @force: Force hard KickStart of IOC
2187 * @sleepFlag: Specifies whether the process can sleep
2190 * 1 - DIAG reset and READY
2191 * 0 - READY initially OR soft reset and READY
2192 * -1 - Any failure on KickStart
2193 * -2 - Msg Unit Reset Failed
2194 * -3 - IO Unit Reset Failed
2195 * -4 - IOC owned by a PEER
2198 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2203 int hard_reset_done = 0;
2208 /* Get current [raw] IOC state */
2209 ioc_state = mpt_GetIocState(ioc, 0);
2210 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2213 * Check to see if IOC got left/stuck in doorbell handshake
2214 * grip of death. If so, hard reset the IOC.
2216 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2218 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2222 /* Is it already READY? */
2223 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2227 * Check to see if IOC is in FAULT state.
2229 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2231 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2233 printk(KERN_WARNING " FAULT code = %04xh\n",
2234 ioc_state & MPI_DOORBELL_DATA_MASK);
2238 * Hmmm... Did it get left operational?
2240 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2241 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2245 * If PCI Peer, exit.
2246 * Else, if no fault conditions are present, issue a MessageUnitReset
2247 * Else, fall through to KickStart case
2249 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2250 dinitprintk((KERN_INFO MYNAM
2251 ": whoinit 0x%x statefault %d force %d\n",
2252 whoinit, statefault, force));
2253 if (whoinit == MPI_WHOINIT_PCI_PEER)
2256 if ((statefault == 0 ) && (force == 0)) {
2257 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2264 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2265 if (hard_reset_done < 0)
2269 * Loop here waiting for IOC to come READY.
2272 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2274 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2275 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2277 * BIOS or previous driver load left IOC in OP state.
2278 * Reset messaging FIFOs.
2280 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2281 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2284 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2286 * Something is wrong. Try to get IOC back
2289 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2290 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2297 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2298 ioc->name, (int)((ii+5)/HZ));
2302 if (sleepFlag == CAN_SLEEP) {
2303 msleep_interruptible(1);
2305 mdelay (1); /* 1 msec delay */
2310 if (statefault < 3) {
2311 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2313 statefault==1 ? "stuck handshake" : "IOC FAULT");
2316 return hard_reset_done;
2319 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2321 * mpt_GetIocState - Get the current state of a MPT adapter.
2322 * @ioc: Pointer to MPT_ADAPTER structure
2323 * @cooked: Request raw or cooked IOC state
2325 * Returns all IOC Doorbell register bits if cooked==0, else just the
2326 * Doorbell bits in MPI_IOC_STATE_MASK.
2329 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2334 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2335 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2336 sc = s & MPI_IOC_STATE_MASK;
2339 ioc->last_state = sc;
2341 return cooked ? sc : s;
2344 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2346 * GetIocFacts - Send IOCFacts request to MPT adapter.
2347 * @ioc: Pointer to MPT_ADAPTER structure
2348 * @sleepFlag: Specifies whether the process can sleep
2349 * @reason: If recovery, only update facts.
2351 * Returns 0 for success, non-zero for failure.
2354 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2356 IOCFacts_t get_facts;
2357 IOCFactsReply_t *facts;
2365 /* IOC *must* NOT be in RESET state! */
2366 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2367 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2373 facts = &ioc->facts;
2375 /* Destination (reply area)... */
2376 reply_sz = sizeof(*facts);
2377 memset(facts, 0, reply_sz);
2379 /* Request area (get_facts on the stack right now!) */
2380 req_sz = sizeof(get_facts);
2381 memset(&get_facts, 0, req_sz);
2383 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2384 /* Assert: All other get_facts fields are zero! */
2386 dinitprintk((MYIOC_s_INFO_FMT
2387 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2388 ioc->name, req_sz, reply_sz));
2390 /* No non-zero fields in the get_facts request are greater than
2391 * 1 byte in size, so we can just fire it off as is.
2393 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2394 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2399 * Now byte swap (GRRR) the necessary fields before any further
2400 * inspection of reply contents.
2402 * But need to do some sanity checks on MsgLength (byte) field
2403 * to make sure we don't zero IOC's req_sz!
2405 /* Did we get a valid reply? */
2406 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2407 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2409 * If not been here, done that, save off first WhoInit value
2411 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2412 ioc->FirstWhoInit = facts->WhoInit;
2415 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2416 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2417 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2418 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2419 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2420 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2421 /* CHECKME! IOCStatus, IOCLogInfo */
2423 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2424 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2427 * FC f/w version changed between 1.1 and 1.2
2428 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2429 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2431 if (facts->MsgVersion < 0x0102) {
2433 * Handle old FC f/w style, convert to new...
2435 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2436 facts->FWVersion.Word =
2437 ((oldv<<12) & 0xFF000000) |
2438 ((oldv<<8) & 0x000FFF00);
2440 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2442 facts->ProductID = le16_to_cpu(facts->ProductID);
2443 facts->CurrentHostMfaHighAddr =
2444 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2445 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2446 facts->CurrentSenseBufferHighAddr =
2447 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2448 facts->CurReplyFrameSize =
2449 le16_to_cpu(facts->CurReplyFrameSize);
2450 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2453 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2454 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2455 * to 14 in MPI-1.01.0x.
2457 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2458 facts->MsgVersion > 0x0100) {
2459 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2462 sz = facts->FWImageSize;
2467 facts->FWImageSize = sz;
2469 if (!facts->RequestFrameSize) {
2470 /* Something is wrong! */
2471 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2476 r = sz = facts->BlockSize;
2477 vv = ((63 / (sz * 4)) + 1) & 0x03;
2478 ioc->NB_for_64_byte_frame = vv;
2484 ioc->NBShiftFactor = shiftFactor;
2485 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2486 ioc->name, vv, shiftFactor, r));
2488 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2490 * Set values for this IOC's request & reply frame sizes,
2491 * and request & reply queue depths...
2493 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2494 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2495 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2496 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2498 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2499 ioc->name, ioc->reply_sz, ioc->reply_depth));
2500 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2501 ioc->name, ioc->req_sz, ioc->req_depth));
2503 /* Get port facts! */
2504 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2508 printk(MYIOC_s_ERR_FMT
2509 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2510 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2511 RequestFrameSize)/sizeof(u32)));
2518 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2520 * GetPortFacts - Send PortFacts request to MPT adapter.
2521 * @ioc: Pointer to MPT_ADAPTER structure
2522 * @portnum: Port number
2523 * @sleepFlag: Specifies whether the process can sleep
2525 * Returns 0 for success, non-zero for failure.
2528 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2530 PortFacts_t get_pfacts;
2531 PortFactsReply_t *pfacts;
2536 /* IOC *must* NOT be in RESET state! */
2537 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2538 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2544 pfacts = &ioc->pfacts[portnum];
2546 /* Destination (reply area)... */
2547 reply_sz = sizeof(*pfacts);
2548 memset(pfacts, 0, reply_sz);
2550 /* Request area (get_pfacts on the stack right now!) */
2551 req_sz = sizeof(get_pfacts);
2552 memset(&get_pfacts, 0, req_sz);
2554 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2555 get_pfacts.PortNumber = portnum;
2556 /* Assert: All other get_pfacts fields are zero! */
2558 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2559 ioc->name, portnum));
2561 /* No non-zero fields in the get_pfacts request are greater than
2562 * 1 byte in size, so we can just fire it off as is.
2564 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2565 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2569 /* Did we get a valid reply? */
2571 /* Now byte swap the necessary fields in the response. */
2572 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2573 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2574 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2575 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2576 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2577 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2578 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2579 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2580 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2585 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2587 * SendIocInit - Send IOCInit request to MPT adapter.
2588 * @ioc: Pointer to MPT_ADAPTER structure
2589 * @sleepFlag: Specifies whether the process can sleep
2591 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2593 * Returns 0 for success, non-zero for failure.
2596 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2599 MPIDefaultReply_t init_reply;
2605 memset(&ioc_init, 0, sizeof(ioc_init));
2606 memset(&init_reply, 0, sizeof(init_reply));
2608 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2609 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2611 /* If we are in a recovery mode and we uploaded the FW image,
2612 * then this pointer is not NULL. Skip the upload a second time.
2613 * Set this flag if cached_fw set for either IOC.
2615 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2619 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2620 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2622 if(ioc->bus_type == SAS)
2623 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2624 else if(ioc->bus_type == FC)
2625 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2627 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2628 ioc_init.MaxBuses = MPT_MAX_BUS;
2629 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2630 ioc->name, ioc->facts.MsgVersion));
2631 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2632 // set MsgVersion and HeaderVersion host driver was built with
2633 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2634 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2636 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2637 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2638 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2641 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2643 if (sizeof(dma_addr_t) == sizeof(u64)) {
2644 /* Save the upper 32-bits of the request
2645 * (reply) and sense buffers.
2647 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2648 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2650 /* Force 32-bit addressing */
2651 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2652 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2655 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2656 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2657 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2658 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2660 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2661 ioc->name, &ioc_init));
2663 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2664 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2666 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2670 /* No need to byte swap the multibyte fields in the reply
2671 * since we don't even look at it's contents.
2674 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2675 ioc->name, &ioc_init));
2677 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2678 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2682 /* YIKES! SUPER IMPORTANT!!!
2683 * Poll IocState until _OPERATIONAL while IOC is doing
2684 * LoopInit and TargetDiscovery!
2687 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2688 state = mpt_GetIocState(ioc, 1);
2689 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2690 if (sleepFlag == CAN_SLEEP) {
2691 msleep_interruptible(1);
2697 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2698 ioc->name, (int)((count+5)/HZ));
2702 state = mpt_GetIocState(ioc, 1);
2705 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2713 * SendPortEnable - Send PortEnable request to MPT adapter port.
2714 * @ioc: Pointer to MPT_ADAPTER structure
2715 * @portnum: Port number to enable
2716 * @sleepFlag: Specifies whether the process can sleep
2718 * Send PortEnable to bring IOC to OPERATIONAL state.
2720 * Returns 0 for success, non-zero for failure.
2723 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2725 PortEnable_t port_enable;
2726 MPIDefaultReply_t reply_buf;
2731 /* Destination... */
2732 reply_sz = sizeof(MPIDefaultReply_t);
2733 memset(&reply_buf, 0, reply_sz);
2735 req_sz = sizeof(PortEnable_t);
2736 memset(&port_enable, 0, req_sz);
2738 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2739 port_enable.PortNumber = portnum;
2740 /* port_enable.ChainOffset = 0; */
2741 /* port_enable.MsgFlags = 0; */
2742 /* port_enable.MsgContext = 0; */
2744 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2745 ioc->name, portnum, &port_enable));
2747 /* RAID FW may take a long time to enable
2749 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2750 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2751 (ioc->bus_type == SAS)) {
2752 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2753 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2754 300 /*seconds*/, sleepFlag);
2756 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2757 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2758 30 /*seconds*/, sleepFlag);
2764 * ioc: Pointer to MPT_ADAPTER structure
2765 * size - total FW bytes
2768 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2771 return; /* use already allocated memory */
2772 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2773 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2774 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2776 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2777 ioc->alloc_total += size;
2781 * If alt_img is NULL, delete from ioc structure.
2782 * Else, delete a secondary image in same format.
2785 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2789 sz = ioc->facts.FWImageSize;
2790 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2791 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2792 pci_free_consistent(ioc->pcidev, sz,
2793 ioc->cached_fw, ioc->cached_fw_dma);
2794 ioc->cached_fw = NULL;
2800 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2802 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2803 * @ioc: Pointer to MPT_ADAPTER structure
2804 * @sleepFlag: Specifies whether the process can sleep
2806 * Returns 0 for success, >0 for handshake failure
2807 * <0 for fw upload failure.
2809 * Remark: If bound IOC and a successful FWUpload was performed
2810 * on the bound IOC, the second image is discarded
2811 * and memory is free'd. Both channels must upload to prevent
2812 * IOC from running in degraded mode.
2815 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2817 u8 request[ioc->req_sz];
2818 u8 reply[sizeof(FWUploadReply_t)];
2819 FWUpload_t *prequest;
2820 FWUploadReply_t *preply;
2821 FWUploadTCSGE_t *ptcsge;
2824 int ii, sz, reply_sz;
2827 /* If the image size is 0, we are done.
2829 if ((sz = ioc->facts.FWImageSize) == 0)
2832 mpt_alloc_fw_memory(ioc, sz);
2834 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2835 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2837 if (ioc->cached_fw == NULL) {
2843 prequest = (FWUpload_t *)&request;
2844 preply = (FWUploadReply_t *)&reply;
2846 /* Destination... */
2847 memset(prequest, 0, ioc->req_sz);
2849 reply_sz = sizeof(reply);
2850 memset(preply, 0, reply_sz);
2852 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2853 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2855 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2856 ptcsge->DetailsLength = 12;
2857 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2858 ptcsge->ImageSize = cpu_to_le32(sz);
2860 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2862 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2863 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2865 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2866 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2867 prequest, sgeoffset));
2868 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2870 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2871 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2873 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2875 cmdStatus = -EFAULT;
2877 /* Handshake transfer was complete and successful.
2878 * Check the Reply Frame.
2880 int status, transfer_sz;
2881 status = le16_to_cpu(preply->IOCStatus);
2882 if (status == MPI_IOCSTATUS_SUCCESS) {
2883 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2884 if (transfer_sz == sz)
2888 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2889 ioc->name, cmdStatus));
2894 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2896 mpt_free_fw_memory(ioc);
2902 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2904 * mpt_downloadboot - DownloadBoot code
2905 * @ioc: Pointer to MPT_ADAPTER structure
2906 * @flag: Specify which part of IOC memory is to be uploaded.
2907 * @sleepFlag: Specifies whether the process can sleep
2909 * FwDownloadBoot requires Programmed IO access.
2911 * Returns 0 for success
2912 * -1 FW Image size is 0
2913 * -2 No valid cached_fw Pointer
2914 * <0 for fw upload failure.
2917 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2919 MpiExtImageHeader_t *pExtImage;
2929 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2930 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2932 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2933 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2934 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2935 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2936 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2937 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2939 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2942 if (sleepFlag == CAN_SLEEP) {
2943 msleep_interruptible(1);
2948 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2949 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2951 for (count = 0; count < 30; count ++) {
2952 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2953 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2954 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2959 if (sleepFlag == CAN_SLEEP) {
2960 msleep_interruptible (100);
2966 if ( count == 30 ) {
2967 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2968 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2969 ioc->name, diag0val));
2973 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2974 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2975 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2976 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2977 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2978 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2980 /* Set the DiagRwEn and Disable ARM bits */
2981 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2983 fwSize = (pFwHeader->ImageSize + 3)/4;
2984 ptrFw = (u32 *) pFwHeader;
2986 /* Write the LoadStartAddress to the DiagRw Address Register
2987 * using Programmed IO
2989 if (ioc->errata_flag_1064)
2990 pci_enable_io_access(ioc->pcidev);
2992 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2993 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2994 ioc->name, pFwHeader->LoadStartAddress));
2996 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2997 ioc->name, fwSize*4, ptrFw));
2999 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3002 nextImage = pFwHeader->NextImageHeaderOffset;
3004 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3006 load_addr = pExtImage->LoadStartAddress;
3008 fwSize = (pExtImage->ImageSize + 3) >> 2;
3009 ptrFw = (u32 *)pExtImage;
3011 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3012 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3013 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3016 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3018 nextImage = pExtImage->NextImageHeaderOffset;
3021 /* Write the IopResetVectorRegAddr */
3022 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3023 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3025 /* Write the IopResetVectorValue */
3026 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3027 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3029 /* Clear the internal flash bad bit - autoincrementing register,
3030 * so must do two writes.
3032 if (ioc->bus_type == SPI) {
3034 * 1030 and 1035 H/W errata, workaround to access
3035 * the ClearFlashBadSignatureBit
3037 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3038 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3039 diagRwData |= 0x40000000;
3040 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3041 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3043 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3044 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3045 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3046 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3049 if (sleepFlag == CAN_SLEEP) {
3050 msleep_interruptible (1);
3056 if (ioc->errata_flag_1064)
3057 pci_disable_io_access(ioc->pcidev);
3059 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3060 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3061 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3062 ioc->name, diag0val));
3063 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3064 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3065 ioc->name, diag0val));
3066 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3068 /* Write 0xFF to reset the sequencer */
3069 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3071 if (ioc->bus_type == SAS) {
3072 ioc_state = mpt_GetIocState(ioc, 0);
3073 if ( (GetIocFacts(ioc, sleepFlag,
3074 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3075 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3076 ioc->name, ioc_state));
3081 for (count=0; count<HZ*20; count++) {
3082 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3083 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3084 ioc->name, count, ioc_state));
3085 if (ioc->bus_type == SAS) {
3088 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3089 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3093 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3097 if (sleepFlag == CAN_SLEEP) {
3098 msleep_interruptible (10);
3103 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3104 ioc->name, ioc_state));
3108 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3110 * KickStart - Perform hard reset of MPT adapter.
3111 * @ioc: Pointer to MPT_ADAPTER structure
3112 * @force: Force hard reset
3113 * @sleepFlag: Specifies whether the process can sleep
3115 * This routine places MPT adapter in diagnostic mode via the
3116 * WriteSequence register, and then performs a hard reset of adapter
3117 * via the Diagnostic register.
3119 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3120 * or NO_SLEEP (interrupt thread, use mdelay)
3121 * force - 1 if doorbell active, board fault state
3122 * board operational, IOC_RECOVERY or
3123 * IOC_BRINGUP and there is an alt_ioc.
3127 * 1 - hard reset, READY
3128 * 0 - no reset due to History bit, READY
3129 * -1 - no reset due to History bit but not READY
3130 * OR reset but failed to come READY
3131 * -2 - no reset, could not enter DIAG mode
3132 * -3 - reset but bad FW bit
3135 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3137 int hard_reset_done = 0;
3141 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3142 if (ioc->bus_type == SPI) {
3143 /* Always issue a Msg Unit Reset first. This will clear some
3144 * SCSI bus hang conditions.
3146 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3148 if (sleepFlag == CAN_SLEEP) {
3149 msleep_interruptible (1000);
3155 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3156 if (hard_reset_done < 0)
3157 return hard_reset_done;
3159 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3162 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3163 for (cnt=0; cnt<cntdn; cnt++) {
3164 ioc_state = mpt_GetIocState(ioc, 1);
3165 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3166 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3168 return hard_reset_done;
3170 if (sleepFlag == CAN_SLEEP) {
3171 msleep_interruptible (10);
3177 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3178 ioc->name, ioc_state);
3182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3184 * mpt_diag_reset - Perform hard reset of the adapter.
3185 * @ioc: Pointer to MPT_ADAPTER structure
3186 * @ignore: Set if to honor and clear to ignore
3187 * the reset history bit
3188 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3189 * else set to NO_SLEEP (use mdelay instead)
3191 * This routine places the adapter in diagnostic mode via the
3192 * WriteSequence register and then performs a hard reset of adapter
3193 * via the Diagnostic register. Adapter should be in ready state
3194 * upon successful completion.
3196 * Returns: 1 hard reset successful
3197 * 0 no reset performed because reset history bit set
3198 * -2 enabling diagnostic mode failed
3199 * -3 diagnostic reset failed
3202 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3206 int hard_reset_done = 0;
3212 /* Clear any existing interrupts */
3213 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3215 /* Use "Diagnostic reset" method! (only thing available!) */
3216 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3220 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3221 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3222 ioc->name, diag0val, diag1val));
3225 /* Do the reset if we are told to ignore the reset history
3226 * or if the reset history is 0
3228 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3229 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3230 /* Write magic sequence to WriteSequence register
3231 * Loop until in diagnostic mode
3233 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3234 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3235 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3236 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3237 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3238 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3241 if (sleepFlag == CAN_SLEEP) {
3242 msleep_interruptible (100);
3249 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3250 ioc->name, diag0val);
3255 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3257 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3258 ioc->name, diag0val));
3263 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3264 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3265 ioc->name, diag0val, diag1val));
3268 * Disable the ARM (Bug fix)
3271 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3275 * Now hit the reset bit in the Diagnostic register
3276 * (THE BIG HAMMER!) (Clears DRWE bit).
3278 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3279 hard_reset_done = 1;
3280 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3284 * Call each currently registered protocol IOC reset handler
3285 * with pre-reset indication.
3286 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3287 * MptResetHandlers[] registered yet.
3293 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3294 if (MptResetHandlers[ii]) {
3295 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3297 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3299 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3300 ioc->name, ioc->alt_ioc->name, ii));
3301 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3305 /* FIXME? Examine results here? */
3308 if (ioc->cached_fw) {
3309 /* If the DownloadBoot operation fails, the
3310 * IOC will be left unusable. This is a fatal error
3311 * case. _diag_reset will return < 0
3313 for (count = 0; count < 30; count ++) {
3314 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3315 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3320 if (sleepFlag == CAN_SLEEP) {
3321 msleep_interruptible (1000);
3326 if ((count = mpt_downloadboot(ioc,
3327 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3328 printk(KERN_WARNING MYNAM
3329 ": firmware downloadboot failure (%d)!\n", count);
3333 /* Wait for FW to reload and for board
3334 * to go to the READY state.
3335 * Maximum wait is 60 seconds.
3336 * If fail, no error will check again
3337 * with calling program.
3339 for (count = 0; count < 60; count ++) {
3340 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3341 doorbell &= MPI_IOC_STATE_MASK;
3343 if (doorbell == MPI_IOC_STATE_READY) {
3348 if (sleepFlag == CAN_SLEEP) {
3349 msleep_interruptible (1000);
3357 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3360 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3361 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3362 ioc->name, diag0val, diag1val));
3365 /* Clear RESET_HISTORY bit! Place board in the
3366 * diagnostic mode to update the diag register.
3368 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3370 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3371 /* Write magic sequence to WriteSequence register
3372 * Loop until in diagnostic mode
3374 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3375 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3376 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3377 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3378 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3379 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3382 if (sleepFlag == CAN_SLEEP) {
3383 msleep_interruptible (100);
3390 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3391 ioc->name, diag0val);
3394 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3396 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3397 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3398 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3399 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3400 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3404 /* Disable Diagnostic Mode
3406 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3408 /* Check FW reload status flags.
3410 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3411 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3412 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3413 ioc->name, diag0val);
3419 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3420 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3421 ioc->name, diag0val, diag1val));
3425 * Reset flag that says we've enabled event notification
3427 ioc->facts.EventState = 0;
3430 ioc->alt_ioc->facts.EventState = 0;
3432 return hard_reset_done;
3435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3437 * SendIocReset - Send IOCReset request to MPT adapter.
3438 * @ioc: Pointer to MPT_ADAPTER structure
3439 * @reset_type: reset type, expected values are
3440 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3442 * Send IOCReset request to the MPT adapter.
3444 * Returns 0 for success, non-zero for failure.
3447 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3453 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3454 ioc->name, reset_type));
3455 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3456 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3459 /* FW ACK'd request, wait for READY state
3462 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3464 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3468 if (sleepFlag != CAN_SLEEP)
3471 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3472 ioc->name, (int)((count+5)/HZ));
3476 if (sleepFlag == CAN_SLEEP) {
3477 msleep_interruptible(1);
3479 mdelay (1); /* 1 msec delay */
3484 * Cleanup all event stuff for this IOC; re-issue EventNotification
3485 * request if needed.
3487 if (ioc->facts.Function)
3488 ioc->facts.EventState = 0;
3493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3495 * initChainBuffers - Allocate memory for and initialize
3496 * chain buffers, chain buffer control arrays and spinlock.
3497 * @hd: Pointer to MPT_SCSI_HOST structure
3498 * @init: If set, initialize the spin lock.
3501 initChainBuffers(MPT_ADAPTER *ioc)
3504 int sz, ii, num_chain;
3505 int scale, num_sge, numSGE;
3507 /* ReqToChain size must equal the req_depth
3510 if (ioc->ReqToChain == NULL) {
3511 sz = ioc->req_depth * sizeof(int);
3512 mem = kmalloc(sz, GFP_ATOMIC);
3516 ioc->ReqToChain = (int *) mem;
3517 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3518 ioc->name, mem, sz));
3519 mem = kmalloc(sz, GFP_ATOMIC);
3523 ioc->RequestNB = (int *) mem;
3524 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3525 ioc->name, mem, sz));
3527 for (ii = 0; ii < ioc->req_depth; ii++) {
3528 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3531 /* ChainToChain size must equal the total number
3532 * of chain buffers to be allocated.
3535 * Calculate the number of chain buffers needed(plus 1) per I/O
3536 * then multiply the the maximum number of simultaneous cmds
3538 * num_sge = num sge in request frame + last chain buffer
3539 * scale = num sge per chain buffer if no chain element
3541 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3542 if (sizeof(dma_addr_t) == sizeof(u64))
3543 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3545 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3547 if (sizeof(dma_addr_t) == sizeof(u64)) {
3548 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3549 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3551 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3552 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3554 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3555 ioc->name, num_sge, numSGE));
3557 if ( numSGE > MPT_SCSI_SG_DEPTH )
3558 numSGE = MPT_SCSI_SG_DEPTH;
3561 while (numSGE - num_sge > 0) {
3563 num_sge += (scale - 1);
3567 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3568 ioc->name, numSGE, num_sge, num_chain));
3570 if (ioc->bus_type == SPI)
3571 num_chain *= MPT_SCSI_CAN_QUEUE;
3573 num_chain *= MPT_FC_CAN_QUEUE;
3575 ioc->num_chain = num_chain;
3577 sz = num_chain * sizeof(int);
3578 if (ioc->ChainToChain == NULL) {
3579 mem = kmalloc(sz, GFP_ATOMIC);
3583 ioc->ChainToChain = (int *) mem;
3584 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3585 ioc->name, mem, sz));
3587 mem = (u8 *) ioc->ChainToChain;
3589 memset(mem, 0xFF, sz);
3593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3595 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3596 * @ioc: Pointer to MPT_ADAPTER structure
3598 * This routine allocates memory for the MPT reply and request frame
3599 * pools (if necessary), and primes the IOC reply FIFO with
3602 * Returns 0 for success, non-zero for failure.
3605 PrimeIocFifos(MPT_ADAPTER *ioc)
3608 unsigned long flags;
3609 dma_addr_t alloc_dma;
3611 int i, reply_sz, sz, total_size, num_chain;
3613 /* Prime reply FIFO... */
3615 if (ioc->reply_frames == NULL) {
3616 if ( (num_chain = initChainBuffers(ioc)) < 0)
3619 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3620 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3621 ioc->name, ioc->reply_sz, ioc->reply_depth));
3622 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3623 ioc->name, reply_sz, reply_sz));
3625 sz = (ioc->req_sz * ioc->req_depth);
3626 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3627 ioc->name, ioc->req_sz, ioc->req_depth));
3628 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3629 ioc->name, sz, sz));
3632 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3633 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3634 ioc->name, ioc->req_sz, num_chain));
3635 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3636 ioc->name, sz, sz, num_chain));
3639 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3641 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3646 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3647 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3649 memset(mem, 0, total_size);
3650 ioc->alloc_total += total_size;
3652 ioc->alloc_dma = alloc_dma;
3653 ioc->alloc_sz = total_size;
3654 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3655 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3657 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3658 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3660 alloc_dma += reply_sz;
3663 /* Request FIFO - WE manage this! */
3665 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3666 ioc->req_frames_dma = alloc_dma;
3668 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3669 ioc->name, mem, (void *)(ulong)alloc_dma));
3671 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3673 #if defined(CONFIG_MTRR) && 0
3675 * Enable Write Combining MTRR for IOC's memory region.
3676 * (at least as much as we can; "size and base must be
3677 * multiples of 4 kiB"
3679 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3681 MTRR_TYPE_WRCOMB, 1);
3682 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3683 ioc->name, ioc->req_frames_dma, sz));
3686 for (i = 0; i < ioc->req_depth; i++) {
3687 alloc_dma += ioc->req_sz;
3691 ioc->ChainBuffer = mem;
3692 ioc->ChainBufferDMA = alloc_dma;
3694 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3695 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3697 /* Initialize the free chain Q.
3700 INIT_LIST_HEAD(&ioc->FreeChainQ);
3702 /* Post the chain buffers to the FreeChainQ.
3704 mem = (u8 *)ioc->ChainBuffer;
3705 for (i=0; i < num_chain; i++) {
3706 mf = (MPT_FRAME_HDR *) mem;
3707 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3711 /* Initialize Request frames linked list
3713 alloc_dma = ioc->req_frames_dma;
3714 mem = (u8 *) ioc->req_frames;
3716 spin_lock_irqsave(&ioc->FreeQlock, flags);
3717 INIT_LIST_HEAD(&ioc->FreeQ);
3718 for (i = 0; i < ioc->req_depth; i++) {
3719 mf = (MPT_FRAME_HDR *) mem;
3721 /* Queue REQUESTs *internally*! */
3722 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3726 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3728 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3729 ioc->sense_buf_pool =
3730 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3731 if (ioc->sense_buf_pool == NULL) {
3732 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3737 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3738 ioc->alloc_total += sz;
3739 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3740 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3744 /* Post Reply frames to FIFO
3746 alloc_dma = ioc->alloc_dma;
3747 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3748 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3750 for (i = 0; i < ioc->reply_depth; i++) {
3751 /* Write each address to the IOC! */
3752 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3753 alloc_dma += ioc->reply_sz;
3759 if (ioc->alloc != NULL) {
3761 pci_free_consistent(ioc->pcidev,
3763 ioc->alloc, ioc->alloc_dma);
3764 ioc->reply_frames = NULL;
3765 ioc->req_frames = NULL;
3766 ioc->alloc_total -= sz;
3768 if (ioc->sense_buf_pool != NULL) {
3769 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3770 pci_free_consistent(ioc->pcidev,
3772 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3773 ioc->sense_buf_pool = NULL;
3778 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3780 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3781 * from IOC via doorbell handshake method.
3782 * @ioc: Pointer to MPT_ADAPTER structure
3783 * @reqBytes: Size of the request in bytes
3784 * @req: Pointer to MPT request frame
3785 * @replyBytes: Expected size of the reply in bytes
3786 * @u16reply: Pointer to area where reply should be written
3787 * @maxwait: Max wait time for a reply (in seconds)
3788 * @sleepFlag: Specifies whether the process can sleep
3790 * NOTES: It is the callers responsibility to byte-swap fields in the
3791 * request which are greater than 1 byte in size. It is also the
3792 * callers responsibility to byte-swap response fields which are
3793 * greater than 1 byte in size.
3795 * Returns 0 for success, non-zero for failure.
3798 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3799 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3801 MPIDefaultReply_t *mptReply;
3806 * Get ready to cache a handshake reply
3808 ioc->hs_reply_idx = 0;
3809 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3810 mptReply->MsgLength = 0;
3813 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3814 * then tell IOC that we want to handshake a request of N words.
3815 * (WRITE u32val to Doorbell reg).
3817 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3818 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3819 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3820 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3823 * Wait for IOC's doorbell handshake int
3825 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3828 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3829 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3831 /* Read doorbell and check for active bit */
3832 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3836 * Clear doorbell int (WRITE 0 to IntStatus reg),
3837 * then wait for IOC to ACKnowledge that it's ready for
3838 * our handshake request.
3840 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3841 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3846 u8 *req_as_bytes = (u8 *) req;
3849 * Stuff request words via doorbell handshake,
3850 * with ACK from IOC for each.
3852 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3853 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3854 (req_as_bytes[(ii*4) + 1] << 8) |
3855 (req_as_bytes[(ii*4) + 2] << 16) |
3856 (req_as_bytes[(ii*4) + 3] << 24));
3858 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3859 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3863 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3864 DBG_DUMP_REQUEST_FRAME_HDR(req)
3866 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3867 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3870 * Wait for completion of doorbell handshake reply from the IOC
3872 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3875 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3876 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3879 * Copy out the cached reply...
3881 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3882 u16reply[ii] = ioc->hs_reply[ii];
3890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3892 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3893 * in it's IntStatus register.
3894 * @ioc: Pointer to MPT_ADAPTER structure
3895 * @howlong: How long to wait (in seconds)
3896 * @sleepFlag: Specifies whether the process can sleep
3898 * This routine waits (up to ~2 seconds max) for IOC doorbell
3899 * handshake ACKnowledge.
3901 * Returns a negative value on failure, else wait loop count.
3904 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3910 cntdn = 1000 * howlong;
3912 if (sleepFlag == CAN_SLEEP) {
3914 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3915 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3917 msleep_interruptible (1);
3922 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3923 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3931 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3936 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3937 ioc->name, count, intstat);
3941 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3943 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3944 * in it's IntStatus register.
3945 * @ioc: Pointer to MPT_ADAPTER structure
3946 * @howlong: How long to wait (in seconds)
3947 * @sleepFlag: Specifies whether the process can sleep
3949 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3951 * Returns a negative value on failure, else wait loop count.
3954 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3960 cntdn = 1000 * howlong;
3961 if (sleepFlag == CAN_SLEEP) {
3963 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3964 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3966 msleep_interruptible(1);
3971 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3972 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3980 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3981 ioc->name, count, howlong));
3985 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3986 ioc->name, count, intstat);
3990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3992 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3993 * @ioc: Pointer to MPT_ADAPTER structure
3994 * @howlong: How long to wait (in seconds)
3995 * @sleepFlag: Specifies whether the process can sleep
3997 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3998 * Reply is cached to IOC private area large enough to hold a maximum
3999 * of 128 bytes of reply data.
4001 * Returns a negative value on failure, else size of reply in WORDS.
4004 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4009 u16 *hs_reply = ioc->hs_reply;
4010 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4013 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4016 * Get first two u16's so we can look at IOC's intended reply MsgLength
4019 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4022 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4023 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4024 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4027 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4028 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4032 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4033 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4034 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4037 * If no error (and IOC said MsgLength is > 0), piece together
4038 * reply 16 bits at a time.
4040 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4041 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4043 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4044 /* don't overflow our IOC hs_reply[] buffer! */
4045 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4046 hs_reply[u16cnt] = hword;
4047 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4050 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4052 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4055 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4060 else if (u16cnt != (2 * mptReply->MsgLength)) {
4063 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4068 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4069 DBG_DUMP_REPLY_FRAME(mptReply)
4071 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4072 ioc->name, t, u16cnt/2));
4076 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4078 * GetLanConfigPages - Fetch LANConfig pages.
4079 * @ioc: Pointer to MPT_ADAPTER structure
4081 * Return: 0 for success
4082 * -ENOMEM if no memory available
4083 * -EPERM if not allowed due to ISR context
4084 * -EAGAIN if no msg frames currently available
4085 * -EFAULT for non-successful reply or no reply (timeout)
4088 GetLanConfigPages(MPT_ADAPTER *ioc)
4090 ConfigPageHeader_t hdr;
4092 LANPage0_t *ppage0_alloc;
4093 dma_addr_t page0_dma;
4094 LANPage1_t *ppage1_alloc;
4095 dma_addr_t page1_dma;
4100 /* Get LAN Page 0 header */
4101 hdr.PageVersion = 0;
4104 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4105 cfg.cfghdr.hdr = &hdr;
4107 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4112 if ((rc = mpt_config(ioc, &cfg)) != 0)
4115 if (hdr.PageLength > 0) {
4116 data_sz = hdr.PageLength * 4;
4117 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4120 memset((u8 *)ppage0_alloc, 0, data_sz);
4121 cfg.physAddr = page0_dma;
4122 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4124 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4126 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4127 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4131 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4134 * Normalize endianness of structure data,
4135 * by byte-swapping all > 1 byte fields!
4144 /* Get LAN Page 1 header */
4145 hdr.PageVersion = 0;
4148 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4149 cfg.cfghdr.hdr = &hdr;
4151 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4155 if ((rc = mpt_config(ioc, &cfg)) != 0)
4158 if (hdr.PageLength == 0)
4161 data_sz = hdr.PageLength * 4;
4163 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4165 memset((u8 *)ppage1_alloc, 0, data_sz);
4166 cfg.physAddr = page1_dma;
4167 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4169 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4171 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4172 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4175 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4178 * Normalize endianness of structure data,
4179 * by byte-swapping all > 1 byte fields!
4187 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4189 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4190 * @ioc: Pointer to MPT_ADAPTER structure
4191 * @portnum: IOC Port number
4193 * Return: 0 for success
4194 * -ENOMEM if no memory available
4195 * -EPERM if not allowed due to ISR context
4196 * -EAGAIN if no msg frames currently available
4197 * -EFAULT for non-successful reply or no reply (timeout)
4200 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4202 ConfigPageHeader_t hdr;
4204 FCPortPage0_t *ppage0_alloc;
4205 FCPortPage0_t *pp0dest;
4206 dma_addr_t page0_dma;
4213 /* Get FCPort Page 0 header */
4214 hdr.PageVersion = 0;
4217 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4218 cfg.cfghdr.hdr = &hdr;
4220 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4222 cfg.pageAddr = portnum;
4225 if ((rc = mpt_config(ioc, &cfg)) != 0)
4228 if (hdr.PageLength == 0)
4231 data_sz = hdr.PageLength * 4;
4233 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4237 memset((u8 *)ppage0_alloc, 0, data_sz);
4238 cfg.physAddr = page0_dma;
4239 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4241 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4243 pp0dest = &ioc->fc_port_page0[portnum];
4244 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4245 memcpy(pp0dest, ppage0_alloc, copy_sz);
4248 * Normalize endianness of structure data,
4249 * by byte-swapping all > 1 byte fields!
4251 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4252 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4253 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4254 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4255 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4256 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4257 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4258 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4259 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4260 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4261 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4262 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4263 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4264 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4265 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4266 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4269 * if still doing discovery,
4270 * hang loose a while until finished
4272 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4274 msleep_interruptible(100);
4277 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4283 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4289 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4291 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4292 * @ioc: Pointer to MPT_ADAPTER structure
4293 * @sas_address: 64bit SAS Address for operation.
4294 * @target_id: specified target for operation
4295 * @bus: specified bus for operation
4296 * @persist_opcode: see below
4298 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4299 * devices not currently present.
4300 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4302 * NOTE: Don't use not this function during interrupt time.
4304 * Returns: 0 for success, non-zero error
4307 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4309 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4311 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4312 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4313 MPT_FRAME_HDR *mf = NULL;
4314 MPIHeader_t *mpi_hdr;
4317 /* insure garbage is not sent to fw */
4318 switch(persist_opcode) {
4320 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4321 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4329 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4331 /* Get a MF for this command.
4333 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4334 printk("%s: no msg frames!\n",__FUNCTION__);
4338 mpi_hdr = (MPIHeader_t *) mf;
4339 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4340 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4341 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4342 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4343 sasIoUnitCntrReq->Operation = persist_opcode;
4345 init_timer(&ioc->persist_timer);
4346 ioc->persist_timer.data = (unsigned long) ioc;
4347 ioc->persist_timer.function = mpt_timer_expired;
4348 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4349 ioc->persist_wait_done=0;
4350 add_timer(&ioc->persist_timer);
4351 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4352 wait_event(mpt_waitq, ioc->persist_wait_done);
4354 sasIoUnitCntrReply =
4355 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4356 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4357 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4359 sasIoUnitCntrReply->IOCStatus,
4360 sasIoUnitCntrReply->IOCLogInfo);
4364 printk("%s: success\n",__FUNCTION__);
4368 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4371 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4372 MpiEventDataRaid_t * pRaidEventData)
4381 volume = pRaidEventData->VolumeID;
4382 reason = pRaidEventData->ReasonCode;
4383 disk = pRaidEventData->PhysDiskNum;
4384 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4385 flags = (status >> 0) & 0xff;
4386 state = (status >> 8) & 0xff;
4388 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4392 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4393 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4394 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4395 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4398 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4403 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4404 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4408 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4410 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4414 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4415 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4419 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4420 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4422 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4424 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4426 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4429 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4431 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4432 ? ", quiesced" : "",
4433 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4434 ? ", resync in progress" : "" );
4437 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4438 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4442 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4443 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4447 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4448 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4452 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4453 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4457 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4458 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4460 state == MPI_PHYSDISK0_STATUS_ONLINE
4462 : state == MPI_PHYSDISK0_STATUS_MISSING
4464 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4466 : state == MPI_PHYSDISK0_STATUS_FAILED
4468 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4470 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4471 ? "offline requested"
4472 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4473 ? "failed requested"
4474 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4477 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4478 ? ", out of sync" : "",
4479 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4480 ? ", quiesced" : "" );
4483 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4484 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4488 case MPI_EVENT_RAID_RC_SMART_DATA:
4489 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4490 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4493 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4494 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4500 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4502 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4503 * @ioc: Pointer to MPT_ADAPTER structure
4505 * Returns: 0 for success
4506 * -ENOMEM if no memory available
4507 * -EPERM if not allowed due to ISR context
4508 * -EAGAIN if no msg frames currently available
4509 * -EFAULT for non-successful reply or no reply (timeout)
4512 GetIoUnitPage2(MPT_ADAPTER *ioc)
4514 ConfigPageHeader_t hdr;
4516 IOUnitPage2_t *ppage_alloc;
4517 dma_addr_t page_dma;
4521 /* Get the page header */
4522 hdr.PageVersion = 0;
4525 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4526 cfg.cfghdr.hdr = &hdr;
4528 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4533 if ((rc = mpt_config(ioc, &cfg)) != 0)
4536 if (hdr.PageLength == 0)
4539 /* Read the config page */
4540 data_sz = hdr.PageLength * 4;
4542 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4544 memset((u8 *)ppage_alloc, 0, data_sz);
4545 cfg.physAddr = page_dma;
4546 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4548 /* If Good, save data */
4549 if ((rc = mpt_config(ioc, &cfg)) == 0)
4550 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4552 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4558 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4559 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4560 * @ioc: Pointer to a Adapter Strucutre
4561 * @portnum: IOC port number
4563 * Return: -EFAULT if read of config page header fails
4565 * If read of SCSI Port Page 0 fails,
4566 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4567 * Adapter settings: async, narrow
4569 * If read of SCSI Port Page 2 fails,
4570 * Adapter settings valid
4571 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4576 * CHECK - what type of locking mechanisms should be used????
4579 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4584 ConfigPageHeader_t header;
4590 if (!ioc->spi_data.nvram) {
4593 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4594 mem = kmalloc(sz, GFP_ATOMIC);
4598 ioc->spi_data.nvram = (int *) mem;
4600 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4601 ioc->name, ioc->spi_data.nvram, sz));
4604 /* Invalidate NVRAM information
4606 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4607 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4610 /* Read SPP0 header, allocate memory, then read page.
4612 header.PageVersion = 0;
4613 header.PageLength = 0;
4614 header.PageNumber = 0;
4615 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4616 cfg.cfghdr.hdr = &header;
4618 cfg.pageAddr = portnum;
4619 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4621 cfg.timeout = 0; /* use default */
4622 if (mpt_config(ioc, &cfg) != 0)
4625 if (header.PageLength > 0) {
4626 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4628 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4629 cfg.physAddr = buf_dma;
4630 if (mpt_config(ioc, &cfg) != 0) {
4631 ioc->spi_data.maxBusWidth = MPT_NARROW;
4632 ioc->spi_data.maxSyncOffset = 0;
4633 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4634 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4636 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4637 ioc->name, ioc->spi_data.minSyncFactor));
4639 /* Save the Port Page 0 data
4641 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4642 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4643 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4645 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4646 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4647 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4648 ioc->name, pPP0->Capabilities));
4650 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4651 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4653 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4654 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4655 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4656 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4657 ioc->name, ioc->spi_data.minSyncFactor));
4659 ioc->spi_data.maxSyncOffset = 0;
4660 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4663 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4665 /* Update the minSyncFactor based on bus type.
4667 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4668 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4670 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4671 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4672 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4673 ioc->name, ioc->spi_data.minSyncFactor));
4678 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4683 /* SCSI Port Page 2 - Read the header then the page.
4685 header.PageVersion = 0;
4686 header.PageLength = 0;
4687 header.PageNumber = 2;
4688 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4689 cfg.cfghdr.hdr = &header;
4691 cfg.pageAddr = portnum;
4692 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4694 if (mpt_config(ioc, &cfg) != 0)
4697 if (header.PageLength > 0) {
4698 /* Allocate memory and read SCSI Port Page 2
4700 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4702 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4703 cfg.physAddr = buf_dma;
4704 if (mpt_config(ioc, &cfg) != 0) {
4705 /* Nvram data is left with INVALID mark
4709 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4710 MpiDeviceInfo_t *pdevice = NULL;
4713 * Save "Set to Avoid SCSI Bus Resets" flag
4715 ioc->spi_data.bus_reset =
4716 (le32_to_cpu(pPP2->PortFlags) &
4717 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4720 /* Save the Port Page 2 data
4721 * (reformat into a 32bit quantity)
4723 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4724 ioc->spi_data.PortFlags = data;
4725 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4726 pdevice = &pPP2->DeviceSettings[ii];
4727 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4728 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4729 ioc->spi_data.nvram[ii] = data;
4733 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4737 /* Update Adapter limits with those from NVRAM
4738 * Comment: Don't need to do this. Target performance
4739 * parameters will never exceed the adapters limits.
4745 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4746 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4747 * @ioc: Pointer to a Adapter Strucutre
4748 * @portnum: IOC port number
4750 * Return: -EFAULT if read of config page header fails
4754 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4757 ConfigPageHeader_t header;
4759 /* Read the SCSI Device Page 1 header
4761 header.PageVersion = 0;
4762 header.PageLength = 0;
4763 header.PageNumber = 1;
4764 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4765 cfg.cfghdr.hdr = &header;
4767 cfg.pageAddr = portnum;
4768 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4771 if (mpt_config(ioc, &cfg) != 0)
4774 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4775 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4777 header.PageVersion = 0;
4778 header.PageLength = 0;
4779 header.PageNumber = 0;
4780 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4781 if (mpt_config(ioc, &cfg) != 0)
4784 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4785 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4787 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4788 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4790 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4791 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4795 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4797 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4798 * @ioc: Pointer to a Adapter Strucutre
4799 * @portnum: IOC port number
4803 * -EFAULT if read of config page header fails or data pointer not NULL
4804 * -ENOMEM if pci_alloc failed
4807 mpt_findImVolumes(MPT_ADAPTER *ioc)
4811 ConfigPageIoc2RaidVol_t *pIocRv;
4812 dma_addr_t ioc2_dma;
4814 ConfigPageHeader_t header;
4821 /* Read IOCP2 header then the page.
4823 header.PageVersion = 0;
4824 header.PageLength = 0;
4825 header.PageNumber = 2;
4826 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4827 cfg.cfghdr.hdr = &header;
4830 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4833 if (mpt_config(ioc, &cfg) != 0)
4836 if (header.PageLength == 0)
4839 iocpage2sz = header.PageLength * 4;
4840 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4844 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4845 cfg.physAddr = ioc2_dma;
4846 if (mpt_config(ioc, &cfg) != 0)
4849 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4850 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4852 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4857 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4859 /* Identify RAID Volume Id's */
4860 nVols = pIoc2->NumActiveVolumes;
4866 /* At least 1 RAID Volume
4868 pIocRv = pIoc2->RaidVolume;
4869 ioc->raid_data.isRaid = 0;
4870 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4871 vid = pIocRv->VolumeID;
4872 vbus = pIocRv->VolumeBus;
4873 vioc = pIocRv->VolumeIOC;
4878 ioc->raid_data.isRaid |= (1 << vid);
4880 /* Error! Always bus 0
4886 /* Identify Hidden Physical Disk Id's */
4887 nPhys = pIoc2->NumActivePhysDisks;
4889 /* No physical disks.
4892 mpt_read_ioc_pg_3(ioc);
4896 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4902 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4907 ConfigPageHeader_t header;
4908 dma_addr_t ioc3_dma;
4911 /* Free the old page
4913 kfree(ioc->raid_data.pIocPg3);
4914 ioc->raid_data.pIocPg3 = NULL;
4916 /* There is at least one physical disk.
4917 * Read and save IOC Page 3
4919 header.PageVersion = 0;
4920 header.PageLength = 0;
4921 header.PageNumber = 3;
4922 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4923 cfg.cfghdr.hdr = &header;
4926 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4929 if (mpt_config(ioc, &cfg) != 0)
4932 if (header.PageLength == 0)
4935 /* Read Header good, alloc memory
4937 iocpage3sz = header.PageLength * 4;
4938 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4942 /* Read the Page and save the data
4943 * into malloc'd memory.
4945 cfg.physAddr = ioc3_dma;
4946 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4947 if (mpt_config(ioc, &cfg) == 0) {
4948 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4950 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4951 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4955 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4961 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4965 ConfigPageHeader_t header;
4966 dma_addr_t ioc4_dma;
4969 /* Read and save IOC Page 4
4971 header.PageVersion = 0;
4972 header.PageLength = 0;
4973 header.PageNumber = 4;
4974 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4975 cfg.cfghdr.hdr = &header;
4978 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4981 if (mpt_config(ioc, &cfg) != 0)
4984 if (header.PageLength == 0)
4987 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4988 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4989 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4993 ioc4_dma = ioc->spi_data.IocPg4_dma;
4994 iocpage4sz = ioc->spi_data.IocPg4Sz;
4997 /* Read the Page into dma memory.
4999 cfg.physAddr = ioc4_dma;
5000 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5001 if (mpt_config(ioc, &cfg) == 0) {
5002 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5003 ioc->spi_data.IocPg4_dma = ioc4_dma;
5004 ioc->spi_data.IocPg4Sz = iocpage4sz;
5006 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5007 ioc->spi_data.pIocPg4 = NULL;
5012 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5016 ConfigPageHeader_t header;
5017 dma_addr_t ioc1_dma;
5021 /* Check the Coalescing Timeout in IOC Page 1
5023 header.PageVersion = 0;
5024 header.PageLength = 0;
5025 header.PageNumber = 1;
5026 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5027 cfg.cfghdr.hdr = &header;
5030 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5033 if (mpt_config(ioc, &cfg) != 0)
5036 if (header.PageLength == 0)
5039 /* Read Header good, alloc memory
5041 iocpage1sz = header.PageLength * 4;
5042 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5046 /* Read the Page and check coalescing timeout
5048 cfg.physAddr = ioc1_dma;
5049 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5050 if (mpt_config(ioc, &cfg) == 0) {
5052 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5053 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5054 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5056 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
5059 if (tmp > MPT_COALESCING_TIMEOUT) {
5060 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5062 /* Write NVRAM and current
5065 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5066 if (mpt_config(ioc, &cfg) == 0) {
5067 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
5068 ioc->name, MPT_COALESCING_TIMEOUT));
5070 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5071 if (mpt_config(ioc, &cfg) == 0) {
5072 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
5073 ioc->name, MPT_COALESCING_TIMEOUT));
5075 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
5080 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
5086 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5090 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5097 * SendEventNotification - Send EventNotification (on or off) request
5099 * @ioc: Pointer to MPT_ADAPTER structure
5100 * @EvSwitch: Event switch flags
5103 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5105 EventNotification_t *evnp;
5107 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5109 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5113 memset(evnp, 0, sizeof(*evnp));
5115 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5117 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5118 evnp->ChainOffset = 0;
5120 evnp->Switch = EvSwitch;
5122 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5127 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5129 * SendEventAck - Send EventAck request to MPT adapter.
5130 * @ioc: Pointer to MPT_ADAPTER structure
5131 * @evnp: Pointer to original EventNotification request
5134 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5138 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5139 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5140 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5141 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5142 le32_to_cpu(evnp->Data[0]));
5145 memset(pAck, 0, sizeof(*pAck));
5147 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5149 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5150 pAck->ChainOffset = 0;
5152 pAck->Event = evnp->Event;
5153 pAck->EventContext = evnp->EventContext;
5155 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5160 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5162 * mpt_config - Generic function to issue config message
5163 * @ioc - Pointer to an adapter structure
5164 * @cfg - Pointer to a configuration structure. Struct contains
5165 * action, page address, direction, physical address
5166 * and pointer to a configuration page header
5167 * Page header is updated.
5169 * Returns 0 for success
5170 * -EPERM if not allowed due to ISR context
5171 * -EAGAIN if no msg frames currently available
5172 * -EFAULT for non-successful reply or no reply (timeout)
5175 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5178 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5180 unsigned long flags;
5185 /* Prevent calling wait_event() (below), if caller happens
5186 * to be in ISR context, because that is fatal!
5188 in_isr = in_interrupt();
5190 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5195 /* Get and Populate a free Frame
5197 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5198 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5202 pReq = (Config_t *)mf;
5203 pReq->Action = pCfg->action;
5205 pReq->ChainOffset = 0;
5206 pReq->Function = MPI_FUNCTION_CONFIG;
5208 /* Assume page type is not extended and clear "reserved" fields. */
5209 pReq->ExtPageLength = 0;
5210 pReq->ExtPageType = 0;
5213 for (ii=0; ii < 8; ii++)
5214 pReq->Reserved2[ii] = 0;
5216 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5217 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5218 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5219 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5221 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5222 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5223 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5224 pReq->ExtPageType = pExtHdr->ExtPageType;
5225 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5227 /* Page Length must be treated as a reserved field for the extended header. */
5228 pReq->Header.PageLength = 0;
5231 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5233 /* Add a SGE to the config request.
5236 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5238 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5240 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5241 flagsLength |= pExtHdr->ExtPageLength * 4;
5243 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5244 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5247 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5249 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5250 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5253 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5255 /* Append pCfg pointer to end of mf
5257 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5259 /* Initalize the timer
5261 init_timer(&pCfg->timer);
5262 pCfg->timer.data = (unsigned long) ioc;
5263 pCfg->timer.function = mpt_timer_expired;
5264 pCfg->wait_done = 0;
5266 /* Set the timer; ensure 10 second minimum */
5267 if (pCfg->timeout < 10)
5268 pCfg->timer.expires = jiffies + HZ*10;
5270 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5272 /* Add to end of Q, set timer and then issue this command */
5273 spin_lock_irqsave(&ioc->FreeQlock, flags);
5274 list_add_tail(&pCfg->linkage, &ioc->configQ);
5275 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5277 add_timer(&pCfg->timer);
5278 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5279 wait_event(mpt_waitq, pCfg->wait_done);
5281 /* mf has been freed - do not access */
5288 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5290 * mpt_timer_expired - Call back for timer process.
5291 * Used only internal config functionality.
5292 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5295 mpt_timer_expired(unsigned long data)
5297 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5299 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5301 /* Perform a FW reload */
5302 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5303 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5305 /* No more processing.
5306 * Hard reset clean-up will wake up
5307 * process and free all resources.
5309 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5314 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5316 * mpt_ioc_reset - Base cleanup for hard reset
5317 * @ioc: Pointer to the adapter structure
5318 * @reset_phase: Indicates pre- or post-reset functionality
5320 * Remark: Free's resources with internally generated commands.
5323 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5326 unsigned long flags;
5328 dprintk((KERN_WARNING MYNAM
5329 ": IOC %s_reset routed to MPT base driver!\n",
5330 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5331 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5333 if (reset_phase == MPT_IOC_SETUP_RESET) {
5335 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5336 /* If the internal config Q is not empty -
5337 * delete timer. MF resources will be freed when
5338 * the FIFO's are primed.
5340 spin_lock_irqsave(&ioc->FreeQlock, flags);
5341 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5342 del_timer(&pCfg->timer);
5343 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5348 /* Search the configQ for internal commands.
5349 * Flush the Q, and wake up all suspended threads.
5351 spin_lock_irqsave(&ioc->FreeQlock, flags);
5352 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5353 list_del(&pCfg->linkage);
5355 pCfg->status = MPT_CONFIG_ERROR;
5356 pCfg->wait_done = 1;
5357 wake_up(&mpt_waitq);
5359 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5362 return 1; /* currently means nothing really */
5366 #ifdef CONFIG_PROC_FS /* { */
5367 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5369 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5371 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5373 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5375 * Returns 0 for success, non-zero for failure.
5378 procmpt_create(void)
5380 struct proc_dir_entry *ent;
5382 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5383 if (mpt_proc_root_dir == NULL)
5386 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5388 ent->read_proc = procmpt_summary_read;
5390 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5392 ent->read_proc = procmpt_version_read;
5397 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5399 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5401 * Returns 0 for success, non-zero for failure.
5404 procmpt_destroy(void)
5406 remove_proc_entry("version", mpt_proc_root_dir);
5407 remove_proc_entry("summary", mpt_proc_root_dir);
5408 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5411 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5413 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5414 * or from /proc/mpt/iocN/summary.
5415 * @buf: Pointer to area to write information
5416 * @start: Pointer to start pointer
5417 * @offset: Offset to start writing
5419 * @eof: Pointer to EOF integer
5422 * Returns number of characters written to process performing the read.
5425 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5435 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5439 list_for_each_entry(ioc, &ioc_list, list) {
5442 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5445 if ((out-buf) >= request)
5452 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5455 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5457 * procmpt_version_read - Handle read request from /proc/mpt/version.
5458 * @buf: Pointer to area to write information
5459 * @start: Pointer to start pointer
5460 * @offset: Offset to start writing
5462 * @eof: Pointer to EOF integer
5465 * Returns number of characters written to process performing the read.
5468 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5471 int scsi, fc, sas, lan, ctl, targ, dmp;
5475 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5476 len += sprintf(buf+len, " Fusion MPT base driver\n");
5478 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5479 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5481 if (MptCallbacks[ii]) {
5482 switch (MptDriverClass[ii]) {
5484 if (!scsi++) drvname = "SPI host";
5487 if (!fc++) drvname = "FC host";
5490 if (!sas++) drvname = "SAS host";
5493 if (!lan++) drvname = "LAN";
5496 if (!targ++) drvname = "SCSI target";
5499 if (!ctl++) drvname = "ioctl";
5504 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5508 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5511 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5513 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5514 * @buf: Pointer to area to write information
5515 * @start: Pointer to start pointer
5516 * @offset: Offset to start writing
5518 * @eof: Pointer to EOF integer
5521 * Returns number of characters written to process performing the read.
5524 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5526 MPT_ADAPTER *ioc = data;
5532 mpt_get_fw_exp_ver(expVer, ioc);
5534 len = sprintf(buf, "%s:", ioc->name);
5535 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5536 len += sprintf(buf+len, " (f/w download boot flag set)");
5537 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5538 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5540 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5541 ioc->facts.ProductID,
5543 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5544 if (ioc->facts.FWImageSize)
5545 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5546 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5547 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5548 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5550 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5551 ioc->facts.CurrentHostMfaHighAddr);
5552 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5553 ioc->facts.CurrentSenseBufferHighAddr);
5555 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5556 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5558 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5559 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5561 * Rounding UP to nearest 4-kB boundary here...
5563 sz = (ioc->req_sz * ioc->req_depth) + 128;
5564 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5565 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5566 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5567 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5568 4*ioc->facts.RequestFrameSize,
5569 ioc->facts.GlobalCredits);
5571 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5572 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5573 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5574 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5575 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5576 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5577 ioc->facts.CurReplyFrameSize,
5578 ioc->facts.ReplyQueueDepth);
5580 len += sprintf(buf+len, " MaxDevices = %d\n",
5581 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5582 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5585 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5586 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5588 ioc->facts.NumberOfPorts);
5589 if (ioc->bus_type == FC) {
5590 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5591 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5592 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5593 a[5], a[4], a[3], a[2], a[1], a[0]);
5595 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5596 ioc->fc_port_page0[p].WWNN.High,
5597 ioc->fc_port_page0[p].WWNN.Low,
5598 ioc->fc_port_page0[p].WWPN.High,
5599 ioc->fc_port_page0[p].WWPN.Low);
5603 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5606 #endif /* CONFIG_PROC_FS } */
5608 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5610 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5613 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5614 sprintf(buf, " (Exp %02d%02d)",
5615 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5616 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5619 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5620 strcat(buf, " [MDBG]");
5624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5626 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5627 * @ioc: Pointer to MPT_ADAPTER structure
5628 * @buffer: Pointer to buffer where IOC summary info should be written
5629 * @size: Pointer to number of bytes we wrote (set by this routine)
5630 * @len: Offset at which to start writing in buffer
5631 * @showlan: Display LAN stuff?
5633 * This routine writes (english readable) ASCII text, which represents
5634 * a summary of IOC information, to a buffer.
5637 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5642 mpt_get_fw_exp_ver(expVer, ioc);
5645 * Shorter summary of attached ioc's...
5647 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5650 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5651 ioc->facts.FWVersion.Word,
5653 ioc->facts.NumberOfPorts,
5656 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5657 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5658 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5659 a[5], a[4], a[3], a[2], a[1], a[0]);
5663 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5665 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5669 y += sprintf(buffer+len+y, " (disabled)");
5671 y += sprintf(buffer+len+y, "\n");
5676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5682 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5683 * Management call based on input arg values. If TaskMgmt fails,
5684 * return associated SCSI request.
5685 * @ioc: Pointer to MPT_ADAPTER structure
5686 * @sleepFlag: Indicates if sleep or schedule must be called.
5688 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5689 * or a non-interrupt thread. In the former, must not call schedule().
5691 * Remark: A return of -1 is a FATAL error case, as it means a
5692 * FW reload/initialization failed.
5694 * Returns 0 for SUCCESS or -1 if FAILED.
5697 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5700 unsigned long flags;
5702 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5704 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5705 printk("MF count 0x%x !\n", ioc->mfcnt);
5708 /* Reset the adapter. Prevent more than 1 call to
5709 * mpt_do_ioc_recovery at any instant in time.
5711 spin_lock_irqsave(&ioc->diagLock, flags);
5712 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5713 spin_unlock_irqrestore(&ioc->diagLock, flags);
5716 ioc->diagPending = 1;
5718 spin_unlock_irqrestore(&ioc->diagLock, flags);
5720 /* FIXME: If do_ioc_recovery fails, repeat....
5723 /* The SCSI driver needs to adjust timeouts on all current
5724 * commands prior to the diagnostic reset being issued.
5725 * Prevents timeouts occuring during a diagnostic reset...very bad.
5726 * For all other protocol drivers, this is a no-op.
5732 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5733 if (MptResetHandlers[ii]) {
5734 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5736 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5738 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5739 ioc->name, ioc->alt_ioc->name, ii));
5740 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5746 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5747 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5752 ioc->alt_ioc->reload_fw = 0;
5754 spin_lock_irqsave(&ioc->diagLock, flags);
5755 ioc->diagPending = 0;
5757 ioc->alt_ioc->diagPending = 0;
5758 spin_unlock_irqrestore(&ioc->diagLock, flags);
5760 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5765 # define EVENT_DESCR_STR_SZ 100
5767 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5769 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5774 case MPI_EVENT_NONE:
5777 case MPI_EVENT_LOG_DATA:
5780 case MPI_EVENT_STATE_CHANGE:
5781 ds = "State Change";
5783 case MPI_EVENT_UNIT_ATTENTION:
5784 ds = "Unit Attention";
5786 case MPI_EVENT_IOC_BUS_RESET:
5787 ds = "IOC Bus Reset";
5789 case MPI_EVENT_EXT_BUS_RESET:
5790 ds = "External Bus Reset";
5792 case MPI_EVENT_RESCAN:
5793 ds = "Bus Rescan Event";
5794 /* Ok, do we need to do anything here? As far as
5795 I can tell, this is when a new device gets added
5798 case MPI_EVENT_LINK_STATUS_CHANGE:
5799 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5800 ds = "Link Status(FAILURE) Change";
5802 ds = "Link Status(ACTIVE) Change";
5804 case MPI_EVENT_LOOP_STATE_CHANGE:
5805 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5806 ds = "Loop State(LIP) Change";
5807 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5808 ds = "Loop State(LPE) Change"; /* ??? */
5810 ds = "Loop State(LPB) Change"; /* ??? */
5812 case MPI_EVENT_LOGOUT:
5815 case MPI_EVENT_EVENT_CHANGE:
5817 ds = "Events(ON) Change";
5819 ds = "Events(OFF) Change";
5821 case MPI_EVENT_INTEGRATED_RAID:
5823 u8 ReasonCode = (u8)(evData0 >> 16);
5824 switch (ReasonCode) {
5825 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5826 ds = "Integrated Raid: Volume Created";
5828 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5829 ds = "Integrated Raid: Volume Deleted";
5831 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5832 ds = "Integrated Raid: Volume Settings Changed";
5834 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5835 ds = "Integrated Raid: Volume Status Changed";
5837 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5838 ds = "Integrated Raid: Volume Physdisk Changed";
5840 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5841 ds = "Integrated Raid: Physdisk Created";
5843 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5844 ds = "Integrated Raid: Physdisk Deleted";
5846 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5847 ds = "Integrated Raid: Physdisk Settings Changed";
5849 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5850 ds = "Integrated Raid: Physdisk Status Changed";
5852 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5853 ds = "Integrated Raid: Domain Validation Needed";
5855 case MPI_EVENT_RAID_RC_SMART_DATA :
5856 ds = "Integrated Raid; Smart Data";
5858 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5859 ds = "Integrated Raid: Replace Action Started";
5862 ds = "Integrated Raid";
5867 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5868 ds = "SCSI Device Status Change";
5870 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5872 u8 id = (u8)(evData0);
5873 u8 ReasonCode = (u8)(evData0 >> 16);
5874 switch (ReasonCode) {
5875 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5876 snprintf(evStr, EVENT_DESCR_STR_SZ,
5877 "SAS Device Status Change: Added: id=%d", id);
5879 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5880 snprintf(evStr, EVENT_DESCR_STR_SZ,
5881 "SAS Device Status Change: Deleted: id=%d", id);
5883 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5884 snprintf(evStr, EVENT_DESCR_STR_SZ,
5885 "SAS Device Status Change: SMART Data: id=%d",
5888 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5889 snprintf(evStr, EVENT_DESCR_STR_SZ,
5890 "SAS Device Status Change: No Persistancy "
5891 "Added: id=%d", id);
5894 snprintf(evStr, EVENT_DESCR_STR_SZ,
5895 "SAS Device Status Change: Unknown: id=%d", id);
5900 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5901 ds = "Bus Timer Expired";
5903 case MPI_EVENT_QUEUE_FULL:
5906 case MPI_EVENT_SAS_SES:
5907 ds = "SAS SES Event";
5909 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5910 ds = "Persistent Table Full";
5912 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5914 u8 LinkRates = (u8)(evData0 >> 8);
5915 u8 PhyNumber = (u8)(evData0);
5916 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5917 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5918 switch (LinkRates) {
5919 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5920 snprintf(evStr, EVENT_DESCR_STR_SZ,
5921 "SAS PHY Link Status: Phy=%d:"
5922 " Rate Unknown",PhyNumber);
5924 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5925 snprintf(evStr, EVENT_DESCR_STR_SZ,
5926 "SAS PHY Link Status: Phy=%d:"
5927 " Phy Disabled",PhyNumber);
5929 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5930 snprintf(evStr, EVENT_DESCR_STR_SZ,
5931 "SAS PHY Link Status: Phy=%d:"
5932 " Failed Speed Nego",PhyNumber);
5934 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5935 snprintf(evStr, EVENT_DESCR_STR_SZ,
5936 "SAS PHY Link Status: Phy=%d:"
5937 " Sata OOB Completed",PhyNumber);
5939 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5940 snprintf(evStr, EVENT_DESCR_STR_SZ,
5941 "SAS PHY Link Status: Phy=%d:"
5942 " Rate 1.5 Gbps",PhyNumber);
5944 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5945 snprintf(evStr, EVENT_DESCR_STR_SZ,
5946 "SAS PHY Link Status: Phy=%d:"
5947 " Rate 3.0 Gpbs",PhyNumber);
5950 snprintf(evStr, EVENT_DESCR_STR_SZ,
5951 "SAS PHY Link Status: Phy=%d", PhyNumber);
5956 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5957 ds = "SAS Discovery Error";
5959 case MPI_EVENT_IR_RESYNC_UPDATE:
5961 u8 resync_complete = (u8)(evData0 >> 16);
5962 snprintf(evStr, EVENT_DESCR_STR_SZ,
5963 "IR Resync Update: Complete = %d:",resync_complete);
5968 u8 ReasonCode = (u8)(evData0 >> 16);
5969 switch (ReasonCode) {
5970 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5971 ds = "IR2: LD State Changed";
5973 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5974 ds = "IR2: PD State Changed";
5976 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5977 ds = "IR2: Bad Block Table Full";
5979 case MPI_EVENT_IR2_RC_PD_INSERTED:
5980 ds = "IR2: PD Inserted";
5982 case MPI_EVENT_IR2_RC_PD_REMOVED:
5983 ds = "IR2: PD Removed";
5985 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5986 ds = "IR2: Foreign CFG Detected";
5988 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5989 ds = "IR2: Rebuild Medium Error";
5997 case MPI_EVENT_SAS_DISCOVERY:
6000 ds = "SAS Discovery: Start";
6002 ds = "SAS Discovery: Stop";
6005 case MPI_EVENT_LOG_ENTRY_ADDED:
6006 ds = "SAS Log Entry Added";
6010 * MPT base "custom" events may be added here...
6017 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6020 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6022 * ProcessEventNotification - Route a received EventNotificationReply to
6023 * all currently regeistered event handlers.
6024 * @ioc: Pointer to MPT_ADAPTER structure
6025 * @pEventReply: Pointer to EventNotification reply frame
6026 * @evHandlers: Pointer to integer, number of event handlers
6028 * Returns sum of event handlers return values.
6031 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6039 char evStr[EVENT_DESCR_STR_SZ];
6043 * Do platform normalization of values
6045 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6046 // evCtx = le32_to_cpu(pEventReply->EventContext);
6047 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6049 evData0 = le32_to_cpu(pEventReply->Data[0]);
6052 EventDescriptionStr(event, evData0, evStr);
6053 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
6058 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
6059 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
6060 for (ii = 0; ii < evDataLen; ii++)
6061 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
6066 * Do general / base driver event processing
6069 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6071 u8 evState = evData0 & 0xFF;
6073 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6075 /* Update EventState field in cached IocFacts */
6076 if (ioc->facts.Function) {
6077 ioc->facts.EventState = evState;
6081 case MPI_EVENT_INTEGRATED_RAID:
6082 mptbase_raid_process_event_data(ioc,
6083 (MpiEventDataRaid_t *)pEventReply->Data);
6090 * Should this event be logged? Events are written sequentially.
6091 * When buffer is full, start again at the top.
6093 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6096 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6098 ioc->events[idx].event = event;
6099 ioc->events[idx].eventContext = ioc->eventContext;
6101 for (ii = 0; ii < 2; ii++) {
6103 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6105 ioc->events[idx].data[ii] = 0;
6108 ioc->eventContext++;
6113 * Call each currently registered protocol event handler.
6115 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6116 if (MptEvHandlers[ii]) {
6117 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6119 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6123 /* FIXME? Examine results here? */
6126 * If needed, send (a single) EventAck.
6128 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6129 devtverboseprintk((MYIOC_s_WARN_FMT
6130 "EventAck required\n",ioc->name));
6131 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6132 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6137 *evHandlers = handlers;
6141 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6143 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6144 * @ioc: Pointer to MPT_ADAPTER structure
6145 * @log_info: U32 LogInfo reply word from the IOC
6147 * Refer to lsi/fc_log.h.
6150 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6152 static char *subcl_str[8] = {
6153 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6154 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6156 u8 subcl = (log_info >> 24) & 0x7;
6158 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6159 ioc->name, log_info, subcl_str[subcl]);
6162 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6164 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6165 * @ioc: Pointer to MPT_ADAPTER structure
6166 * @mr: Pointer to MPT reply frame
6167 * @log_info: U32 LogInfo word from the IOC
6169 * Refer to lsi/sp_log.h.
6172 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6174 u32 info = log_info & 0x00FF0000;
6175 char *desc = "unknown";
6179 desc = "bug! MID not found";
6180 if (ioc->reload_fw == 0)
6185 desc = "Parity Error";
6189 desc = "ASYNC Outbound Overrun";
6193 desc = "SYNC Offset Error";
6201 desc = "Msg In Overflow";
6209 desc = "Outbound DMA Overrun";
6213 desc = "Task Management";
6217 desc = "Device Problem";
6221 desc = "Invalid Phase Change";
6225 desc = "Untagged Table Size";
6230 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6233 /* strings for sas loginfo */
6234 static char *originator_str[] = {
6239 static char *iop_code_str[] = {
6241 "Invalid SAS Address", /* 01h */
6243 "Invalid Page", /* 03h */
6245 "Task Terminated" /* 05h */
6247 static char *pl_code_str[] = {
6249 "Open Failure", /* 01h */
6250 "Invalid Scatter Gather List", /* 02h */
6251 "Wrong Relative Offset or Frame Length", /* 03h */
6252 "Frame Transfer Error", /* 04h */
6253 "Transmit Frame Connected Low", /* 05h */
6254 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6255 "SATA Read Log Receive Data Error", /* 07h */
6256 "SATA NCQ Fail All Commands After Error", /* 08h */
6257 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6258 "Receive Frame Invalid Message", /* 0Ah */
6259 "Receive Context Message Valid Error", /* 0Bh */
6260 "Receive Frame Current Frame Error", /* 0Ch */
6261 "SATA Link Down", /* 0Dh */
6262 "Discovery SATA Init W IOS", /* 0Eh */
6263 "Config Invalid Page", /* 0Fh */
6264 "Discovery SATA Init Timeout", /* 10h */
6267 "IO Not Yet Executed", /* 13h */
6268 "IO Executed", /* 14h */
6269 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6270 "Open Transmit DMA Abort", /* 16h */
6280 "Enclosure Management" /* 20h */
6283 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6285 * mpt_sas_log_info - Log information returned from SAS IOC.
6286 * @ioc: Pointer to MPT_ADAPTER structure
6287 * @log_info: U32 LogInfo reply word from the IOC
6289 * Refer to lsi/mpi_log_sas.h.
6292 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6294 union loginfo_type {
6303 union loginfo_type sas_loginfo;
6304 char *code_desc = NULL;
6306 sas_loginfo.loginfo = log_info;
6307 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6308 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6310 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6311 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6312 code_desc = iop_code_str[sas_loginfo.dw.code];
6313 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6314 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6315 code_desc = pl_code_str[sas_loginfo.dw.code];
6318 if (code_desc != NULL)
6319 printk(MYIOC_s_INFO_FMT
6320 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6321 " SubCode(0x%04x)\n",
6324 originator_str[sas_loginfo.dw.originator],
6326 sas_loginfo.dw.subcode);
6328 printk(MYIOC_s_INFO_FMT
6329 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6330 " SubCode(0x%04x)\n",
6333 originator_str[sas_loginfo.dw.originator],
6334 sas_loginfo.dw.code,
6335 sas_loginfo.dw.subcode);
6338 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6340 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6341 * @ioc: Pointer to MPT_ADAPTER structure
6342 * @ioc_status: U32 IOCStatus word from IOC
6343 * @mf: Pointer to MPT request frame
6345 * Refer to lsi/mpi.h.
6348 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6350 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6354 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6355 desc = "Invalid Function";
6358 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6362 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6363 desc = "Invalid SGL";
6366 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6367 desc = "Internal Error";
6370 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6374 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6375 desc = "Insufficient Resources";
6378 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6379 desc = "Invalid Field";
6382 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6383 desc = "Invalid State";
6386 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6387 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6388 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6389 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6390 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6391 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6392 /* No message for Config IOCStatus values */
6395 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6396 /* No message for recovered error
6397 desc = "SCSI Recovered Error";
6401 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6402 desc = "SCSI Invalid Bus";
6405 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6406 desc = "SCSI Invalid TargetID";
6409 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6411 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6412 U8 cdb = pScsiReq->CDB[0];
6413 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6414 desc = "SCSI Device Not There";
6419 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6420 desc = "SCSI Data Overrun";
6423 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6424 /* This error is checked in scsi_io_done(). Skip.
6425 desc = "SCSI Data Underrun";
6429 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6430 desc = "SCSI I/O Data Error";
6433 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6434 desc = "SCSI Protocol Error";
6437 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6438 desc = "SCSI Task Terminated";
6441 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6442 desc = "SCSI Residual Mismatch";
6445 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6446 desc = "SCSI Task Management Failed";
6449 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6450 desc = "SCSI IOC Terminated";
6453 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6454 desc = "SCSI Ext Terminated";
6462 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6465 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6466 EXPORT_SYMBOL(mpt_attach);
6467 EXPORT_SYMBOL(mpt_detach);
6469 EXPORT_SYMBOL(mpt_resume);
6470 EXPORT_SYMBOL(mpt_suspend);
6472 EXPORT_SYMBOL(ioc_list);
6473 EXPORT_SYMBOL(mpt_proc_root_dir);
6474 EXPORT_SYMBOL(mpt_register);
6475 EXPORT_SYMBOL(mpt_deregister);
6476 EXPORT_SYMBOL(mpt_event_register);
6477 EXPORT_SYMBOL(mpt_event_deregister);
6478 EXPORT_SYMBOL(mpt_reset_register);
6479 EXPORT_SYMBOL(mpt_reset_deregister);
6480 EXPORT_SYMBOL(mpt_device_driver_register);
6481 EXPORT_SYMBOL(mpt_device_driver_deregister);
6482 EXPORT_SYMBOL(mpt_get_msg_frame);
6483 EXPORT_SYMBOL(mpt_put_msg_frame);
6484 EXPORT_SYMBOL(mpt_free_msg_frame);
6485 EXPORT_SYMBOL(mpt_add_sge);
6486 EXPORT_SYMBOL(mpt_send_handshake_request);
6487 EXPORT_SYMBOL(mpt_verify_adapter);
6488 EXPORT_SYMBOL(mpt_GetIocState);
6489 EXPORT_SYMBOL(mpt_print_ioc_summary);
6490 EXPORT_SYMBOL(mpt_lan_index);
6491 EXPORT_SYMBOL(mpt_stm_index);
6492 EXPORT_SYMBOL(mpt_HardResetHandler);
6493 EXPORT_SYMBOL(mpt_config);
6494 EXPORT_SYMBOL(mpt_findImVolumes);
6495 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6496 EXPORT_SYMBOL(mpt_free_fw_memory);
6497 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6498 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6501 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6503 * fusion_init - Fusion MPT base driver initialization routine.
6505 * Returns 0 for success, non-zero for failure.
6512 show_mptmod_ver(my_NAME, my_VERSION);
6513 printk(KERN_INFO COPYRIGHT "\n");
6515 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6516 MptCallbacks[i] = NULL;
6517 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6518 MptEvHandlers[i] = NULL;
6519 MptResetHandlers[i] = NULL;
6522 /* Register ourselves (mptbase) in order to facilitate
6523 * EventNotification handling.
6525 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6527 /* Register for hard reset handling callbacks.
6529 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6530 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6535 #ifdef CONFIG_PROC_FS
6536 (void) procmpt_create();
6541 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6543 * fusion_exit - Perform driver unload cleanup.
6545 * This routine frees all resources associated with each MPT adapter
6546 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6552 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6554 mpt_reset_deregister(mpt_base_index);
6556 #ifdef CONFIG_PROC_FS
6561 module_init(fusion_init);
6562 module_exit(fusion_exit);