2 * linux/drivers/message/fusion/mptbase.c
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
5 * For use with LSI Logic PCI chip/adapter(s)
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2005 LSI Logic Corporation
9 * (mailto:mpt_linux_developer@lsil.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
49 #include <linux/kernel.h>
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/types.h>
55 #include <linux/pci.h>
56 #include <linux/kdev_t.h>
57 #include <linux/blkdev.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
60 #include <linux/dma-mapping.h>
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT base driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
71 #define MYNAM "mptbase"
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
76 MODULE_VERSION(MPT_LINUX_VERSION_COMMON);
81 static int mpt_msi_enable;
82 module_param(mpt_msi_enable, int, 0);
83 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
86 static int mfcounter = 0;
87 #define PRINT_MF_COUNT 20000
90 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
94 int mpt_lan_index = -1;
95 int mpt_stm_index = -1;
97 struct proc_dir_entry *mpt_proc_root_dir;
99 #define WHOINIT_UNKNOWN 0xAA
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
105 /* Adapter link list */
107 /* Callback lookup table */
108 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
109 /* Protocol driver class lookup table */
110 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
111 /* Event handler lookup table */
112 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
113 /* Reset handler lookup table */
114 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
115 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
117 static int mpt_base_index = -1;
118 static int last_drv_idx = -1;
120 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
126 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
127 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
128 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
129 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
131 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
132 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
133 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
134 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
136 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
137 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
138 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
139 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
140 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
141 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
142 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
143 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
144 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
145 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
146 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
147 static int PrimeIocFifos(MPT_ADAPTER *ioc);
148 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
151 static int GetLanConfigPages(MPT_ADAPTER *ioc);
152 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
153 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
154 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
155 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
156 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
157 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
158 static void mpt_timer_expired(unsigned long data);
159 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
160 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
161 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
162 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
164 #ifdef CONFIG_PROC_FS
165 static int procmpt_summary_read(char *buf, char **start, off_t offset,
166 int request, int *eof, void *data);
167 static int procmpt_version_read(char *buf, char **start, off_t offset,
168 int request, int *eof, void *data);
169 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
170 int request, int *eof, void *data);
172 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
174 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
175 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
176 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
177 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
178 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
179 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
180 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
182 /* module entry point */
183 static int __init fusion_init (void);
184 static void __exit fusion_exit (void);
186 #define CHIPREG_READ32(addr) readl_relaxed(addr)
187 #define CHIPREG_READ32_dmasync(addr) readl(addr)
188 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
189 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
190 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
193 pci_disable_io_access(struct pci_dev *pdev)
197 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
199 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
203 pci_enable_io_access(struct pci_dev *pdev)
207 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
209 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
213 * Process turbo (context) reply...
216 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
218 MPT_FRAME_HDR *mf = NULL;
219 MPT_FRAME_HDR *mr = NULL;
223 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
226 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
227 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
228 req_idx = pa & 0x0000FFFF;
229 cb_idx = (pa & 0x00FF0000) >> 16;
230 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
232 case MPI_CONTEXT_REPLY_TYPE_LAN:
233 cb_idx = mpt_lan_index;
235 * Blind set of mf to NULL here was fatal
236 * after lan_reply says "freeme"
237 * Fix sort of combined with an optimization here;
238 * added explicit check for case where lan_reply
239 * was just returning 1 and doing nothing else.
240 * For this case skip the callback, but set up
241 * proper mf value first here:-)
243 if ((pa & 0x58000000) == 0x58000000) {
244 req_idx = pa & 0x0000FFFF;
245 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
246 mpt_free_msg_frame(ioc, mf);
251 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
253 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
254 cb_idx = mpt_stm_index;
255 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
262 /* Check for (valid) IO callback! */
263 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
264 MptCallbacks[cb_idx] == NULL) {
265 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
266 __FUNCTION__, ioc->name, cb_idx);
270 if (MptCallbacks[cb_idx](ioc, mf, mr))
271 mpt_free_msg_frame(ioc, mf);
277 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
288 /* non-TURBO reply! Hmmm, something may be up...
289 * Newest turbo reply mechanism; get address
290 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
293 /* Map DMA address of reply header to cpu address.
294 * pa is 32 bits - but the dma address may be 32 or 64 bits
295 * get offset based only only the low addresses
298 reply_dma_low = (pa <<= 1);
299 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
300 (reply_dma_low - ioc->reply_frames_low_dma));
302 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
303 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
304 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
306 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
307 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
308 DBG_DUMP_REPLY_FRAME(mr)
310 /* Check/log IOC log info
312 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
313 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
314 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
315 if (ioc->bus_type == FC)
316 mpt_fc_log_info(ioc, log_info);
317 else if (ioc->bus_type == SPI)
318 mpt_spi_log_info(ioc, log_info);
319 else if (ioc->bus_type == SAS)
320 mpt_sas_log_info(ioc, log_info);
322 if (ioc_stat & MPI_IOCSTATUS_MASK) {
323 if (ioc->bus_type == SPI &&
324 cb_idx != mpt_stm_index &&
325 cb_idx != mpt_lan_index)
326 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
330 /* Check for (valid) IO callback! */
331 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
332 MptCallbacks[cb_idx] == NULL) {
333 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
334 __FUNCTION__, ioc->name, cb_idx);
339 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
342 /* Flush (non-TURBO) reply with a WRITE! */
343 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
346 mpt_free_msg_frame(ioc, mf);
350 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
352 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
353 * @irq: irq number (not used)
354 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
355 * @r: pt_regs pointer (not used)
357 * This routine is registered via the request_irq() kernel API call,
358 * and handles all interrupts generated from a specific MPT adapter
359 * (also referred to as a IO Controller or IOC).
360 * This routine must clear the interrupt from the adapter and does
361 * so by reading the reply FIFO. Multiple replies may be processed
362 * per single call to this routine.
364 * This routine handles register-level access of the adapter but
365 * dispatches (calls) a protocol-specific callback routine to handle
366 * the protocol-specific details of the MPT request completion.
369 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
371 MPT_ADAPTER *ioc = bus_id;
372 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
374 if (pa == 0xFFFFFFFF)
378 * Drain the reply FIFO!
381 if (pa & MPI_ADDRESS_REPLY_A_BIT)
384 mpt_turbo_reply(ioc, pa);
385 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
386 } while (pa != 0xFFFFFFFF);
391 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
393 * mpt_base_reply - MPT base driver's callback routine; all base driver
394 * "internal" request/reply processing is routed here.
395 * Currently used for EventNotification and EventAck handling.
396 * @ioc: Pointer to MPT_ADAPTER structure
397 * @mf: Pointer to original MPT request frame
398 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
400 * Returns 1 indicating original alloc'd request frame ptr
401 * should be freed, or 0 if it shouldn't.
404 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
409 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
411 #if defined(MPT_DEBUG_MSG_FRAME)
412 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
413 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
414 DBG_DUMP_REQUEST_FRAME_HDR(mf)
418 func = reply->u.hdr.Function;
419 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
422 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
423 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
427 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
428 if (results != evHandlers) {
429 /* CHECKME! Any special handling needed here? */
430 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
431 ioc->name, evHandlers, results));
435 * Hmmm... It seems that EventNotificationReply is an exception
436 * to the rule of one reply per request.
438 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
441 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
442 ioc->name, pEvReply));
445 #ifdef CONFIG_PROC_FS
446 // LogEvent(ioc, pEvReply);
449 } else if (func == MPI_FUNCTION_EVENT_ACK) {
450 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
452 } else if (func == MPI_FUNCTION_CONFIG) {
456 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
457 ioc->name, mf, reply));
459 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
462 /* disable timer and remove from linked list */
463 del_timer(&pCfg->timer);
465 spin_lock_irqsave(&ioc->FreeQlock, flags);
466 list_del(&pCfg->linkage);
467 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
470 * If IOC Status is SUCCESS, save the header
471 * and set the status code to GOOD.
473 pCfg->status = MPT_CONFIG_ERROR;
475 ConfigReply_t *pReply = (ConfigReply_t *)reply;
478 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
479 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
480 status, le32_to_cpu(pReply->IOCLogInfo)));
482 pCfg->status = status;
483 if (status == MPI_IOCSTATUS_SUCCESS) {
484 if ((pReply->Header.PageType &
485 MPI_CONFIG_PAGETYPE_MASK) ==
486 MPI_CONFIG_PAGETYPE_EXTENDED) {
487 pCfg->cfghdr.ehdr->ExtPageLength =
488 le16_to_cpu(pReply->ExtPageLength);
489 pCfg->cfghdr.ehdr->ExtPageType =
492 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
494 /* If this is a regular header, save PageLength. */
495 /* LMP Do this better so not using a reserved field! */
496 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
497 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
498 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
503 * Wake up the original calling thread
508 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
509 /* we should be always getting a reply frame */
510 memcpy(ioc->persist_reply_frame, reply,
511 min(MPT_DEFAULT_FRAME_SIZE,
512 4*reply->u.reply.MsgLength));
513 del_timer(&ioc->persist_timer);
514 ioc->persist_wait_done = 1;
517 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
522 * Conditionally tell caller to free the original
523 * EventNotification/EventAck/unexpected request frame!
528 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
530 * mpt_register - Register protocol-specific main callback handler.
531 * @cbfunc: callback function pointer
532 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
534 * This routine is called by a protocol-specific driver (SCSI host,
535 * LAN, SCSI target) to register it's reply callback routine. Each
536 * protocol-specific driver must do this before it will be able to
537 * use any IOC resources, such as obtaining request frames.
539 * NOTES: The SCSI protocol driver currently calls this routine thrice
540 * in order to register separate callbacks; one for "normal" SCSI IO;
541 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
543 * Returns a positive integer valued "handle" in the
544 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
545 * Any non-positive return value (including zero!) should be considered
546 * an error by the caller.
549 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
556 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
557 * (slot/handle 0 is reserved!)
559 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
560 if (MptCallbacks[i] == NULL) {
561 MptCallbacks[i] = cbfunc;
562 MptDriverClass[i] = dclass;
563 MptEvHandlers[i] = NULL;
572 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
574 * mpt_deregister - Deregister a protocol drivers resources.
575 * @cb_idx: previously registered callback handle
577 * Each protocol-specific driver should call this routine when it's
578 * module is unloaded.
581 mpt_deregister(int cb_idx)
583 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
584 MptCallbacks[cb_idx] = NULL;
585 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
586 MptEvHandlers[cb_idx] = NULL;
592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
594 * mpt_event_register - Register protocol-specific event callback
596 * @cb_idx: previously registered (via mpt_register) callback handle
597 * @ev_cbfunc: callback function
599 * This routine can be called by one or more protocol-specific drivers
600 * if/when they choose to be notified of MPT events.
602 * Returns 0 for success.
605 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
607 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
610 MptEvHandlers[cb_idx] = ev_cbfunc;
614 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
616 * mpt_event_deregister - Deregister protocol-specific event callback
618 * @cb_idx: previously registered callback handle
620 * Each protocol-specific driver should call this routine
621 * when it does not (or can no longer) handle events,
622 * or when it's module is unloaded.
625 mpt_event_deregister(int cb_idx)
627 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
630 MptEvHandlers[cb_idx] = NULL;
633 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
635 * mpt_reset_register - Register protocol-specific IOC reset handler.
636 * @cb_idx: previously registered (via mpt_register) callback handle
637 * @reset_func: reset function
639 * This routine can be called by one or more protocol-specific drivers
640 * if/when they choose to be notified of IOC resets.
642 * Returns 0 for success.
645 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
647 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
650 MptResetHandlers[cb_idx] = reset_func;
654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
656 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
657 * @cb_idx: previously registered callback handle
659 * Each protocol-specific driver should call this routine
660 * when it does not (or can no longer) handle IOC reset handling,
661 * or when it's module is unloaded.
664 mpt_reset_deregister(int cb_idx)
666 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
669 MptResetHandlers[cb_idx] = NULL;
672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
674 * mpt_device_driver_register - Register device driver hooks
677 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
680 const struct pci_device_id *id;
682 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
685 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
687 /* call per pci device probe entry point */
688 list_for_each_entry(ioc, &ioc_list, list) {
689 id = ioc->pcidev->driver ?
690 ioc->pcidev->driver->id_table : NULL;
691 if (dd_cbfunc->probe)
692 dd_cbfunc->probe(ioc->pcidev, id);
698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
700 * mpt_device_driver_deregister - DeRegister device driver hooks
703 mpt_device_driver_deregister(int cb_idx)
705 struct mpt_pci_driver *dd_cbfunc;
708 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
711 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
713 list_for_each_entry(ioc, &ioc_list, list) {
714 if (dd_cbfunc->remove)
715 dd_cbfunc->remove(ioc->pcidev);
718 MptDeviceDriverHandlers[cb_idx] = NULL;
722 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
724 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
725 * allocated per MPT adapter.
726 * @handle: Handle of registered MPT protocol driver
727 * @ioc: Pointer to MPT adapter structure
729 * Returns pointer to a MPT request frame or %NULL if none are available
730 * or IOC is not active.
733 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
737 u16 req_idx; /* Request index */
739 /* validate handle and ioc identifier */
743 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
746 /* If interrupts are not attached, do not return a request frame */
750 spin_lock_irqsave(&ioc->FreeQlock, flags);
751 if (!list_empty(&ioc->FreeQ)) {
754 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
755 u.frame.linkage.list);
756 list_del(&mf->u.frame.linkage.list);
757 mf->u.frame.linkage.arg1 = 0;
758 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
759 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
761 req_idx = req_offset / ioc->req_sz;
762 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
763 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
764 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
771 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
775 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
777 if (mfcounter == PRINT_MF_COUNT)
778 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
781 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
782 ioc->name, handle, ioc->id, mf));
786 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
788 * mpt_put_msg_frame - Send a protocol specific MPT request frame
790 * @handle: Handle of registered MPT protocol driver
791 * @ioc: Pointer to MPT adapter structure
792 * @mf: Pointer to MPT request frame
794 * This routine posts a MPT request frame to the request post FIFO of a
795 * specific MPT adapter.
798 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
802 u16 req_idx; /* Request index */
804 /* ensure values are reset properly! */
805 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
806 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
808 req_idx = req_offset / ioc->req_sz;
809 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
810 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
812 #ifdef MPT_DEBUG_MSG_FRAME
814 u32 *m = mf->u.frame.hwhdr.__hdr;
817 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
819 n = ioc->req_sz/4 - 1;
822 for (ii=0; ii<=n; ii++) {
823 if (ii && ((ii%8)==0))
824 printk("\n" KERN_INFO " ");
825 printk(" %08x", le32_to_cpu(m[ii]));
831 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
832 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]));
833 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
838 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
839 * @handle: Handle of registered MPT protocol driver
840 * @ioc: Pointer to MPT adapter structure
841 * @mf: Pointer to MPT request frame
843 * This routine places a MPT request frame back on the MPT adapter's
847 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
851 /* Put Request back on FreeQ! */
852 spin_lock_irqsave(&ioc->FreeQlock, flags);
853 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
854 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
858 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
861 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
863 * mpt_add_sge - Place a simple SGE at address pAddr.
864 * @pAddr: virtual address for SGE
865 * @flagslength: SGE flags and data transfer length
866 * @dma_addr: Physical address
868 * This routine places a MPT request frame back on the MPT adapter's
872 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
874 if (sizeof(dma_addr_t) == sizeof(u64)) {
875 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
876 u32 tmp = dma_addr & 0xFFFFFFFF;
878 pSge->FlagsLength = cpu_to_le32(flagslength);
879 pSge->Address.Low = cpu_to_le32(tmp);
880 tmp = (u32) ((u64)dma_addr >> 32);
881 pSge->Address.High = cpu_to_le32(tmp);
884 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
885 pSge->FlagsLength = cpu_to_le32(flagslength);
886 pSge->Address = cpu_to_le32(dma_addr);
890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
892 * mpt_send_handshake_request - Send MPT request via doorbell
894 * @handle: Handle of registered MPT protocol driver
895 * @ioc: Pointer to MPT adapter structure
896 * @reqBytes: Size of the request in bytes
897 * @req: Pointer to MPT request frame
898 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
900 * This routine is used exclusively to send MptScsiTaskMgmt
901 * requests since they are required to be sent via doorbell handshake.
903 * NOTE: It is the callers responsibility to byte-swap fields in the
904 * request which are greater than 1 byte in size.
906 * Returns 0 for success, non-zero for failure.
909 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
915 /* State is known to be good upon entering
916 * this function so issue the bus reset
921 * Emulate what mpt_put_msg_frame() does /wrt to sanity
922 * setting cb_idx/req_idx. But ONLY if this request
923 * is in proper (pre-alloc'd) request buffer range...
925 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
926 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
927 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
928 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
929 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
932 /* Make sure there are no doorbells */
933 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
935 CHIPREG_WRITE32(&ioc->chip->Doorbell,
936 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
937 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
939 /* Wait for IOC doorbell int */
940 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
944 /* Read doorbell and check for active bit */
945 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
948 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
951 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
953 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
957 /* Send request via doorbell handshake */
958 req_as_bytes = (u8 *) req;
959 for (ii = 0; ii < reqBytes/4; ii++) {
962 word = ((req_as_bytes[(ii*4) + 0] << 0) |
963 (req_as_bytes[(ii*4) + 1] << 8) |
964 (req_as_bytes[(ii*4) + 2] << 16) |
965 (req_as_bytes[(ii*4) + 3] << 24));
966 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
967 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
973 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
978 /* Make sure there are no doorbells */
979 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
986 * mpt_host_page_access_control - provides mechanism for the host
987 * driver to control the IOC's Host Page Buffer access.
988 * @ioc: Pointer to MPT adapter structure
989 * @access_control_value: define bits below
991 * Access Control Value - bits[15:12]
993 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
994 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
995 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
997 * Returns 0 for success, non-zero for failure.
1001 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1005 /* return if in use */
1006 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1007 & MPI_DOORBELL_ACTIVE)
1010 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1012 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1013 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1014 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1015 (access_control_value<<12)));
1017 /* Wait for IOC to clear Doorbell Status bit */
1018 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1024 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1026 * mpt_host_page_alloc - allocate system memory for the fw
1027 * If we already allocated memory in past, then resend the same pointer.
1028 * ioc@: Pointer to pointer to IOC adapter
1029 * ioc_init@: Pointer to ioc init config page
1031 * Returns 0 for success, non-zero for failure.
1034 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1038 u32 host_page_buffer_sz=0;
1040 if(!ioc->HostPageBuffer) {
1042 host_page_buffer_sz =
1043 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1045 if(!host_page_buffer_sz)
1046 return 0; /* fw doesn't need any host buffers */
1048 /* spin till we get enough memory */
1049 while(host_page_buffer_sz > 0) {
1051 if((ioc->HostPageBuffer = pci_alloc_consistent(
1053 host_page_buffer_sz,
1054 &ioc->HostPageBuffer_dma)) != NULL) {
1056 dinitprintk((MYIOC_s_INFO_FMT
1057 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1058 ioc->name, ioc->HostPageBuffer,
1059 (u32)ioc->HostPageBuffer_dma,
1060 host_page_buffer_sz));
1061 ioc->alloc_total += host_page_buffer_sz;
1062 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1066 host_page_buffer_sz -= (4*1024);
1070 if(!ioc->HostPageBuffer) {
1071 printk(MYIOC_s_ERR_FMT
1072 "Failed to alloc memory for host_page_buffer!\n",
1077 psge = (char *)&ioc_init->HostPageBufferSGE;
1078 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1079 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1080 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1081 MPI_SGE_FLAGS_HOST_TO_IOC |
1082 MPI_SGE_FLAGS_END_OF_BUFFER;
1083 if (sizeof(dma_addr_t) == sizeof(u64)) {
1084 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1086 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1087 flags_length |= ioc->HostPageBuffer_sz;
1088 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1089 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1094 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1097 * the associated MPT adapter structure.
1098 * @iocid: IOC unique identifier (integer)
1099 * @iocpp: Pointer to pointer to IOC adapter
1101 * Returns iocid and sets iocpp.
1104 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1108 list_for_each_entry(ioc,&ioc_list,list) {
1109 if (ioc->id == iocid) {
1119 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1121 * mpt_attach - Install a PCI intelligent MPT adapter.
1122 * @pdev: Pointer to pci_dev structure
1124 * This routine performs all the steps necessary to bring the IOC of
1125 * a MPT adapter to a OPERATIONAL state. This includes registering
1126 * memory regions, registering the interrupt, and allocating request
1127 * and reply memory pools.
1129 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1132 * Returns 0 for success, non-zero for failure.
1134 * TODO: Add support for polled controllers
1137 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1141 unsigned long mem_phys;
1149 static int mpt_ids = 0;
1150 #ifdef CONFIG_PROC_FS
1151 struct proc_dir_entry *dent, *ent;
1154 if (pci_enable_device(pdev))
1157 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1159 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1160 dprintk((KERN_INFO MYNAM
1161 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1162 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1163 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1167 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1168 dprintk((KERN_INFO MYNAM
1169 ": Using 64 bit consistent mask\n"));
1171 dprintk((KERN_INFO MYNAM
1172 ": Not using 64 bit consistent mask\n"));
1174 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1176 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1179 ioc->alloc_total = sizeof(MPT_ADAPTER);
1180 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1181 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1184 ioc->diagPending = 0;
1185 spin_lock_init(&ioc->diagLock);
1186 spin_lock_init(&ioc->initializing_hba_lock);
1188 /* Initialize the event logging.
1190 ioc->eventTypes = 0; /* None */
1191 ioc->eventContext = 0;
1192 ioc->eventLogSize = 0;
1199 ioc->cached_fw = NULL;
1201 /* Initilize SCSI Config Data structure
1203 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1205 /* Initialize the running configQ head.
1207 INIT_LIST_HEAD(&ioc->configQ);
1209 /* Initialize the fc rport list head.
1211 INIT_LIST_HEAD(&ioc->fc_rports);
1213 /* Find lookup slot. */
1214 INIT_LIST_HEAD(&ioc->list);
1215 ioc->id = mpt_ids++;
1217 mem_phys = msize = 0;
1219 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1220 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1223 /* Get I/O space! */
1224 port = pci_resource_start(pdev, ii);
1225 psize = pci_resource_len(pdev,ii);
1230 mem_phys = pci_resource_start(pdev, ii);
1231 msize = pci_resource_len(pdev,ii);
1234 ioc->mem_size = msize;
1237 /* Get logical ptr for PciMem0 space */
1238 /*mem = ioremap(mem_phys, msize);*/
1239 mem = ioremap(mem_phys, msize);
1241 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1246 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1248 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1249 &ioc->facts, &ioc->pfacts[0]));
1251 ioc->mem_phys = mem_phys;
1252 ioc->chip = (SYSIF_REGS __iomem *)mem;
1254 /* Save Port IO values in case we need to do downloadboot */
1256 u8 *pmem = (u8*)port;
1257 ioc->pio_mem_phys = port;
1258 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1261 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1262 ioc->prod_name = "LSIFC909";
1265 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1266 ioc->prod_name = "LSIFC929";
1269 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1270 ioc->prod_name = "LSIFC919";
1273 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1274 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1276 if (revision < XL_929) {
1277 ioc->prod_name = "LSIFC929X";
1278 /* 929X Chip Fix. Set Split transactions level
1279 * for PCIX. Set MOST bits to zero.
1281 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1283 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1285 ioc->prod_name = "LSIFC929XL";
1286 /* 929XL Chip Fix. Set MMRBC to 0x08.
1288 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1290 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1293 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1294 ioc->prod_name = "LSIFC919X";
1296 /* 919X Chip Fix. Set Split transactions level
1297 * for PCIX. Set MOST bits to zero.
1299 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1301 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1303 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1304 ioc->prod_name = "LSIFC939X";
1306 ioc->errata_flag_1064 = 1;
1308 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1309 ioc->prod_name = "LSIFC949X";
1311 ioc->errata_flag_1064 = 1;
1313 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1314 ioc->prod_name = "LSIFC949E";
1317 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1318 ioc->prod_name = "LSI53C1030";
1319 ioc->bus_type = SPI;
1320 /* 1030 Chip Fix. Disable Split transactions
1321 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1323 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1324 if (revision < C0_1030) {
1325 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1327 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1330 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1331 ioc->prod_name = "LSI53C1035";
1332 ioc->bus_type = SPI;
1334 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1335 ioc->prod_name = "LSISAS1064";
1336 ioc->bus_type = SAS;
1337 ioc->errata_flag_1064 = 1;
1339 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1340 ioc->prod_name = "LSISAS1068";
1341 ioc->bus_type = SAS;
1342 ioc->errata_flag_1064 = 1;
1344 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1345 ioc->prod_name = "LSISAS1064E";
1346 ioc->bus_type = SAS;
1348 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1349 ioc->prod_name = "LSISAS1068E";
1350 ioc->bus_type = SAS;
1352 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
1353 ioc->prod_name = "LSISAS1078";
1354 ioc->bus_type = SAS;
1357 if (ioc->errata_flag_1064)
1358 pci_disable_io_access(pdev);
1360 sprintf(ioc->name, "ioc%d", ioc->id);
1362 spin_lock_init(&ioc->FreeQlock);
1365 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1367 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1369 /* Set lookup ptr. */
1370 list_add_tail(&ioc->list, &ioc_list);
1372 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1374 mpt_detect_bound_ports(ioc, pdev);
1376 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1378 printk(KERN_WARNING MYNAM
1379 ": WARNING - %s did not initialize properly! (%d)\n",
1382 list_del(&ioc->list);
1384 ioc->alt_ioc->alt_ioc = NULL;
1387 pci_set_drvdata(pdev, NULL);
1391 /* call per device driver probe entry point */
1392 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1393 if(MptDeviceDriverHandlers[ii] &&
1394 MptDeviceDriverHandlers[ii]->probe) {
1395 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1399 #ifdef CONFIG_PROC_FS
1401 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1403 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1405 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1407 ent->read_proc = procmpt_iocinfo_read;
1410 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1412 ent->read_proc = procmpt_summary_read;
1421 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1423 * mpt_detach - Remove a PCI intelligent MPT adapter.
1424 * @pdev: Pointer to pci_dev structure
1429 mpt_detach(struct pci_dev *pdev)
1431 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1435 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1436 remove_proc_entry(pname, NULL);
1437 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1438 remove_proc_entry(pname, NULL);
1439 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1440 remove_proc_entry(pname, NULL);
1442 /* call per device driver remove entry point */
1443 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1444 if(MptDeviceDriverHandlers[ii] &&
1445 MptDeviceDriverHandlers[ii]->remove) {
1446 MptDeviceDriverHandlers[ii]->remove(pdev);
1450 /* Disable interrupts! */
1451 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1454 synchronize_irq(pdev->irq);
1456 /* Clear any lingering interrupt */
1457 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1459 CHIPREG_READ32(&ioc->chip->IntStatus);
1461 mpt_adapter_dispose(ioc);
1463 pci_set_drvdata(pdev, NULL);
1466 /**************************************************************************
1470 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1472 * mpt_suspend - Fusion MPT base driver suspend routine.
1477 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1480 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1482 device_state=pci_choose_state(pdev, state);
1484 printk(MYIOC_s_INFO_FMT
1485 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1486 ioc->name, pdev, pci_name(pdev), device_state);
1488 pci_save_state(pdev);
1490 /* put ioc into READY_STATE */
1491 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1492 printk(MYIOC_s_ERR_FMT
1493 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1496 /* disable interrupts */
1497 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1500 /* Clear any lingering interrupt */
1501 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1503 pci_disable_device(pdev);
1504 pci_set_power_state(pdev, device_state);
1509 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1511 * mpt_resume - Fusion MPT base driver resume routine.
1516 mpt_resume(struct pci_dev *pdev)
1518 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1519 u32 device_state = pdev->current_state;
1522 printk(MYIOC_s_INFO_FMT
1523 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1524 ioc->name, pdev, pci_name(pdev), device_state);
1526 pci_set_power_state(pdev, 0);
1527 pci_restore_state(pdev);
1528 pci_enable_device(pdev);
1530 /* enable interrupts */
1531 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1534 printk(MYIOC_s_INFO_FMT
1535 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1537 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1538 CHIPREG_READ32(&ioc->chip->Doorbell));
1540 /* bring ioc to operational state */
1541 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1542 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1543 printk(MYIOC_s_INFO_FMT
1544 "pci-resume: Cannot recover, error:[%x]\n",
1545 ioc->name, recovery_state);
1547 printk(MYIOC_s_INFO_FMT
1548 "pci-resume: success\n", ioc->name);
1556 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1558 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1559 ioc->bus_type != SPI) ||
1560 (MptDriverClass[index] == MPTFC_DRIVER &&
1561 ioc->bus_type != FC) ||
1562 (MptDriverClass[index] == MPTSAS_DRIVER &&
1563 ioc->bus_type != SAS))
1564 /* make sure we only call the relevant reset handler
1567 return (MptResetHandlers[index])(ioc, reset_phase);
1570 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1572 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1573 * @ioc: Pointer to MPT adapter structure
1574 * @reason: Event word / reason
1575 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1577 * This routine performs all the steps necessary to bring the IOC
1578 * to a OPERATIONAL state.
1580 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1585 * -1 if failed to get board READY
1586 * -2 if READY but IOCFacts Failed
1587 * -3 if READY but PrimeIOCFifos Failed
1588 * -4 if READY but IOCInit Failed
1591 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1593 int hard_reset_done = 0;
1594 int alt_ioc_ready = 0;
1600 int reset_alt_ioc_active = 0;
1601 int irq_allocated = 0;
1603 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1604 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1606 /* Disable reply interrupts (also blocks FreeQ) */
1607 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1611 if (ioc->alt_ioc->active)
1612 reset_alt_ioc_active = 1;
1614 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1615 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1616 ioc->alt_ioc->active = 0;
1620 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1623 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1624 if (hard_reset_done == -4) {
1625 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1628 if (reset_alt_ioc_active && ioc->alt_ioc) {
1629 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1630 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1631 ioc->alt_ioc->name));
1632 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1633 ioc->alt_ioc->active = 1;
1637 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1643 /* hard_reset_done = 0 if a soft reset was performed
1644 * and 1 if a hard reset was performed.
1646 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1647 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1650 printk(KERN_WARNING MYNAM
1651 ": alt-%s: Not ready WARNING!\n",
1652 ioc->alt_ioc->name);
1655 for (ii=0; ii<5; ii++) {
1656 /* Get IOC facts! Allow 5 retries */
1657 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1663 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1665 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1666 MptDisplayIocCapabilities(ioc);
1669 if (alt_ioc_ready) {
1670 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1671 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1672 /* Retry - alt IOC was initialized once
1674 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1677 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1679 reset_alt_ioc_active = 0;
1680 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1681 MptDisplayIocCapabilities(ioc->alt_ioc);
1686 * Device is reset now. It must have de-asserted the interrupt line
1687 * (if it was asserted) and it should be safe to register for the
1690 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1692 if (ioc->pcidev->irq) {
1693 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1694 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1696 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1697 IRQF_SHARED, ioc->name, ioc);
1699 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1700 "interrupt %d!\n", ioc->name,
1703 pci_disable_msi(ioc->pcidev);
1707 ioc->pci_irq = ioc->pcidev->irq;
1708 pci_set_master(ioc->pcidev); /* ?? */
1709 pci_set_drvdata(ioc->pcidev, ioc);
1710 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1711 "%d\n", ioc->name, ioc->pcidev->irq));
1715 /* Prime reply & request queues!
1716 * (mucho alloc's) Must be done prior to
1717 * init as upper addresses are needed for init.
1718 * If fails, continue with alt-ioc processing
1720 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1723 /* May need to check/upload firmware & data here!
1724 * If fails, continue with alt-ioc processing
1726 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1729 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1730 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1731 ioc->alt_ioc->name, rc);
1733 reset_alt_ioc_active = 0;
1736 if (alt_ioc_ready) {
1737 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1739 reset_alt_ioc_active = 0;
1740 printk(KERN_WARNING MYNAM
1741 ": alt-%s: (%d) init failure WARNING!\n",
1742 ioc->alt_ioc->name, rc);
1746 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1747 if (ioc->upload_fw) {
1748 ddlprintk((MYIOC_s_INFO_FMT
1749 "firmware upload required!\n", ioc->name));
1751 /* Controller is not operational, cannot do upload
1754 rc = mpt_do_upload(ioc, sleepFlag);
1756 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1758 * Maintain only one pointer to FW memory
1759 * so there will not be two attempt to
1760 * downloadboot onboard dual function
1761 * chips (mpt_adapter_disable,
1764 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1765 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1766 ioc->alt_ioc->cached_fw = NULL;
1769 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1777 /* Enable! (reply interrupt) */
1778 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1782 if (reset_alt_ioc_active && ioc->alt_ioc) {
1783 /* (re)Enable alt-IOC! (reply interrupt) */
1784 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1785 ioc->alt_ioc->name));
1786 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1787 ioc->alt_ioc->active = 1;
1790 /* Enable MPT base driver management of EventNotification
1791 * and EventAck handling.
1793 if ((ret == 0) && (!ioc->facts.EventState))
1794 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1796 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1797 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1799 /* Add additional "reason" check before call to GetLanConfigPages
1800 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1801 * recursive scenario; GetLanConfigPages times out, timer expired
1802 * routine calls HardResetHandler, which calls into here again,
1803 * and we try GetLanConfigPages again...
1805 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1806 if (ioc->bus_type == SAS) {
1808 /* clear persistency table */
1809 if(ioc->facts.IOCExceptions &
1810 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1811 ret = mptbase_sas_persist_operation(ioc,
1812 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1819 mpt_findImVolumes(ioc);
1821 } else if (ioc->bus_type == FC) {
1822 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1823 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1825 * Pre-fetch the ports LAN MAC address!
1826 * (LANPage1_t stuff)
1828 (void) GetLanConfigPages(ioc);
1831 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1832 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1833 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1838 /* Get NVRAM and adapter maximums from SPP 0 and 2
1840 mpt_GetScsiPortSettings(ioc, 0);
1842 /* Get version and length of SDP 1
1844 mpt_readScsiDevicePageHeaders(ioc, 0);
1848 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1849 mpt_findImVolumes(ioc);
1851 /* Check, and possibly reset, the coalescing value
1853 mpt_read_ioc_pg_1(ioc);
1855 mpt_read_ioc_pg_4(ioc);
1858 GetIoUnitPage2(ioc);
1862 * Call each currently registered protocol IOC reset handler
1863 * with post-reset indication.
1864 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1865 * MptResetHandlers[] registered yet.
1867 if (hard_reset_done) {
1869 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1870 if ((ret == 0) && MptResetHandlers[ii]) {
1871 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1873 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1877 if (alt_ioc_ready && MptResetHandlers[ii]) {
1878 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1879 ioc->name, ioc->alt_ioc->name, ii));
1880 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1884 /* FIXME? Examine results here? */
1888 if ((ret != 0) && irq_allocated) {
1889 free_irq(ioc->pci_irq, ioc);
1891 pci_disable_msi(ioc->pcidev);
1896 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1898 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1899 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1900 * 929X, 1030 or 1035.
1901 * @ioc: Pointer to MPT adapter structure
1902 * @pdev: Pointer to (struct pci_dev) structure
1904 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1905 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1908 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1910 struct pci_dev *peer=NULL;
1911 unsigned int slot = PCI_SLOT(pdev->devfn);
1912 unsigned int func = PCI_FUNC(pdev->devfn);
1913 MPT_ADAPTER *ioc_srch;
1915 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1916 " searching for devfn match on %x or %x\n",
1917 ioc->name, pci_name(pdev), pdev->bus->number,
1918 pdev->devfn, func-1, func+1));
1920 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1922 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1927 list_for_each_entry(ioc_srch, &ioc_list, list) {
1928 struct pci_dev *_pcidev = ioc_srch->pcidev;
1929 if (_pcidev == peer) {
1930 /* Paranoia checks */
1931 if (ioc->alt_ioc != NULL) {
1932 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1933 ioc->name, ioc->alt_ioc->name);
1935 } else if (ioc_srch->alt_ioc != NULL) {
1936 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1937 ioc_srch->name, ioc_srch->alt_ioc->name);
1940 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1941 ioc->name, ioc_srch->name));
1942 ioc_srch->alt_ioc = ioc;
1943 ioc->alt_ioc = ioc_srch;
1949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1951 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1952 * @this: Pointer to MPT adapter structure
1955 mpt_adapter_disable(MPT_ADAPTER *ioc)
1960 if (ioc->cached_fw != NULL) {
1961 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1962 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1963 printk(KERN_WARNING MYNAM
1964 ": firmware downloadboot failure (%d)!\n", ret);
1968 /* Disable adapter interrupts! */
1969 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1971 /* Clear any lingering interrupt */
1972 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1974 if (ioc->alloc != NULL) {
1976 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1977 ioc->name, ioc->alloc, ioc->alloc_sz));
1978 pci_free_consistent(ioc->pcidev, sz,
1979 ioc->alloc, ioc->alloc_dma);
1980 ioc->reply_frames = NULL;
1981 ioc->req_frames = NULL;
1983 ioc->alloc_total -= sz;
1986 if (ioc->sense_buf_pool != NULL) {
1987 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1988 pci_free_consistent(ioc->pcidev, sz,
1989 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
1990 ioc->sense_buf_pool = NULL;
1991 ioc->alloc_total -= sz;
1994 if (ioc->events != NULL){
1995 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1998 ioc->alloc_total -= sz;
2001 if (ioc->cached_fw != NULL) {
2002 sz = ioc->facts.FWImageSize;
2003 pci_free_consistent(ioc->pcidev, sz,
2004 ioc->cached_fw, ioc->cached_fw_dma);
2005 ioc->cached_fw = NULL;
2006 ioc->alloc_total -= sz;
2009 kfree(ioc->spi_data.nvram);
2010 kfree(ioc->raid_data.pIocPg3);
2011 ioc->spi_data.nvram = NULL;
2012 ioc->raid_data.pIocPg3 = NULL;
2014 if (ioc->spi_data.pIocPg4 != NULL) {
2015 sz = ioc->spi_data.IocPg4Sz;
2016 pci_free_consistent(ioc->pcidev, sz,
2017 ioc->spi_data.pIocPg4,
2018 ioc->spi_data.IocPg4_dma);
2019 ioc->spi_data.pIocPg4 = NULL;
2020 ioc->alloc_total -= sz;
2023 if (ioc->ReqToChain != NULL) {
2024 kfree(ioc->ReqToChain);
2025 kfree(ioc->RequestNB);
2026 ioc->ReqToChain = NULL;
2029 kfree(ioc->ChainToChain);
2030 ioc->ChainToChain = NULL;
2032 if (ioc->HostPageBuffer != NULL) {
2033 if((ret = mpt_host_page_access_control(ioc,
2034 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2035 printk(KERN_ERR MYNAM
2036 ": %s: host page buffers free failed (%d)!\n",
2039 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2040 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2041 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2042 ioc->HostPageBuffer,
2043 ioc->HostPageBuffer_dma);
2044 ioc->HostPageBuffer = NULL;
2045 ioc->HostPageBuffer_sz = 0;
2046 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2052 * mpt_adapter_dispose - Free all resources associated with a MPT
2054 * @ioc: Pointer to MPT adapter structure
2056 * This routine unregisters h/w resources and frees all alloc'd memory
2057 * associated with a MPT adapter structure.
2060 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2062 int sz_first, sz_last;
2067 sz_first = ioc->alloc_total;
2069 mpt_adapter_disable(ioc);
2071 if (ioc->pci_irq != -1) {
2072 free_irq(ioc->pci_irq, ioc);
2074 pci_disable_msi(ioc->pcidev);
2078 if (ioc->memmap != NULL) {
2079 iounmap(ioc->memmap);
2083 #if defined(CONFIG_MTRR) && 0
2084 if (ioc->mtrr_reg > 0) {
2085 mtrr_del(ioc->mtrr_reg, 0, 0);
2086 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2090 /* Zap the adapter lookup ptr! */
2091 list_del(&ioc->list);
2093 sz_last = ioc->alloc_total;
2094 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2095 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2098 ioc->alt_ioc->alt_ioc = NULL;
2103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2105 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2106 * @ioc: Pointer to MPT adapter structure
2109 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2113 printk(KERN_INFO "%s: ", ioc->name);
2114 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2115 printk("%s: ", ioc->prod_name+3);
2116 printk("Capabilities={");
2118 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2119 printk("Initiator");
2123 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2124 printk("%sTarget", i ? "," : "");
2128 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2129 printk("%sLAN", i ? "," : "");
2135 * This would probably evoke more questions than it's worth
2137 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2138 printk("%sLogBusAddr", i ? "," : "");
2146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2148 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2149 * @ioc: Pointer to MPT_ADAPTER structure
2150 * @force: Force hard KickStart of IOC
2151 * @sleepFlag: Specifies whether the process can sleep
2154 * 1 - DIAG reset and READY
2155 * 0 - READY initially OR soft reset and READY
2156 * -1 - Any failure on KickStart
2157 * -2 - Msg Unit Reset Failed
2158 * -3 - IO Unit Reset Failed
2159 * -4 - IOC owned by a PEER
2162 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2167 int hard_reset_done = 0;
2172 /* Get current [raw] IOC state */
2173 ioc_state = mpt_GetIocState(ioc, 0);
2174 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2177 * Check to see if IOC got left/stuck in doorbell handshake
2178 * grip of death. If so, hard reset the IOC.
2180 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2182 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2186 /* Is it already READY? */
2187 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2191 * Check to see if IOC is in FAULT state.
2193 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2195 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2197 printk(KERN_WARNING " FAULT code = %04xh\n",
2198 ioc_state & MPI_DOORBELL_DATA_MASK);
2202 * Hmmm... Did it get left operational?
2204 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2205 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2209 * If PCI Peer, exit.
2210 * Else, if no fault conditions are present, issue a MessageUnitReset
2211 * Else, fall through to KickStart case
2213 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2214 dinitprintk((KERN_INFO MYNAM
2215 ": whoinit 0x%x statefault %d force %d\n",
2216 whoinit, statefault, force));
2217 if (whoinit == MPI_WHOINIT_PCI_PEER)
2220 if ((statefault == 0 ) && (force == 0)) {
2221 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2228 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2229 if (hard_reset_done < 0)
2233 * Loop here waiting for IOC to come READY.
2236 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2238 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2239 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2241 * BIOS or previous driver load left IOC in OP state.
2242 * Reset messaging FIFOs.
2244 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2245 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2248 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2250 * Something is wrong. Try to get IOC back
2253 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2254 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2261 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2262 ioc->name, (int)((ii+5)/HZ));
2266 if (sleepFlag == CAN_SLEEP) {
2269 mdelay (1); /* 1 msec delay */
2274 if (statefault < 3) {
2275 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2277 statefault==1 ? "stuck handshake" : "IOC FAULT");
2280 return hard_reset_done;
2283 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2285 * mpt_GetIocState - Get the current state of a MPT adapter.
2286 * @ioc: Pointer to MPT_ADAPTER structure
2287 * @cooked: Request raw or cooked IOC state
2289 * Returns all IOC Doorbell register bits if cooked==0, else just the
2290 * Doorbell bits in MPI_IOC_STATE_MASK.
2293 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2298 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2299 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2300 sc = s & MPI_IOC_STATE_MASK;
2303 ioc->last_state = sc;
2305 return cooked ? sc : s;
2308 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2310 * GetIocFacts - Send IOCFacts request to MPT adapter.
2311 * @ioc: Pointer to MPT_ADAPTER structure
2312 * @sleepFlag: Specifies whether the process can sleep
2313 * @reason: If recovery, only update facts.
2315 * Returns 0 for success, non-zero for failure.
2318 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2320 IOCFacts_t get_facts;
2321 IOCFactsReply_t *facts;
2329 /* IOC *must* NOT be in RESET state! */
2330 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2331 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2337 facts = &ioc->facts;
2339 /* Destination (reply area)... */
2340 reply_sz = sizeof(*facts);
2341 memset(facts, 0, reply_sz);
2343 /* Request area (get_facts on the stack right now!) */
2344 req_sz = sizeof(get_facts);
2345 memset(&get_facts, 0, req_sz);
2347 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2348 /* Assert: All other get_facts fields are zero! */
2350 dinitprintk((MYIOC_s_INFO_FMT
2351 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2352 ioc->name, req_sz, reply_sz));
2354 /* No non-zero fields in the get_facts request are greater than
2355 * 1 byte in size, so we can just fire it off as is.
2357 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2358 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2363 * Now byte swap (GRRR) the necessary fields before any further
2364 * inspection of reply contents.
2366 * But need to do some sanity checks on MsgLength (byte) field
2367 * to make sure we don't zero IOC's req_sz!
2369 /* Did we get a valid reply? */
2370 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2371 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2373 * If not been here, done that, save off first WhoInit value
2375 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2376 ioc->FirstWhoInit = facts->WhoInit;
2379 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2380 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2381 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2382 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2383 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2384 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2385 /* CHECKME! IOCStatus, IOCLogInfo */
2387 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2388 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2391 * FC f/w version changed between 1.1 and 1.2
2392 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2393 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2395 if (facts->MsgVersion < 0x0102) {
2397 * Handle old FC f/w style, convert to new...
2399 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2400 facts->FWVersion.Word =
2401 ((oldv<<12) & 0xFF000000) |
2402 ((oldv<<8) & 0x000FFF00);
2404 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2406 facts->ProductID = le16_to_cpu(facts->ProductID);
2407 facts->CurrentHostMfaHighAddr =
2408 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2409 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2410 facts->CurrentSenseBufferHighAddr =
2411 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2412 facts->CurReplyFrameSize =
2413 le16_to_cpu(facts->CurReplyFrameSize);
2414 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2417 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2418 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2419 * to 14 in MPI-1.01.0x.
2421 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2422 facts->MsgVersion > 0x0100) {
2423 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2426 sz = facts->FWImageSize;
2431 facts->FWImageSize = sz;
2433 if (!facts->RequestFrameSize) {
2434 /* Something is wrong! */
2435 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2440 r = sz = facts->BlockSize;
2441 vv = ((63 / (sz * 4)) + 1) & 0x03;
2442 ioc->NB_for_64_byte_frame = vv;
2448 ioc->NBShiftFactor = shiftFactor;
2449 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2450 ioc->name, vv, shiftFactor, r));
2452 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2454 * Set values for this IOC's request & reply frame sizes,
2455 * and request & reply queue depths...
2457 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2458 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2459 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2460 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2462 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2463 ioc->name, ioc->reply_sz, ioc->reply_depth));
2464 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2465 ioc->name, ioc->req_sz, ioc->req_depth));
2467 /* Get port facts! */
2468 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2472 printk(MYIOC_s_ERR_FMT
2473 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2474 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2475 RequestFrameSize)/sizeof(u32)));
2482 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2484 * GetPortFacts - Send PortFacts request to MPT adapter.
2485 * @ioc: Pointer to MPT_ADAPTER structure
2486 * @portnum: Port number
2487 * @sleepFlag: Specifies whether the process can sleep
2489 * Returns 0 for success, non-zero for failure.
2492 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2494 PortFacts_t get_pfacts;
2495 PortFactsReply_t *pfacts;
2500 /* IOC *must* NOT be in RESET state! */
2501 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2502 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2508 pfacts = &ioc->pfacts[portnum];
2510 /* Destination (reply area)... */
2511 reply_sz = sizeof(*pfacts);
2512 memset(pfacts, 0, reply_sz);
2514 /* Request area (get_pfacts on the stack right now!) */
2515 req_sz = sizeof(get_pfacts);
2516 memset(&get_pfacts, 0, req_sz);
2518 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2519 get_pfacts.PortNumber = portnum;
2520 /* Assert: All other get_pfacts fields are zero! */
2522 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2523 ioc->name, portnum));
2525 /* No non-zero fields in the get_pfacts request are greater than
2526 * 1 byte in size, so we can just fire it off as is.
2528 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2529 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2533 /* Did we get a valid reply? */
2535 /* Now byte swap the necessary fields in the response. */
2536 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2537 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2538 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2539 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2540 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2541 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2542 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2543 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2544 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2549 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2551 * SendIocInit - Send IOCInit request to MPT adapter.
2552 * @ioc: Pointer to MPT_ADAPTER structure
2553 * @sleepFlag: Specifies whether the process can sleep
2555 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2557 * Returns 0 for success, non-zero for failure.
2560 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2563 MPIDefaultReply_t init_reply;
2569 memset(&ioc_init, 0, sizeof(ioc_init));
2570 memset(&init_reply, 0, sizeof(init_reply));
2572 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2573 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2575 /* If we are in a recovery mode and we uploaded the FW image,
2576 * then this pointer is not NULL. Skip the upload a second time.
2577 * Set this flag if cached_fw set for either IOC.
2579 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2583 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2584 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2586 if(ioc->bus_type == SAS)
2587 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2588 else if(ioc->bus_type == FC)
2589 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2591 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2592 ioc_init.MaxBuses = MPT_MAX_BUS;
2593 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2594 ioc->name, ioc->facts.MsgVersion));
2595 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2596 // set MsgVersion and HeaderVersion host driver was built with
2597 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2598 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2600 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2601 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2602 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2605 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2607 if (sizeof(dma_addr_t) == sizeof(u64)) {
2608 /* Save the upper 32-bits of the request
2609 * (reply) and sense buffers.
2611 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2612 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2614 /* Force 32-bit addressing */
2615 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2616 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2619 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2620 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2621 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2622 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2624 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2625 ioc->name, &ioc_init));
2627 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2628 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2630 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2634 /* No need to byte swap the multibyte fields in the reply
2635 * since we don't even look at it's contents.
2638 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2639 ioc->name, &ioc_init));
2641 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2642 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2646 /* YIKES! SUPER IMPORTANT!!!
2647 * Poll IocState until _OPERATIONAL while IOC is doing
2648 * LoopInit and TargetDiscovery!
2651 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2652 state = mpt_GetIocState(ioc, 1);
2653 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2654 if (sleepFlag == CAN_SLEEP) {
2661 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2662 ioc->name, (int)((count+5)/HZ));
2666 state = mpt_GetIocState(ioc, 1);
2669 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2672 ioc->aen_event_read_flag=0;
2676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2678 * SendPortEnable - Send PortEnable request to MPT adapter port.
2679 * @ioc: Pointer to MPT_ADAPTER structure
2680 * @portnum: Port number to enable
2681 * @sleepFlag: Specifies whether the process can sleep
2683 * Send PortEnable to bring IOC to OPERATIONAL state.
2685 * Returns 0 for success, non-zero for failure.
2688 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2690 PortEnable_t port_enable;
2691 MPIDefaultReply_t reply_buf;
2696 /* Destination... */
2697 reply_sz = sizeof(MPIDefaultReply_t);
2698 memset(&reply_buf, 0, reply_sz);
2700 req_sz = sizeof(PortEnable_t);
2701 memset(&port_enable, 0, req_sz);
2703 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2704 port_enable.PortNumber = portnum;
2705 /* port_enable.ChainOffset = 0; */
2706 /* port_enable.MsgFlags = 0; */
2707 /* port_enable.MsgContext = 0; */
2709 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2710 ioc->name, portnum, &port_enable));
2712 /* RAID FW may take a long time to enable
2714 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2715 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2716 (ioc->bus_type == SAS)) {
2717 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2718 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2719 300 /*seconds*/, sleepFlag);
2721 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2722 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2723 30 /*seconds*/, sleepFlag);
2729 * ioc: Pointer to MPT_ADAPTER structure
2730 * size - total FW bytes
2733 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2736 return; /* use already allocated memory */
2737 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2738 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2739 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2740 ioc->alloc_total += size;
2741 ioc->alt_ioc->alloc_total -= size;
2743 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2744 ioc->alloc_total += size;
2748 * If alt_img is NULL, delete from ioc structure.
2749 * Else, delete a secondary image in same format.
2752 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2756 sz = ioc->facts.FWImageSize;
2757 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2758 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2759 pci_free_consistent(ioc->pcidev, sz,
2760 ioc->cached_fw, ioc->cached_fw_dma);
2761 ioc->cached_fw = NULL;
2767 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2769 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2770 * @ioc: Pointer to MPT_ADAPTER structure
2771 * @sleepFlag: Specifies whether the process can sleep
2773 * Returns 0 for success, >0 for handshake failure
2774 * <0 for fw upload failure.
2776 * Remark: If bound IOC and a successful FWUpload was performed
2777 * on the bound IOC, the second image is discarded
2778 * and memory is free'd. Both channels must upload to prevent
2779 * IOC from running in degraded mode.
2782 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2784 u8 request[ioc->req_sz];
2785 u8 reply[sizeof(FWUploadReply_t)];
2786 FWUpload_t *prequest;
2787 FWUploadReply_t *preply;
2788 FWUploadTCSGE_t *ptcsge;
2791 int ii, sz, reply_sz;
2794 /* If the image size is 0, we are done.
2796 if ((sz = ioc->facts.FWImageSize) == 0)
2799 mpt_alloc_fw_memory(ioc, sz);
2801 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2802 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2804 if (ioc->cached_fw == NULL) {
2810 prequest = (FWUpload_t *)&request;
2811 preply = (FWUploadReply_t *)&reply;
2813 /* Destination... */
2814 memset(prequest, 0, ioc->req_sz);
2816 reply_sz = sizeof(reply);
2817 memset(preply, 0, reply_sz);
2819 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2820 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2822 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2823 ptcsge->DetailsLength = 12;
2824 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2825 ptcsge->ImageSize = cpu_to_le32(sz);
2827 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2829 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2830 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2832 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2833 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2834 prequest, sgeoffset));
2835 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2837 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2838 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2840 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2842 cmdStatus = -EFAULT;
2844 /* Handshake transfer was complete and successful.
2845 * Check the Reply Frame.
2847 int status, transfer_sz;
2848 status = le16_to_cpu(preply->IOCStatus);
2849 if (status == MPI_IOCSTATUS_SUCCESS) {
2850 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2851 if (transfer_sz == sz)
2855 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2856 ioc->name, cmdStatus));
2861 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2863 mpt_free_fw_memory(ioc);
2869 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2871 * mpt_downloadboot - DownloadBoot code
2872 * @ioc: Pointer to MPT_ADAPTER structure
2873 * @flag: Specify which part of IOC memory is to be uploaded.
2874 * @sleepFlag: Specifies whether the process can sleep
2876 * FwDownloadBoot requires Programmed IO access.
2878 * Returns 0 for success
2879 * -1 FW Image size is 0
2880 * -2 No valid cached_fw Pointer
2881 * <0 for fw upload failure.
2884 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2886 MpiExtImageHeader_t *pExtImage;
2896 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2897 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2899 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2900 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2901 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2902 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2903 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2904 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2906 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2909 if (sleepFlag == CAN_SLEEP) {
2915 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2916 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2918 for (count = 0; count < 30; count ++) {
2919 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2920 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2921 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2926 if (sleepFlag == CAN_SLEEP) {
2933 if ( count == 30 ) {
2934 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2935 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2936 ioc->name, diag0val));
2940 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2941 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2942 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2943 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2944 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2945 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2947 /* Set the DiagRwEn and Disable ARM bits */
2948 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2950 fwSize = (pFwHeader->ImageSize + 3)/4;
2951 ptrFw = (u32 *) pFwHeader;
2953 /* Write the LoadStartAddress to the DiagRw Address Register
2954 * using Programmed IO
2956 if (ioc->errata_flag_1064)
2957 pci_enable_io_access(ioc->pcidev);
2959 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2960 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2961 ioc->name, pFwHeader->LoadStartAddress));
2963 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2964 ioc->name, fwSize*4, ptrFw));
2966 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2969 nextImage = pFwHeader->NextImageHeaderOffset;
2971 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2973 load_addr = pExtImage->LoadStartAddress;
2975 fwSize = (pExtImage->ImageSize + 3) >> 2;
2976 ptrFw = (u32 *)pExtImage;
2978 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
2979 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
2980 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2983 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2985 nextImage = pExtImage->NextImageHeaderOffset;
2988 /* Write the IopResetVectorRegAddr */
2989 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2990 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2992 /* Write the IopResetVectorValue */
2993 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
2994 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
2996 /* Clear the internal flash bad bit - autoincrementing register,
2997 * so must do two writes.
2999 if (ioc->bus_type == SPI) {
3001 * 1030 and 1035 H/W errata, workaround to access
3002 * the ClearFlashBadSignatureBit
3004 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3005 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3006 diagRwData |= 0x40000000;
3007 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3008 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3010 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3011 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3012 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3013 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3016 if (sleepFlag == CAN_SLEEP) {
3023 if (ioc->errata_flag_1064)
3024 pci_disable_io_access(ioc->pcidev);
3026 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3027 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3028 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3029 ioc->name, diag0val));
3030 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3031 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3032 ioc->name, diag0val));
3033 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3035 /* Write 0xFF to reset the sequencer */
3036 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3038 if (ioc->bus_type == SAS) {
3039 ioc_state = mpt_GetIocState(ioc, 0);
3040 if ( (GetIocFacts(ioc, sleepFlag,
3041 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3042 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3043 ioc->name, ioc_state));
3048 for (count=0; count<HZ*20; count++) {
3049 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3050 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3051 ioc->name, count, ioc_state));
3052 if (ioc->bus_type == SAS) {
3055 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3056 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3060 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3064 if (sleepFlag == CAN_SLEEP) {
3070 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3071 ioc->name, ioc_state));
3075 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3077 * KickStart - Perform hard reset of MPT adapter.
3078 * @ioc: Pointer to MPT_ADAPTER structure
3079 * @force: Force hard reset
3080 * @sleepFlag: Specifies whether the process can sleep
3082 * This routine places MPT adapter in diagnostic mode via the
3083 * WriteSequence register, and then performs a hard reset of adapter
3084 * via the Diagnostic register.
3086 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3087 * or NO_SLEEP (interrupt thread, use mdelay)
3088 * force - 1 if doorbell active, board fault state
3089 * board operational, IOC_RECOVERY or
3090 * IOC_BRINGUP and there is an alt_ioc.
3094 * 1 - hard reset, READY
3095 * 0 - no reset due to History bit, READY
3096 * -1 - no reset due to History bit but not READY
3097 * OR reset but failed to come READY
3098 * -2 - no reset, could not enter DIAG mode
3099 * -3 - reset but bad FW bit
3102 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3104 int hard_reset_done = 0;
3108 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3109 if (ioc->bus_type == SPI) {
3110 /* Always issue a Msg Unit Reset first. This will clear some
3111 * SCSI bus hang conditions.
3113 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3115 if (sleepFlag == CAN_SLEEP) {
3122 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3123 if (hard_reset_done < 0)
3124 return hard_reset_done;
3126 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3129 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3130 for (cnt=0; cnt<cntdn; cnt++) {
3131 ioc_state = mpt_GetIocState(ioc, 1);
3132 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3133 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3135 return hard_reset_done;
3137 if (sleepFlag == CAN_SLEEP) {
3144 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3145 ioc->name, ioc_state);
3149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3151 * mpt_diag_reset - Perform hard reset of the adapter.
3152 * @ioc: Pointer to MPT_ADAPTER structure
3153 * @ignore: Set if to honor and clear to ignore
3154 * the reset history bit
3155 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3156 * else set to NO_SLEEP (use mdelay instead)
3158 * This routine places the adapter in diagnostic mode via the
3159 * WriteSequence register and then performs a hard reset of adapter
3160 * via the Diagnostic register. Adapter should be in ready state
3161 * upon successful completion.
3163 * Returns: 1 hard reset successful
3164 * 0 no reset performed because reset history bit set
3165 * -2 enabling diagnostic mode failed
3166 * -3 diagnostic reset failed
3169 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3171 MPT_ADAPTER *iocp=NULL;
3174 int hard_reset_done = 0;
3180 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3181 drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3182 "address=%p\n", ioc->name, __FUNCTION__,
3183 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3184 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3185 if (sleepFlag == CAN_SLEEP)
3190 for (count = 0; count < 60; count ++) {
3191 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3192 doorbell &= MPI_IOC_STATE_MASK;
3194 drsprintk((MYIOC_s_INFO_FMT
3195 "looking for READY STATE: doorbell=%x"
3197 ioc->name, doorbell, count));
3198 if (doorbell == MPI_IOC_STATE_READY) {
3203 if (sleepFlag == CAN_SLEEP)
3211 /* Clear any existing interrupts */
3212 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3214 /* Use "Diagnostic reset" method! (only thing available!) */
3215 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3219 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3220 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3221 ioc->name, diag0val, diag1val));
3224 /* Do the reset if we are told to ignore the reset history
3225 * or if the reset history is 0
3227 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3228 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3229 /* Write magic sequence to WriteSequence register
3230 * Loop until in diagnostic mode
3232 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3233 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3234 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3235 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3236 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3237 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3240 if (sleepFlag == CAN_SLEEP) {
3248 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3249 ioc->name, diag0val);
3254 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3256 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3257 ioc->name, diag0val));
3262 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3263 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3264 ioc->name, diag0val, diag1val));
3267 * Disable the ARM (Bug fix)
3270 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3274 * Now hit the reset bit in the Diagnostic register
3275 * (THE BIG HAMMER!) (Clears DRWE bit).
3277 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3278 hard_reset_done = 1;
3279 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3283 * Call each currently registered protocol IOC reset handler
3284 * with pre-reset indication.
3285 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3286 * MptResetHandlers[] registered yet.
3292 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3293 if (MptResetHandlers[ii]) {
3294 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3296 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3298 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3299 ioc->name, ioc->alt_ioc->name, ii));
3300 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3304 /* FIXME? Examine results here? */
3309 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3310 iocp = ioc->alt_ioc;
3312 /* If the DownloadBoot operation fails, the
3313 * IOC will be left unusable. This is a fatal error
3314 * case. _diag_reset will return < 0
3316 for (count = 0; count < 30; count ++) {
3317 diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
3318 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3322 dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
3323 iocp->name, diag0val, count));
3325 if (sleepFlag == CAN_SLEEP) {
3331 if ((count = mpt_downloadboot(ioc,
3332 (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
3333 printk(KERN_WARNING MYNAM
3334 ": firmware downloadboot failure (%d)!\n", count);
3338 /* Wait for FW to reload and for board
3339 * to go to the READY state.
3340 * Maximum wait is 60 seconds.
3341 * If fail, no error will check again
3342 * with calling program.
3344 for (count = 0; count < 60; count ++) {
3345 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3346 doorbell &= MPI_IOC_STATE_MASK;
3348 if (doorbell == MPI_IOC_STATE_READY) {
3353 if (sleepFlag == CAN_SLEEP) {
3362 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3365 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3366 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3367 ioc->name, diag0val, diag1val));
3370 /* Clear RESET_HISTORY bit! Place board in the
3371 * diagnostic mode to update the diag register.
3373 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3375 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3376 /* Write magic sequence to WriteSequence register
3377 * Loop until in diagnostic mode
3379 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3380 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3381 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3382 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3383 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3384 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3387 if (sleepFlag == CAN_SLEEP) {
3395 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3396 ioc->name, diag0val);
3399 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3401 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3402 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3403 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3404 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3405 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3409 /* Disable Diagnostic Mode
3411 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3413 /* Check FW reload status flags.
3415 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3416 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3417 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3418 ioc->name, diag0val);
3424 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3425 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3426 ioc->name, diag0val, diag1val));
3430 * Reset flag that says we've enabled event notification
3432 ioc->facts.EventState = 0;
3435 ioc->alt_ioc->facts.EventState = 0;
3437 return hard_reset_done;
3440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3442 * SendIocReset - Send IOCReset request to MPT adapter.
3443 * @ioc: Pointer to MPT_ADAPTER structure
3444 * @reset_type: reset type, expected values are
3445 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3447 * Send IOCReset request to the MPT adapter.
3449 * Returns 0 for success, non-zero for failure.
3452 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3458 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3459 ioc->name, reset_type));
3460 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3461 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3464 /* FW ACK'd request, wait for READY state
3467 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3469 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3473 if (sleepFlag != CAN_SLEEP)
3476 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3477 ioc->name, (int)((count+5)/HZ));
3481 if (sleepFlag == CAN_SLEEP) {
3484 mdelay (1); /* 1 msec delay */
3489 * Cleanup all event stuff for this IOC; re-issue EventNotification
3490 * request if needed.
3492 if (ioc->facts.Function)
3493 ioc->facts.EventState = 0;
3498 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3500 * initChainBuffers - Allocate memory for and initialize
3501 * chain buffers, chain buffer control arrays and spinlock.
3502 * @hd: Pointer to MPT_SCSI_HOST structure
3503 * @init: If set, initialize the spin lock.
3506 initChainBuffers(MPT_ADAPTER *ioc)
3509 int sz, ii, num_chain;
3510 int scale, num_sge, numSGE;
3512 /* ReqToChain size must equal the req_depth
3515 if (ioc->ReqToChain == NULL) {
3516 sz = ioc->req_depth * sizeof(int);
3517 mem = kmalloc(sz, GFP_ATOMIC);
3521 ioc->ReqToChain = (int *) mem;
3522 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3523 ioc->name, mem, sz));
3524 mem = kmalloc(sz, GFP_ATOMIC);
3528 ioc->RequestNB = (int *) mem;
3529 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3530 ioc->name, mem, sz));
3532 for (ii = 0; ii < ioc->req_depth; ii++) {
3533 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3536 /* ChainToChain size must equal the total number
3537 * of chain buffers to be allocated.
3540 * Calculate the number of chain buffers needed(plus 1) per I/O
3541 * then multiply the the maximum number of simultaneous cmds
3543 * num_sge = num sge in request frame + last chain buffer
3544 * scale = num sge per chain buffer if no chain element
3546 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3547 if (sizeof(dma_addr_t) == sizeof(u64))
3548 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3550 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3552 if (sizeof(dma_addr_t) == sizeof(u64)) {
3553 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3554 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3556 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3557 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3559 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3560 ioc->name, num_sge, numSGE));
3562 if ( numSGE > MPT_SCSI_SG_DEPTH )
3563 numSGE = MPT_SCSI_SG_DEPTH;
3566 while (numSGE - num_sge > 0) {
3568 num_sge += (scale - 1);
3572 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3573 ioc->name, numSGE, num_sge, num_chain));
3575 if (ioc->bus_type == SPI)
3576 num_chain *= MPT_SCSI_CAN_QUEUE;
3578 num_chain *= MPT_FC_CAN_QUEUE;
3580 ioc->num_chain = num_chain;
3582 sz = num_chain * sizeof(int);
3583 if (ioc->ChainToChain == NULL) {
3584 mem = kmalloc(sz, GFP_ATOMIC);
3588 ioc->ChainToChain = (int *) mem;
3589 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3590 ioc->name, mem, sz));
3592 mem = (u8 *) ioc->ChainToChain;
3594 memset(mem, 0xFF, sz);
3598 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3600 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3601 * @ioc: Pointer to MPT_ADAPTER structure
3603 * This routine allocates memory for the MPT reply and request frame
3604 * pools (if necessary), and primes the IOC reply FIFO with
3607 * Returns 0 for success, non-zero for failure.
3610 PrimeIocFifos(MPT_ADAPTER *ioc)
3613 unsigned long flags;
3614 dma_addr_t alloc_dma;
3616 int i, reply_sz, sz, total_size, num_chain;
3618 /* Prime reply FIFO... */
3620 if (ioc->reply_frames == NULL) {
3621 if ( (num_chain = initChainBuffers(ioc)) < 0)
3624 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3625 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3626 ioc->name, ioc->reply_sz, ioc->reply_depth));
3627 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3628 ioc->name, reply_sz, reply_sz));
3630 sz = (ioc->req_sz * ioc->req_depth);
3631 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3632 ioc->name, ioc->req_sz, ioc->req_depth));
3633 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3634 ioc->name, sz, sz));
3637 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3638 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3639 ioc->name, ioc->req_sz, num_chain));
3640 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3641 ioc->name, sz, sz, num_chain));
3644 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3646 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3651 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3652 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3654 memset(mem, 0, total_size);
3655 ioc->alloc_total += total_size;
3657 ioc->alloc_dma = alloc_dma;
3658 ioc->alloc_sz = total_size;
3659 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3660 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3662 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3663 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3665 alloc_dma += reply_sz;
3668 /* Request FIFO - WE manage this! */
3670 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3671 ioc->req_frames_dma = alloc_dma;
3673 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3674 ioc->name, mem, (void *)(ulong)alloc_dma));
3676 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3678 #if defined(CONFIG_MTRR) && 0
3680 * Enable Write Combining MTRR for IOC's memory region.
3681 * (at least as much as we can; "size and base must be
3682 * multiples of 4 kiB"
3684 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3686 MTRR_TYPE_WRCOMB, 1);
3687 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3688 ioc->name, ioc->req_frames_dma, sz));
3691 for (i = 0; i < ioc->req_depth; i++) {
3692 alloc_dma += ioc->req_sz;
3696 ioc->ChainBuffer = mem;
3697 ioc->ChainBufferDMA = alloc_dma;
3699 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3700 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3702 /* Initialize the free chain Q.
3705 INIT_LIST_HEAD(&ioc->FreeChainQ);
3707 /* Post the chain buffers to the FreeChainQ.
3709 mem = (u8 *)ioc->ChainBuffer;
3710 for (i=0; i < num_chain; i++) {
3711 mf = (MPT_FRAME_HDR *) mem;
3712 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3716 /* Initialize Request frames linked list
3718 alloc_dma = ioc->req_frames_dma;
3719 mem = (u8 *) ioc->req_frames;
3721 spin_lock_irqsave(&ioc->FreeQlock, flags);
3722 INIT_LIST_HEAD(&ioc->FreeQ);
3723 for (i = 0; i < ioc->req_depth; i++) {
3724 mf = (MPT_FRAME_HDR *) mem;
3726 /* Queue REQUESTs *internally*! */
3727 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3731 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3733 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3734 ioc->sense_buf_pool =
3735 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3736 if (ioc->sense_buf_pool == NULL) {
3737 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3742 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3743 ioc->alloc_total += sz;
3744 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3745 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3749 /* Post Reply frames to FIFO
3751 alloc_dma = ioc->alloc_dma;
3752 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3753 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3755 for (i = 0; i < ioc->reply_depth; i++) {
3756 /* Write each address to the IOC! */
3757 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3758 alloc_dma += ioc->reply_sz;
3764 if (ioc->alloc != NULL) {
3766 pci_free_consistent(ioc->pcidev,
3768 ioc->alloc, ioc->alloc_dma);
3769 ioc->reply_frames = NULL;
3770 ioc->req_frames = NULL;
3771 ioc->alloc_total -= sz;
3773 if (ioc->sense_buf_pool != NULL) {
3774 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3775 pci_free_consistent(ioc->pcidev,
3777 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3778 ioc->sense_buf_pool = NULL;
3783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3785 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3786 * from IOC via doorbell handshake method.
3787 * @ioc: Pointer to MPT_ADAPTER structure
3788 * @reqBytes: Size of the request in bytes
3789 * @req: Pointer to MPT request frame
3790 * @replyBytes: Expected size of the reply in bytes
3791 * @u16reply: Pointer to area where reply should be written
3792 * @maxwait: Max wait time for a reply (in seconds)
3793 * @sleepFlag: Specifies whether the process can sleep
3795 * NOTES: It is the callers responsibility to byte-swap fields in the
3796 * request which are greater than 1 byte in size. It is also the
3797 * callers responsibility to byte-swap response fields which are
3798 * greater than 1 byte in size.
3800 * Returns 0 for success, non-zero for failure.
3803 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3804 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3806 MPIDefaultReply_t *mptReply;
3811 * Get ready to cache a handshake reply
3813 ioc->hs_reply_idx = 0;
3814 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3815 mptReply->MsgLength = 0;
3818 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3819 * then tell IOC that we want to handshake a request of N words.
3820 * (WRITE u32val to Doorbell reg).
3822 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3823 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3824 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3825 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3828 * Wait for IOC's doorbell handshake int
3830 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3833 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3834 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3836 /* Read doorbell and check for active bit */
3837 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3841 * Clear doorbell int (WRITE 0 to IntStatus reg),
3842 * then wait for IOC to ACKnowledge that it's ready for
3843 * our handshake request.
3845 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3846 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3851 u8 *req_as_bytes = (u8 *) req;
3854 * Stuff request words via doorbell handshake,
3855 * with ACK from IOC for each.
3857 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3858 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3859 (req_as_bytes[(ii*4) + 1] << 8) |
3860 (req_as_bytes[(ii*4) + 2] << 16) |
3861 (req_as_bytes[(ii*4) + 3] << 24));
3863 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3864 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3868 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3869 DBG_DUMP_REQUEST_FRAME_HDR(req)
3871 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3872 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3875 * Wait for completion of doorbell handshake reply from the IOC
3877 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3880 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3881 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3884 * Copy out the cached reply...
3886 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3887 u16reply[ii] = ioc->hs_reply[ii];
3895 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3897 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3898 * in it's IntStatus register.
3899 * @ioc: Pointer to MPT_ADAPTER structure
3900 * @howlong: How long to wait (in seconds)
3901 * @sleepFlag: Specifies whether the process can sleep
3903 * This routine waits (up to ~2 seconds max) for IOC doorbell
3904 * handshake ACKnowledge.
3906 * Returns a negative value on failure, else wait loop count.
3909 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3915 cntdn = 1000 * howlong;
3917 if (sleepFlag == CAN_SLEEP) {
3920 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3921 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3928 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3929 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3936 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3941 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3942 ioc->name, count, intstat);
3946 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3948 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3949 * in it's IntStatus register.
3950 * @ioc: Pointer to MPT_ADAPTER structure
3951 * @howlong: How long to wait (in seconds)
3952 * @sleepFlag: Specifies whether the process can sleep
3954 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3956 * Returns a negative value on failure, else wait loop count.
3959 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3965 cntdn = 1000 * howlong;
3966 if (sleepFlag == CAN_SLEEP) {
3968 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3969 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3976 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3977 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3985 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3986 ioc->name, count, howlong));
3990 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3991 ioc->name, count, intstat);
3995 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3997 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3998 * @ioc: Pointer to MPT_ADAPTER structure
3999 * @howlong: How long to wait (in seconds)
4000 * @sleepFlag: Specifies whether the process can sleep
4002 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4003 * Reply is cached to IOC private area large enough to hold a maximum
4004 * of 128 bytes of reply data.
4006 * Returns a negative value on failure, else size of reply in WORDS.
4009 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4014 u16 *hs_reply = ioc->hs_reply;
4015 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4018 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4021 * Get first two u16's so we can look at IOC's intended reply MsgLength
4024 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4027 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4028 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4029 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4032 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4033 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4037 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4038 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4039 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4042 * If no error (and IOC said MsgLength is > 0), piece together
4043 * reply 16 bits at a time.
4045 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4046 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4048 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4049 /* don't overflow our IOC hs_reply[] buffer! */
4050 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4051 hs_reply[u16cnt] = hword;
4052 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4055 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4057 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4060 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4065 else if (u16cnt != (2 * mptReply->MsgLength)) {
4068 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4073 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4074 DBG_DUMP_REPLY_FRAME(mptReply)
4076 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4077 ioc->name, t, u16cnt/2));
4081 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4083 * GetLanConfigPages - Fetch LANConfig pages.
4084 * @ioc: Pointer to MPT_ADAPTER structure
4086 * Return: 0 for success
4087 * -ENOMEM if no memory available
4088 * -EPERM if not allowed due to ISR context
4089 * -EAGAIN if no msg frames currently available
4090 * -EFAULT for non-successful reply or no reply (timeout)
4093 GetLanConfigPages(MPT_ADAPTER *ioc)
4095 ConfigPageHeader_t hdr;
4097 LANPage0_t *ppage0_alloc;
4098 dma_addr_t page0_dma;
4099 LANPage1_t *ppage1_alloc;
4100 dma_addr_t page1_dma;
4105 /* Get LAN Page 0 header */
4106 hdr.PageVersion = 0;
4109 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4110 cfg.cfghdr.hdr = &hdr;
4112 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4117 if ((rc = mpt_config(ioc, &cfg)) != 0)
4120 if (hdr.PageLength > 0) {
4121 data_sz = hdr.PageLength * 4;
4122 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4125 memset((u8 *)ppage0_alloc, 0, data_sz);
4126 cfg.physAddr = page0_dma;
4127 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4129 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4131 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4132 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4136 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4139 * Normalize endianness of structure data,
4140 * by byte-swapping all > 1 byte fields!
4149 /* Get LAN Page 1 header */
4150 hdr.PageVersion = 0;
4153 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4154 cfg.cfghdr.hdr = &hdr;
4156 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4160 if ((rc = mpt_config(ioc, &cfg)) != 0)
4163 if (hdr.PageLength == 0)
4166 data_sz = hdr.PageLength * 4;
4168 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4170 memset((u8 *)ppage1_alloc, 0, data_sz);
4171 cfg.physAddr = page1_dma;
4172 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4174 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4176 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4177 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4180 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4183 * Normalize endianness of structure data,
4184 * by byte-swapping all > 1 byte fields!
4192 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4194 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4195 * @ioc: Pointer to MPT_ADAPTER structure
4196 * @sas_address: 64bit SAS Address for operation.
4197 * @target_id: specified target for operation
4198 * @bus: specified bus for operation
4199 * @persist_opcode: see below
4201 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4202 * devices not currently present.
4203 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4205 * NOTE: Don't use not this function during interrupt time.
4207 * Returns: 0 for success, non-zero error
4210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4212 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4214 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4215 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4216 MPT_FRAME_HDR *mf = NULL;
4217 MPIHeader_t *mpi_hdr;
4220 /* insure garbage is not sent to fw */
4221 switch(persist_opcode) {
4223 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4224 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4232 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4234 /* Get a MF for this command.
4236 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4237 printk("%s: no msg frames!\n",__FUNCTION__);
4241 mpi_hdr = (MPIHeader_t *) mf;
4242 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4243 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4244 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4245 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4246 sasIoUnitCntrReq->Operation = persist_opcode;
4248 init_timer(&ioc->persist_timer);
4249 ioc->persist_timer.data = (unsigned long) ioc;
4250 ioc->persist_timer.function = mpt_timer_expired;
4251 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4252 ioc->persist_wait_done=0;
4253 add_timer(&ioc->persist_timer);
4254 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4255 wait_event(mpt_waitq, ioc->persist_wait_done);
4257 sasIoUnitCntrReply =
4258 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4259 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4260 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4262 sasIoUnitCntrReply->IOCStatus,
4263 sasIoUnitCntrReply->IOCLogInfo);
4267 printk("%s: success\n",__FUNCTION__);
4271 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4274 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4275 MpiEventDataRaid_t * pRaidEventData)
4284 volume = pRaidEventData->VolumeID;
4285 reason = pRaidEventData->ReasonCode;
4286 disk = pRaidEventData->PhysDiskNum;
4287 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4288 flags = (status >> 0) & 0xff;
4289 state = (status >> 8) & 0xff;
4291 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4295 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4296 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4297 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4298 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4301 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4306 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4307 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4311 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4313 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4317 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4318 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4322 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4323 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4325 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4327 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4329 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4332 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4334 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4335 ? ", quiesced" : "",
4336 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4337 ? ", resync in progress" : "" );
4340 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4341 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4345 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4346 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4350 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4351 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4355 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4356 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4360 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4361 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4363 state == MPI_PHYSDISK0_STATUS_ONLINE
4365 : state == MPI_PHYSDISK0_STATUS_MISSING
4367 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4369 : state == MPI_PHYSDISK0_STATUS_FAILED
4371 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4373 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4374 ? "offline requested"
4375 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4376 ? "failed requested"
4377 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4380 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4381 ? ", out of sync" : "",
4382 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4383 ? ", quiesced" : "" );
4386 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4387 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4391 case MPI_EVENT_RAID_RC_SMART_DATA:
4392 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4393 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4396 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4397 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4403 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4405 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4406 * @ioc: Pointer to MPT_ADAPTER structure
4408 * Returns: 0 for success
4409 * -ENOMEM if no memory available
4410 * -EPERM if not allowed due to ISR context
4411 * -EAGAIN if no msg frames currently available
4412 * -EFAULT for non-successful reply or no reply (timeout)
4415 GetIoUnitPage2(MPT_ADAPTER *ioc)
4417 ConfigPageHeader_t hdr;
4419 IOUnitPage2_t *ppage_alloc;
4420 dma_addr_t page_dma;
4424 /* Get the page header */
4425 hdr.PageVersion = 0;
4428 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4429 cfg.cfghdr.hdr = &hdr;
4431 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4436 if ((rc = mpt_config(ioc, &cfg)) != 0)
4439 if (hdr.PageLength == 0)
4442 /* Read the config page */
4443 data_sz = hdr.PageLength * 4;
4445 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4447 memset((u8 *)ppage_alloc, 0, data_sz);
4448 cfg.physAddr = page_dma;
4449 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4451 /* If Good, save data */
4452 if ((rc = mpt_config(ioc, &cfg)) == 0)
4453 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4455 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4461 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4462 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4463 * @ioc: Pointer to a Adapter Strucutre
4464 * @portnum: IOC port number
4466 * Return: -EFAULT if read of config page header fails
4468 * If read of SCSI Port Page 0 fails,
4469 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4470 * Adapter settings: async, narrow
4472 * If read of SCSI Port Page 2 fails,
4473 * Adapter settings valid
4474 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4479 * CHECK - what type of locking mechanisms should be used????
4482 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4487 ConfigPageHeader_t header;
4493 if (!ioc->spi_data.nvram) {
4496 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4497 mem = kmalloc(sz, GFP_ATOMIC);
4501 ioc->spi_data.nvram = (int *) mem;
4503 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4504 ioc->name, ioc->spi_data.nvram, sz));
4507 /* Invalidate NVRAM information
4509 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4510 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4513 /* Read SPP0 header, allocate memory, then read page.
4515 header.PageVersion = 0;
4516 header.PageLength = 0;
4517 header.PageNumber = 0;
4518 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4519 cfg.cfghdr.hdr = &header;
4521 cfg.pageAddr = portnum;
4522 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4524 cfg.timeout = 0; /* use default */
4525 if (mpt_config(ioc, &cfg) != 0)
4528 if (header.PageLength > 0) {
4529 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4531 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4532 cfg.physAddr = buf_dma;
4533 if (mpt_config(ioc, &cfg) != 0) {
4534 ioc->spi_data.maxBusWidth = MPT_NARROW;
4535 ioc->spi_data.maxSyncOffset = 0;
4536 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4537 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4539 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4540 ioc->name, ioc->spi_data.minSyncFactor));
4542 /* Save the Port Page 0 data
4544 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4545 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4546 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4548 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4549 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4550 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4551 ioc->name, pPP0->Capabilities));
4553 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4554 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4556 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4557 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4558 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4559 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4560 ioc->name, ioc->spi_data.minSyncFactor));
4562 ioc->spi_data.maxSyncOffset = 0;
4563 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4566 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4568 /* Update the minSyncFactor based on bus type.
4570 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4571 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4573 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4574 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4575 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4576 ioc->name, ioc->spi_data.minSyncFactor));
4581 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4586 /* SCSI Port Page 2 - Read the header then the page.
4588 header.PageVersion = 0;
4589 header.PageLength = 0;
4590 header.PageNumber = 2;
4591 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4592 cfg.cfghdr.hdr = &header;
4594 cfg.pageAddr = portnum;
4595 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4597 if (mpt_config(ioc, &cfg) != 0)
4600 if (header.PageLength > 0) {
4601 /* Allocate memory and read SCSI Port Page 2
4603 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4605 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4606 cfg.physAddr = buf_dma;
4607 if (mpt_config(ioc, &cfg) != 0) {
4608 /* Nvram data is left with INVALID mark
4612 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4613 MpiDeviceInfo_t *pdevice = NULL;
4616 * Save "Set to Avoid SCSI Bus Resets" flag
4618 ioc->spi_data.bus_reset =
4619 (le32_to_cpu(pPP2->PortFlags) &
4620 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4623 /* Save the Port Page 2 data
4624 * (reformat into a 32bit quantity)
4626 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4627 ioc->spi_data.PortFlags = data;
4628 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4629 pdevice = &pPP2->DeviceSettings[ii];
4630 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4631 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4632 ioc->spi_data.nvram[ii] = data;
4636 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4640 /* Update Adapter limits with those from NVRAM
4641 * Comment: Don't need to do this. Target performance
4642 * parameters will never exceed the adapters limits.
4648 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4649 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4650 * @ioc: Pointer to a Adapter Strucutre
4651 * @portnum: IOC port number
4653 * Return: -EFAULT if read of config page header fails
4657 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4660 ConfigPageHeader_t header;
4662 /* Read the SCSI Device Page 1 header
4664 header.PageVersion = 0;
4665 header.PageLength = 0;
4666 header.PageNumber = 1;
4667 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4668 cfg.cfghdr.hdr = &header;
4670 cfg.pageAddr = portnum;
4671 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4674 if (mpt_config(ioc, &cfg) != 0)
4677 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4678 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4680 header.PageVersion = 0;
4681 header.PageLength = 0;
4682 header.PageNumber = 0;
4683 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4684 if (mpt_config(ioc, &cfg) != 0)
4687 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4688 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4690 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4691 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4693 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4694 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4700 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4701 * @ioc: Pointer to a Adapter Strucutre
4702 * @portnum: IOC port number
4706 * -EFAULT if read of config page header fails or data pointer not NULL
4707 * -ENOMEM if pci_alloc failed
4710 mpt_findImVolumes(MPT_ADAPTER *ioc)
4714 ConfigPageIoc2RaidVol_t *pIocRv;
4715 dma_addr_t ioc2_dma;
4717 ConfigPageHeader_t header;
4724 /* Read IOCP2 header then the page.
4726 header.PageVersion = 0;
4727 header.PageLength = 0;
4728 header.PageNumber = 2;
4729 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4730 cfg.cfghdr.hdr = &header;
4733 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4736 if (mpt_config(ioc, &cfg) != 0)
4739 if (header.PageLength == 0)
4742 iocpage2sz = header.PageLength * 4;
4743 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4747 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4748 cfg.physAddr = ioc2_dma;
4749 if (mpt_config(ioc, &cfg) != 0)
4752 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4753 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4755 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4760 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4762 /* Identify RAID Volume Id's */
4763 nVols = pIoc2->NumActiveVolumes;
4769 /* At least 1 RAID Volume
4771 pIocRv = pIoc2->RaidVolume;
4772 ioc->raid_data.isRaid = 0;
4773 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4774 vid = pIocRv->VolumeID;
4775 vbus = pIocRv->VolumeBus;
4776 vioc = pIocRv->VolumeIOC;
4781 ioc->raid_data.isRaid |= (1 << vid);
4783 /* Error! Always bus 0
4789 /* Identify Hidden Physical Disk Id's */
4790 nPhys = pIoc2->NumActivePhysDisks;
4792 /* No physical disks.
4795 mpt_read_ioc_pg_3(ioc);
4799 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4805 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4810 ConfigPageHeader_t header;
4811 dma_addr_t ioc3_dma;
4814 /* Free the old page
4816 kfree(ioc->raid_data.pIocPg3);
4817 ioc->raid_data.pIocPg3 = NULL;
4819 /* There is at least one physical disk.
4820 * Read and save IOC Page 3
4822 header.PageVersion = 0;
4823 header.PageLength = 0;
4824 header.PageNumber = 3;
4825 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4826 cfg.cfghdr.hdr = &header;
4829 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4832 if (mpt_config(ioc, &cfg) != 0)
4835 if (header.PageLength == 0)
4838 /* Read Header good, alloc memory
4840 iocpage3sz = header.PageLength * 4;
4841 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4845 /* Read the Page and save the data
4846 * into malloc'd memory.
4848 cfg.physAddr = ioc3_dma;
4849 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4850 if (mpt_config(ioc, &cfg) == 0) {
4851 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4853 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4854 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4858 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4864 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4868 ConfigPageHeader_t header;
4869 dma_addr_t ioc4_dma;
4872 /* Read and save IOC Page 4
4874 header.PageVersion = 0;
4875 header.PageLength = 0;
4876 header.PageNumber = 4;
4877 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4878 cfg.cfghdr.hdr = &header;
4881 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4884 if (mpt_config(ioc, &cfg) != 0)
4887 if (header.PageLength == 0)
4890 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4891 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4892 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4895 ioc->alloc_total += iocpage4sz;
4897 ioc4_dma = ioc->spi_data.IocPg4_dma;
4898 iocpage4sz = ioc->spi_data.IocPg4Sz;
4901 /* Read the Page into dma memory.
4903 cfg.physAddr = ioc4_dma;
4904 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4905 if (mpt_config(ioc, &cfg) == 0) {
4906 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4907 ioc->spi_data.IocPg4_dma = ioc4_dma;
4908 ioc->spi_data.IocPg4Sz = iocpage4sz;
4910 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4911 ioc->spi_data.pIocPg4 = NULL;
4912 ioc->alloc_total -= iocpage4sz;
4917 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4921 ConfigPageHeader_t header;
4922 dma_addr_t ioc1_dma;
4926 /* Check the Coalescing Timeout in IOC Page 1
4928 header.PageVersion = 0;
4929 header.PageLength = 0;
4930 header.PageNumber = 1;
4931 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4932 cfg.cfghdr.hdr = &header;
4935 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4938 if (mpt_config(ioc, &cfg) != 0)
4941 if (header.PageLength == 0)
4944 /* Read Header good, alloc memory
4946 iocpage1sz = header.PageLength * 4;
4947 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4951 /* Read the Page and check coalescing timeout
4953 cfg.physAddr = ioc1_dma;
4954 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4955 if (mpt_config(ioc, &cfg) == 0) {
4957 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4958 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4959 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4961 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4964 if (tmp > MPT_COALESCING_TIMEOUT) {
4965 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4967 /* Write NVRAM and current
4970 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4971 if (mpt_config(ioc, &cfg) == 0) {
4972 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4973 ioc->name, MPT_COALESCING_TIMEOUT));
4975 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4976 if (mpt_config(ioc, &cfg) == 0) {
4977 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4978 ioc->name, MPT_COALESCING_TIMEOUT));
4980 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4985 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4991 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4995 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5000 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5002 * SendEventNotification - Send EventNotification (on or off) request
5004 * @ioc: Pointer to MPT_ADAPTER structure
5005 * @EvSwitch: Event switch flags
5008 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5010 EventNotification_t *evnp;
5012 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5014 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5018 memset(evnp, 0, sizeof(*evnp));
5020 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5022 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5023 evnp->ChainOffset = 0;
5025 evnp->Switch = EvSwitch;
5027 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5032 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5034 * SendEventAck - Send EventAck request to MPT adapter.
5035 * @ioc: Pointer to MPT_ADAPTER structure
5036 * @evnp: Pointer to original EventNotification request
5039 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5043 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5044 dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5045 ioc->name,__FUNCTION__));
5049 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5051 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5052 pAck->ChainOffset = 0;
5053 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5055 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5056 pAck->Event = evnp->Event;
5057 pAck->EventContext = evnp->EventContext;
5059 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5066 * mpt_config - Generic function to issue config message
5067 * @ioc - Pointer to an adapter structure
5068 * @cfg - Pointer to a configuration structure. Struct contains
5069 * action, page address, direction, physical address
5070 * and pointer to a configuration page header
5071 * Page header is updated.
5073 * Returns 0 for success
5074 * -EPERM if not allowed due to ISR context
5075 * -EAGAIN if no msg frames currently available
5076 * -EFAULT for non-successful reply or no reply (timeout)
5079 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5082 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5084 unsigned long flags;
5089 /* Prevent calling wait_event() (below), if caller happens
5090 * to be in ISR context, because that is fatal!
5092 in_isr = in_interrupt();
5094 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5099 /* Get and Populate a free Frame
5101 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5102 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5106 pReq = (Config_t *)mf;
5107 pReq->Action = pCfg->action;
5109 pReq->ChainOffset = 0;
5110 pReq->Function = MPI_FUNCTION_CONFIG;
5112 /* Assume page type is not extended and clear "reserved" fields. */
5113 pReq->ExtPageLength = 0;
5114 pReq->ExtPageType = 0;
5117 for (ii=0; ii < 8; ii++)
5118 pReq->Reserved2[ii] = 0;
5120 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5121 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5122 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5123 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5125 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5126 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5127 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5128 pReq->ExtPageType = pExtHdr->ExtPageType;
5129 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5131 /* Page Length must be treated as a reserved field for the extended header. */
5132 pReq->Header.PageLength = 0;
5135 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5137 /* Add a SGE to the config request.
5140 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5142 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5144 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5145 flagsLength |= pExtHdr->ExtPageLength * 4;
5147 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5148 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5151 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5153 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5154 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5157 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5159 /* Append pCfg pointer to end of mf
5161 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5163 /* Initalize the timer
5165 init_timer(&pCfg->timer);
5166 pCfg->timer.data = (unsigned long) ioc;
5167 pCfg->timer.function = mpt_timer_expired;
5168 pCfg->wait_done = 0;
5170 /* Set the timer; ensure 10 second minimum */
5171 if (pCfg->timeout < 10)
5172 pCfg->timer.expires = jiffies + HZ*10;
5174 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5176 /* Add to end of Q, set timer and then issue this command */
5177 spin_lock_irqsave(&ioc->FreeQlock, flags);
5178 list_add_tail(&pCfg->linkage, &ioc->configQ);
5179 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5181 add_timer(&pCfg->timer);
5182 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5183 wait_event(mpt_waitq, pCfg->wait_done);
5185 /* mf has been freed - do not access */
5192 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5194 * mpt_timer_expired - Call back for timer process.
5195 * Used only internal config functionality.
5196 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5199 mpt_timer_expired(unsigned long data)
5201 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5203 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5205 /* Perform a FW reload */
5206 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5207 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5209 /* No more processing.
5210 * Hard reset clean-up will wake up
5211 * process and free all resources.
5213 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5218 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5220 * mpt_ioc_reset - Base cleanup for hard reset
5221 * @ioc: Pointer to the adapter structure
5222 * @reset_phase: Indicates pre- or post-reset functionality
5224 * Remark: Free's resources with internally generated commands.
5227 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5230 unsigned long flags;
5232 dprintk((KERN_WARNING MYNAM
5233 ": IOC %s_reset routed to MPT base driver!\n",
5234 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5235 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5237 if (reset_phase == MPT_IOC_SETUP_RESET) {
5239 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5240 /* If the internal config Q is not empty -
5241 * delete timer. MF resources will be freed when
5242 * the FIFO's are primed.
5244 spin_lock_irqsave(&ioc->FreeQlock, flags);
5245 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5246 del_timer(&pCfg->timer);
5247 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5252 /* Search the configQ for internal commands.
5253 * Flush the Q, and wake up all suspended threads.
5255 spin_lock_irqsave(&ioc->FreeQlock, flags);
5256 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5257 list_del(&pCfg->linkage);
5259 pCfg->status = MPT_CONFIG_ERROR;
5260 pCfg->wait_done = 1;
5261 wake_up(&mpt_waitq);
5263 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5266 return 1; /* currently means nothing really */
5270 #ifdef CONFIG_PROC_FS /* { */
5271 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5273 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5275 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5277 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5279 * Returns 0 for success, non-zero for failure.
5282 procmpt_create(void)
5284 struct proc_dir_entry *ent;
5286 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5287 if (mpt_proc_root_dir == NULL)
5290 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5292 ent->read_proc = procmpt_summary_read;
5294 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5296 ent->read_proc = procmpt_version_read;
5301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5303 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5305 * Returns 0 for success, non-zero for failure.
5308 procmpt_destroy(void)
5310 remove_proc_entry("version", mpt_proc_root_dir);
5311 remove_proc_entry("summary", mpt_proc_root_dir);
5312 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5315 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5317 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5318 * or from /proc/mpt/iocN/summary.
5319 * @buf: Pointer to area to write information
5320 * @start: Pointer to start pointer
5321 * @offset: Offset to start writing
5323 * @eof: Pointer to EOF integer
5326 * Returns number of characters written to process performing the read.
5329 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5339 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5343 list_for_each_entry(ioc, &ioc_list, list) {
5346 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5349 if ((out-buf) >= request)
5356 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5361 * procmpt_version_read - Handle read request from /proc/mpt/version.
5362 * @buf: Pointer to area to write information
5363 * @start: Pointer to start pointer
5364 * @offset: Offset to start writing
5366 * @eof: Pointer to EOF integer
5369 * Returns number of characters written to process performing the read.
5372 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5375 int scsi, fc, sas, lan, ctl, targ, dmp;
5379 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5380 len += sprintf(buf+len, " Fusion MPT base driver\n");
5382 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5383 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5385 if (MptCallbacks[ii]) {
5386 switch (MptDriverClass[ii]) {
5388 if (!scsi++) drvname = "SPI host";
5391 if (!fc++) drvname = "FC host";
5394 if (!sas++) drvname = "SAS host";
5397 if (!lan++) drvname = "LAN";
5400 if (!targ++) drvname = "SCSI target";
5403 if (!ctl++) drvname = "ioctl";
5408 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5412 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5415 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5417 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5418 * @buf: Pointer to area to write information
5419 * @start: Pointer to start pointer
5420 * @offset: Offset to start writing
5422 * @eof: Pointer to EOF integer
5425 * Returns number of characters written to process performing the read.
5428 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5430 MPT_ADAPTER *ioc = data;
5436 mpt_get_fw_exp_ver(expVer, ioc);
5438 len = sprintf(buf, "%s:", ioc->name);
5439 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5440 len += sprintf(buf+len, " (f/w download boot flag set)");
5441 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5442 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5444 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5445 ioc->facts.ProductID,
5447 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5448 if (ioc->facts.FWImageSize)
5449 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5450 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5451 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5452 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5454 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5455 ioc->facts.CurrentHostMfaHighAddr);
5456 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5457 ioc->facts.CurrentSenseBufferHighAddr);
5459 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5460 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5462 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5463 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5465 * Rounding UP to nearest 4-kB boundary here...
5467 sz = (ioc->req_sz * ioc->req_depth) + 128;
5468 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5469 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5470 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5471 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5472 4*ioc->facts.RequestFrameSize,
5473 ioc->facts.GlobalCredits);
5475 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5476 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5477 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5478 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5479 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5480 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5481 ioc->facts.CurReplyFrameSize,
5482 ioc->facts.ReplyQueueDepth);
5484 len += sprintf(buf+len, " MaxDevices = %d\n",
5485 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5486 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5489 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5490 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5492 ioc->facts.NumberOfPorts);
5493 if (ioc->bus_type == FC) {
5494 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5495 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5496 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5497 a[5], a[4], a[3], a[2], a[1], a[0]);
5499 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5500 ioc->fc_port_page0[p].WWNN.High,
5501 ioc->fc_port_page0[p].WWNN.Low,
5502 ioc->fc_port_page0[p].WWPN.High,
5503 ioc->fc_port_page0[p].WWPN.Low);
5507 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5510 #endif /* CONFIG_PROC_FS } */
5512 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5514 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5517 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5518 sprintf(buf, " (Exp %02d%02d)",
5519 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5520 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5523 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5524 strcat(buf, " [MDBG]");
5528 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5530 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5531 * @ioc: Pointer to MPT_ADAPTER structure
5532 * @buffer: Pointer to buffer where IOC summary info should be written
5533 * @size: Pointer to number of bytes we wrote (set by this routine)
5534 * @len: Offset at which to start writing in buffer
5535 * @showlan: Display LAN stuff?
5537 * This routine writes (english readable) ASCII text, which represents
5538 * a summary of IOC information, to a buffer.
5541 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5546 mpt_get_fw_exp_ver(expVer, ioc);
5549 * Shorter summary of attached ioc's...
5551 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5554 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5555 ioc->facts.FWVersion.Word,
5557 ioc->facts.NumberOfPorts,
5560 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5561 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5562 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5563 a[5], a[4], a[3], a[2], a[1], a[0]);
5566 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5569 y += sprintf(buffer+len+y, " (disabled)");
5571 y += sprintf(buffer+len+y, "\n");
5576 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5580 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5582 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5583 * Management call based on input arg values. If TaskMgmt fails,
5584 * return associated SCSI request.
5585 * @ioc: Pointer to MPT_ADAPTER structure
5586 * @sleepFlag: Indicates if sleep or schedule must be called.
5588 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5589 * or a non-interrupt thread. In the former, must not call schedule().
5591 * Remark: A return of -1 is a FATAL error case, as it means a
5592 * FW reload/initialization failed.
5594 * Returns 0 for SUCCESS or -1 if FAILED.
5597 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5600 unsigned long flags;
5602 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5604 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5605 printk("MF count 0x%x !\n", ioc->mfcnt);
5608 /* Reset the adapter. Prevent more than 1 call to
5609 * mpt_do_ioc_recovery at any instant in time.
5611 spin_lock_irqsave(&ioc->diagLock, flags);
5612 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5613 spin_unlock_irqrestore(&ioc->diagLock, flags);
5616 ioc->diagPending = 1;
5618 spin_unlock_irqrestore(&ioc->diagLock, flags);
5620 /* FIXME: If do_ioc_recovery fails, repeat....
5623 /* The SCSI driver needs to adjust timeouts on all current
5624 * commands prior to the diagnostic reset being issued.
5625 * Prevents timeouts occurring during a diagnostic reset...very bad.
5626 * For all other protocol drivers, this is a no-op.
5632 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5633 if (MptResetHandlers[ii]) {
5634 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5636 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5638 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5639 ioc->name, ioc->alt_ioc->name, ii));
5640 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5646 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5647 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5652 ioc->alt_ioc->reload_fw = 0;
5654 spin_lock_irqsave(&ioc->diagLock, flags);
5655 ioc->diagPending = 0;
5657 ioc->alt_ioc->diagPending = 0;
5658 spin_unlock_irqrestore(&ioc->diagLock, flags);
5660 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5665 # define EVENT_DESCR_STR_SZ 100
5667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5669 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5674 case MPI_EVENT_NONE:
5677 case MPI_EVENT_LOG_DATA:
5680 case MPI_EVENT_STATE_CHANGE:
5681 ds = "State Change";
5683 case MPI_EVENT_UNIT_ATTENTION:
5684 ds = "Unit Attention";
5686 case MPI_EVENT_IOC_BUS_RESET:
5687 ds = "IOC Bus Reset";
5689 case MPI_EVENT_EXT_BUS_RESET:
5690 ds = "External Bus Reset";
5692 case MPI_EVENT_RESCAN:
5693 ds = "Bus Rescan Event";
5694 /* Ok, do we need to do anything here? As far as
5695 I can tell, this is when a new device gets added
5698 case MPI_EVENT_LINK_STATUS_CHANGE:
5699 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5700 ds = "Link Status(FAILURE) Change";
5702 ds = "Link Status(ACTIVE) Change";
5704 case MPI_EVENT_LOOP_STATE_CHANGE:
5705 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5706 ds = "Loop State(LIP) Change";
5707 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5708 ds = "Loop State(LPE) Change"; /* ??? */
5710 ds = "Loop State(LPB) Change"; /* ??? */
5712 case MPI_EVENT_LOGOUT:
5715 case MPI_EVENT_EVENT_CHANGE:
5721 case MPI_EVENT_INTEGRATED_RAID:
5723 u8 ReasonCode = (u8)(evData0 >> 16);
5724 switch (ReasonCode) {
5725 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5726 ds = "Integrated Raid: Volume Created";
5728 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5729 ds = "Integrated Raid: Volume Deleted";
5731 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5732 ds = "Integrated Raid: Volume Settings Changed";
5734 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5735 ds = "Integrated Raid: Volume Status Changed";
5737 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5738 ds = "Integrated Raid: Volume Physdisk Changed";
5740 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5741 ds = "Integrated Raid: Physdisk Created";
5743 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5744 ds = "Integrated Raid: Physdisk Deleted";
5746 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5747 ds = "Integrated Raid: Physdisk Settings Changed";
5749 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5750 ds = "Integrated Raid: Physdisk Status Changed";
5752 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5753 ds = "Integrated Raid: Domain Validation Needed";
5755 case MPI_EVENT_RAID_RC_SMART_DATA :
5756 ds = "Integrated Raid; Smart Data";
5758 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5759 ds = "Integrated Raid: Replace Action Started";
5762 ds = "Integrated Raid";
5767 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5768 ds = "SCSI Device Status Change";
5770 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5772 u8 id = (u8)(evData0);
5773 u8 ReasonCode = (u8)(evData0 >> 16);
5774 switch (ReasonCode) {
5775 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5776 snprintf(evStr, EVENT_DESCR_STR_SZ,
5777 "SAS Device Status Change: Added: id=%d", id);
5779 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5780 snprintf(evStr, EVENT_DESCR_STR_SZ,
5781 "SAS Device Status Change: Deleted: id=%d", id);
5783 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5784 snprintf(evStr, EVENT_DESCR_STR_SZ,
5785 "SAS Device Status Change: SMART Data: id=%d",
5788 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5789 snprintf(evStr, EVENT_DESCR_STR_SZ,
5790 "SAS Device Status Change: No Persistancy: id=%d", id);
5792 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5793 snprintf(evStr, EVENT_DESCR_STR_SZ,
5794 "SAS Device Status Change: Internal Device Reset : id=%d", id);
5796 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5797 snprintf(evStr, EVENT_DESCR_STR_SZ,
5798 "SAS Device Status Change: Internal Task Abort : id=%d", id);
5800 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5801 snprintf(evStr, EVENT_DESCR_STR_SZ,
5802 "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
5804 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5805 snprintf(evStr, EVENT_DESCR_STR_SZ,
5806 "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
5808 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5809 snprintf(evStr, EVENT_DESCR_STR_SZ,
5810 "SAS Device Status Change: Internal Query Task : id=%d", id);
5813 snprintf(evStr, EVENT_DESCR_STR_SZ,
5814 "SAS Device Status Change: Unknown: id=%d", id);
5819 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5820 ds = "Bus Timer Expired";
5822 case MPI_EVENT_QUEUE_FULL:
5825 case MPI_EVENT_SAS_SES:
5826 ds = "SAS SES Event";
5828 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5829 ds = "Persistent Table Full";
5831 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5833 u8 LinkRates = (u8)(evData0 >> 8);
5834 u8 PhyNumber = (u8)(evData0);
5835 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5836 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5837 switch (LinkRates) {
5838 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5839 snprintf(evStr, EVENT_DESCR_STR_SZ,
5840 "SAS PHY Link Status: Phy=%d:"
5841 " Rate Unknown",PhyNumber);
5843 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5844 snprintf(evStr, EVENT_DESCR_STR_SZ,
5845 "SAS PHY Link Status: Phy=%d:"
5846 " Phy Disabled",PhyNumber);
5848 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5849 snprintf(evStr, EVENT_DESCR_STR_SZ,
5850 "SAS PHY Link Status: Phy=%d:"
5851 " Failed Speed Nego",PhyNumber);
5853 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5854 snprintf(evStr, EVENT_DESCR_STR_SZ,
5855 "SAS PHY Link Status: Phy=%d:"
5856 " Sata OOB Completed",PhyNumber);
5858 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5859 snprintf(evStr, EVENT_DESCR_STR_SZ,
5860 "SAS PHY Link Status: Phy=%d:"
5861 " Rate 1.5 Gbps",PhyNumber);
5863 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5864 snprintf(evStr, EVENT_DESCR_STR_SZ,
5865 "SAS PHY Link Status: Phy=%d:"
5866 " Rate 3.0 Gpbs",PhyNumber);
5869 snprintf(evStr, EVENT_DESCR_STR_SZ,
5870 "SAS PHY Link Status: Phy=%d", PhyNumber);
5875 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5876 ds = "SAS Discovery Error";
5878 case MPI_EVENT_IR_RESYNC_UPDATE:
5880 u8 resync_complete = (u8)(evData0 >> 16);
5881 snprintf(evStr, EVENT_DESCR_STR_SZ,
5882 "IR Resync Update: Complete = %d:",resync_complete);
5887 u8 ReasonCode = (u8)(evData0 >> 16);
5888 switch (ReasonCode) {
5889 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5890 ds = "IR2: LD State Changed";
5892 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5893 ds = "IR2: PD State Changed";
5895 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5896 ds = "IR2: Bad Block Table Full";
5898 case MPI_EVENT_IR2_RC_PD_INSERTED:
5899 ds = "IR2: PD Inserted";
5901 case MPI_EVENT_IR2_RC_PD_REMOVED:
5902 ds = "IR2: PD Removed";
5904 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5905 ds = "IR2: Foreign CFG Detected";
5907 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5908 ds = "IR2: Rebuild Medium Error";
5916 case MPI_EVENT_SAS_DISCOVERY:
5919 ds = "SAS Discovery: Start";
5921 ds = "SAS Discovery: Stop";
5924 case MPI_EVENT_LOG_ENTRY_ADDED:
5925 ds = "SAS Log Entry Added";
5929 * MPT base "custom" events may be added here...
5936 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
5939 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5941 * ProcessEventNotification - Route a received EventNotificationReply to
5942 * all currently regeistered event handlers.
5943 * @ioc: Pointer to MPT_ADAPTER structure
5944 * @pEventReply: Pointer to EventNotification reply frame
5945 * @evHandlers: Pointer to integer, number of event handlers
5947 * Returns sum of event handlers return values.
5950 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5958 char evStr[EVENT_DESCR_STR_SZ];
5962 * Do platform normalization of values
5964 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5965 // evCtx = le32_to_cpu(pEventReply->EventContext);
5966 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5968 evData0 = le32_to_cpu(pEventReply->Data[0]);
5971 EventDescriptionStr(event, evData0, evStr);
5972 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
5977 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
5978 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5979 for (ii = 0; ii < evDataLen; ii++)
5980 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5985 * Do general / base driver event processing
5988 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5990 u8 evState = evData0 & 0xFF;
5992 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5994 /* Update EventState field in cached IocFacts */
5995 if (ioc->facts.Function) {
5996 ioc->facts.EventState = evState;
6000 case MPI_EVENT_INTEGRATED_RAID:
6001 mptbase_raid_process_event_data(ioc,
6002 (MpiEventDataRaid_t *)pEventReply->Data);
6009 * Should this event be logged? Events are written sequentially.
6010 * When buffer is full, start again at the top.
6012 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6015 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6017 ioc->events[idx].event = event;
6018 ioc->events[idx].eventContext = ioc->eventContext;
6020 for (ii = 0; ii < 2; ii++) {
6022 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6024 ioc->events[idx].data[ii] = 0;
6027 ioc->eventContext++;
6032 * Call each currently registered protocol event handler.
6034 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6035 if (MptEvHandlers[ii]) {
6036 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6038 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6042 /* FIXME? Examine results here? */
6045 * If needed, send (a single) EventAck.
6047 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6048 devtverboseprintk((MYIOC_s_WARN_FMT
6049 "EventAck required\n",ioc->name));
6050 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6051 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6056 *evHandlers = handlers;
6060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6062 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6063 * @ioc: Pointer to MPT_ADAPTER structure
6064 * @log_info: U32 LogInfo reply word from the IOC
6066 * Refer to lsi/mpi_log_fc.h.
6069 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6071 static char *subcl_str[8] = {
6072 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6073 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6075 u8 subcl = (log_info >> 24) & 0x7;
6077 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6078 ioc->name, log_info, subcl_str[subcl]);
6081 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6083 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6084 * @ioc: Pointer to MPT_ADAPTER structure
6085 * @mr: Pointer to MPT reply frame
6086 * @log_info: U32 LogInfo word from the IOC
6088 * Refer to lsi/sp_log.h.
6091 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6093 u32 info = log_info & 0x00FF0000;
6094 char *desc = "unknown";
6098 desc = "bug! MID not found";
6099 if (ioc->reload_fw == 0)
6104 desc = "Parity Error";
6108 desc = "ASYNC Outbound Overrun";
6112 desc = "SYNC Offset Error";
6120 desc = "Msg In Overflow";
6128 desc = "Outbound DMA Overrun";
6132 desc = "Task Management";
6136 desc = "Device Problem";
6140 desc = "Invalid Phase Change";
6144 desc = "Untagged Table Size";
6149 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6152 /* strings for sas loginfo */
6153 static char *originator_str[] = {
6158 static char *iop_code_str[] = {
6160 "Invalid SAS Address", /* 01h */
6162 "Invalid Page", /* 03h */
6163 "Diag Message Error", /* 04h */
6164 "Task Terminated", /* 05h */
6165 "Enclosure Management", /* 06h */
6166 "Target Mode" /* 07h */
6168 static char *pl_code_str[] = {
6170 "Open Failure", /* 01h */
6171 "Invalid Scatter Gather List", /* 02h */
6172 "Wrong Relative Offset or Frame Length", /* 03h */
6173 "Frame Transfer Error", /* 04h */
6174 "Transmit Frame Connected Low", /* 05h */
6175 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6176 "SATA Read Log Receive Data Error", /* 07h */
6177 "SATA NCQ Fail All Commands After Error", /* 08h */
6178 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6179 "Receive Frame Invalid Message", /* 0Ah */
6180 "Receive Context Message Valid Error", /* 0Bh */
6181 "Receive Frame Current Frame Error", /* 0Ch */
6182 "SATA Link Down", /* 0Dh */
6183 "Discovery SATA Init W IOS", /* 0Eh */
6184 "Config Invalid Page", /* 0Fh */
6185 "Discovery SATA Init Timeout", /* 10h */
6188 "IO Not Yet Executed", /* 13h */
6189 "IO Executed", /* 14h */
6190 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6191 "Open Transmit DMA Abort", /* 16h */
6192 "IO Device Missing Delay Retry", /* 17h */
6201 "Enclosure Management" /* 20h */
6204 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6206 * mpt_sas_log_info - Log information returned from SAS IOC.
6207 * @ioc: Pointer to MPT_ADAPTER structure
6208 * @log_info: U32 LogInfo reply word from the IOC
6210 * Refer to lsi/mpi_log_sas.h.
6213 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6215 union loginfo_type {
6224 union loginfo_type sas_loginfo;
6225 char *code_desc = NULL;
6227 sas_loginfo.loginfo = log_info;
6228 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6229 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6231 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6232 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6233 code_desc = iop_code_str[sas_loginfo.dw.code];
6234 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6235 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6236 code_desc = pl_code_str[sas_loginfo.dw.code];
6239 if (code_desc != NULL)
6240 printk(MYIOC_s_INFO_FMT
6241 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6242 " SubCode(0x%04x)\n",
6245 originator_str[sas_loginfo.dw.originator],
6247 sas_loginfo.dw.subcode);
6249 printk(MYIOC_s_INFO_FMT
6250 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6251 " SubCode(0x%04x)\n",
6254 originator_str[sas_loginfo.dw.originator],
6255 sas_loginfo.dw.code,
6256 sas_loginfo.dw.subcode);
6259 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6261 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6262 * @ioc: Pointer to MPT_ADAPTER structure
6263 * @ioc_status: U32 IOCStatus word from IOC
6264 * @mf: Pointer to MPT request frame
6266 * Refer to lsi/mpi.h.
6269 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6271 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6275 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6276 desc = "Invalid Function";
6279 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6283 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6284 desc = "Invalid SGL";
6287 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6288 desc = "Internal Error";
6291 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6295 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6296 desc = "Insufficient Resources";
6299 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6300 desc = "Invalid Field";
6303 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6304 desc = "Invalid State";
6307 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6308 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6309 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6310 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6311 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6312 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6313 /* No message for Config IOCStatus values */
6316 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6317 /* No message for recovered error
6318 desc = "SCSI Recovered Error";
6322 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6323 desc = "SCSI Invalid Bus";
6326 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6327 desc = "SCSI Invalid TargetID";
6330 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6332 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6333 U8 cdb = pScsiReq->CDB[0];
6334 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6335 desc = "SCSI Device Not There";
6340 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6341 desc = "SCSI Data Overrun";
6344 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6345 /* This error is checked in scsi_io_done(). Skip.
6346 desc = "SCSI Data Underrun";
6350 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6351 desc = "SCSI I/O Data Error";
6354 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6355 desc = "SCSI Protocol Error";
6358 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6359 desc = "SCSI Task Terminated";
6362 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6363 desc = "SCSI Residual Mismatch";
6366 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6367 desc = "SCSI Task Management Failed";
6370 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6371 desc = "SCSI IOC Terminated";
6374 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6375 desc = "SCSI Ext Terminated";
6383 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6386 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6387 EXPORT_SYMBOL(mpt_attach);
6388 EXPORT_SYMBOL(mpt_detach);
6390 EXPORT_SYMBOL(mpt_resume);
6391 EXPORT_SYMBOL(mpt_suspend);
6393 EXPORT_SYMBOL(ioc_list);
6394 EXPORT_SYMBOL(mpt_proc_root_dir);
6395 EXPORT_SYMBOL(mpt_register);
6396 EXPORT_SYMBOL(mpt_deregister);
6397 EXPORT_SYMBOL(mpt_event_register);
6398 EXPORT_SYMBOL(mpt_event_deregister);
6399 EXPORT_SYMBOL(mpt_reset_register);
6400 EXPORT_SYMBOL(mpt_reset_deregister);
6401 EXPORT_SYMBOL(mpt_device_driver_register);
6402 EXPORT_SYMBOL(mpt_device_driver_deregister);
6403 EXPORT_SYMBOL(mpt_get_msg_frame);
6404 EXPORT_SYMBOL(mpt_put_msg_frame);
6405 EXPORT_SYMBOL(mpt_free_msg_frame);
6406 EXPORT_SYMBOL(mpt_add_sge);
6407 EXPORT_SYMBOL(mpt_send_handshake_request);
6408 EXPORT_SYMBOL(mpt_verify_adapter);
6409 EXPORT_SYMBOL(mpt_GetIocState);
6410 EXPORT_SYMBOL(mpt_print_ioc_summary);
6411 EXPORT_SYMBOL(mpt_lan_index);
6412 EXPORT_SYMBOL(mpt_stm_index);
6413 EXPORT_SYMBOL(mpt_HardResetHandler);
6414 EXPORT_SYMBOL(mpt_config);
6415 EXPORT_SYMBOL(mpt_findImVolumes);
6416 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6417 EXPORT_SYMBOL(mpt_free_fw_memory);
6418 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6420 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6422 * fusion_init - Fusion MPT base driver initialization routine.
6424 * Returns 0 for success, non-zero for failure.
6431 show_mptmod_ver(my_NAME, my_VERSION);
6432 printk(KERN_INFO COPYRIGHT "\n");
6434 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6435 MptCallbacks[i] = NULL;
6436 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6437 MptEvHandlers[i] = NULL;
6438 MptResetHandlers[i] = NULL;
6441 /* Register ourselves (mptbase) in order to facilitate
6442 * EventNotification handling.
6444 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6446 /* Register for hard reset handling callbacks.
6448 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6449 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6454 #ifdef CONFIG_PROC_FS
6455 (void) procmpt_create();
6460 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6462 * fusion_exit - Perform driver unload cleanup.
6464 * This routine frees all resources associated with each MPT adapter
6465 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6471 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6473 mpt_reset_deregister(mpt_base_index);
6475 #ifdef CONFIG_PROC_FS
6480 module_init(fusion_init);
6481 module_exit(fusion_exit);