iwlwifi: introduce host commands callbacks
[linux/fpc-iii.git] / drivers / message / fusion / mptbase.c
blobc6be6eba7dc360d82c63e0892d5da4008742f906
1 /*
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 PCI chip/adapter(s)
6 * running LSI Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2007 LSI Corporation
9 * (mailto:DL-MPTFusionLinux@lsi.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.
23 NO WARRANTY
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>
61 #include <asm/io.h>
62 #ifdef CONFIG_MTRR
63 #include <asm/mtrr.h>
64 #endif
66 #include "mptbase.h"
67 #include "lsi/mpi_log_fc.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT base driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptbase"
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION);
80 * cmd line parameters
82 static int mpt_msi_enable;
83 module_param(mpt_msi_enable, int, 0);
84 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
86 static int mpt_channel_mapping;
87 module_param(mpt_channel_mapping, int, 0);
88 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
90 static int mpt_debug_level;
91 static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
92 module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
93 &mpt_debug_level, 0600);
94 MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");
96 #ifdef MFCNT
97 static int mfcounter = 0;
98 #define PRINT_MF_COUNT 20000
99 #endif
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
103 * Public data...
106 struct proc_dir_entry *mpt_proc_root_dir;
108 #define WHOINIT_UNKNOWN 0xAA
110 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
112 * Private data...
114 /* Adapter link list */
115 LIST_HEAD(ioc_list);
116 /* Callback lookup table */
117 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
118 /* Protocol driver class lookup table */
119 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
120 /* Event handler lookup table */
121 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
122 /* Reset handler lookup table */
123 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
124 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
126 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
129 * Driver Callback Index's
131 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
132 static u8 last_drv_idx;
134 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
136 * Forward protos...
138 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
139 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
140 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
141 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
142 int sleepFlag);
143 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
144 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
145 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
146 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
148 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
149 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
150 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
151 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
152 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
153 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
154 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
155 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
156 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
157 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
158 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
159 static int PrimeIocFifos(MPT_ADAPTER *ioc);
160 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
161 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
162 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
163 static int GetLanConfigPages(MPT_ADAPTER *ioc);
164 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
165 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
166 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
167 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
168 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
169 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
170 static void mpt_timer_expired(unsigned long data);
171 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
172 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
173 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
174 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
175 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
177 #ifdef CONFIG_PROC_FS
178 static int procmpt_summary_read(char *buf, char **start, off_t offset,
179 int request, int *eof, void *data);
180 static int procmpt_version_read(char *buf, char **start, off_t offset,
181 int request, int *eof, void *data);
182 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
183 int request, int *eof, void *data);
184 #endif
185 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
187 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
188 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
189 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
190 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
191 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
192 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
193 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
194 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
196 /* module entry point */
197 static int __init fusion_init (void);
198 static void __exit fusion_exit (void);
200 #define CHIPREG_READ32(addr) readl_relaxed(addr)
201 #define CHIPREG_READ32_dmasync(addr) readl(addr)
202 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
203 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
204 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
206 static void
207 pci_disable_io_access(struct pci_dev *pdev)
209 u16 command_reg;
211 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
212 command_reg &= ~1;
213 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
216 static void
217 pci_enable_io_access(struct pci_dev *pdev)
219 u16 command_reg;
221 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
222 command_reg |= 1;
223 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
226 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
228 int ret = param_set_int(val, kp);
229 MPT_ADAPTER *ioc;
231 if (ret)
232 return ret;
234 list_for_each_entry(ioc, &ioc_list, list)
235 ioc->debug_level = mpt_debug_level;
236 return 0;
240 * mpt_get_cb_idx - obtain cb_idx for registered driver
241 * @dclass: class driver enum
243 * Returns cb_idx, or zero means it wasn't found
245 static u8
246 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
248 u8 cb_idx;
250 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
251 if (MptDriverClass[cb_idx] == dclass)
252 return cb_idx;
253 return 0;
257 * Process turbo (context) reply...
259 static void
260 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
262 MPT_FRAME_HDR *mf = NULL;
263 MPT_FRAME_HDR *mr = NULL;
264 u16 req_idx = 0;
265 u8 cb_idx;
267 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
268 ioc->name, pa));
270 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
271 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
272 req_idx = pa & 0x0000FFFF;
273 cb_idx = (pa & 0x00FF0000) >> 16;
274 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
275 break;
276 case MPI_CONTEXT_REPLY_TYPE_LAN:
277 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
279 * Blind set of mf to NULL here was fatal
280 * after lan_reply says "freeme"
281 * Fix sort of combined with an optimization here;
282 * added explicit check for case where lan_reply
283 * was just returning 1 and doing nothing else.
284 * For this case skip the callback, but set up
285 * proper mf value first here:-)
287 if ((pa & 0x58000000) == 0x58000000) {
288 req_idx = pa & 0x0000FFFF;
289 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
290 mpt_free_msg_frame(ioc, mf);
291 mb();
292 return;
293 break;
295 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
296 break;
297 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
298 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
299 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
300 break;
301 default:
302 cb_idx = 0;
303 BUG();
306 /* Check for (valid) IO callback! */
307 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
308 MptCallbacks[cb_idx] == NULL) {
309 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
310 __FUNCTION__, ioc->name, cb_idx);
311 goto out;
314 if (MptCallbacks[cb_idx](ioc, mf, mr))
315 mpt_free_msg_frame(ioc, mf);
316 out:
317 mb();
320 static void
321 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
323 MPT_FRAME_HDR *mf;
324 MPT_FRAME_HDR *mr;
325 u16 req_idx;
326 u8 cb_idx;
327 int freeme;
329 u32 reply_dma_low;
330 u16 ioc_stat;
332 /* non-TURBO reply! Hmmm, something may be up...
333 * Newest turbo reply mechanism; get address
334 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
337 /* Map DMA address of reply header to cpu address.
338 * pa is 32 bits - but the dma address may be 32 or 64 bits
339 * get offset based only only the low addresses
342 reply_dma_low = (pa <<= 1);
343 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
344 (reply_dma_low - ioc->reply_frames_low_dma));
346 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
347 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
348 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
350 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
351 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
352 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
354 /* Check/log IOC log info
356 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
357 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
358 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
359 if (ioc->bus_type == FC)
360 mpt_fc_log_info(ioc, log_info);
361 else if (ioc->bus_type == SPI)
362 mpt_spi_log_info(ioc, log_info);
363 else if (ioc->bus_type == SAS)
364 mpt_sas_log_info(ioc, log_info);
367 if (ioc_stat & MPI_IOCSTATUS_MASK)
368 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
370 /* Check for (valid) IO callback! */
371 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
372 MptCallbacks[cb_idx] == NULL) {
373 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
374 __FUNCTION__, ioc->name, cb_idx);
375 freeme = 0;
376 goto out;
379 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
381 out:
382 /* Flush (non-TURBO) reply with a WRITE! */
383 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
385 if (freeme)
386 mpt_free_msg_frame(ioc, mf);
387 mb();
390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
392 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
393 * @irq: irq number (not used)
394 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
396 * This routine is registered via the request_irq() kernel API call,
397 * and handles all interrupts generated from a specific MPT adapter
398 * (also referred to as a IO Controller or IOC).
399 * This routine must clear the interrupt from the adapter and does
400 * so by reading the reply FIFO. Multiple replies may be processed
401 * per single call to this routine.
403 * This routine handles register-level access of the adapter but
404 * dispatches (calls) a protocol-specific callback routine to handle
405 * the protocol-specific details of the MPT request completion.
407 static irqreturn_t
408 mpt_interrupt(int irq, void *bus_id)
410 MPT_ADAPTER *ioc = bus_id;
411 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
413 if (pa == 0xFFFFFFFF)
414 return IRQ_NONE;
417 * Drain the reply FIFO!
419 do {
420 if (pa & MPI_ADDRESS_REPLY_A_BIT)
421 mpt_reply(ioc, pa);
422 else
423 mpt_turbo_reply(ioc, pa);
424 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
425 } while (pa != 0xFFFFFFFF);
427 return IRQ_HANDLED;
430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
432 * mpt_base_reply - MPT base driver's callback routine
433 * @ioc: Pointer to MPT_ADAPTER structure
434 * @mf: Pointer to original MPT request frame
435 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
437 * MPT base driver's callback routine; all base driver
438 * "internal" request/reply processing is routed here.
439 * Currently used for EventNotification and EventAck handling.
441 * Returns 1 indicating original alloc'd request frame ptr
442 * should be freed, or 0 if it shouldn't.
444 static int
445 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
447 int freereq = 1;
448 u8 func;
450 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
451 #ifdef CONFIG_FUSION_LOGGING
452 if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
453 !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
454 dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
455 ioc->name, mf));
456 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
458 #endif
460 func = reply->u.hdr.Function;
461 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
462 ioc->name, func));
464 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
465 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
466 int evHandlers = 0;
467 int results;
469 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
470 if (results != evHandlers) {
471 /* CHECKME! Any special handling needed here? */
472 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
473 ioc->name, evHandlers, results));
477 * Hmmm... It seems that EventNotificationReply is an exception
478 * to the rule of one reply per request.
480 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
481 freereq = 0;
482 } else {
483 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
484 ioc->name, pEvReply));
487 #ifdef CONFIG_PROC_FS
488 // LogEvent(ioc, pEvReply);
489 #endif
491 } else if (func == MPI_FUNCTION_EVENT_ACK) {
492 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
493 ioc->name));
494 } else if (func == MPI_FUNCTION_CONFIG) {
495 CONFIGPARMS *pCfg;
496 unsigned long flags;
498 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
499 ioc->name, mf, reply));
501 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
503 if (pCfg) {
504 /* disable timer and remove from linked list */
505 del_timer(&pCfg->timer);
507 spin_lock_irqsave(&ioc->FreeQlock, flags);
508 list_del(&pCfg->linkage);
509 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
512 * If IOC Status is SUCCESS, save the header
513 * and set the status code to GOOD.
515 pCfg->status = MPT_CONFIG_ERROR;
516 if (reply) {
517 ConfigReply_t *pReply = (ConfigReply_t *)reply;
518 u16 status;
520 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
521 dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
522 ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
524 pCfg->status = status;
525 if (status == MPI_IOCSTATUS_SUCCESS) {
526 if ((pReply->Header.PageType &
527 MPI_CONFIG_PAGETYPE_MASK) ==
528 MPI_CONFIG_PAGETYPE_EXTENDED) {
529 pCfg->cfghdr.ehdr->ExtPageLength =
530 le16_to_cpu(pReply->ExtPageLength);
531 pCfg->cfghdr.ehdr->ExtPageType =
532 pReply->ExtPageType;
534 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
536 /* If this is a regular header, save PageLength. */
537 /* LMP Do this better so not using a reserved field! */
538 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
539 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
540 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
545 * Wake up the original calling thread
547 pCfg->wait_done = 1;
548 wake_up(&mpt_waitq);
550 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
551 /* we should be always getting a reply frame */
552 memcpy(ioc->persist_reply_frame, reply,
553 min(MPT_DEFAULT_FRAME_SIZE,
554 4*reply->u.reply.MsgLength));
555 del_timer(&ioc->persist_timer);
556 ioc->persist_wait_done = 1;
557 wake_up(&mpt_waitq);
558 } else {
559 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
560 ioc->name, func);
564 * Conditionally tell caller to free the original
565 * EventNotification/EventAck/unexpected request frame!
567 return freereq;
570 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
572 * mpt_register - Register protocol-specific main callback handler.
573 * @cbfunc: callback function pointer
574 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
576 * This routine is called by a protocol-specific driver (SCSI host,
577 * LAN, SCSI target) to register its reply callback routine. Each
578 * protocol-specific driver must do this before it will be able to
579 * use any IOC resources, such as obtaining request frames.
581 * NOTES: The SCSI protocol driver currently calls this routine thrice
582 * in order to register separate callbacks; one for "normal" SCSI IO;
583 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
585 * Returns u8 valued "handle" in the range (and S.O.D. order)
586 * {N,...,7,6,5,...,1} if successful.
587 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
588 * considered an error by the caller.
591 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
593 u8 cb_idx;
594 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
597 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
598 * (slot/handle 0 is reserved!)
600 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
601 if (MptCallbacks[cb_idx] == NULL) {
602 MptCallbacks[cb_idx] = cbfunc;
603 MptDriverClass[cb_idx] = dclass;
604 MptEvHandlers[cb_idx] = NULL;
605 last_drv_idx = cb_idx;
606 break;
610 return last_drv_idx;
613 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
615 * mpt_deregister - Deregister a protocol drivers resources.
616 * @cb_idx: previously registered callback handle
618 * Each protocol-specific driver should call this routine when its
619 * module is unloaded.
621 void
622 mpt_deregister(u8 cb_idx)
624 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
625 MptCallbacks[cb_idx] = NULL;
626 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
627 MptEvHandlers[cb_idx] = NULL;
629 last_drv_idx++;
633 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
635 * mpt_event_register - Register protocol-specific event callback handler.
636 * @cb_idx: previously registered (via mpt_register) callback handle
637 * @ev_cbfunc: callback function
639 * This routine can be called by one or more protocol-specific drivers
640 * if/when they choose to be notified of MPT events.
642 * Returns 0 for success.
645 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
647 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
648 return -1;
650 MptEvHandlers[cb_idx] = ev_cbfunc;
651 return 0;
654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
656 * mpt_event_deregister - Deregister protocol-specific event callback 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 events,
661 * or when its module is unloaded.
663 void
664 mpt_event_deregister(u8 cb_idx)
666 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
667 return;
669 MptEvHandlers[cb_idx] = NULL;
672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
674 * mpt_reset_register - Register protocol-specific IOC reset handler.
675 * @cb_idx: previously registered (via mpt_register) callback handle
676 * @reset_func: reset function
678 * This routine can be called by one or more protocol-specific drivers
679 * if/when they choose to be notified of IOC resets.
681 * Returns 0 for success.
684 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
686 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
687 return -1;
689 MptResetHandlers[cb_idx] = reset_func;
690 return 0;
693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
695 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
696 * @cb_idx: previously registered callback handle
698 * Each protocol-specific driver should call this routine
699 * when it does not (or can no longer) handle IOC reset handling,
700 * or when its module is unloaded.
702 void
703 mpt_reset_deregister(u8 cb_idx)
705 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
706 return;
708 MptResetHandlers[cb_idx] = NULL;
711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
713 * mpt_device_driver_register - Register device driver hooks
714 * @dd_cbfunc: driver callbacks struct
715 * @cb_idx: MPT protocol driver index
718 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
720 MPT_ADAPTER *ioc;
721 const struct pci_device_id *id;
723 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
724 return -EINVAL;
726 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
728 /* call per pci device probe entry point */
729 list_for_each_entry(ioc, &ioc_list, list) {
730 id = ioc->pcidev->driver ?
731 ioc->pcidev->driver->id_table : NULL;
732 if (dd_cbfunc->probe)
733 dd_cbfunc->probe(ioc->pcidev, id);
736 return 0;
739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
741 * mpt_device_driver_deregister - DeRegister device driver hooks
742 * @cb_idx: MPT protocol driver index
744 void
745 mpt_device_driver_deregister(u8 cb_idx)
747 struct mpt_pci_driver *dd_cbfunc;
748 MPT_ADAPTER *ioc;
750 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
751 return;
753 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
755 list_for_each_entry(ioc, &ioc_list, list) {
756 if (dd_cbfunc->remove)
757 dd_cbfunc->remove(ioc->pcidev);
760 MptDeviceDriverHandlers[cb_idx] = NULL;
764 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
766 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
767 * @cb_idx: Handle of registered MPT protocol driver
768 * @ioc: Pointer to MPT adapter structure
770 * Obtain an MPT request frame from the pool (of 1024) that are
771 * allocated per MPT adapter.
773 * Returns pointer to a MPT request frame or %NULL if none are available
774 * or IOC is not active.
776 MPT_FRAME_HDR*
777 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
779 MPT_FRAME_HDR *mf;
780 unsigned long flags;
781 u16 req_idx; /* Request index */
783 /* validate handle and ioc identifier */
785 #ifdef MFCNT
786 if (!ioc->active)
787 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
788 "returning NULL!\n", ioc->name);
789 #endif
791 /* If interrupts are not attached, do not return a request frame */
792 if (!ioc->active)
793 return NULL;
795 spin_lock_irqsave(&ioc->FreeQlock, flags);
796 if (!list_empty(&ioc->FreeQ)) {
797 int req_offset;
799 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
800 u.frame.linkage.list);
801 list_del(&mf->u.frame.linkage.list);
802 mf->u.frame.linkage.arg1 = 0;
803 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
804 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
805 /* u16! */
806 req_idx = req_offset / ioc->req_sz;
807 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
808 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
809 /* Default, will be changed if necessary in SG generation */
810 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
811 #ifdef MFCNT
812 ioc->mfcnt++;
813 #endif
815 else
816 mf = NULL;
817 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
819 #ifdef MFCNT
820 if (mf == NULL)
821 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
822 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
823 ioc->req_depth);
824 mfcounter++;
825 if (mfcounter == PRINT_MF_COUNT)
826 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
827 ioc->mfcnt, ioc->req_depth);
828 #endif
830 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
831 ioc->name, cb_idx, ioc->id, mf));
832 return mf;
835 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
837 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
838 * @cb_idx: Handle of registered MPT protocol driver
839 * @ioc: Pointer to MPT adapter structure
840 * @mf: Pointer to MPT request frame
842 * This routine posts an MPT request frame to the request post FIFO of a
843 * specific MPT adapter.
845 void
846 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
848 u32 mf_dma_addr;
849 int req_offset;
850 u16 req_idx; /* Request index */
852 /* ensure values are reset properly! */
853 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
854 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
855 /* u16! */
856 req_idx = req_offset / ioc->req_sz;
857 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
858 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
860 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
862 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
863 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
864 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
865 ioc->RequestNB[req_idx]));
866 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
870 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
871 * @cb_idx: Handle of registered MPT protocol driver
872 * @ioc: Pointer to MPT adapter structure
873 * @mf: Pointer to MPT request frame
875 * Send a protocol-specific MPT request frame to an IOC using
876 * hi-priority request queue.
878 * This routine posts an MPT request frame to the request post FIFO of a
879 * specific MPT adapter.
881 void
882 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
884 u32 mf_dma_addr;
885 int req_offset;
886 u16 req_idx; /* Request index */
888 /* ensure values are reset properly! */
889 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
890 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
891 req_idx = req_offset / ioc->req_sz;
892 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
893 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
895 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
897 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
898 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
899 ioc->name, mf_dma_addr, req_idx));
900 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
903 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
905 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
906 * @handle: Handle of registered MPT protocol driver
907 * @ioc: Pointer to MPT adapter structure
908 * @mf: Pointer to MPT request frame
910 * This routine places a MPT request frame back on the MPT adapter's
911 * FreeQ.
913 void
914 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
916 unsigned long flags;
918 /* Put Request back on FreeQ! */
919 spin_lock_irqsave(&ioc->FreeQlock, flags);
920 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
921 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
922 #ifdef MFCNT
923 ioc->mfcnt--;
924 #endif
925 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
928 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
930 * mpt_add_sge - Place a simple SGE at address pAddr.
931 * @pAddr: virtual address for SGE
932 * @flagslength: SGE flags and data transfer length
933 * @dma_addr: Physical address
935 * This routine places a MPT request frame back on the MPT adapter's
936 * FreeQ.
938 void
939 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
941 if (sizeof(dma_addr_t) == sizeof(u64)) {
942 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
943 u32 tmp = dma_addr & 0xFFFFFFFF;
945 pSge->FlagsLength = cpu_to_le32(flagslength);
946 pSge->Address.Low = cpu_to_le32(tmp);
947 tmp = (u32) ((u64)dma_addr >> 32);
948 pSge->Address.High = cpu_to_le32(tmp);
950 } else {
951 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
952 pSge->FlagsLength = cpu_to_le32(flagslength);
953 pSge->Address = cpu_to_le32(dma_addr);
957 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
959 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
960 * @cb_idx: Handle of registered MPT protocol driver
961 * @ioc: Pointer to MPT adapter structure
962 * @reqBytes: Size of the request in bytes
963 * @req: Pointer to MPT request frame
964 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
966 * This routine is used exclusively to send MptScsiTaskMgmt
967 * requests since they are required to be sent via doorbell handshake.
969 * NOTE: It is the callers responsibility to byte-swap fields in the
970 * request which are greater than 1 byte in size.
972 * Returns 0 for success, non-zero for failure.
975 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
977 int r = 0;
978 u8 *req_as_bytes;
979 int ii;
981 /* State is known to be good upon entering
982 * this function so issue the bus reset
983 * request.
987 * Emulate what mpt_put_msg_frame() does /wrt to sanity
988 * setting cb_idx/req_idx. But ONLY if this request
989 * is in proper (pre-alloc'd) request buffer range...
991 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
992 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
993 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
994 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
995 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
998 /* Make sure there are no doorbells */
999 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1001 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1002 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1003 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1005 /* Wait for IOC doorbell int */
1006 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1007 return ii;
1010 /* Read doorbell and check for active bit */
1011 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1012 return -5;
1014 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1015 ioc->name, ii));
1017 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1019 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1020 return -2;
1023 /* Send request via doorbell handshake */
1024 req_as_bytes = (u8 *) req;
1025 for (ii = 0; ii < reqBytes/4; ii++) {
1026 u32 word;
1028 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1029 (req_as_bytes[(ii*4) + 1] << 8) |
1030 (req_as_bytes[(ii*4) + 2] << 16) |
1031 (req_as_bytes[(ii*4) + 3] << 24));
1032 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1033 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1034 r = -3;
1035 break;
1039 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1040 r = 0;
1041 else
1042 r = -4;
1044 /* Make sure there are no doorbells */
1045 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1047 return r;
1050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1052 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1053 * @ioc: Pointer to MPT adapter structure
1054 * @access_control_value: define bits below
1055 * @sleepFlag: Specifies whether the process can sleep
1057 * Provides mechanism for the host driver to control the IOC's
1058 * Host Page Buffer access.
1060 * Access Control Value - bits[15:12]
1061 * 0h Reserved
1062 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1063 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1064 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1066 * Returns 0 for success, non-zero for failure.
1069 static int
1070 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1072 int r = 0;
1074 /* return if in use */
1075 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1076 & MPI_DOORBELL_ACTIVE)
1077 return -1;
1079 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1081 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1082 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1083 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1084 (access_control_value<<12)));
1086 /* Wait for IOC to clear Doorbell Status bit */
1087 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1088 return -2;
1089 }else
1090 return 0;
1093 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1095 * mpt_host_page_alloc - allocate system memory for the fw
1096 * @ioc: Pointer to pointer to IOC adapter
1097 * @ioc_init: Pointer to ioc init config page
1099 * If we already allocated memory in past, then resend the same pointer.
1100 * Returns 0 for success, non-zero for failure.
1102 static int
1103 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1105 char *psge;
1106 int flags_length;
1107 u32 host_page_buffer_sz=0;
1109 if(!ioc->HostPageBuffer) {
1111 host_page_buffer_sz =
1112 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1114 if(!host_page_buffer_sz)
1115 return 0; /* fw doesn't need any host buffers */
1117 /* spin till we get enough memory */
1118 while(host_page_buffer_sz > 0) {
1120 if((ioc->HostPageBuffer = pci_alloc_consistent(
1121 ioc->pcidev,
1122 host_page_buffer_sz,
1123 &ioc->HostPageBuffer_dma)) != NULL) {
1125 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1126 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1127 ioc->name, ioc->HostPageBuffer,
1128 (u32)ioc->HostPageBuffer_dma,
1129 host_page_buffer_sz));
1130 ioc->alloc_total += host_page_buffer_sz;
1131 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1132 break;
1135 host_page_buffer_sz -= (4*1024);
1139 if(!ioc->HostPageBuffer) {
1140 printk(MYIOC_s_ERR_FMT
1141 "Failed to alloc memory for host_page_buffer!\n",
1142 ioc->name);
1143 return -999;
1146 psge = (char *)&ioc_init->HostPageBufferSGE;
1147 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1148 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1149 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1150 MPI_SGE_FLAGS_HOST_TO_IOC |
1151 MPI_SGE_FLAGS_END_OF_BUFFER;
1152 if (sizeof(dma_addr_t) == sizeof(u64)) {
1153 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1155 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1156 flags_length |= ioc->HostPageBuffer_sz;
1157 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1158 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1160 return 0;
1163 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1165 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1166 * @iocid: IOC unique identifier (integer)
1167 * @iocpp: Pointer to pointer to IOC adapter
1169 * Given a unique IOC identifier, set pointer to the associated MPT
1170 * adapter structure.
1172 * Returns iocid and sets iocpp if iocid is found.
1173 * Returns -1 if iocid is not found.
1176 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1178 MPT_ADAPTER *ioc;
1180 list_for_each_entry(ioc,&ioc_list,list) {
1181 if (ioc->id == iocid) {
1182 *iocpp =ioc;
1183 return iocid;
1187 *iocpp = NULL;
1188 return -1;
1192 * mpt_get_product_name - returns product string
1193 * @vendor: pci vendor id
1194 * @device: pci device id
1195 * @revision: pci revision id
1196 * @prod_name: string returned
1198 * Returns product string displayed when driver loads,
1199 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1202 static void
1203 mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1205 char *product_str = NULL;
1207 if (vendor == PCI_VENDOR_ID_BROCADE) {
1208 switch (device)
1210 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1211 switch (revision)
1213 case 0x00:
1214 product_str = "BRE040 A0";
1215 break;
1216 case 0x01:
1217 product_str = "BRE040 A1";
1218 break;
1219 default:
1220 product_str = "BRE040";
1221 break;
1223 break;
1225 goto out;
1228 switch (device)
1230 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1231 product_str = "LSIFC909 B1";
1232 break;
1233 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1234 product_str = "LSIFC919 B0";
1235 break;
1236 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1237 product_str = "LSIFC929 B0";
1238 break;
1239 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1240 if (revision < 0x80)
1241 product_str = "LSIFC919X A0";
1242 else
1243 product_str = "LSIFC919XL A1";
1244 break;
1245 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1246 if (revision < 0x80)
1247 product_str = "LSIFC929X A0";
1248 else
1249 product_str = "LSIFC929XL A1";
1250 break;
1251 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1252 product_str = "LSIFC939X A1";
1253 break;
1254 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1255 product_str = "LSIFC949X A1";
1256 break;
1257 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1258 switch (revision)
1260 case 0x00:
1261 product_str = "LSIFC949E A0";
1262 break;
1263 case 0x01:
1264 product_str = "LSIFC949E A1";
1265 break;
1266 default:
1267 product_str = "LSIFC949E";
1268 break;
1270 break;
1271 case MPI_MANUFACTPAGE_DEVID_53C1030:
1272 switch (revision)
1274 case 0x00:
1275 product_str = "LSI53C1030 A0";
1276 break;
1277 case 0x01:
1278 product_str = "LSI53C1030 B0";
1279 break;
1280 case 0x03:
1281 product_str = "LSI53C1030 B1";
1282 break;
1283 case 0x07:
1284 product_str = "LSI53C1030 B2";
1285 break;
1286 case 0x08:
1287 product_str = "LSI53C1030 C0";
1288 break;
1289 case 0x80:
1290 product_str = "LSI53C1030T A0";
1291 break;
1292 case 0x83:
1293 product_str = "LSI53C1030T A2";
1294 break;
1295 case 0x87:
1296 product_str = "LSI53C1030T A3";
1297 break;
1298 case 0xc1:
1299 product_str = "LSI53C1020A A1";
1300 break;
1301 default:
1302 product_str = "LSI53C1030";
1303 break;
1305 break;
1306 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1307 switch (revision)
1309 case 0x03:
1310 product_str = "LSI53C1035 A2";
1311 break;
1312 case 0x04:
1313 product_str = "LSI53C1035 B0";
1314 break;
1315 default:
1316 product_str = "LSI53C1035";
1317 break;
1319 break;
1320 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1321 switch (revision)
1323 case 0x00:
1324 product_str = "LSISAS1064 A1";
1325 break;
1326 case 0x01:
1327 product_str = "LSISAS1064 A2";
1328 break;
1329 case 0x02:
1330 product_str = "LSISAS1064 A3";
1331 break;
1332 case 0x03:
1333 product_str = "LSISAS1064 A4";
1334 break;
1335 default:
1336 product_str = "LSISAS1064";
1337 break;
1339 break;
1340 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1341 switch (revision)
1343 case 0x00:
1344 product_str = "LSISAS1064E A0";
1345 break;
1346 case 0x01:
1347 product_str = "LSISAS1064E B0";
1348 break;
1349 case 0x02:
1350 product_str = "LSISAS1064E B1";
1351 break;
1352 case 0x04:
1353 product_str = "LSISAS1064E B2";
1354 break;
1355 case 0x08:
1356 product_str = "LSISAS1064E B3";
1357 break;
1358 default:
1359 product_str = "LSISAS1064E";
1360 break;
1362 break;
1363 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1364 switch (revision)
1366 case 0x00:
1367 product_str = "LSISAS1068 A0";
1368 break;
1369 case 0x01:
1370 product_str = "LSISAS1068 B0";
1371 break;
1372 case 0x02:
1373 product_str = "LSISAS1068 B1";
1374 break;
1375 default:
1376 product_str = "LSISAS1068";
1377 break;
1379 break;
1380 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1381 switch (revision)
1383 case 0x00:
1384 product_str = "LSISAS1068E A0";
1385 break;
1386 case 0x01:
1387 product_str = "LSISAS1068E B0";
1388 break;
1389 case 0x02:
1390 product_str = "LSISAS1068E B1";
1391 break;
1392 case 0x04:
1393 product_str = "LSISAS1068E B2";
1394 break;
1395 case 0x08:
1396 product_str = "LSISAS1068E B3";
1397 break;
1398 default:
1399 product_str = "LSISAS1068E";
1400 break;
1402 break;
1403 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1404 switch (revision)
1406 case 0x00:
1407 product_str = "LSISAS1078 A0";
1408 break;
1409 case 0x01:
1410 product_str = "LSISAS1078 B0";
1411 break;
1412 case 0x02:
1413 product_str = "LSISAS1078 C0";
1414 break;
1415 case 0x03:
1416 product_str = "LSISAS1078 C1";
1417 break;
1418 case 0x04:
1419 product_str = "LSISAS1078 C2";
1420 break;
1421 default:
1422 product_str = "LSISAS1078";
1423 break;
1425 break;
1428 out:
1429 if (product_str)
1430 sprintf(prod_name, "%s", product_str);
1434 * mpt_mapresources - map in memory mapped io
1435 * @ioc: Pointer to pointer to IOC adapter
1438 static int
1439 mpt_mapresources(MPT_ADAPTER *ioc)
1441 u8 __iomem *mem;
1442 int ii;
1443 unsigned long mem_phys;
1444 unsigned long port;
1445 u32 msize;
1446 u32 psize;
1447 u8 revision;
1448 int r = -ENODEV;
1449 struct pci_dev *pdev;
1451 pdev = ioc->pcidev;
1452 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1453 if (pci_enable_device_mem(pdev)) {
1454 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1455 "failed\n", ioc->name);
1456 return r;
1458 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1459 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1460 "MEM failed\n", ioc->name);
1461 return r;
1464 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1466 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
1467 && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
1468 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1469 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1470 ioc->name));
1471 } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
1472 && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
1473 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1474 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1475 ioc->name));
1476 } else {
1477 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1478 ioc->name, pci_name(pdev));
1479 pci_release_selected_regions(pdev, ioc->bars);
1480 return r;
1483 mem_phys = msize = 0;
1484 port = psize = 0;
1485 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1486 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1487 if (psize)
1488 continue;
1489 /* Get I/O space! */
1490 port = pci_resource_start(pdev, ii);
1491 psize = pci_resource_len(pdev, ii);
1492 } else {
1493 if (msize)
1494 continue;
1495 /* Get memmap */
1496 mem_phys = pci_resource_start(pdev, ii);
1497 msize = pci_resource_len(pdev, ii);
1500 ioc->mem_size = msize;
1502 mem = NULL;
1503 /* Get logical ptr for PciMem0 space */
1504 /*mem = ioremap(mem_phys, msize);*/
1505 mem = ioremap(mem_phys, msize);
1506 if (mem == NULL) {
1507 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1508 " memory!\n", ioc->name);
1509 return -EINVAL;
1511 ioc->memmap = mem;
1512 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
1513 ioc->name, mem, mem_phys));
1515 ioc->mem_phys = mem_phys;
1516 ioc->chip = (SYSIF_REGS __iomem *)mem;
1518 /* Save Port IO values in case we need to do downloadboot */
1519 ioc->pio_mem_phys = port;
1520 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1522 return 0;
1525 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1527 * mpt_attach - Install a PCI intelligent MPT adapter.
1528 * @pdev: Pointer to pci_dev structure
1529 * @id: PCI device ID information
1531 * This routine performs all the steps necessary to bring the IOC of
1532 * a MPT adapter to a OPERATIONAL state. This includes registering
1533 * memory regions, registering the interrupt, and allocating request
1534 * and reply memory pools.
1536 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1537 * MPT adapter.
1539 * Returns 0 for success, non-zero for failure.
1541 * TODO: Add support for polled controllers
1544 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1546 MPT_ADAPTER *ioc;
1547 u8 cb_idx;
1548 int r = -ENODEV;
1549 u8 revision;
1550 u8 pcixcmd;
1551 static int mpt_ids = 0;
1552 #ifdef CONFIG_PROC_FS
1553 struct proc_dir_entry *dent, *ent;
1554 #endif
1556 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1557 if (ioc == NULL) {
1558 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1559 return -ENOMEM;
1562 ioc->id = mpt_ids++;
1563 sprintf(ioc->name, "ioc%d", ioc->id);
1566 * set initial debug level
1567 * (refer to mptdebug.h)
1570 ioc->debug_level = mpt_debug_level;
1571 if (mpt_debug_level)
1572 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1574 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1576 ioc->pcidev = pdev;
1577 if (mpt_mapresources(ioc)) {
1578 kfree(ioc);
1579 return r;
1582 ioc->alloc_total = sizeof(MPT_ADAPTER);
1583 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1584 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1586 ioc->pcidev = pdev;
1587 ioc->diagPending = 0;
1588 spin_lock_init(&ioc->diagLock);
1589 spin_lock_init(&ioc->initializing_hba_lock);
1591 /* Initialize the event logging.
1593 ioc->eventTypes = 0; /* None */
1594 ioc->eventContext = 0;
1595 ioc->eventLogSize = 0;
1596 ioc->events = NULL;
1598 #ifdef MFCNT
1599 ioc->mfcnt = 0;
1600 #endif
1602 ioc->cached_fw = NULL;
1604 /* Initilize SCSI Config Data structure
1606 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1608 /* Initialize the running configQ head.
1610 INIT_LIST_HEAD(&ioc->configQ);
1612 /* Initialize the fc rport list head.
1614 INIT_LIST_HEAD(&ioc->fc_rports);
1616 /* Find lookup slot. */
1617 INIT_LIST_HEAD(&ioc->list);
1619 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1620 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1622 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1623 mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1625 switch (pdev->device)
1627 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1628 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1629 ioc->errata_flag_1064 = 1;
1630 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1631 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1632 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1633 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1634 ioc->bus_type = FC;
1635 break;
1637 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1638 if (revision < XL_929) {
1639 /* 929X Chip Fix. Set Split transactions level
1640 * for PCIX. Set MOST bits to zero.
1642 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1643 pcixcmd &= 0x8F;
1644 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1645 } else {
1646 /* 929XL Chip Fix. Set MMRBC to 0x08.
1648 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1649 pcixcmd |= 0x08;
1650 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1652 ioc->bus_type = FC;
1653 break;
1655 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1656 /* 919X Chip Fix. Set Split transactions level
1657 * for PCIX. Set MOST bits to zero.
1659 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1660 pcixcmd &= 0x8F;
1661 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1662 ioc->bus_type = FC;
1663 break;
1665 case MPI_MANUFACTPAGE_DEVID_53C1030:
1666 /* 1030 Chip Fix. Disable Split transactions
1667 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1669 if (revision < C0_1030) {
1670 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1671 pcixcmd &= 0x8F;
1672 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1675 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1676 ioc->bus_type = SPI;
1677 break;
1679 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1680 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1681 ioc->errata_flag_1064 = 1;
1683 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1684 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1685 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1686 ioc->bus_type = SAS;
1689 if (ioc->errata_flag_1064)
1690 pci_disable_io_access(pdev);
1692 spin_lock_init(&ioc->FreeQlock);
1694 /* Disable all! */
1695 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1696 ioc->active = 0;
1697 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1699 /* Set IOC ptr in the pcidev's driver data. */
1700 pci_set_drvdata(ioc->pcidev, ioc);
1702 /* Set lookup ptr. */
1703 list_add_tail(&ioc->list, &ioc_list);
1705 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1707 mpt_detect_bound_ports(ioc, pdev);
1709 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1710 CAN_SLEEP)) != 0){
1711 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1712 ioc->name, r);
1714 list_del(&ioc->list);
1715 if (ioc->alt_ioc)
1716 ioc->alt_ioc->alt_ioc = NULL;
1717 iounmap(ioc->memmap);
1718 if (r != -5)
1719 pci_release_selected_regions(pdev, ioc->bars);
1720 kfree(ioc);
1721 pci_set_drvdata(pdev, NULL);
1722 return r;
1725 /* call per device driver probe entry point */
1726 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1727 if(MptDeviceDriverHandlers[cb_idx] &&
1728 MptDeviceDriverHandlers[cb_idx]->probe) {
1729 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1733 #ifdef CONFIG_PROC_FS
1735 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1737 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1738 if (dent) {
1739 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1740 if (ent) {
1741 ent->read_proc = procmpt_iocinfo_read;
1742 ent->data = ioc;
1744 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1745 if (ent) {
1746 ent->read_proc = procmpt_summary_read;
1747 ent->data = ioc;
1750 #endif
1752 return 0;
1755 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1757 * mpt_detach - Remove a PCI intelligent MPT adapter.
1758 * @pdev: Pointer to pci_dev structure
1761 void
1762 mpt_detach(struct pci_dev *pdev)
1764 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1765 char pname[32];
1766 u8 cb_idx;
1768 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1769 remove_proc_entry(pname, NULL);
1770 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1771 remove_proc_entry(pname, NULL);
1772 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1773 remove_proc_entry(pname, NULL);
1775 /* call per device driver remove entry point */
1776 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1777 if(MptDeviceDriverHandlers[cb_idx] &&
1778 MptDeviceDriverHandlers[cb_idx]->remove) {
1779 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
1783 /* Disable interrupts! */
1784 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1786 ioc->active = 0;
1787 synchronize_irq(pdev->irq);
1789 /* Clear any lingering interrupt */
1790 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1792 CHIPREG_READ32(&ioc->chip->IntStatus);
1794 mpt_adapter_dispose(ioc);
1796 pci_set_drvdata(pdev, NULL);
1799 /**************************************************************************
1800 * Power Management
1802 #ifdef CONFIG_PM
1803 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1805 * mpt_suspend - Fusion MPT base driver suspend routine.
1806 * @pdev: Pointer to pci_dev structure
1807 * @state: new state to enter
1810 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1812 u32 device_state;
1813 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1815 device_state = pci_choose_state(pdev, state);
1816 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
1817 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1818 device_state);
1820 /* put ioc into READY_STATE */
1821 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1822 printk(MYIOC_s_ERR_FMT
1823 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1826 /* disable interrupts */
1827 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1828 ioc->active = 0;
1830 /* Clear any lingering interrupt */
1831 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1833 free_irq(ioc->pci_irq, ioc);
1834 if (mpt_msi_enable)
1835 pci_disable_msi(ioc->pcidev);
1836 ioc->pci_irq = -1;
1837 pci_save_state(pdev);
1838 pci_disable_device(pdev);
1839 pci_release_selected_regions(pdev, ioc->bars);
1840 pci_set_power_state(pdev, device_state);
1841 return 0;
1844 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1846 * mpt_resume - Fusion MPT base driver resume routine.
1847 * @pdev: Pointer to pci_dev structure
1850 mpt_resume(struct pci_dev *pdev)
1852 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1853 u32 device_state = pdev->current_state;
1854 int recovery_state;
1855 int err;
1857 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
1858 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1859 device_state);
1861 pci_set_power_state(pdev, PCI_D0);
1862 pci_enable_wake(pdev, PCI_D0, 0);
1863 pci_restore_state(pdev);
1864 ioc->pcidev = pdev;
1865 err = mpt_mapresources(ioc);
1866 if (err)
1867 return err;
1869 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1870 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1871 CHIPREG_READ32(&ioc->chip->Doorbell));
1874 * Errata workaround for SAS pci express:
1875 * Upon returning to the D0 state, the contents of the doorbell will be
1876 * stale data, and this will incorrectly signal to the host driver that
1877 * the firmware is ready to process mpt commands. The workaround is
1878 * to issue a diagnostic reset.
1880 if (ioc->bus_type == SAS && (pdev->device ==
1881 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
1882 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
1883 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
1884 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
1885 ioc->name);
1886 goto out;
1890 /* bring ioc to operational state */
1891 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
1892 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1893 CAN_SLEEP);
1894 if (recovery_state != 0)
1895 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
1896 "error:[%x]\n", ioc->name, recovery_state);
1897 else
1898 printk(MYIOC_s_INFO_FMT
1899 "pci-resume: success\n", ioc->name);
1900 out:
1901 return 0;
1904 #endif
1906 static int
1907 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
1909 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1910 ioc->bus_type != SPI) ||
1911 (MptDriverClass[index] == MPTFC_DRIVER &&
1912 ioc->bus_type != FC) ||
1913 (MptDriverClass[index] == MPTSAS_DRIVER &&
1914 ioc->bus_type != SAS))
1915 /* make sure we only call the relevant reset handler
1916 * for the bus */
1917 return 0;
1918 return (MptResetHandlers[index])(ioc, reset_phase);
1921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1923 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1924 * @ioc: Pointer to MPT adapter structure
1925 * @reason: Event word / reason
1926 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1928 * This routine performs all the steps necessary to bring the IOC
1929 * to a OPERATIONAL state.
1931 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1932 * MPT adapter.
1934 * Returns:
1935 * 0 for success
1936 * -1 if failed to get board READY
1937 * -2 if READY but IOCFacts Failed
1938 * -3 if READY but PrimeIOCFifos Failed
1939 * -4 if READY but IOCInit Failed
1940 * -5 if failed to enable_device and/or request_selected_regions
1941 * -6 if failed to upload firmware
1943 static int
1944 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1946 int hard_reset_done = 0;
1947 int alt_ioc_ready = 0;
1948 int hard;
1949 int rc=0;
1950 int ii;
1951 u8 cb_idx;
1952 int handlers;
1953 int ret = 0;
1954 int reset_alt_ioc_active = 0;
1955 int irq_allocated = 0;
1956 u8 *a;
1958 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
1959 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1961 /* Disable reply interrupts (also blocks FreeQ) */
1962 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1963 ioc->active = 0;
1965 if (ioc->alt_ioc) {
1966 if (ioc->alt_ioc->active)
1967 reset_alt_ioc_active = 1;
1969 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1970 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1971 ioc->alt_ioc->active = 0;
1974 hard = 1;
1975 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1976 hard = 0;
1978 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1979 if (hard_reset_done == -4) {
1980 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
1981 ioc->name);
1983 if (reset_alt_ioc_active && ioc->alt_ioc) {
1984 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1985 dprintk(ioc, printk(MYIOC_s_INFO_FMT
1986 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
1987 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1988 ioc->alt_ioc->active = 1;
1991 } else {
1992 printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
1994 return -1;
1997 /* hard_reset_done = 0 if a soft reset was performed
1998 * and 1 if a hard reset was performed.
2000 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2001 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2002 alt_ioc_ready = 1;
2003 else
2004 printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
2007 for (ii=0; ii<5; ii++) {
2008 /* Get IOC facts! Allow 5 retries */
2009 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2010 break;
2014 if (ii == 5) {
2015 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2016 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2017 ret = -2;
2018 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2019 MptDisplayIocCapabilities(ioc);
2022 if (alt_ioc_ready) {
2023 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2024 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2025 "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
2026 /* Retry - alt IOC was initialized once
2028 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2030 if (rc) {
2031 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2032 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2033 alt_ioc_ready = 0;
2034 reset_alt_ioc_active = 0;
2035 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2036 MptDisplayIocCapabilities(ioc->alt_ioc);
2040 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2041 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2042 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2043 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2044 IORESOURCE_IO);
2045 if (pci_enable_device(ioc->pcidev))
2046 return -5;
2047 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2048 "mpt"))
2049 return -5;
2053 * Device is reset now. It must have de-asserted the interrupt line
2054 * (if it was asserted) and it should be safe to register for the
2055 * interrupt now.
2057 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2058 ioc->pci_irq = -1;
2059 if (ioc->pcidev->irq) {
2060 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
2061 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2062 ioc->name);
2063 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2064 IRQF_SHARED, ioc->name, ioc);
2065 if (rc < 0) {
2066 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2067 "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
2068 if (mpt_msi_enable)
2069 pci_disable_msi(ioc->pcidev);
2070 return -EBUSY;
2072 irq_allocated = 1;
2073 ioc->pci_irq = ioc->pcidev->irq;
2074 pci_set_master(ioc->pcidev); /* ?? */
2075 dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
2076 "%d\n", ioc->name, ioc->pcidev->irq));
2080 /* Prime reply & request queues!
2081 * (mucho alloc's) Must be done prior to
2082 * init as upper addresses are needed for init.
2083 * If fails, continue with alt-ioc processing
2085 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2086 ret = -3;
2088 /* May need to check/upload firmware & data here!
2089 * If fails, continue with alt-ioc processing
2091 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2092 ret = -4;
2093 // NEW!
2094 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2095 printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
2096 ioc->alt_ioc->name, rc);
2097 alt_ioc_ready = 0;
2098 reset_alt_ioc_active = 0;
2101 if (alt_ioc_ready) {
2102 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2103 alt_ioc_ready = 0;
2104 reset_alt_ioc_active = 0;
2105 printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
2106 ioc->alt_ioc->name, rc);
2110 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2111 if (ioc->upload_fw) {
2112 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2113 "firmware upload required!\n", ioc->name));
2115 /* Controller is not operational, cannot do upload
2117 if (ret == 0) {
2118 rc = mpt_do_upload(ioc, sleepFlag);
2119 if (rc == 0) {
2120 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2122 * Maintain only one pointer to FW memory
2123 * so there will not be two attempt to
2124 * downloadboot onboard dual function
2125 * chips (mpt_adapter_disable,
2126 * mpt_diag_reset)
2128 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2129 "mpt_upload: alt_%s has cached_fw=%p \n",
2130 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2131 ioc->cached_fw = NULL;
2133 } else {
2134 printk(MYIOC_s_WARN_FMT
2135 "firmware upload failure!\n", ioc->name);
2136 ret = -6;
2142 if (ret == 0) {
2143 /* Enable! (reply interrupt) */
2144 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2145 ioc->active = 1;
2148 if (reset_alt_ioc_active && ioc->alt_ioc) {
2149 /* (re)Enable alt-IOC! (reply interrupt) */
2150 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
2151 ioc->alt_ioc->name));
2152 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2153 ioc->alt_ioc->active = 1;
2156 /* Enable MPT base driver management of EventNotification
2157 * and EventAck handling.
2159 if ((ret == 0) && (!ioc->facts.EventState))
2160 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
2162 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2163 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
2165 /* Add additional "reason" check before call to GetLanConfigPages
2166 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2167 * recursive scenario; GetLanConfigPages times out, timer expired
2168 * routine calls HardResetHandler, which calls into here again,
2169 * and we try GetLanConfigPages again...
2171 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2174 * Initalize link list for inactive raid volumes.
2176 init_MUTEX(&ioc->raid_data.inactive_list_mutex);
2177 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2179 if (ioc->bus_type == SAS) {
2181 /* clear persistency table */
2182 if(ioc->facts.IOCExceptions &
2183 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2184 ret = mptbase_sas_persist_operation(ioc,
2185 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2186 if(ret != 0)
2187 goto out;
2190 /* Find IM volumes
2192 mpt_findImVolumes(ioc);
2194 } else if (ioc->bus_type == FC) {
2195 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
2196 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2198 * Pre-fetch the ports LAN MAC address!
2199 * (LANPage1_t stuff)
2201 (void) GetLanConfigPages(ioc);
2202 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2203 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2204 "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2205 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
2208 } else {
2209 /* Get NVRAM and adapter maximums from SPP 0 and 2
2211 mpt_GetScsiPortSettings(ioc, 0);
2213 /* Get version and length of SDP 1
2215 mpt_readScsiDevicePageHeaders(ioc, 0);
2217 /* Find IM volumes
2219 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2220 mpt_findImVolumes(ioc);
2222 /* Check, and possibly reset, the coalescing value
2224 mpt_read_ioc_pg_1(ioc);
2226 mpt_read_ioc_pg_4(ioc);
2229 GetIoUnitPage2(ioc);
2230 mpt_get_manufacturing_pg_0(ioc);
2234 * Call each currently registered protocol IOC reset handler
2235 * with post-reset indication.
2236 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2237 * MptResetHandlers[] registered yet.
2239 if (hard_reset_done) {
2240 rc = handlers = 0;
2241 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2242 if ((ret == 0) && MptResetHandlers[cb_idx]) {
2243 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2244 "Calling IOC post_reset handler #%d\n",
2245 ioc->name, cb_idx));
2246 rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2247 handlers++;
2250 if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2251 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2252 "Calling IOC post_reset handler #%d\n",
2253 ioc->alt_ioc->name, cb_idx));
2254 rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2255 handlers++;
2258 /* FIXME? Examine results here? */
2261 out:
2262 if ((ret != 0) && irq_allocated) {
2263 free_irq(ioc->pci_irq, ioc);
2264 if (mpt_msi_enable)
2265 pci_disable_msi(ioc->pcidev);
2267 return ret;
2270 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2272 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2273 * @ioc: Pointer to MPT adapter structure
2274 * @pdev: Pointer to (struct pci_dev) structure
2276 * Search for PCI bus/dev_function which matches
2277 * PCI bus/dev_function (+/-1) for newly discovered 929,
2278 * 929X, 1030 or 1035.
2280 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2281 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2283 static void
2284 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2286 struct pci_dev *peer=NULL;
2287 unsigned int slot = PCI_SLOT(pdev->devfn);
2288 unsigned int func = PCI_FUNC(pdev->devfn);
2289 MPT_ADAPTER *ioc_srch;
2291 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2292 " searching for devfn match on %x or %x\n",
2293 ioc->name, pci_name(pdev), pdev->bus->number,
2294 pdev->devfn, func-1, func+1));
2296 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2297 if (!peer) {
2298 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2299 if (!peer)
2300 return;
2303 list_for_each_entry(ioc_srch, &ioc_list, list) {
2304 struct pci_dev *_pcidev = ioc_srch->pcidev;
2305 if (_pcidev == peer) {
2306 /* Paranoia checks */
2307 if (ioc->alt_ioc != NULL) {
2308 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2309 ioc->name, ioc->alt_ioc->name);
2310 break;
2311 } else if (ioc_srch->alt_ioc != NULL) {
2312 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2313 ioc_srch->name, ioc_srch->alt_ioc->name);
2314 break;
2316 dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
2317 ioc->name, ioc_srch->name));
2318 ioc_srch->alt_ioc = ioc;
2319 ioc->alt_ioc = ioc_srch;
2322 pci_dev_put(peer);
2325 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2327 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2328 * @ioc: Pointer to MPT adapter structure
2330 static void
2331 mpt_adapter_disable(MPT_ADAPTER *ioc)
2333 int sz;
2334 int ret;
2336 if (ioc->cached_fw != NULL) {
2337 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2338 "adapter\n", __FUNCTION__, ioc->name));
2339 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2340 ioc->cached_fw, CAN_SLEEP)) < 0) {
2341 printk(MYIOC_s_WARN_FMT
2342 ": firmware downloadboot failure (%d)!\n",
2343 ioc->name, ret);
2347 /* Disable adapter interrupts! */
2348 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2349 ioc->active = 0;
2350 /* Clear any lingering interrupt */
2351 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2353 if (ioc->alloc != NULL) {
2354 sz = ioc->alloc_sz;
2355 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2356 ioc->name, ioc->alloc, ioc->alloc_sz));
2357 pci_free_consistent(ioc->pcidev, sz,
2358 ioc->alloc, ioc->alloc_dma);
2359 ioc->reply_frames = NULL;
2360 ioc->req_frames = NULL;
2361 ioc->alloc = NULL;
2362 ioc->alloc_total -= sz;
2365 if (ioc->sense_buf_pool != NULL) {
2366 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2367 pci_free_consistent(ioc->pcidev, sz,
2368 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2369 ioc->sense_buf_pool = NULL;
2370 ioc->alloc_total -= sz;
2373 if (ioc->events != NULL){
2374 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2375 kfree(ioc->events);
2376 ioc->events = NULL;
2377 ioc->alloc_total -= sz;
2380 mpt_free_fw_memory(ioc);
2382 kfree(ioc->spi_data.nvram);
2383 mpt_inactive_raid_list_free(ioc);
2384 kfree(ioc->raid_data.pIocPg2);
2385 kfree(ioc->raid_data.pIocPg3);
2386 ioc->spi_data.nvram = NULL;
2387 ioc->raid_data.pIocPg3 = NULL;
2389 if (ioc->spi_data.pIocPg4 != NULL) {
2390 sz = ioc->spi_data.IocPg4Sz;
2391 pci_free_consistent(ioc->pcidev, sz,
2392 ioc->spi_data.pIocPg4,
2393 ioc->spi_data.IocPg4_dma);
2394 ioc->spi_data.pIocPg4 = NULL;
2395 ioc->alloc_total -= sz;
2398 if (ioc->ReqToChain != NULL) {
2399 kfree(ioc->ReqToChain);
2400 kfree(ioc->RequestNB);
2401 ioc->ReqToChain = NULL;
2404 kfree(ioc->ChainToChain);
2405 ioc->ChainToChain = NULL;
2407 if (ioc->HostPageBuffer != NULL) {
2408 if((ret = mpt_host_page_access_control(ioc,
2409 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2410 printk(MYIOC_s_ERR_FMT
2411 "host page buffers free failed (%d)!\n",
2412 ioc->name, ret);
2414 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n",
2415 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2416 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2417 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2418 ioc->HostPageBuffer = NULL;
2419 ioc->HostPageBuffer_sz = 0;
2420 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2424 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2426 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2427 * @ioc: Pointer to MPT adapter structure
2429 * This routine unregisters h/w resources and frees all alloc'd memory
2430 * associated with a MPT adapter structure.
2432 static void
2433 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2435 int sz_first, sz_last;
2437 if (ioc == NULL)
2438 return;
2440 sz_first = ioc->alloc_total;
2442 mpt_adapter_disable(ioc);
2444 if (ioc->pci_irq != -1) {
2445 free_irq(ioc->pci_irq, ioc);
2446 if (mpt_msi_enable)
2447 pci_disable_msi(ioc->pcidev);
2448 ioc->pci_irq = -1;
2451 if (ioc->memmap != NULL) {
2452 iounmap(ioc->memmap);
2453 ioc->memmap = NULL;
2456 pci_disable_device(ioc->pcidev);
2457 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2459 #if defined(CONFIG_MTRR) && 0
2460 if (ioc->mtrr_reg > 0) {
2461 mtrr_del(ioc->mtrr_reg, 0, 0);
2462 dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2464 #endif
2466 /* Zap the adapter lookup ptr! */
2467 list_del(&ioc->list);
2469 sz_last = ioc->alloc_total;
2470 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2471 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2473 if (ioc->alt_ioc)
2474 ioc->alt_ioc->alt_ioc = NULL;
2476 kfree(ioc);
2479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2481 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2482 * @ioc: Pointer to MPT adapter structure
2484 static void
2485 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2487 int i = 0;
2489 printk(KERN_INFO "%s: ", ioc->name);
2490 if (ioc->prod_name)
2491 printk("%s: ", ioc->prod_name);
2492 printk("Capabilities={");
2494 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2495 printk("Initiator");
2496 i++;
2499 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2500 printk("%sTarget", i ? "," : "");
2501 i++;
2504 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2505 printk("%sLAN", i ? "," : "");
2506 i++;
2509 #if 0
2511 * This would probably evoke more questions than it's worth
2513 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2514 printk("%sLogBusAddr", i ? "," : "");
2515 i++;
2517 #endif
2519 printk("}\n");
2522 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2524 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2525 * @ioc: Pointer to MPT_ADAPTER structure
2526 * @force: Force hard KickStart of IOC
2527 * @sleepFlag: Specifies whether the process can sleep
2529 * Returns:
2530 * 1 - DIAG reset and READY
2531 * 0 - READY initially OR soft reset and READY
2532 * -1 - Any failure on KickStart
2533 * -2 - Msg Unit Reset Failed
2534 * -3 - IO Unit Reset Failed
2535 * -4 - IOC owned by a PEER
2537 static int
2538 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2540 u32 ioc_state;
2541 int statefault = 0;
2542 int cntdn;
2543 int hard_reset_done = 0;
2544 int r;
2545 int ii;
2546 int whoinit;
2548 /* Get current [raw] IOC state */
2549 ioc_state = mpt_GetIocState(ioc, 0);
2550 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2553 * Check to see if IOC got left/stuck in doorbell handshake
2554 * grip of death. If so, hard reset the IOC.
2556 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2557 statefault = 1;
2558 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2559 ioc->name);
2562 /* Is it already READY? */
2563 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2564 return 0;
2567 * Check to see if IOC is in FAULT state.
2569 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2570 statefault = 2;
2571 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2572 ioc->name);
2573 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2574 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2578 * Hmmm... Did it get left operational?
2580 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2581 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2582 ioc->name));
2584 /* Check WhoInit.
2585 * If PCI Peer, exit.
2586 * Else, if no fault conditions are present, issue a MessageUnitReset
2587 * Else, fall through to KickStart case
2589 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2590 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2591 "whoinit 0x%x statefault %d force %d\n",
2592 ioc->name, whoinit, statefault, force));
2593 if (whoinit == MPI_WHOINIT_PCI_PEER)
2594 return -4;
2595 else {
2596 if ((statefault == 0 ) && (force == 0)) {
2597 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2598 return 0;
2600 statefault = 3;
2604 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2605 if (hard_reset_done < 0)
2606 return -1;
2609 * Loop here waiting for IOC to come READY.
2611 ii = 0;
2612 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2614 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2615 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2617 * BIOS or previous driver load left IOC in OP state.
2618 * Reset messaging FIFOs.
2620 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2621 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2622 return -2;
2624 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2626 * Something is wrong. Try to get IOC back
2627 * to a known state.
2629 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2630 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2631 return -3;
2635 ii++; cntdn--;
2636 if (!cntdn) {
2637 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2638 ioc->name, (int)((ii+5)/HZ));
2639 return -ETIME;
2642 if (sleepFlag == CAN_SLEEP) {
2643 msleep(1);
2644 } else {
2645 mdelay (1); /* 1 msec delay */
2650 if (statefault < 3) {
2651 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2652 ioc->name,
2653 statefault==1 ? "stuck handshake" : "IOC FAULT");
2656 return hard_reset_done;
2659 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2661 * mpt_GetIocState - Get the current state of a MPT adapter.
2662 * @ioc: Pointer to MPT_ADAPTER structure
2663 * @cooked: Request raw or cooked IOC state
2665 * Returns all IOC Doorbell register bits if cooked==0, else just the
2666 * Doorbell bits in MPI_IOC_STATE_MASK.
2669 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2671 u32 s, sc;
2673 /* Get! */
2674 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2675 sc = s & MPI_IOC_STATE_MASK;
2677 /* Save! */
2678 ioc->last_state = sc;
2680 return cooked ? sc : s;
2683 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2685 * GetIocFacts - Send IOCFacts request to MPT adapter.
2686 * @ioc: Pointer to MPT_ADAPTER structure
2687 * @sleepFlag: Specifies whether the process can sleep
2688 * @reason: If recovery, only update facts.
2690 * Returns 0 for success, non-zero for failure.
2692 static int
2693 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2695 IOCFacts_t get_facts;
2696 IOCFactsReply_t *facts;
2697 int r;
2698 int req_sz;
2699 int reply_sz;
2700 int sz;
2701 u32 status, vv;
2702 u8 shiftFactor=1;
2704 /* IOC *must* NOT be in RESET state! */
2705 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2706 printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
2707 ioc->name, ioc->last_state );
2708 return -44;
2711 facts = &ioc->facts;
2713 /* Destination (reply area)... */
2714 reply_sz = sizeof(*facts);
2715 memset(facts, 0, reply_sz);
2717 /* Request area (get_facts on the stack right now!) */
2718 req_sz = sizeof(get_facts);
2719 memset(&get_facts, 0, req_sz);
2721 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2722 /* Assert: All other get_facts fields are zero! */
2724 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2725 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2726 ioc->name, req_sz, reply_sz));
2728 /* No non-zero fields in the get_facts request are greater than
2729 * 1 byte in size, so we can just fire it off as is.
2731 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2732 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2733 if (r != 0)
2734 return r;
2737 * Now byte swap (GRRR) the necessary fields before any further
2738 * inspection of reply contents.
2740 * But need to do some sanity checks on MsgLength (byte) field
2741 * to make sure we don't zero IOC's req_sz!
2743 /* Did we get a valid reply? */
2744 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2745 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2747 * If not been here, done that, save off first WhoInit value
2749 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2750 ioc->FirstWhoInit = facts->WhoInit;
2753 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2754 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2755 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2756 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2757 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2758 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2759 /* CHECKME! IOCStatus, IOCLogInfo */
2761 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2762 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2765 * FC f/w version changed between 1.1 and 1.2
2766 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2767 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2769 if (facts->MsgVersion < 0x0102) {
2771 * Handle old FC f/w style, convert to new...
2773 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2774 facts->FWVersion.Word =
2775 ((oldv<<12) & 0xFF000000) |
2776 ((oldv<<8) & 0x000FFF00);
2777 } else
2778 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2780 facts->ProductID = le16_to_cpu(facts->ProductID);
2781 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2782 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
2783 ioc->ir_firmware = 1;
2784 facts->CurrentHostMfaHighAddr =
2785 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2786 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2787 facts->CurrentSenseBufferHighAddr =
2788 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2789 facts->CurReplyFrameSize =
2790 le16_to_cpu(facts->CurReplyFrameSize);
2791 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2794 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2795 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2796 * to 14 in MPI-1.01.0x.
2798 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2799 facts->MsgVersion > 0x0100) {
2800 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2803 sz = facts->FWImageSize;
2804 if ( sz & 0x01 )
2805 sz += 1;
2806 if ( sz & 0x02 )
2807 sz += 2;
2808 facts->FWImageSize = sz;
2810 if (!facts->RequestFrameSize) {
2811 /* Something is wrong! */
2812 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2813 ioc->name);
2814 return -55;
2817 r = sz = facts->BlockSize;
2818 vv = ((63 / (sz * 4)) + 1) & 0x03;
2819 ioc->NB_for_64_byte_frame = vv;
2820 while ( sz )
2822 shiftFactor++;
2823 sz = sz >> 1;
2825 ioc->NBShiftFactor = shiftFactor;
2826 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2827 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2828 ioc->name, vv, shiftFactor, r));
2830 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2832 * Set values for this IOC's request & reply frame sizes,
2833 * and request & reply queue depths...
2835 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2836 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2837 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2838 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2840 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
2841 ioc->name, ioc->reply_sz, ioc->reply_depth));
2842 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
2843 ioc->name, ioc->req_sz, ioc->req_depth));
2845 /* Get port facts! */
2846 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2847 return r;
2849 } else {
2850 printk(MYIOC_s_ERR_FMT
2851 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2852 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2853 RequestFrameSize)/sizeof(u32)));
2854 return -66;
2857 return 0;
2860 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2862 * GetPortFacts - Send PortFacts request to MPT adapter.
2863 * @ioc: Pointer to MPT_ADAPTER structure
2864 * @portnum: Port number
2865 * @sleepFlag: Specifies whether the process can sleep
2867 * Returns 0 for success, non-zero for failure.
2869 static int
2870 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2872 PortFacts_t get_pfacts;
2873 PortFactsReply_t *pfacts;
2874 int ii;
2875 int req_sz;
2876 int reply_sz;
2877 int max_id;
2879 /* IOC *must* NOT be in RESET state! */
2880 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2881 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
2882 ioc->name, ioc->last_state );
2883 return -4;
2886 pfacts = &ioc->pfacts[portnum];
2888 /* Destination (reply area)... */
2889 reply_sz = sizeof(*pfacts);
2890 memset(pfacts, 0, reply_sz);
2892 /* Request area (get_pfacts on the stack right now!) */
2893 req_sz = sizeof(get_pfacts);
2894 memset(&get_pfacts, 0, req_sz);
2896 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2897 get_pfacts.PortNumber = portnum;
2898 /* Assert: All other get_pfacts fields are zero! */
2900 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
2901 ioc->name, portnum));
2903 /* No non-zero fields in the get_pfacts request are greater than
2904 * 1 byte in size, so we can just fire it off as is.
2906 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2907 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2908 if (ii != 0)
2909 return ii;
2911 /* Did we get a valid reply? */
2913 /* Now byte swap the necessary fields in the response. */
2914 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2915 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2916 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2917 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2918 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2919 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2920 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2921 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2922 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2924 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
2925 pfacts->MaxDevices;
2926 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
2927 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
2930 * Place all the devices on channels
2932 * (for debuging)
2934 if (mpt_channel_mapping) {
2935 ioc->devices_per_bus = 1;
2936 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
2939 return 0;
2942 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2944 * SendIocInit - Send IOCInit request to MPT adapter.
2945 * @ioc: Pointer to MPT_ADAPTER structure
2946 * @sleepFlag: Specifies whether the process can sleep
2948 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2950 * Returns 0 for success, non-zero for failure.
2952 static int
2953 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2955 IOCInit_t ioc_init;
2956 MPIDefaultReply_t init_reply;
2957 u32 state;
2958 int r;
2959 int count;
2960 int cntdn;
2962 memset(&ioc_init, 0, sizeof(ioc_init));
2963 memset(&init_reply, 0, sizeof(init_reply));
2965 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2966 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2968 /* If we are in a recovery mode and we uploaded the FW image,
2969 * then this pointer is not NULL. Skip the upload a second time.
2970 * Set this flag if cached_fw set for either IOC.
2972 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2973 ioc->upload_fw = 1;
2974 else
2975 ioc->upload_fw = 0;
2976 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
2977 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2979 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
2980 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
2981 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
2982 ioc->name, ioc->facts.MsgVersion));
2983 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2984 // set MsgVersion and HeaderVersion host driver was built with
2985 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2986 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2988 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2989 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2990 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2991 return -99;
2993 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2995 if (sizeof(dma_addr_t) == sizeof(u64)) {
2996 /* Save the upper 32-bits of the request
2997 * (reply) and sense buffers.
2999 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3000 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3001 } else {
3002 /* Force 32-bit addressing */
3003 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3004 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3007 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3008 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3009 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3010 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3012 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3013 ioc->name, &ioc_init));
3015 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3016 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3017 if (r != 0) {
3018 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3019 return r;
3022 /* No need to byte swap the multibyte fields in the reply
3023 * since we don't even look at its contents.
3026 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3027 ioc->name, &ioc_init));
3029 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3030 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3031 return r;
3034 /* YIKES! SUPER IMPORTANT!!!
3035 * Poll IocState until _OPERATIONAL while IOC is doing
3036 * LoopInit and TargetDiscovery!
3038 count = 0;
3039 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3040 state = mpt_GetIocState(ioc, 1);
3041 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3042 if (sleepFlag == CAN_SLEEP) {
3043 msleep(1);
3044 } else {
3045 mdelay(1);
3048 if (!cntdn) {
3049 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3050 ioc->name, (int)((count+5)/HZ));
3051 return -9;
3054 state = mpt_GetIocState(ioc, 1);
3055 count++;
3057 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3058 ioc->name, count));
3060 ioc->aen_event_read_flag=0;
3061 return r;
3064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3066 * SendPortEnable - Send PortEnable request to MPT adapter port.
3067 * @ioc: Pointer to MPT_ADAPTER structure
3068 * @portnum: Port number to enable
3069 * @sleepFlag: Specifies whether the process can sleep
3071 * Send PortEnable to bring IOC to OPERATIONAL state.
3073 * Returns 0 for success, non-zero for failure.
3075 static int
3076 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3078 PortEnable_t port_enable;
3079 MPIDefaultReply_t reply_buf;
3080 int rc;
3081 int req_sz;
3082 int reply_sz;
3084 /* Destination... */
3085 reply_sz = sizeof(MPIDefaultReply_t);
3086 memset(&reply_buf, 0, reply_sz);
3088 req_sz = sizeof(PortEnable_t);
3089 memset(&port_enable, 0, req_sz);
3091 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3092 port_enable.PortNumber = portnum;
3093 /* port_enable.ChainOffset = 0; */
3094 /* port_enable.MsgFlags = 0; */
3095 /* port_enable.MsgContext = 0; */
3097 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3098 ioc->name, portnum, &port_enable));
3100 /* RAID FW may take a long time to enable
3102 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3103 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3104 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3105 300 /*seconds*/, sleepFlag);
3106 } else {
3107 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3108 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3109 30 /*seconds*/, sleepFlag);
3111 return rc;
3115 * mpt_alloc_fw_memory - allocate firmware memory
3116 * @ioc: Pointer to MPT_ADAPTER structure
3117 * @size: total FW bytes
3119 * If memory has already been allocated, the same (cached) value
3120 * is returned.
3122 * Return 0 if successfull, or non-zero for failure
3125 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3127 int rc;
3129 if (ioc->cached_fw) {
3130 rc = 0; /* use already allocated memory */
3131 goto out;
3133 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3134 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3135 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3136 rc = 0;
3137 goto out;
3139 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3140 if (!ioc->cached_fw) {
3141 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3142 ioc->name);
3143 rc = -1;
3144 } else {
3145 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3146 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3147 ioc->alloc_total += size;
3148 rc = 0;
3150 out:
3151 return rc;
3155 * mpt_free_fw_memory - free firmware memory
3156 * @ioc: Pointer to MPT_ADAPTER structure
3158 * If alt_img is NULL, delete from ioc structure.
3159 * Else, delete a secondary image in same format.
3161 void
3162 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3164 int sz;
3166 if (!ioc->cached_fw)
3167 return;
3169 sz = ioc->facts.FWImageSize;
3170 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3171 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3172 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3173 ioc->alloc_total -= sz;
3174 ioc->cached_fw = NULL;
3177 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3179 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3180 * @ioc: Pointer to MPT_ADAPTER structure
3181 * @sleepFlag: Specifies whether the process can sleep
3183 * Returns 0 for success, >0 for handshake failure
3184 * <0 for fw upload failure.
3186 * Remark: If bound IOC and a successful FWUpload was performed
3187 * on the bound IOC, the second image is discarded
3188 * and memory is free'd. Both channels must upload to prevent
3189 * IOC from running in degraded mode.
3191 static int
3192 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3194 u8 reply[sizeof(FWUploadReply_t)];
3195 FWUpload_t *prequest;
3196 FWUploadReply_t *preply;
3197 FWUploadTCSGE_t *ptcsge;
3198 int sgeoffset;
3199 u32 flagsLength;
3200 int ii, sz, reply_sz;
3201 int cmdStatus;
3203 /* If the image size is 0, we are done.
3205 if ((sz = ioc->facts.FWImageSize) == 0)
3206 return 0;
3208 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3209 return -ENOMEM;
3211 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3212 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3214 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3215 kzalloc(ioc->req_sz, GFP_KERNEL);
3216 if (!prequest) {
3217 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3218 "while allocating memory \n", ioc->name));
3219 mpt_free_fw_memory(ioc);
3220 return -ENOMEM;
3223 preply = (FWUploadReply_t *)&reply;
3225 reply_sz = sizeof(reply);
3226 memset(preply, 0, reply_sz);
3228 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3229 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3231 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3232 ptcsge->DetailsLength = 12;
3233 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3234 ptcsge->ImageSize = cpu_to_le32(sz);
3235 ptcsge++;
3237 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
3239 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3240 mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3242 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
3243 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3244 ioc->name, prequest, sgeoffset));
3245 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3247 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
3248 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3250 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
3252 cmdStatus = -EFAULT;
3253 if (ii == 0) {
3254 /* Handshake transfer was complete and successful.
3255 * Check the Reply Frame.
3257 int status, transfer_sz;
3258 status = le16_to_cpu(preply->IOCStatus);
3259 if (status == MPI_IOCSTATUS_SUCCESS) {
3260 transfer_sz = le32_to_cpu(preply->ActualImageSize);
3261 if (transfer_sz == sz)
3262 cmdStatus = 0;
3265 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3266 ioc->name, cmdStatus));
3269 if (cmdStatus) {
3271 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
3272 ioc->name));
3273 mpt_free_fw_memory(ioc);
3275 kfree(prequest);
3277 return cmdStatus;
3280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3282 * mpt_downloadboot - DownloadBoot code
3283 * @ioc: Pointer to MPT_ADAPTER structure
3284 * @pFwHeader: Pointer to firmware header info
3285 * @sleepFlag: Specifies whether the process can sleep
3287 * FwDownloadBoot requires Programmed IO access.
3289 * Returns 0 for success
3290 * -1 FW Image size is 0
3291 * -2 No valid cached_fw Pointer
3292 * <0 for fw upload failure.
3294 static int
3295 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3297 MpiExtImageHeader_t *pExtImage;
3298 u32 fwSize;
3299 u32 diag0val;
3300 int count;
3301 u32 *ptrFw;
3302 u32 diagRwData;
3303 u32 nextImage;
3304 u32 load_addr;
3305 u32 ioc_state=0;
3307 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3308 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3310 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3311 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3312 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3313 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3314 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3315 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3317 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3319 /* wait 1 msec */
3320 if (sleepFlag == CAN_SLEEP) {
3321 msleep(1);
3322 } else {
3323 mdelay (1);
3326 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3327 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3329 for (count = 0; count < 30; count ++) {
3330 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3331 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3332 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3333 ioc->name, count));
3334 break;
3336 /* wait .1 sec */
3337 if (sleepFlag == CAN_SLEEP) {
3338 msleep (100);
3339 } else {
3340 mdelay (100);
3344 if ( count == 30 ) {
3345 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3346 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3347 ioc->name, diag0val));
3348 return -3;
3351 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3352 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3353 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3354 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3355 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3356 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3358 /* Set the DiagRwEn and Disable ARM bits */
3359 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3361 fwSize = (pFwHeader->ImageSize + 3)/4;
3362 ptrFw = (u32 *) pFwHeader;
3364 /* Write the LoadStartAddress to the DiagRw Address Register
3365 * using Programmed IO
3367 if (ioc->errata_flag_1064)
3368 pci_enable_io_access(ioc->pcidev);
3370 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3371 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3372 ioc->name, pFwHeader->LoadStartAddress));
3374 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3375 ioc->name, fwSize*4, ptrFw));
3376 while (fwSize--) {
3377 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3380 nextImage = pFwHeader->NextImageHeaderOffset;
3381 while (nextImage) {
3382 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3384 load_addr = pExtImage->LoadStartAddress;
3386 fwSize = (pExtImage->ImageSize + 3) >> 2;
3387 ptrFw = (u32 *)pExtImage;
3389 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3390 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3391 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3393 while (fwSize--) {
3394 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3396 nextImage = pExtImage->NextImageHeaderOffset;
3399 /* Write the IopResetVectorRegAddr */
3400 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3401 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3403 /* Write the IopResetVectorValue */
3404 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3405 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3407 /* Clear the internal flash bad bit - autoincrementing register,
3408 * so must do two writes.
3410 if (ioc->bus_type == SPI) {
3412 * 1030 and 1035 H/W errata, workaround to access
3413 * the ClearFlashBadSignatureBit
3415 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3416 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3417 diagRwData |= 0x40000000;
3418 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3419 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3421 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3422 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3423 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3424 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3426 /* wait 1 msec */
3427 if (sleepFlag == CAN_SLEEP) {
3428 msleep (1);
3429 } else {
3430 mdelay (1);
3434 if (ioc->errata_flag_1064)
3435 pci_disable_io_access(ioc->pcidev);
3437 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3438 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3439 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3440 ioc->name, diag0val));
3441 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3442 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3443 ioc->name, diag0val));
3444 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3446 /* Write 0xFF to reset the sequencer */
3447 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3449 if (ioc->bus_type == SAS) {
3450 ioc_state = mpt_GetIocState(ioc, 0);
3451 if ( (GetIocFacts(ioc, sleepFlag,
3452 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3453 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3454 ioc->name, ioc_state));
3455 return -EFAULT;
3459 for (count=0; count<HZ*20; count++) {
3460 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3461 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3462 "downloadboot successful! (count=%d) IocState=%x\n",
3463 ioc->name, count, ioc_state));
3464 if (ioc->bus_type == SAS) {
3465 return 0;
3467 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3468 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3469 "downloadboot: SendIocInit failed\n",
3470 ioc->name));
3471 return -EFAULT;
3473 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3474 "downloadboot: SendIocInit successful\n",
3475 ioc->name));
3476 return 0;
3478 if (sleepFlag == CAN_SLEEP) {
3479 msleep (10);
3480 } else {
3481 mdelay (10);
3484 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3485 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3486 return -EFAULT;
3489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3491 * KickStart - Perform hard reset of MPT adapter.
3492 * @ioc: Pointer to MPT_ADAPTER structure
3493 * @force: Force hard reset
3494 * @sleepFlag: Specifies whether the process can sleep
3496 * This routine places MPT adapter in diagnostic mode via the
3497 * WriteSequence register, and then performs a hard reset of adapter
3498 * via the Diagnostic register.
3500 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3501 * or NO_SLEEP (interrupt thread, use mdelay)
3502 * force - 1 if doorbell active, board fault state
3503 * board operational, IOC_RECOVERY or
3504 * IOC_BRINGUP and there is an alt_ioc.
3505 * 0 else
3507 * Returns:
3508 * 1 - hard reset, READY
3509 * 0 - no reset due to History bit, READY
3510 * -1 - no reset due to History bit but not READY
3511 * OR reset but failed to come READY
3512 * -2 - no reset, could not enter DIAG mode
3513 * -3 - reset but bad FW bit
3515 static int
3516 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3518 int hard_reset_done = 0;
3519 u32 ioc_state=0;
3520 int cnt,cntdn;
3522 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3523 if (ioc->bus_type == SPI) {
3524 /* Always issue a Msg Unit Reset first. This will clear some
3525 * SCSI bus hang conditions.
3527 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3529 if (sleepFlag == CAN_SLEEP) {
3530 msleep (1000);
3531 } else {
3532 mdelay (1000);
3536 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3537 if (hard_reset_done < 0)
3538 return hard_reset_done;
3540 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3541 ioc->name));
3543 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3544 for (cnt=0; cnt<cntdn; cnt++) {
3545 ioc_state = mpt_GetIocState(ioc, 1);
3546 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3547 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3548 ioc->name, cnt));
3549 return hard_reset_done;
3551 if (sleepFlag == CAN_SLEEP) {
3552 msleep (10);
3553 } else {
3554 mdelay (10);
3558 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3559 ioc->name, mpt_GetIocState(ioc, 0)));
3560 return -1;
3563 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3565 * mpt_diag_reset - Perform hard reset of the adapter.
3566 * @ioc: Pointer to MPT_ADAPTER structure
3567 * @ignore: Set if to honor and clear to ignore
3568 * the reset history bit
3569 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3570 * else set to NO_SLEEP (use mdelay instead)
3572 * This routine places the adapter in diagnostic mode via the
3573 * WriteSequence register and then performs a hard reset of adapter
3574 * via the Diagnostic register. Adapter should be in ready state
3575 * upon successful completion.
3577 * Returns: 1 hard reset successful
3578 * 0 no reset performed because reset history bit set
3579 * -2 enabling diagnostic mode failed
3580 * -3 diagnostic reset failed
3582 static int
3583 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3585 u32 diag0val;
3586 u32 doorbell;
3587 int hard_reset_done = 0;
3588 int count = 0;
3589 u32 diag1val = 0;
3590 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3592 /* Clear any existing interrupts */
3593 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3595 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3596 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3597 "address=%p\n", ioc->name, __FUNCTION__,
3598 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3599 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3600 if (sleepFlag == CAN_SLEEP)
3601 msleep(1);
3602 else
3603 mdelay(1);
3605 for (count = 0; count < 60; count ++) {
3606 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3607 doorbell &= MPI_IOC_STATE_MASK;
3609 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3610 "looking for READY STATE: doorbell=%x"
3611 " count=%d\n",
3612 ioc->name, doorbell, count));
3613 if (doorbell == MPI_IOC_STATE_READY) {
3614 return 1;
3617 /* wait 1 sec */
3618 if (sleepFlag == CAN_SLEEP)
3619 msleep(1000);
3620 else
3621 mdelay(1000);
3623 return -1;
3626 /* Use "Diagnostic reset" method! (only thing available!) */
3627 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3629 if (ioc->debug_level & MPT_DEBUG) {
3630 if (ioc->alt_ioc)
3631 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3632 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3633 ioc->name, diag0val, diag1val));
3636 /* Do the reset if we are told to ignore the reset history
3637 * or if the reset history is 0
3639 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3640 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3641 /* Write magic sequence to WriteSequence register
3642 * Loop until in diagnostic mode
3644 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3645 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3646 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3647 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3648 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3649 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3651 /* wait 100 msec */
3652 if (sleepFlag == CAN_SLEEP) {
3653 msleep (100);
3654 } else {
3655 mdelay (100);
3658 count++;
3659 if (count > 20) {
3660 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3661 ioc->name, diag0val);
3662 return -2;
3666 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3668 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3669 ioc->name, diag0val));
3672 if (ioc->debug_level & MPT_DEBUG) {
3673 if (ioc->alt_ioc)
3674 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3675 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3676 ioc->name, diag0val, diag1val));
3679 * Disable the ARM (Bug fix)
3682 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3683 mdelay(1);
3686 * Now hit the reset bit in the Diagnostic register
3687 * (THE BIG HAMMER!) (Clears DRWE bit).
3689 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3690 hard_reset_done = 1;
3691 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3692 ioc->name));
3695 * Call each currently registered protocol IOC reset handler
3696 * with pre-reset indication.
3697 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3698 * MptResetHandlers[] registered yet.
3701 u8 cb_idx;
3702 int r = 0;
3704 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3705 if (MptResetHandlers[cb_idx]) {
3706 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3707 "Calling IOC pre_reset handler #%d\n",
3708 ioc->name, cb_idx));
3709 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
3710 if (ioc->alt_ioc) {
3711 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3712 "Calling alt-%s pre_reset handler #%d\n",
3713 ioc->name, ioc->alt_ioc->name, cb_idx));
3714 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3718 /* FIXME? Examine results here? */
3721 if (ioc->cached_fw)
3722 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3723 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3724 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3725 else
3726 cached_fw = NULL;
3727 if (cached_fw) {
3728 /* If the DownloadBoot operation fails, the
3729 * IOC will be left unusable. This is a fatal error
3730 * case. _diag_reset will return < 0
3732 for (count = 0; count < 30; count ++) {
3733 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3734 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3735 break;
3738 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3739 ioc->name, diag0val, count));
3740 /* wait 1 sec */
3741 if (sleepFlag == CAN_SLEEP) {
3742 msleep (1000);
3743 } else {
3744 mdelay (1000);
3747 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3748 printk(MYIOC_s_WARN_FMT
3749 "firmware downloadboot failure (%d)!\n", ioc->name, count);
3752 } else {
3753 /* Wait for FW to reload and for board
3754 * to go to the READY state.
3755 * Maximum wait is 60 seconds.
3756 * If fail, no error will check again
3757 * with calling program.
3759 for (count = 0; count < 60; count ++) {
3760 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3761 doorbell &= MPI_IOC_STATE_MASK;
3763 if (doorbell == MPI_IOC_STATE_READY) {
3764 break;
3767 /* wait 1 sec */
3768 if (sleepFlag == CAN_SLEEP) {
3769 msleep (1000);
3770 } else {
3771 mdelay (1000);
3777 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3778 if (ioc->debug_level & MPT_DEBUG) {
3779 if (ioc->alt_ioc)
3780 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3781 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3782 ioc->name, diag0val, diag1val));
3785 /* Clear RESET_HISTORY bit! Place board in the
3786 * diagnostic mode to update the diag register.
3788 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3789 count = 0;
3790 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3791 /* Write magic sequence to WriteSequence register
3792 * Loop until in diagnostic mode
3794 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3795 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3796 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3797 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3798 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3799 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3801 /* wait 100 msec */
3802 if (sleepFlag == CAN_SLEEP) {
3803 msleep (100);
3804 } else {
3805 mdelay (100);
3808 count++;
3809 if (count > 20) {
3810 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3811 ioc->name, diag0val);
3812 break;
3814 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3816 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3817 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3818 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3819 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3820 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3821 ioc->name);
3824 /* Disable Diagnostic Mode
3826 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3828 /* Check FW reload status flags.
3830 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3831 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3832 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3833 ioc->name, diag0val);
3834 return -3;
3837 if (ioc->debug_level & MPT_DEBUG) {
3838 if (ioc->alt_ioc)
3839 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3840 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3841 ioc->name, diag0val, diag1val));
3845 * Reset flag that says we've enabled event notification
3847 ioc->facts.EventState = 0;
3849 if (ioc->alt_ioc)
3850 ioc->alt_ioc->facts.EventState = 0;
3852 return hard_reset_done;
3855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3857 * SendIocReset - Send IOCReset request to MPT adapter.
3858 * @ioc: Pointer to MPT_ADAPTER structure
3859 * @reset_type: reset type, expected values are
3860 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3861 * @sleepFlag: Specifies whether the process can sleep
3863 * Send IOCReset request to the MPT adapter.
3865 * Returns 0 for success, non-zero for failure.
3867 static int
3868 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3870 int r;
3871 u32 state;
3872 int cntdn, count;
3874 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
3875 ioc->name, reset_type));
3876 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3877 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3878 return r;
3880 /* FW ACK'd request, wait for READY state
3882 count = 0;
3883 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3885 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3886 cntdn--;
3887 count++;
3888 if (!cntdn) {
3889 if (sleepFlag != CAN_SLEEP)
3890 count *= 10;
3892 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
3893 ioc->name, (int)((count+5)/HZ));
3894 return -ETIME;
3897 if (sleepFlag == CAN_SLEEP) {
3898 msleep(1);
3899 } else {
3900 mdelay (1); /* 1 msec delay */
3904 /* TODO!
3905 * Cleanup all event stuff for this IOC; re-issue EventNotification
3906 * request if needed.
3908 if (ioc->facts.Function)
3909 ioc->facts.EventState = 0;
3911 return 0;
3914 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3916 * initChainBuffers - Allocate memory for and initialize chain buffers
3917 * @ioc: Pointer to MPT_ADAPTER structure
3919 * Allocates memory for and initializes chain buffers,
3920 * chain buffer control arrays and spinlock.
3922 static int
3923 initChainBuffers(MPT_ADAPTER *ioc)
3925 u8 *mem;
3926 int sz, ii, num_chain;
3927 int scale, num_sge, numSGE;
3929 /* ReqToChain size must equal the req_depth
3930 * index = req_idx
3932 if (ioc->ReqToChain == NULL) {
3933 sz = ioc->req_depth * sizeof(int);
3934 mem = kmalloc(sz, GFP_ATOMIC);
3935 if (mem == NULL)
3936 return -1;
3938 ioc->ReqToChain = (int *) mem;
3939 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
3940 ioc->name, mem, sz));
3941 mem = kmalloc(sz, GFP_ATOMIC);
3942 if (mem == NULL)
3943 return -1;
3945 ioc->RequestNB = (int *) mem;
3946 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
3947 ioc->name, mem, sz));
3949 for (ii = 0; ii < ioc->req_depth; ii++) {
3950 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3953 /* ChainToChain size must equal the total number
3954 * of chain buffers to be allocated.
3955 * index = chain_idx
3957 * Calculate the number of chain buffers needed(plus 1) per I/O
3958 * then multiply the maximum number of simultaneous cmds
3960 * num_sge = num sge in request frame + last chain buffer
3961 * scale = num sge per chain buffer if no chain element
3963 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3964 if (sizeof(dma_addr_t) == sizeof(u64))
3965 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3966 else
3967 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3969 if (sizeof(dma_addr_t) == sizeof(u64)) {
3970 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3971 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3972 } else {
3973 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3974 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3976 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
3977 ioc->name, num_sge, numSGE));
3979 if ( numSGE > MPT_SCSI_SG_DEPTH )
3980 numSGE = MPT_SCSI_SG_DEPTH;
3982 num_chain = 1;
3983 while (numSGE - num_sge > 0) {
3984 num_chain++;
3985 num_sge += (scale - 1);
3987 num_chain++;
3989 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
3990 ioc->name, numSGE, num_sge, num_chain));
3992 if (ioc->bus_type == SPI)
3993 num_chain *= MPT_SCSI_CAN_QUEUE;
3994 else
3995 num_chain *= MPT_FC_CAN_QUEUE;
3997 ioc->num_chain = num_chain;
3999 sz = num_chain * sizeof(int);
4000 if (ioc->ChainToChain == NULL) {
4001 mem = kmalloc(sz, GFP_ATOMIC);
4002 if (mem == NULL)
4003 return -1;
4005 ioc->ChainToChain = (int *) mem;
4006 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4007 ioc->name, mem, sz));
4008 } else {
4009 mem = (u8 *) ioc->ChainToChain;
4011 memset(mem, 0xFF, sz);
4012 return num_chain;
4015 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4017 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4018 * @ioc: Pointer to MPT_ADAPTER structure
4020 * This routine allocates memory for the MPT reply and request frame
4021 * pools (if necessary), and primes the IOC reply FIFO with
4022 * reply frames.
4024 * Returns 0 for success, non-zero for failure.
4026 static int
4027 PrimeIocFifos(MPT_ADAPTER *ioc)
4029 MPT_FRAME_HDR *mf;
4030 unsigned long flags;
4031 dma_addr_t alloc_dma;
4032 u8 *mem;
4033 int i, reply_sz, sz, total_size, num_chain;
4035 /* Prime reply FIFO... */
4037 if (ioc->reply_frames == NULL) {
4038 if ( (num_chain = initChainBuffers(ioc)) < 0)
4039 return -1;
4041 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4042 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4043 ioc->name, ioc->reply_sz, ioc->reply_depth));
4044 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4045 ioc->name, reply_sz, reply_sz));
4047 sz = (ioc->req_sz * ioc->req_depth);
4048 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4049 ioc->name, ioc->req_sz, ioc->req_depth));
4050 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4051 ioc->name, sz, sz));
4052 total_size += sz;
4054 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4055 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4056 ioc->name, ioc->req_sz, num_chain));
4057 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4058 ioc->name, sz, sz, num_chain));
4060 total_size += sz;
4061 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4062 if (mem == NULL) {
4063 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4064 ioc->name);
4065 goto out_fail;
4068 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4069 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4071 memset(mem, 0, total_size);
4072 ioc->alloc_total += total_size;
4073 ioc->alloc = mem;
4074 ioc->alloc_dma = alloc_dma;
4075 ioc->alloc_sz = total_size;
4076 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4077 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4079 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4080 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4082 alloc_dma += reply_sz;
4083 mem += reply_sz;
4085 /* Request FIFO - WE manage this! */
4087 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4088 ioc->req_frames_dma = alloc_dma;
4090 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4091 ioc->name, mem, (void *)(ulong)alloc_dma));
4093 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4095 #if defined(CONFIG_MTRR) && 0
4097 * Enable Write Combining MTRR for IOC's memory region.
4098 * (at least as much as we can; "size and base must be
4099 * multiples of 4 kiB"
4101 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4103 MTRR_TYPE_WRCOMB, 1);
4104 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4105 ioc->name, ioc->req_frames_dma, sz));
4106 #endif
4108 for (i = 0; i < ioc->req_depth; i++) {
4109 alloc_dma += ioc->req_sz;
4110 mem += ioc->req_sz;
4113 ioc->ChainBuffer = mem;
4114 ioc->ChainBufferDMA = alloc_dma;
4116 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4117 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4119 /* Initialize the free chain Q.
4122 INIT_LIST_HEAD(&ioc->FreeChainQ);
4124 /* Post the chain buffers to the FreeChainQ.
4126 mem = (u8 *)ioc->ChainBuffer;
4127 for (i=0; i < num_chain; i++) {
4128 mf = (MPT_FRAME_HDR *) mem;
4129 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4130 mem += ioc->req_sz;
4133 /* Initialize Request frames linked list
4135 alloc_dma = ioc->req_frames_dma;
4136 mem = (u8 *) ioc->req_frames;
4138 spin_lock_irqsave(&ioc->FreeQlock, flags);
4139 INIT_LIST_HEAD(&ioc->FreeQ);
4140 for (i = 0; i < ioc->req_depth; i++) {
4141 mf = (MPT_FRAME_HDR *) mem;
4143 /* Queue REQUESTs *internally*! */
4144 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4146 mem += ioc->req_sz;
4148 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4150 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4151 ioc->sense_buf_pool =
4152 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4153 if (ioc->sense_buf_pool == NULL) {
4154 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4155 ioc->name);
4156 goto out_fail;
4159 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4160 ioc->alloc_total += sz;
4161 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4162 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4166 /* Post Reply frames to FIFO
4168 alloc_dma = ioc->alloc_dma;
4169 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4170 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4172 for (i = 0; i < ioc->reply_depth; i++) {
4173 /* Write each address to the IOC! */
4174 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4175 alloc_dma += ioc->reply_sz;
4178 return 0;
4180 out_fail:
4181 if (ioc->alloc != NULL) {
4182 sz = ioc->alloc_sz;
4183 pci_free_consistent(ioc->pcidev,
4185 ioc->alloc, ioc->alloc_dma);
4186 ioc->reply_frames = NULL;
4187 ioc->req_frames = NULL;
4188 ioc->alloc_total -= sz;
4190 if (ioc->sense_buf_pool != NULL) {
4191 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4192 pci_free_consistent(ioc->pcidev,
4194 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4195 ioc->sense_buf_pool = NULL;
4197 return -1;
4200 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4202 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4203 * from IOC via doorbell handshake method.
4204 * @ioc: Pointer to MPT_ADAPTER structure
4205 * @reqBytes: Size of the request in bytes
4206 * @req: Pointer to MPT request frame
4207 * @replyBytes: Expected size of the reply in bytes
4208 * @u16reply: Pointer to area where reply should be written
4209 * @maxwait: Max wait time for a reply (in seconds)
4210 * @sleepFlag: Specifies whether the process can sleep
4212 * NOTES: It is the callers responsibility to byte-swap fields in the
4213 * request which are greater than 1 byte in size. It is also the
4214 * callers responsibility to byte-swap response fields which are
4215 * greater than 1 byte in size.
4217 * Returns 0 for success, non-zero for failure.
4219 static int
4220 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4221 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4223 MPIDefaultReply_t *mptReply;
4224 int failcnt = 0;
4225 int t;
4228 * Get ready to cache a handshake reply
4230 ioc->hs_reply_idx = 0;
4231 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4232 mptReply->MsgLength = 0;
4235 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4236 * then tell IOC that we want to handshake a request of N words.
4237 * (WRITE u32val to Doorbell reg).
4239 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4240 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4241 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4242 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4245 * Wait for IOC's doorbell handshake int
4247 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4248 failcnt++;
4250 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4251 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4253 /* Read doorbell and check for active bit */
4254 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4255 return -1;
4258 * Clear doorbell int (WRITE 0 to IntStatus reg),
4259 * then wait for IOC to ACKnowledge that it's ready for
4260 * our handshake request.
4262 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4263 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4264 failcnt++;
4266 if (!failcnt) {
4267 int ii;
4268 u8 *req_as_bytes = (u8 *) req;
4271 * Stuff request words via doorbell handshake,
4272 * with ACK from IOC for each.
4274 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4275 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4276 (req_as_bytes[(ii*4) + 1] << 8) |
4277 (req_as_bytes[(ii*4) + 2] << 16) |
4278 (req_as_bytes[(ii*4) + 3] << 24));
4280 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4281 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4282 failcnt++;
4285 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4286 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4288 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4289 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4292 * Wait for completion of doorbell handshake reply from the IOC
4294 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4295 failcnt++;
4297 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4298 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4301 * Copy out the cached reply...
4303 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4304 u16reply[ii] = ioc->hs_reply[ii];
4305 } else {
4306 return -99;
4309 return -failcnt;
4312 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4314 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4315 * @ioc: Pointer to MPT_ADAPTER structure
4316 * @howlong: How long to wait (in seconds)
4317 * @sleepFlag: Specifies whether the process can sleep
4319 * This routine waits (up to ~2 seconds max) for IOC doorbell
4320 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4321 * bit in its IntStatus register being clear.
4323 * Returns a negative value on failure, else wait loop count.
4325 static int
4326 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4328 int cntdn;
4329 int count = 0;
4330 u32 intstat=0;
4332 cntdn = 1000 * howlong;
4334 if (sleepFlag == CAN_SLEEP) {
4335 while (--cntdn) {
4336 msleep (1);
4337 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4338 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4339 break;
4340 count++;
4342 } else {
4343 while (--cntdn) {
4344 udelay (1000);
4345 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4346 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4347 break;
4348 count++;
4352 if (cntdn) {
4353 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4354 ioc->name, count));
4355 return count;
4358 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4359 ioc->name, count, intstat);
4360 return -1;
4363 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4365 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4366 * @ioc: Pointer to MPT_ADAPTER structure
4367 * @howlong: How long to wait (in seconds)
4368 * @sleepFlag: Specifies whether the process can sleep
4370 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4371 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4373 * Returns a negative value on failure, else wait loop count.
4375 static int
4376 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4378 int cntdn;
4379 int count = 0;
4380 u32 intstat=0;
4382 cntdn = 1000 * howlong;
4383 if (sleepFlag == CAN_SLEEP) {
4384 while (--cntdn) {
4385 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4386 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4387 break;
4388 msleep(1);
4389 count++;
4391 } else {
4392 while (--cntdn) {
4393 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4394 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4395 break;
4396 udelay (1000);
4397 count++;
4401 if (cntdn) {
4402 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4403 ioc->name, count, howlong));
4404 return count;
4407 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4408 ioc->name, count, intstat);
4409 return -1;
4412 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4414 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4415 * @ioc: Pointer to MPT_ADAPTER structure
4416 * @howlong: How long to wait (in seconds)
4417 * @sleepFlag: Specifies whether the process can sleep
4419 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4420 * Reply is cached to IOC private area large enough to hold a maximum
4421 * of 128 bytes of reply data.
4423 * Returns a negative value on failure, else size of reply in WORDS.
4425 static int
4426 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4428 int u16cnt = 0;
4429 int failcnt = 0;
4430 int t;
4431 u16 *hs_reply = ioc->hs_reply;
4432 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4433 u16 hword;
4435 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4438 * Get first two u16's so we can look at IOC's intended reply MsgLength
4440 u16cnt=0;
4441 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4442 failcnt++;
4443 } else {
4444 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4445 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4446 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4447 failcnt++;
4448 else {
4449 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4450 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4454 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4455 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4456 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4459 * If no error (and IOC said MsgLength is > 0), piece together
4460 * reply 16 bits at a time.
4462 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4463 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4464 failcnt++;
4465 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4466 /* don't overflow our IOC hs_reply[] buffer! */
4467 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4468 hs_reply[u16cnt] = hword;
4469 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4472 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4473 failcnt++;
4474 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4476 if (failcnt) {
4477 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4478 ioc->name);
4479 return -failcnt;
4481 #if 0
4482 else if (u16cnt != (2 * mptReply->MsgLength)) {
4483 return -101;
4485 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4486 return -102;
4488 #endif
4490 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4491 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4493 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4494 ioc->name, t, u16cnt/2));
4495 return u16cnt/2;
4498 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4500 * GetLanConfigPages - Fetch LANConfig pages.
4501 * @ioc: Pointer to MPT_ADAPTER structure
4503 * Return: 0 for success
4504 * -ENOMEM if no memory available
4505 * -EPERM if not allowed due to ISR context
4506 * -EAGAIN if no msg frames currently available
4507 * -EFAULT for non-successful reply or no reply (timeout)
4509 static int
4510 GetLanConfigPages(MPT_ADAPTER *ioc)
4512 ConfigPageHeader_t hdr;
4513 CONFIGPARMS cfg;
4514 LANPage0_t *ppage0_alloc;
4515 dma_addr_t page0_dma;
4516 LANPage1_t *ppage1_alloc;
4517 dma_addr_t page1_dma;
4518 int rc = 0;
4519 int data_sz;
4520 int copy_sz;
4522 /* Get LAN Page 0 header */
4523 hdr.PageVersion = 0;
4524 hdr.PageLength = 0;
4525 hdr.PageNumber = 0;
4526 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4527 cfg.cfghdr.hdr = &hdr;
4528 cfg.physAddr = -1;
4529 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4530 cfg.dir = 0;
4531 cfg.pageAddr = 0;
4532 cfg.timeout = 0;
4534 if ((rc = mpt_config(ioc, &cfg)) != 0)
4535 return rc;
4537 if (hdr.PageLength > 0) {
4538 data_sz = hdr.PageLength * 4;
4539 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4540 rc = -ENOMEM;
4541 if (ppage0_alloc) {
4542 memset((u8 *)ppage0_alloc, 0, data_sz);
4543 cfg.physAddr = page0_dma;
4544 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4546 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4547 /* save the data */
4548 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4549 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4553 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4555 /* FIXME!
4556 * Normalize endianness of structure data,
4557 * by byte-swapping all > 1 byte fields!
4562 if (rc)
4563 return rc;
4566 /* Get LAN Page 1 header */
4567 hdr.PageVersion = 0;
4568 hdr.PageLength = 0;
4569 hdr.PageNumber = 1;
4570 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4571 cfg.cfghdr.hdr = &hdr;
4572 cfg.physAddr = -1;
4573 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4574 cfg.dir = 0;
4575 cfg.pageAddr = 0;
4577 if ((rc = mpt_config(ioc, &cfg)) != 0)
4578 return rc;
4580 if (hdr.PageLength == 0)
4581 return 0;
4583 data_sz = hdr.PageLength * 4;
4584 rc = -ENOMEM;
4585 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4586 if (ppage1_alloc) {
4587 memset((u8 *)ppage1_alloc, 0, data_sz);
4588 cfg.physAddr = page1_dma;
4589 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4591 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4592 /* save the data */
4593 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4594 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4597 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4599 /* FIXME!
4600 * Normalize endianness of structure data,
4601 * by byte-swapping all > 1 byte fields!
4606 return rc;
4609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4611 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4612 * @ioc: Pointer to MPT_ADAPTER structure
4613 * @persist_opcode: see below
4615 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4616 * devices not currently present.
4617 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4619 * NOTE: Don't use not this function during interrupt time.
4621 * Returns 0 for success, non-zero error
4624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4626 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4628 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4629 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4630 MPT_FRAME_HDR *mf = NULL;
4631 MPIHeader_t *mpi_hdr;
4634 /* insure garbage is not sent to fw */
4635 switch(persist_opcode) {
4637 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4638 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4639 break;
4641 default:
4642 return -1;
4643 break;
4646 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4648 /* Get a MF for this command.
4650 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4651 printk("%s: no msg frames!\n",__FUNCTION__);
4652 return -1;
4655 mpi_hdr = (MPIHeader_t *) mf;
4656 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4657 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4658 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4659 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4660 sasIoUnitCntrReq->Operation = persist_opcode;
4662 init_timer(&ioc->persist_timer);
4663 ioc->persist_timer.data = (unsigned long) ioc;
4664 ioc->persist_timer.function = mpt_timer_expired;
4665 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4666 ioc->persist_wait_done=0;
4667 add_timer(&ioc->persist_timer);
4668 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4669 wait_event(mpt_waitq, ioc->persist_wait_done);
4671 sasIoUnitCntrReply =
4672 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4673 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4674 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4675 __FUNCTION__,
4676 sasIoUnitCntrReply->IOCStatus,
4677 sasIoUnitCntrReply->IOCLogInfo);
4678 return -1;
4681 printk("%s: success\n",__FUNCTION__);
4682 return 0;
4685 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4687 static void
4688 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4689 MpiEventDataRaid_t * pRaidEventData)
4691 int volume;
4692 int reason;
4693 int disk;
4694 int status;
4695 int flags;
4696 int state;
4698 volume = pRaidEventData->VolumeID;
4699 reason = pRaidEventData->ReasonCode;
4700 disk = pRaidEventData->PhysDiskNum;
4701 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4702 flags = (status >> 0) & 0xff;
4703 state = (status >> 8) & 0xff;
4705 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4706 return;
4709 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4710 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4711 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4712 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4713 ioc->name, disk, volume);
4714 } else {
4715 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4716 ioc->name, volume);
4719 switch(reason) {
4720 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4721 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4722 ioc->name);
4723 break;
4725 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4727 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4728 ioc->name);
4729 break;
4731 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4732 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4733 ioc->name);
4734 break;
4736 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4737 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4738 ioc->name,
4739 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4740 ? "optimal"
4741 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4742 ? "degraded"
4743 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4744 ? "failed"
4745 : "state unknown",
4746 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4747 ? ", enabled" : "",
4748 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4749 ? ", quiesced" : "",
4750 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4751 ? ", resync in progress" : "" );
4752 break;
4754 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4755 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4756 ioc->name, disk);
4757 break;
4759 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4760 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4761 ioc->name);
4762 break;
4764 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4765 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4766 ioc->name);
4767 break;
4769 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4770 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4771 ioc->name);
4772 break;
4774 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4775 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4776 ioc->name,
4777 state == MPI_PHYSDISK0_STATUS_ONLINE
4778 ? "online"
4779 : state == MPI_PHYSDISK0_STATUS_MISSING
4780 ? "missing"
4781 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4782 ? "not compatible"
4783 : state == MPI_PHYSDISK0_STATUS_FAILED
4784 ? "failed"
4785 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4786 ? "initializing"
4787 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4788 ? "offline requested"
4789 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4790 ? "failed requested"
4791 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4792 ? "offline"
4793 : "state unknown",
4794 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4795 ? ", out of sync" : "",
4796 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4797 ? ", quiesced" : "" );
4798 break;
4800 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4801 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4802 ioc->name, disk);
4803 break;
4805 case MPI_EVENT_RAID_RC_SMART_DATA:
4806 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4807 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4808 break;
4810 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4811 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4812 ioc->name, disk);
4813 break;
4817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4819 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4820 * @ioc: Pointer to MPT_ADAPTER structure
4822 * Returns: 0 for success
4823 * -ENOMEM if no memory available
4824 * -EPERM if not allowed due to ISR context
4825 * -EAGAIN if no msg frames currently available
4826 * -EFAULT for non-successful reply or no reply (timeout)
4828 static int
4829 GetIoUnitPage2(MPT_ADAPTER *ioc)
4831 ConfigPageHeader_t hdr;
4832 CONFIGPARMS cfg;
4833 IOUnitPage2_t *ppage_alloc;
4834 dma_addr_t page_dma;
4835 int data_sz;
4836 int rc;
4838 /* Get the page header */
4839 hdr.PageVersion = 0;
4840 hdr.PageLength = 0;
4841 hdr.PageNumber = 2;
4842 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4843 cfg.cfghdr.hdr = &hdr;
4844 cfg.physAddr = -1;
4845 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4846 cfg.dir = 0;
4847 cfg.pageAddr = 0;
4848 cfg.timeout = 0;
4850 if ((rc = mpt_config(ioc, &cfg)) != 0)
4851 return rc;
4853 if (hdr.PageLength == 0)
4854 return 0;
4856 /* Read the config page */
4857 data_sz = hdr.PageLength * 4;
4858 rc = -ENOMEM;
4859 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4860 if (ppage_alloc) {
4861 memset((u8 *)ppage_alloc, 0, data_sz);
4862 cfg.physAddr = page_dma;
4863 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4865 /* If Good, save data */
4866 if ((rc = mpt_config(ioc, &cfg)) == 0)
4867 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4869 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4872 return rc;
4875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4877 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4878 * @ioc: Pointer to a Adapter Strucutre
4879 * @portnum: IOC port number
4881 * Return: -EFAULT if read of config page header fails
4882 * or if no nvram
4883 * If read of SCSI Port Page 0 fails,
4884 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4885 * Adapter settings: async, narrow
4886 * Return 1
4887 * If read of SCSI Port Page 2 fails,
4888 * Adapter settings valid
4889 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4890 * Return 1
4891 * Else
4892 * Both valid
4893 * Return 0
4894 * CHECK - what type of locking mechanisms should be used????
4896 static int
4897 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4899 u8 *pbuf;
4900 dma_addr_t buf_dma;
4901 CONFIGPARMS cfg;
4902 ConfigPageHeader_t header;
4903 int ii;
4904 int data, rc = 0;
4906 /* Allocate memory
4908 if (!ioc->spi_data.nvram) {
4909 int sz;
4910 u8 *mem;
4911 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4912 mem = kmalloc(sz, GFP_ATOMIC);
4913 if (mem == NULL)
4914 return -EFAULT;
4916 ioc->spi_data.nvram = (int *) mem;
4918 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4919 ioc->name, ioc->spi_data.nvram, sz));
4922 /* Invalidate NVRAM information
4924 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4925 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4928 /* Read SPP0 header, allocate memory, then read page.
4930 header.PageVersion = 0;
4931 header.PageLength = 0;
4932 header.PageNumber = 0;
4933 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4934 cfg.cfghdr.hdr = &header;
4935 cfg.physAddr = -1;
4936 cfg.pageAddr = portnum;
4937 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4938 cfg.dir = 0;
4939 cfg.timeout = 0; /* use default */
4940 if (mpt_config(ioc, &cfg) != 0)
4941 return -EFAULT;
4943 if (header.PageLength > 0) {
4944 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4945 if (pbuf) {
4946 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4947 cfg.physAddr = buf_dma;
4948 if (mpt_config(ioc, &cfg) != 0) {
4949 ioc->spi_data.maxBusWidth = MPT_NARROW;
4950 ioc->spi_data.maxSyncOffset = 0;
4951 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4952 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4953 rc = 1;
4954 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4955 "Unable to read PortPage0 minSyncFactor=%x\n",
4956 ioc->name, ioc->spi_data.minSyncFactor));
4957 } else {
4958 /* Save the Port Page 0 data
4960 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4961 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4962 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4964 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4965 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4966 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4967 "noQas due to Capabilities=%x\n",
4968 ioc->name, pPP0->Capabilities));
4970 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4971 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4972 if (data) {
4973 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4974 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4975 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4976 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4977 "PortPage0 minSyncFactor=%x\n",
4978 ioc->name, ioc->spi_data.minSyncFactor));
4979 } else {
4980 ioc->spi_data.maxSyncOffset = 0;
4981 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4984 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4986 /* Update the minSyncFactor based on bus type.
4988 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4989 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4991 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4992 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4993 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4994 "HVD or SE detected, minSyncFactor=%x\n",
4995 ioc->name, ioc->spi_data.minSyncFactor));
4999 if (pbuf) {
5000 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5005 /* SCSI Port Page 2 - Read the header then the page.
5007 header.PageVersion = 0;
5008 header.PageLength = 0;
5009 header.PageNumber = 2;
5010 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5011 cfg.cfghdr.hdr = &header;
5012 cfg.physAddr = -1;
5013 cfg.pageAddr = portnum;
5014 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5015 cfg.dir = 0;
5016 if (mpt_config(ioc, &cfg) != 0)
5017 return -EFAULT;
5019 if (header.PageLength > 0) {
5020 /* Allocate memory and read SCSI Port Page 2
5022 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5023 if (pbuf) {
5024 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5025 cfg.physAddr = buf_dma;
5026 if (mpt_config(ioc, &cfg) != 0) {
5027 /* Nvram data is left with INVALID mark
5029 rc = 1;
5030 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5032 /* This is an ATTO adapter, read Page2 accordingly
5034 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5035 ATTODeviceInfo_t *pdevice = NULL;
5036 u16 ATTOFlags;
5038 /* Save the Port Page 2 data
5039 * (reformat into a 32bit quantity)
5041 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5042 pdevice = &pPP2->DeviceSettings[ii];
5043 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5044 data = 0;
5046 /* Translate ATTO device flags to LSI format
5048 if (ATTOFlags & ATTOFLAG_DISC)
5049 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5050 if (ATTOFlags & ATTOFLAG_ID_ENB)
5051 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5052 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5053 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5054 if (ATTOFlags & ATTOFLAG_TAGGED)
5055 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5056 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5057 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5059 data = (data << 16) | (pdevice->Period << 8) | 10;
5060 ioc->spi_data.nvram[ii] = data;
5062 } else {
5063 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5064 MpiDeviceInfo_t *pdevice = NULL;
5067 * Save "Set to Avoid SCSI Bus Resets" flag
5069 ioc->spi_data.bus_reset =
5070 (le32_to_cpu(pPP2->PortFlags) &
5071 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5072 0 : 1 ;
5074 /* Save the Port Page 2 data
5075 * (reformat into a 32bit quantity)
5077 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5078 ioc->spi_data.PortFlags = data;
5079 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5080 pdevice = &pPP2->DeviceSettings[ii];
5081 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5082 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5083 ioc->spi_data.nvram[ii] = data;
5087 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5091 /* Update Adapter limits with those from NVRAM
5092 * Comment: Don't need to do this. Target performance
5093 * parameters will never exceed the adapters limits.
5096 return rc;
5099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5101 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5102 * @ioc: Pointer to a Adapter Strucutre
5103 * @portnum: IOC port number
5105 * Return: -EFAULT if read of config page header fails
5106 * or 0 if success.
5108 static int
5109 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5111 CONFIGPARMS cfg;
5112 ConfigPageHeader_t header;
5114 /* Read the SCSI Device Page 1 header
5116 header.PageVersion = 0;
5117 header.PageLength = 0;
5118 header.PageNumber = 1;
5119 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5120 cfg.cfghdr.hdr = &header;
5121 cfg.physAddr = -1;
5122 cfg.pageAddr = portnum;
5123 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5124 cfg.dir = 0;
5125 cfg.timeout = 0;
5126 if (mpt_config(ioc, &cfg) != 0)
5127 return -EFAULT;
5129 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5130 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5132 header.PageVersion = 0;
5133 header.PageLength = 0;
5134 header.PageNumber = 0;
5135 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5136 if (mpt_config(ioc, &cfg) != 0)
5137 return -EFAULT;
5139 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5140 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5142 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5143 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5145 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5146 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5147 return 0;
5151 * mpt_inactive_raid_list_free - This clears this link list.
5152 * @ioc : pointer to per adapter structure
5154 static void
5155 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5157 struct inactive_raid_component_info *component_info, *pNext;
5159 if (list_empty(&ioc->raid_data.inactive_list))
5160 return;
5162 down(&ioc->raid_data.inactive_list_mutex);
5163 list_for_each_entry_safe(component_info, pNext,
5164 &ioc->raid_data.inactive_list, list) {
5165 list_del(&component_info->list);
5166 kfree(component_info);
5168 up(&ioc->raid_data.inactive_list_mutex);
5172 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5174 * @ioc : pointer to per adapter structure
5175 * @channel : volume channel
5176 * @id : volume target id
5178 static void
5179 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5181 CONFIGPARMS cfg;
5182 ConfigPageHeader_t hdr;
5183 dma_addr_t dma_handle;
5184 pRaidVolumePage0_t buffer = NULL;
5185 int i;
5186 RaidPhysDiskPage0_t phys_disk;
5187 struct inactive_raid_component_info *component_info;
5188 int handle_inactive_volumes;
5190 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5191 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5192 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5193 cfg.pageAddr = (channel << 8) + id;
5194 cfg.cfghdr.hdr = &hdr;
5195 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5197 if (mpt_config(ioc, &cfg) != 0)
5198 goto out;
5200 if (!hdr.PageLength)
5201 goto out;
5203 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5204 &dma_handle);
5206 if (!buffer)
5207 goto out;
5209 cfg.physAddr = dma_handle;
5210 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5212 if (mpt_config(ioc, &cfg) != 0)
5213 goto out;
5215 if (!buffer->NumPhysDisks)
5216 goto out;
5218 handle_inactive_volumes =
5219 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5220 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5221 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5222 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5224 if (!handle_inactive_volumes)
5225 goto out;
5227 down(&ioc->raid_data.inactive_list_mutex);
5228 for (i = 0; i < buffer->NumPhysDisks; i++) {
5229 if(mpt_raid_phys_disk_pg0(ioc,
5230 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5231 continue;
5233 if ((component_info = kmalloc(sizeof (*component_info),
5234 GFP_KERNEL)) == NULL)
5235 continue;
5237 component_info->volumeID = id;
5238 component_info->volumeBus = channel;
5239 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5240 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5241 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5242 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5244 list_add_tail(&component_info->list,
5245 &ioc->raid_data.inactive_list);
5247 up(&ioc->raid_data.inactive_list_mutex);
5249 out:
5250 if (buffer)
5251 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5252 dma_handle);
5256 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5257 * @ioc: Pointer to a Adapter Structure
5258 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5259 * @phys_disk: requested payload data returned
5261 * Return:
5262 * 0 on success
5263 * -EFAULT if read of config page header fails or data pointer not NULL
5264 * -ENOMEM if pci_alloc failed
5267 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
5269 CONFIGPARMS cfg;
5270 ConfigPageHeader_t hdr;
5271 dma_addr_t dma_handle;
5272 pRaidPhysDiskPage0_t buffer = NULL;
5273 int rc;
5275 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5276 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5278 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5279 cfg.cfghdr.hdr = &hdr;
5280 cfg.physAddr = -1;
5281 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5283 if (mpt_config(ioc, &cfg) != 0) {
5284 rc = -EFAULT;
5285 goto out;
5288 if (!hdr.PageLength) {
5289 rc = -EFAULT;
5290 goto out;
5293 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5294 &dma_handle);
5296 if (!buffer) {
5297 rc = -ENOMEM;
5298 goto out;
5301 cfg.physAddr = dma_handle;
5302 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5303 cfg.pageAddr = phys_disk_num;
5305 if (mpt_config(ioc, &cfg) != 0) {
5306 rc = -EFAULT;
5307 goto out;
5310 rc = 0;
5311 memcpy(phys_disk, buffer, sizeof(*buffer));
5312 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5314 out:
5316 if (buffer)
5317 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5318 dma_handle);
5320 return rc;
5324 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5325 * @ioc: Pointer to a Adapter Strucutre
5326 * @portnum: IOC port number
5328 * Return:
5329 * 0 on success
5330 * -EFAULT if read of config page header fails or data pointer not NULL
5331 * -ENOMEM if pci_alloc failed
5334 mpt_findImVolumes(MPT_ADAPTER *ioc)
5336 IOCPage2_t *pIoc2;
5337 u8 *mem;
5338 dma_addr_t ioc2_dma;
5339 CONFIGPARMS cfg;
5340 ConfigPageHeader_t header;
5341 int rc = 0;
5342 int iocpage2sz;
5343 int i;
5345 if (!ioc->ir_firmware)
5346 return 0;
5348 /* Free the old page
5350 kfree(ioc->raid_data.pIocPg2);
5351 ioc->raid_data.pIocPg2 = NULL;
5352 mpt_inactive_raid_list_free(ioc);
5354 /* Read IOCP2 header then the page.
5356 header.PageVersion = 0;
5357 header.PageLength = 0;
5358 header.PageNumber = 2;
5359 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5360 cfg.cfghdr.hdr = &header;
5361 cfg.physAddr = -1;
5362 cfg.pageAddr = 0;
5363 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5364 cfg.dir = 0;
5365 cfg.timeout = 0;
5366 if (mpt_config(ioc, &cfg) != 0)
5367 return -EFAULT;
5369 if (header.PageLength == 0)
5370 return -EFAULT;
5372 iocpage2sz = header.PageLength * 4;
5373 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5374 if (!pIoc2)
5375 return -ENOMEM;
5377 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5378 cfg.physAddr = ioc2_dma;
5379 if (mpt_config(ioc, &cfg) != 0)
5380 goto out;
5382 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5383 if (!mem)
5384 goto out;
5386 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5387 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5389 mpt_read_ioc_pg_3(ioc);
5391 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5392 mpt_inactive_raid_volumes(ioc,
5393 pIoc2->RaidVolume[i].VolumeBus,
5394 pIoc2->RaidVolume[i].VolumeID);
5396 out:
5397 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5399 return rc;
5402 static int
5403 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5405 IOCPage3_t *pIoc3;
5406 u8 *mem;
5407 CONFIGPARMS cfg;
5408 ConfigPageHeader_t header;
5409 dma_addr_t ioc3_dma;
5410 int iocpage3sz = 0;
5412 /* Free the old page
5414 kfree(ioc->raid_data.pIocPg3);
5415 ioc->raid_data.pIocPg3 = NULL;
5417 /* There is at least one physical disk.
5418 * Read and save IOC Page 3
5420 header.PageVersion = 0;
5421 header.PageLength = 0;
5422 header.PageNumber = 3;
5423 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5424 cfg.cfghdr.hdr = &header;
5425 cfg.physAddr = -1;
5426 cfg.pageAddr = 0;
5427 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5428 cfg.dir = 0;
5429 cfg.timeout = 0;
5430 if (mpt_config(ioc, &cfg) != 0)
5431 return 0;
5433 if (header.PageLength == 0)
5434 return 0;
5436 /* Read Header good, alloc memory
5438 iocpage3sz = header.PageLength * 4;
5439 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5440 if (!pIoc3)
5441 return 0;
5443 /* Read the Page and save the data
5444 * into malloc'd memory.
5446 cfg.physAddr = ioc3_dma;
5447 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5448 if (mpt_config(ioc, &cfg) == 0) {
5449 mem = kmalloc(iocpage3sz, GFP_KERNEL);
5450 if (mem) {
5451 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5452 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5456 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5458 return 0;
5461 static void
5462 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5464 IOCPage4_t *pIoc4;
5465 CONFIGPARMS cfg;
5466 ConfigPageHeader_t header;
5467 dma_addr_t ioc4_dma;
5468 int iocpage4sz;
5470 /* Read and save IOC Page 4
5472 header.PageVersion = 0;
5473 header.PageLength = 0;
5474 header.PageNumber = 4;
5475 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5476 cfg.cfghdr.hdr = &header;
5477 cfg.physAddr = -1;
5478 cfg.pageAddr = 0;
5479 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5480 cfg.dir = 0;
5481 cfg.timeout = 0;
5482 if (mpt_config(ioc, &cfg) != 0)
5483 return;
5485 if (header.PageLength == 0)
5486 return;
5488 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5489 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5490 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5491 if (!pIoc4)
5492 return;
5493 ioc->alloc_total += iocpage4sz;
5494 } else {
5495 ioc4_dma = ioc->spi_data.IocPg4_dma;
5496 iocpage4sz = ioc->spi_data.IocPg4Sz;
5499 /* Read the Page into dma memory.
5501 cfg.physAddr = ioc4_dma;
5502 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5503 if (mpt_config(ioc, &cfg) == 0) {
5504 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5505 ioc->spi_data.IocPg4_dma = ioc4_dma;
5506 ioc->spi_data.IocPg4Sz = iocpage4sz;
5507 } else {
5508 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5509 ioc->spi_data.pIocPg4 = NULL;
5510 ioc->alloc_total -= iocpage4sz;
5514 static void
5515 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5517 IOCPage1_t *pIoc1;
5518 CONFIGPARMS cfg;
5519 ConfigPageHeader_t header;
5520 dma_addr_t ioc1_dma;
5521 int iocpage1sz = 0;
5522 u32 tmp;
5524 /* Check the Coalescing Timeout in IOC Page 1
5526 header.PageVersion = 0;
5527 header.PageLength = 0;
5528 header.PageNumber = 1;
5529 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5530 cfg.cfghdr.hdr = &header;
5531 cfg.physAddr = -1;
5532 cfg.pageAddr = 0;
5533 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5534 cfg.dir = 0;
5535 cfg.timeout = 0;
5536 if (mpt_config(ioc, &cfg) != 0)
5537 return;
5539 if (header.PageLength == 0)
5540 return;
5542 /* Read Header good, alloc memory
5544 iocpage1sz = header.PageLength * 4;
5545 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5546 if (!pIoc1)
5547 return;
5549 /* Read the Page and check coalescing timeout
5551 cfg.physAddr = ioc1_dma;
5552 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5553 if (mpt_config(ioc, &cfg) == 0) {
5555 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5556 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5557 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5559 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
5560 ioc->name, tmp));
5562 if (tmp > MPT_COALESCING_TIMEOUT) {
5563 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5565 /* Write NVRAM and current
5567 cfg.dir = 1;
5568 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5569 if (mpt_config(ioc, &cfg) == 0) {
5570 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
5571 ioc->name, MPT_COALESCING_TIMEOUT));
5573 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5574 if (mpt_config(ioc, &cfg) == 0) {
5575 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5576 "Reset NVRAM Coalescing Timeout to = %d\n",
5577 ioc->name, MPT_COALESCING_TIMEOUT));
5578 } else {
5579 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5580 "Reset NVRAM Coalescing Timeout Failed\n",
5581 ioc->name));
5584 } else {
5585 dprintk(ioc, printk(MYIOC_s_WARN_FMT
5586 "Reset of Current Coalescing Timeout Failed!\n",
5587 ioc->name));
5591 } else {
5592 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5596 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5598 return;
5601 static void
5602 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
5604 CONFIGPARMS cfg;
5605 ConfigPageHeader_t hdr;
5606 dma_addr_t buf_dma;
5607 ManufacturingPage0_t *pbuf = NULL;
5609 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5610 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5612 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5613 cfg.cfghdr.hdr = &hdr;
5614 cfg.physAddr = -1;
5615 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5616 cfg.timeout = 10;
5618 if (mpt_config(ioc, &cfg) != 0)
5619 goto out;
5621 if (!cfg.cfghdr.hdr->PageLength)
5622 goto out;
5624 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5625 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
5626 if (!pbuf)
5627 goto out;
5629 cfg.physAddr = buf_dma;
5631 if (mpt_config(ioc, &cfg) != 0)
5632 goto out;
5634 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
5635 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
5636 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
5638 out:
5640 if (pbuf)
5641 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
5644 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5646 * SendEventNotification - Send EventNotification (on or off) request to adapter
5647 * @ioc: Pointer to MPT_ADAPTER structure
5648 * @EvSwitch: Event switch flags
5650 static int
5651 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5653 EventNotification_t *evnp;
5655 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5656 if (evnp == NULL) {
5657 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5658 ioc->name));
5659 return 0;
5661 memset(evnp, 0, sizeof(*evnp));
5663 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5665 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5666 evnp->ChainOffset = 0;
5667 evnp->MsgFlags = 0;
5668 evnp->Switch = EvSwitch;
5670 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5672 return 0;
5675 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5677 * SendEventAck - Send EventAck request to MPT adapter.
5678 * @ioc: Pointer to MPT_ADAPTER structure
5679 * @evnp: Pointer to original EventNotification request
5681 static int
5682 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5684 EventAck_t *pAck;
5686 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5687 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5688 ioc->name,__FUNCTION__));
5689 return -1;
5692 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
5694 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5695 pAck->ChainOffset = 0;
5696 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5697 pAck->MsgFlags = 0;
5698 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5699 pAck->Event = evnp->Event;
5700 pAck->EventContext = evnp->EventContext;
5702 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5704 return 0;
5707 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5709 * mpt_config - Generic function to issue config message
5710 * @ioc: Pointer to an adapter structure
5711 * @pCfg: Pointer to a configuration structure. Struct contains
5712 * action, page address, direction, physical address
5713 * and pointer to a configuration page header
5714 * Page header is updated.
5716 * Returns 0 for success
5717 * -EPERM if not allowed due to ISR context
5718 * -EAGAIN if no msg frames currently available
5719 * -EFAULT for non-successful reply or no reply (timeout)
5722 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5724 Config_t *pReq;
5725 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5726 MPT_FRAME_HDR *mf;
5727 unsigned long flags;
5728 int ii, rc;
5729 int flagsLength;
5730 int in_isr;
5732 /* Prevent calling wait_event() (below), if caller happens
5733 * to be in ISR context, because that is fatal!
5735 in_isr = in_interrupt();
5736 if (in_isr) {
5737 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5738 ioc->name));
5739 return -EPERM;
5742 /* Get and Populate a free Frame
5744 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5745 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5746 ioc->name));
5747 return -EAGAIN;
5749 pReq = (Config_t *)mf;
5750 pReq->Action = pCfg->action;
5751 pReq->Reserved = 0;
5752 pReq->ChainOffset = 0;
5753 pReq->Function = MPI_FUNCTION_CONFIG;
5755 /* Assume page type is not extended and clear "reserved" fields. */
5756 pReq->ExtPageLength = 0;
5757 pReq->ExtPageType = 0;
5758 pReq->MsgFlags = 0;
5760 for (ii=0; ii < 8; ii++)
5761 pReq->Reserved2[ii] = 0;
5763 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5764 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5765 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5766 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5768 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5769 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5770 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5771 pReq->ExtPageType = pExtHdr->ExtPageType;
5772 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5774 /* Page Length must be treated as a reserved field for the extended header. */
5775 pReq->Header.PageLength = 0;
5778 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5780 /* Add a SGE to the config request.
5782 if (pCfg->dir)
5783 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5784 else
5785 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5787 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5788 flagsLength |= pExtHdr->ExtPageLength * 4;
5790 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5791 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5793 else {
5794 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5796 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5797 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5800 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5802 /* Append pCfg pointer to end of mf
5804 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5806 /* Initalize the timer
5808 init_timer(&pCfg->timer);
5809 pCfg->timer.data = (unsigned long) ioc;
5810 pCfg->timer.function = mpt_timer_expired;
5811 pCfg->wait_done = 0;
5813 /* Set the timer; ensure 10 second minimum */
5814 if (pCfg->timeout < 10)
5815 pCfg->timer.expires = jiffies + HZ*10;
5816 else
5817 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5819 /* Add to end of Q, set timer and then issue this command */
5820 spin_lock_irqsave(&ioc->FreeQlock, flags);
5821 list_add_tail(&pCfg->linkage, &ioc->configQ);
5822 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5824 add_timer(&pCfg->timer);
5825 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5826 wait_event(mpt_waitq, pCfg->wait_done);
5828 /* mf has been freed - do not access */
5830 rc = pCfg->status;
5832 return rc;
5835 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5837 * mpt_timer_expired - Callback for timer process.
5838 * Used only internal config functionality.
5839 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5841 static void
5842 mpt_timer_expired(unsigned long data)
5844 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5846 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
5848 /* Perform a FW reload */
5849 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5850 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5852 /* No more processing.
5853 * Hard reset clean-up will wake up
5854 * process and free all resources.
5856 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
5858 return;
5861 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5863 * mpt_ioc_reset - Base cleanup for hard reset
5864 * @ioc: Pointer to the adapter structure
5865 * @reset_phase: Indicates pre- or post-reset functionality
5867 * Remark: Frees resources with internally generated commands.
5869 static int
5870 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5872 CONFIGPARMS *pCfg;
5873 unsigned long flags;
5875 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5876 ": IOC %s_reset routed to MPT base driver!\n",
5877 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5878 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5880 if (reset_phase == MPT_IOC_SETUP_RESET) {
5882 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5883 /* If the internal config Q is not empty -
5884 * delete timer. MF resources will be freed when
5885 * the FIFO's are primed.
5887 spin_lock_irqsave(&ioc->FreeQlock, flags);
5888 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5889 del_timer(&pCfg->timer);
5890 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5892 } else {
5893 CONFIGPARMS *pNext;
5895 /* Search the configQ for internal commands.
5896 * Flush the Q, and wake up all suspended threads.
5898 spin_lock_irqsave(&ioc->FreeQlock, flags);
5899 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5900 list_del(&pCfg->linkage);
5902 pCfg->status = MPT_CONFIG_ERROR;
5903 pCfg->wait_done = 1;
5904 wake_up(&mpt_waitq);
5906 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5909 return 1; /* currently means nothing really */
5913 #ifdef CONFIG_PROC_FS /* { */
5914 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5916 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5918 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5920 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5922 * Returns 0 for success, non-zero for failure.
5924 static int
5925 procmpt_create(void)
5927 struct proc_dir_entry *ent;
5929 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5930 if (mpt_proc_root_dir == NULL)
5931 return -ENOTDIR;
5933 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5934 if (ent)
5935 ent->read_proc = procmpt_summary_read;
5937 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5938 if (ent)
5939 ent->read_proc = procmpt_version_read;
5941 return 0;
5944 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5946 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5948 * Returns 0 for success, non-zero for failure.
5950 static void
5951 procmpt_destroy(void)
5953 remove_proc_entry("version", mpt_proc_root_dir);
5954 remove_proc_entry("summary", mpt_proc_root_dir);
5955 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5960 * procmpt_summary_read - Handle read request of a summary file
5961 * @buf: Pointer to area to write information
5962 * @start: Pointer to start pointer
5963 * @offset: Offset to start writing
5964 * @request: Amount of read data requested
5965 * @eof: Pointer to EOF integer
5966 * @data: Pointer
5968 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
5969 * Returns number of characters written to process performing the read.
5971 static int
5972 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5974 MPT_ADAPTER *ioc;
5975 char *out = buf;
5976 int len;
5978 if (data) {
5979 int more = 0;
5981 ioc = data;
5982 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5984 out += more;
5985 } else {
5986 list_for_each_entry(ioc, &ioc_list, list) {
5987 int more = 0;
5989 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5991 out += more;
5992 if ((out-buf) >= request)
5993 break;
5997 len = out - buf;
5999 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6002 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6004 * procmpt_version_read - Handle read request from /proc/mpt/version.
6005 * @buf: Pointer to area to write information
6006 * @start: Pointer to start pointer
6007 * @offset: Offset to start writing
6008 * @request: Amount of read data requested
6009 * @eof: Pointer to EOF integer
6010 * @data: Pointer
6012 * Returns number of characters written to process performing the read.
6014 static int
6015 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6017 u8 cb_idx;
6018 int scsi, fc, sas, lan, ctl, targ, dmp;
6019 char *drvname;
6020 int len;
6022 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6023 len += sprintf(buf+len, " Fusion MPT base driver\n");
6025 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6026 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6027 drvname = NULL;
6028 if (MptCallbacks[cb_idx]) {
6029 switch (MptDriverClass[cb_idx]) {
6030 case MPTSPI_DRIVER:
6031 if (!scsi++) drvname = "SPI host";
6032 break;
6033 case MPTFC_DRIVER:
6034 if (!fc++) drvname = "FC host";
6035 break;
6036 case MPTSAS_DRIVER:
6037 if (!sas++) drvname = "SAS host";
6038 break;
6039 case MPTLAN_DRIVER:
6040 if (!lan++) drvname = "LAN";
6041 break;
6042 case MPTSTM_DRIVER:
6043 if (!targ++) drvname = "SCSI target";
6044 break;
6045 case MPTCTL_DRIVER:
6046 if (!ctl++) drvname = "ioctl";
6047 break;
6050 if (drvname)
6051 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
6055 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6058 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6060 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6061 * @buf: Pointer to area to write information
6062 * @start: Pointer to start pointer
6063 * @offset: Offset to start writing
6064 * @request: Amount of read data requested
6065 * @eof: Pointer to EOF integer
6066 * @data: Pointer
6068 * Returns number of characters written to process performing the read.
6070 static int
6071 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6073 MPT_ADAPTER *ioc = data;
6074 int len;
6075 char expVer[32];
6076 int sz;
6077 int p;
6079 mpt_get_fw_exp_ver(expVer, ioc);
6081 len = sprintf(buf, "%s:", ioc->name);
6082 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6083 len += sprintf(buf+len, " (f/w download boot flag set)");
6084 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6085 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6087 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
6088 ioc->facts.ProductID,
6089 ioc->prod_name);
6090 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6091 if (ioc->facts.FWImageSize)
6092 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6093 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6094 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6095 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
6097 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
6098 ioc->facts.CurrentHostMfaHighAddr);
6099 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
6100 ioc->facts.CurrentSenseBufferHighAddr);
6102 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6103 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6105 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6106 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6108 * Rounding UP to nearest 4-kB boundary here...
6110 sz = (ioc->req_sz * ioc->req_depth) + 128;
6111 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6112 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6113 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6114 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6115 4*ioc->facts.RequestFrameSize,
6116 ioc->facts.GlobalCredits);
6118 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
6119 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6120 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6121 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6122 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6123 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6124 ioc->facts.CurReplyFrameSize,
6125 ioc->facts.ReplyQueueDepth);
6127 len += sprintf(buf+len, " MaxDevices = %d\n",
6128 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6129 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6131 /* per-port info */
6132 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6133 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
6134 p+1,
6135 ioc->facts.NumberOfPorts);
6136 if (ioc->bus_type == FC) {
6137 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6138 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6139 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6140 a[5], a[4], a[3], a[2], a[1], a[0]);
6142 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
6143 ioc->fc_port_page0[p].WWNN.High,
6144 ioc->fc_port_page0[p].WWNN.Low,
6145 ioc->fc_port_page0[p].WWPN.High,
6146 ioc->fc_port_page0[p].WWPN.Low);
6150 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6153 #endif /* CONFIG_PROC_FS } */
6155 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6156 static void
6157 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6159 buf[0] ='\0';
6160 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6161 sprintf(buf, " (Exp %02d%02d)",
6162 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6163 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6165 /* insider hack! */
6166 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6167 strcat(buf, " [MDBG]");
6171 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6173 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6174 * @ioc: Pointer to MPT_ADAPTER structure
6175 * @buffer: Pointer to buffer where IOC summary info should be written
6176 * @size: Pointer to number of bytes we wrote (set by this routine)
6177 * @len: Offset at which to start writing in buffer
6178 * @showlan: Display LAN stuff?
6180 * This routine writes (english readable) ASCII text, which represents
6181 * a summary of IOC information, to a buffer.
6183 void
6184 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6186 char expVer[32];
6187 int y;
6189 mpt_get_fw_exp_ver(expVer, ioc);
6192 * Shorter summary of attached ioc's...
6194 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6195 ioc->name,
6196 ioc->prod_name,
6197 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6198 ioc->facts.FWVersion.Word,
6199 expVer,
6200 ioc->facts.NumberOfPorts,
6201 ioc->req_depth);
6203 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6204 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6205 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6206 a[5], a[4], a[3], a[2], a[1], a[0]);
6209 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6211 if (!ioc->active)
6212 y += sprintf(buffer+len+y, " (disabled)");
6214 y += sprintf(buffer+len+y, "\n");
6216 *size = y;
6219 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6221 * Reset Handling
6223 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6225 * mpt_HardResetHandler - Generic reset handler
6226 * @ioc: Pointer to MPT_ADAPTER structure
6227 * @sleepFlag: Indicates if sleep or schedule must be called.
6229 * Issues SCSI Task Management call based on input arg values.
6230 * If TaskMgmt fails, returns associated SCSI request.
6232 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6233 * or a non-interrupt thread. In the former, must not call schedule().
6235 * Note: A return of -1 is a FATAL error case, as it means a
6236 * FW reload/initialization failed.
6238 * Returns 0 for SUCCESS or -1 if FAILED.
6241 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6243 int rc;
6244 unsigned long flags;
6246 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6247 #ifdef MFCNT
6248 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6249 printk("MF count 0x%x !\n", ioc->mfcnt);
6250 #endif
6252 /* Reset the adapter. Prevent more than 1 call to
6253 * mpt_do_ioc_recovery at any instant in time.
6255 spin_lock_irqsave(&ioc->diagLock, flags);
6256 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
6257 spin_unlock_irqrestore(&ioc->diagLock, flags);
6258 return 0;
6259 } else {
6260 ioc->diagPending = 1;
6262 spin_unlock_irqrestore(&ioc->diagLock, flags);
6264 /* FIXME: If do_ioc_recovery fails, repeat....
6267 /* The SCSI driver needs to adjust timeouts on all current
6268 * commands prior to the diagnostic reset being issued.
6269 * Prevents timeouts occurring during a diagnostic reset...very bad.
6270 * For all other protocol drivers, this is a no-op.
6273 u8 cb_idx;
6274 int r = 0;
6276 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6277 if (MptResetHandlers[cb_idx]) {
6278 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
6279 ioc->name, cb_idx));
6280 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6281 if (ioc->alt_ioc) {
6282 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
6283 ioc->name, ioc->alt_ioc->name, cb_idx));
6284 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
6290 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
6291 printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
6293 ioc->reload_fw = 0;
6294 if (ioc->alt_ioc)
6295 ioc->alt_ioc->reload_fw = 0;
6297 spin_lock_irqsave(&ioc->diagLock, flags);
6298 ioc->diagPending = 0;
6299 if (ioc->alt_ioc)
6300 ioc->alt_ioc->diagPending = 0;
6301 spin_unlock_irqrestore(&ioc->diagLock, flags);
6303 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
6305 return rc;
6308 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6309 static void
6310 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
6312 char *ds = NULL;
6314 switch(event) {
6315 case MPI_EVENT_NONE:
6316 ds = "None";
6317 break;
6318 case MPI_EVENT_LOG_DATA:
6319 ds = "Log Data";
6320 break;
6321 case MPI_EVENT_STATE_CHANGE:
6322 ds = "State Change";
6323 break;
6324 case MPI_EVENT_UNIT_ATTENTION:
6325 ds = "Unit Attention";
6326 break;
6327 case MPI_EVENT_IOC_BUS_RESET:
6328 ds = "IOC Bus Reset";
6329 break;
6330 case MPI_EVENT_EXT_BUS_RESET:
6331 ds = "External Bus Reset";
6332 break;
6333 case MPI_EVENT_RESCAN:
6334 ds = "Bus Rescan Event";
6335 break;
6336 case MPI_EVENT_LINK_STATUS_CHANGE:
6337 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
6338 ds = "Link Status(FAILURE) Change";
6339 else
6340 ds = "Link Status(ACTIVE) Change";
6341 break;
6342 case MPI_EVENT_LOOP_STATE_CHANGE:
6343 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
6344 ds = "Loop State(LIP) Change";
6345 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
6346 ds = "Loop State(LPE) Change"; /* ??? */
6347 else
6348 ds = "Loop State(LPB) Change"; /* ??? */
6349 break;
6350 case MPI_EVENT_LOGOUT:
6351 ds = "Logout";
6352 break;
6353 case MPI_EVENT_EVENT_CHANGE:
6354 if (evData0)
6355 ds = "Events ON";
6356 else
6357 ds = "Events OFF";
6358 break;
6359 case MPI_EVENT_INTEGRATED_RAID:
6361 u8 ReasonCode = (u8)(evData0 >> 16);
6362 switch (ReasonCode) {
6363 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
6364 ds = "Integrated Raid: Volume Created";
6365 break;
6366 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
6367 ds = "Integrated Raid: Volume Deleted";
6368 break;
6369 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
6370 ds = "Integrated Raid: Volume Settings Changed";
6371 break;
6372 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
6373 ds = "Integrated Raid: Volume Status Changed";
6374 break;
6375 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
6376 ds = "Integrated Raid: Volume Physdisk Changed";
6377 break;
6378 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
6379 ds = "Integrated Raid: Physdisk Created";
6380 break;
6381 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
6382 ds = "Integrated Raid: Physdisk Deleted";
6383 break;
6384 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
6385 ds = "Integrated Raid: Physdisk Settings Changed";
6386 break;
6387 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
6388 ds = "Integrated Raid: Physdisk Status Changed";
6389 break;
6390 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
6391 ds = "Integrated Raid: Domain Validation Needed";
6392 break;
6393 case MPI_EVENT_RAID_RC_SMART_DATA :
6394 ds = "Integrated Raid; Smart Data";
6395 break;
6396 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
6397 ds = "Integrated Raid: Replace Action Started";
6398 break;
6399 default:
6400 ds = "Integrated Raid";
6401 break;
6403 break;
6405 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
6406 ds = "SCSI Device Status Change";
6407 break;
6408 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
6410 u8 id = (u8)(evData0);
6411 u8 channel = (u8)(evData0 >> 8);
6412 u8 ReasonCode = (u8)(evData0 >> 16);
6413 switch (ReasonCode) {
6414 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
6415 snprintf(evStr, EVENT_DESCR_STR_SZ,
6416 "SAS Device Status Change: Added: "
6417 "id=%d channel=%d", id, channel);
6418 break;
6419 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
6420 snprintf(evStr, EVENT_DESCR_STR_SZ,
6421 "SAS Device Status Change: Deleted: "
6422 "id=%d channel=%d", id, channel);
6423 break;
6424 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
6425 snprintf(evStr, EVENT_DESCR_STR_SZ,
6426 "SAS Device Status Change: SMART Data: "
6427 "id=%d channel=%d", id, channel);
6428 break;
6429 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
6430 snprintf(evStr, EVENT_DESCR_STR_SZ,
6431 "SAS Device Status Change: No Persistancy: "
6432 "id=%d channel=%d", id, channel);
6433 break;
6434 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
6435 snprintf(evStr, EVENT_DESCR_STR_SZ,
6436 "SAS Device Status Change: Unsupported Device "
6437 "Discovered : id=%d channel=%d", id, channel);
6438 break;
6439 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
6440 snprintf(evStr, EVENT_DESCR_STR_SZ,
6441 "SAS Device Status Change: Internal Device "
6442 "Reset : id=%d channel=%d", id, channel);
6443 break;
6444 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
6445 snprintf(evStr, EVENT_DESCR_STR_SZ,
6446 "SAS Device Status Change: Internal Task "
6447 "Abort : id=%d channel=%d", id, channel);
6448 break;
6449 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
6450 snprintf(evStr, EVENT_DESCR_STR_SZ,
6451 "SAS Device Status Change: Internal Abort "
6452 "Task Set : id=%d channel=%d", id, channel);
6453 break;
6454 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
6455 snprintf(evStr, EVENT_DESCR_STR_SZ,
6456 "SAS Device Status Change: Internal Clear "
6457 "Task Set : id=%d channel=%d", id, channel);
6458 break;
6459 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
6460 snprintf(evStr, EVENT_DESCR_STR_SZ,
6461 "SAS Device Status Change: Internal Query "
6462 "Task : id=%d channel=%d", id, channel);
6463 break;
6464 default:
6465 snprintf(evStr, EVENT_DESCR_STR_SZ,
6466 "SAS Device Status Change: Unknown: "
6467 "id=%d channel=%d", id, channel);
6468 break;
6470 break;
6472 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
6473 ds = "Bus Timer Expired";
6474 break;
6475 case MPI_EVENT_QUEUE_FULL:
6477 u16 curr_depth = (u16)(evData0 >> 16);
6478 u8 channel = (u8)(evData0 >> 8);
6479 u8 id = (u8)(evData0);
6481 snprintf(evStr, EVENT_DESCR_STR_SZ,
6482 "Queue Full: channel=%d id=%d depth=%d",
6483 channel, id, curr_depth);
6484 break;
6486 case MPI_EVENT_SAS_SES:
6487 ds = "SAS SES Event";
6488 break;
6489 case MPI_EVENT_PERSISTENT_TABLE_FULL:
6490 ds = "Persistent Table Full";
6491 break;
6492 case MPI_EVENT_SAS_PHY_LINK_STATUS:
6494 u8 LinkRates = (u8)(evData0 >> 8);
6495 u8 PhyNumber = (u8)(evData0);
6496 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
6497 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
6498 switch (LinkRates) {
6499 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
6500 snprintf(evStr, EVENT_DESCR_STR_SZ,
6501 "SAS PHY Link Status: Phy=%d:"
6502 " Rate Unknown",PhyNumber);
6503 break;
6504 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
6505 snprintf(evStr, EVENT_DESCR_STR_SZ,
6506 "SAS PHY Link Status: Phy=%d:"
6507 " Phy Disabled",PhyNumber);
6508 break;
6509 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
6510 snprintf(evStr, EVENT_DESCR_STR_SZ,
6511 "SAS PHY Link Status: Phy=%d:"
6512 " Failed Speed Nego",PhyNumber);
6513 break;
6514 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
6515 snprintf(evStr, EVENT_DESCR_STR_SZ,
6516 "SAS PHY Link Status: Phy=%d:"
6517 " Sata OOB Completed",PhyNumber);
6518 break;
6519 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
6520 snprintf(evStr, EVENT_DESCR_STR_SZ,
6521 "SAS PHY Link Status: Phy=%d:"
6522 " Rate 1.5 Gbps",PhyNumber);
6523 break;
6524 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
6525 snprintf(evStr, EVENT_DESCR_STR_SZ,
6526 "SAS PHY Link Status: Phy=%d:"
6527 " Rate 3.0 Gpbs",PhyNumber);
6528 break;
6529 default:
6530 snprintf(evStr, EVENT_DESCR_STR_SZ,
6531 "SAS PHY Link Status: Phy=%d", PhyNumber);
6532 break;
6534 break;
6536 case MPI_EVENT_SAS_DISCOVERY_ERROR:
6537 ds = "SAS Discovery Error";
6538 break;
6539 case MPI_EVENT_IR_RESYNC_UPDATE:
6541 u8 resync_complete = (u8)(evData0 >> 16);
6542 snprintf(evStr, EVENT_DESCR_STR_SZ,
6543 "IR Resync Update: Complete = %d:",resync_complete);
6544 break;
6546 case MPI_EVENT_IR2:
6548 u8 ReasonCode = (u8)(evData0 >> 16);
6549 switch (ReasonCode) {
6550 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
6551 ds = "IR2: LD State Changed";
6552 break;
6553 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
6554 ds = "IR2: PD State Changed";
6555 break;
6556 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
6557 ds = "IR2: Bad Block Table Full";
6558 break;
6559 case MPI_EVENT_IR2_RC_PD_INSERTED:
6560 ds = "IR2: PD Inserted";
6561 break;
6562 case MPI_EVENT_IR2_RC_PD_REMOVED:
6563 ds = "IR2: PD Removed";
6564 break;
6565 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
6566 ds = "IR2: Foreign CFG Detected";
6567 break;
6568 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
6569 ds = "IR2: Rebuild Medium Error";
6570 break;
6571 default:
6572 ds = "IR2";
6573 break;
6575 break;
6577 case MPI_EVENT_SAS_DISCOVERY:
6579 if (evData0)
6580 ds = "SAS Discovery: Start";
6581 else
6582 ds = "SAS Discovery: Stop";
6583 break;
6585 case MPI_EVENT_LOG_ENTRY_ADDED:
6586 ds = "SAS Log Entry Added";
6587 break;
6589 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
6591 u8 phy_num = (u8)(evData0);
6592 u8 port_num = (u8)(evData0 >> 8);
6593 u8 port_width = (u8)(evData0 >> 16);
6594 u8 primative = (u8)(evData0 >> 24);
6595 snprintf(evStr, EVENT_DESCR_STR_SZ,
6596 "SAS Broadcase Primative: phy=%d port=%d "
6597 "width=%d primative=0x%02x",
6598 phy_num, port_num, port_width, primative);
6599 break;
6602 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
6604 u8 reason = (u8)(evData0);
6605 u8 port_num = (u8)(evData0 >> 8);
6606 u16 handle = le16_to_cpu(evData0 >> 16);
6608 snprintf(evStr, EVENT_DESCR_STR_SZ,
6609 "SAS Initiator Device Status Change: reason=0x%02x "
6610 "port=%d handle=0x%04x",
6611 reason, port_num, handle);
6612 break;
6615 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6617 u8 max_init = (u8)(evData0);
6618 u8 current_init = (u8)(evData0 >> 8);
6620 snprintf(evStr, EVENT_DESCR_STR_SZ,
6621 "SAS Initiator Device Table Overflow: max initiators=%02d "
6622 "current initators=%02d",
6623 max_init, current_init);
6624 break;
6626 case MPI_EVENT_SAS_SMP_ERROR:
6628 u8 status = (u8)(evData0);
6629 u8 port_num = (u8)(evData0 >> 8);
6630 u8 result = (u8)(evData0 >> 16);
6632 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6633 snprintf(evStr, EVENT_DESCR_STR_SZ,
6634 "SAS SMP Error: port=%d result=0x%02x",
6635 port_num, result);
6636 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6637 snprintf(evStr, EVENT_DESCR_STR_SZ,
6638 "SAS SMP Error: port=%d : CRC Error",
6639 port_num);
6640 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6641 snprintf(evStr, EVENT_DESCR_STR_SZ,
6642 "SAS SMP Error: port=%d : Timeout",
6643 port_num);
6644 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6645 snprintf(evStr, EVENT_DESCR_STR_SZ,
6646 "SAS SMP Error: port=%d : No Destination",
6647 port_num);
6648 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6649 snprintf(evStr, EVENT_DESCR_STR_SZ,
6650 "SAS SMP Error: port=%d : Bad Destination",
6651 port_num);
6652 else
6653 snprintf(evStr, EVENT_DESCR_STR_SZ,
6654 "SAS SMP Error: port=%d : status=0x%02x",
6655 port_num, status);
6656 break;
6660 * MPT base "custom" events may be added here...
6662 default:
6663 ds = "Unknown";
6664 break;
6666 if (ds)
6667 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6670 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6672 * ProcessEventNotification - Route EventNotificationReply to all event handlers
6673 * @ioc: Pointer to MPT_ADAPTER structure
6674 * @pEventReply: Pointer to EventNotification reply frame
6675 * @evHandlers: Pointer to integer, number of event handlers
6677 * Routes a received EventNotificationReply to all currently registered
6678 * event handlers.
6679 * Returns sum of event handlers return values.
6681 static int
6682 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6684 u16 evDataLen;
6685 u32 evData0 = 0;
6686 // u32 evCtx;
6687 int ii;
6688 u8 cb_idx;
6689 int r = 0;
6690 int handlers = 0;
6691 char evStr[EVENT_DESCR_STR_SZ];
6692 u8 event;
6695 * Do platform normalization of values
6697 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6698 // evCtx = le32_to_cpu(pEventReply->EventContext);
6699 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6700 if (evDataLen) {
6701 evData0 = le32_to_cpu(pEventReply->Data[0]);
6704 EventDescriptionStr(event, evData0, evStr);
6705 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
6706 ioc->name,
6707 event,
6708 evStr));
6710 #ifdef CONFIG_FUSION_LOGGING
6711 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6712 ": Event data:\n", ioc->name));
6713 for (ii = 0; ii < evDataLen; ii++)
6714 devtverboseprintk(ioc, printk(" %08x",
6715 le32_to_cpu(pEventReply->Data[ii])));
6716 devtverboseprintk(ioc, printk("\n"));
6717 #endif
6720 * Do general / base driver event processing
6722 switch(event) {
6723 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6724 if (evDataLen) {
6725 u8 evState = evData0 & 0xFF;
6727 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6729 /* Update EventState field in cached IocFacts */
6730 if (ioc->facts.Function) {
6731 ioc->facts.EventState = evState;
6734 break;
6735 case MPI_EVENT_INTEGRATED_RAID:
6736 mptbase_raid_process_event_data(ioc,
6737 (MpiEventDataRaid_t *)pEventReply->Data);
6738 break;
6739 default:
6740 break;
6744 * Should this event be logged? Events are written sequentially.
6745 * When buffer is full, start again at the top.
6747 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6748 int idx;
6750 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6752 ioc->events[idx].event = event;
6753 ioc->events[idx].eventContext = ioc->eventContext;
6755 for (ii = 0; ii < 2; ii++) {
6756 if (ii < evDataLen)
6757 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6758 else
6759 ioc->events[idx].data[ii] = 0;
6762 ioc->eventContext++;
6767 * Call each currently registered protocol event handler.
6769 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6770 if (MptEvHandlers[cb_idx]) {
6771 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
6772 ioc->name, cb_idx));
6773 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
6774 handlers++;
6777 /* FIXME? Examine results here? */
6780 * If needed, send (a single) EventAck.
6782 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6783 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6784 "EventAck required\n",ioc->name));
6785 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6786 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
6787 ioc->name, ii));
6791 *evHandlers = handlers;
6792 return r;
6795 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6797 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6798 * @ioc: Pointer to MPT_ADAPTER structure
6799 * @log_info: U32 LogInfo reply word from the IOC
6801 * Refer to lsi/mpi_log_fc.h.
6803 static void
6804 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6806 char *desc = "unknown";
6808 switch (log_info & 0xFF000000) {
6809 case MPI_IOCLOGINFO_FC_INIT_BASE:
6810 desc = "FCP Initiator";
6811 break;
6812 case MPI_IOCLOGINFO_FC_TARGET_BASE:
6813 desc = "FCP Target";
6814 break;
6815 case MPI_IOCLOGINFO_FC_LAN_BASE:
6816 desc = "LAN";
6817 break;
6818 case MPI_IOCLOGINFO_FC_MSG_BASE:
6819 desc = "MPI Message Layer";
6820 break;
6821 case MPI_IOCLOGINFO_FC_LINK_BASE:
6822 desc = "FC Link";
6823 break;
6824 case MPI_IOCLOGINFO_FC_CTX_BASE:
6825 desc = "Context Manager";
6826 break;
6827 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
6828 desc = "Invalid Field Offset";
6829 break;
6830 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
6831 desc = "State Change Info";
6832 break;
6835 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6836 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
6839 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6841 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6842 * @ioc: Pointer to MPT_ADAPTER structure
6843 * @mr: Pointer to MPT reply frame
6844 * @log_info: U32 LogInfo word from the IOC
6846 * Refer to lsi/sp_log.h.
6848 static void
6849 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6851 u32 info = log_info & 0x00FF0000;
6852 char *desc = "unknown";
6854 switch (info) {
6855 case 0x00010000:
6856 desc = "bug! MID not found";
6857 if (ioc->reload_fw == 0)
6858 ioc->reload_fw++;
6859 break;
6861 case 0x00020000:
6862 desc = "Parity Error";
6863 break;
6865 case 0x00030000:
6866 desc = "ASYNC Outbound Overrun";
6867 break;
6869 case 0x00040000:
6870 desc = "SYNC Offset Error";
6871 break;
6873 case 0x00050000:
6874 desc = "BM Change";
6875 break;
6877 case 0x00060000:
6878 desc = "Msg In Overflow";
6879 break;
6881 case 0x00070000:
6882 desc = "DMA Error";
6883 break;
6885 case 0x00080000:
6886 desc = "Outbound DMA Overrun";
6887 break;
6889 case 0x00090000:
6890 desc = "Task Management";
6891 break;
6893 case 0x000A0000:
6894 desc = "Device Problem";
6895 break;
6897 case 0x000B0000:
6898 desc = "Invalid Phase Change";
6899 break;
6901 case 0x000C0000:
6902 desc = "Untagged Table Size";
6903 break;
6907 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6910 /* strings for sas loginfo */
6911 static char *originator_str[] = {
6912 "IOP", /* 00h */
6913 "PL", /* 01h */
6914 "IR" /* 02h */
6916 static char *iop_code_str[] = {
6917 NULL, /* 00h */
6918 "Invalid SAS Address", /* 01h */
6919 NULL, /* 02h */
6920 "Invalid Page", /* 03h */
6921 "Diag Message Error", /* 04h */
6922 "Task Terminated", /* 05h */
6923 "Enclosure Management", /* 06h */
6924 "Target Mode" /* 07h */
6926 static char *pl_code_str[] = {
6927 NULL, /* 00h */
6928 "Open Failure", /* 01h */
6929 "Invalid Scatter Gather List", /* 02h */
6930 "Wrong Relative Offset or Frame Length", /* 03h */
6931 "Frame Transfer Error", /* 04h */
6932 "Transmit Frame Connected Low", /* 05h */
6933 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6934 "SATA Read Log Receive Data Error", /* 07h */
6935 "SATA NCQ Fail All Commands After Error", /* 08h */
6936 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6937 "Receive Frame Invalid Message", /* 0Ah */
6938 "Receive Context Message Valid Error", /* 0Bh */
6939 "Receive Frame Current Frame Error", /* 0Ch */
6940 "SATA Link Down", /* 0Dh */
6941 "Discovery SATA Init W IOS", /* 0Eh */
6942 "Config Invalid Page", /* 0Fh */
6943 "Discovery SATA Init Timeout", /* 10h */
6944 "Reset", /* 11h */
6945 "Abort", /* 12h */
6946 "IO Not Yet Executed", /* 13h */
6947 "IO Executed", /* 14h */
6948 "Persistent Reservation Out Not Affiliation "
6949 "Owner", /* 15h */
6950 "Open Transmit DMA Abort", /* 16h */
6951 "IO Device Missing Delay Retry", /* 17h */
6952 "IO Cancelled Due to Recieve Error", /* 18h */
6953 NULL, /* 19h */
6954 NULL, /* 1Ah */
6955 NULL, /* 1Bh */
6956 NULL, /* 1Ch */
6957 NULL, /* 1Dh */
6958 NULL, /* 1Eh */
6959 NULL, /* 1Fh */
6960 "Enclosure Management" /* 20h */
6962 static char *ir_code_str[] = {
6963 "Raid Action Error", /* 00h */
6964 NULL, /* 00h */
6965 NULL, /* 01h */
6966 NULL, /* 02h */
6967 NULL, /* 03h */
6968 NULL, /* 04h */
6969 NULL, /* 05h */
6970 NULL, /* 06h */
6971 NULL /* 07h */
6973 static char *raid_sub_code_str[] = {
6974 NULL, /* 00h */
6975 "Volume Creation Failed: Data Passed too "
6976 "Large", /* 01h */
6977 "Volume Creation Failed: Duplicate Volumes "
6978 "Attempted", /* 02h */
6979 "Volume Creation Failed: Max Number "
6980 "Supported Volumes Exceeded", /* 03h */
6981 "Volume Creation Failed: DMA Error", /* 04h */
6982 "Volume Creation Failed: Invalid Volume Type", /* 05h */
6983 "Volume Creation Failed: Error Reading "
6984 "MFG Page 4", /* 06h */
6985 "Volume Creation Failed: Creating Internal "
6986 "Structures", /* 07h */
6987 NULL, /* 08h */
6988 NULL, /* 09h */
6989 NULL, /* 0Ah */
6990 NULL, /* 0Bh */
6991 NULL, /* 0Ch */
6992 NULL, /* 0Dh */
6993 NULL, /* 0Eh */
6994 NULL, /* 0Fh */
6995 "Activation failed: Already Active Volume", /* 10h */
6996 "Activation failed: Unsupported Volume Type", /* 11h */
6997 "Activation failed: Too Many Active Volumes", /* 12h */
6998 "Activation failed: Volume ID in Use", /* 13h */
6999 "Activation failed: Reported Failure", /* 14h */
7000 "Activation failed: Importing a Volume", /* 15h */
7001 NULL, /* 16h */
7002 NULL, /* 17h */
7003 NULL, /* 18h */
7004 NULL, /* 19h */
7005 NULL, /* 1Ah */
7006 NULL, /* 1Bh */
7007 NULL, /* 1Ch */
7008 NULL, /* 1Dh */
7009 NULL, /* 1Eh */
7010 NULL, /* 1Fh */
7011 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7012 "Phys Disk failed: Data Passed too Large", /* 21h */
7013 "Phys Disk failed: DMA Error", /* 22h */
7014 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7015 "Phys Disk failed: Creating Phys Disk Config "
7016 "Page", /* 24h */
7017 NULL, /* 25h */
7018 NULL, /* 26h */
7019 NULL, /* 27h */
7020 NULL, /* 28h */
7021 NULL, /* 29h */
7022 NULL, /* 2Ah */
7023 NULL, /* 2Bh */
7024 NULL, /* 2Ch */
7025 NULL, /* 2Dh */
7026 NULL, /* 2Eh */
7027 NULL, /* 2Fh */
7028 "Compatibility Error: IR Disabled", /* 30h */
7029 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7030 "Compatibility Error: Device not Direct Access "
7031 "Device ", /* 32h */
7032 "Compatibility Error: Removable Device Found", /* 33h */
7033 "Compatibility Error: Device SCSI Version not "
7034 "2 or Higher", /* 34h */
7035 "Compatibility Error: SATA Device, 48 BIT LBA "
7036 "not Supported", /* 35h */
7037 "Compatibility Error: Device doesn't have "
7038 "512 Byte Block Sizes", /* 36h */
7039 "Compatibility Error: Volume Type Check Failed", /* 37h */
7040 "Compatibility Error: Volume Type is "
7041 "Unsupported by FW", /* 38h */
7042 "Compatibility Error: Disk Drive too Small for "
7043 "use in Volume", /* 39h */
7044 "Compatibility Error: Phys Disk for Create "
7045 "Volume not Found", /* 3Ah */
7046 "Compatibility Error: Too Many or too Few "
7047 "Disks for Volume Type", /* 3Bh */
7048 "Compatibility Error: Disk stripe Sizes "
7049 "Must be 64KB", /* 3Ch */
7050 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7053 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7055 * mpt_sas_log_info - Log information returned from SAS IOC.
7056 * @ioc: Pointer to MPT_ADAPTER structure
7057 * @log_info: U32 LogInfo reply word from the IOC
7059 * Refer to lsi/mpi_log_sas.h.
7061 static void
7062 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7064 union loginfo_type {
7065 u32 loginfo;
7066 struct {
7067 u32 subcode:16;
7068 u32 code:8;
7069 u32 originator:4;
7070 u32 bus_type:4;
7071 }dw;
7073 union loginfo_type sas_loginfo;
7074 char *originator_desc = NULL;
7075 char *code_desc = NULL;
7076 char *sub_code_desc = NULL;
7078 sas_loginfo.loginfo = log_info;
7079 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7080 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
7081 return;
7083 originator_desc = originator_str[sas_loginfo.dw.originator];
7085 switch (sas_loginfo.dw.originator) {
7087 case 0: /* IOP */
7088 if (sas_loginfo.dw.code <
7089 sizeof(iop_code_str)/sizeof(char*))
7090 code_desc = iop_code_str[sas_loginfo.dw.code];
7091 break;
7092 case 1: /* PL */
7093 if (sas_loginfo.dw.code <
7094 sizeof(pl_code_str)/sizeof(char*))
7095 code_desc = pl_code_str[sas_loginfo.dw.code];
7096 break;
7097 case 2: /* IR */
7098 if (sas_loginfo.dw.code >=
7099 sizeof(ir_code_str)/sizeof(char*))
7100 break;
7101 code_desc = ir_code_str[sas_loginfo.dw.code];
7102 if (sas_loginfo.dw.subcode >=
7103 sizeof(raid_sub_code_str)/sizeof(char*))
7104 break;
7105 if (sas_loginfo.dw.code == 0)
7106 sub_code_desc =
7107 raid_sub_code_str[sas_loginfo.dw.subcode];
7108 break;
7109 default:
7110 return;
7113 if (sub_code_desc != NULL)
7114 printk(MYIOC_s_INFO_FMT
7115 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7116 " SubCode={%s}\n",
7117 ioc->name, log_info, originator_desc, code_desc,
7118 sub_code_desc);
7119 else if (code_desc != NULL)
7120 printk(MYIOC_s_INFO_FMT
7121 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7122 " SubCode(0x%04x)\n",
7123 ioc->name, log_info, originator_desc, code_desc,
7124 sas_loginfo.dw.subcode);
7125 else
7126 printk(MYIOC_s_INFO_FMT
7127 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7128 " SubCode(0x%04x)\n",
7129 ioc->name, log_info, originator_desc,
7130 sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7135 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7136 * @ioc: Pointer to MPT_ADAPTER structure
7137 * @ioc_status: U32 IOCStatus word from IOC
7138 * @mf: Pointer to MPT request frame
7140 * Refer to lsi/mpi.h.
7142 static void
7143 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7145 Config_t *pReq = (Config_t *)mf;
7146 char extend_desc[EVENT_DESCR_STR_SZ];
7147 char *desc = NULL;
7148 u32 form;
7149 u8 page_type;
7151 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7152 page_type = pReq->ExtPageType;
7153 else
7154 page_type = pReq->Header.PageType;
7157 * ignore invalid page messages for GET_NEXT_HANDLE
7159 form = le32_to_cpu(pReq->PageAddress);
7160 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7161 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7162 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7163 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7164 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7165 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7166 return;
7168 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7169 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7170 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7171 return;
7174 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7175 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7176 page_type, pReq->Header.PageNumber, pReq->Action, form);
7178 switch (ioc_status) {
7180 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7181 desc = "Config Page Invalid Action";
7182 break;
7184 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7185 desc = "Config Page Invalid Type";
7186 break;
7188 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7189 desc = "Config Page Invalid Page";
7190 break;
7192 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7193 desc = "Config Page Invalid Data";
7194 break;
7196 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7197 desc = "Config Page No Defaults";
7198 break;
7200 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7201 desc = "Config Page Can't Commit";
7202 break;
7205 if (!desc)
7206 return;
7208 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7209 ioc->name, ioc_status, desc, extend_desc));
7213 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7214 * @ioc: Pointer to MPT_ADAPTER structure
7215 * @ioc_status: U32 IOCStatus word from IOC
7216 * @mf: Pointer to MPT request frame
7218 * Refer to lsi/mpi.h.
7220 static void
7221 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7223 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
7224 char *desc = NULL;
7226 switch (status) {
7228 /****************************************************************************/
7229 /* Common IOCStatus values for all replies */
7230 /****************************************************************************/
7232 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
7233 desc = "Invalid Function";
7234 break;
7236 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
7237 desc = "Busy";
7238 break;
7240 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
7241 desc = "Invalid SGL";
7242 break;
7244 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
7245 desc = "Internal Error";
7246 break;
7248 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
7249 desc = "Reserved";
7250 break;
7252 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
7253 desc = "Insufficient Resources";
7254 break;
7256 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
7257 desc = "Invalid Field";
7258 break;
7260 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
7261 desc = "Invalid State";
7262 break;
7264 /****************************************************************************/
7265 /* Config IOCStatus values */
7266 /****************************************************************************/
7268 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7269 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7270 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7271 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7272 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7273 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7274 mpt_iocstatus_info_config(ioc, status, mf);
7275 break;
7277 /****************************************************************************/
7278 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
7279 /* */
7280 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7281 /* */
7282 /****************************************************************************/
7284 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
7285 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
7286 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
7287 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
7288 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
7289 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
7290 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
7291 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
7292 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
7293 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
7294 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
7295 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
7296 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
7297 break;
7299 /****************************************************************************/
7300 /* SCSI Target values */
7301 /****************************************************************************/
7303 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
7304 desc = "Target: Priority IO";
7305 break;
7307 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
7308 desc = "Target: Invalid Port";
7309 break;
7311 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
7312 desc = "Target Invalid IO Index:";
7313 break;
7315 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
7316 desc = "Target: Aborted";
7317 break;
7319 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
7320 desc = "Target: No Conn Retryable";
7321 break;
7323 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
7324 desc = "Target: No Connection";
7325 break;
7327 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
7328 desc = "Target: Transfer Count Mismatch";
7329 break;
7331 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
7332 desc = "Target: STS Data not Sent";
7333 break;
7335 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
7336 desc = "Target: Data Offset Error";
7337 break;
7339 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
7340 desc = "Target: Too Much Write Data";
7341 break;
7343 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
7344 desc = "Target: IU Too Short";
7345 break;
7347 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
7348 desc = "Target: ACK NAK Timeout";
7349 break;
7351 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
7352 desc = "Target: Nak Received";
7353 break;
7355 /****************************************************************************/
7356 /* Fibre Channel Direct Access values */
7357 /****************************************************************************/
7359 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
7360 desc = "FC: Aborted";
7361 break;
7363 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
7364 desc = "FC: RX ID Invalid";
7365 break;
7367 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
7368 desc = "FC: DID Invalid";
7369 break;
7371 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
7372 desc = "FC: Node Logged Out";
7373 break;
7375 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
7376 desc = "FC: Exchange Canceled";
7377 break;
7379 /****************************************************************************/
7380 /* LAN values */
7381 /****************************************************************************/
7383 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
7384 desc = "LAN: Device not Found";
7385 break;
7387 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
7388 desc = "LAN: Device Failure";
7389 break;
7391 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
7392 desc = "LAN: Transmit Error";
7393 break;
7395 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
7396 desc = "LAN: Transmit Aborted";
7397 break;
7399 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
7400 desc = "LAN: Receive Error";
7401 break;
7403 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
7404 desc = "LAN: Receive Aborted";
7405 break;
7407 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
7408 desc = "LAN: Partial Packet";
7409 break;
7411 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
7412 desc = "LAN: Canceled";
7413 break;
7415 /****************************************************************************/
7416 /* Serial Attached SCSI values */
7417 /****************************************************************************/
7419 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
7420 desc = "SAS: SMP Request Failed";
7421 break;
7423 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
7424 desc = "SAS: SMP Data Overrun";
7425 break;
7427 default:
7428 desc = "Others";
7429 break;
7432 if (!desc)
7433 return;
7435 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
7436 ioc->name, status, desc));
7439 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7440 EXPORT_SYMBOL(mpt_attach);
7441 EXPORT_SYMBOL(mpt_detach);
7442 #ifdef CONFIG_PM
7443 EXPORT_SYMBOL(mpt_resume);
7444 EXPORT_SYMBOL(mpt_suspend);
7445 #endif
7446 EXPORT_SYMBOL(ioc_list);
7447 EXPORT_SYMBOL(mpt_proc_root_dir);
7448 EXPORT_SYMBOL(mpt_register);
7449 EXPORT_SYMBOL(mpt_deregister);
7450 EXPORT_SYMBOL(mpt_event_register);
7451 EXPORT_SYMBOL(mpt_event_deregister);
7452 EXPORT_SYMBOL(mpt_reset_register);
7453 EXPORT_SYMBOL(mpt_reset_deregister);
7454 EXPORT_SYMBOL(mpt_device_driver_register);
7455 EXPORT_SYMBOL(mpt_device_driver_deregister);
7456 EXPORT_SYMBOL(mpt_get_msg_frame);
7457 EXPORT_SYMBOL(mpt_put_msg_frame);
7458 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
7459 EXPORT_SYMBOL(mpt_free_msg_frame);
7460 EXPORT_SYMBOL(mpt_add_sge);
7461 EXPORT_SYMBOL(mpt_send_handshake_request);
7462 EXPORT_SYMBOL(mpt_verify_adapter);
7463 EXPORT_SYMBOL(mpt_GetIocState);
7464 EXPORT_SYMBOL(mpt_print_ioc_summary);
7465 EXPORT_SYMBOL(mpt_HardResetHandler);
7466 EXPORT_SYMBOL(mpt_config);
7467 EXPORT_SYMBOL(mpt_findImVolumes);
7468 EXPORT_SYMBOL(mpt_alloc_fw_memory);
7469 EXPORT_SYMBOL(mpt_free_fw_memory);
7470 EXPORT_SYMBOL(mptbase_sas_persist_operation);
7471 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
7473 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7475 * fusion_init - Fusion MPT base driver initialization routine.
7477 * Returns 0 for success, non-zero for failure.
7479 static int __init
7480 fusion_init(void)
7482 u8 cb_idx;
7484 show_mptmod_ver(my_NAME, my_VERSION);
7485 printk(KERN_INFO COPYRIGHT "\n");
7487 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
7488 MptCallbacks[cb_idx] = NULL;
7489 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
7490 MptEvHandlers[cb_idx] = NULL;
7491 MptResetHandlers[cb_idx] = NULL;
7494 /* Register ourselves (mptbase) in order to facilitate
7495 * EventNotification handling.
7497 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
7499 /* Register for hard reset handling callbacks.
7501 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
7503 #ifdef CONFIG_PROC_FS
7504 (void) procmpt_create();
7505 #endif
7506 return 0;
7509 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7511 * fusion_exit - Perform driver unload cleanup.
7513 * This routine frees all resources associated with each MPT adapter
7514 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
7516 static void __exit
7517 fusion_exit(void)
7520 mpt_reset_deregister(mpt_base_index);
7522 #ifdef CONFIG_PROC_FS
7523 procmpt_destroy();
7524 #endif
7527 module_init(fusion_init);
7528 module_exit(fusion_exit);