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->fc_rport_lock);
1193 spin_lock_init(&ioc->initializing_hba_lock);
1195 /* Initialize the event logging.
1197 ioc->eventTypes = 0; /* None */
1198 ioc->eventContext = 0;
1199 ioc->eventLogSize = 0;
1206 ioc->cached_fw = NULL;
1208 /* Initilize SCSI Config Data structure
1210 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1212 /* Initialize the running configQ head.
1214 INIT_LIST_HEAD(&ioc->configQ);
1216 /* Initialize the fc rport list head.
1218 INIT_LIST_HEAD(&ioc->fc_rports);
1220 /* Find lookup slot. */
1221 INIT_LIST_HEAD(&ioc->list);
1222 ioc->id = mpt_ids++;
1224 mem_phys = msize = 0;
1226 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1227 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1228 /* Get I/O space! */
1229 port = pci_resource_start(pdev, ii);
1230 psize = pci_resource_len(pdev,ii);
1233 mem_phys = pci_resource_start(pdev, ii);
1234 msize = pci_resource_len(pdev,ii);
1238 ioc->mem_size = msize;
1240 if (ii == DEVICE_COUNT_RESOURCE) {
1241 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1246 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1247 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1250 /* Get logical ptr for PciMem0 space */
1251 /*mem = ioremap(mem_phys, msize);*/
1252 mem = ioremap(mem_phys, 0x100);
1254 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1259 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1261 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1262 &ioc->facts, &ioc->pfacts[0]));
1264 ioc->mem_phys = mem_phys;
1265 ioc->chip = (SYSIF_REGS __iomem *)mem;
1267 /* Save Port IO values in case we need to do downloadboot */
1269 u8 *pmem = (u8*)port;
1270 ioc->pio_mem_phys = port;
1271 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1274 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1275 ioc->prod_name = "LSIFC909";
1278 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1279 ioc->prod_name = "LSIFC929";
1282 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1283 ioc->prod_name = "LSIFC919";
1286 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1287 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1289 if (revision < XL_929) {
1290 ioc->prod_name = "LSIFC929X";
1291 /* 929X Chip Fix. Set Split transactions level
1292 * for PCIX. Set MOST bits to zero.
1294 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1296 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1298 ioc->prod_name = "LSIFC929XL";
1299 /* 929XL Chip Fix. Set MMRBC to 0x08.
1301 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1303 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1306 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1307 ioc->prod_name = "LSIFC919X";
1309 /* 919X Chip Fix. Set Split transactions level
1310 * for PCIX. Set MOST bits to zero.
1312 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1314 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1316 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1317 ioc->prod_name = "LSIFC939X";
1319 ioc->errata_flag_1064 = 1;
1321 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1322 ioc->prod_name = "LSIFC949X";
1324 ioc->errata_flag_1064 = 1;
1326 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1327 ioc->prod_name = "LSIFC949E";
1330 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1331 ioc->prod_name = "LSI53C1030";
1332 ioc->bus_type = SPI;
1333 /* 1030 Chip Fix. Disable Split transactions
1334 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1336 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1337 if (revision < C0_1030) {
1338 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1340 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1343 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1344 ioc->prod_name = "LSI53C1035";
1345 ioc->bus_type = SPI;
1347 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1348 ioc->prod_name = "LSISAS1064";
1349 ioc->bus_type = SAS;
1350 ioc->errata_flag_1064 = 1;
1352 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1353 ioc->prod_name = "LSISAS1066";
1354 ioc->bus_type = SAS;
1355 ioc->errata_flag_1064 = 1;
1357 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1358 ioc->prod_name = "LSISAS1068";
1359 ioc->bus_type = SAS;
1360 ioc->errata_flag_1064 = 1;
1362 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1363 ioc->prod_name = "LSISAS1064E";
1364 ioc->bus_type = SAS;
1366 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1367 ioc->prod_name = "LSISAS1066E";
1368 ioc->bus_type = SAS;
1370 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1371 ioc->prod_name = "LSISAS1068E";
1372 ioc->bus_type = SAS;
1375 if (ioc->errata_flag_1064)
1376 pci_disable_io_access(pdev);
1378 sprintf(ioc->name, "ioc%d", ioc->id);
1380 spin_lock_init(&ioc->FreeQlock);
1383 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1385 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1387 /* Set lookup ptr. */
1388 list_add_tail(&ioc->list, &ioc_list);
1392 if (mpt_msi_enable && !pci_enable_msi(pdev))
1393 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
1395 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1399 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1400 ioc->name, pdev->irq);
1402 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1403 ioc->name, __irq_itoa(pdev->irq));
1405 list_del(&ioc->list);
1411 ioc->pci_irq = pdev->irq;
1413 pci_set_master(pdev); /* ?? */
1414 pci_set_drvdata(pdev, ioc);
1417 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1419 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1423 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1425 mpt_detect_bound_ports(ioc, pdev);
1427 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1429 printk(KERN_WARNING MYNAM
1430 ": WARNING - %s did not initialize properly! (%d)\n",
1433 list_del(&ioc->list);
1434 free_irq(ioc->pci_irq, ioc);
1436 pci_disable_msi(pdev);
1438 ioc->alt_ioc->alt_ioc = NULL;
1441 pci_set_drvdata(pdev, NULL);
1445 /* call per device driver probe entry point */
1446 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1447 if(MptDeviceDriverHandlers[ii] &&
1448 MptDeviceDriverHandlers[ii]->probe) {
1449 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1453 #ifdef CONFIG_PROC_FS
1455 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1457 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1459 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1461 ent->read_proc = procmpt_iocinfo_read;
1464 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1466 ent->read_proc = procmpt_summary_read;
1475 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1477 * mpt_detach - Remove a PCI intelligent MPT adapter.
1478 * @pdev: Pointer to pci_dev structure
1483 mpt_detach(struct pci_dev *pdev)
1485 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1489 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1490 remove_proc_entry(pname, NULL);
1491 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1492 remove_proc_entry(pname, NULL);
1493 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1494 remove_proc_entry(pname, NULL);
1496 /* call per device driver remove entry point */
1497 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1498 if(MptDeviceDriverHandlers[ii] &&
1499 MptDeviceDriverHandlers[ii]->remove) {
1500 MptDeviceDriverHandlers[ii]->remove(pdev);
1504 /* Disable interrupts! */
1505 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1508 synchronize_irq(pdev->irq);
1510 /* Clear any lingering interrupt */
1511 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1513 CHIPREG_READ32(&ioc->chip->IntStatus);
1515 mpt_adapter_dispose(ioc);
1517 pci_set_drvdata(pdev, NULL);
1520 /**************************************************************************
1524 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526 * mpt_suspend - Fusion MPT base driver suspend routine.
1531 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1534 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1536 device_state=pci_choose_state(pdev, state);
1538 printk(MYIOC_s_INFO_FMT
1539 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1540 ioc->name, pdev, pci_name(pdev), device_state);
1542 pci_save_state(pdev);
1544 /* put ioc into READY_STATE */
1545 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1546 printk(MYIOC_s_ERR_FMT
1547 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1550 /* disable interrupts */
1551 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1554 /* Clear any lingering interrupt */
1555 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1557 pci_disable_device(pdev);
1558 pci_set_power_state(pdev, device_state);
1563 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1565 * mpt_resume - Fusion MPT base driver resume routine.
1570 mpt_resume(struct pci_dev *pdev)
1572 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1573 u32 device_state = pdev->current_state;
1576 printk(MYIOC_s_INFO_FMT
1577 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1578 ioc->name, pdev, pci_name(pdev), device_state);
1580 pci_set_power_state(pdev, 0);
1581 pci_restore_state(pdev);
1582 pci_enable_device(pdev);
1584 /* enable interrupts */
1585 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1588 printk(MYIOC_s_INFO_FMT
1589 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1591 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1592 CHIPREG_READ32(&ioc->chip->Doorbell));
1594 /* bring ioc to operational state */
1595 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1596 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1597 printk(MYIOC_s_INFO_FMT
1598 "pci-resume: Cannot recover, error:[%x]\n",
1599 ioc->name, recovery_state);
1601 printk(MYIOC_s_INFO_FMT
1602 "pci-resume: success\n", ioc->name);
1609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1611 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1612 * @ioc: Pointer to MPT adapter structure
1613 * @reason: Event word / reason
1614 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1616 * This routine performs all the steps necessary to bring the IOC
1617 * to a OPERATIONAL state.
1619 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1624 * -1 if failed to get board READY
1625 * -2 if READY but IOCFacts Failed
1626 * -3 if READY but PrimeIOCFifos Failed
1627 * -4 if READY but IOCInit Failed
1630 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1632 int hard_reset_done = 0;
1633 int alt_ioc_ready = 0;
1639 int reset_alt_ioc_active = 0;
1641 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1642 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1644 /* Disable reply interrupts (also blocks FreeQ) */
1645 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1649 if (ioc->alt_ioc->active)
1650 reset_alt_ioc_active = 1;
1652 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1653 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1654 ioc->alt_ioc->active = 0;
1658 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1661 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1662 if (hard_reset_done == -4) {
1663 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1666 if (reset_alt_ioc_active && ioc->alt_ioc) {
1667 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1668 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1669 ioc->alt_ioc->name));
1670 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1671 ioc->alt_ioc->active = 1;
1675 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1681 /* hard_reset_done = 0 if a soft reset was performed
1682 * and 1 if a hard reset was performed.
1684 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1685 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1688 printk(KERN_WARNING MYNAM
1689 ": alt-%s: Not ready WARNING!\n",
1690 ioc->alt_ioc->name);
1693 for (ii=0; ii<5; ii++) {
1694 /* Get IOC facts! Allow 5 retries */
1695 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1701 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1703 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1704 MptDisplayIocCapabilities(ioc);
1707 if (alt_ioc_ready) {
1708 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1709 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1710 /* Retry - alt IOC was initialized once
1712 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1715 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1717 reset_alt_ioc_active = 0;
1718 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1719 MptDisplayIocCapabilities(ioc->alt_ioc);
1723 /* Prime reply & request queues!
1724 * (mucho alloc's) Must be done prior to
1725 * init as upper addresses are needed for init.
1726 * If fails, continue with alt-ioc processing
1728 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1731 /* May need to check/upload firmware & data here!
1732 * If fails, continue with alt-ioc processing
1734 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1737 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1738 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1739 ioc->alt_ioc->name, rc);
1741 reset_alt_ioc_active = 0;
1744 if (alt_ioc_ready) {
1745 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1747 reset_alt_ioc_active = 0;
1748 printk(KERN_WARNING MYNAM
1749 ": alt-%s: (%d) init failure WARNING!\n",
1750 ioc->alt_ioc->name, rc);
1754 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1755 if (ioc->upload_fw) {
1756 ddlprintk((MYIOC_s_INFO_FMT
1757 "firmware upload required!\n", ioc->name));
1759 /* Controller is not operational, cannot do upload
1762 rc = mpt_do_upload(ioc, sleepFlag);
1764 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1766 * Maintain only one pointer to FW memory
1767 * so there will not be two attempt to
1768 * downloadboot onboard dual function
1769 * chips (mpt_adapter_disable,
1772 ioc->cached_fw = NULL;
1773 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1774 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1777 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1785 /* Enable! (reply interrupt) */
1786 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1790 if (reset_alt_ioc_active && ioc->alt_ioc) {
1791 /* (re)Enable alt-IOC! (reply interrupt) */
1792 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1793 ioc->alt_ioc->name));
1794 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1795 ioc->alt_ioc->active = 1;
1798 /* Enable MPT base driver management of EventNotification
1799 * and EventAck handling.
1801 if ((ret == 0) && (!ioc->facts.EventState))
1802 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1804 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1805 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1807 /* Add additional "reason" check before call to GetLanConfigPages
1808 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1809 * recursive scenario; GetLanConfigPages times out, timer expired
1810 * routine calls HardResetHandler, which calls into here again,
1811 * and we try GetLanConfigPages again...
1813 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1814 if (ioc->bus_type == SAS) {
1816 /* clear persistency table */
1817 if(ioc->facts.IOCExceptions &
1818 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1819 ret = mptbase_sas_persist_operation(ioc,
1820 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1827 mpt_findImVolumes(ioc);
1829 } else if (ioc->bus_type == FC) {
1831 * Pre-fetch FC port WWN and stuff...
1832 * (FCPortPage0_t stuff)
1834 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1835 (void) mptbase_GetFcPortPage0(ioc, ii);
1838 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1839 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1841 * Pre-fetch the ports LAN MAC address!
1842 * (LANPage1_t stuff)
1844 (void) GetLanConfigPages(ioc);
1847 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1848 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1849 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1854 /* Get NVRAM and adapter maximums from SPP 0 and 2
1856 mpt_GetScsiPortSettings(ioc, 0);
1858 /* Get version and length of SDP 1
1860 mpt_readScsiDevicePageHeaders(ioc, 0);
1864 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1865 mpt_findImVolumes(ioc);
1867 /* Check, and possibly reset, the coalescing value
1869 mpt_read_ioc_pg_1(ioc);
1871 mpt_read_ioc_pg_4(ioc);
1874 GetIoUnitPage2(ioc);
1878 * Call each currently registered protocol IOC reset handler
1879 * with post-reset indication.
1880 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1881 * MptResetHandlers[] registered yet.
1883 if (hard_reset_done) {
1885 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1886 if ((ret == 0) && MptResetHandlers[ii]) {
1887 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1889 rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1893 if (alt_ioc_ready && MptResetHandlers[ii]) {
1894 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1895 ioc->name, ioc->alt_ioc->name, ii));
1896 rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1900 /* FIXME? Examine results here? */
1906 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1908 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1909 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1910 * 929X, 1030 or 1035.
1911 * @ioc: Pointer to MPT adapter structure
1912 * @pdev: Pointer to (struct pci_dev) structure
1914 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1915 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1918 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1920 struct pci_dev *peer=NULL;
1921 unsigned int slot = PCI_SLOT(pdev->devfn);
1922 unsigned int func = PCI_FUNC(pdev->devfn);
1923 MPT_ADAPTER *ioc_srch;
1925 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1926 " searching for devfn match on %x or %x\n",
1927 ioc->name, pci_name(pdev), pdev->bus->number,
1928 pdev->devfn, func-1, func+1));
1930 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1932 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1937 list_for_each_entry(ioc_srch, &ioc_list, list) {
1938 struct pci_dev *_pcidev = ioc_srch->pcidev;
1939 if (_pcidev == peer) {
1940 /* Paranoia checks */
1941 if (ioc->alt_ioc != NULL) {
1942 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1943 ioc->name, ioc->alt_ioc->name);
1945 } else if (ioc_srch->alt_ioc != NULL) {
1946 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1947 ioc_srch->name, ioc_srch->alt_ioc->name);
1950 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1951 ioc->name, ioc_srch->name));
1952 ioc_srch->alt_ioc = ioc;
1953 ioc->alt_ioc = ioc_srch;
1959 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1961 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1962 * @this: Pointer to MPT adapter structure
1965 mpt_adapter_disable(MPT_ADAPTER *ioc)
1970 if (ioc->cached_fw != NULL) {
1971 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1972 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1973 printk(KERN_WARNING MYNAM
1974 ": firmware downloadboot failure (%d)!\n", ret);
1978 /* Disable adapter interrupts! */
1979 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1981 /* Clear any lingering interrupt */
1982 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1984 if (ioc->alloc != NULL) {
1986 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1987 ioc->name, ioc->alloc, ioc->alloc_sz));
1988 pci_free_consistent(ioc->pcidev, sz,
1989 ioc->alloc, ioc->alloc_dma);
1990 ioc->reply_frames = NULL;
1991 ioc->req_frames = NULL;
1993 ioc->alloc_total -= sz;
1996 if (ioc->sense_buf_pool != NULL) {
1997 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1998 pci_free_consistent(ioc->pcidev, sz,
1999 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2000 ioc->sense_buf_pool = NULL;
2001 ioc->alloc_total -= sz;
2004 if (ioc->events != NULL){
2005 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2008 ioc->alloc_total -= sz;
2011 if (ioc->cached_fw != NULL) {
2012 sz = ioc->facts.FWImageSize;
2013 pci_free_consistent(ioc->pcidev, sz,
2014 ioc->cached_fw, ioc->cached_fw_dma);
2015 ioc->cached_fw = NULL;
2016 ioc->alloc_total -= sz;
2019 kfree(ioc->spi_data.nvram);
2020 kfree(ioc->raid_data.pIocPg3);
2021 ioc->spi_data.nvram = NULL;
2022 ioc->raid_data.pIocPg3 = NULL;
2024 if (ioc->spi_data.pIocPg4 != NULL) {
2025 sz = ioc->spi_data.IocPg4Sz;
2026 pci_free_consistent(ioc->pcidev, sz,
2027 ioc->spi_data.pIocPg4,
2028 ioc->spi_data.IocPg4_dma);
2029 ioc->spi_data.pIocPg4 = NULL;
2030 ioc->alloc_total -= sz;
2033 if (ioc->ReqToChain != NULL) {
2034 kfree(ioc->ReqToChain);
2035 kfree(ioc->RequestNB);
2036 ioc->ReqToChain = NULL;
2039 kfree(ioc->ChainToChain);
2040 ioc->ChainToChain = NULL;
2042 if (ioc->HostPageBuffer != NULL) {
2043 if((ret = mpt_host_page_access_control(ioc,
2044 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2045 printk(KERN_ERR MYNAM
2046 ": %s: host page buffers free failed (%d)!\n",
2049 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2050 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2051 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2052 ioc->HostPageBuffer,
2053 ioc->HostPageBuffer_dma);
2054 ioc->HostPageBuffer = NULL;
2055 ioc->HostPageBuffer_sz = 0;
2056 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2062 * mpt_adapter_dispose - Free all resources associated with a MPT
2064 * @ioc: Pointer to MPT adapter structure
2066 * This routine unregisters h/w resources and frees all alloc'd memory
2067 * associated with a MPT adapter structure.
2070 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2072 int sz_first, sz_last;
2077 sz_first = ioc->alloc_total;
2079 mpt_adapter_disable(ioc);
2081 if (ioc->pci_irq != -1) {
2082 free_irq(ioc->pci_irq, ioc);
2084 pci_disable_msi(ioc->pcidev);
2088 if (ioc->memmap != NULL) {
2089 iounmap(ioc->memmap);
2093 #if defined(CONFIG_MTRR) && 0
2094 if (ioc->mtrr_reg > 0) {
2095 mtrr_del(ioc->mtrr_reg, 0, 0);
2096 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2100 /* Zap the adapter lookup ptr! */
2101 list_del(&ioc->list);
2103 sz_last = ioc->alloc_total;
2104 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2105 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2108 ioc->alt_ioc->alt_ioc = NULL;
2113 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2115 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2116 * @ioc: Pointer to MPT adapter structure
2119 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2123 printk(KERN_INFO "%s: ", ioc->name);
2124 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2125 printk("%s: ", ioc->prod_name+3);
2126 printk("Capabilities={");
2128 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2129 printk("Initiator");
2133 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2134 printk("%sTarget", i ? "," : "");
2138 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2139 printk("%sLAN", i ? "," : "");
2145 * This would probably evoke more questions than it's worth
2147 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2148 printk("%sLogBusAddr", i ? "," : "");
2156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2158 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2159 * @ioc: Pointer to MPT_ADAPTER structure
2160 * @force: Force hard KickStart of IOC
2161 * @sleepFlag: Specifies whether the process can sleep
2164 * 1 - DIAG reset and READY
2165 * 0 - READY initially OR soft reset and READY
2166 * -1 - Any failure on KickStart
2167 * -2 - Msg Unit Reset Failed
2168 * -3 - IO Unit Reset Failed
2169 * -4 - IOC owned by a PEER
2172 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2177 int hard_reset_done = 0;
2182 /* Get current [raw] IOC state */
2183 ioc_state = mpt_GetIocState(ioc, 0);
2184 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2187 * Check to see if IOC got left/stuck in doorbell handshake
2188 * grip of death. If so, hard reset the IOC.
2190 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2192 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2196 /* Is it already READY? */
2197 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2201 * Check to see if IOC is in FAULT state.
2203 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2205 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2207 printk(KERN_WARNING " FAULT code = %04xh\n",
2208 ioc_state & MPI_DOORBELL_DATA_MASK);
2212 * Hmmm... Did it get left operational?
2214 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2215 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2219 * If PCI Peer, exit.
2220 * Else, if no fault conditions are present, issue a MessageUnitReset
2221 * Else, fall through to KickStart case
2223 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2224 dinitprintk((KERN_INFO MYNAM
2225 ": whoinit 0x%x statefault %d force %d\n",
2226 whoinit, statefault, force));
2227 if (whoinit == MPI_WHOINIT_PCI_PEER)
2230 if ((statefault == 0 ) && (force == 0)) {
2231 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2238 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2239 if (hard_reset_done < 0)
2243 * Loop here waiting for IOC to come READY.
2246 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2248 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2249 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2251 * BIOS or previous driver load left IOC in OP state.
2252 * Reset messaging FIFOs.
2254 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2255 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2258 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2260 * Something is wrong. Try to get IOC back
2263 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2264 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2271 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2272 ioc->name, (int)((ii+5)/HZ));
2276 if (sleepFlag == CAN_SLEEP) {
2277 msleep_interruptible(1);
2279 mdelay (1); /* 1 msec delay */
2284 if (statefault < 3) {
2285 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2287 statefault==1 ? "stuck handshake" : "IOC FAULT");
2290 return hard_reset_done;
2293 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2295 * mpt_GetIocState - Get the current state of a MPT adapter.
2296 * @ioc: Pointer to MPT_ADAPTER structure
2297 * @cooked: Request raw or cooked IOC state
2299 * Returns all IOC Doorbell register bits if cooked==0, else just the
2300 * Doorbell bits in MPI_IOC_STATE_MASK.
2303 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2308 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2309 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2310 sc = s & MPI_IOC_STATE_MASK;
2313 ioc->last_state = sc;
2315 return cooked ? sc : s;
2318 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2320 * GetIocFacts - Send IOCFacts request to MPT adapter.
2321 * @ioc: Pointer to MPT_ADAPTER structure
2322 * @sleepFlag: Specifies whether the process can sleep
2323 * @reason: If recovery, only update facts.
2325 * Returns 0 for success, non-zero for failure.
2328 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2330 IOCFacts_t get_facts;
2331 IOCFactsReply_t *facts;
2339 /* IOC *must* NOT be in RESET state! */
2340 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2341 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2347 facts = &ioc->facts;
2349 /* Destination (reply area)... */
2350 reply_sz = sizeof(*facts);
2351 memset(facts, 0, reply_sz);
2353 /* Request area (get_facts on the stack right now!) */
2354 req_sz = sizeof(get_facts);
2355 memset(&get_facts, 0, req_sz);
2357 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2358 /* Assert: All other get_facts fields are zero! */
2360 dinitprintk((MYIOC_s_INFO_FMT
2361 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2362 ioc->name, req_sz, reply_sz));
2364 /* No non-zero fields in the get_facts request are greater than
2365 * 1 byte in size, so we can just fire it off as is.
2367 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2368 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2373 * Now byte swap (GRRR) the necessary fields before any further
2374 * inspection of reply contents.
2376 * But need to do some sanity checks on MsgLength (byte) field
2377 * to make sure we don't zero IOC's req_sz!
2379 /* Did we get a valid reply? */
2380 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2381 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2383 * If not been here, done that, save off first WhoInit value
2385 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2386 ioc->FirstWhoInit = facts->WhoInit;
2389 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2390 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2391 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2392 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2393 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2394 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2395 /* CHECKME! IOCStatus, IOCLogInfo */
2397 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2398 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2401 * FC f/w version changed between 1.1 and 1.2
2402 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2403 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2405 if (facts->MsgVersion < 0x0102) {
2407 * Handle old FC f/w style, convert to new...
2409 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2410 facts->FWVersion.Word =
2411 ((oldv<<12) & 0xFF000000) |
2412 ((oldv<<8) & 0x000FFF00);
2414 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2416 facts->ProductID = le16_to_cpu(facts->ProductID);
2417 facts->CurrentHostMfaHighAddr =
2418 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2419 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2420 facts->CurrentSenseBufferHighAddr =
2421 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2422 facts->CurReplyFrameSize =
2423 le16_to_cpu(facts->CurReplyFrameSize);
2424 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2427 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2428 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2429 * to 14 in MPI-1.01.0x.
2431 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2432 facts->MsgVersion > 0x0100) {
2433 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2436 sz = facts->FWImageSize;
2441 facts->FWImageSize = sz;
2443 if (!facts->RequestFrameSize) {
2444 /* Something is wrong! */
2445 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2450 r = sz = facts->BlockSize;
2451 vv = ((63 / (sz * 4)) + 1) & 0x03;
2452 ioc->NB_for_64_byte_frame = vv;
2458 ioc->NBShiftFactor = shiftFactor;
2459 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2460 ioc->name, vv, shiftFactor, r));
2462 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2464 * Set values for this IOC's request & reply frame sizes,
2465 * and request & reply queue depths...
2467 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2468 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2469 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2470 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2472 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2473 ioc->name, ioc->reply_sz, ioc->reply_depth));
2474 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2475 ioc->name, ioc->req_sz, ioc->req_depth));
2477 /* Get port facts! */
2478 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2482 printk(MYIOC_s_ERR_FMT
2483 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2484 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2485 RequestFrameSize)/sizeof(u32)));
2492 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2494 * GetPortFacts - Send PortFacts request to MPT adapter.
2495 * @ioc: Pointer to MPT_ADAPTER structure
2496 * @portnum: Port number
2497 * @sleepFlag: Specifies whether the process can sleep
2499 * Returns 0 for success, non-zero for failure.
2502 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2504 PortFacts_t get_pfacts;
2505 PortFactsReply_t *pfacts;
2510 /* IOC *must* NOT be in RESET state! */
2511 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2512 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2518 pfacts = &ioc->pfacts[portnum];
2520 /* Destination (reply area)... */
2521 reply_sz = sizeof(*pfacts);
2522 memset(pfacts, 0, reply_sz);
2524 /* Request area (get_pfacts on the stack right now!) */
2525 req_sz = sizeof(get_pfacts);
2526 memset(&get_pfacts, 0, req_sz);
2528 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2529 get_pfacts.PortNumber = portnum;
2530 /* Assert: All other get_pfacts fields are zero! */
2532 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2533 ioc->name, portnum));
2535 /* No non-zero fields in the get_pfacts request are greater than
2536 * 1 byte in size, so we can just fire it off as is.
2538 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2539 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2543 /* Did we get a valid reply? */
2545 /* Now byte swap the necessary fields in the response. */
2546 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2547 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2548 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2549 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2550 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2551 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2552 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2553 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2554 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2559 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2561 * SendIocInit - Send IOCInit request to MPT adapter.
2562 * @ioc: Pointer to MPT_ADAPTER structure
2563 * @sleepFlag: Specifies whether the process can sleep
2565 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2567 * Returns 0 for success, non-zero for failure.
2570 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2573 MPIDefaultReply_t init_reply;
2579 memset(&ioc_init, 0, sizeof(ioc_init));
2580 memset(&init_reply, 0, sizeof(init_reply));
2582 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2583 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2585 /* If we are in a recovery mode and we uploaded the FW image,
2586 * then this pointer is not NULL. Skip the upload a second time.
2587 * Set this flag if cached_fw set for either IOC.
2589 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2593 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2594 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2596 if(ioc->bus_type == SAS)
2597 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2598 else if(ioc->bus_type == FC)
2599 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2601 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2602 ioc_init.MaxBuses = MPT_MAX_BUS;
2603 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2604 ioc->name, ioc->facts.MsgVersion));
2605 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2606 // set MsgVersion and HeaderVersion host driver was built with
2607 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2608 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2610 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2611 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2612 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2615 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2617 if (sizeof(dma_addr_t) == sizeof(u64)) {
2618 /* Save the upper 32-bits of the request
2619 * (reply) and sense buffers.
2621 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2622 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2624 /* Force 32-bit addressing */
2625 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2626 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2629 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2630 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2631 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2632 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2634 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2635 ioc->name, &ioc_init));
2637 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2638 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2640 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2644 /* No need to byte swap the multibyte fields in the reply
2645 * since we don't even look at it's contents.
2648 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2649 ioc->name, &ioc_init));
2651 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2652 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2656 /* YIKES! SUPER IMPORTANT!!!
2657 * Poll IocState until _OPERATIONAL while IOC is doing
2658 * LoopInit and TargetDiscovery!
2661 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2662 state = mpt_GetIocState(ioc, 1);
2663 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2664 if (sleepFlag == CAN_SLEEP) {
2665 msleep_interruptible(1);
2671 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2672 ioc->name, (int)((count+5)/HZ));
2676 state = mpt_GetIocState(ioc, 1);
2679 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2685 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2687 * SendPortEnable - Send PortEnable request to MPT adapter port.
2688 * @ioc: Pointer to MPT_ADAPTER structure
2689 * @portnum: Port number to enable
2690 * @sleepFlag: Specifies whether the process can sleep
2692 * Send PortEnable to bring IOC to OPERATIONAL state.
2694 * Returns 0 for success, non-zero for failure.
2697 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2699 PortEnable_t port_enable;
2700 MPIDefaultReply_t reply_buf;
2705 /* Destination... */
2706 reply_sz = sizeof(MPIDefaultReply_t);
2707 memset(&reply_buf, 0, reply_sz);
2709 req_sz = sizeof(PortEnable_t);
2710 memset(&port_enable, 0, req_sz);
2712 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2713 port_enable.PortNumber = portnum;
2714 /* port_enable.ChainOffset = 0; */
2715 /* port_enable.MsgFlags = 0; */
2716 /* port_enable.MsgContext = 0; */
2718 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2719 ioc->name, portnum, &port_enable));
2721 /* RAID FW may take a long time to enable
2723 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2724 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2725 (ioc->bus_type == SAS)) {
2726 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2727 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2728 300 /*seconds*/, sleepFlag);
2730 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2731 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2732 30 /*seconds*/, sleepFlag);
2738 * ioc: Pointer to MPT_ADAPTER structure
2739 * size - total FW bytes
2742 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2745 return; /* use already allocated memory */
2746 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2747 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2748 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2750 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2751 ioc->alloc_total += size;
2755 * If alt_img is NULL, delete from ioc structure.
2756 * Else, delete a secondary image in same format.
2759 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2763 sz = ioc->facts.FWImageSize;
2764 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2765 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2766 pci_free_consistent(ioc->pcidev, sz,
2767 ioc->cached_fw, ioc->cached_fw_dma);
2768 ioc->cached_fw = NULL;
2774 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2776 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2777 * @ioc: Pointer to MPT_ADAPTER structure
2778 * @sleepFlag: Specifies whether the process can sleep
2780 * Returns 0 for success, >0 for handshake failure
2781 * <0 for fw upload failure.
2783 * Remark: If bound IOC and a successful FWUpload was performed
2784 * on the bound IOC, the second image is discarded
2785 * and memory is free'd. Both channels must upload to prevent
2786 * IOC from running in degraded mode.
2789 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2791 u8 request[ioc->req_sz];
2792 u8 reply[sizeof(FWUploadReply_t)];
2793 FWUpload_t *prequest;
2794 FWUploadReply_t *preply;
2795 FWUploadTCSGE_t *ptcsge;
2798 int ii, sz, reply_sz;
2801 /* If the image size is 0, we are done.
2803 if ((sz = ioc->facts.FWImageSize) == 0)
2806 mpt_alloc_fw_memory(ioc, sz);
2808 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2809 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2811 if (ioc->cached_fw == NULL) {
2817 prequest = (FWUpload_t *)&request;
2818 preply = (FWUploadReply_t *)&reply;
2820 /* Destination... */
2821 memset(prequest, 0, ioc->req_sz);
2823 reply_sz = sizeof(reply);
2824 memset(preply, 0, reply_sz);
2826 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2827 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2829 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2830 ptcsge->DetailsLength = 12;
2831 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2832 ptcsge->ImageSize = cpu_to_le32(sz);
2834 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2836 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2837 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2839 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2840 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2841 prequest, sgeoffset));
2842 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2844 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2845 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2847 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2849 cmdStatus = -EFAULT;
2851 /* Handshake transfer was complete and successful.
2852 * Check the Reply Frame.
2854 int status, transfer_sz;
2855 status = le16_to_cpu(preply->IOCStatus);
2856 if (status == MPI_IOCSTATUS_SUCCESS) {
2857 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2858 if (transfer_sz == sz)
2862 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2863 ioc->name, cmdStatus));
2868 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2870 mpt_free_fw_memory(ioc);
2876 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2878 * mpt_downloadboot - DownloadBoot code
2879 * @ioc: Pointer to MPT_ADAPTER structure
2880 * @flag: Specify which part of IOC memory is to be uploaded.
2881 * @sleepFlag: Specifies whether the process can sleep
2883 * FwDownloadBoot requires Programmed IO access.
2885 * Returns 0 for success
2886 * -1 FW Image size is 0
2887 * -2 No valid cached_fw Pointer
2888 * <0 for fw upload failure.
2891 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2893 MpiExtImageHeader_t *pExtImage;
2903 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2904 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2906 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2907 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2908 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2909 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2910 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2911 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2913 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2916 if (sleepFlag == CAN_SLEEP) {
2917 msleep_interruptible(1);
2922 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2923 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2925 for (count = 0; count < 30; count ++) {
2926 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2927 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2928 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2933 if (sleepFlag == CAN_SLEEP) {
2934 msleep_interruptible (100);
2940 if ( count == 30 ) {
2941 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2942 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2943 ioc->name, diag0val));
2947 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2948 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2949 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2950 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2951 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2952 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2954 /* Set the DiagRwEn and Disable ARM bits */
2955 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2957 fwSize = (pFwHeader->ImageSize + 3)/4;
2958 ptrFw = (u32 *) pFwHeader;
2960 /* Write the LoadStartAddress to the DiagRw Address Register
2961 * using Programmed IO
2963 if (ioc->errata_flag_1064)
2964 pci_enable_io_access(ioc->pcidev);
2966 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2967 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2968 ioc->name, pFwHeader->LoadStartAddress));
2970 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2971 ioc->name, fwSize*4, ptrFw));
2973 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2976 nextImage = pFwHeader->NextImageHeaderOffset;
2978 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2980 load_addr = pExtImage->LoadStartAddress;
2982 fwSize = (pExtImage->ImageSize + 3) >> 2;
2983 ptrFw = (u32 *)pExtImage;
2985 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
2986 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
2987 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2990 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2992 nextImage = pExtImage->NextImageHeaderOffset;
2995 /* Write the IopResetVectorRegAddr */
2996 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2997 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2999 /* Write the IopResetVectorValue */
3000 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3001 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3003 /* Clear the internal flash bad bit - autoincrementing register,
3004 * so must do two writes.
3006 if (ioc->bus_type == SPI) {
3008 * 1030 and 1035 H/W errata, workaround to access
3009 * the ClearFlashBadSignatureBit
3011 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3012 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3013 diagRwData |= 0x40000000;
3014 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3015 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3017 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3018 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3019 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3020 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3023 if (sleepFlag == CAN_SLEEP) {
3024 msleep_interruptible (1);
3030 if (ioc->errata_flag_1064)
3031 pci_disable_io_access(ioc->pcidev);
3033 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3034 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3035 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3036 ioc->name, diag0val));
3037 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3038 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3039 ioc->name, diag0val));
3040 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3042 /* Write 0xFF to reset the sequencer */
3043 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3045 if (ioc->bus_type == SAS) {
3046 ioc_state = mpt_GetIocState(ioc, 0);
3047 if ( (GetIocFacts(ioc, sleepFlag,
3048 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3049 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3050 ioc->name, ioc_state));
3055 for (count=0; count<HZ*20; count++) {
3056 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3057 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3058 ioc->name, count, ioc_state));
3059 if (ioc->bus_type == SAS) {
3062 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3063 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3067 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3071 if (sleepFlag == CAN_SLEEP) {
3072 msleep_interruptible (10);
3077 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3078 ioc->name, ioc_state));
3082 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3084 * KickStart - Perform hard reset of MPT adapter.
3085 * @ioc: Pointer to MPT_ADAPTER structure
3086 * @force: Force hard reset
3087 * @sleepFlag: Specifies whether the process can sleep
3089 * This routine places MPT adapter in diagnostic mode via the
3090 * WriteSequence register, and then performs a hard reset of adapter
3091 * via the Diagnostic register.
3093 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3094 * or NO_SLEEP (interrupt thread, use mdelay)
3095 * force - 1 if doorbell active, board fault state
3096 * board operational, IOC_RECOVERY or
3097 * IOC_BRINGUP and there is an alt_ioc.
3101 * 1 - hard reset, READY
3102 * 0 - no reset due to History bit, READY
3103 * -1 - no reset due to History bit but not READY
3104 * OR reset but failed to come READY
3105 * -2 - no reset, could not enter DIAG mode
3106 * -3 - reset but bad FW bit
3109 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3111 int hard_reset_done = 0;
3115 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3116 if (ioc->bus_type == SPI) {
3117 /* Always issue a Msg Unit Reset first. This will clear some
3118 * SCSI bus hang conditions.
3120 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3122 if (sleepFlag == CAN_SLEEP) {
3123 msleep_interruptible (1000);
3129 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3130 if (hard_reset_done < 0)
3131 return hard_reset_done;
3133 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3136 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3137 for (cnt=0; cnt<cntdn; cnt++) {
3138 ioc_state = mpt_GetIocState(ioc, 1);
3139 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3140 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3142 return hard_reset_done;
3144 if (sleepFlag == CAN_SLEEP) {
3145 msleep_interruptible (10);
3151 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3152 ioc->name, ioc_state);
3156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3158 * mpt_diag_reset - Perform hard reset of the adapter.
3159 * @ioc: Pointer to MPT_ADAPTER structure
3160 * @ignore: Set if to honor and clear to ignore
3161 * the reset history bit
3162 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3163 * else set to NO_SLEEP (use mdelay instead)
3165 * This routine places the adapter in diagnostic mode via the
3166 * WriteSequence register and then performs a hard reset of adapter
3167 * via the Diagnostic register. Adapter should be in ready state
3168 * upon successful completion.
3170 * Returns: 1 hard reset successful
3171 * 0 no reset performed because reset history bit set
3172 * -2 enabling diagnostic mode failed
3173 * -3 diagnostic reset failed
3176 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3180 int hard_reset_done = 0;
3186 /* Clear any existing interrupts */
3187 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3189 /* Use "Diagnostic reset" method! (only thing available!) */
3190 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3194 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3195 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3196 ioc->name, diag0val, diag1val));
3199 /* Do the reset if we are told to ignore the reset history
3200 * or if the reset history is 0
3202 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3203 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3204 /* Write magic sequence to WriteSequence register
3205 * Loop until in diagnostic mode
3207 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3208 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3209 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3210 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3211 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3212 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3215 if (sleepFlag == CAN_SLEEP) {
3216 msleep_interruptible (100);
3223 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3224 ioc->name, diag0val);
3229 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3231 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3232 ioc->name, diag0val));
3237 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3238 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3239 ioc->name, diag0val, diag1val));
3242 * Disable the ARM (Bug fix)
3245 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3249 * Now hit the reset bit in the Diagnostic register
3250 * (THE BIG HAMMER!) (Clears DRWE bit).
3252 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3253 hard_reset_done = 1;
3254 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3258 * Call each currently registered protocol IOC reset handler
3259 * with pre-reset indication.
3260 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3261 * MptResetHandlers[] registered yet.
3267 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3268 if (MptResetHandlers[ii]) {
3269 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3271 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3273 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3274 ioc->name, ioc->alt_ioc->name, ii));
3275 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3279 /* FIXME? Examine results here? */
3282 if (ioc->cached_fw) {
3283 /* If the DownloadBoot operation fails, the
3284 * IOC will be left unusable. This is a fatal error
3285 * case. _diag_reset will return < 0
3287 for (count = 0; count < 30; count ++) {
3288 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3289 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3294 if (sleepFlag == CAN_SLEEP) {
3295 msleep_interruptible (1000);
3300 if ((count = mpt_downloadboot(ioc,
3301 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3302 printk(KERN_WARNING MYNAM
3303 ": firmware downloadboot failure (%d)!\n", count);
3307 /* Wait for FW to reload and for board
3308 * to go to the READY state.
3309 * Maximum wait is 60 seconds.
3310 * If fail, no error will check again
3311 * with calling program.
3313 for (count = 0; count < 60; count ++) {
3314 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3315 doorbell &= MPI_IOC_STATE_MASK;
3317 if (doorbell == MPI_IOC_STATE_READY) {
3322 if (sleepFlag == CAN_SLEEP) {
3323 msleep_interruptible (1000);
3331 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3334 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3335 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3336 ioc->name, diag0val, diag1val));
3339 /* Clear RESET_HISTORY bit! Place board in the
3340 * diagnostic mode to update the diag register.
3342 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3344 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3345 /* Write magic sequence to WriteSequence register
3346 * Loop until in diagnostic mode
3348 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3349 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3350 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3351 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3352 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3353 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3356 if (sleepFlag == CAN_SLEEP) {
3357 msleep_interruptible (100);
3364 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3365 ioc->name, diag0val);
3368 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3370 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3371 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3372 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3373 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3374 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3378 /* Disable Diagnostic Mode
3380 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3382 /* Check FW reload status flags.
3384 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3385 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3386 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3387 ioc->name, diag0val);
3393 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3394 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3395 ioc->name, diag0val, diag1val));
3399 * Reset flag that says we've enabled event notification
3401 ioc->facts.EventState = 0;
3404 ioc->alt_ioc->facts.EventState = 0;
3406 return hard_reset_done;
3409 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3411 * SendIocReset - Send IOCReset request to MPT adapter.
3412 * @ioc: Pointer to MPT_ADAPTER structure
3413 * @reset_type: reset type, expected values are
3414 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3416 * Send IOCReset request to the MPT adapter.
3418 * Returns 0 for success, non-zero for failure.
3421 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3427 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3428 ioc->name, reset_type));
3429 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3430 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3433 /* FW ACK'd request, wait for READY state
3436 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3438 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3442 if (sleepFlag != CAN_SLEEP)
3445 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3446 ioc->name, (int)((count+5)/HZ));
3450 if (sleepFlag == CAN_SLEEP) {
3451 msleep_interruptible(1);
3453 mdelay (1); /* 1 msec delay */
3458 * Cleanup all event stuff for this IOC; re-issue EventNotification
3459 * request if needed.
3461 if (ioc->facts.Function)
3462 ioc->facts.EventState = 0;
3467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3469 * initChainBuffers - Allocate memory for and initialize
3470 * chain buffers, chain buffer control arrays and spinlock.
3471 * @hd: Pointer to MPT_SCSI_HOST structure
3472 * @init: If set, initialize the spin lock.
3475 initChainBuffers(MPT_ADAPTER *ioc)
3478 int sz, ii, num_chain;
3479 int scale, num_sge, numSGE;
3481 /* ReqToChain size must equal the req_depth
3484 if (ioc->ReqToChain == NULL) {
3485 sz = ioc->req_depth * sizeof(int);
3486 mem = kmalloc(sz, GFP_ATOMIC);
3490 ioc->ReqToChain = (int *) mem;
3491 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3492 ioc->name, mem, sz));
3493 mem = kmalloc(sz, GFP_ATOMIC);
3497 ioc->RequestNB = (int *) mem;
3498 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3499 ioc->name, mem, sz));
3501 for (ii = 0; ii < ioc->req_depth; ii++) {
3502 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3505 /* ChainToChain size must equal the total number
3506 * of chain buffers to be allocated.
3509 * Calculate the number of chain buffers needed(plus 1) per I/O
3510 * then multiply the the maximum number of simultaneous cmds
3512 * num_sge = num sge in request frame + last chain buffer
3513 * scale = num sge per chain buffer if no chain element
3515 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3516 if (sizeof(dma_addr_t) == sizeof(u64))
3517 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3519 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3521 if (sizeof(dma_addr_t) == sizeof(u64)) {
3522 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3523 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3525 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3526 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3528 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3529 ioc->name, num_sge, numSGE));
3531 if ( numSGE > MPT_SCSI_SG_DEPTH )
3532 numSGE = MPT_SCSI_SG_DEPTH;
3535 while (numSGE - num_sge > 0) {
3537 num_sge += (scale - 1);
3541 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3542 ioc->name, numSGE, num_sge, num_chain));
3544 if (ioc->bus_type == SPI)
3545 num_chain *= MPT_SCSI_CAN_QUEUE;
3547 num_chain *= MPT_FC_CAN_QUEUE;
3549 ioc->num_chain = num_chain;
3551 sz = num_chain * sizeof(int);
3552 if (ioc->ChainToChain == NULL) {
3553 mem = kmalloc(sz, GFP_ATOMIC);
3557 ioc->ChainToChain = (int *) mem;
3558 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3559 ioc->name, mem, sz));
3561 mem = (u8 *) ioc->ChainToChain;
3563 memset(mem, 0xFF, sz);
3567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3569 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3570 * @ioc: Pointer to MPT_ADAPTER structure
3572 * This routine allocates memory for the MPT reply and request frame
3573 * pools (if necessary), and primes the IOC reply FIFO with
3576 * Returns 0 for success, non-zero for failure.
3579 PrimeIocFifos(MPT_ADAPTER *ioc)
3582 unsigned long flags;
3583 dma_addr_t alloc_dma;
3585 int i, reply_sz, sz, total_size, num_chain;
3587 /* Prime reply FIFO... */
3589 if (ioc->reply_frames == NULL) {
3590 if ( (num_chain = initChainBuffers(ioc)) < 0)
3593 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3594 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3595 ioc->name, ioc->reply_sz, ioc->reply_depth));
3596 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3597 ioc->name, reply_sz, reply_sz));
3599 sz = (ioc->req_sz * ioc->req_depth);
3600 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3601 ioc->name, ioc->req_sz, ioc->req_depth));
3602 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3603 ioc->name, sz, sz));
3606 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3607 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3608 ioc->name, ioc->req_sz, num_chain));
3609 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3610 ioc->name, sz, sz, num_chain));
3613 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3615 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3620 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3621 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3623 memset(mem, 0, total_size);
3624 ioc->alloc_total += total_size;
3626 ioc->alloc_dma = alloc_dma;
3627 ioc->alloc_sz = total_size;
3628 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3629 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3631 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3632 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3634 alloc_dma += reply_sz;
3637 /* Request FIFO - WE manage this! */
3639 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3640 ioc->req_frames_dma = alloc_dma;
3642 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3643 ioc->name, mem, (void *)(ulong)alloc_dma));
3645 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3647 #if defined(CONFIG_MTRR) && 0
3649 * Enable Write Combining MTRR for IOC's memory region.
3650 * (at least as much as we can; "size and base must be
3651 * multiples of 4 kiB"
3653 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3655 MTRR_TYPE_WRCOMB, 1);
3656 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3657 ioc->name, ioc->req_frames_dma, sz));
3660 for (i = 0; i < ioc->req_depth; i++) {
3661 alloc_dma += ioc->req_sz;
3665 ioc->ChainBuffer = mem;
3666 ioc->ChainBufferDMA = alloc_dma;
3668 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3669 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3671 /* Initialize the free chain Q.
3674 INIT_LIST_HEAD(&ioc->FreeChainQ);
3676 /* Post the chain buffers to the FreeChainQ.
3678 mem = (u8 *)ioc->ChainBuffer;
3679 for (i=0; i < num_chain; i++) {
3680 mf = (MPT_FRAME_HDR *) mem;
3681 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3685 /* Initialize Request frames linked list
3687 alloc_dma = ioc->req_frames_dma;
3688 mem = (u8 *) ioc->req_frames;
3690 spin_lock_irqsave(&ioc->FreeQlock, flags);
3691 INIT_LIST_HEAD(&ioc->FreeQ);
3692 for (i = 0; i < ioc->req_depth; i++) {
3693 mf = (MPT_FRAME_HDR *) mem;
3695 /* Queue REQUESTs *internally*! */
3696 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3700 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3702 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3703 ioc->sense_buf_pool =
3704 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3705 if (ioc->sense_buf_pool == NULL) {
3706 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3711 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3712 ioc->alloc_total += sz;
3713 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3714 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3718 /* Post Reply frames to FIFO
3720 alloc_dma = ioc->alloc_dma;
3721 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3722 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3724 for (i = 0; i < ioc->reply_depth; i++) {
3725 /* Write each address to the IOC! */
3726 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3727 alloc_dma += ioc->reply_sz;
3733 if (ioc->alloc != NULL) {
3735 pci_free_consistent(ioc->pcidev,
3737 ioc->alloc, ioc->alloc_dma);
3738 ioc->reply_frames = NULL;
3739 ioc->req_frames = NULL;
3740 ioc->alloc_total -= sz;
3742 if (ioc->sense_buf_pool != NULL) {
3743 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3744 pci_free_consistent(ioc->pcidev,
3746 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3747 ioc->sense_buf_pool = NULL;
3752 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3754 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3755 * from IOC via doorbell handshake method.
3756 * @ioc: Pointer to MPT_ADAPTER structure
3757 * @reqBytes: Size of the request in bytes
3758 * @req: Pointer to MPT request frame
3759 * @replyBytes: Expected size of the reply in bytes
3760 * @u16reply: Pointer to area where reply should be written
3761 * @maxwait: Max wait time for a reply (in seconds)
3762 * @sleepFlag: Specifies whether the process can sleep
3764 * NOTES: It is the callers responsibility to byte-swap fields in the
3765 * request which are greater than 1 byte in size. It is also the
3766 * callers responsibility to byte-swap response fields which are
3767 * greater than 1 byte in size.
3769 * Returns 0 for success, non-zero for failure.
3772 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3773 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3775 MPIDefaultReply_t *mptReply;
3780 * Get ready to cache a handshake reply
3782 ioc->hs_reply_idx = 0;
3783 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3784 mptReply->MsgLength = 0;
3787 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3788 * then tell IOC that we want to handshake a request of N words.
3789 * (WRITE u32val to Doorbell reg).
3791 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3792 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3793 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3794 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3797 * Wait for IOC's doorbell handshake int
3799 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3802 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3803 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3805 /* Read doorbell and check for active bit */
3806 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3810 * Clear doorbell int (WRITE 0 to IntStatus reg),
3811 * then wait for IOC to ACKnowledge that it's ready for
3812 * our handshake request.
3814 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3815 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3820 u8 *req_as_bytes = (u8 *) req;
3823 * Stuff request words via doorbell handshake,
3824 * with ACK from IOC for each.
3826 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3827 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3828 (req_as_bytes[(ii*4) + 1] << 8) |
3829 (req_as_bytes[(ii*4) + 2] << 16) |
3830 (req_as_bytes[(ii*4) + 3] << 24));
3832 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3833 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3837 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3838 DBG_DUMP_REQUEST_FRAME_HDR(req)
3840 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3841 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3844 * Wait for completion of doorbell handshake reply from the IOC
3846 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3849 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3850 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3853 * Copy out the cached reply...
3855 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3856 u16reply[ii] = ioc->hs_reply[ii];
3864 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3866 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3867 * in it's IntStatus register.
3868 * @ioc: Pointer to MPT_ADAPTER structure
3869 * @howlong: How long to wait (in seconds)
3870 * @sleepFlag: Specifies whether the process can sleep
3872 * This routine waits (up to ~2 seconds max) for IOC doorbell
3873 * handshake ACKnowledge.
3875 * Returns a negative value on failure, else wait loop count.
3878 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3884 cntdn = 1000 * howlong;
3886 if (sleepFlag == CAN_SLEEP) {
3888 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3889 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3891 msleep_interruptible (1);
3896 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3897 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3905 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3910 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3911 ioc->name, count, intstat);
3915 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3917 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3918 * in it's IntStatus register.
3919 * @ioc: Pointer to MPT_ADAPTER structure
3920 * @howlong: How long to wait (in seconds)
3921 * @sleepFlag: Specifies whether the process can sleep
3923 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3925 * Returns a negative value on failure, else wait loop count.
3928 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3934 cntdn = 1000 * howlong;
3935 if (sleepFlag == CAN_SLEEP) {
3937 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3938 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3940 msleep_interruptible(1);
3945 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3946 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3954 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3955 ioc->name, count, howlong));
3959 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3960 ioc->name, count, intstat);
3964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3966 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3967 * @ioc: Pointer to MPT_ADAPTER structure
3968 * @howlong: How long to wait (in seconds)
3969 * @sleepFlag: Specifies whether the process can sleep
3971 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3972 * Reply is cached to IOC private area large enough to hold a maximum
3973 * of 128 bytes of reply data.
3975 * Returns a negative value on failure, else size of reply in WORDS.
3978 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3983 u16 *hs_reply = ioc->hs_reply;
3984 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3987 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
3990 * Get first two u16's so we can look at IOC's intended reply MsgLength
3993 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
3996 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3997 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3998 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4001 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4002 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4006 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4007 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4008 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4011 * If no error (and IOC said MsgLength is > 0), piece together
4012 * reply 16 bits at a time.
4014 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4015 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4017 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4018 /* don't overflow our IOC hs_reply[] buffer! */
4019 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4020 hs_reply[u16cnt] = hword;
4021 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4024 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4026 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4029 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4034 else if (u16cnt != (2 * mptReply->MsgLength)) {
4037 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4042 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4043 DBG_DUMP_REPLY_FRAME(mptReply)
4045 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4046 ioc->name, t, u16cnt/2));
4050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4052 * GetLanConfigPages - Fetch LANConfig pages.
4053 * @ioc: Pointer to MPT_ADAPTER structure
4055 * Return: 0 for success
4056 * -ENOMEM if no memory available
4057 * -EPERM if not allowed due to ISR context
4058 * -EAGAIN if no msg frames currently available
4059 * -EFAULT for non-successful reply or no reply (timeout)
4062 GetLanConfigPages(MPT_ADAPTER *ioc)
4064 ConfigPageHeader_t hdr;
4066 LANPage0_t *ppage0_alloc;
4067 dma_addr_t page0_dma;
4068 LANPage1_t *ppage1_alloc;
4069 dma_addr_t page1_dma;
4074 /* Get LAN Page 0 header */
4075 hdr.PageVersion = 0;
4078 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4079 cfg.cfghdr.hdr = &hdr;
4081 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4086 if ((rc = mpt_config(ioc, &cfg)) != 0)
4089 if (hdr.PageLength > 0) {
4090 data_sz = hdr.PageLength * 4;
4091 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4094 memset((u8 *)ppage0_alloc, 0, data_sz);
4095 cfg.physAddr = page0_dma;
4096 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4098 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4100 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4101 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4105 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4108 * Normalize endianness of structure data,
4109 * by byte-swapping all > 1 byte fields!
4118 /* Get LAN Page 1 header */
4119 hdr.PageVersion = 0;
4122 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4123 cfg.cfghdr.hdr = &hdr;
4125 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4129 if ((rc = mpt_config(ioc, &cfg)) != 0)
4132 if (hdr.PageLength == 0)
4135 data_sz = hdr.PageLength * 4;
4137 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4139 memset((u8 *)ppage1_alloc, 0, data_sz);
4140 cfg.physAddr = page1_dma;
4141 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4143 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4145 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4146 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4149 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4152 * Normalize endianness of structure data,
4153 * by byte-swapping all > 1 byte fields!
4161 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4163 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4164 * @ioc: Pointer to MPT_ADAPTER structure
4165 * @portnum: IOC Port number
4167 * Return: 0 for success
4168 * -ENOMEM if no memory available
4169 * -EPERM if not allowed due to ISR context
4170 * -EAGAIN if no msg frames currently available
4171 * -EFAULT for non-successful reply or no reply (timeout)
4174 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4176 ConfigPageHeader_t hdr;
4178 FCPortPage0_t *ppage0_alloc;
4179 FCPortPage0_t *pp0dest;
4180 dma_addr_t page0_dma;
4187 /* Get FCPort Page 0 header */
4188 hdr.PageVersion = 0;
4191 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4192 cfg.cfghdr.hdr = &hdr;
4194 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4196 cfg.pageAddr = portnum;
4199 if ((rc = mpt_config(ioc, &cfg)) != 0)
4202 if (hdr.PageLength == 0)
4205 data_sz = hdr.PageLength * 4;
4207 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4211 memset((u8 *)ppage0_alloc, 0, data_sz);
4212 cfg.physAddr = page0_dma;
4213 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4215 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4217 pp0dest = &ioc->fc_port_page0[portnum];
4218 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4219 memcpy(pp0dest, ppage0_alloc, copy_sz);
4222 * Normalize endianness of structure data,
4223 * by byte-swapping all > 1 byte fields!
4225 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4226 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4227 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4228 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4229 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4230 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4231 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4232 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4233 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4234 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4235 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4236 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4237 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4238 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4239 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4240 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4243 * if still doing discovery,
4244 * hang loose a while until finished
4246 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4248 msleep_interruptible(100);
4251 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4257 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4263 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4265 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4266 * @ioc: Pointer to MPT_ADAPTER structure
4267 * @sas_address: 64bit SAS Address for operation.
4268 * @target_id: specified target for operation
4269 * @bus: specified bus for operation
4270 * @persist_opcode: see below
4272 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4273 * devices not currently present.
4274 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4276 * NOTE: Don't use not this function during interrupt time.
4278 * Returns: 0 for success, non-zero error
4281 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4283 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4285 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4286 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4287 MPT_FRAME_HDR *mf = NULL;
4288 MPIHeader_t *mpi_hdr;
4291 /* insure garbage is not sent to fw */
4292 switch(persist_opcode) {
4294 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4295 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4303 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4305 /* Get a MF for this command.
4307 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4308 printk("%s: no msg frames!\n",__FUNCTION__);
4312 mpi_hdr = (MPIHeader_t *) mf;
4313 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4314 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4315 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4316 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4317 sasIoUnitCntrReq->Operation = persist_opcode;
4319 init_timer(&ioc->persist_timer);
4320 ioc->persist_timer.data = (unsigned long) ioc;
4321 ioc->persist_timer.function = mpt_timer_expired;
4322 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4323 ioc->persist_wait_done=0;
4324 add_timer(&ioc->persist_timer);
4325 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4326 wait_event(mpt_waitq, ioc->persist_wait_done);
4328 sasIoUnitCntrReply =
4329 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4330 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4331 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4333 sasIoUnitCntrReply->IOCStatus,
4334 sasIoUnitCntrReply->IOCLogInfo);
4338 printk("%s: success\n",__FUNCTION__);
4342 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4345 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4346 MpiEventDataRaid_t * pRaidEventData)
4355 volume = pRaidEventData->VolumeID;
4356 reason = pRaidEventData->ReasonCode;
4357 disk = pRaidEventData->PhysDiskNum;
4358 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4359 flags = (status >> 0) & 0xff;
4360 state = (status >> 8) & 0xff;
4362 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4366 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4367 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4368 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4369 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4372 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4377 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4378 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4382 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4384 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4388 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4389 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4393 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4394 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4396 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4398 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4400 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4403 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4405 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4406 ? ", quiesced" : "",
4407 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4408 ? ", resync in progress" : "" );
4411 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4412 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4416 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4417 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4421 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4422 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4426 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4427 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4431 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4432 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4434 state == MPI_PHYSDISK0_STATUS_ONLINE
4436 : state == MPI_PHYSDISK0_STATUS_MISSING
4438 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4440 : state == MPI_PHYSDISK0_STATUS_FAILED
4442 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4444 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4445 ? "offline requested"
4446 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4447 ? "failed requested"
4448 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4451 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4452 ? ", out of sync" : "",
4453 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4454 ? ", quiesced" : "" );
4457 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4458 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4462 case MPI_EVENT_RAID_RC_SMART_DATA:
4463 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4464 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4467 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4468 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4474 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4476 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4477 * @ioc: Pointer to MPT_ADAPTER structure
4479 * Returns: 0 for success
4480 * -ENOMEM if no memory available
4481 * -EPERM if not allowed due to ISR context
4482 * -EAGAIN if no msg frames currently available
4483 * -EFAULT for non-successful reply or no reply (timeout)
4486 GetIoUnitPage2(MPT_ADAPTER *ioc)
4488 ConfigPageHeader_t hdr;
4490 IOUnitPage2_t *ppage_alloc;
4491 dma_addr_t page_dma;
4495 /* Get the page header */
4496 hdr.PageVersion = 0;
4499 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4500 cfg.cfghdr.hdr = &hdr;
4502 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4507 if ((rc = mpt_config(ioc, &cfg)) != 0)
4510 if (hdr.PageLength == 0)
4513 /* Read the config page */
4514 data_sz = hdr.PageLength * 4;
4516 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4518 memset((u8 *)ppage_alloc, 0, data_sz);
4519 cfg.physAddr = page_dma;
4520 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4522 /* If Good, save data */
4523 if ((rc = mpt_config(ioc, &cfg)) == 0)
4524 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4526 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4533 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4534 * @ioc: Pointer to a Adapter Strucutre
4535 * @portnum: IOC port number
4537 * Return: -EFAULT if read of config page header fails
4539 * If read of SCSI Port Page 0 fails,
4540 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4541 * Adapter settings: async, narrow
4543 * If read of SCSI Port Page 2 fails,
4544 * Adapter settings valid
4545 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4550 * CHECK - what type of locking mechanisms should be used????
4553 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4558 ConfigPageHeader_t header;
4564 if (!ioc->spi_data.nvram) {
4567 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4568 mem = kmalloc(sz, GFP_ATOMIC);
4572 ioc->spi_data.nvram = (int *) mem;
4574 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4575 ioc->name, ioc->spi_data.nvram, sz));
4578 /* Invalidate NVRAM information
4580 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4581 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4584 /* Read SPP0 header, allocate memory, then read page.
4586 header.PageVersion = 0;
4587 header.PageLength = 0;
4588 header.PageNumber = 0;
4589 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4590 cfg.cfghdr.hdr = &header;
4592 cfg.pageAddr = portnum;
4593 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4595 cfg.timeout = 0; /* use default */
4596 if (mpt_config(ioc, &cfg) != 0)
4599 if (header.PageLength > 0) {
4600 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4602 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4603 cfg.physAddr = buf_dma;
4604 if (mpt_config(ioc, &cfg) != 0) {
4605 ioc->spi_data.maxBusWidth = MPT_NARROW;
4606 ioc->spi_data.maxSyncOffset = 0;
4607 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4608 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4610 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4611 ioc->name, ioc->spi_data.minSyncFactor));
4613 /* Save the Port Page 0 data
4615 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4616 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4617 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4619 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4620 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4621 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4622 ioc->name, pPP0->Capabilities));
4624 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4625 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4627 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4628 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4629 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4630 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4631 ioc->name, ioc->spi_data.minSyncFactor));
4633 ioc->spi_data.maxSyncOffset = 0;
4634 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4637 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4639 /* Update the minSyncFactor based on bus type.
4641 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4642 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4644 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4645 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4646 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4647 ioc->name, ioc->spi_data.minSyncFactor));
4652 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4657 /* SCSI Port Page 2 - Read the header then the page.
4659 header.PageVersion = 0;
4660 header.PageLength = 0;
4661 header.PageNumber = 2;
4662 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4663 cfg.cfghdr.hdr = &header;
4665 cfg.pageAddr = portnum;
4666 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4668 if (mpt_config(ioc, &cfg) != 0)
4671 if (header.PageLength > 0) {
4672 /* Allocate memory and read SCSI Port Page 2
4674 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4676 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4677 cfg.physAddr = buf_dma;
4678 if (mpt_config(ioc, &cfg) != 0) {
4679 /* Nvram data is left with INVALID mark
4683 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4684 MpiDeviceInfo_t *pdevice = NULL;
4687 * Save "Set to Avoid SCSI Bus Resets" flag
4689 ioc->spi_data.bus_reset =
4690 (le32_to_cpu(pPP2->PortFlags) &
4691 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4694 /* Save the Port Page 2 data
4695 * (reformat into a 32bit quantity)
4697 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4698 ioc->spi_data.PortFlags = data;
4699 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4700 pdevice = &pPP2->DeviceSettings[ii];
4701 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4702 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4703 ioc->spi_data.nvram[ii] = data;
4707 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4711 /* Update Adapter limits with those from NVRAM
4712 * Comment: Don't need to do this. Target performance
4713 * parameters will never exceed the adapters limits.
4719 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4720 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4721 * @ioc: Pointer to a Adapter Strucutre
4722 * @portnum: IOC port number
4724 * Return: -EFAULT if read of config page header fails
4728 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4731 ConfigPageHeader_t header;
4733 /* Read the SCSI Device Page 1 header
4735 header.PageVersion = 0;
4736 header.PageLength = 0;
4737 header.PageNumber = 1;
4738 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4739 cfg.cfghdr.hdr = &header;
4741 cfg.pageAddr = portnum;
4742 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4745 if (mpt_config(ioc, &cfg) != 0)
4748 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4749 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4751 header.PageVersion = 0;
4752 header.PageLength = 0;
4753 header.PageNumber = 0;
4754 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4755 if (mpt_config(ioc, &cfg) != 0)
4758 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4759 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4761 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4762 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4764 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4765 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4769 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4771 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4772 * @ioc: Pointer to a Adapter Strucutre
4773 * @portnum: IOC port number
4777 * -EFAULT if read of config page header fails or data pointer not NULL
4778 * -ENOMEM if pci_alloc failed
4781 mpt_findImVolumes(MPT_ADAPTER *ioc)
4785 ConfigPageIoc2RaidVol_t *pIocRv;
4786 dma_addr_t ioc2_dma;
4788 ConfigPageHeader_t header;
4795 /* Read IOCP2 header then the page.
4797 header.PageVersion = 0;
4798 header.PageLength = 0;
4799 header.PageNumber = 2;
4800 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4801 cfg.cfghdr.hdr = &header;
4804 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4807 if (mpt_config(ioc, &cfg) != 0)
4810 if (header.PageLength == 0)
4813 iocpage2sz = header.PageLength * 4;
4814 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4818 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4819 cfg.physAddr = ioc2_dma;
4820 if (mpt_config(ioc, &cfg) != 0)
4823 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4824 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4826 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4831 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4833 /* Identify RAID Volume Id's */
4834 nVols = pIoc2->NumActiveVolumes;
4840 /* At least 1 RAID Volume
4842 pIocRv = pIoc2->RaidVolume;
4843 ioc->raid_data.isRaid = 0;
4844 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4845 vid = pIocRv->VolumeID;
4846 vbus = pIocRv->VolumeBus;
4847 vioc = pIocRv->VolumeIOC;
4852 ioc->raid_data.isRaid |= (1 << vid);
4854 /* Error! Always bus 0
4860 /* Identify Hidden Physical Disk Id's */
4861 nPhys = pIoc2->NumActivePhysDisks;
4863 /* No physical disks.
4866 mpt_read_ioc_pg_3(ioc);
4870 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4876 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4881 ConfigPageHeader_t header;
4882 dma_addr_t ioc3_dma;
4885 /* Free the old page
4887 kfree(ioc->raid_data.pIocPg3);
4888 ioc->raid_data.pIocPg3 = NULL;
4890 /* There is at least one physical disk.
4891 * Read and save IOC Page 3
4893 header.PageVersion = 0;
4894 header.PageLength = 0;
4895 header.PageNumber = 3;
4896 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4897 cfg.cfghdr.hdr = &header;
4900 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4903 if (mpt_config(ioc, &cfg) != 0)
4906 if (header.PageLength == 0)
4909 /* Read Header good, alloc memory
4911 iocpage3sz = header.PageLength * 4;
4912 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4916 /* Read the Page and save the data
4917 * into malloc'd memory.
4919 cfg.physAddr = ioc3_dma;
4920 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4921 if (mpt_config(ioc, &cfg) == 0) {
4922 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4924 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4925 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4929 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4935 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4939 ConfigPageHeader_t header;
4940 dma_addr_t ioc4_dma;
4943 /* Read and save IOC Page 4
4945 header.PageVersion = 0;
4946 header.PageLength = 0;
4947 header.PageNumber = 4;
4948 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4949 cfg.cfghdr.hdr = &header;
4952 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4955 if (mpt_config(ioc, &cfg) != 0)
4958 if (header.PageLength == 0)
4961 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4962 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4963 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4967 ioc4_dma = ioc->spi_data.IocPg4_dma;
4968 iocpage4sz = ioc->spi_data.IocPg4Sz;
4971 /* Read the Page into dma memory.
4973 cfg.physAddr = ioc4_dma;
4974 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4975 if (mpt_config(ioc, &cfg) == 0) {
4976 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4977 ioc->spi_data.IocPg4_dma = ioc4_dma;
4978 ioc->spi_data.IocPg4Sz = iocpage4sz;
4980 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4981 ioc->spi_data.pIocPg4 = NULL;
4986 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4990 ConfigPageHeader_t header;
4991 dma_addr_t ioc1_dma;
4995 /* Check the Coalescing Timeout in IOC Page 1
4997 header.PageVersion = 0;
4998 header.PageLength = 0;
4999 header.PageNumber = 1;
5000 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5001 cfg.cfghdr.hdr = &header;
5004 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5007 if (mpt_config(ioc, &cfg) != 0)
5010 if (header.PageLength == 0)
5013 /* Read Header good, alloc memory
5015 iocpage1sz = header.PageLength * 4;
5016 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5020 /* Read the Page and check coalescing timeout
5022 cfg.physAddr = ioc1_dma;
5023 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5024 if (mpt_config(ioc, &cfg) == 0) {
5026 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5027 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5028 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5030 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
5033 if (tmp > MPT_COALESCING_TIMEOUT) {
5034 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5036 /* Write NVRAM and current
5039 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5040 if (mpt_config(ioc, &cfg) == 0) {
5041 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
5042 ioc->name, MPT_COALESCING_TIMEOUT));
5044 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5045 if (mpt_config(ioc, &cfg) == 0) {
5046 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
5047 ioc->name, MPT_COALESCING_TIMEOUT));
5049 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
5054 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
5060 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5064 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5069 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5071 * SendEventNotification - Send EventNotification (on or off) request
5073 * @ioc: Pointer to MPT_ADAPTER structure
5074 * @EvSwitch: Event switch flags
5077 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5079 EventNotification_t *evnp;
5081 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5083 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5087 memset(evnp, 0, sizeof(*evnp));
5089 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5091 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5092 evnp->ChainOffset = 0;
5094 evnp->Switch = EvSwitch;
5096 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5103 * SendEventAck - Send EventAck request to MPT adapter.
5104 * @ioc: Pointer to MPT_ADAPTER structure
5105 * @evnp: Pointer to original EventNotification request
5108 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5112 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5113 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5114 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5115 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5116 le32_to_cpu(evnp->Data[0]));
5119 memset(pAck, 0, sizeof(*pAck));
5121 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5123 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5124 pAck->ChainOffset = 0;
5126 pAck->Event = evnp->Event;
5127 pAck->EventContext = evnp->EventContext;
5129 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5134 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5136 * mpt_config - Generic function to issue config message
5137 * @ioc - Pointer to an adapter structure
5138 * @cfg - Pointer to a configuration structure. Struct contains
5139 * action, page address, direction, physical address
5140 * and pointer to a configuration page header
5141 * Page header is updated.
5143 * Returns 0 for success
5144 * -EPERM if not allowed due to ISR context
5145 * -EAGAIN if no msg frames currently available
5146 * -EFAULT for non-successful reply or no reply (timeout)
5149 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5152 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5154 unsigned long flags;
5159 /* Prevent calling wait_event() (below), if caller happens
5160 * to be in ISR context, because that is fatal!
5162 in_isr = in_interrupt();
5164 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5169 /* Get and Populate a free Frame
5171 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5172 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5176 pReq = (Config_t *)mf;
5177 pReq->Action = pCfg->action;
5179 pReq->ChainOffset = 0;
5180 pReq->Function = MPI_FUNCTION_CONFIG;
5182 /* Assume page type is not extended and clear "reserved" fields. */
5183 pReq->ExtPageLength = 0;
5184 pReq->ExtPageType = 0;
5187 for (ii=0; ii < 8; ii++)
5188 pReq->Reserved2[ii] = 0;
5190 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5191 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5192 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5193 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5195 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5196 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5197 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5198 pReq->ExtPageType = pExtHdr->ExtPageType;
5199 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5201 /* Page Length must be treated as a reserved field for the extended header. */
5202 pReq->Header.PageLength = 0;
5205 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5207 /* Add a SGE to the config request.
5210 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5212 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5214 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5215 flagsLength |= pExtHdr->ExtPageLength * 4;
5217 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5218 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5221 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5223 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5224 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5227 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5229 /* Append pCfg pointer to end of mf
5231 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5233 /* Initalize the timer
5235 init_timer(&pCfg->timer);
5236 pCfg->timer.data = (unsigned long) ioc;
5237 pCfg->timer.function = mpt_timer_expired;
5238 pCfg->wait_done = 0;
5240 /* Set the timer; ensure 10 second minimum */
5241 if (pCfg->timeout < 10)
5242 pCfg->timer.expires = jiffies + HZ*10;
5244 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5246 /* Add to end of Q, set timer and then issue this command */
5247 spin_lock_irqsave(&ioc->FreeQlock, flags);
5248 list_add_tail(&pCfg->linkage, &ioc->configQ);
5249 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5251 add_timer(&pCfg->timer);
5252 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5253 wait_event(mpt_waitq, pCfg->wait_done);
5255 /* mf has been freed - do not access */
5262 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5264 * mpt_timer_expired - Call back for timer process.
5265 * Used only internal config functionality.
5266 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5269 mpt_timer_expired(unsigned long data)
5271 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5273 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5275 /* Perform a FW reload */
5276 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5277 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5279 /* No more processing.
5280 * Hard reset clean-up will wake up
5281 * process and free all resources.
5283 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5288 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5290 * mpt_ioc_reset - Base cleanup for hard reset
5291 * @ioc: Pointer to the adapter structure
5292 * @reset_phase: Indicates pre- or post-reset functionality
5294 * Remark: Free's resources with internally generated commands.
5297 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5300 unsigned long flags;
5302 dprintk((KERN_WARNING MYNAM
5303 ": IOC %s_reset routed to MPT base driver!\n",
5304 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5305 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5307 if (reset_phase == MPT_IOC_SETUP_RESET) {
5309 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5310 /* If the internal config Q is not empty -
5311 * delete timer. MF resources will be freed when
5312 * the FIFO's are primed.
5314 spin_lock_irqsave(&ioc->FreeQlock, flags);
5315 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5316 del_timer(&pCfg->timer);
5317 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5322 /* Search the configQ for internal commands.
5323 * Flush the Q, and wake up all suspended threads.
5325 spin_lock_irqsave(&ioc->FreeQlock, flags);
5326 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5327 list_del(&pCfg->linkage);
5329 pCfg->status = MPT_CONFIG_ERROR;
5330 pCfg->wait_done = 1;
5331 wake_up(&mpt_waitq);
5333 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5336 return 1; /* currently means nothing really */
5340 #ifdef CONFIG_PROC_FS /* { */
5341 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5343 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5345 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5347 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5349 * Returns 0 for success, non-zero for failure.
5352 procmpt_create(void)
5354 struct proc_dir_entry *ent;
5356 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5357 if (mpt_proc_root_dir == NULL)
5360 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5362 ent->read_proc = procmpt_summary_read;
5364 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5366 ent->read_proc = procmpt_version_read;
5371 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5373 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5375 * Returns 0 for success, non-zero for failure.
5378 procmpt_destroy(void)
5380 remove_proc_entry("version", mpt_proc_root_dir);
5381 remove_proc_entry("summary", mpt_proc_root_dir);
5382 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5387 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5388 * or from /proc/mpt/iocN/summary.
5389 * @buf: Pointer to area to write information
5390 * @start: Pointer to start pointer
5391 * @offset: Offset to start writing
5393 * @eof: Pointer to EOF integer
5396 * Returns number of characters written to process performing the read.
5399 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5409 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5413 list_for_each_entry(ioc, &ioc_list, list) {
5416 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5419 if ((out-buf) >= request)
5426 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5431 * procmpt_version_read - Handle read request from /proc/mpt/version.
5432 * @buf: Pointer to area to write information
5433 * @start: Pointer to start pointer
5434 * @offset: Offset to start writing
5436 * @eof: Pointer to EOF integer
5439 * Returns number of characters written to process performing the read.
5442 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5445 int scsi, fc, sas, lan, ctl, targ, dmp;
5449 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5450 len += sprintf(buf+len, " Fusion MPT base driver\n");
5452 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5453 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5455 if (MptCallbacks[ii]) {
5456 switch (MptDriverClass[ii]) {
5458 if (!scsi++) drvname = "SPI host";
5461 if (!fc++) drvname = "FC host";
5464 if (!sas++) drvname = "SAS host";
5467 if (!lan++) drvname = "LAN";
5470 if (!targ++) drvname = "SCSI target";
5473 if (!ctl++) drvname = "ioctl";
5478 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5482 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5485 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5487 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5488 * @buf: Pointer to area to write information
5489 * @start: Pointer to start pointer
5490 * @offset: Offset to start writing
5492 * @eof: Pointer to EOF integer
5495 * Returns number of characters written to process performing the read.
5498 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5500 MPT_ADAPTER *ioc = data;
5506 mpt_get_fw_exp_ver(expVer, ioc);
5508 len = sprintf(buf, "%s:", ioc->name);
5509 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5510 len += sprintf(buf+len, " (f/w download boot flag set)");
5511 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5512 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5514 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5515 ioc->facts.ProductID,
5517 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5518 if (ioc->facts.FWImageSize)
5519 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5520 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5521 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5522 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5524 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5525 ioc->facts.CurrentHostMfaHighAddr);
5526 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5527 ioc->facts.CurrentSenseBufferHighAddr);
5529 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5530 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5532 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5533 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5535 * Rounding UP to nearest 4-kB boundary here...
5537 sz = (ioc->req_sz * ioc->req_depth) + 128;
5538 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5539 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5540 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5541 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5542 4*ioc->facts.RequestFrameSize,
5543 ioc->facts.GlobalCredits);
5545 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5546 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5547 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5548 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5549 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5550 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5551 ioc->facts.CurReplyFrameSize,
5552 ioc->facts.ReplyQueueDepth);
5554 len += sprintf(buf+len, " MaxDevices = %d\n",
5555 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5556 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5559 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5560 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5562 ioc->facts.NumberOfPorts);
5563 if (ioc->bus_type == FC) {
5564 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5565 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5566 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5567 a[5], a[4], a[3], a[2], a[1], a[0]);
5569 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5570 ioc->fc_port_page0[p].WWNN.High,
5571 ioc->fc_port_page0[p].WWNN.Low,
5572 ioc->fc_port_page0[p].WWPN.High,
5573 ioc->fc_port_page0[p].WWPN.Low);
5577 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5580 #endif /* CONFIG_PROC_FS } */
5582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5584 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5587 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5588 sprintf(buf, " (Exp %02d%02d)",
5589 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5590 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5593 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5594 strcat(buf, " [MDBG]");
5598 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5600 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5601 * @ioc: Pointer to MPT_ADAPTER structure
5602 * @buffer: Pointer to buffer where IOC summary info should be written
5603 * @size: Pointer to number of bytes we wrote (set by this routine)
5604 * @len: Offset at which to start writing in buffer
5605 * @showlan: Display LAN stuff?
5607 * This routine writes (english readable) ASCII text, which represents
5608 * a summary of IOC information, to a buffer.
5611 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5616 mpt_get_fw_exp_ver(expVer, ioc);
5619 * Shorter summary of attached ioc's...
5621 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5624 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5625 ioc->facts.FWVersion.Word,
5627 ioc->facts.NumberOfPorts,
5630 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5631 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5632 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5633 a[5], a[4], a[3], a[2], a[1], a[0]);
5637 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5639 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5643 y += sprintf(buffer+len+y, " (disabled)");
5645 y += sprintf(buffer+len+y, "\n");
5650 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5656 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5657 * Management call based on input arg values. If TaskMgmt fails,
5658 * return associated SCSI request.
5659 * @ioc: Pointer to MPT_ADAPTER structure
5660 * @sleepFlag: Indicates if sleep or schedule must be called.
5662 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5663 * or a non-interrupt thread. In the former, must not call schedule().
5665 * Remark: A return of -1 is a FATAL error case, as it means a
5666 * FW reload/initialization failed.
5668 * Returns 0 for SUCCESS or -1 if FAILED.
5671 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5674 unsigned long flags;
5676 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5678 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5679 printk("MF count 0x%x !\n", ioc->mfcnt);
5682 /* Reset the adapter. Prevent more than 1 call to
5683 * mpt_do_ioc_recovery at any instant in time.
5685 spin_lock_irqsave(&ioc->diagLock, flags);
5686 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5687 spin_unlock_irqrestore(&ioc->diagLock, flags);
5690 ioc->diagPending = 1;
5692 spin_unlock_irqrestore(&ioc->diagLock, flags);
5694 /* FIXME: If do_ioc_recovery fails, repeat....
5697 /* The SCSI driver needs to adjust timeouts on all current
5698 * commands prior to the diagnostic reset being issued.
5699 * Prevents timeouts occuring during a diagnostic reset...very bad.
5700 * For all other protocol drivers, this is a no-op.
5706 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5707 if (MptResetHandlers[ii]) {
5708 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5710 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5712 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5713 ioc->name, ioc->alt_ioc->name, ii));
5714 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5720 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5721 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5726 ioc->alt_ioc->reload_fw = 0;
5728 spin_lock_irqsave(&ioc->diagLock, flags);
5729 ioc->diagPending = 0;
5731 ioc->alt_ioc->diagPending = 0;
5732 spin_unlock_irqrestore(&ioc->diagLock, flags);
5734 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5741 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5746 case MPI_EVENT_NONE:
5749 case MPI_EVENT_LOG_DATA:
5752 case MPI_EVENT_STATE_CHANGE:
5753 ds = "State Change";
5755 case MPI_EVENT_UNIT_ATTENTION:
5756 ds = "Unit Attention";
5758 case MPI_EVENT_IOC_BUS_RESET:
5759 ds = "IOC Bus Reset";
5761 case MPI_EVENT_EXT_BUS_RESET:
5762 ds = "External Bus Reset";
5764 case MPI_EVENT_RESCAN:
5765 ds = "Bus Rescan Event";
5766 /* Ok, do we need to do anything here? As far as
5767 I can tell, this is when a new device gets added
5770 case MPI_EVENT_LINK_STATUS_CHANGE:
5771 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5772 ds = "Link Status(FAILURE) Change";
5774 ds = "Link Status(ACTIVE) Change";
5776 case MPI_EVENT_LOOP_STATE_CHANGE:
5777 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5778 ds = "Loop State(LIP) Change";
5779 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5780 ds = "Loop State(LPE) Change"; /* ??? */
5782 ds = "Loop State(LPB) Change"; /* ??? */
5784 case MPI_EVENT_LOGOUT:
5787 case MPI_EVENT_EVENT_CHANGE:
5789 ds = "Events(ON) Change";
5791 ds = "Events(OFF) Change";
5793 case MPI_EVENT_INTEGRATED_RAID:
5795 u8 ReasonCode = (u8)(evData0 >> 16);
5796 switch (ReasonCode) {
5797 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5798 ds = "Integrated Raid: Volume Created";
5800 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5801 ds = "Integrated Raid: Volume Deleted";
5803 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5804 ds = "Integrated Raid: Volume Settings Changed";
5806 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5807 ds = "Integrated Raid: Volume Status Changed";
5809 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5810 ds = "Integrated Raid: Volume Physdisk Changed";
5812 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5813 ds = "Integrated Raid: Physdisk Created";
5815 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5816 ds = "Integrated Raid: Physdisk Deleted";
5818 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5819 ds = "Integrated Raid: Physdisk Settings Changed";
5821 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5822 ds = "Integrated Raid: Physdisk Status Changed";
5824 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5825 ds = "Integrated Raid: Domain Validation Needed";
5827 case MPI_EVENT_RAID_RC_SMART_DATA :
5828 ds = "Integrated Raid; Smart Data";
5830 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5831 ds = "Integrated Raid: Replace Action Started";
5834 ds = "Integrated Raid";
5839 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5840 ds = "SCSI Device Status Change";
5842 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5845 u8 id = (u8)(evData0);
5846 u8 ReasonCode = (u8)(evData0 >> 16);
5847 switch (ReasonCode) {
5848 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5849 sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
5851 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5852 sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
5854 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5855 sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
5857 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5858 sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
5861 sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
5867 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5868 ds = "Bus Timer Expired";
5870 case MPI_EVENT_QUEUE_FULL:
5873 case MPI_EVENT_SAS_SES:
5874 ds = "SAS SES Event";
5876 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5877 ds = "Persistent Table Full";
5879 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5882 u8 LinkRates = (u8)(evData0 >> 8);
5883 u8 PhyNumber = (u8)(evData0);
5884 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5885 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5886 switch (LinkRates) {
5887 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5888 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5889 " Rate Unknown",PhyNumber);
5891 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5892 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5893 " Phy Disabled",PhyNumber);
5895 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5896 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5897 " Failed Speed Nego",PhyNumber);
5899 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5900 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5901 " Sata OOB Completed",PhyNumber);
5903 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5904 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5905 " Rate 1.5 Gbps",PhyNumber);
5907 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5908 sprintf(buf,"SAS PHY Link Status: Phy=%d:"
5909 " Rate 3.0 Gpbs",PhyNumber);
5912 sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
5918 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5919 ds = "SAS Discovery Error";
5921 case MPI_EVENT_IR_RESYNC_UPDATE:
5923 u8 resync_complete = (u8)(evData0 >> 16);
5925 sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
5931 u8 ReasonCode = (u8)(evData0 >> 16);
5932 switch (ReasonCode) {
5933 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5934 ds = "IR2: LD State Changed";
5936 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5937 ds = "IR2: PD State Changed";
5939 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5940 ds = "IR2: Bad Block Table Full";
5942 case MPI_EVENT_IR2_RC_PD_INSERTED:
5943 ds = "IR2: PD Inserted";
5945 case MPI_EVENT_IR2_RC_PD_REMOVED:
5946 ds = "IR2: PD Removed";
5948 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5949 ds = "IR2: Foreign CFG Detected";
5951 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5952 ds = "IR2: Rebuild Medium Error";
5960 case MPI_EVENT_SAS_DISCOVERY:
5963 ds = "SAS Discovery: Start";
5965 ds = "SAS Discovery: Stop";
5968 case MPI_EVENT_LOG_ENTRY_ADDED:
5969 ds = "SAS Log Entry Added";
5973 * MPT base "custom" events may be added here...
5982 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5984 * ProcessEventNotification - Route a received EventNotificationReply to
5985 * all currently regeistered event handlers.
5986 * @ioc: Pointer to MPT_ADAPTER structure
5987 * @pEventReply: Pointer to EventNotification reply frame
5988 * @evHandlers: Pointer to integer, number of event handlers
5990 * Returns sum of event handlers return values.
5993 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6005 * Do platform normalization of values
6007 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6008 // evCtx = le32_to_cpu(pEventReply->EventContext);
6009 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6011 evData0 = le32_to_cpu(pEventReply->Data[0]);
6014 EventDescriptionStr(event, evData0, evStr);
6015 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
6020 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
6021 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
6022 for (ii = 0; ii < evDataLen; ii++)
6023 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
6028 * Do general / base driver event processing
6031 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6033 u8 evState = evData0 & 0xFF;
6035 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6037 /* Update EventState field in cached IocFacts */
6038 if (ioc->facts.Function) {
6039 ioc->facts.EventState = evState;
6043 case MPI_EVENT_INTEGRATED_RAID:
6044 mptbase_raid_process_event_data(ioc,
6045 (MpiEventDataRaid_t *)pEventReply->Data);
6052 * Should this event be logged? Events are written sequentially.
6053 * When buffer is full, start again at the top.
6055 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6058 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6060 ioc->events[idx].event = event;
6061 ioc->events[idx].eventContext = ioc->eventContext;
6063 for (ii = 0; ii < 2; ii++) {
6065 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6067 ioc->events[idx].data[ii] = 0;
6070 ioc->eventContext++;
6075 * Call each currently registered protocol event handler.
6077 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6078 if (MptEvHandlers[ii]) {
6079 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6081 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6085 /* FIXME? Examine results here? */
6088 * If needed, send (a single) EventAck.
6090 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6091 devtverboseprintk((MYIOC_s_WARN_FMT
6092 "EventAck required\n",ioc->name));
6093 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6094 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6099 *evHandlers = handlers;
6103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6105 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6106 * @ioc: Pointer to MPT_ADAPTER structure
6107 * @log_info: U32 LogInfo reply word from the IOC
6109 * Refer to lsi/fc_log.h.
6112 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6114 static char *subcl_str[8] = {
6115 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6116 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6118 u8 subcl = (log_info >> 24) & 0x7;
6120 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6121 ioc->name, log_info, subcl_str[subcl]);
6124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6126 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6127 * @ioc: Pointer to MPT_ADAPTER structure
6128 * @mr: Pointer to MPT reply frame
6129 * @log_info: U32 LogInfo word from the IOC
6131 * Refer to lsi/sp_log.h.
6134 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6136 u32 info = log_info & 0x00FF0000;
6137 char *desc = "unknown";
6141 desc = "bug! MID not found";
6142 if (ioc->reload_fw == 0)
6147 desc = "Parity Error";
6151 desc = "ASYNC Outbound Overrun";
6155 desc = "SYNC Offset Error";
6163 desc = "Msg In Overflow";
6171 desc = "Outbound DMA Overrun";
6175 desc = "Task Management";
6179 desc = "Device Problem";
6183 desc = "Invalid Phase Change";
6187 desc = "Untagged Table Size";
6192 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6195 /* strings for sas loginfo */
6196 static char *originator_str[] = {
6201 static char *iop_code_str[] = {
6203 "Invalid SAS Address", /* 01h */
6205 "Invalid Page", /* 03h */
6207 "Task Terminated" /* 05h */
6209 static char *pl_code_str[] = {
6211 "Open Failure", /* 01h */
6212 "Invalid Scatter Gather List", /* 02h */
6213 "Wrong Relative Offset or Frame Length", /* 03h */
6214 "Frame Transfer Error", /* 04h */
6215 "Transmit Frame Connected Low", /* 05h */
6216 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6217 "SATA Read Log Receive Data Error", /* 07h */
6218 "SATA NCQ Fail All Commands After Error", /* 08h */
6219 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6220 "Receive Frame Invalid Message", /* 0Ah */
6221 "Receive Context Message Valid Error", /* 0Bh */
6222 "Receive Frame Current Frame Error", /* 0Ch */
6223 "SATA Link Down", /* 0Dh */
6224 "Discovery SATA Init W IOS", /* 0Eh */
6225 "Config Invalid Page", /* 0Fh */
6226 "Discovery SATA Init Timeout", /* 10h */
6229 "IO Not Yet Executed", /* 13h */
6230 "IO Executed", /* 14h */
6231 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6232 "Open Transmit DMA Abort", /* 16h */
6242 "Enclosure Management" /* 20h */
6245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6247 * mpt_sas_log_info - Log information returned from SAS IOC.
6248 * @ioc: Pointer to MPT_ADAPTER structure
6249 * @log_info: U32 LogInfo reply word from the IOC
6251 * Refer to lsi/mpi_log_sas.h.
6254 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6256 union loginfo_type {
6265 union loginfo_type sas_loginfo;
6266 char *code_desc = NULL;
6268 sas_loginfo.loginfo = log_info;
6269 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6270 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6272 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6273 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6274 code_desc = iop_code_str[sas_loginfo.dw.code];
6275 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6276 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6277 code_desc = pl_code_str[sas_loginfo.dw.code];
6280 if (code_desc != NULL)
6281 printk(MYIOC_s_INFO_FMT
6282 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6283 " SubCode(0x%04x)\n",
6286 originator_str[sas_loginfo.dw.originator],
6288 sas_loginfo.dw.subcode);
6290 printk(MYIOC_s_INFO_FMT
6291 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6292 " SubCode(0x%04x)\n",
6295 originator_str[sas_loginfo.dw.originator],
6296 sas_loginfo.dw.code,
6297 sas_loginfo.dw.subcode);
6300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6302 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6303 * @ioc: Pointer to MPT_ADAPTER structure
6304 * @ioc_status: U32 IOCStatus word from IOC
6305 * @mf: Pointer to MPT request frame
6307 * Refer to lsi/mpi.h.
6310 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6312 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6316 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6317 desc = "Invalid Function";
6320 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6324 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6325 desc = "Invalid SGL";
6328 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6329 desc = "Internal Error";
6332 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6336 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6337 desc = "Insufficient Resources";
6340 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6341 desc = "Invalid Field";
6344 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6345 desc = "Invalid State";
6348 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6349 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6350 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6351 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6352 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6353 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6354 /* No message for Config IOCStatus values */
6357 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6358 /* No message for recovered error
6359 desc = "SCSI Recovered Error";
6363 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6364 desc = "SCSI Invalid Bus";
6367 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6368 desc = "SCSI Invalid TargetID";
6371 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6373 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6374 U8 cdb = pScsiReq->CDB[0];
6375 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6376 desc = "SCSI Device Not There";
6381 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6382 desc = "SCSI Data Overrun";
6385 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6386 /* This error is checked in scsi_io_done(). Skip.
6387 desc = "SCSI Data Underrun";
6391 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6392 desc = "SCSI I/O Data Error";
6395 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6396 desc = "SCSI Protocol Error";
6399 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6400 desc = "SCSI Task Terminated";
6403 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6404 desc = "SCSI Residual Mismatch";
6407 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6408 desc = "SCSI Task Management Failed";
6411 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6412 desc = "SCSI IOC Terminated";
6415 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6416 desc = "SCSI Ext Terminated";
6424 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6427 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6428 EXPORT_SYMBOL(mpt_attach);
6429 EXPORT_SYMBOL(mpt_detach);
6431 EXPORT_SYMBOL(mpt_resume);
6432 EXPORT_SYMBOL(mpt_suspend);
6434 EXPORT_SYMBOL(ioc_list);
6435 EXPORT_SYMBOL(mpt_proc_root_dir);
6436 EXPORT_SYMBOL(mpt_register);
6437 EXPORT_SYMBOL(mpt_deregister);
6438 EXPORT_SYMBOL(mpt_event_register);
6439 EXPORT_SYMBOL(mpt_event_deregister);
6440 EXPORT_SYMBOL(mpt_reset_register);
6441 EXPORT_SYMBOL(mpt_reset_deregister);
6442 EXPORT_SYMBOL(mpt_device_driver_register);
6443 EXPORT_SYMBOL(mpt_device_driver_deregister);
6444 EXPORT_SYMBOL(mpt_get_msg_frame);
6445 EXPORT_SYMBOL(mpt_put_msg_frame);
6446 EXPORT_SYMBOL(mpt_free_msg_frame);
6447 EXPORT_SYMBOL(mpt_add_sge);
6448 EXPORT_SYMBOL(mpt_send_handshake_request);
6449 EXPORT_SYMBOL(mpt_verify_adapter);
6450 EXPORT_SYMBOL(mpt_GetIocState);
6451 EXPORT_SYMBOL(mpt_print_ioc_summary);
6452 EXPORT_SYMBOL(mpt_lan_index);
6453 EXPORT_SYMBOL(mpt_stm_index);
6454 EXPORT_SYMBOL(mpt_HardResetHandler);
6455 EXPORT_SYMBOL(mpt_config);
6456 EXPORT_SYMBOL(mpt_findImVolumes);
6457 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6458 EXPORT_SYMBOL(mpt_free_fw_memory);
6459 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6460 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6463 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6465 * fusion_init - Fusion MPT base driver initialization routine.
6467 * Returns 0 for success, non-zero for failure.
6474 show_mptmod_ver(my_NAME, my_VERSION);
6475 printk(KERN_INFO COPYRIGHT "\n");
6477 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6478 MptCallbacks[i] = NULL;
6479 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6480 MptEvHandlers[i] = NULL;
6481 MptResetHandlers[i] = NULL;
6484 /* Register ourselves (mptbase) in order to facilitate
6485 * EventNotification handling.
6487 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6489 /* Register for hard reset handling callbacks.
6491 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6492 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6497 #ifdef CONFIG_PROC_FS
6498 (void) procmpt_create();
6503 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6505 * fusion_exit - Perform driver unload cleanup.
6507 * This routine frees all resources associated with each MPT adapter
6508 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6514 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6516 mpt_reset_deregister(mpt_base_index);
6518 #ifdef CONFIG_PROC_FS
6523 module_init(fusion_init);
6524 module_exit(fusion_exit);