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->initializing_hba_lock);
1193 /* Initialize the event logging.
1195 ioc->eventTypes = 0; /* None */
1196 ioc->eventContext = 0;
1197 ioc->eventLogSize = 0;
1204 ioc->cached_fw = NULL;
1206 /* Initilize SCSI Config Data structure
1208 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1210 /* Initialize the running configQ head.
1212 INIT_LIST_HEAD(&ioc->configQ);
1214 /* Initialize the fc rport list head.
1216 INIT_LIST_HEAD(&ioc->fc_rports);
1218 /* Find lookup slot. */
1219 INIT_LIST_HEAD(&ioc->list);
1220 ioc->id = mpt_ids++;
1222 mem_phys = msize = 0;
1224 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1225 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1226 /* Get I/O space! */
1227 port = pci_resource_start(pdev, ii);
1228 psize = pci_resource_len(pdev,ii);
1231 mem_phys = pci_resource_start(pdev, ii);
1232 msize = pci_resource_len(pdev,ii);
1236 ioc->mem_size = msize;
1238 if (ii == DEVICE_COUNT_RESOURCE) {
1239 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1244 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1245 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1248 /* Get logical ptr for PciMem0 space */
1249 /*mem = ioremap(mem_phys, msize);*/
1250 mem = ioremap(mem_phys, 0x100);
1252 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1257 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1259 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1260 &ioc->facts, &ioc->pfacts[0]));
1262 ioc->mem_phys = mem_phys;
1263 ioc->chip = (SYSIF_REGS __iomem *)mem;
1265 /* Save Port IO values in case we need to do downloadboot */
1267 u8 *pmem = (u8*)port;
1268 ioc->pio_mem_phys = port;
1269 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1272 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1273 ioc->prod_name = "LSIFC909";
1276 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1277 ioc->prod_name = "LSIFC929";
1280 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1281 ioc->prod_name = "LSIFC919";
1284 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1285 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1287 if (revision < XL_929) {
1288 ioc->prod_name = "LSIFC929X";
1289 /* 929X Chip Fix. Set Split transactions level
1290 * for PCIX. Set MOST bits to zero.
1292 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1294 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1296 ioc->prod_name = "LSIFC929XL";
1297 /* 929XL Chip Fix. Set MMRBC to 0x08.
1299 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1301 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1304 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1305 ioc->prod_name = "LSIFC919X";
1307 /* 919X Chip Fix. Set Split transactions level
1308 * for PCIX. Set MOST bits to zero.
1310 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1312 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1314 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1315 ioc->prod_name = "LSIFC939X";
1317 ioc->errata_flag_1064 = 1;
1319 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1320 ioc->prod_name = "LSIFC949X";
1322 ioc->errata_flag_1064 = 1;
1324 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1325 ioc->prod_name = "LSIFC949E";
1328 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1329 ioc->prod_name = "LSI53C1030";
1330 ioc->bus_type = SPI;
1331 /* 1030 Chip Fix. Disable Split transactions
1332 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1334 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1335 if (revision < C0_1030) {
1336 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1338 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1341 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1342 ioc->prod_name = "LSI53C1035";
1343 ioc->bus_type = SPI;
1345 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1346 ioc->prod_name = "LSISAS1064";
1347 ioc->bus_type = SAS;
1348 ioc->errata_flag_1064 = 1;
1350 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1351 ioc->prod_name = "LSISAS1066";
1352 ioc->bus_type = SAS;
1353 ioc->errata_flag_1064 = 1;
1355 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1356 ioc->prod_name = "LSISAS1068";
1357 ioc->bus_type = SAS;
1358 ioc->errata_flag_1064 = 1;
1360 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1361 ioc->prod_name = "LSISAS1064E";
1362 ioc->bus_type = SAS;
1364 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1365 ioc->prod_name = "LSISAS1066E";
1366 ioc->bus_type = SAS;
1368 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1369 ioc->prod_name = "LSISAS1068E";
1370 ioc->bus_type = SAS;
1373 if (ioc->errata_flag_1064)
1374 pci_disable_io_access(pdev);
1376 sprintf(ioc->name, "ioc%d", ioc->id);
1378 spin_lock_init(&ioc->FreeQlock);
1381 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1383 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1385 /* Set lookup ptr. */
1386 list_add_tail(&ioc->list, &ioc_list);
1388 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1390 mpt_detect_bound_ports(ioc, pdev);
1392 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1394 printk(KERN_WARNING MYNAM
1395 ": WARNING - %s did not initialize properly! (%d)\n",
1397 list_del(&ioc->list);
1399 ioc->alt_ioc->alt_ioc = NULL;
1402 pci_set_drvdata(pdev, NULL);
1406 /* call per device driver probe entry point */
1407 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1408 if(MptDeviceDriverHandlers[ii] &&
1409 MptDeviceDriverHandlers[ii]->probe) {
1410 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1414 #ifdef CONFIG_PROC_FS
1416 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1418 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1420 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1422 ent->read_proc = procmpt_iocinfo_read;
1425 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1427 ent->read_proc = procmpt_summary_read;
1436 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1438 * mpt_detach - Remove a PCI intelligent MPT adapter.
1439 * @pdev: Pointer to pci_dev structure
1444 mpt_detach(struct pci_dev *pdev)
1446 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1450 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1451 remove_proc_entry(pname, NULL);
1452 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1453 remove_proc_entry(pname, NULL);
1454 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1455 remove_proc_entry(pname, NULL);
1457 /* call per device driver remove entry point */
1458 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1459 if(MptDeviceDriverHandlers[ii] &&
1460 MptDeviceDriverHandlers[ii]->remove) {
1461 MptDeviceDriverHandlers[ii]->remove(pdev);
1465 /* Disable interrupts! */
1466 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1469 synchronize_irq(pdev->irq);
1471 /* Clear any lingering interrupt */
1472 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1474 CHIPREG_READ32(&ioc->chip->IntStatus);
1476 mpt_adapter_dispose(ioc);
1478 pci_set_drvdata(pdev, NULL);
1481 /**************************************************************************
1485 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1487 * mpt_suspend - Fusion MPT base driver suspend routine.
1492 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1495 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1497 device_state=pci_choose_state(pdev, state);
1499 printk(MYIOC_s_INFO_FMT
1500 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1501 ioc->name, pdev, pci_name(pdev), device_state);
1503 pci_save_state(pdev);
1505 /* put ioc into READY_STATE */
1506 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1507 printk(MYIOC_s_ERR_FMT
1508 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1511 /* disable interrupts */
1512 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1515 /* Clear any lingering interrupt */
1516 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1518 pci_disable_device(pdev);
1519 pci_set_power_state(pdev, device_state);
1524 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526 * mpt_resume - Fusion MPT base driver resume routine.
1531 mpt_resume(struct pci_dev *pdev)
1533 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1534 u32 device_state = pdev->current_state;
1537 printk(MYIOC_s_INFO_FMT
1538 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1539 ioc->name, pdev, pci_name(pdev), device_state);
1541 pci_set_power_state(pdev, 0);
1542 pci_restore_state(pdev);
1543 pci_enable_device(pdev);
1545 /* enable interrupts */
1546 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1549 printk(MYIOC_s_INFO_FMT
1550 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1552 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1553 CHIPREG_READ32(&ioc->chip->Doorbell));
1555 /* bring ioc to operational state */
1556 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1557 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1558 printk(MYIOC_s_INFO_FMT
1559 "pci-resume: Cannot recover, error:[%x]\n",
1560 ioc->name, recovery_state);
1562 printk(MYIOC_s_INFO_FMT
1563 "pci-resume: success\n", ioc->name);
1571 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1573 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1574 ioc->bus_type != SPI) ||
1575 (MptDriverClass[index] == MPTFC_DRIVER &&
1576 ioc->bus_type != FC) ||
1577 (MptDriverClass[index] == MPTSAS_DRIVER &&
1578 ioc->bus_type != SAS))
1579 /* make sure we only call the relevant reset handler
1582 return (MptResetHandlers[index])(ioc, reset_phase);
1585 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1587 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1588 * @ioc: Pointer to MPT adapter structure
1589 * @reason: Event word / reason
1590 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1592 * This routine performs all the steps necessary to bring the IOC
1593 * to a OPERATIONAL state.
1595 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1600 * -1 if failed to get board READY
1601 * -2 if READY but IOCFacts Failed
1602 * -3 if READY but PrimeIOCFifos Failed
1603 * -4 if READY but IOCInit Failed
1606 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1608 int hard_reset_done = 0;
1609 int alt_ioc_ready = 0;
1615 int reset_alt_ioc_active = 0;
1616 int irq_allocated = 0;
1618 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1619 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1621 /* Disable reply interrupts (also blocks FreeQ) */
1622 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1626 if (ioc->alt_ioc->active)
1627 reset_alt_ioc_active = 1;
1629 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1630 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1631 ioc->alt_ioc->active = 0;
1635 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1638 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1639 if (hard_reset_done == -4) {
1640 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1643 if (reset_alt_ioc_active && ioc->alt_ioc) {
1644 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1645 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1646 ioc->alt_ioc->name));
1647 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1648 ioc->alt_ioc->active = 1;
1652 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1658 /* hard_reset_done = 0 if a soft reset was performed
1659 * and 1 if a hard reset was performed.
1661 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1662 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1665 printk(KERN_WARNING MYNAM
1666 ": alt-%s: Not ready WARNING!\n",
1667 ioc->alt_ioc->name);
1670 for (ii=0; ii<5; ii++) {
1671 /* Get IOC facts! Allow 5 retries */
1672 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1678 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1680 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1681 MptDisplayIocCapabilities(ioc);
1684 if (alt_ioc_ready) {
1685 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1686 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1687 /* Retry - alt IOC was initialized once
1689 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1692 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1694 reset_alt_ioc_active = 0;
1695 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1696 MptDisplayIocCapabilities(ioc->alt_ioc);
1701 * Device is reset now. It must have de-asserted the interrupt line
1702 * (if it was asserted) and it should be safe to register for the
1705 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1707 if (ioc->pcidev->irq) {
1708 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1709 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1711 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1712 SA_SHIRQ, ioc->name, ioc);
1715 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1716 "interrupt %d!\n", ioc->name,
1719 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1720 "interrupt %s!\n", ioc->name,
1721 __irq_itoa(ioc->pcidev->irq));
1724 pci_disable_msi(ioc->pcidev);
1728 ioc->pci_irq = ioc->pcidev->irq;
1729 pci_set_master(ioc->pcidev); /* ?? */
1730 pci_set_drvdata(ioc->pcidev, ioc);
1732 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1733 "%d\n", ioc->name, ioc->pcidev->irq));
1735 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1737 __irq_itoa(ioc->pcidev->irq)));
1742 /* Prime reply & request queues!
1743 * (mucho alloc's) Must be done prior to
1744 * init as upper addresses are needed for init.
1745 * If fails, continue with alt-ioc processing
1747 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1750 /* May need to check/upload firmware & data here!
1751 * If fails, continue with alt-ioc processing
1753 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1756 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1757 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1758 ioc->alt_ioc->name, rc);
1760 reset_alt_ioc_active = 0;
1763 if (alt_ioc_ready) {
1764 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1766 reset_alt_ioc_active = 0;
1767 printk(KERN_WARNING MYNAM
1768 ": alt-%s: (%d) init failure WARNING!\n",
1769 ioc->alt_ioc->name, rc);
1773 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1774 if (ioc->upload_fw) {
1775 ddlprintk((MYIOC_s_INFO_FMT
1776 "firmware upload required!\n", ioc->name));
1778 /* Controller is not operational, cannot do upload
1781 rc = mpt_do_upload(ioc, sleepFlag);
1783 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1785 * Maintain only one pointer to FW memory
1786 * so there will not be two attempt to
1787 * downloadboot onboard dual function
1788 * chips (mpt_adapter_disable,
1791 ioc->cached_fw = NULL;
1792 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1793 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1796 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1804 /* Enable! (reply interrupt) */
1805 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1809 if (reset_alt_ioc_active && ioc->alt_ioc) {
1810 /* (re)Enable alt-IOC! (reply interrupt) */
1811 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1812 ioc->alt_ioc->name));
1813 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1814 ioc->alt_ioc->active = 1;
1817 /* Enable MPT base driver management of EventNotification
1818 * and EventAck handling.
1820 if ((ret == 0) && (!ioc->facts.EventState))
1821 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1823 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1824 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1826 /* Add additional "reason" check before call to GetLanConfigPages
1827 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1828 * recursive scenario; GetLanConfigPages times out, timer expired
1829 * routine calls HardResetHandler, which calls into here again,
1830 * and we try GetLanConfigPages again...
1832 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1833 if (ioc->bus_type == SAS) {
1835 /* clear persistency table */
1836 if(ioc->facts.IOCExceptions &
1837 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1838 ret = mptbase_sas_persist_operation(ioc,
1839 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1846 mpt_findImVolumes(ioc);
1848 } else if (ioc->bus_type == FC) {
1849 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1850 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1852 * Pre-fetch the ports LAN MAC address!
1853 * (LANPage1_t stuff)
1855 (void) GetLanConfigPages(ioc);
1858 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1859 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1860 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1865 /* Get NVRAM and adapter maximums from SPP 0 and 2
1867 mpt_GetScsiPortSettings(ioc, 0);
1869 /* Get version and length of SDP 1
1871 mpt_readScsiDevicePageHeaders(ioc, 0);
1875 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1876 mpt_findImVolumes(ioc);
1878 /* Check, and possibly reset, the coalescing value
1880 mpt_read_ioc_pg_1(ioc);
1882 mpt_read_ioc_pg_4(ioc);
1885 GetIoUnitPage2(ioc);
1889 * Call each currently registered protocol IOC reset handler
1890 * with post-reset indication.
1891 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1892 * MptResetHandlers[] registered yet.
1894 if (hard_reset_done) {
1896 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1897 if ((ret == 0) && MptResetHandlers[ii]) {
1898 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1900 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1904 if (alt_ioc_ready && MptResetHandlers[ii]) {
1905 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1906 ioc->name, ioc->alt_ioc->name, ii));
1907 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1911 /* FIXME? Examine results here? */
1915 if ((ret != 0) && irq_allocated) {
1916 free_irq(ioc->pci_irq, ioc);
1918 pci_disable_msi(ioc->pcidev);
1923 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1925 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1926 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1927 * 929X, 1030 or 1035.
1928 * @ioc: Pointer to MPT adapter structure
1929 * @pdev: Pointer to (struct pci_dev) structure
1931 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1932 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1935 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1937 struct pci_dev *peer=NULL;
1938 unsigned int slot = PCI_SLOT(pdev->devfn);
1939 unsigned int func = PCI_FUNC(pdev->devfn);
1940 MPT_ADAPTER *ioc_srch;
1942 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1943 " searching for devfn match on %x or %x\n",
1944 ioc->name, pci_name(pdev), pdev->bus->number,
1945 pdev->devfn, func-1, func+1));
1947 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1949 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1954 list_for_each_entry(ioc_srch, &ioc_list, list) {
1955 struct pci_dev *_pcidev = ioc_srch->pcidev;
1956 if (_pcidev == peer) {
1957 /* Paranoia checks */
1958 if (ioc->alt_ioc != NULL) {
1959 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1960 ioc->name, ioc->alt_ioc->name);
1962 } else if (ioc_srch->alt_ioc != NULL) {
1963 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1964 ioc_srch->name, ioc_srch->alt_ioc->name);
1967 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1968 ioc->name, ioc_srch->name));
1969 ioc_srch->alt_ioc = ioc;
1970 ioc->alt_ioc = ioc_srch;
1976 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1978 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1979 * @this: Pointer to MPT adapter structure
1982 mpt_adapter_disable(MPT_ADAPTER *ioc)
1987 if (ioc->cached_fw != NULL) {
1988 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1989 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1990 printk(KERN_WARNING MYNAM
1991 ": firmware downloadboot failure (%d)!\n", ret);
1995 /* Disable adapter interrupts! */
1996 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1998 /* Clear any lingering interrupt */
1999 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2001 if (ioc->alloc != NULL) {
2003 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2004 ioc->name, ioc->alloc, ioc->alloc_sz));
2005 pci_free_consistent(ioc->pcidev, sz,
2006 ioc->alloc, ioc->alloc_dma);
2007 ioc->reply_frames = NULL;
2008 ioc->req_frames = NULL;
2010 ioc->alloc_total -= sz;
2013 if (ioc->sense_buf_pool != NULL) {
2014 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2015 pci_free_consistent(ioc->pcidev, sz,
2016 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2017 ioc->sense_buf_pool = NULL;
2018 ioc->alloc_total -= sz;
2021 if (ioc->events != NULL){
2022 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2025 ioc->alloc_total -= sz;
2028 if (ioc->cached_fw != NULL) {
2029 sz = ioc->facts.FWImageSize;
2030 pci_free_consistent(ioc->pcidev, sz,
2031 ioc->cached_fw, ioc->cached_fw_dma);
2032 ioc->cached_fw = NULL;
2033 ioc->alloc_total -= sz;
2036 kfree(ioc->spi_data.nvram);
2037 kfree(ioc->raid_data.pIocPg3);
2038 ioc->spi_data.nvram = NULL;
2039 ioc->raid_data.pIocPg3 = NULL;
2041 if (ioc->spi_data.pIocPg4 != NULL) {
2042 sz = ioc->spi_data.IocPg4Sz;
2043 pci_free_consistent(ioc->pcidev, sz,
2044 ioc->spi_data.pIocPg4,
2045 ioc->spi_data.IocPg4_dma);
2046 ioc->spi_data.pIocPg4 = NULL;
2047 ioc->alloc_total -= sz;
2050 if (ioc->ReqToChain != NULL) {
2051 kfree(ioc->ReqToChain);
2052 kfree(ioc->RequestNB);
2053 ioc->ReqToChain = NULL;
2056 kfree(ioc->ChainToChain);
2057 ioc->ChainToChain = NULL;
2059 if (ioc->HostPageBuffer != NULL) {
2060 if((ret = mpt_host_page_access_control(ioc,
2061 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2062 printk(KERN_ERR MYNAM
2063 ": %s: host page buffers free failed (%d)!\n",
2066 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2067 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2068 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2069 ioc->HostPageBuffer,
2070 ioc->HostPageBuffer_dma);
2071 ioc->HostPageBuffer = NULL;
2072 ioc->HostPageBuffer_sz = 0;
2073 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2077 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2079 * mpt_adapter_dispose - Free all resources associated with a MPT
2081 * @ioc: Pointer to MPT adapter structure
2083 * This routine unregisters h/w resources and frees all alloc'd memory
2084 * associated with a MPT adapter structure.
2087 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2089 int sz_first, sz_last;
2094 sz_first = ioc->alloc_total;
2096 mpt_adapter_disable(ioc);
2098 if (ioc->pci_irq != -1) {
2099 free_irq(ioc->pci_irq, ioc);
2101 pci_disable_msi(ioc->pcidev);
2105 if (ioc->memmap != NULL) {
2106 iounmap(ioc->memmap);
2110 #if defined(CONFIG_MTRR) && 0
2111 if (ioc->mtrr_reg > 0) {
2112 mtrr_del(ioc->mtrr_reg, 0, 0);
2113 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2117 /* Zap the adapter lookup ptr! */
2118 list_del(&ioc->list);
2120 sz_last = ioc->alloc_total;
2121 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2122 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2125 ioc->alt_ioc->alt_ioc = NULL;
2130 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2132 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2133 * @ioc: Pointer to MPT adapter structure
2136 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2140 printk(KERN_INFO "%s: ", ioc->name);
2141 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2142 printk("%s: ", ioc->prod_name+3);
2143 printk("Capabilities={");
2145 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2146 printk("Initiator");
2150 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2151 printk("%sTarget", i ? "," : "");
2155 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2156 printk("%sLAN", i ? "," : "");
2162 * This would probably evoke more questions than it's worth
2164 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2165 printk("%sLogBusAddr", i ? "," : "");
2173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2175 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2176 * @ioc: Pointer to MPT_ADAPTER structure
2177 * @force: Force hard KickStart of IOC
2178 * @sleepFlag: Specifies whether the process can sleep
2181 * 1 - DIAG reset and READY
2182 * 0 - READY initially OR soft reset and READY
2183 * -1 - Any failure on KickStart
2184 * -2 - Msg Unit Reset Failed
2185 * -3 - IO Unit Reset Failed
2186 * -4 - IOC owned by a PEER
2189 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2194 int hard_reset_done = 0;
2199 /* Get current [raw] IOC state */
2200 ioc_state = mpt_GetIocState(ioc, 0);
2201 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2204 * Check to see if IOC got left/stuck in doorbell handshake
2205 * grip of death. If so, hard reset the IOC.
2207 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2209 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2213 /* Is it already READY? */
2214 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2218 * Check to see if IOC is in FAULT state.
2220 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2222 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2224 printk(KERN_WARNING " FAULT code = %04xh\n",
2225 ioc_state & MPI_DOORBELL_DATA_MASK);
2229 * Hmmm... Did it get left operational?
2231 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2232 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2236 * If PCI Peer, exit.
2237 * Else, if no fault conditions are present, issue a MessageUnitReset
2238 * Else, fall through to KickStart case
2240 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2241 dinitprintk((KERN_INFO MYNAM
2242 ": whoinit 0x%x statefault %d force %d\n",
2243 whoinit, statefault, force));
2244 if (whoinit == MPI_WHOINIT_PCI_PEER)
2247 if ((statefault == 0 ) && (force == 0)) {
2248 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2255 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2256 if (hard_reset_done < 0)
2260 * Loop here waiting for IOC to come READY.
2263 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2265 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2266 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2268 * BIOS or previous driver load left IOC in OP state.
2269 * Reset messaging FIFOs.
2271 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2272 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2275 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2277 * Something is wrong. Try to get IOC back
2280 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2281 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2288 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2289 ioc->name, (int)((ii+5)/HZ));
2293 if (sleepFlag == CAN_SLEEP) {
2294 msleep_interruptible(1);
2296 mdelay (1); /* 1 msec delay */
2301 if (statefault < 3) {
2302 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2304 statefault==1 ? "stuck handshake" : "IOC FAULT");
2307 return hard_reset_done;
2310 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2312 * mpt_GetIocState - Get the current state of a MPT adapter.
2313 * @ioc: Pointer to MPT_ADAPTER structure
2314 * @cooked: Request raw or cooked IOC state
2316 * Returns all IOC Doorbell register bits if cooked==0, else just the
2317 * Doorbell bits in MPI_IOC_STATE_MASK.
2320 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2325 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2326 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2327 sc = s & MPI_IOC_STATE_MASK;
2330 ioc->last_state = sc;
2332 return cooked ? sc : s;
2335 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2337 * GetIocFacts - Send IOCFacts request to MPT adapter.
2338 * @ioc: Pointer to MPT_ADAPTER structure
2339 * @sleepFlag: Specifies whether the process can sleep
2340 * @reason: If recovery, only update facts.
2342 * Returns 0 for success, non-zero for failure.
2345 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2347 IOCFacts_t get_facts;
2348 IOCFactsReply_t *facts;
2356 /* IOC *must* NOT be in RESET state! */
2357 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2358 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2364 facts = &ioc->facts;
2366 /* Destination (reply area)... */
2367 reply_sz = sizeof(*facts);
2368 memset(facts, 0, reply_sz);
2370 /* Request area (get_facts on the stack right now!) */
2371 req_sz = sizeof(get_facts);
2372 memset(&get_facts, 0, req_sz);
2374 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2375 /* Assert: All other get_facts fields are zero! */
2377 dinitprintk((MYIOC_s_INFO_FMT
2378 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2379 ioc->name, req_sz, reply_sz));
2381 /* No non-zero fields in the get_facts request are greater than
2382 * 1 byte in size, so we can just fire it off as is.
2384 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2385 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2390 * Now byte swap (GRRR) the necessary fields before any further
2391 * inspection of reply contents.
2393 * But need to do some sanity checks on MsgLength (byte) field
2394 * to make sure we don't zero IOC's req_sz!
2396 /* Did we get a valid reply? */
2397 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2398 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2400 * If not been here, done that, save off first WhoInit value
2402 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2403 ioc->FirstWhoInit = facts->WhoInit;
2406 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2407 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2408 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2409 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2410 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2411 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2412 /* CHECKME! IOCStatus, IOCLogInfo */
2414 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2415 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2418 * FC f/w version changed between 1.1 and 1.2
2419 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2420 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2422 if (facts->MsgVersion < 0x0102) {
2424 * Handle old FC f/w style, convert to new...
2426 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2427 facts->FWVersion.Word =
2428 ((oldv<<12) & 0xFF000000) |
2429 ((oldv<<8) & 0x000FFF00);
2431 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2433 facts->ProductID = le16_to_cpu(facts->ProductID);
2434 facts->CurrentHostMfaHighAddr =
2435 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2436 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2437 facts->CurrentSenseBufferHighAddr =
2438 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2439 facts->CurReplyFrameSize =
2440 le16_to_cpu(facts->CurReplyFrameSize);
2441 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2444 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2445 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2446 * to 14 in MPI-1.01.0x.
2448 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2449 facts->MsgVersion > 0x0100) {
2450 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2453 sz = facts->FWImageSize;
2458 facts->FWImageSize = sz;
2460 if (!facts->RequestFrameSize) {
2461 /* Something is wrong! */
2462 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2467 r = sz = facts->BlockSize;
2468 vv = ((63 / (sz * 4)) + 1) & 0x03;
2469 ioc->NB_for_64_byte_frame = vv;
2475 ioc->NBShiftFactor = shiftFactor;
2476 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2477 ioc->name, vv, shiftFactor, r));
2479 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2481 * Set values for this IOC's request & reply frame sizes,
2482 * and request & reply queue depths...
2484 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2485 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2486 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2487 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2489 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2490 ioc->name, ioc->reply_sz, ioc->reply_depth));
2491 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2492 ioc->name, ioc->req_sz, ioc->req_depth));
2494 /* Get port facts! */
2495 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2499 printk(MYIOC_s_ERR_FMT
2500 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2501 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2502 RequestFrameSize)/sizeof(u32)));
2509 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2511 * GetPortFacts - Send PortFacts request to MPT adapter.
2512 * @ioc: Pointer to MPT_ADAPTER structure
2513 * @portnum: Port number
2514 * @sleepFlag: Specifies whether the process can sleep
2516 * Returns 0 for success, non-zero for failure.
2519 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2521 PortFacts_t get_pfacts;
2522 PortFactsReply_t *pfacts;
2527 /* IOC *must* NOT be in RESET state! */
2528 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2529 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2535 pfacts = &ioc->pfacts[portnum];
2537 /* Destination (reply area)... */
2538 reply_sz = sizeof(*pfacts);
2539 memset(pfacts, 0, reply_sz);
2541 /* Request area (get_pfacts on the stack right now!) */
2542 req_sz = sizeof(get_pfacts);
2543 memset(&get_pfacts, 0, req_sz);
2545 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2546 get_pfacts.PortNumber = portnum;
2547 /* Assert: All other get_pfacts fields are zero! */
2549 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2550 ioc->name, portnum));
2552 /* No non-zero fields in the get_pfacts request are greater than
2553 * 1 byte in size, so we can just fire it off as is.
2555 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2556 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2560 /* Did we get a valid reply? */
2562 /* Now byte swap the necessary fields in the response. */
2563 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2564 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2565 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2566 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2567 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2568 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2569 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2570 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2571 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2576 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2578 * SendIocInit - Send IOCInit request to MPT adapter.
2579 * @ioc: Pointer to MPT_ADAPTER structure
2580 * @sleepFlag: Specifies whether the process can sleep
2582 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2584 * Returns 0 for success, non-zero for failure.
2587 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2590 MPIDefaultReply_t init_reply;
2596 memset(&ioc_init, 0, sizeof(ioc_init));
2597 memset(&init_reply, 0, sizeof(init_reply));
2599 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2600 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2602 /* If we are in a recovery mode and we uploaded the FW image,
2603 * then this pointer is not NULL. Skip the upload a second time.
2604 * Set this flag if cached_fw set for either IOC.
2606 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2610 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2611 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2613 if(ioc->bus_type == SAS)
2614 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2615 else if(ioc->bus_type == FC)
2616 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2618 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2619 ioc_init.MaxBuses = MPT_MAX_BUS;
2620 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2621 ioc->name, ioc->facts.MsgVersion));
2622 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2623 // set MsgVersion and HeaderVersion host driver was built with
2624 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2625 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2627 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2628 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2629 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2632 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2634 if (sizeof(dma_addr_t) == sizeof(u64)) {
2635 /* Save the upper 32-bits of the request
2636 * (reply) and sense buffers.
2638 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2639 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2641 /* Force 32-bit addressing */
2642 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2643 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2646 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2647 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2648 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2649 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2651 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2652 ioc->name, &ioc_init));
2654 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2655 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2657 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2661 /* No need to byte swap the multibyte fields in the reply
2662 * since we don't even look at it's contents.
2665 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2666 ioc->name, &ioc_init));
2668 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2669 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2673 /* YIKES! SUPER IMPORTANT!!!
2674 * Poll IocState until _OPERATIONAL while IOC is doing
2675 * LoopInit and TargetDiscovery!
2678 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2679 state = mpt_GetIocState(ioc, 1);
2680 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2681 if (sleepFlag == CAN_SLEEP) {
2682 msleep_interruptible(1);
2688 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2689 ioc->name, (int)((count+5)/HZ));
2693 state = mpt_GetIocState(ioc, 1);
2696 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2702 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2704 * SendPortEnable - Send PortEnable request to MPT adapter port.
2705 * @ioc: Pointer to MPT_ADAPTER structure
2706 * @portnum: Port number to enable
2707 * @sleepFlag: Specifies whether the process can sleep
2709 * Send PortEnable to bring IOC to OPERATIONAL state.
2711 * Returns 0 for success, non-zero for failure.
2714 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2716 PortEnable_t port_enable;
2717 MPIDefaultReply_t reply_buf;
2722 /* Destination... */
2723 reply_sz = sizeof(MPIDefaultReply_t);
2724 memset(&reply_buf, 0, reply_sz);
2726 req_sz = sizeof(PortEnable_t);
2727 memset(&port_enable, 0, req_sz);
2729 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2730 port_enable.PortNumber = portnum;
2731 /* port_enable.ChainOffset = 0; */
2732 /* port_enable.MsgFlags = 0; */
2733 /* port_enable.MsgContext = 0; */
2735 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2736 ioc->name, portnum, &port_enable));
2738 /* RAID FW may take a long time to enable
2740 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2741 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2742 (ioc->bus_type == SAS)) {
2743 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2744 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2745 300 /*seconds*/, sleepFlag);
2747 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2748 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2749 30 /*seconds*/, sleepFlag);
2755 * ioc: Pointer to MPT_ADAPTER structure
2756 * size - total FW bytes
2759 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2762 return; /* use already allocated memory */
2763 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2764 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2765 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2767 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2768 ioc->alloc_total += size;
2772 * If alt_img is NULL, delete from ioc structure.
2773 * Else, delete a secondary image in same format.
2776 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2780 sz = ioc->facts.FWImageSize;
2781 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2782 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2783 pci_free_consistent(ioc->pcidev, sz,
2784 ioc->cached_fw, ioc->cached_fw_dma);
2785 ioc->cached_fw = NULL;
2791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2793 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2794 * @ioc: Pointer to MPT_ADAPTER structure
2795 * @sleepFlag: Specifies whether the process can sleep
2797 * Returns 0 for success, >0 for handshake failure
2798 * <0 for fw upload failure.
2800 * Remark: If bound IOC and a successful FWUpload was performed
2801 * on the bound IOC, the second image is discarded
2802 * and memory is free'd. Both channels must upload to prevent
2803 * IOC from running in degraded mode.
2806 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2808 u8 request[ioc->req_sz];
2809 u8 reply[sizeof(FWUploadReply_t)];
2810 FWUpload_t *prequest;
2811 FWUploadReply_t *preply;
2812 FWUploadTCSGE_t *ptcsge;
2815 int ii, sz, reply_sz;
2818 /* If the image size is 0, we are done.
2820 if ((sz = ioc->facts.FWImageSize) == 0)
2823 mpt_alloc_fw_memory(ioc, sz);
2825 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2826 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2828 if (ioc->cached_fw == NULL) {
2834 prequest = (FWUpload_t *)&request;
2835 preply = (FWUploadReply_t *)&reply;
2837 /* Destination... */
2838 memset(prequest, 0, ioc->req_sz);
2840 reply_sz = sizeof(reply);
2841 memset(preply, 0, reply_sz);
2843 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2844 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2846 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2847 ptcsge->DetailsLength = 12;
2848 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2849 ptcsge->ImageSize = cpu_to_le32(sz);
2851 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2853 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2854 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2856 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2857 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2858 prequest, sgeoffset));
2859 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2861 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2862 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2864 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2866 cmdStatus = -EFAULT;
2868 /* Handshake transfer was complete and successful.
2869 * Check the Reply Frame.
2871 int status, transfer_sz;
2872 status = le16_to_cpu(preply->IOCStatus);
2873 if (status == MPI_IOCSTATUS_SUCCESS) {
2874 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2875 if (transfer_sz == sz)
2879 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2880 ioc->name, cmdStatus));
2885 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2887 mpt_free_fw_memory(ioc);
2893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2895 * mpt_downloadboot - DownloadBoot code
2896 * @ioc: Pointer to MPT_ADAPTER structure
2897 * @flag: Specify which part of IOC memory is to be uploaded.
2898 * @sleepFlag: Specifies whether the process can sleep
2900 * FwDownloadBoot requires Programmed IO access.
2902 * Returns 0 for success
2903 * -1 FW Image size is 0
2904 * -2 No valid cached_fw Pointer
2905 * <0 for fw upload failure.
2908 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2910 MpiExtImageHeader_t *pExtImage;
2920 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2921 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2923 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2924 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2925 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2926 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2927 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2928 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2930 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2933 if (sleepFlag == CAN_SLEEP) {
2934 msleep_interruptible(1);
2939 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2940 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2942 for (count = 0; count < 30; count ++) {
2943 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2944 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2945 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2950 if (sleepFlag == CAN_SLEEP) {
2951 msleep_interruptible (100);
2957 if ( count == 30 ) {
2958 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2959 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2960 ioc->name, diag0val));
2964 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2965 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2966 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2967 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2968 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2969 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2971 /* Set the DiagRwEn and Disable ARM bits */
2972 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2974 fwSize = (pFwHeader->ImageSize + 3)/4;
2975 ptrFw = (u32 *) pFwHeader;
2977 /* Write the LoadStartAddress to the DiagRw Address Register
2978 * using Programmed IO
2980 if (ioc->errata_flag_1064)
2981 pci_enable_io_access(ioc->pcidev);
2983 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2984 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2985 ioc->name, pFwHeader->LoadStartAddress));
2987 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2988 ioc->name, fwSize*4, ptrFw));
2990 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2993 nextImage = pFwHeader->NextImageHeaderOffset;
2995 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2997 load_addr = pExtImage->LoadStartAddress;
2999 fwSize = (pExtImage->ImageSize + 3) >> 2;
3000 ptrFw = (u32 *)pExtImage;
3002 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3003 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3004 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3007 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3009 nextImage = pExtImage->NextImageHeaderOffset;
3012 /* Write the IopResetVectorRegAddr */
3013 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3014 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3016 /* Write the IopResetVectorValue */
3017 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3018 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3020 /* Clear the internal flash bad bit - autoincrementing register,
3021 * so must do two writes.
3023 if (ioc->bus_type == SPI) {
3025 * 1030 and 1035 H/W errata, workaround to access
3026 * the ClearFlashBadSignatureBit
3028 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3029 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3030 diagRwData |= 0x40000000;
3031 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3032 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3034 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3035 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3036 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3037 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3040 if (sleepFlag == CAN_SLEEP) {
3041 msleep_interruptible (1);
3047 if (ioc->errata_flag_1064)
3048 pci_disable_io_access(ioc->pcidev);
3050 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3051 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3052 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3053 ioc->name, diag0val));
3054 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3055 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3056 ioc->name, diag0val));
3057 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3059 /* Write 0xFF to reset the sequencer */
3060 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3062 if (ioc->bus_type == SAS) {
3063 ioc_state = mpt_GetIocState(ioc, 0);
3064 if ( (GetIocFacts(ioc, sleepFlag,
3065 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3066 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3067 ioc->name, ioc_state));
3072 for (count=0; count<HZ*20; count++) {
3073 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3074 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3075 ioc->name, count, ioc_state));
3076 if (ioc->bus_type == SAS) {
3079 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3080 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3084 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3088 if (sleepFlag == CAN_SLEEP) {
3089 msleep_interruptible (10);
3094 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3095 ioc->name, ioc_state));
3099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3101 * KickStart - Perform hard reset of MPT adapter.
3102 * @ioc: Pointer to MPT_ADAPTER structure
3103 * @force: Force hard reset
3104 * @sleepFlag: Specifies whether the process can sleep
3106 * This routine places MPT adapter in diagnostic mode via the
3107 * WriteSequence register, and then performs a hard reset of adapter
3108 * via the Diagnostic register.
3110 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3111 * or NO_SLEEP (interrupt thread, use mdelay)
3112 * force - 1 if doorbell active, board fault state
3113 * board operational, IOC_RECOVERY or
3114 * IOC_BRINGUP and there is an alt_ioc.
3118 * 1 - hard reset, READY
3119 * 0 - no reset due to History bit, READY
3120 * -1 - no reset due to History bit but not READY
3121 * OR reset but failed to come READY
3122 * -2 - no reset, could not enter DIAG mode
3123 * -3 - reset but bad FW bit
3126 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3128 int hard_reset_done = 0;
3132 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3133 if (ioc->bus_type == SPI) {
3134 /* Always issue a Msg Unit Reset first. This will clear some
3135 * SCSI bus hang conditions.
3137 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3139 if (sleepFlag == CAN_SLEEP) {
3140 msleep_interruptible (1000);
3146 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3147 if (hard_reset_done < 0)
3148 return hard_reset_done;
3150 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3153 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3154 for (cnt=0; cnt<cntdn; cnt++) {
3155 ioc_state = mpt_GetIocState(ioc, 1);
3156 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3157 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3159 return hard_reset_done;
3161 if (sleepFlag == CAN_SLEEP) {
3162 msleep_interruptible (10);
3168 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3169 ioc->name, ioc_state);
3173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3175 * mpt_diag_reset - Perform hard reset of the adapter.
3176 * @ioc: Pointer to MPT_ADAPTER structure
3177 * @ignore: Set if to honor and clear to ignore
3178 * the reset history bit
3179 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3180 * else set to NO_SLEEP (use mdelay instead)
3182 * This routine places the adapter in diagnostic mode via the
3183 * WriteSequence register and then performs a hard reset of adapter
3184 * via the Diagnostic register. Adapter should be in ready state
3185 * upon successful completion.
3187 * Returns: 1 hard reset successful
3188 * 0 no reset performed because reset history bit set
3189 * -2 enabling diagnostic mode failed
3190 * -3 diagnostic reset failed
3193 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3197 int hard_reset_done = 0;
3203 /* Clear any existing interrupts */
3204 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3206 /* Use "Diagnostic reset" method! (only thing available!) */
3207 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3211 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3212 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3213 ioc->name, diag0val, diag1val));
3216 /* Do the reset if we are told to ignore the reset history
3217 * or if the reset history is 0
3219 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3220 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3221 /* Write magic sequence to WriteSequence register
3222 * Loop until in diagnostic mode
3224 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3225 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3226 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3227 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3228 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3229 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3232 if (sleepFlag == CAN_SLEEP) {
3233 msleep_interruptible (100);
3240 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3241 ioc->name, diag0val);
3246 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3248 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3249 ioc->name, diag0val));
3254 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3255 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3256 ioc->name, diag0val, diag1val));
3259 * Disable the ARM (Bug fix)
3262 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3266 * Now hit the reset bit in the Diagnostic register
3267 * (THE BIG HAMMER!) (Clears DRWE bit).
3269 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3270 hard_reset_done = 1;
3271 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3275 * Call each currently registered protocol IOC reset handler
3276 * with pre-reset indication.
3277 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3278 * MptResetHandlers[] registered yet.
3284 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3285 if (MptResetHandlers[ii]) {
3286 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3288 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3290 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3291 ioc->name, ioc->alt_ioc->name, ii));
3292 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3296 /* FIXME? Examine results here? */
3299 if (ioc->cached_fw) {
3300 /* If the DownloadBoot operation fails, the
3301 * IOC will be left unusable. This is a fatal error
3302 * case. _diag_reset will return < 0
3304 for (count = 0; count < 30; count ++) {
3305 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3306 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3311 if (sleepFlag == CAN_SLEEP) {
3312 msleep_interruptible (1000);
3317 if ((count = mpt_downloadboot(ioc,
3318 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3319 printk(KERN_WARNING MYNAM
3320 ": firmware downloadboot failure (%d)!\n", count);
3324 /* Wait for FW to reload and for board
3325 * to go to the READY state.
3326 * Maximum wait is 60 seconds.
3327 * If fail, no error will check again
3328 * with calling program.
3330 for (count = 0; count < 60; count ++) {
3331 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3332 doorbell &= MPI_IOC_STATE_MASK;
3334 if (doorbell == MPI_IOC_STATE_READY) {
3339 if (sleepFlag == CAN_SLEEP) {
3340 msleep_interruptible (1000);
3348 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3351 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3352 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3353 ioc->name, diag0val, diag1val));
3356 /* Clear RESET_HISTORY bit! Place board in the
3357 * diagnostic mode to update the diag register.
3359 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3361 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3362 /* Write magic sequence to WriteSequence register
3363 * Loop until in diagnostic mode
3365 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3366 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3367 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3368 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3369 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3370 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3373 if (sleepFlag == CAN_SLEEP) {
3374 msleep_interruptible (100);
3381 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3382 ioc->name, diag0val);
3385 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3387 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3388 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3389 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3390 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3391 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3395 /* Disable Diagnostic Mode
3397 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3399 /* Check FW reload status flags.
3401 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3402 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3403 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3404 ioc->name, diag0val);
3410 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3411 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3412 ioc->name, diag0val, diag1val));
3416 * Reset flag that says we've enabled event notification
3418 ioc->facts.EventState = 0;
3421 ioc->alt_ioc->facts.EventState = 0;
3423 return hard_reset_done;
3426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3428 * SendIocReset - Send IOCReset request to MPT adapter.
3429 * @ioc: Pointer to MPT_ADAPTER structure
3430 * @reset_type: reset type, expected values are
3431 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3433 * Send IOCReset request to the MPT adapter.
3435 * Returns 0 for success, non-zero for failure.
3438 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3444 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3445 ioc->name, reset_type));
3446 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3447 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3450 /* FW ACK'd request, wait for READY state
3453 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3455 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3459 if (sleepFlag != CAN_SLEEP)
3462 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3463 ioc->name, (int)((count+5)/HZ));
3467 if (sleepFlag == CAN_SLEEP) {
3468 msleep_interruptible(1);
3470 mdelay (1); /* 1 msec delay */
3475 * Cleanup all event stuff for this IOC; re-issue EventNotification
3476 * request if needed.
3478 if (ioc->facts.Function)
3479 ioc->facts.EventState = 0;
3484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3486 * initChainBuffers - Allocate memory for and initialize
3487 * chain buffers, chain buffer control arrays and spinlock.
3488 * @hd: Pointer to MPT_SCSI_HOST structure
3489 * @init: If set, initialize the spin lock.
3492 initChainBuffers(MPT_ADAPTER *ioc)
3495 int sz, ii, num_chain;
3496 int scale, num_sge, numSGE;
3498 /* ReqToChain size must equal the req_depth
3501 if (ioc->ReqToChain == NULL) {
3502 sz = ioc->req_depth * sizeof(int);
3503 mem = kmalloc(sz, GFP_ATOMIC);
3507 ioc->ReqToChain = (int *) mem;
3508 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3509 ioc->name, mem, sz));
3510 mem = kmalloc(sz, GFP_ATOMIC);
3514 ioc->RequestNB = (int *) mem;
3515 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3516 ioc->name, mem, sz));
3518 for (ii = 0; ii < ioc->req_depth; ii++) {
3519 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3522 /* ChainToChain size must equal the total number
3523 * of chain buffers to be allocated.
3526 * Calculate the number of chain buffers needed(plus 1) per I/O
3527 * then multiply the the maximum number of simultaneous cmds
3529 * num_sge = num sge in request frame + last chain buffer
3530 * scale = num sge per chain buffer if no chain element
3532 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3533 if (sizeof(dma_addr_t) == sizeof(u64))
3534 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3536 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3538 if (sizeof(dma_addr_t) == sizeof(u64)) {
3539 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3540 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3542 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3543 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3545 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3546 ioc->name, num_sge, numSGE));
3548 if ( numSGE > MPT_SCSI_SG_DEPTH )
3549 numSGE = MPT_SCSI_SG_DEPTH;
3552 while (numSGE - num_sge > 0) {
3554 num_sge += (scale - 1);
3558 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3559 ioc->name, numSGE, num_sge, num_chain));
3561 if (ioc->bus_type == SPI)
3562 num_chain *= MPT_SCSI_CAN_QUEUE;
3564 num_chain *= MPT_FC_CAN_QUEUE;
3566 ioc->num_chain = num_chain;
3568 sz = num_chain * sizeof(int);
3569 if (ioc->ChainToChain == NULL) {
3570 mem = kmalloc(sz, GFP_ATOMIC);
3574 ioc->ChainToChain = (int *) mem;
3575 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3576 ioc->name, mem, sz));
3578 mem = (u8 *) ioc->ChainToChain;
3580 memset(mem, 0xFF, sz);
3584 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3586 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3587 * @ioc: Pointer to MPT_ADAPTER structure
3589 * This routine allocates memory for the MPT reply and request frame
3590 * pools (if necessary), and primes the IOC reply FIFO with
3593 * Returns 0 for success, non-zero for failure.
3596 PrimeIocFifos(MPT_ADAPTER *ioc)
3599 unsigned long flags;
3600 dma_addr_t alloc_dma;
3602 int i, reply_sz, sz, total_size, num_chain;
3604 /* Prime reply FIFO... */
3606 if (ioc->reply_frames == NULL) {
3607 if ( (num_chain = initChainBuffers(ioc)) < 0)
3610 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3611 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3612 ioc->name, ioc->reply_sz, ioc->reply_depth));
3613 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3614 ioc->name, reply_sz, reply_sz));
3616 sz = (ioc->req_sz * ioc->req_depth);
3617 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3618 ioc->name, ioc->req_sz, ioc->req_depth));
3619 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3620 ioc->name, sz, sz));
3623 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3624 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3625 ioc->name, ioc->req_sz, num_chain));
3626 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3627 ioc->name, sz, sz, num_chain));
3630 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3632 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3637 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3638 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3640 memset(mem, 0, total_size);
3641 ioc->alloc_total += total_size;
3643 ioc->alloc_dma = alloc_dma;
3644 ioc->alloc_sz = total_size;
3645 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3646 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3648 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3649 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3651 alloc_dma += reply_sz;
3654 /* Request FIFO - WE manage this! */
3656 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3657 ioc->req_frames_dma = alloc_dma;
3659 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3660 ioc->name, mem, (void *)(ulong)alloc_dma));
3662 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3664 #if defined(CONFIG_MTRR) && 0
3666 * Enable Write Combining MTRR for IOC's memory region.
3667 * (at least as much as we can; "size and base must be
3668 * multiples of 4 kiB"
3670 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3672 MTRR_TYPE_WRCOMB, 1);
3673 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3674 ioc->name, ioc->req_frames_dma, sz));
3677 for (i = 0; i < ioc->req_depth; i++) {
3678 alloc_dma += ioc->req_sz;
3682 ioc->ChainBuffer = mem;
3683 ioc->ChainBufferDMA = alloc_dma;
3685 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3686 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3688 /* Initialize the free chain Q.
3691 INIT_LIST_HEAD(&ioc->FreeChainQ);
3693 /* Post the chain buffers to the FreeChainQ.
3695 mem = (u8 *)ioc->ChainBuffer;
3696 for (i=0; i < num_chain; i++) {
3697 mf = (MPT_FRAME_HDR *) mem;
3698 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3702 /* Initialize Request frames linked list
3704 alloc_dma = ioc->req_frames_dma;
3705 mem = (u8 *) ioc->req_frames;
3707 spin_lock_irqsave(&ioc->FreeQlock, flags);
3708 INIT_LIST_HEAD(&ioc->FreeQ);
3709 for (i = 0; i < ioc->req_depth; i++) {
3710 mf = (MPT_FRAME_HDR *) mem;
3712 /* Queue REQUESTs *internally*! */
3713 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3717 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3719 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3720 ioc->sense_buf_pool =
3721 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3722 if (ioc->sense_buf_pool == NULL) {
3723 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3728 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3729 ioc->alloc_total += sz;
3730 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3731 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3735 /* Post Reply frames to FIFO
3737 alloc_dma = ioc->alloc_dma;
3738 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3739 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3741 for (i = 0; i < ioc->reply_depth; i++) {
3742 /* Write each address to the IOC! */
3743 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3744 alloc_dma += ioc->reply_sz;
3750 if (ioc->alloc != NULL) {
3752 pci_free_consistent(ioc->pcidev,
3754 ioc->alloc, ioc->alloc_dma);
3755 ioc->reply_frames = NULL;
3756 ioc->req_frames = NULL;
3757 ioc->alloc_total -= sz;
3759 if (ioc->sense_buf_pool != NULL) {
3760 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3761 pci_free_consistent(ioc->pcidev,
3763 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3764 ioc->sense_buf_pool = NULL;
3769 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3771 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3772 * from IOC via doorbell handshake method.
3773 * @ioc: Pointer to MPT_ADAPTER structure
3774 * @reqBytes: Size of the request in bytes
3775 * @req: Pointer to MPT request frame
3776 * @replyBytes: Expected size of the reply in bytes
3777 * @u16reply: Pointer to area where reply should be written
3778 * @maxwait: Max wait time for a reply (in seconds)
3779 * @sleepFlag: Specifies whether the process can sleep
3781 * NOTES: It is the callers responsibility to byte-swap fields in the
3782 * request which are greater than 1 byte in size. It is also the
3783 * callers responsibility to byte-swap response fields which are
3784 * greater than 1 byte in size.
3786 * Returns 0 for success, non-zero for failure.
3789 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3790 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3792 MPIDefaultReply_t *mptReply;
3797 * Get ready to cache a handshake reply
3799 ioc->hs_reply_idx = 0;
3800 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3801 mptReply->MsgLength = 0;
3804 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3805 * then tell IOC that we want to handshake a request of N words.
3806 * (WRITE u32val to Doorbell reg).
3808 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3809 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3810 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3811 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3814 * Wait for IOC's doorbell handshake int
3816 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3819 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3820 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3822 /* Read doorbell and check for active bit */
3823 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3827 * Clear doorbell int (WRITE 0 to IntStatus reg),
3828 * then wait for IOC to ACKnowledge that it's ready for
3829 * our handshake request.
3831 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3832 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3837 u8 *req_as_bytes = (u8 *) req;
3840 * Stuff request words via doorbell handshake,
3841 * with ACK from IOC for each.
3843 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3844 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3845 (req_as_bytes[(ii*4) + 1] << 8) |
3846 (req_as_bytes[(ii*4) + 2] << 16) |
3847 (req_as_bytes[(ii*4) + 3] << 24));
3849 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3850 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3854 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3855 DBG_DUMP_REQUEST_FRAME_HDR(req)
3857 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3858 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3861 * Wait for completion of doorbell handshake reply from the IOC
3863 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3866 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3867 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3870 * Copy out the cached reply...
3872 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3873 u16reply[ii] = ioc->hs_reply[ii];
3881 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3883 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3884 * in it's IntStatus register.
3885 * @ioc: Pointer to MPT_ADAPTER structure
3886 * @howlong: How long to wait (in seconds)
3887 * @sleepFlag: Specifies whether the process can sleep
3889 * This routine waits (up to ~2 seconds max) for IOC doorbell
3890 * handshake ACKnowledge.
3892 * Returns a negative value on failure, else wait loop count.
3895 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3901 cntdn = 1000 * howlong;
3903 if (sleepFlag == CAN_SLEEP) {
3905 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3906 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3908 msleep_interruptible (1);
3913 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3914 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3922 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3927 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3928 ioc->name, count, intstat);
3932 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3934 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3935 * in it's IntStatus register.
3936 * @ioc: Pointer to MPT_ADAPTER structure
3937 * @howlong: How long to wait (in seconds)
3938 * @sleepFlag: Specifies whether the process can sleep
3940 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3942 * Returns a negative value on failure, else wait loop count.
3945 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3951 cntdn = 1000 * howlong;
3952 if (sleepFlag == CAN_SLEEP) {
3954 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3955 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3957 msleep_interruptible(1);
3962 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3963 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3971 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3972 ioc->name, count, howlong));
3976 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3977 ioc->name, count, intstat);
3981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3983 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3984 * @ioc: Pointer to MPT_ADAPTER structure
3985 * @howlong: How long to wait (in seconds)
3986 * @sleepFlag: Specifies whether the process can sleep
3988 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3989 * Reply is cached to IOC private area large enough to hold a maximum
3990 * of 128 bytes of reply data.
3992 * Returns a negative value on failure, else size of reply in WORDS.
3995 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4000 u16 *hs_reply = ioc->hs_reply;
4001 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4004 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4007 * Get first two u16's so we can look at IOC's intended reply MsgLength
4010 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4013 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4014 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4015 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4018 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4019 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4023 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4024 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4025 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4028 * If no error (and IOC said MsgLength is > 0), piece together
4029 * reply 16 bits at a time.
4031 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4032 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4034 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4035 /* don't overflow our IOC hs_reply[] buffer! */
4036 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4037 hs_reply[u16cnt] = hword;
4038 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4041 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4043 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4046 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4051 else if (u16cnt != (2 * mptReply->MsgLength)) {
4054 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4059 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4060 DBG_DUMP_REPLY_FRAME(mptReply)
4062 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4063 ioc->name, t, u16cnt/2));
4067 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4069 * GetLanConfigPages - Fetch LANConfig pages.
4070 * @ioc: Pointer to MPT_ADAPTER structure
4072 * Return: 0 for success
4073 * -ENOMEM if no memory available
4074 * -EPERM if not allowed due to ISR context
4075 * -EAGAIN if no msg frames currently available
4076 * -EFAULT for non-successful reply or no reply (timeout)
4079 GetLanConfigPages(MPT_ADAPTER *ioc)
4081 ConfigPageHeader_t hdr;
4083 LANPage0_t *ppage0_alloc;
4084 dma_addr_t page0_dma;
4085 LANPage1_t *ppage1_alloc;
4086 dma_addr_t page1_dma;
4091 /* Get LAN Page 0 header */
4092 hdr.PageVersion = 0;
4095 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4096 cfg.cfghdr.hdr = &hdr;
4098 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4103 if ((rc = mpt_config(ioc, &cfg)) != 0)
4106 if (hdr.PageLength > 0) {
4107 data_sz = hdr.PageLength * 4;
4108 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4111 memset((u8 *)ppage0_alloc, 0, data_sz);
4112 cfg.physAddr = page0_dma;
4113 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4115 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4117 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4118 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4122 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4125 * Normalize endianness of structure data,
4126 * by byte-swapping all > 1 byte fields!
4135 /* Get LAN Page 1 header */
4136 hdr.PageVersion = 0;
4139 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4140 cfg.cfghdr.hdr = &hdr;
4142 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4146 if ((rc = mpt_config(ioc, &cfg)) != 0)
4149 if (hdr.PageLength == 0)
4152 data_sz = hdr.PageLength * 4;
4154 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4156 memset((u8 *)ppage1_alloc, 0, data_sz);
4157 cfg.physAddr = page1_dma;
4158 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4160 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4162 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4163 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4166 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4169 * Normalize endianness of structure data,
4170 * by byte-swapping all > 1 byte fields!
4178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4180 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4181 * @ioc: Pointer to MPT_ADAPTER structure
4182 * @sas_address: 64bit SAS Address for operation.
4183 * @target_id: specified target for operation
4184 * @bus: specified bus for operation
4185 * @persist_opcode: see below
4187 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4188 * devices not currently present.
4189 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4191 * NOTE: Don't use not this function during interrupt time.
4193 * Returns: 0 for success, non-zero error
4196 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4198 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4200 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4201 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4202 MPT_FRAME_HDR *mf = NULL;
4203 MPIHeader_t *mpi_hdr;
4206 /* insure garbage is not sent to fw */
4207 switch(persist_opcode) {
4209 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4210 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4218 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4220 /* Get a MF for this command.
4222 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4223 printk("%s: no msg frames!\n",__FUNCTION__);
4227 mpi_hdr = (MPIHeader_t *) mf;
4228 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4229 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4230 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4231 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4232 sasIoUnitCntrReq->Operation = persist_opcode;
4234 init_timer(&ioc->persist_timer);
4235 ioc->persist_timer.data = (unsigned long) ioc;
4236 ioc->persist_timer.function = mpt_timer_expired;
4237 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4238 ioc->persist_wait_done=0;
4239 add_timer(&ioc->persist_timer);
4240 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4241 wait_event(mpt_waitq, ioc->persist_wait_done);
4243 sasIoUnitCntrReply =
4244 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4245 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4246 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4248 sasIoUnitCntrReply->IOCStatus,
4249 sasIoUnitCntrReply->IOCLogInfo);
4253 printk("%s: success\n",__FUNCTION__);
4257 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4260 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4261 MpiEventDataRaid_t * pRaidEventData)
4270 volume = pRaidEventData->VolumeID;
4271 reason = pRaidEventData->ReasonCode;
4272 disk = pRaidEventData->PhysDiskNum;
4273 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4274 flags = (status >> 0) & 0xff;
4275 state = (status >> 8) & 0xff;
4277 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4281 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4282 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4283 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4284 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4287 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4292 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4293 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4297 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4299 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4303 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4304 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4308 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4309 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4311 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4313 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4315 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4318 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4320 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4321 ? ", quiesced" : "",
4322 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4323 ? ", resync in progress" : "" );
4326 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4327 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4331 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4332 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4336 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4337 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4341 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4342 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4346 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4347 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4349 state == MPI_PHYSDISK0_STATUS_ONLINE
4351 : state == MPI_PHYSDISK0_STATUS_MISSING
4353 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4355 : state == MPI_PHYSDISK0_STATUS_FAILED
4357 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4359 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4360 ? "offline requested"
4361 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4362 ? "failed requested"
4363 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4366 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4367 ? ", out of sync" : "",
4368 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4369 ? ", quiesced" : "" );
4372 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4373 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4377 case MPI_EVENT_RAID_RC_SMART_DATA:
4378 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4379 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4382 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4383 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4391 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4392 * @ioc: Pointer to MPT_ADAPTER structure
4394 * Returns: 0 for success
4395 * -ENOMEM if no memory available
4396 * -EPERM if not allowed due to ISR context
4397 * -EAGAIN if no msg frames currently available
4398 * -EFAULT for non-successful reply or no reply (timeout)
4401 GetIoUnitPage2(MPT_ADAPTER *ioc)
4403 ConfigPageHeader_t hdr;
4405 IOUnitPage2_t *ppage_alloc;
4406 dma_addr_t page_dma;
4410 /* Get the page header */
4411 hdr.PageVersion = 0;
4414 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4415 cfg.cfghdr.hdr = &hdr;
4417 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4422 if ((rc = mpt_config(ioc, &cfg)) != 0)
4425 if (hdr.PageLength == 0)
4428 /* Read the config page */
4429 data_sz = hdr.PageLength * 4;
4431 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4433 memset((u8 *)ppage_alloc, 0, data_sz);
4434 cfg.physAddr = page_dma;
4435 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4437 /* If Good, save data */
4438 if ((rc = mpt_config(ioc, &cfg)) == 0)
4439 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4441 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4447 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4448 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4449 * @ioc: Pointer to a Adapter Strucutre
4450 * @portnum: IOC port number
4452 * Return: -EFAULT if read of config page header fails
4454 * If read of SCSI Port Page 0 fails,
4455 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4456 * Adapter settings: async, narrow
4458 * If read of SCSI Port Page 2 fails,
4459 * Adapter settings valid
4460 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4465 * CHECK - what type of locking mechanisms should be used????
4468 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4473 ConfigPageHeader_t header;
4479 if (!ioc->spi_data.nvram) {
4482 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4483 mem = kmalloc(sz, GFP_ATOMIC);
4487 ioc->spi_data.nvram = (int *) mem;
4489 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4490 ioc->name, ioc->spi_data.nvram, sz));
4493 /* Invalidate NVRAM information
4495 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4496 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4499 /* Read SPP0 header, allocate memory, then read page.
4501 header.PageVersion = 0;
4502 header.PageLength = 0;
4503 header.PageNumber = 0;
4504 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4505 cfg.cfghdr.hdr = &header;
4507 cfg.pageAddr = portnum;
4508 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4510 cfg.timeout = 0; /* use default */
4511 if (mpt_config(ioc, &cfg) != 0)
4514 if (header.PageLength > 0) {
4515 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4517 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4518 cfg.physAddr = buf_dma;
4519 if (mpt_config(ioc, &cfg) != 0) {
4520 ioc->spi_data.maxBusWidth = MPT_NARROW;
4521 ioc->spi_data.maxSyncOffset = 0;
4522 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4523 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4525 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4526 ioc->name, ioc->spi_data.minSyncFactor));
4528 /* Save the Port Page 0 data
4530 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4531 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4532 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4534 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4535 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4536 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4537 ioc->name, pPP0->Capabilities));
4539 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4540 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4542 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4543 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4544 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4545 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4546 ioc->name, ioc->spi_data.minSyncFactor));
4548 ioc->spi_data.maxSyncOffset = 0;
4549 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4552 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4554 /* Update the minSyncFactor based on bus type.
4556 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4557 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4559 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4560 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4561 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4562 ioc->name, ioc->spi_data.minSyncFactor));
4567 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4572 /* SCSI Port Page 2 - Read the header then the page.
4574 header.PageVersion = 0;
4575 header.PageLength = 0;
4576 header.PageNumber = 2;
4577 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4578 cfg.cfghdr.hdr = &header;
4580 cfg.pageAddr = portnum;
4581 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4583 if (mpt_config(ioc, &cfg) != 0)
4586 if (header.PageLength > 0) {
4587 /* Allocate memory and read SCSI Port Page 2
4589 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4591 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4592 cfg.physAddr = buf_dma;
4593 if (mpt_config(ioc, &cfg) != 0) {
4594 /* Nvram data is left with INVALID mark
4598 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4599 MpiDeviceInfo_t *pdevice = NULL;
4602 * Save "Set to Avoid SCSI Bus Resets" flag
4604 ioc->spi_data.bus_reset =
4605 (le32_to_cpu(pPP2->PortFlags) &
4606 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4609 /* Save the Port Page 2 data
4610 * (reformat into a 32bit quantity)
4612 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4613 ioc->spi_data.PortFlags = data;
4614 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4615 pdevice = &pPP2->DeviceSettings[ii];
4616 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4617 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4618 ioc->spi_data.nvram[ii] = data;
4622 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4626 /* Update Adapter limits with those from NVRAM
4627 * Comment: Don't need to do this. Target performance
4628 * parameters will never exceed the adapters limits.
4634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4635 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4636 * @ioc: Pointer to a Adapter Strucutre
4637 * @portnum: IOC port number
4639 * Return: -EFAULT if read of config page header fails
4643 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4646 ConfigPageHeader_t header;
4648 /* Read the SCSI Device Page 1 header
4650 header.PageVersion = 0;
4651 header.PageLength = 0;
4652 header.PageNumber = 1;
4653 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4654 cfg.cfghdr.hdr = &header;
4656 cfg.pageAddr = portnum;
4657 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4660 if (mpt_config(ioc, &cfg) != 0)
4663 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4664 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4666 header.PageVersion = 0;
4667 header.PageLength = 0;
4668 header.PageNumber = 0;
4669 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4670 if (mpt_config(ioc, &cfg) != 0)
4673 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4674 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4676 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4677 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4679 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4680 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4686 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4687 * @ioc: Pointer to a Adapter Strucutre
4688 * @portnum: IOC port number
4692 * -EFAULT if read of config page header fails or data pointer not NULL
4693 * -ENOMEM if pci_alloc failed
4696 mpt_findImVolumes(MPT_ADAPTER *ioc)
4700 ConfigPageIoc2RaidVol_t *pIocRv;
4701 dma_addr_t ioc2_dma;
4703 ConfigPageHeader_t header;
4710 /* Read IOCP2 header then the page.
4712 header.PageVersion = 0;
4713 header.PageLength = 0;
4714 header.PageNumber = 2;
4715 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4716 cfg.cfghdr.hdr = &header;
4719 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4722 if (mpt_config(ioc, &cfg) != 0)
4725 if (header.PageLength == 0)
4728 iocpage2sz = header.PageLength * 4;
4729 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4733 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4734 cfg.physAddr = ioc2_dma;
4735 if (mpt_config(ioc, &cfg) != 0)
4738 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4739 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4741 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4746 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4748 /* Identify RAID Volume Id's */
4749 nVols = pIoc2->NumActiveVolumes;
4755 /* At least 1 RAID Volume
4757 pIocRv = pIoc2->RaidVolume;
4758 ioc->raid_data.isRaid = 0;
4759 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4760 vid = pIocRv->VolumeID;
4761 vbus = pIocRv->VolumeBus;
4762 vioc = pIocRv->VolumeIOC;
4767 ioc->raid_data.isRaid |= (1 << vid);
4769 /* Error! Always bus 0
4775 /* Identify Hidden Physical Disk Id's */
4776 nPhys = pIoc2->NumActivePhysDisks;
4778 /* No physical disks.
4781 mpt_read_ioc_pg_3(ioc);
4785 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4791 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4796 ConfigPageHeader_t header;
4797 dma_addr_t ioc3_dma;
4800 /* Free the old page
4802 kfree(ioc->raid_data.pIocPg3);
4803 ioc->raid_data.pIocPg3 = NULL;
4805 /* There is at least one physical disk.
4806 * Read and save IOC Page 3
4808 header.PageVersion = 0;
4809 header.PageLength = 0;
4810 header.PageNumber = 3;
4811 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4812 cfg.cfghdr.hdr = &header;
4815 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4818 if (mpt_config(ioc, &cfg) != 0)
4821 if (header.PageLength == 0)
4824 /* Read Header good, alloc memory
4826 iocpage3sz = header.PageLength * 4;
4827 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4831 /* Read the Page and save the data
4832 * into malloc'd memory.
4834 cfg.physAddr = ioc3_dma;
4835 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4836 if (mpt_config(ioc, &cfg) == 0) {
4837 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4839 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4840 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4844 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4850 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4854 ConfigPageHeader_t header;
4855 dma_addr_t ioc4_dma;
4858 /* Read and save IOC Page 4
4860 header.PageVersion = 0;
4861 header.PageLength = 0;
4862 header.PageNumber = 4;
4863 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4864 cfg.cfghdr.hdr = &header;
4867 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4870 if (mpt_config(ioc, &cfg) != 0)
4873 if (header.PageLength == 0)
4876 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4877 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4878 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4882 ioc4_dma = ioc->spi_data.IocPg4_dma;
4883 iocpage4sz = ioc->spi_data.IocPg4Sz;
4886 /* Read the Page into dma memory.
4888 cfg.physAddr = ioc4_dma;
4889 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4890 if (mpt_config(ioc, &cfg) == 0) {
4891 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4892 ioc->spi_data.IocPg4_dma = ioc4_dma;
4893 ioc->spi_data.IocPg4Sz = iocpage4sz;
4895 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4896 ioc->spi_data.pIocPg4 = NULL;
4901 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4905 ConfigPageHeader_t header;
4906 dma_addr_t ioc1_dma;
4910 /* Check the Coalescing Timeout in IOC Page 1
4912 header.PageVersion = 0;
4913 header.PageLength = 0;
4914 header.PageNumber = 1;
4915 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4916 cfg.cfghdr.hdr = &header;
4919 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4922 if (mpt_config(ioc, &cfg) != 0)
4925 if (header.PageLength == 0)
4928 /* Read Header good, alloc memory
4930 iocpage1sz = header.PageLength * 4;
4931 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4935 /* Read the Page and check coalescing timeout
4937 cfg.physAddr = ioc1_dma;
4938 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4939 if (mpt_config(ioc, &cfg) == 0) {
4941 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4942 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4943 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4945 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4948 if (tmp > MPT_COALESCING_TIMEOUT) {
4949 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4951 /* Write NVRAM and current
4954 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4955 if (mpt_config(ioc, &cfg) == 0) {
4956 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4957 ioc->name, MPT_COALESCING_TIMEOUT));
4959 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4960 if (mpt_config(ioc, &cfg) == 0) {
4961 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4962 ioc->name, MPT_COALESCING_TIMEOUT));
4964 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4969 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4975 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4979 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4986 * SendEventNotification - Send EventNotification (on or off) request
4988 * @ioc: Pointer to MPT_ADAPTER structure
4989 * @EvSwitch: Event switch flags
4992 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4994 EventNotification_t *evnp;
4996 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
4998 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5002 memset(evnp, 0, sizeof(*evnp));
5004 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5006 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5007 evnp->ChainOffset = 0;
5009 evnp->Switch = EvSwitch;
5011 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5016 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5018 * SendEventAck - Send EventAck request to MPT adapter.
5019 * @ioc: Pointer to MPT_ADAPTER structure
5020 * @evnp: Pointer to original EventNotification request
5023 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5027 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5028 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5029 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5030 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5031 le32_to_cpu(evnp->Data[0]));
5034 memset(pAck, 0, sizeof(*pAck));
5036 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5038 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5039 pAck->ChainOffset = 0;
5041 pAck->Event = evnp->Event;
5042 pAck->EventContext = evnp->EventContext;
5044 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5051 * mpt_config - Generic function to issue config message
5052 * @ioc - Pointer to an adapter structure
5053 * @cfg - Pointer to a configuration structure. Struct contains
5054 * action, page address, direction, physical address
5055 * and pointer to a configuration page header
5056 * Page header is updated.
5058 * Returns 0 for success
5059 * -EPERM if not allowed due to ISR context
5060 * -EAGAIN if no msg frames currently available
5061 * -EFAULT for non-successful reply or no reply (timeout)
5064 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5067 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5069 unsigned long flags;
5074 /* Prevent calling wait_event() (below), if caller happens
5075 * to be in ISR context, because that is fatal!
5077 in_isr = in_interrupt();
5079 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5084 /* Get and Populate a free Frame
5086 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5087 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5091 pReq = (Config_t *)mf;
5092 pReq->Action = pCfg->action;
5094 pReq->ChainOffset = 0;
5095 pReq->Function = MPI_FUNCTION_CONFIG;
5097 /* Assume page type is not extended and clear "reserved" fields. */
5098 pReq->ExtPageLength = 0;
5099 pReq->ExtPageType = 0;
5102 for (ii=0; ii < 8; ii++)
5103 pReq->Reserved2[ii] = 0;
5105 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5106 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5107 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5108 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5110 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5111 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5112 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5113 pReq->ExtPageType = pExtHdr->ExtPageType;
5114 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5116 /* Page Length must be treated as a reserved field for the extended header. */
5117 pReq->Header.PageLength = 0;
5120 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5122 /* Add a SGE to the config request.
5125 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5127 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5129 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5130 flagsLength |= pExtHdr->ExtPageLength * 4;
5132 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5133 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5136 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5138 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5139 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5142 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5144 /* Append pCfg pointer to end of mf
5146 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5148 /* Initalize the timer
5150 init_timer(&pCfg->timer);
5151 pCfg->timer.data = (unsigned long) ioc;
5152 pCfg->timer.function = mpt_timer_expired;
5153 pCfg->wait_done = 0;
5155 /* Set the timer; ensure 10 second minimum */
5156 if (pCfg->timeout < 10)
5157 pCfg->timer.expires = jiffies + HZ*10;
5159 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5161 /* Add to end of Q, set timer and then issue this command */
5162 spin_lock_irqsave(&ioc->FreeQlock, flags);
5163 list_add_tail(&pCfg->linkage, &ioc->configQ);
5164 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5166 add_timer(&pCfg->timer);
5167 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5168 wait_event(mpt_waitq, pCfg->wait_done);
5170 /* mf has been freed - do not access */
5177 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5179 * mpt_timer_expired - Call back for timer process.
5180 * Used only internal config functionality.
5181 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5184 mpt_timer_expired(unsigned long data)
5186 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5188 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5190 /* Perform a FW reload */
5191 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5192 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5194 /* No more processing.
5195 * Hard reset clean-up will wake up
5196 * process and free all resources.
5198 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5205 * mpt_ioc_reset - Base cleanup for hard reset
5206 * @ioc: Pointer to the adapter structure
5207 * @reset_phase: Indicates pre- or post-reset functionality
5209 * Remark: Free's resources with internally generated commands.
5212 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5215 unsigned long flags;
5217 dprintk((KERN_WARNING MYNAM
5218 ": IOC %s_reset routed to MPT base driver!\n",
5219 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5220 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5222 if (reset_phase == MPT_IOC_SETUP_RESET) {
5224 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5225 /* If the internal config Q is not empty -
5226 * delete timer. MF resources will be freed when
5227 * the FIFO's are primed.
5229 spin_lock_irqsave(&ioc->FreeQlock, flags);
5230 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5231 del_timer(&pCfg->timer);
5232 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5237 /* Search the configQ for internal commands.
5238 * Flush the Q, and wake up all suspended threads.
5240 spin_lock_irqsave(&ioc->FreeQlock, flags);
5241 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5242 list_del(&pCfg->linkage);
5244 pCfg->status = MPT_CONFIG_ERROR;
5245 pCfg->wait_done = 1;
5246 wake_up(&mpt_waitq);
5248 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5251 return 1; /* currently means nothing really */
5255 #ifdef CONFIG_PROC_FS /* { */
5256 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5258 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5260 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5262 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5264 * Returns 0 for success, non-zero for failure.
5267 procmpt_create(void)
5269 struct proc_dir_entry *ent;
5271 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5272 if (mpt_proc_root_dir == NULL)
5275 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5277 ent->read_proc = procmpt_summary_read;
5279 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5281 ent->read_proc = procmpt_version_read;
5286 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5288 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5290 * Returns 0 for success, non-zero for failure.
5293 procmpt_destroy(void)
5295 remove_proc_entry("version", mpt_proc_root_dir);
5296 remove_proc_entry("summary", mpt_proc_root_dir);
5297 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5302 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5303 * or from /proc/mpt/iocN/summary.
5304 * @buf: Pointer to area to write information
5305 * @start: Pointer to start pointer
5306 * @offset: Offset to start writing
5308 * @eof: Pointer to EOF integer
5311 * Returns number of characters written to process performing the read.
5314 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5324 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5328 list_for_each_entry(ioc, &ioc_list, list) {
5331 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5334 if ((out-buf) >= request)
5341 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5344 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5346 * procmpt_version_read - Handle read request from /proc/mpt/version.
5347 * @buf: Pointer to area to write information
5348 * @start: Pointer to start pointer
5349 * @offset: Offset to start writing
5351 * @eof: Pointer to EOF integer
5354 * Returns number of characters written to process performing the read.
5357 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5360 int scsi, fc, sas, lan, ctl, targ, dmp;
5364 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5365 len += sprintf(buf+len, " Fusion MPT base driver\n");
5367 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5368 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5370 if (MptCallbacks[ii]) {
5371 switch (MptDriverClass[ii]) {
5373 if (!scsi++) drvname = "SPI host";
5376 if (!fc++) drvname = "FC host";
5379 if (!sas++) drvname = "SAS host";
5382 if (!lan++) drvname = "LAN";
5385 if (!targ++) drvname = "SCSI target";
5388 if (!ctl++) drvname = "ioctl";
5393 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5397 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5402 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5403 * @buf: Pointer to area to write information
5404 * @start: Pointer to start pointer
5405 * @offset: Offset to start writing
5407 * @eof: Pointer to EOF integer
5410 * Returns number of characters written to process performing the read.
5413 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5415 MPT_ADAPTER *ioc = data;
5421 mpt_get_fw_exp_ver(expVer, ioc);
5423 len = sprintf(buf, "%s:", ioc->name);
5424 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5425 len += sprintf(buf+len, " (f/w download boot flag set)");
5426 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5427 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5429 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5430 ioc->facts.ProductID,
5432 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5433 if (ioc->facts.FWImageSize)
5434 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5435 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5436 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5437 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5439 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5440 ioc->facts.CurrentHostMfaHighAddr);
5441 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5442 ioc->facts.CurrentSenseBufferHighAddr);
5444 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5445 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5447 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5448 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5450 * Rounding UP to nearest 4-kB boundary here...
5452 sz = (ioc->req_sz * ioc->req_depth) + 128;
5453 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5454 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5455 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5456 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5457 4*ioc->facts.RequestFrameSize,
5458 ioc->facts.GlobalCredits);
5460 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5461 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5462 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5463 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5464 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5465 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5466 ioc->facts.CurReplyFrameSize,
5467 ioc->facts.ReplyQueueDepth);
5469 len += sprintf(buf+len, " MaxDevices = %d\n",
5470 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5471 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5474 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5475 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5477 ioc->facts.NumberOfPorts);
5478 if (ioc->bus_type == FC) {
5479 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5480 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5481 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5482 a[5], a[4], a[3], a[2], a[1], a[0]);
5484 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5485 ioc->fc_port_page0[p].WWNN.High,
5486 ioc->fc_port_page0[p].WWNN.Low,
5487 ioc->fc_port_page0[p].WWPN.High,
5488 ioc->fc_port_page0[p].WWPN.Low);
5492 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5495 #endif /* CONFIG_PROC_FS } */
5497 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5499 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5502 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5503 sprintf(buf, " (Exp %02d%02d)",
5504 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5505 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5508 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5509 strcat(buf, " [MDBG]");
5513 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5515 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5516 * @ioc: Pointer to MPT_ADAPTER structure
5517 * @buffer: Pointer to buffer where IOC summary info should be written
5518 * @size: Pointer to number of bytes we wrote (set by this routine)
5519 * @len: Offset at which to start writing in buffer
5520 * @showlan: Display LAN stuff?
5522 * This routine writes (english readable) ASCII text, which represents
5523 * a summary of IOC information, to a buffer.
5526 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5531 mpt_get_fw_exp_ver(expVer, ioc);
5534 * Shorter summary of attached ioc's...
5536 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5539 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5540 ioc->facts.FWVersion.Word,
5542 ioc->facts.NumberOfPorts,
5545 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5546 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5547 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5548 a[5], a[4], a[3], a[2], a[1], a[0]);
5552 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5554 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5558 y += sprintf(buffer+len+y, " (disabled)");
5560 y += sprintf(buffer+len+y, "\n");
5565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5569 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5571 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5572 * Management call based on input arg values. If TaskMgmt fails,
5573 * return associated SCSI request.
5574 * @ioc: Pointer to MPT_ADAPTER structure
5575 * @sleepFlag: Indicates if sleep or schedule must be called.
5577 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5578 * or a non-interrupt thread. In the former, must not call schedule().
5580 * Remark: A return of -1 is a FATAL error case, as it means a
5581 * FW reload/initialization failed.
5583 * Returns 0 for SUCCESS or -1 if FAILED.
5586 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5589 unsigned long flags;
5591 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5593 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5594 printk("MF count 0x%x !\n", ioc->mfcnt);
5597 /* Reset the adapter. Prevent more than 1 call to
5598 * mpt_do_ioc_recovery at any instant in time.
5600 spin_lock_irqsave(&ioc->diagLock, flags);
5601 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5602 spin_unlock_irqrestore(&ioc->diagLock, flags);
5605 ioc->diagPending = 1;
5607 spin_unlock_irqrestore(&ioc->diagLock, flags);
5609 /* FIXME: If do_ioc_recovery fails, repeat....
5612 /* The SCSI driver needs to adjust timeouts on all current
5613 * commands prior to the diagnostic reset being issued.
5614 * Prevents timeouts occuring during a diagnostic reset...very bad.
5615 * For all other protocol drivers, this is a no-op.
5621 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5622 if (MptResetHandlers[ii]) {
5623 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5625 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5627 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5628 ioc->name, ioc->alt_ioc->name, ii));
5629 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5635 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5636 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5641 ioc->alt_ioc->reload_fw = 0;
5643 spin_lock_irqsave(&ioc->diagLock, flags);
5644 ioc->diagPending = 0;
5646 ioc->alt_ioc->diagPending = 0;
5647 spin_unlock_irqrestore(&ioc->diagLock, flags);
5649 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5654 # define EVENT_DESCR_STR_SZ 100
5656 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5658 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5663 case MPI_EVENT_NONE:
5666 case MPI_EVENT_LOG_DATA:
5669 case MPI_EVENT_STATE_CHANGE:
5670 ds = "State Change";
5672 case MPI_EVENT_UNIT_ATTENTION:
5673 ds = "Unit Attention";
5675 case MPI_EVENT_IOC_BUS_RESET:
5676 ds = "IOC Bus Reset";
5678 case MPI_EVENT_EXT_BUS_RESET:
5679 ds = "External Bus Reset";
5681 case MPI_EVENT_RESCAN:
5682 ds = "Bus Rescan Event";
5683 /* Ok, do we need to do anything here? As far as
5684 I can tell, this is when a new device gets added
5687 case MPI_EVENT_LINK_STATUS_CHANGE:
5688 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5689 ds = "Link Status(FAILURE) Change";
5691 ds = "Link Status(ACTIVE) Change";
5693 case MPI_EVENT_LOOP_STATE_CHANGE:
5694 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5695 ds = "Loop State(LIP) Change";
5696 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5697 ds = "Loop State(LPE) Change"; /* ??? */
5699 ds = "Loop State(LPB) Change"; /* ??? */
5701 case MPI_EVENT_LOGOUT:
5704 case MPI_EVENT_EVENT_CHANGE:
5706 ds = "Events(ON) Change";
5708 ds = "Events(OFF) Change";
5710 case MPI_EVENT_INTEGRATED_RAID:
5712 u8 ReasonCode = (u8)(evData0 >> 16);
5713 switch (ReasonCode) {
5714 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5715 ds = "Integrated Raid: Volume Created";
5717 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5718 ds = "Integrated Raid: Volume Deleted";
5720 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5721 ds = "Integrated Raid: Volume Settings Changed";
5723 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5724 ds = "Integrated Raid: Volume Status Changed";
5726 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5727 ds = "Integrated Raid: Volume Physdisk Changed";
5729 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5730 ds = "Integrated Raid: Physdisk Created";
5732 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5733 ds = "Integrated Raid: Physdisk Deleted";
5735 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5736 ds = "Integrated Raid: Physdisk Settings Changed";
5738 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5739 ds = "Integrated Raid: Physdisk Status Changed";
5741 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5742 ds = "Integrated Raid: Domain Validation Needed";
5744 case MPI_EVENT_RAID_RC_SMART_DATA :
5745 ds = "Integrated Raid; Smart Data";
5747 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5748 ds = "Integrated Raid: Replace Action Started";
5751 ds = "Integrated Raid";
5756 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5757 ds = "SCSI Device Status Change";
5759 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5761 u8 id = (u8)(evData0);
5762 u8 ReasonCode = (u8)(evData0 >> 16);
5763 switch (ReasonCode) {
5764 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5765 snprintf(evStr, EVENT_DESCR_STR_SZ,
5766 "SAS Device Status Change: Added: id=%d", id);
5768 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5769 snprintf(evStr, EVENT_DESCR_STR_SZ,
5770 "SAS Device Status Change: Deleted: id=%d", id);
5772 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5773 snprintf(evStr, EVENT_DESCR_STR_SZ,
5774 "SAS Device Status Change: SMART Data: id=%d",
5777 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5778 snprintf(evStr, EVENT_DESCR_STR_SZ,
5779 "SAS Device Status Change: No Persistancy "
5780 "Added: id=%d", id);
5783 snprintf(evStr, EVENT_DESCR_STR_SZ,
5784 "SAS Device Status Change: Unknown: id=%d", id);
5789 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5790 ds = "Bus Timer Expired";
5792 case MPI_EVENT_QUEUE_FULL:
5795 case MPI_EVENT_SAS_SES:
5796 ds = "SAS SES Event";
5798 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5799 ds = "Persistent Table Full";
5801 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5803 u8 LinkRates = (u8)(evData0 >> 8);
5804 u8 PhyNumber = (u8)(evData0);
5805 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5806 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5807 switch (LinkRates) {
5808 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5809 snprintf(evStr, EVENT_DESCR_STR_SZ,
5810 "SAS PHY Link Status: Phy=%d:"
5811 " Rate Unknown",PhyNumber);
5813 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5814 snprintf(evStr, EVENT_DESCR_STR_SZ,
5815 "SAS PHY Link Status: Phy=%d:"
5816 " Phy Disabled",PhyNumber);
5818 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5819 snprintf(evStr, EVENT_DESCR_STR_SZ,
5820 "SAS PHY Link Status: Phy=%d:"
5821 " Failed Speed Nego",PhyNumber);
5823 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5824 snprintf(evStr, EVENT_DESCR_STR_SZ,
5825 "SAS PHY Link Status: Phy=%d:"
5826 " Sata OOB Completed",PhyNumber);
5828 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5829 snprintf(evStr, EVENT_DESCR_STR_SZ,
5830 "SAS PHY Link Status: Phy=%d:"
5831 " Rate 1.5 Gbps",PhyNumber);
5833 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5834 snprintf(evStr, EVENT_DESCR_STR_SZ,
5835 "SAS PHY Link Status: Phy=%d:"
5836 " Rate 3.0 Gpbs",PhyNumber);
5839 snprintf(evStr, EVENT_DESCR_STR_SZ,
5840 "SAS PHY Link Status: Phy=%d", PhyNumber);
5845 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5846 ds = "SAS Discovery Error";
5848 case MPI_EVENT_IR_RESYNC_UPDATE:
5850 u8 resync_complete = (u8)(evData0 >> 16);
5851 snprintf(evStr, EVENT_DESCR_STR_SZ,
5852 "IR Resync Update: Complete = %d:",resync_complete);
5857 u8 ReasonCode = (u8)(evData0 >> 16);
5858 switch (ReasonCode) {
5859 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5860 ds = "IR2: LD State Changed";
5862 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5863 ds = "IR2: PD State Changed";
5865 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5866 ds = "IR2: Bad Block Table Full";
5868 case MPI_EVENT_IR2_RC_PD_INSERTED:
5869 ds = "IR2: PD Inserted";
5871 case MPI_EVENT_IR2_RC_PD_REMOVED:
5872 ds = "IR2: PD Removed";
5874 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5875 ds = "IR2: Foreign CFG Detected";
5877 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5878 ds = "IR2: Rebuild Medium Error";
5886 case MPI_EVENT_SAS_DISCOVERY:
5889 ds = "SAS Discovery: Start";
5891 ds = "SAS Discovery: Stop";
5894 case MPI_EVENT_LOG_ENTRY_ADDED:
5895 ds = "SAS Log Entry Added";
5899 * MPT base "custom" events may be added here...
5906 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
5909 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5911 * ProcessEventNotification - Route a received EventNotificationReply to
5912 * all currently regeistered event handlers.
5913 * @ioc: Pointer to MPT_ADAPTER structure
5914 * @pEventReply: Pointer to EventNotification reply frame
5915 * @evHandlers: Pointer to integer, number of event handlers
5917 * Returns sum of event handlers return values.
5920 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5928 char evStr[EVENT_DESCR_STR_SZ];
5932 * Do platform normalization of values
5934 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5935 // evCtx = le32_to_cpu(pEventReply->EventContext);
5936 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5938 evData0 = le32_to_cpu(pEventReply->Data[0]);
5941 EventDescriptionStr(event, evData0, evStr);
5942 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
5947 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
5948 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5949 for (ii = 0; ii < evDataLen; ii++)
5950 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5955 * Do general / base driver event processing
5958 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5960 u8 evState = evData0 & 0xFF;
5962 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5964 /* Update EventState field in cached IocFacts */
5965 if (ioc->facts.Function) {
5966 ioc->facts.EventState = evState;
5970 case MPI_EVENT_INTEGRATED_RAID:
5971 mptbase_raid_process_event_data(ioc,
5972 (MpiEventDataRaid_t *)pEventReply->Data);
5979 * Should this event be logged? Events are written sequentially.
5980 * When buffer is full, start again at the top.
5982 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5985 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
5987 ioc->events[idx].event = event;
5988 ioc->events[idx].eventContext = ioc->eventContext;
5990 for (ii = 0; ii < 2; ii++) {
5992 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5994 ioc->events[idx].data[ii] = 0;
5997 ioc->eventContext++;
6002 * Call each currently registered protocol event handler.
6004 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6005 if (MptEvHandlers[ii]) {
6006 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6008 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6012 /* FIXME? Examine results here? */
6015 * If needed, send (a single) EventAck.
6017 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6018 devtverboseprintk((MYIOC_s_WARN_FMT
6019 "EventAck required\n",ioc->name));
6020 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6021 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6026 *evHandlers = handlers;
6030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6032 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6033 * @ioc: Pointer to MPT_ADAPTER structure
6034 * @log_info: U32 LogInfo reply word from the IOC
6036 * Refer to lsi/fc_log.h.
6039 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6041 static char *subcl_str[8] = {
6042 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6043 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6045 u8 subcl = (log_info >> 24) & 0x7;
6047 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6048 ioc->name, log_info, subcl_str[subcl]);
6051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6053 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6054 * @ioc: Pointer to MPT_ADAPTER structure
6055 * @mr: Pointer to MPT reply frame
6056 * @log_info: U32 LogInfo word from the IOC
6058 * Refer to lsi/sp_log.h.
6061 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6063 u32 info = log_info & 0x00FF0000;
6064 char *desc = "unknown";
6068 desc = "bug! MID not found";
6069 if (ioc->reload_fw == 0)
6074 desc = "Parity Error";
6078 desc = "ASYNC Outbound Overrun";
6082 desc = "SYNC Offset Error";
6090 desc = "Msg In Overflow";
6098 desc = "Outbound DMA Overrun";
6102 desc = "Task Management";
6106 desc = "Device Problem";
6110 desc = "Invalid Phase Change";
6114 desc = "Untagged Table Size";
6119 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6122 /* strings for sas loginfo */
6123 static char *originator_str[] = {
6128 static char *iop_code_str[] = {
6130 "Invalid SAS Address", /* 01h */
6132 "Invalid Page", /* 03h */
6134 "Task Terminated" /* 05h */
6136 static char *pl_code_str[] = {
6138 "Open Failure", /* 01h */
6139 "Invalid Scatter Gather List", /* 02h */
6140 "Wrong Relative Offset or Frame Length", /* 03h */
6141 "Frame Transfer Error", /* 04h */
6142 "Transmit Frame Connected Low", /* 05h */
6143 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6144 "SATA Read Log Receive Data Error", /* 07h */
6145 "SATA NCQ Fail All Commands After Error", /* 08h */
6146 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6147 "Receive Frame Invalid Message", /* 0Ah */
6148 "Receive Context Message Valid Error", /* 0Bh */
6149 "Receive Frame Current Frame Error", /* 0Ch */
6150 "SATA Link Down", /* 0Dh */
6151 "Discovery SATA Init W IOS", /* 0Eh */
6152 "Config Invalid Page", /* 0Fh */
6153 "Discovery SATA Init Timeout", /* 10h */
6156 "IO Not Yet Executed", /* 13h */
6157 "IO Executed", /* 14h */
6158 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6159 "Open Transmit DMA Abort", /* 16h */
6169 "Enclosure Management" /* 20h */
6172 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6174 * mpt_sas_log_info - Log information returned from SAS IOC.
6175 * @ioc: Pointer to MPT_ADAPTER structure
6176 * @log_info: U32 LogInfo reply word from the IOC
6178 * Refer to lsi/mpi_log_sas.h.
6181 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6183 union loginfo_type {
6192 union loginfo_type sas_loginfo;
6193 char *code_desc = NULL;
6195 sas_loginfo.loginfo = log_info;
6196 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6197 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6199 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6200 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6201 code_desc = iop_code_str[sas_loginfo.dw.code];
6202 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6203 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6204 code_desc = pl_code_str[sas_loginfo.dw.code];
6207 if (code_desc != NULL)
6208 printk(MYIOC_s_INFO_FMT
6209 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6210 " SubCode(0x%04x)\n",
6213 originator_str[sas_loginfo.dw.originator],
6215 sas_loginfo.dw.subcode);
6217 printk(MYIOC_s_INFO_FMT
6218 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6219 " SubCode(0x%04x)\n",
6222 originator_str[sas_loginfo.dw.originator],
6223 sas_loginfo.dw.code,
6224 sas_loginfo.dw.subcode);
6227 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6229 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6230 * @ioc: Pointer to MPT_ADAPTER structure
6231 * @ioc_status: U32 IOCStatus word from IOC
6232 * @mf: Pointer to MPT request frame
6234 * Refer to lsi/mpi.h.
6237 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6239 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6243 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6244 desc = "Invalid Function";
6247 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6251 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6252 desc = "Invalid SGL";
6255 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6256 desc = "Internal Error";
6259 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6263 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6264 desc = "Insufficient Resources";
6267 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6268 desc = "Invalid Field";
6271 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6272 desc = "Invalid State";
6275 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6276 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6277 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6278 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6279 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6280 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6281 /* No message for Config IOCStatus values */
6284 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6285 /* No message for recovered error
6286 desc = "SCSI Recovered Error";
6290 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6291 desc = "SCSI Invalid Bus";
6294 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6295 desc = "SCSI Invalid TargetID";
6298 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6300 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6301 U8 cdb = pScsiReq->CDB[0];
6302 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6303 desc = "SCSI Device Not There";
6308 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6309 desc = "SCSI Data Overrun";
6312 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6313 /* This error is checked in scsi_io_done(). Skip.
6314 desc = "SCSI Data Underrun";
6318 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6319 desc = "SCSI I/O Data Error";
6322 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6323 desc = "SCSI Protocol Error";
6326 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6327 desc = "SCSI Task Terminated";
6330 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6331 desc = "SCSI Residual Mismatch";
6334 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6335 desc = "SCSI Task Management Failed";
6338 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6339 desc = "SCSI IOC Terminated";
6342 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6343 desc = "SCSI Ext Terminated";
6351 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6354 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6355 EXPORT_SYMBOL(mpt_attach);
6356 EXPORT_SYMBOL(mpt_detach);
6358 EXPORT_SYMBOL(mpt_resume);
6359 EXPORT_SYMBOL(mpt_suspend);
6361 EXPORT_SYMBOL(ioc_list);
6362 EXPORT_SYMBOL(mpt_proc_root_dir);
6363 EXPORT_SYMBOL(mpt_register);
6364 EXPORT_SYMBOL(mpt_deregister);
6365 EXPORT_SYMBOL(mpt_event_register);
6366 EXPORT_SYMBOL(mpt_event_deregister);
6367 EXPORT_SYMBOL(mpt_reset_register);
6368 EXPORT_SYMBOL(mpt_reset_deregister);
6369 EXPORT_SYMBOL(mpt_device_driver_register);
6370 EXPORT_SYMBOL(mpt_device_driver_deregister);
6371 EXPORT_SYMBOL(mpt_get_msg_frame);
6372 EXPORT_SYMBOL(mpt_put_msg_frame);
6373 EXPORT_SYMBOL(mpt_free_msg_frame);
6374 EXPORT_SYMBOL(mpt_add_sge);
6375 EXPORT_SYMBOL(mpt_send_handshake_request);
6376 EXPORT_SYMBOL(mpt_verify_adapter);
6377 EXPORT_SYMBOL(mpt_GetIocState);
6378 EXPORT_SYMBOL(mpt_print_ioc_summary);
6379 EXPORT_SYMBOL(mpt_lan_index);
6380 EXPORT_SYMBOL(mpt_stm_index);
6381 EXPORT_SYMBOL(mpt_HardResetHandler);
6382 EXPORT_SYMBOL(mpt_config);
6383 EXPORT_SYMBOL(mpt_findImVolumes);
6384 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6385 EXPORT_SYMBOL(mpt_free_fw_memory);
6386 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6391 * fusion_init - Fusion MPT base driver initialization routine.
6393 * Returns 0 for success, non-zero for failure.
6400 show_mptmod_ver(my_NAME, my_VERSION);
6401 printk(KERN_INFO COPYRIGHT "\n");
6403 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6404 MptCallbacks[i] = NULL;
6405 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6406 MptEvHandlers[i] = NULL;
6407 MptResetHandlers[i] = NULL;
6410 /* Register ourselves (mptbase) in order to facilitate
6411 * EventNotification handling.
6413 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6415 /* Register for hard reset handling callbacks.
6417 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6418 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6423 #ifdef CONFIG_PROC_FS
6424 (void) procmpt_create();
6429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6431 * fusion_exit - Perform driver unload cleanup.
6433 * This routine frees all resources associated with each MPT adapter
6434 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6440 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6442 mpt_reset_deregister(mpt_base_index);
6444 #ifdef CONFIG_PROC_FS
6449 module_init(fusion_init);
6450 module_exit(fusion_exit);