[SCSI] mpt fusion: convert inactive_list_mutex to a mutex
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / message / fusion / mptbase.c
bloba34ddc7bce80c93682c5af5275d63d8bd6940ff7
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 = -1;
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->bus_type == SAS && mpt_msi_enable == -1)
1690 ioc->msi_enable = 1;
1691 else
1692 ioc->msi_enable = mpt_msi_enable;
1694 if (ioc->errata_flag_1064)
1695 pci_disable_io_access(pdev);
1697 spin_lock_init(&ioc->FreeQlock);
1699 /* Disable all! */
1700 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1701 ioc->active = 0;
1702 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1704 /* Set IOC ptr in the pcidev's driver data. */
1705 pci_set_drvdata(ioc->pcidev, ioc);
1707 /* Set lookup ptr. */
1708 list_add_tail(&ioc->list, &ioc_list);
1710 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1712 mpt_detect_bound_ports(ioc, pdev);
1714 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1715 CAN_SLEEP)) != 0){
1716 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1717 ioc->name, r);
1719 list_del(&ioc->list);
1720 if (ioc->alt_ioc)
1721 ioc->alt_ioc->alt_ioc = NULL;
1722 iounmap(ioc->memmap);
1723 if (r != -5)
1724 pci_release_selected_regions(pdev, ioc->bars);
1725 kfree(ioc);
1726 pci_set_drvdata(pdev, NULL);
1727 return r;
1730 /* call per device driver probe entry point */
1731 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1732 if(MptDeviceDriverHandlers[cb_idx] &&
1733 MptDeviceDriverHandlers[cb_idx]->probe) {
1734 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1738 #ifdef CONFIG_PROC_FS
1740 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1742 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1743 if (dent) {
1744 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1745 if (ent) {
1746 ent->read_proc = procmpt_iocinfo_read;
1747 ent->data = ioc;
1749 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1750 if (ent) {
1751 ent->read_proc = procmpt_summary_read;
1752 ent->data = ioc;
1755 #endif
1757 return 0;
1760 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1762 * mpt_detach - Remove a PCI intelligent MPT adapter.
1763 * @pdev: Pointer to pci_dev structure
1766 void
1767 mpt_detach(struct pci_dev *pdev)
1769 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1770 char pname[32];
1771 u8 cb_idx;
1773 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1774 remove_proc_entry(pname, NULL);
1775 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1776 remove_proc_entry(pname, NULL);
1777 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1778 remove_proc_entry(pname, NULL);
1780 /* call per device driver remove entry point */
1781 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1782 if(MptDeviceDriverHandlers[cb_idx] &&
1783 MptDeviceDriverHandlers[cb_idx]->remove) {
1784 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
1788 /* Disable interrupts! */
1789 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1791 ioc->active = 0;
1792 synchronize_irq(pdev->irq);
1794 /* Clear any lingering interrupt */
1795 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1797 CHIPREG_READ32(&ioc->chip->IntStatus);
1799 mpt_adapter_dispose(ioc);
1801 pci_set_drvdata(pdev, NULL);
1804 /**************************************************************************
1805 * Power Management
1807 #ifdef CONFIG_PM
1808 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1810 * mpt_suspend - Fusion MPT base driver suspend routine.
1811 * @pdev: Pointer to pci_dev structure
1812 * @state: new state to enter
1815 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1817 u32 device_state;
1818 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1820 device_state = pci_choose_state(pdev, state);
1821 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
1822 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1823 device_state);
1825 /* put ioc into READY_STATE */
1826 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1827 printk(MYIOC_s_ERR_FMT
1828 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1831 /* disable interrupts */
1832 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1833 ioc->active = 0;
1835 /* Clear any lingering interrupt */
1836 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1838 free_irq(ioc->pci_irq, ioc);
1839 if (mpt_msi_enable)
1840 pci_disable_msi(ioc->pcidev);
1841 ioc->pci_irq = -1;
1842 pci_save_state(pdev);
1843 pci_disable_device(pdev);
1844 pci_release_selected_regions(pdev, ioc->bars);
1845 pci_set_power_state(pdev, device_state);
1846 return 0;
1849 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1851 * mpt_resume - Fusion MPT base driver resume routine.
1852 * @pdev: Pointer to pci_dev structure
1855 mpt_resume(struct pci_dev *pdev)
1857 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1858 u32 device_state = pdev->current_state;
1859 int recovery_state;
1860 int err;
1862 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
1863 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1864 device_state);
1866 pci_set_power_state(pdev, PCI_D0);
1867 pci_enable_wake(pdev, PCI_D0, 0);
1868 pci_restore_state(pdev);
1869 ioc->pcidev = pdev;
1870 err = mpt_mapresources(ioc);
1871 if (err)
1872 return err;
1874 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1875 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1876 CHIPREG_READ32(&ioc->chip->Doorbell));
1879 * Errata workaround for SAS pci express:
1880 * Upon returning to the D0 state, the contents of the doorbell will be
1881 * stale data, and this will incorrectly signal to the host driver that
1882 * the firmware is ready to process mpt commands. The workaround is
1883 * to issue a diagnostic reset.
1885 if (ioc->bus_type == SAS && (pdev->device ==
1886 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
1887 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
1888 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
1889 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
1890 ioc->name);
1891 goto out;
1895 /* bring ioc to operational state */
1896 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
1897 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1898 CAN_SLEEP);
1899 if (recovery_state != 0)
1900 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
1901 "error:[%x]\n", ioc->name, recovery_state);
1902 else
1903 printk(MYIOC_s_INFO_FMT
1904 "pci-resume: success\n", ioc->name);
1905 out:
1906 return 0;
1909 #endif
1911 static int
1912 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
1914 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1915 ioc->bus_type != SPI) ||
1916 (MptDriverClass[index] == MPTFC_DRIVER &&
1917 ioc->bus_type != FC) ||
1918 (MptDriverClass[index] == MPTSAS_DRIVER &&
1919 ioc->bus_type != SAS))
1920 /* make sure we only call the relevant reset handler
1921 * for the bus */
1922 return 0;
1923 return (MptResetHandlers[index])(ioc, reset_phase);
1926 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1928 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1929 * @ioc: Pointer to MPT adapter structure
1930 * @reason: Event word / reason
1931 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1933 * This routine performs all the steps necessary to bring the IOC
1934 * to a OPERATIONAL state.
1936 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1937 * MPT adapter.
1939 * Returns:
1940 * 0 for success
1941 * -1 if failed to get board READY
1942 * -2 if READY but IOCFacts Failed
1943 * -3 if READY but PrimeIOCFifos Failed
1944 * -4 if READY but IOCInit Failed
1945 * -5 if failed to enable_device and/or request_selected_regions
1946 * -6 if failed to upload firmware
1948 static int
1949 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1951 int hard_reset_done = 0;
1952 int alt_ioc_ready = 0;
1953 int hard;
1954 int rc=0;
1955 int ii;
1956 u8 cb_idx;
1957 int handlers;
1958 int ret = 0;
1959 int reset_alt_ioc_active = 0;
1960 int irq_allocated = 0;
1961 u8 *a;
1963 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
1964 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1966 /* Disable reply interrupts (also blocks FreeQ) */
1967 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1968 ioc->active = 0;
1970 if (ioc->alt_ioc) {
1971 if (ioc->alt_ioc->active)
1972 reset_alt_ioc_active = 1;
1974 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1975 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1976 ioc->alt_ioc->active = 0;
1979 hard = 1;
1980 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1981 hard = 0;
1983 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1984 if (hard_reset_done == -4) {
1985 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
1986 ioc->name);
1988 if (reset_alt_ioc_active && ioc->alt_ioc) {
1989 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1990 dprintk(ioc, printk(MYIOC_s_INFO_FMT
1991 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
1992 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1993 ioc->alt_ioc->active = 1;
1996 } else {
1997 printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
1999 return -1;
2002 /* hard_reset_done = 0 if a soft reset was performed
2003 * and 1 if a hard reset was performed.
2005 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2006 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2007 alt_ioc_ready = 1;
2008 else
2009 printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
2012 for (ii=0; ii<5; ii++) {
2013 /* Get IOC facts! Allow 5 retries */
2014 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2015 break;
2019 if (ii == 5) {
2020 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2021 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2022 ret = -2;
2023 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2024 MptDisplayIocCapabilities(ioc);
2027 if (alt_ioc_ready) {
2028 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2029 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2030 "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
2031 /* Retry - alt IOC was initialized once
2033 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2035 if (rc) {
2036 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2037 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2038 alt_ioc_ready = 0;
2039 reset_alt_ioc_active = 0;
2040 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2041 MptDisplayIocCapabilities(ioc->alt_ioc);
2045 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2046 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2047 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2048 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2049 IORESOURCE_IO);
2050 if (pci_enable_device(ioc->pcidev))
2051 return -5;
2052 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2053 "mpt"))
2054 return -5;
2058 * Device is reset now. It must have de-asserted the interrupt line
2059 * (if it was asserted) and it should be safe to register for the
2060 * interrupt now.
2062 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2063 ioc->pci_irq = -1;
2064 if (ioc->pcidev->irq) {
2065 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2066 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2067 ioc->name);
2068 else
2069 ioc->msi_enable = 0;
2070 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2071 IRQF_SHARED, ioc->name, ioc);
2072 if (rc < 0) {
2073 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2074 "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
2075 if (ioc->msi_enable)
2076 pci_disable_msi(ioc->pcidev);
2077 return -EBUSY;
2079 irq_allocated = 1;
2080 ioc->pci_irq = ioc->pcidev->irq;
2081 pci_set_master(ioc->pcidev); /* ?? */
2082 dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
2083 "%d\n", ioc->name, ioc->pcidev->irq));
2087 /* Prime reply & request queues!
2088 * (mucho alloc's) Must be done prior to
2089 * init as upper addresses are needed for init.
2090 * If fails, continue with alt-ioc processing
2092 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2093 ret = -3;
2095 /* May need to check/upload firmware & data here!
2096 * If fails, continue with alt-ioc processing
2098 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2099 ret = -4;
2100 // NEW!
2101 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2102 printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
2103 ioc->alt_ioc->name, rc);
2104 alt_ioc_ready = 0;
2105 reset_alt_ioc_active = 0;
2108 if (alt_ioc_ready) {
2109 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2110 alt_ioc_ready = 0;
2111 reset_alt_ioc_active = 0;
2112 printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
2113 ioc->alt_ioc->name, rc);
2117 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2118 if (ioc->upload_fw) {
2119 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2120 "firmware upload required!\n", ioc->name));
2122 /* Controller is not operational, cannot do upload
2124 if (ret == 0) {
2125 rc = mpt_do_upload(ioc, sleepFlag);
2126 if (rc == 0) {
2127 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2129 * Maintain only one pointer to FW memory
2130 * so there will not be two attempt to
2131 * downloadboot onboard dual function
2132 * chips (mpt_adapter_disable,
2133 * mpt_diag_reset)
2135 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2136 "mpt_upload: alt_%s has cached_fw=%p \n",
2137 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2138 ioc->cached_fw = NULL;
2140 } else {
2141 printk(MYIOC_s_WARN_FMT
2142 "firmware upload failure!\n", ioc->name);
2143 ret = -6;
2149 if (ret == 0) {
2150 /* Enable! (reply interrupt) */
2151 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2152 ioc->active = 1;
2155 if (reset_alt_ioc_active && ioc->alt_ioc) {
2156 /* (re)Enable alt-IOC! (reply interrupt) */
2157 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
2158 ioc->alt_ioc->name));
2159 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2160 ioc->alt_ioc->active = 1;
2163 /* Enable MPT base driver management of EventNotification
2164 * and EventAck handling.
2166 if ((ret == 0) && (!ioc->facts.EventState))
2167 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
2169 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2170 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
2172 /* Add additional "reason" check before call to GetLanConfigPages
2173 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2174 * recursive scenario; GetLanConfigPages times out, timer expired
2175 * routine calls HardResetHandler, which calls into here again,
2176 * and we try GetLanConfigPages again...
2178 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2181 * Initalize link list for inactive raid volumes.
2183 mutex_init(&ioc->raid_data.inactive_list_mutex);
2184 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2186 if (ioc->bus_type == SAS) {
2188 /* clear persistency table */
2189 if(ioc->facts.IOCExceptions &
2190 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2191 ret = mptbase_sas_persist_operation(ioc,
2192 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2193 if(ret != 0)
2194 goto out;
2197 /* Find IM volumes
2199 mpt_findImVolumes(ioc);
2201 } else if (ioc->bus_type == FC) {
2202 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
2203 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2205 * Pre-fetch the ports LAN MAC address!
2206 * (LANPage1_t stuff)
2208 (void) GetLanConfigPages(ioc);
2209 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2210 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2211 "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2212 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
2215 } else {
2216 /* Get NVRAM and adapter maximums from SPP 0 and 2
2218 mpt_GetScsiPortSettings(ioc, 0);
2220 /* Get version and length of SDP 1
2222 mpt_readScsiDevicePageHeaders(ioc, 0);
2224 /* Find IM volumes
2226 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2227 mpt_findImVolumes(ioc);
2229 /* Check, and possibly reset, the coalescing value
2231 mpt_read_ioc_pg_1(ioc);
2233 mpt_read_ioc_pg_4(ioc);
2236 GetIoUnitPage2(ioc);
2237 mpt_get_manufacturing_pg_0(ioc);
2241 * Call each currently registered protocol IOC reset handler
2242 * with post-reset indication.
2243 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2244 * MptResetHandlers[] registered yet.
2246 if (hard_reset_done) {
2247 rc = handlers = 0;
2248 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2249 if ((ret == 0) && MptResetHandlers[cb_idx]) {
2250 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2251 "Calling IOC post_reset handler #%d\n",
2252 ioc->name, cb_idx));
2253 rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2254 handlers++;
2257 if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2258 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2259 "Calling IOC post_reset handler #%d\n",
2260 ioc->alt_ioc->name, cb_idx));
2261 rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2262 handlers++;
2265 /* FIXME? Examine results here? */
2268 out:
2269 if ((ret != 0) && irq_allocated) {
2270 free_irq(ioc->pci_irq, ioc);
2271 if (ioc->msi_enable)
2272 pci_disable_msi(ioc->pcidev);
2274 return ret;
2277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2279 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2280 * @ioc: Pointer to MPT adapter structure
2281 * @pdev: Pointer to (struct pci_dev) structure
2283 * Search for PCI bus/dev_function which matches
2284 * PCI bus/dev_function (+/-1) for newly discovered 929,
2285 * 929X, 1030 or 1035.
2287 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2288 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2290 static void
2291 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2293 struct pci_dev *peer=NULL;
2294 unsigned int slot = PCI_SLOT(pdev->devfn);
2295 unsigned int func = PCI_FUNC(pdev->devfn);
2296 MPT_ADAPTER *ioc_srch;
2298 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2299 " searching for devfn match on %x or %x\n",
2300 ioc->name, pci_name(pdev), pdev->bus->number,
2301 pdev->devfn, func-1, func+1));
2303 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2304 if (!peer) {
2305 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2306 if (!peer)
2307 return;
2310 list_for_each_entry(ioc_srch, &ioc_list, list) {
2311 struct pci_dev *_pcidev = ioc_srch->pcidev;
2312 if (_pcidev == peer) {
2313 /* Paranoia checks */
2314 if (ioc->alt_ioc != NULL) {
2315 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2316 ioc->name, ioc->alt_ioc->name);
2317 break;
2318 } else if (ioc_srch->alt_ioc != NULL) {
2319 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2320 ioc_srch->name, ioc_srch->alt_ioc->name);
2321 break;
2323 dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
2324 ioc->name, ioc_srch->name));
2325 ioc_srch->alt_ioc = ioc;
2326 ioc->alt_ioc = ioc_srch;
2329 pci_dev_put(peer);
2332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2334 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2335 * @ioc: Pointer to MPT adapter structure
2337 static void
2338 mpt_adapter_disable(MPT_ADAPTER *ioc)
2340 int sz;
2341 int ret;
2343 if (ioc->cached_fw != NULL) {
2344 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2345 "adapter\n", __FUNCTION__, ioc->name));
2346 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2347 ioc->cached_fw, CAN_SLEEP)) < 0) {
2348 printk(MYIOC_s_WARN_FMT
2349 ": firmware downloadboot failure (%d)!\n",
2350 ioc->name, ret);
2354 /* Disable adapter interrupts! */
2355 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2356 ioc->active = 0;
2357 /* Clear any lingering interrupt */
2358 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2360 if (ioc->alloc != NULL) {
2361 sz = ioc->alloc_sz;
2362 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2363 ioc->name, ioc->alloc, ioc->alloc_sz));
2364 pci_free_consistent(ioc->pcidev, sz,
2365 ioc->alloc, ioc->alloc_dma);
2366 ioc->reply_frames = NULL;
2367 ioc->req_frames = NULL;
2368 ioc->alloc = NULL;
2369 ioc->alloc_total -= sz;
2372 if (ioc->sense_buf_pool != NULL) {
2373 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2374 pci_free_consistent(ioc->pcidev, sz,
2375 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2376 ioc->sense_buf_pool = NULL;
2377 ioc->alloc_total -= sz;
2380 if (ioc->events != NULL){
2381 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2382 kfree(ioc->events);
2383 ioc->events = NULL;
2384 ioc->alloc_total -= sz;
2387 mpt_free_fw_memory(ioc);
2389 kfree(ioc->spi_data.nvram);
2390 mpt_inactive_raid_list_free(ioc);
2391 kfree(ioc->raid_data.pIocPg2);
2392 kfree(ioc->raid_data.pIocPg3);
2393 ioc->spi_data.nvram = NULL;
2394 ioc->raid_data.pIocPg3 = NULL;
2396 if (ioc->spi_data.pIocPg4 != NULL) {
2397 sz = ioc->spi_data.IocPg4Sz;
2398 pci_free_consistent(ioc->pcidev, sz,
2399 ioc->spi_data.pIocPg4,
2400 ioc->spi_data.IocPg4_dma);
2401 ioc->spi_data.pIocPg4 = NULL;
2402 ioc->alloc_total -= sz;
2405 if (ioc->ReqToChain != NULL) {
2406 kfree(ioc->ReqToChain);
2407 kfree(ioc->RequestNB);
2408 ioc->ReqToChain = NULL;
2411 kfree(ioc->ChainToChain);
2412 ioc->ChainToChain = NULL;
2414 if (ioc->HostPageBuffer != NULL) {
2415 if((ret = mpt_host_page_access_control(ioc,
2416 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2417 printk(MYIOC_s_ERR_FMT
2418 "host page buffers free failed (%d)!\n",
2419 ioc->name, ret);
2421 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n",
2422 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2423 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2424 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2425 ioc->HostPageBuffer = NULL;
2426 ioc->HostPageBuffer_sz = 0;
2427 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2431 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2433 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2434 * @ioc: Pointer to MPT adapter structure
2436 * This routine unregisters h/w resources and frees all alloc'd memory
2437 * associated with a MPT adapter structure.
2439 static void
2440 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2442 int sz_first, sz_last;
2444 if (ioc == NULL)
2445 return;
2447 sz_first = ioc->alloc_total;
2449 mpt_adapter_disable(ioc);
2451 if (ioc->pci_irq != -1) {
2452 free_irq(ioc->pci_irq, ioc);
2453 if (ioc->msi_enable)
2454 pci_disable_msi(ioc->pcidev);
2455 ioc->pci_irq = -1;
2458 if (ioc->memmap != NULL) {
2459 iounmap(ioc->memmap);
2460 ioc->memmap = NULL;
2463 pci_disable_device(ioc->pcidev);
2464 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2466 #if defined(CONFIG_MTRR) && 0
2467 if (ioc->mtrr_reg > 0) {
2468 mtrr_del(ioc->mtrr_reg, 0, 0);
2469 dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2471 #endif
2473 /* Zap the adapter lookup ptr! */
2474 list_del(&ioc->list);
2476 sz_last = ioc->alloc_total;
2477 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2478 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2480 if (ioc->alt_ioc)
2481 ioc->alt_ioc->alt_ioc = NULL;
2483 kfree(ioc);
2486 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2488 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2489 * @ioc: Pointer to MPT adapter structure
2491 static void
2492 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2494 int i = 0;
2496 printk(KERN_INFO "%s: ", ioc->name);
2497 if (ioc->prod_name)
2498 printk("%s: ", ioc->prod_name);
2499 printk("Capabilities={");
2501 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2502 printk("Initiator");
2503 i++;
2506 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2507 printk("%sTarget", i ? "," : "");
2508 i++;
2511 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2512 printk("%sLAN", i ? "," : "");
2513 i++;
2516 #if 0
2518 * This would probably evoke more questions than it's worth
2520 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2521 printk("%sLogBusAddr", i ? "," : "");
2522 i++;
2524 #endif
2526 printk("}\n");
2529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2531 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2532 * @ioc: Pointer to MPT_ADAPTER structure
2533 * @force: Force hard KickStart of IOC
2534 * @sleepFlag: Specifies whether the process can sleep
2536 * Returns:
2537 * 1 - DIAG reset and READY
2538 * 0 - READY initially OR soft reset and READY
2539 * -1 - Any failure on KickStart
2540 * -2 - Msg Unit Reset Failed
2541 * -3 - IO Unit Reset Failed
2542 * -4 - IOC owned by a PEER
2544 static int
2545 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2547 u32 ioc_state;
2548 int statefault = 0;
2549 int cntdn;
2550 int hard_reset_done = 0;
2551 int r;
2552 int ii;
2553 int whoinit;
2555 /* Get current [raw] IOC state */
2556 ioc_state = mpt_GetIocState(ioc, 0);
2557 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2560 * Check to see if IOC got left/stuck in doorbell handshake
2561 * grip of death. If so, hard reset the IOC.
2563 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2564 statefault = 1;
2565 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2566 ioc->name);
2569 /* Is it already READY? */
2570 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2571 return 0;
2574 * Check to see if IOC is in FAULT state.
2576 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2577 statefault = 2;
2578 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2579 ioc->name);
2580 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2581 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2585 * Hmmm... Did it get left operational?
2587 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2588 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2589 ioc->name));
2591 /* Check WhoInit.
2592 * If PCI Peer, exit.
2593 * Else, if no fault conditions are present, issue a MessageUnitReset
2594 * Else, fall through to KickStart case
2596 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2597 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2598 "whoinit 0x%x statefault %d force %d\n",
2599 ioc->name, whoinit, statefault, force));
2600 if (whoinit == MPI_WHOINIT_PCI_PEER)
2601 return -4;
2602 else {
2603 if ((statefault == 0 ) && (force == 0)) {
2604 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2605 return 0;
2607 statefault = 3;
2611 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2612 if (hard_reset_done < 0)
2613 return -1;
2616 * Loop here waiting for IOC to come READY.
2618 ii = 0;
2619 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2621 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2622 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2624 * BIOS or previous driver load left IOC in OP state.
2625 * Reset messaging FIFOs.
2627 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2628 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2629 return -2;
2631 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2633 * Something is wrong. Try to get IOC back
2634 * to a known state.
2636 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2637 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2638 return -3;
2642 ii++; cntdn--;
2643 if (!cntdn) {
2644 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2645 ioc->name, (int)((ii+5)/HZ));
2646 return -ETIME;
2649 if (sleepFlag == CAN_SLEEP) {
2650 msleep(1);
2651 } else {
2652 mdelay (1); /* 1 msec delay */
2657 if (statefault < 3) {
2658 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2659 ioc->name,
2660 statefault==1 ? "stuck handshake" : "IOC FAULT");
2663 return hard_reset_done;
2666 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2668 * mpt_GetIocState - Get the current state of a MPT adapter.
2669 * @ioc: Pointer to MPT_ADAPTER structure
2670 * @cooked: Request raw or cooked IOC state
2672 * Returns all IOC Doorbell register bits if cooked==0, else just the
2673 * Doorbell bits in MPI_IOC_STATE_MASK.
2676 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2678 u32 s, sc;
2680 /* Get! */
2681 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2682 sc = s & MPI_IOC_STATE_MASK;
2684 /* Save! */
2685 ioc->last_state = sc;
2687 return cooked ? sc : s;
2690 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2692 * GetIocFacts - Send IOCFacts request to MPT adapter.
2693 * @ioc: Pointer to MPT_ADAPTER structure
2694 * @sleepFlag: Specifies whether the process can sleep
2695 * @reason: If recovery, only update facts.
2697 * Returns 0 for success, non-zero for failure.
2699 static int
2700 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2702 IOCFacts_t get_facts;
2703 IOCFactsReply_t *facts;
2704 int r;
2705 int req_sz;
2706 int reply_sz;
2707 int sz;
2708 u32 status, vv;
2709 u8 shiftFactor=1;
2711 /* IOC *must* NOT be in RESET state! */
2712 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2713 printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
2714 ioc->name, ioc->last_state );
2715 return -44;
2718 facts = &ioc->facts;
2720 /* Destination (reply area)... */
2721 reply_sz = sizeof(*facts);
2722 memset(facts, 0, reply_sz);
2724 /* Request area (get_facts on the stack right now!) */
2725 req_sz = sizeof(get_facts);
2726 memset(&get_facts, 0, req_sz);
2728 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2729 /* Assert: All other get_facts fields are zero! */
2731 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2732 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2733 ioc->name, req_sz, reply_sz));
2735 /* No non-zero fields in the get_facts request are greater than
2736 * 1 byte in size, so we can just fire it off as is.
2738 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2739 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2740 if (r != 0)
2741 return r;
2744 * Now byte swap (GRRR) the necessary fields before any further
2745 * inspection of reply contents.
2747 * But need to do some sanity checks on MsgLength (byte) field
2748 * to make sure we don't zero IOC's req_sz!
2750 /* Did we get a valid reply? */
2751 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2752 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2754 * If not been here, done that, save off first WhoInit value
2756 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2757 ioc->FirstWhoInit = facts->WhoInit;
2760 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2761 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2762 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2763 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2764 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2765 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2766 /* CHECKME! IOCStatus, IOCLogInfo */
2768 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2769 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2772 * FC f/w version changed between 1.1 and 1.2
2773 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2774 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2776 if (facts->MsgVersion < 0x0102) {
2778 * Handle old FC f/w style, convert to new...
2780 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2781 facts->FWVersion.Word =
2782 ((oldv<<12) & 0xFF000000) |
2783 ((oldv<<8) & 0x000FFF00);
2784 } else
2785 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2787 facts->ProductID = le16_to_cpu(facts->ProductID);
2788 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2789 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
2790 ioc->ir_firmware = 1;
2791 facts->CurrentHostMfaHighAddr =
2792 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2793 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2794 facts->CurrentSenseBufferHighAddr =
2795 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2796 facts->CurReplyFrameSize =
2797 le16_to_cpu(facts->CurReplyFrameSize);
2798 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2801 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2802 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2803 * to 14 in MPI-1.01.0x.
2805 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2806 facts->MsgVersion > 0x0100) {
2807 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2810 sz = facts->FWImageSize;
2811 if ( sz & 0x01 )
2812 sz += 1;
2813 if ( sz & 0x02 )
2814 sz += 2;
2815 facts->FWImageSize = sz;
2817 if (!facts->RequestFrameSize) {
2818 /* Something is wrong! */
2819 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2820 ioc->name);
2821 return -55;
2824 r = sz = facts->BlockSize;
2825 vv = ((63 / (sz * 4)) + 1) & 0x03;
2826 ioc->NB_for_64_byte_frame = vv;
2827 while ( sz )
2829 shiftFactor++;
2830 sz = sz >> 1;
2832 ioc->NBShiftFactor = shiftFactor;
2833 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2834 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2835 ioc->name, vv, shiftFactor, r));
2837 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2839 * Set values for this IOC's request & reply frame sizes,
2840 * and request & reply queue depths...
2842 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2843 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2844 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2845 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2847 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
2848 ioc->name, ioc->reply_sz, ioc->reply_depth));
2849 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
2850 ioc->name, ioc->req_sz, ioc->req_depth));
2852 /* Get port facts! */
2853 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2854 return r;
2856 } else {
2857 printk(MYIOC_s_ERR_FMT
2858 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2859 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2860 RequestFrameSize)/sizeof(u32)));
2861 return -66;
2864 return 0;
2867 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2869 * GetPortFacts - Send PortFacts request to MPT adapter.
2870 * @ioc: Pointer to MPT_ADAPTER structure
2871 * @portnum: Port number
2872 * @sleepFlag: Specifies whether the process can sleep
2874 * Returns 0 for success, non-zero for failure.
2876 static int
2877 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2879 PortFacts_t get_pfacts;
2880 PortFactsReply_t *pfacts;
2881 int ii;
2882 int req_sz;
2883 int reply_sz;
2884 int max_id;
2886 /* IOC *must* NOT be in RESET state! */
2887 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2888 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
2889 ioc->name, ioc->last_state );
2890 return -4;
2893 pfacts = &ioc->pfacts[portnum];
2895 /* Destination (reply area)... */
2896 reply_sz = sizeof(*pfacts);
2897 memset(pfacts, 0, reply_sz);
2899 /* Request area (get_pfacts on the stack right now!) */
2900 req_sz = sizeof(get_pfacts);
2901 memset(&get_pfacts, 0, req_sz);
2903 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2904 get_pfacts.PortNumber = portnum;
2905 /* Assert: All other get_pfacts fields are zero! */
2907 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
2908 ioc->name, portnum));
2910 /* No non-zero fields in the get_pfacts request are greater than
2911 * 1 byte in size, so we can just fire it off as is.
2913 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2914 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2915 if (ii != 0)
2916 return ii;
2918 /* Did we get a valid reply? */
2920 /* Now byte swap the necessary fields in the response. */
2921 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2922 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2923 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2924 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2925 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2926 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2927 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2928 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2929 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2931 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
2932 pfacts->MaxDevices;
2933 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
2934 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
2937 * Place all the devices on channels
2939 * (for debuging)
2941 if (mpt_channel_mapping) {
2942 ioc->devices_per_bus = 1;
2943 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
2946 return 0;
2949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2951 * SendIocInit - Send IOCInit request to MPT adapter.
2952 * @ioc: Pointer to MPT_ADAPTER structure
2953 * @sleepFlag: Specifies whether the process can sleep
2955 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2957 * Returns 0 for success, non-zero for failure.
2959 static int
2960 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2962 IOCInit_t ioc_init;
2963 MPIDefaultReply_t init_reply;
2964 u32 state;
2965 int r;
2966 int count;
2967 int cntdn;
2969 memset(&ioc_init, 0, sizeof(ioc_init));
2970 memset(&init_reply, 0, sizeof(init_reply));
2972 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2973 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2975 /* If we are in a recovery mode and we uploaded the FW image,
2976 * then this pointer is not NULL. Skip the upload a second time.
2977 * Set this flag if cached_fw set for either IOC.
2979 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2980 ioc->upload_fw = 1;
2981 else
2982 ioc->upload_fw = 0;
2983 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
2984 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2986 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
2987 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
2988 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
2989 ioc->name, ioc->facts.MsgVersion));
2990 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2991 // set MsgVersion and HeaderVersion host driver was built with
2992 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2993 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2995 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2996 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2997 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2998 return -99;
3000 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3002 if (sizeof(dma_addr_t) == sizeof(u64)) {
3003 /* Save the upper 32-bits of the request
3004 * (reply) and sense buffers.
3006 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3007 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3008 } else {
3009 /* Force 32-bit addressing */
3010 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3011 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3014 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3015 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3016 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3017 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3019 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3020 ioc->name, &ioc_init));
3022 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3023 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3024 if (r != 0) {
3025 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3026 return r;
3029 /* No need to byte swap the multibyte fields in the reply
3030 * since we don't even look at its contents.
3033 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3034 ioc->name, &ioc_init));
3036 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3037 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3038 return r;
3041 /* YIKES! SUPER IMPORTANT!!!
3042 * Poll IocState until _OPERATIONAL while IOC is doing
3043 * LoopInit and TargetDiscovery!
3045 count = 0;
3046 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3047 state = mpt_GetIocState(ioc, 1);
3048 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3049 if (sleepFlag == CAN_SLEEP) {
3050 msleep(1);
3051 } else {
3052 mdelay(1);
3055 if (!cntdn) {
3056 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3057 ioc->name, (int)((count+5)/HZ));
3058 return -9;
3061 state = mpt_GetIocState(ioc, 1);
3062 count++;
3064 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3065 ioc->name, count));
3067 ioc->aen_event_read_flag=0;
3068 return r;
3071 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3073 * SendPortEnable - Send PortEnable request to MPT adapter port.
3074 * @ioc: Pointer to MPT_ADAPTER structure
3075 * @portnum: Port number to enable
3076 * @sleepFlag: Specifies whether the process can sleep
3078 * Send PortEnable to bring IOC to OPERATIONAL state.
3080 * Returns 0 for success, non-zero for failure.
3082 static int
3083 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3085 PortEnable_t port_enable;
3086 MPIDefaultReply_t reply_buf;
3087 int rc;
3088 int req_sz;
3089 int reply_sz;
3091 /* Destination... */
3092 reply_sz = sizeof(MPIDefaultReply_t);
3093 memset(&reply_buf, 0, reply_sz);
3095 req_sz = sizeof(PortEnable_t);
3096 memset(&port_enable, 0, req_sz);
3098 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3099 port_enable.PortNumber = portnum;
3100 /* port_enable.ChainOffset = 0; */
3101 /* port_enable.MsgFlags = 0; */
3102 /* port_enable.MsgContext = 0; */
3104 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3105 ioc->name, portnum, &port_enable));
3107 /* RAID FW may take a long time to enable
3109 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3110 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3111 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3112 300 /*seconds*/, sleepFlag);
3113 } else {
3114 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3115 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3116 30 /*seconds*/, sleepFlag);
3118 return rc;
3122 * mpt_alloc_fw_memory - allocate firmware memory
3123 * @ioc: Pointer to MPT_ADAPTER structure
3124 * @size: total FW bytes
3126 * If memory has already been allocated, the same (cached) value
3127 * is returned.
3129 * Return 0 if successfull, or non-zero for failure
3132 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3134 int rc;
3136 if (ioc->cached_fw) {
3137 rc = 0; /* use already allocated memory */
3138 goto out;
3140 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3141 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3142 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3143 rc = 0;
3144 goto out;
3146 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3147 if (!ioc->cached_fw) {
3148 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3149 ioc->name);
3150 rc = -1;
3151 } else {
3152 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3153 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3154 ioc->alloc_total += size;
3155 rc = 0;
3157 out:
3158 return rc;
3162 * mpt_free_fw_memory - free firmware memory
3163 * @ioc: Pointer to MPT_ADAPTER structure
3165 * If alt_img is NULL, delete from ioc structure.
3166 * Else, delete a secondary image in same format.
3168 void
3169 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3171 int sz;
3173 if (!ioc->cached_fw)
3174 return;
3176 sz = ioc->facts.FWImageSize;
3177 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3178 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3179 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3180 ioc->alloc_total -= sz;
3181 ioc->cached_fw = NULL;
3184 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3186 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3187 * @ioc: Pointer to MPT_ADAPTER structure
3188 * @sleepFlag: Specifies whether the process can sleep
3190 * Returns 0 for success, >0 for handshake failure
3191 * <0 for fw upload failure.
3193 * Remark: If bound IOC and a successful FWUpload was performed
3194 * on the bound IOC, the second image is discarded
3195 * and memory is free'd. Both channels must upload to prevent
3196 * IOC from running in degraded mode.
3198 static int
3199 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3201 u8 reply[sizeof(FWUploadReply_t)];
3202 FWUpload_t *prequest;
3203 FWUploadReply_t *preply;
3204 FWUploadTCSGE_t *ptcsge;
3205 int sgeoffset;
3206 u32 flagsLength;
3207 int ii, sz, reply_sz;
3208 int cmdStatus;
3210 /* If the image size is 0, we are done.
3212 if ((sz = ioc->facts.FWImageSize) == 0)
3213 return 0;
3215 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3216 return -ENOMEM;
3218 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3219 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3221 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3222 kzalloc(ioc->req_sz, GFP_KERNEL);
3223 if (!prequest) {
3224 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3225 "while allocating memory \n", ioc->name));
3226 mpt_free_fw_memory(ioc);
3227 return -ENOMEM;
3230 preply = (FWUploadReply_t *)&reply;
3232 reply_sz = sizeof(reply);
3233 memset(preply, 0, reply_sz);
3235 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3236 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3238 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3239 ptcsge->DetailsLength = 12;
3240 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3241 ptcsge->ImageSize = cpu_to_le32(sz);
3242 ptcsge++;
3244 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
3246 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3247 mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3249 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
3250 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3251 ioc->name, prequest, sgeoffset));
3252 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3254 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
3255 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3257 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
3259 cmdStatus = -EFAULT;
3260 if (ii == 0) {
3261 /* Handshake transfer was complete and successful.
3262 * Check the Reply Frame.
3264 int status, transfer_sz;
3265 status = le16_to_cpu(preply->IOCStatus);
3266 if (status == MPI_IOCSTATUS_SUCCESS) {
3267 transfer_sz = le32_to_cpu(preply->ActualImageSize);
3268 if (transfer_sz == sz)
3269 cmdStatus = 0;
3272 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3273 ioc->name, cmdStatus));
3276 if (cmdStatus) {
3278 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
3279 ioc->name));
3280 mpt_free_fw_memory(ioc);
3282 kfree(prequest);
3284 return cmdStatus;
3287 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3289 * mpt_downloadboot - DownloadBoot code
3290 * @ioc: Pointer to MPT_ADAPTER structure
3291 * @pFwHeader: Pointer to firmware header info
3292 * @sleepFlag: Specifies whether the process can sleep
3294 * FwDownloadBoot requires Programmed IO access.
3296 * Returns 0 for success
3297 * -1 FW Image size is 0
3298 * -2 No valid cached_fw Pointer
3299 * <0 for fw upload failure.
3301 static int
3302 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3304 MpiExtImageHeader_t *pExtImage;
3305 u32 fwSize;
3306 u32 diag0val;
3307 int count;
3308 u32 *ptrFw;
3309 u32 diagRwData;
3310 u32 nextImage;
3311 u32 load_addr;
3312 u32 ioc_state=0;
3314 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3315 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3317 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3318 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3319 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3320 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3321 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3322 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3324 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3326 /* wait 1 msec */
3327 if (sleepFlag == CAN_SLEEP) {
3328 msleep(1);
3329 } else {
3330 mdelay (1);
3333 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3334 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3336 for (count = 0; count < 30; count ++) {
3337 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3338 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3339 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3340 ioc->name, count));
3341 break;
3343 /* wait .1 sec */
3344 if (sleepFlag == CAN_SLEEP) {
3345 msleep (100);
3346 } else {
3347 mdelay (100);
3351 if ( count == 30 ) {
3352 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3353 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3354 ioc->name, diag0val));
3355 return -3;
3358 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3359 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3360 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3361 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3362 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3363 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3365 /* Set the DiagRwEn and Disable ARM bits */
3366 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3368 fwSize = (pFwHeader->ImageSize + 3)/4;
3369 ptrFw = (u32 *) pFwHeader;
3371 /* Write the LoadStartAddress to the DiagRw Address Register
3372 * using Programmed IO
3374 if (ioc->errata_flag_1064)
3375 pci_enable_io_access(ioc->pcidev);
3377 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3378 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3379 ioc->name, pFwHeader->LoadStartAddress));
3381 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3382 ioc->name, fwSize*4, ptrFw));
3383 while (fwSize--) {
3384 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3387 nextImage = pFwHeader->NextImageHeaderOffset;
3388 while (nextImage) {
3389 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3391 load_addr = pExtImage->LoadStartAddress;
3393 fwSize = (pExtImage->ImageSize + 3) >> 2;
3394 ptrFw = (u32 *)pExtImage;
3396 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3397 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3398 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3400 while (fwSize--) {
3401 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3403 nextImage = pExtImage->NextImageHeaderOffset;
3406 /* Write the IopResetVectorRegAddr */
3407 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3408 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3410 /* Write the IopResetVectorValue */
3411 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3412 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3414 /* Clear the internal flash bad bit - autoincrementing register,
3415 * so must do two writes.
3417 if (ioc->bus_type == SPI) {
3419 * 1030 and 1035 H/W errata, workaround to access
3420 * the ClearFlashBadSignatureBit
3422 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3423 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3424 diagRwData |= 0x40000000;
3425 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3426 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3428 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3429 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3430 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3431 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3433 /* wait 1 msec */
3434 if (sleepFlag == CAN_SLEEP) {
3435 msleep (1);
3436 } else {
3437 mdelay (1);
3441 if (ioc->errata_flag_1064)
3442 pci_disable_io_access(ioc->pcidev);
3444 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3445 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3446 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3447 ioc->name, diag0val));
3448 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3449 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3450 ioc->name, diag0val));
3451 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3453 /* Write 0xFF to reset the sequencer */
3454 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3456 if (ioc->bus_type == SAS) {
3457 ioc_state = mpt_GetIocState(ioc, 0);
3458 if ( (GetIocFacts(ioc, sleepFlag,
3459 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3460 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3461 ioc->name, ioc_state));
3462 return -EFAULT;
3466 for (count=0; count<HZ*20; count++) {
3467 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3468 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3469 "downloadboot successful! (count=%d) IocState=%x\n",
3470 ioc->name, count, ioc_state));
3471 if (ioc->bus_type == SAS) {
3472 return 0;
3474 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3475 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3476 "downloadboot: SendIocInit failed\n",
3477 ioc->name));
3478 return -EFAULT;
3480 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3481 "downloadboot: SendIocInit successful\n",
3482 ioc->name));
3483 return 0;
3485 if (sleepFlag == CAN_SLEEP) {
3486 msleep (10);
3487 } else {
3488 mdelay (10);
3491 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3492 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3493 return -EFAULT;
3496 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3498 * KickStart - Perform hard reset of MPT adapter.
3499 * @ioc: Pointer to MPT_ADAPTER structure
3500 * @force: Force hard reset
3501 * @sleepFlag: Specifies whether the process can sleep
3503 * This routine places MPT adapter in diagnostic mode via the
3504 * WriteSequence register, and then performs a hard reset of adapter
3505 * via the Diagnostic register.
3507 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3508 * or NO_SLEEP (interrupt thread, use mdelay)
3509 * force - 1 if doorbell active, board fault state
3510 * board operational, IOC_RECOVERY or
3511 * IOC_BRINGUP and there is an alt_ioc.
3512 * 0 else
3514 * Returns:
3515 * 1 - hard reset, READY
3516 * 0 - no reset due to History bit, READY
3517 * -1 - no reset due to History bit but not READY
3518 * OR reset but failed to come READY
3519 * -2 - no reset, could not enter DIAG mode
3520 * -3 - reset but bad FW bit
3522 static int
3523 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3525 int hard_reset_done = 0;
3526 u32 ioc_state=0;
3527 int cnt,cntdn;
3529 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3530 if (ioc->bus_type == SPI) {
3531 /* Always issue a Msg Unit Reset first. This will clear some
3532 * SCSI bus hang conditions.
3534 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3536 if (sleepFlag == CAN_SLEEP) {
3537 msleep (1000);
3538 } else {
3539 mdelay (1000);
3543 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3544 if (hard_reset_done < 0)
3545 return hard_reset_done;
3547 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3548 ioc->name));
3550 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3551 for (cnt=0; cnt<cntdn; cnt++) {
3552 ioc_state = mpt_GetIocState(ioc, 1);
3553 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3554 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3555 ioc->name, cnt));
3556 return hard_reset_done;
3558 if (sleepFlag == CAN_SLEEP) {
3559 msleep (10);
3560 } else {
3561 mdelay (10);
3565 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3566 ioc->name, mpt_GetIocState(ioc, 0)));
3567 return -1;
3570 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3572 * mpt_diag_reset - Perform hard reset of the adapter.
3573 * @ioc: Pointer to MPT_ADAPTER structure
3574 * @ignore: Set if to honor and clear to ignore
3575 * the reset history bit
3576 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3577 * else set to NO_SLEEP (use mdelay instead)
3579 * This routine places the adapter in diagnostic mode via the
3580 * WriteSequence register and then performs a hard reset of adapter
3581 * via the Diagnostic register. Adapter should be in ready state
3582 * upon successful completion.
3584 * Returns: 1 hard reset successful
3585 * 0 no reset performed because reset history bit set
3586 * -2 enabling diagnostic mode failed
3587 * -3 diagnostic reset failed
3589 static int
3590 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3592 u32 diag0val;
3593 u32 doorbell;
3594 int hard_reset_done = 0;
3595 int count = 0;
3596 u32 diag1val = 0;
3597 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3599 /* Clear any existing interrupts */
3600 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3602 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3603 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3604 "address=%p\n", ioc->name, __FUNCTION__,
3605 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3606 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3607 if (sleepFlag == CAN_SLEEP)
3608 msleep(1);
3609 else
3610 mdelay(1);
3612 for (count = 0; count < 60; count ++) {
3613 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3614 doorbell &= MPI_IOC_STATE_MASK;
3616 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3617 "looking for READY STATE: doorbell=%x"
3618 " count=%d\n",
3619 ioc->name, doorbell, count));
3620 if (doorbell == MPI_IOC_STATE_READY) {
3621 return 1;
3624 /* wait 1 sec */
3625 if (sleepFlag == CAN_SLEEP)
3626 msleep(1000);
3627 else
3628 mdelay(1000);
3630 return -1;
3633 /* Use "Diagnostic reset" method! (only thing available!) */
3634 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3636 if (ioc->debug_level & MPT_DEBUG) {
3637 if (ioc->alt_ioc)
3638 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3639 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3640 ioc->name, diag0val, diag1val));
3643 /* Do the reset if we are told to ignore the reset history
3644 * or if the reset history is 0
3646 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3647 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3648 /* Write magic sequence to WriteSequence register
3649 * Loop until in diagnostic mode
3651 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3652 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3653 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3654 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3655 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3656 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3658 /* wait 100 msec */
3659 if (sleepFlag == CAN_SLEEP) {
3660 msleep (100);
3661 } else {
3662 mdelay (100);
3665 count++;
3666 if (count > 20) {
3667 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3668 ioc->name, diag0val);
3669 return -2;
3673 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3675 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3676 ioc->name, diag0val));
3679 if (ioc->debug_level & MPT_DEBUG) {
3680 if (ioc->alt_ioc)
3681 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3682 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3683 ioc->name, diag0val, diag1val));
3686 * Disable the ARM (Bug fix)
3689 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3690 mdelay(1);
3693 * Now hit the reset bit in the Diagnostic register
3694 * (THE BIG HAMMER!) (Clears DRWE bit).
3696 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3697 hard_reset_done = 1;
3698 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3699 ioc->name));
3702 * Call each currently registered protocol IOC reset handler
3703 * with pre-reset indication.
3704 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3705 * MptResetHandlers[] registered yet.
3708 u8 cb_idx;
3709 int r = 0;
3711 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3712 if (MptResetHandlers[cb_idx]) {
3713 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3714 "Calling IOC pre_reset handler #%d\n",
3715 ioc->name, cb_idx));
3716 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
3717 if (ioc->alt_ioc) {
3718 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3719 "Calling alt-%s pre_reset handler #%d\n",
3720 ioc->name, ioc->alt_ioc->name, cb_idx));
3721 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3725 /* FIXME? Examine results here? */
3728 if (ioc->cached_fw)
3729 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3730 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3731 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3732 else
3733 cached_fw = NULL;
3734 if (cached_fw) {
3735 /* If the DownloadBoot operation fails, the
3736 * IOC will be left unusable. This is a fatal error
3737 * case. _diag_reset will return < 0
3739 for (count = 0; count < 30; count ++) {
3740 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3741 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3742 break;
3745 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3746 ioc->name, diag0val, count));
3747 /* wait 1 sec */
3748 if (sleepFlag == CAN_SLEEP) {
3749 msleep (1000);
3750 } else {
3751 mdelay (1000);
3754 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3755 printk(MYIOC_s_WARN_FMT
3756 "firmware downloadboot failure (%d)!\n", ioc->name, count);
3759 } else {
3760 /* Wait for FW to reload and for board
3761 * to go to the READY state.
3762 * Maximum wait is 60 seconds.
3763 * If fail, no error will check again
3764 * with calling program.
3766 for (count = 0; count < 60; count ++) {
3767 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3768 doorbell &= MPI_IOC_STATE_MASK;
3770 if (doorbell == MPI_IOC_STATE_READY) {
3771 break;
3774 /* wait 1 sec */
3775 if (sleepFlag == CAN_SLEEP) {
3776 msleep (1000);
3777 } else {
3778 mdelay (1000);
3784 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3785 if (ioc->debug_level & MPT_DEBUG) {
3786 if (ioc->alt_ioc)
3787 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3788 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3789 ioc->name, diag0val, diag1val));
3792 /* Clear RESET_HISTORY bit! Place board in the
3793 * diagnostic mode to update the diag register.
3795 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3796 count = 0;
3797 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3798 /* Write magic sequence to WriteSequence register
3799 * Loop until in diagnostic mode
3801 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3802 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3803 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3804 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3805 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3806 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3808 /* wait 100 msec */
3809 if (sleepFlag == CAN_SLEEP) {
3810 msleep (100);
3811 } else {
3812 mdelay (100);
3815 count++;
3816 if (count > 20) {
3817 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3818 ioc->name, diag0val);
3819 break;
3821 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3823 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3824 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3825 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3826 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3827 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3828 ioc->name);
3831 /* Disable Diagnostic Mode
3833 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3835 /* Check FW reload status flags.
3837 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3838 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3839 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3840 ioc->name, diag0val);
3841 return -3;
3844 if (ioc->debug_level & MPT_DEBUG) {
3845 if (ioc->alt_ioc)
3846 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3847 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3848 ioc->name, diag0val, diag1val));
3852 * Reset flag that says we've enabled event notification
3854 ioc->facts.EventState = 0;
3856 if (ioc->alt_ioc)
3857 ioc->alt_ioc->facts.EventState = 0;
3859 return hard_reset_done;
3862 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3864 * SendIocReset - Send IOCReset request to MPT adapter.
3865 * @ioc: Pointer to MPT_ADAPTER structure
3866 * @reset_type: reset type, expected values are
3867 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3868 * @sleepFlag: Specifies whether the process can sleep
3870 * Send IOCReset request to the MPT adapter.
3872 * Returns 0 for success, non-zero for failure.
3874 static int
3875 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3877 int r;
3878 u32 state;
3879 int cntdn, count;
3881 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
3882 ioc->name, reset_type));
3883 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3884 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3885 return r;
3887 /* FW ACK'd request, wait for READY state
3889 count = 0;
3890 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3892 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3893 cntdn--;
3894 count++;
3895 if (!cntdn) {
3896 if (sleepFlag != CAN_SLEEP)
3897 count *= 10;
3899 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
3900 ioc->name, (int)((count+5)/HZ));
3901 return -ETIME;
3904 if (sleepFlag == CAN_SLEEP) {
3905 msleep(1);
3906 } else {
3907 mdelay (1); /* 1 msec delay */
3911 /* TODO!
3912 * Cleanup all event stuff for this IOC; re-issue EventNotification
3913 * request if needed.
3915 if (ioc->facts.Function)
3916 ioc->facts.EventState = 0;
3918 return 0;
3921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3923 * initChainBuffers - Allocate memory for and initialize chain buffers
3924 * @ioc: Pointer to MPT_ADAPTER structure
3926 * Allocates memory for and initializes chain buffers,
3927 * chain buffer control arrays and spinlock.
3929 static int
3930 initChainBuffers(MPT_ADAPTER *ioc)
3932 u8 *mem;
3933 int sz, ii, num_chain;
3934 int scale, num_sge, numSGE;
3936 /* ReqToChain size must equal the req_depth
3937 * index = req_idx
3939 if (ioc->ReqToChain == NULL) {
3940 sz = ioc->req_depth * sizeof(int);
3941 mem = kmalloc(sz, GFP_ATOMIC);
3942 if (mem == NULL)
3943 return -1;
3945 ioc->ReqToChain = (int *) mem;
3946 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
3947 ioc->name, mem, sz));
3948 mem = kmalloc(sz, GFP_ATOMIC);
3949 if (mem == NULL)
3950 return -1;
3952 ioc->RequestNB = (int *) mem;
3953 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
3954 ioc->name, mem, sz));
3956 for (ii = 0; ii < ioc->req_depth; ii++) {
3957 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3960 /* ChainToChain size must equal the total number
3961 * of chain buffers to be allocated.
3962 * index = chain_idx
3964 * Calculate the number of chain buffers needed(plus 1) per I/O
3965 * then multiply the maximum number of simultaneous cmds
3967 * num_sge = num sge in request frame + last chain buffer
3968 * scale = num sge per chain buffer if no chain element
3970 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3971 if (sizeof(dma_addr_t) == sizeof(u64))
3972 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3973 else
3974 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3976 if (sizeof(dma_addr_t) == sizeof(u64)) {
3977 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3978 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3979 } else {
3980 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3981 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3983 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
3984 ioc->name, num_sge, numSGE));
3986 if ( numSGE > MPT_SCSI_SG_DEPTH )
3987 numSGE = MPT_SCSI_SG_DEPTH;
3989 num_chain = 1;
3990 while (numSGE - num_sge > 0) {
3991 num_chain++;
3992 num_sge += (scale - 1);
3994 num_chain++;
3996 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
3997 ioc->name, numSGE, num_sge, num_chain));
3999 if (ioc->bus_type == SPI)
4000 num_chain *= MPT_SCSI_CAN_QUEUE;
4001 else
4002 num_chain *= MPT_FC_CAN_QUEUE;
4004 ioc->num_chain = num_chain;
4006 sz = num_chain * sizeof(int);
4007 if (ioc->ChainToChain == NULL) {
4008 mem = kmalloc(sz, GFP_ATOMIC);
4009 if (mem == NULL)
4010 return -1;
4012 ioc->ChainToChain = (int *) mem;
4013 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4014 ioc->name, mem, sz));
4015 } else {
4016 mem = (u8 *) ioc->ChainToChain;
4018 memset(mem, 0xFF, sz);
4019 return num_chain;
4022 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4024 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4025 * @ioc: Pointer to MPT_ADAPTER structure
4027 * This routine allocates memory for the MPT reply and request frame
4028 * pools (if necessary), and primes the IOC reply FIFO with
4029 * reply frames.
4031 * Returns 0 for success, non-zero for failure.
4033 static int
4034 PrimeIocFifos(MPT_ADAPTER *ioc)
4036 MPT_FRAME_HDR *mf;
4037 unsigned long flags;
4038 dma_addr_t alloc_dma;
4039 u8 *mem;
4040 int i, reply_sz, sz, total_size, num_chain;
4042 /* Prime reply FIFO... */
4044 if (ioc->reply_frames == NULL) {
4045 if ( (num_chain = initChainBuffers(ioc)) < 0)
4046 return -1;
4048 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4049 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4050 ioc->name, ioc->reply_sz, ioc->reply_depth));
4051 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4052 ioc->name, reply_sz, reply_sz));
4054 sz = (ioc->req_sz * ioc->req_depth);
4055 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4056 ioc->name, ioc->req_sz, ioc->req_depth));
4057 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4058 ioc->name, sz, sz));
4059 total_size += sz;
4061 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4062 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4063 ioc->name, ioc->req_sz, num_chain));
4064 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4065 ioc->name, sz, sz, num_chain));
4067 total_size += sz;
4068 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4069 if (mem == NULL) {
4070 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4071 ioc->name);
4072 goto out_fail;
4075 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4076 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4078 memset(mem, 0, total_size);
4079 ioc->alloc_total += total_size;
4080 ioc->alloc = mem;
4081 ioc->alloc_dma = alloc_dma;
4082 ioc->alloc_sz = total_size;
4083 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4084 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4086 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4087 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4089 alloc_dma += reply_sz;
4090 mem += reply_sz;
4092 /* Request FIFO - WE manage this! */
4094 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4095 ioc->req_frames_dma = alloc_dma;
4097 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4098 ioc->name, mem, (void *)(ulong)alloc_dma));
4100 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4102 #if defined(CONFIG_MTRR) && 0
4104 * Enable Write Combining MTRR for IOC's memory region.
4105 * (at least as much as we can; "size and base must be
4106 * multiples of 4 kiB"
4108 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4110 MTRR_TYPE_WRCOMB, 1);
4111 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4112 ioc->name, ioc->req_frames_dma, sz));
4113 #endif
4115 for (i = 0; i < ioc->req_depth; i++) {
4116 alloc_dma += ioc->req_sz;
4117 mem += ioc->req_sz;
4120 ioc->ChainBuffer = mem;
4121 ioc->ChainBufferDMA = alloc_dma;
4123 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4124 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4126 /* Initialize the free chain Q.
4129 INIT_LIST_HEAD(&ioc->FreeChainQ);
4131 /* Post the chain buffers to the FreeChainQ.
4133 mem = (u8 *)ioc->ChainBuffer;
4134 for (i=0; i < num_chain; i++) {
4135 mf = (MPT_FRAME_HDR *) mem;
4136 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4137 mem += ioc->req_sz;
4140 /* Initialize Request frames linked list
4142 alloc_dma = ioc->req_frames_dma;
4143 mem = (u8 *) ioc->req_frames;
4145 spin_lock_irqsave(&ioc->FreeQlock, flags);
4146 INIT_LIST_HEAD(&ioc->FreeQ);
4147 for (i = 0; i < ioc->req_depth; i++) {
4148 mf = (MPT_FRAME_HDR *) mem;
4150 /* Queue REQUESTs *internally*! */
4151 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4153 mem += ioc->req_sz;
4155 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4157 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4158 ioc->sense_buf_pool =
4159 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4160 if (ioc->sense_buf_pool == NULL) {
4161 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4162 ioc->name);
4163 goto out_fail;
4166 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4167 ioc->alloc_total += sz;
4168 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4169 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4173 /* Post Reply frames to FIFO
4175 alloc_dma = ioc->alloc_dma;
4176 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4177 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4179 for (i = 0; i < ioc->reply_depth; i++) {
4180 /* Write each address to the IOC! */
4181 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4182 alloc_dma += ioc->reply_sz;
4185 return 0;
4187 out_fail:
4188 if (ioc->alloc != NULL) {
4189 sz = ioc->alloc_sz;
4190 pci_free_consistent(ioc->pcidev,
4192 ioc->alloc, ioc->alloc_dma);
4193 ioc->reply_frames = NULL;
4194 ioc->req_frames = NULL;
4195 ioc->alloc_total -= sz;
4197 if (ioc->sense_buf_pool != NULL) {
4198 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4199 pci_free_consistent(ioc->pcidev,
4201 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4202 ioc->sense_buf_pool = NULL;
4204 return -1;
4207 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4209 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4210 * from IOC via doorbell handshake method.
4211 * @ioc: Pointer to MPT_ADAPTER structure
4212 * @reqBytes: Size of the request in bytes
4213 * @req: Pointer to MPT request frame
4214 * @replyBytes: Expected size of the reply in bytes
4215 * @u16reply: Pointer to area where reply should be written
4216 * @maxwait: Max wait time for a reply (in seconds)
4217 * @sleepFlag: Specifies whether the process can sleep
4219 * NOTES: It is the callers responsibility to byte-swap fields in the
4220 * request which are greater than 1 byte in size. It is also the
4221 * callers responsibility to byte-swap response fields which are
4222 * greater than 1 byte in size.
4224 * Returns 0 for success, non-zero for failure.
4226 static int
4227 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4228 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4230 MPIDefaultReply_t *mptReply;
4231 int failcnt = 0;
4232 int t;
4235 * Get ready to cache a handshake reply
4237 ioc->hs_reply_idx = 0;
4238 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4239 mptReply->MsgLength = 0;
4242 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4243 * then tell IOC that we want to handshake a request of N words.
4244 * (WRITE u32val to Doorbell reg).
4246 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4247 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4248 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4249 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4252 * Wait for IOC's doorbell handshake int
4254 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4255 failcnt++;
4257 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4258 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4260 /* Read doorbell and check for active bit */
4261 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4262 return -1;
4265 * Clear doorbell int (WRITE 0 to IntStatus reg),
4266 * then wait for IOC to ACKnowledge that it's ready for
4267 * our handshake request.
4269 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4270 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4271 failcnt++;
4273 if (!failcnt) {
4274 int ii;
4275 u8 *req_as_bytes = (u8 *) req;
4278 * Stuff request words via doorbell handshake,
4279 * with ACK from IOC for each.
4281 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4282 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4283 (req_as_bytes[(ii*4) + 1] << 8) |
4284 (req_as_bytes[(ii*4) + 2] << 16) |
4285 (req_as_bytes[(ii*4) + 3] << 24));
4287 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4288 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4289 failcnt++;
4292 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4293 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4295 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4296 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4299 * Wait for completion of doorbell handshake reply from the IOC
4301 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4302 failcnt++;
4304 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4305 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4308 * Copy out the cached reply...
4310 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4311 u16reply[ii] = ioc->hs_reply[ii];
4312 } else {
4313 return -99;
4316 return -failcnt;
4319 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4321 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4322 * @ioc: Pointer to MPT_ADAPTER structure
4323 * @howlong: How long to wait (in seconds)
4324 * @sleepFlag: Specifies whether the process can sleep
4326 * This routine waits (up to ~2 seconds max) for IOC doorbell
4327 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4328 * bit in its IntStatus register being clear.
4330 * Returns a negative value on failure, else wait loop count.
4332 static int
4333 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4335 int cntdn;
4336 int count = 0;
4337 u32 intstat=0;
4339 cntdn = 1000 * howlong;
4341 if (sleepFlag == CAN_SLEEP) {
4342 while (--cntdn) {
4343 msleep (1);
4344 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4345 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4346 break;
4347 count++;
4349 } else {
4350 while (--cntdn) {
4351 udelay (1000);
4352 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4353 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4354 break;
4355 count++;
4359 if (cntdn) {
4360 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4361 ioc->name, count));
4362 return count;
4365 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4366 ioc->name, count, intstat);
4367 return -1;
4370 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4372 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4373 * @ioc: Pointer to MPT_ADAPTER structure
4374 * @howlong: How long to wait (in seconds)
4375 * @sleepFlag: Specifies whether the process can sleep
4377 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4378 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4380 * Returns a negative value on failure, else wait loop count.
4382 static int
4383 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4385 int cntdn;
4386 int count = 0;
4387 u32 intstat=0;
4389 cntdn = 1000 * howlong;
4390 if (sleepFlag == CAN_SLEEP) {
4391 while (--cntdn) {
4392 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4393 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4394 break;
4395 msleep(1);
4396 count++;
4398 } else {
4399 while (--cntdn) {
4400 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4401 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4402 break;
4403 udelay (1000);
4404 count++;
4408 if (cntdn) {
4409 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4410 ioc->name, count, howlong));
4411 return count;
4414 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4415 ioc->name, count, intstat);
4416 return -1;
4419 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4421 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4422 * @ioc: Pointer to MPT_ADAPTER structure
4423 * @howlong: How long to wait (in seconds)
4424 * @sleepFlag: Specifies whether the process can sleep
4426 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4427 * Reply is cached to IOC private area large enough to hold a maximum
4428 * of 128 bytes of reply data.
4430 * Returns a negative value on failure, else size of reply in WORDS.
4432 static int
4433 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4435 int u16cnt = 0;
4436 int failcnt = 0;
4437 int t;
4438 u16 *hs_reply = ioc->hs_reply;
4439 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4440 u16 hword;
4442 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4445 * Get first two u16's so we can look at IOC's intended reply MsgLength
4447 u16cnt=0;
4448 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4449 failcnt++;
4450 } else {
4451 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4452 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4453 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4454 failcnt++;
4455 else {
4456 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4457 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4461 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4462 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4463 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4466 * If no error (and IOC said MsgLength is > 0), piece together
4467 * reply 16 bits at a time.
4469 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4470 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4471 failcnt++;
4472 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4473 /* don't overflow our IOC hs_reply[] buffer! */
4474 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4475 hs_reply[u16cnt] = hword;
4476 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4479 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4480 failcnt++;
4481 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4483 if (failcnt) {
4484 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4485 ioc->name);
4486 return -failcnt;
4488 #if 0
4489 else if (u16cnt != (2 * mptReply->MsgLength)) {
4490 return -101;
4492 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4493 return -102;
4495 #endif
4497 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4498 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4500 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4501 ioc->name, t, u16cnt/2));
4502 return u16cnt/2;
4505 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4507 * GetLanConfigPages - Fetch LANConfig pages.
4508 * @ioc: Pointer to MPT_ADAPTER structure
4510 * Return: 0 for success
4511 * -ENOMEM if no memory available
4512 * -EPERM if not allowed due to ISR context
4513 * -EAGAIN if no msg frames currently available
4514 * -EFAULT for non-successful reply or no reply (timeout)
4516 static int
4517 GetLanConfigPages(MPT_ADAPTER *ioc)
4519 ConfigPageHeader_t hdr;
4520 CONFIGPARMS cfg;
4521 LANPage0_t *ppage0_alloc;
4522 dma_addr_t page0_dma;
4523 LANPage1_t *ppage1_alloc;
4524 dma_addr_t page1_dma;
4525 int rc = 0;
4526 int data_sz;
4527 int copy_sz;
4529 /* Get LAN Page 0 header */
4530 hdr.PageVersion = 0;
4531 hdr.PageLength = 0;
4532 hdr.PageNumber = 0;
4533 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4534 cfg.cfghdr.hdr = &hdr;
4535 cfg.physAddr = -1;
4536 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4537 cfg.dir = 0;
4538 cfg.pageAddr = 0;
4539 cfg.timeout = 0;
4541 if ((rc = mpt_config(ioc, &cfg)) != 0)
4542 return rc;
4544 if (hdr.PageLength > 0) {
4545 data_sz = hdr.PageLength * 4;
4546 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4547 rc = -ENOMEM;
4548 if (ppage0_alloc) {
4549 memset((u8 *)ppage0_alloc, 0, data_sz);
4550 cfg.physAddr = page0_dma;
4551 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4553 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4554 /* save the data */
4555 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4556 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4560 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4562 /* FIXME!
4563 * Normalize endianness of structure data,
4564 * by byte-swapping all > 1 byte fields!
4569 if (rc)
4570 return rc;
4573 /* Get LAN Page 1 header */
4574 hdr.PageVersion = 0;
4575 hdr.PageLength = 0;
4576 hdr.PageNumber = 1;
4577 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4578 cfg.cfghdr.hdr = &hdr;
4579 cfg.physAddr = -1;
4580 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4581 cfg.dir = 0;
4582 cfg.pageAddr = 0;
4584 if ((rc = mpt_config(ioc, &cfg)) != 0)
4585 return rc;
4587 if (hdr.PageLength == 0)
4588 return 0;
4590 data_sz = hdr.PageLength * 4;
4591 rc = -ENOMEM;
4592 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4593 if (ppage1_alloc) {
4594 memset((u8 *)ppage1_alloc, 0, data_sz);
4595 cfg.physAddr = page1_dma;
4596 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4598 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4599 /* save the data */
4600 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4601 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4604 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4606 /* FIXME!
4607 * Normalize endianness of structure data,
4608 * by byte-swapping all > 1 byte fields!
4613 return rc;
4616 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4618 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4619 * @ioc: Pointer to MPT_ADAPTER structure
4620 * @persist_opcode: see below
4622 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4623 * devices not currently present.
4624 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4626 * NOTE: Don't use not this function during interrupt time.
4628 * Returns 0 for success, non-zero error
4631 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4633 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4635 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4636 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4637 MPT_FRAME_HDR *mf = NULL;
4638 MPIHeader_t *mpi_hdr;
4641 /* insure garbage is not sent to fw */
4642 switch(persist_opcode) {
4644 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4645 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4646 break;
4648 default:
4649 return -1;
4650 break;
4653 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4655 /* Get a MF for this command.
4657 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4658 printk("%s: no msg frames!\n",__FUNCTION__);
4659 return -1;
4662 mpi_hdr = (MPIHeader_t *) mf;
4663 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4664 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4665 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4666 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4667 sasIoUnitCntrReq->Operation = persist_opcode;
4669 init_timer(&ioc->persist_timer);
4670 ioc->persist_timer.data = (unsigned long) ioc;
4671 ioc->persist_timer.function = mpt_timer_expired;
4672 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4673 ioc->persist_wait_done=0;
4674 add_timer(&ioc->persist_timer);
4675 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4676 wait_event(mpt_waitq, ioc->persist_wait_done);
4678 sasIoUnitCntrReply =
4679 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4680 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4681 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4682 __FUNCTION__,
4683 sasIoUnitCntrReply->IOCStatus,
4684 sasIoUnitCntrReply->IOCLogInfo);
4685 return -1;
4688 printk("%s: success\n",__FUNCTION__);
4689 return 0;
4692 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4694 static void
4695 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4696 MpiEventDataRaid_t * pRaidEventData)
4698 int volume;
4699 int reason;
4700 int disk;
4701 int status;
4702 int flags;
4703 int state;
4705 volume = pRaidEventData->VolumeID;
4706 reason = pRaidEventData->ReasonCode;
4707 disk = pRaidEventData->PhysDiskNum;
4708 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4709 flags = (status >> 0) & 0xff;
4710 state = (status >> 8) & 0xff;
4712 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4713 return;
4716 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4717 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4718 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4719 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4720 ioc->name, disk, volume);
4721 } else {
4722 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4723 ioc->name, volume);
4726 switch(reason) {
4727 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4728 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4729 ioc->name);
4730 break;
4732 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4734 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4735 ioc->name);
4736 break;
4738 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4739 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4740 ioc->name);
4741 break;
4743 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4744 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4745 ioc->name,
4746 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4747 ? "optimal"
4748 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4749 ? "degraded"
4750 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4751 ? "failed"
4752 : "state unknown",
4753 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4754 ? ", enabled" : "",
4755 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4756 ? ", quiesced" : "",
4757 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4758 ? ", resync in progress" : "" );
4759 break;
4761 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4762 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4763 ioc->name, disk);
4764 break;
4766 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4767 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4768 ioc->name);
4769 break;
4771 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4772 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4773 ioc->name);
4774 break;
4776 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4777 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4778 ioc->name);
4779 break;
4781 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4782 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4783 ioc->name,
4784 state == MPI_PHYSDISK0_STATUS_ONLINE
4785 ? "online"
4786 : state == MPI_PHYSDISK0_STATUS_MISSING
4787 ? "missing"
4788 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4789 ? "not compatible"
4790 : state == MPI_PHYSDISK0_STATUS_FAILED
4791 ? "failed"
4792 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4793 ? "initializing"
4794 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4795 ? "offline requested"
4796 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4797 ? "failed requested"
4798 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4799 ? "offline"
4800 : "state unknown",
4801 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4802 ? ", out of sync" : "",
4803 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4804 ? ", quiesced" : "" );
4805 break;
4807 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4808 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4809 ioc->name, disk);
4810 break;
4812 case MPI_EVENT_RAID_RC_SMART_DATA:
4813 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4814 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4815 break;
4817 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4818 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4819 ioc->name, disk);
4820 break;
4824 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4826 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4827 * @ioc: Pointer to MPT_ADAPTER structure
4829 * Returns: 0 for success
4830 * -ENOMEM if no memory available
4831 * -EPERM if not allowed due to ISR context
4832 * -EAGAIN if no msg frames currently available
4833 * -EFAULT for non-successful reply or no reply (timeout)
4835 static int
4836 GetIoUnitPage2(MPT_ADAPTER *ioc)
4838 ConfigPageHeader_t hdr;
4839 CONFIGPARMS cfg;
4840 IOUnitPage2_t *ppage_alloc;
4841 dma_addr_t page_dma;
4842 int data_sz;
4843 int rc;
4845 /* Get the page header */
4846 hdr.PageVersion = 0;
4847 hdr.PageLength = 0;
4848 hdr.PageNumber = 2;
4849 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4850 cfg.cfghdr.hdr = &hdr;
4851 cfg.physAddr = -1;
4852 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4853 cfg.dir = 0;
4854 cfg.pageAddr = 0;
4855 cfg.timeout = 0;
4857 if ((rc = mpt_config(ioc, &cfg)) != 0)
4858 return rc;
4860 if (hdr.PageLength == 0)
4861 return 0;
4863 /* Read the config page */
4864 data_sz = hdr.PageLength * 4;
4865 rc = -ENOMEM;
4866 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4867 if (ppage_alloc) {
4868 memset((u8 *)ppage_alloc, 0, data_sz);
4869 cfg.physAddr = page_dma;
4870 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4872 /* If Good, save data */
4873 if ((rc = mpt_config(ioc, &cfg)) == 0)
4874 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4876 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4879 return rc;
4882 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4884 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4885 * @ioc: Pointer to a Adapter Strucutre
4886 * @portnum: IOC port number
4888 * Return: -EFAULT if read of config page header fails
4889 * or if no nvram
4890 * If read of SCSI Port Page 0 fails,
4891 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4892 * Adapter settings: async, narrow
4893 * Return 1
4894 * If read of SCSI Port Page 2 fails,
4895 * Adapter settings valid
4896 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4897 * Return 1
4898 * Else
4899 * Both valid
4900 * Return 0
4901 * CHECK - what type of locking mechanisms should be used????
4903 static int
4904 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4906 u8 *pbuf;
4907 dma_addr_t buf_dma;
4908 CONFIGPARMS cfg;
4909 ConfigPageHeader_t header;
4910 int ii;
4911 int data, rc = 0;
4913 /* Allocate memory
4915 if (!ioc->spi_data.nvram) {
4916 int sz;
4917 u8 *mem;
4918 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4919 mem = kmalloc(sz, GFP_ATOMIC);
4920 if (mem == NULL)
4921 return -EFAULT;
4923 ioc->spi_data.nvram = (int *) mem;
4925 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4926 ioc->name, ioc->spi_data.nvram, sz));
4929 /* Invalidate NVRAM information
4931 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4932 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4935 /* Read SPP0 header, allocate memory, then read page.
4937 header.PageVersion = 0;
4938 header.PageLength = 0;
4939 header.PageNumber = 0;
4940 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4941 cfg.cfghdr.hdr = &header;
4942 cfg.physAddr = -1;
4943 cfg.pageAddr = portnum;
4944 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4945 cfg.dir = 0;
4946 cfg.timeout = 0; /* use default */
4947 if (mpt_config(ioc, &cfg) != 0)
4948 return -EFAULT;
4950 if (header.PageLength > 0) {
4951 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4952 if (pbuf) {
4953 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4954 cfg.physAddr = buf_dma;
4955 if (mpt_config(ioc, &cfg) != 0) {
4956 ioc->spi_data.maxBusWidth = MPT_NARROW;
4957 ioc->spi_data.maxSyncOffset = 0;
4958 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4959 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4960 rc = 1;
4961 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4962 "Unable to read PortPage0 minSyncFactor=%x\n",
4963 ioc->name, ioc->spi_data.minSyncFactor));
4964 } else {
4965 /* Save the Port Page 0 data
4967 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4968 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4969 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4971 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4972 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4973 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4974 "noQas due to Capabilities=%x\n",
4975 ioc->name, pPP0->Capabilities));
4977 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4978 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4979 if (data) {
4980 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4981 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4982 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4983 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4984 "PortPage0 minSyncFactor=%x\n",
4985 ioc->name, ioc->spi_data.minSyncFactor));
4986 } else {
4987 ioc->spi_data.maxSyncOffset = 0;
4988 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4991 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4993 /* Update the minSyncFactor based on bus type.
4995 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4996 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4998 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4999 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5000 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5001 "HVD or SE detected, minSyncFactor=%x\n",
5002 ioc->name, ioc->spi_data.minSyncFactor));
5006 if (pbuf) {
5007 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5012 /* SCSI Port Page 2 - Read the header then the page.
5014 header.PageVersion = 0;
5015 header.PageLength = 0;
5016 header.PageNumber = 2;
5017 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5018 cfg.cfghdr.hdr = &header;
5019 cfg.physAddr = -1;
5020 cfg.pageAddr = portnum;
5021 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5022 cfg.dir = 0;
5023 if (mpt_config(ioc, &cfg) != 0)
5024 return -EFAULT;
5026 if (header.PageLength > 0) {
5027 /* Allocate memory and read SCSI Port Page 2
5029 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5030 if (pbuf) {
5031 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5032 cfg.physAddr = buf_dma;
5033 if (mpt_config(ioc, &cfg) != 0) {
5034 /* Nvram data is left with INVALID mark
5036 rc = 1;
5037 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5039 /* This is an ATTO adapter, read Page2 accordingly
5041 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5042 ATTODeviceInfo_t *pdevice = NULL;
5043 u16 ATTOFlags;
5045 /* Save the Port Page 2 data
5046 * (reformat into a 32bit quantity)
5048 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5049 pdevice = &pPP2->DeviceSettings[ii];
5050 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5051 data = 0;
5053 /* Translate ATTO device flags to LSI format
5055 if (ATTOFlags & ATTOFLAG_DISC)
5056 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5057 if (ATTOFlags & ATTOFLAG_ID_ENB)
5058 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5059 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5060 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5061 if (ATTOFlags & ATTOFLAG_TAGGED)
5062 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5063 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5064 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5066 data = (data << 16) | (pdevice->Period << 8) | 10;
5067 ioc->spi_data.nvram[ii] = data;
5069 } else {
5070 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5071 MpiDeviceInfo_t *pdevice = NULL;
5074 * Save "Set to Avoid SCSI Bus Resets" flag
5076 ioc->spi_data.bus_reset =
5077 (le32_to_cpu(pPP2->PortFlags) &
5078 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5079 0 : 1 ;
5081 /* Save the Port Page 2 data
5082 * (reformat into a 32bit quantity)
5084 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5085 ioc->spi_data.PortFlags = data;
5086 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5087 pdevice = &pPP2->DeviceSettings[ii];
5088 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5089 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5090 ioc->spi_data.nvram[ii] = data;
5094 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5098 /* Update Adapter limits with those from NVRAM
5099 * Comment: Don't need to do this. Target performance
5100 * parameters will never exceed the adapters limits.
5103 return rc;
5106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5108 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5109 * @ioc: Pointer to a Adapter Strucutre
5110 * @portnum: IOC port number
5112 * Return: -EFAULT if read of config page header fails
5113 * or 0 if success.
5115 static int
5116 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5118 CONFIGPARMS cfg;
5119 ConfigPageHeader_t header;
5121 /* Read the SCSI Device Page 1 header
5123 header.PageVersion = 0;
5124 header.PageLength = 0;
5125 header.PageNumber = 1;
5126 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5127 cfg.cfghdr.hdr = &header;
5128 cfg.physAddr = -1;
5129 cfg.pageAddr = portnum;
5130 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5131 cfg.dir = 0;
5132 cfg.timeout = 0;
5133 if (mpt_config(ioc, &cfg) != 0)
5134 return -EFAULT;
5136 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5137 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5139 header.PageVersion = 0;
5140 header.PageLength = 0;
5141 header.PageNumber = 0;
5142 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5143 if (mpt_config(ioc, &cfg) != 0)
5144 return -EFAULT;
5146 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5147 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5149 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5150 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5152 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5153 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5154 return 0;
5158 * mpt_inactive_raid_list_free - This clears this link list.
5159 * @ioc : pointer to per adapter structure
5161 static void
5162 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5164 struct inactive_raid_component_info *component_info, *pNext;
5166 if (list_empty(&ioc->raid_data.inactive_list))
5167 return;
5169 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5170 list_for_each_entry_safe(component_info, pNext,
5171 &ioc->raid_data.inactive_list, list) {
5172 list_del(&component_info->list);
5173 kfree(component_info);
5175 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5179 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5181 * @ioc : pointer to per adapter structure
5182 * @channel : volume channel
5183 * @id : volume target id
5185 static void
5186 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5188 CONFIGPARMS cfg;
5189 ConfigPageHeader_t hdr;
5190 dma_addr_t dma_handle;
5191 pRaidVolumePage0_t buffer = NULL;
5192 int i;
5193 RaidPhysDiskPage0_t phys_disk;
5194 struct inactive_raid_component_info *component_info;
5195 int handle_inactive_volumes;
5197 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5198 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5199 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5200 cfg.pageAddr = (channel << 8) + id;
5201 cfg.cfghdr.hdr = &hdr;
5202 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5204 if (mpt_config(ioc, &cfg) != 0)
5205 goto out;
5207 if (!hdr.PageLength)
5208 goto out;
5210 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5211 &dma_handle);
5213 if (!buffer)
5214 goto out;
5216 cfg.physAddr = dma_handle;
5217 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5219 if (mpt_config(ioc, &cfg) != 0)
5220 goto out;
5222 if (!buffer->NumPhysDisks)
5223 goto out;
5225 handle_inactive_volumes =
5226 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5227 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5228 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5229 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5231 if (!handle_inactive_volumes)
5232 goto out;
5234 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5235 for (i = 0; i < buffer->NumPhysDisks; i++) {
5236 if(mpt_raid_phys_disk_pg0(ioc,
5237 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5238 continue;
5240 if ((component_info = kmalloc(sizeof (*component_info),
5241 GFP_KERNEL)) == NULL)
5242 continue;
5244 component_info->volumeID = id;
5245 component_info->volumeBus = channel;
5246 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5247 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5248 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5249 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5251 list_add_tail(&component_info->list,
5252 &ioc->raid_data.inactive_list);
5254 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5256 out:
5257 if (buffer)
5258 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5259 dma_handle);
5263 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5264 * @ioc: Pointer to a Adapter Structure
5265 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5266 * @phys_disk: requested payload data returned
5268 * Return:
5269 * 0 on success
5270 * -EFAULT if read of config page header fails or data pointer not NULL
5271 * -ENOMEM if pci_alloc failed
5274 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
5276 CONFIGPARMS cfg;
5277 ConfigPageHeader_t hdr;
5278 dma_addr_t dma_handle;
5279 pRaidPhysDiskPage0_t buffer = NULL;
5280 int rc;
5282 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5283 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5285 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5286 cfg.cfghdr.hdr = &hdr;
5287 cfg.physAddr = -1;
5288 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5290 if (mpt_config(ioc, &cfg) != 0) {
5291 rc = -EFAULT;
5292 goto out;
5295 if (!hdr.PageLength) {
5296 rc = -EFAULT;
5297 goto out;
5300 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5301 &dma_handle);
5303 if (!buffer) {
5304 rc = -ENOMEM;
5305 goto out;
5308 cfg.physAddr = dma_handle;
5309 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5310 cfg.pageAddr = phys_disk_num;
5312 if (mpt_config(ioc, &cfg) != 0) {
5313 rc = -EFAULT;
5314 goto out;
5317 rc = 0;
5318 memcpy(phys_disk, buffer, sizeof(*buffer));
5319 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5321 out:
5323 if (buffer)
5324 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5325 dma_handle);
5327 return rc;
5331 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5332 * @ioc: Pointer to a Adapter Strucutre
5333 * @portnum: IOC port number
5335 * Return:
5336 * 0 on success
5337 * -EFAULT if read of config page header fails or data pointer not NULL
5338 * -ENOMEM if pci_alloc failed
5341 mpt_findImVolumes(MPT_ADAPTER *ioc)
5343 IOCPage2_t *pIoc2;
5344 u8 *mem;
5345 dma_addr_t ioc2_dma;
5346 CONFIGPARMS cfg;
5347 ConfigPageHeader_t header;
5348 int rc = 0;
5349 int iocpage2sz;
5350 int i;
5352 if (!ioc->ir_firmware)
5353 return 0;
5355 /* Free the old page
5357 kfree(ioc->raid_data.pIocPg2);
5358 ioc->raid_data.pIocPg2 = NULL;
5359 mpt_inactive_raid_list_free(ioc);
5361 /* Read IOCP2 header then the page.
5363 header.PageVersion = 0;
5364 header.PageLength = 0;
5365 header.PageNumber = 2;
5366 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5367 cfg.cfghdr.hdr = &header;
5368 cfg.physAddr = -1;
5369 cfg.pageAddr = 0;
5370 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5371 cfg.dir = 0;
5372 cfg.timeout = 0;
5373 if (mpt_config(ioc, &cfg) != 0)
5374 return -EFAULT;
5376 if (header.PageLength == 0)
5377 return -EFAULT;
5379 iocpage2sz = header.PageLength * 4;
5380 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5381 if (!pIoc2)
5382 return -ENOMEM;
5384 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5385 cfg.physAddr = ioc2_dma;
5386 if (mpt_config(ioc, &cfg) != 0)
5387 goto out;
5389 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5390 if (!mem)
5391 goto out;
5393 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5394 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5396 mpt_read_ioc_pg_3(ioc);
5398 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5399 mpt_inactive_raid_volumes(ioc,
5400 pIoc2->RaidVolume[i].VolumeBus,
5401 pIoc2->RaidVolume[i].VolumeID);
5403 out:
5404 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5406 return rc;
5409 static int
5410 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5412 IOCPage3_t *pIoc3;
5413 u8 *mem;
5414 CONFIGPARMS cfg;
5415 ConfigPageHeader_t header;
5416 dma_addr_t ioc3_dma;
5417 int iocpage3sz = 0;
5419 /* Free the old page
5421 kfree(ioc->raid_data.pIocPg3);
5422 ioc->raid_data.pIocPg3 = NULL;
5424 /* There is at least one physical disk.
5425 * Read and save IOC Page 3
5427 header.PageVersion = 0;
5428 header.PageLength = 0;
5429 header.PageNumber = 3;
5430 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5431 cfg.cfghdr.hdr = &header;
5432 cfg.physAddr = -1;
5433 cfg.pageAddr = 0;
5434 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5435 cfg.dir = 0;
5436 cfg.timeout = 0;
5437 if (mpt_config(ioc, &cfg) != 0)
5438 return 0;
5440 if (header.PageLength == 0)
5441 return 0;
5443 /* Read Header good, alloc memory
5445 iocpage3sz = header.PageLength * 4;
5446 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5447 if (!pIoc3)
5448 return 0;
5450 /* Read the Page and save the data
5451 * into malloc'd memory.
5453 cfg.physAddr = ioc3_dma;
5454 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5455 if (mpt_config(ioc, &cfg) == 0) {
5456 mem = kmalloc(iocpage3sz, GFP_KERNEL);
5457 if (mem) {
5458 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5459 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5463 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5465 return 0;
5468 static void
5469 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5471 IOCPage4_t *pIoc4;
5472 CONFIGPARMS cfg;
5473 ConfigPageHeader_t header;
5474 dma_addr_t ioc4_dma;
5475 int iocpage4sz;
5477 /* Read and save IOC Page 4
5479 header.PageVersion = 0;
5480 header.PageLength = 0;
5481 header.PageNumber = 4;
5482 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5483 cfg.cfghdr.hdr = &header;
5484 cfg.physAddr = -1;
5485 cfg.pageAddr = 0;
5486 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5487 cfg.dir = 0;
5488 cfg.timeout = 0;
5489 if (mpt_config(ioc, &cfg) != 0)
5490 return;
5492 if (header.PageLength == 0)
5493 return;
5495 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5496 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5497 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5498 if (!pIoc4)
5499 return;
5500 ioc->alloc_total += iocpage4sz;
5501 } else {
5502 ioc4_dma = ioc->spi_data.IocPg4_dma;
5503 iocpage4sz = ioc->spi_data.IocPg4Sz;
5506 /* Read the Page into dma memory.
5508 cfg.physAddr = ioc4_dma;
5509 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5510 if (mpt_config(ioc, &cfg) == 0) {
5511 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5512 ioc->spi_data.IocPg4_dma = ioc4_dma;
5513 ioc->spi_data.IocPg4Sz = iocpage4sz;
5514 } else {
5515 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5516 ioc->spi_data.pIocPg4 = NULL;
5517 ioc->alloc_total -= iocpage4sz;
5521 static void
5522 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5524 IOCPage1_t *pIoc1;
5525 CONFIGPARMS cfg;
5526 ConfigPageHeader_t header;
5527 dma_addr_t ioc1_dma;
5528 int iocpage1sz = 0;
5529 u32 tmp;
5531 /* Check the Coalescing Timeout in IOC Page 1
5533 header.PageVersion = 0;
5534 header.PageLength = 0;
5535 header.PageNumber = 1;
5536 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5537 cfg.cfghdr.hdr = &header;
5538 cfg.physAddr = -1;
5539 cfg.pageAddr = 0;
5540 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5541 cfg.dir = 0;
5542 cfg.timeout = 0;
5543 if (mpt_config(ioc, &cfg) != 0)
5544 return;
5546 if (header.PageLength == 0)
5547 return;
5549 /* Read Header good, alloc memory
5551 iocpage1sz = header.PageLength * 4;
5552 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5553 if (!pIoc1)
5554 return;
5556 /* Read the Page and check coalescing timeout
5558 cfg.physAddr = ioc1_dma;
5559 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5560 if (mpt_config(ioc, &cfg) == 0) {
5562 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5563 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5564 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5566 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
5567 ioc->name, tmp));
5569 if (tmp > MPT_COALESCING_TIMEOUT) {
5570 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5572 /* Write NVRAM and current
5574 cfg.dir = 1;
5575 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5576 if (mpt_config(ioc, &cfg) == 0) {
5577 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
5578 ioc->name, MPT_COALESCING_TIMEOUT));
5580 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5581 if (mpt_config(ioc, &cfg) == 0) {
5582 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5583 "Reset NVRAM Coalescing Timeout to = %d\n",
5584 ioc->name, MPT_COALESCING_TIMEOUT));
5585 } else {
5586 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5587 "Reset NVRAM Coalescing Timeout Failed\n",
5588 ioc->name));
5591 } else {
5592 dprintk(ioc, printk(MYIOC_s_WARN_FMT
5593 "Reset of Current Coalescing Timeout Failed!\n",
5594 ioc->name));
5598 } else {
5599 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5603 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5605 return;
5608 static void
5609 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
5611 CONFIGPARMS cfg;
5612 ConfigPageHeader_t hdr;
5613 dma_addr_t buf_dma;
5614 ManufacturingPage0_t *pbuf = NULL;
5616 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5617 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5619 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5620 cfg.cfghdr.hdr = &hdr;
5621 cfg.physAddr = -1;
5622 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5623 cfg.timeout = 10;
5625 if (mpt_config(ioc, &cfg) != 0)
5626 goto out;
5628 if (!cfg.cfghdr.hdr->PageLength)
5629 goto out;
5631 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5632 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
5633 if (!pbuf)
5634 goto out;
5636 cfg.physAddr = buf_dma;
5638 if (mpt_config(ioc, &cfg) != 0)
5639 goto out;
5641 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
5642 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
5643 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
5645 out:
5647 if (pbuf)
5648 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
5651 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5653 * SendEventNotification - Send EventNotification (on or off) request to adapter
5654 * @ioc: Pointer to MPT_ADAPTER structure
5655 * @EvSwitch: Event switch flags
5657 static int
5658 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5660 EventNotification_t *evnp;
5662 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5663 if (evnp == NULL) {
5664 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5665 ioc->name));
5666 return 0;
5668 memset(evnp, 0, sizeof(*evnp));
5670 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5672 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5673 evnp->ChainOffset = 0;
5674 evnp->MsgFlags = 0;
5675 evnp->Switch = EvSwitch;
5677 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5679 return 0;
5682 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5684 * SendEventAck - Send EventAck request to MPT adapter.
5685 * @ioc: Pointer to MPT_ADAPTER structure
5686 * @evnp: Pointer to original EventNotification request
5688 static int
5689 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5691 EventAck_t *pAck;
5693 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5694 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5695 ioc->name,__FUNCTION__));
5696 return -1;
5699 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
5701 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5702 pAck->ChainOffset = 0;
5703 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5704 pAck->MsgFlags = 0;
5705 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5706 pAck->Event = evnp->Event;
5707 pAck->EventContext = evnp->EventContext;
5709 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5711 return 0;
5714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5716 * mpt_config - Generic function to issue config message
5717 * @ioc: Pointer to an adapter structure
5718 * @pCfg: Pointer to a configuration structure. Struct contains
5719 * action, page address, direction, physical address
5720 * and pointer to a configuration page header
5721 * Page header is updated.
5723 * Returns 0 for success
5724 * -EPERM if not allowed due to ISR context
5725 * -EAGAIN if no msg frames currently available
5726 * -EFAULT for non-successful reply or no reply (timeout)
5729 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5731 Config_t *pReq;
5732 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5733 MPT_FRAME_HDR *mf;
5734 unsigned long flags;
5735 int ii, rc;
5736 int flagsLength;
5737 int in_isr;
5739 /* Prevent calling wait_event() (below), if caller happens
5740 * to be in ISR context, because that is fatal!
5742 in_isr = in_interrupt();
5743 if (in_isr) {
5744 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5745 ioc->name));
5746 return -EPERM;
5749 /* Get and Populate a free Frame
5751 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5752 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5753 ioc->name));
5754 return -EAGAIN;
5756 pReq = (Config_t *)mf;
5757 pReq->Action = pCfg->action;
5758 pReq->Reserved = 0;
5759 pReq->ChainOffset = 0;
5760 pReq->Function = MPI_FUNCTION_CONFIG;
5762 /* Assume page type is not extended and clear "reserved" fields. */
5763 pReq->ExtPageLength = 0;
5764 pReq->ExtPageType = 0;
5765 pReq->MsgFlags = 0;
5767 for (ii=0; ii < 8; ii++)
5768 pReq->Reserved2[ii] = 0;
5770 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5771 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5772 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5773 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5775 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5776 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5777 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5778 pReq->ExtPageType = pExtHdr->ExtPageType;
5779 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5781 /* Page Length must be treated as a reserved field for the extended header. */
5782 pReq->Header.PageLength = 0;
5785 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5787 /* Add a SGE to the config request.
5789 if (pCfg->dir)
5790 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5791 else
5792 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5794 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5795 flagsLength |= pExtHdr->ExtPageLength * 4;
5797 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5798 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5800 else {
5801 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5803 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5804 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5807 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5809 /* Append pCfg pointer to end of mf
5811 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5813 /* Initalize the timer
5815 init_timer(&pCfg->timer);
5816 pCfg->timer.data = (unsigned long) ioc;
5817 pCfg->timer.function = mpt_timer_expired;
5818 pCfg->wait_done = 0;
5820 /* Set the timer; ensure 10 second minimum */
5821 if (pCfg->timeout < 10)
5822 pCfg->timer.expires = jiffies + HZ*10;
5823 else
5824 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5826 /* Add to end of Q, set timer and then issue this command */
5827 spin_lock_irqsave(&ioc->FreeQlock, flags);
5828 list_add_tail(&pCfg->linkage, &ioc->configQ);
5829 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5831 add_timer(&pCfg->timer);
5832 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5833 wait_event(mpt_waitq, pCfg->wait_done);
5835 /* mf has been freed - do not access */
5837 rc = pCfg->status;
5839 return rc;
5842 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5844 * mpt_timer_expired - Callback for timer process.
5845 * Used only internal config functionality.
5846 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5848 static void
5849 mpt_timer_expired(unsigned long data)
5851 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5853 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
5855 /* Perform a FW reload */
5856 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5857 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5859 /* No more processing.
5860 * Hard reset clean-up will wake up
5861 * process and free all resources.
5863 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
5865 return;
5868 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5870 * mpt_ioc_reset - Base cleanup for hard reset
5871 * @ioc: Pointer to the adapter structure
5872 * @reset_phase: Indicates pre- or post-reset functionality
5874 * Remark: Frees resources with internally generated commands.
5876 static int
5877 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5879 CONFIGPARMS *pCfg;
5880 unsigned long flags;
5882 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5883 ": IOC %s_reset routed to MPT base driver!\n",
5884 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5885 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5887 if (reset_phase == MPT_IOC_SETUP_RESET) {
5889 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5890 /* If the internal config Q is not empty -
5891 * delete timer. MF resources will be freed when
5892 * the FIFO's are primed.
5894 spin_lock_irqsave(&ioc->FreeQlock, flags);
5895 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5896 del_timer(&pCfg->timer);
5897 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5899 } else {
5900 CONFIGPARMS *pNext;
5902 /* Search the configQ for internal commands.
5903 * Flush the Q, and wake up all suspended threads.
5905 spin_lock_irqsave(&ioc->FreeQlock, flags);
5906 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5907 list_del(&pCfg->linkage);
5909 pCfg->status = MPT_CONFIG_ERROR;
5910 pCfg->wait_done = 1;
5911 wake_up(&mpt_waitq);
5913 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5916 return 1; /* currently means nothing really */
5920 #ifdef CONFIG_PROC_FS /* { */
5921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5923 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5925 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5927 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5929 * Returns 0 for success, non-zero for failure.
5931 static int
5932 procmpt_create(void)
5934 struct proc_dir_entry *ent;
5936 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5937 if (mpt_proc_root_dir == NULL)
5938 return -ENOTDIR;
5940 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5941 if (ent)
5942 ent->read_proc = procmpt_summary_read;
5944 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5945 if (ent)
5946 ent->read_proc = procmpt_version_read;
5948 return 0;
5951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5953 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5955 * Returns 0 for success, non-zero for failure.
5957 static void
5958 procmpt_destroy(void)
5960 remove_proc_entry("version", mpt_proc_root_dir);
5961 remove_proc_entry("summary", mpt_proc_root_dir);
5962 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5965 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5967 * procmpt_summary_read - Handle read request of a summary file
5968 * @buf: Pointer to area to write information
5969 * @start: Pointer to start pointer
5970 * @offset: Offset to start writing
5971 * @request: Amount of read data requested
5972 * @eof: Pointer to EOF integer
5973 * @data: Pointer
5975 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
5976 * Returns number of characters written to process performing the read.
5978 static int
5979 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5981 MPT_ADAPTER *ioc;
5982 char *out = buf;
5983 int len;
5985 if (data) {
5986 int more = 0;
5988 ioc = data;
5989 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5991 out += more;
5992 } else {
5993 list_for_each_entry(ioc, &ioc_list, list) {
5994 int more = 0;
5996 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5998 out += more;
5999 if ((out-buf) >= request)
6000 break;
6004 len = out - buf;
6006 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6009 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6011 * procmpt_version_read - Handle read request from /proc/mpt/version.
6012 * @buf: Pointer to area to write information
6013 * @start: Pointer to start pointer
6014 * @offset: Offset to start writing
6015 * @request: Amount of read data requested
6016 * @eof: Pointer to EOF integer
6017 * @data: Pointer
6019 * Returns number of characters written to process performing the read.
6021 static int
6022 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6024 u8 cb_idx;
6025 int scsi, fc, sas, lan, ctl, targ, dmp;
6026 char *drvname;
6027 int len;
6029 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6030 len += sprintf(buf+len, " Fusion MPT base driver\n");
6032 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6033 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6034 drvname = NULL;
6035 if (MptCallbacks[cb_idx]) {
6036 switch (MptDriverClass[cb_idx]) {
6037 case MPTSPI_DRIVER:
6038 if (!scsi++) drvname = "SPI host";
6039 break;
6040 case MPTFC_DRIVER:
6041 if (!fc++) drvname = "FC host";
6042 break;
6043 case MPTSAS_DRIVER:
6044 if (!sas++) drvname = "SAS host";
6045 break;
6046 case MPTLAN_DRIVER:
6047 if (!lan++) drvname = "LAN";
6048 break;
6049 case MPTSTM_DRIVER:
6050 if (!targ++) drvname = "SCSI target";
6051 break;
6052 case MPTCTL_DRIVER:
6053 if (!ctl++) drvname = "ioctl";
6054 break;
6057 if (drvname)
6058 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
6062 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6065 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6067 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6068 * @buf: Pointer to area to write information
6069 * @start: Pointer to start pointer
6070 * @offset: Offset to start writing
6071 * @request: Amount of read data requested
6072 * @eof: Pointer to EOF integer
6073 * @data: Pointer
6075 * Returns number of characters written to process performing the read.
6077 static int
6078 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6080 MPT_ADAPTER *ioc = data;
6081 int len;
6082 char expVer[32];
6083 int sz;
6084 int p;
6086 mpt_get_fw_exp_ver(expVer, ioc);
6088 len = sprintf(buf, "%s:", ioc->name);
6089 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6090 len += sprintf(buf+len, " (f/w download boot flag set)");
6091 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6092 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6094 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
6095 ioc->facts.ProductID,
6096 ioc->prod_name);
6097 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6098 if (ioc->facts.FWImageSize)
6099 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6100 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6101 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6102 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
6104 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
6105 ioc->facts.CurrentHostMfaHighAddr);
6106 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
6107 ioc->facts.CurrentSenseBufferHighAddr);
6109 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6110 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6112 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6113 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6115 * Rounding UP to nearest 4-kB boundary here...
6117 sz = (ioc->req_sz * ioc->req_depth) + 128;
6118 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6119 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6120 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6121 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6122 4*ioc->facts.RequestFrameSize,
6123 ioc->facts.GlobalCredits);
6125 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
6126 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6127 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6128 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6129 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6130 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6131 ioc->facts.CurReplyFrameSize,
6132 ioc->facts.ReplyQueueDepth);
6134 len += sprintf(buf+len, " MaxDevices = %d\n",
6135 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6136 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6138 /* per-port info */
6139 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6140 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
6141 p+1,
6142 ioc->facts.NumberOfPorts);
6143 if (ioc->bus_type == FC) {
6144 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6145 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6146 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6147 a[5], a[4], a[3], a[2], a[1], a[0]);
6149 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
6150 ioc->fc_port_page0[p].WWNN.High,
6151 ioc->fc_port_page0[p].WWNN.Low,
6152 ioc->fc_port_page0[p].WWPN.High,
6153 ioc->fc_port_page0[p].WWPN.Low);
6157 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6160 #endif /* CONFIG_PROC_FS } */
6162 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6163 static void
6164 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6166 buf[0] ='\0';
6167 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6168 sprintf(buf, " (Exp %02d%02d)",
6169 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6170 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6172 /* insider hack! */
6173 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6174 strcat(buf, " [MDBG]");
6178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6180 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6181 * @ioc: Pointer to MPT_ADAPTER structure
6182 * @buffer: Pointer to buffer where IOC summary info should be written
6183 * @size: Pointer to number of bytes we wrote (set by this routine)
6184 * @len: Offset at which to start writing in buffer
6185 * @showlan: Display LAN stuff?
6187 * This routine writes (english readable) ASCII text, which represents
6188 * a summary of IOC information, to a buffer.
6190 void
6191 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6193 char expVer[32];
6194 int y;
6196 mpt_get_fw_exp_ver(expVer, ioc);
6199 * Shorter summary of attached ioc's...
6201 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6202 ioc->name,
6203 ioc->prod_name,
6204 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6205 ioc->facts.FWVersion.Word,
6206 expVer,
6207 ioc->facts.NumberOfPorts,
6208 ioc->req_depth);
6210 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6211 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6212 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6213 a[5], a[4], a[3], a[2], a[1], a[0]);
6216 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6218 if (!ioc->active)
6219 y += sprintf(buffer+len+y, " (disabled)");
6221 y += sprintf(buffer+len+y, "\n");
6223 *size = y;
6226 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6228 * Reset Handling
6230 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6232 * mpt_HardResetHandler - Generic reset handler
6233 * @ioc: Pointer to MPT_ADAPTER structure
6234 * @sleepFlag: Indicates if sleep or schedule must be called.
6236 * Issues SCSI Task Management call based on input arg values.
6237 * If TaskMgmt fails, returns associated SCSI request.
6239 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6240 * or a non-interrupt thread. In the former, must not call schedule().
6242 * Note: A return of -1 is a FATAL error case, as it means a
6243 * FW reload/initialization failed.
6245 * Returns 0 for SUCCESS or -1 if FAILED.
6248 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6250 int rc;
6251 unsigned long flags;
6253 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6254 #ifdef MFCNT
6255 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6256 printk("MF count 0x%x !\n", ioc->mfcnt);
6257 #endif
6259 /* Reset the adapter. Prevent more than 1 call to
6260 * mpt_do_ioc_recovery at any instant in time.
6262 spin_lock_irqsave(&ioc->diagLock, flags);
6263 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
6264 spin_unlock_irqrestore(&ioc->diagLock, flags);
6265 return 0;
6266 } else {
6267 ioc->diagPending = 1;
6269 spin_unlock_irqrestore(&ioc->diagLock, flags);
6271 /* FIXME: If do_ioc_recovery fails, repeat....
6274 /* The SCSI driver needs to adjust timeouts on all current
6275 * commands prior to the diagnostic reset being issued.
6276 * Prevents timeouts occurring during a diagnostic reset...very bad.
6277 * For all other protocol drivers, this is a no-op.
6280 u8 cb_idx;
6281 int r = 0;
6283 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6284 if (MptResetHandlers[cb_idx]) {
6285 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
6286 ioc->name, cb_idx));
6287 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6288 if (ioc->alt_ioc) {
6289 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
6290 ioc->name, ioc->alt_ioc->name, cb_idx));
6291 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
6297 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
6298 printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
6300 ioc->reload_fw = 0;
6301 if (ioc->alt_ioc)
6302 ioc->alt_ioc->reload_fw = 0;
6304 spin_lock_irqsave(&ioc->diagLock, flags);
6305 ioc->diagPending = 0;
6306 if (ioc->alt_ioc)
6307 ioc->alt_ioc->diagPending = 0;
6308 spin_unlock_irqrestore(&ioc->diagLock, flags);
6310 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
6312 return rc;
6315 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6316 static void
6317 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
6319 char *ds = NULL;
6321 switch(event) {
6322 case MPI_EVENT_NONE:
6323 ds = "None";
6324 break;
6325 case MPI_EVENT_LOG_DATA:
6326 ds = "Log Data";
6327 break;
6328 case MPI_EVENT_STATE_CHANGE:
6329 ds = "State Change";
6330 break;
6331 case MPI_EVENT_UNIT_ATTENTION:
6332 ds = "Unit Attention";
6333 break;
6334 case MPI_EVENT_IOC_BUS_RESET:
6335 ds = "IOC Bus Reset";
6336 break;
6337 case MPI_EVENT_EXT_BUS_RESET:
6338 ds = "External Bus Reset";
6339 break;
6340 case MPI_EVENT_RESCAN:
6341 ds = "Bus Rescan Event";
6342 break;
6343 case MPI_EVENT_LINK_STATUS_CHANGE:
6344 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
6345 ds = "Link Status(FAILURE) Change";
6346 else
6347 ds = "Link Status(ACTIVE) Change";
6348 break;
6349 case MPI_EVENT_LOOP_STATE_CHANGE:
6350 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
6351 ds = "Loop State(LIP) Change";
6352 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
6353 ds = "Loop State(LPE) Change"; /* ??? */
6354 else
6355 ds = "Loop State(LPB) Change"; /* ??? */
6356 break;
6357 case MPI_EVENT_LOGOUT:
6358 ds = "Logout";
6359 break;
6360 case MPI_EVENT_EVENT_CHANGE:
6361 if (evData0)
6362 ds = "Events ON";
6363 else
6364 ds = "Events OFF";
6365 break;
6366 case MPI_EVENT_INTEGRATED_RAID:
6368 u8 ReasonCode = (u8)(evData0 >> 16);
6369 switch (ReasonCode) {
6370 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
6371 ds = "Integrated Raid: Volume Created";
6372 break;
6373 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
6374 ds = "Integrated Raid: Volume Deleted";
6375 break;
6376 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
6377 ds = "Integrated Raid: Volume Settings Changed";
6378 break;
6379 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
6380 ds = "Integrated Raid: Volume Status Changed";
6381 break;
6382 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
6383 ds = "Integrated Raid: Volume Physdisk Changed";
6384 break;
6385 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
6386 ds = "Integrated Raid: Physdisk Created";
6387 break;
6388 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
6389 ds = "Integrated Raid: Physdisk Deleted";
6390 break;
6391 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
6392 ds = "Integrated Raid: Physdisk Settings Changed";
6393 break;
6394 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
6395 ds = "Integrated Raid: Physdisk Status Changed";
6396 break;
6397 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
6398 ds = "Integrated Raid: Domain Validation Needed";
6399 break;
6400 case MPI_EVENT_RAID_RC_SMART_DATA :
6401 ds = "Integrated Raid; Smart Data";
6402 break;
6403 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
6404 ds = "Integrated Raid: Replace Action Started";
6405 break;
6406 default:
6407 ds = "Integrated Raid";
6408 break;
6410 break;
6412 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
6413 ds = "SCSI Device Status Change";
6414 break;
6415 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
6417 u8 id = (u8)(evData0);
6418 u8 channel = (u8)(evData0 >> 8);
6419 u8 ReasonCode = (u8)(evData0 >> 16);
6420 switch (ReasonCode) {
6421 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
6422 snprintf(evStr, EVENT_DESCR_STR_SZ,
6423 "SAS Device Status Change: Added: "
6424 "id=%d channel=%d", id, channel);
6425 break;
6426 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
6427 snprintf(evStr, EVENT_DESCR_STR_SZ,
6428 "SAS Device Status Change: Deleted: "
6429 "id=%d channel=%d", id, channel);
6430 break;
6431 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
6432 snprintf(evStr, EVENT_DESCR_STR_SZ,
6433 "SAS Device Status Change: SMART Data: "
6434 "id=%d channel=%d", id, channel);
6435 break;
6436 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
6437 snprintf(evStr, EVENT_DESCR_STR_SZ,
6438 "SAS Device Status Change: No Persistancy: "
6439 "id=%d channel=%d", id, channel);
6440 break;
6441 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
6442 snprintf(evStr, EVENT_DESCR_STR_SZ,
6443 "SAS Device Status Change: Unsupported Device "
6444 "Discovered : id=%d channel=%d", id, channel);
6445 break;
6446 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
6447 snprintf(evStr, EVENT_DESCR_STR_SZ,
6448 "SAS Device Status Change: Internal Device "
6449 "Reset : id=%d channel=%d", id, channel);
6450 break;
6451 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
6452 snprintf(evStr, EVENT_DESCR_STR_SZ,
6453 "SAS Device Status Change: Internal Task "
6454 "Abort : id=%d channel=%d", id, channel);
6455 break;
6456 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
6457 snprintf(evStr, EVENT_DESCR_STR_SZ,
6458 "SAS Device Status Change: Internal Abort "
6459 "Task Set : id=%d channel=%d", id, channel);
6460 break;
6461 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
6462 snprintf(evStr, EVENT_DESCR_STR_SZ,
6463 "SAS Device Status Change: Internal Clear "
6464 "Task Set : id=%d channel=%d", id, channel);
6465 break;
6466 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
6467 snprintf(evStr, EVENT_DESCR_STR_SZ,
6468 "SAS Device Status Change: Internal Query "
6469 "Task : id=%d channel=%d", id, channel);
6470 break;
6471 default:
6472 snprintf(evStr, EVENT_DESCR_STR_SZ,
6473 "SAS Device Status Change: Unknown: "
6474 "id=%d channel=%d", id, channel);
6475 break;
6477 break;
6479 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
6480 ds = "Bus Timer Expired";
6481 break;
6482 case MPI_EVENT_QUEUE_FULL:
6484 u16 curr_depth = (u16)(evData0 >> 16);
6485 u8 channel = (u8)(evData0 >> 8);
6486 u8 id = (u8)(evData0);
6488 snprintf(evStr, EVENT_DESCR_STR_SZ,
6489 "Queue Full: channel=%d id=%d depth=%d",
6490 channel, id, curr_depth);
6491 break;
6493 case MPI_EVENT_SAS_SES:
6494 ds = "SAS SES Event";
6495 break;
6496 case MPI_EVENT_PERSISTENT_TABLE_FULL:
6497 ds = "Persistent Table Full";
6498 break;
6499 case MPI_EVENT_SAS_PHY_LINK_STATUS:
6501 u8 LinkRates = (u8)(evData0 >> 8);
6502 u8 PhyNumber = (u8)(evData0);
6503 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
6504 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
6505 switch (LinkRates) {
6506 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
6507 snprintf(evStr, EVENT_DESCR_STR_SZ,
6508 "SAS PHY Link Status: Phy=%d:"
6509 " Rate Unknown",PhyNumber);
6510 break;
6511 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
6512 snprintf(evStr, EVENT_DESCR_STR_SZ,
6513 "SAS PHY Link Status: Phy=%d:"
6514 " Phy Disabled",PhyNumber);
6515 break;
6516 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
6517 snprintf(evStr, EVENT_DESCR_STR_SZ,
6518 "SAS PHY Link Status: Phy=%d:"
6519 " Failed Speed Nego",PhyNumber);
6520 break;
6521 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
6522 snprintf(evStr, EVENT_DESCR_STR_SZ,
6523 "SAS PHY Link Status: Phy=%d:"
6524 " Sata OOB Completed",PhyNumber);
6525 break;
6526 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
6527 snprintf(evStr, EVENT_DESCR_STR_SZ,
6528 "SAS PHY Link Status: Phy=%d:"
6529 " Rate 1.5 Gbps",PhyNumber);
6530 break;
6531 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
6532 snprintf(evStr, EVENT_DESCR_STR_SZ,
6533 "SAS PHY Link Status: Phy=%d:"
6534 " Rate 3.0 Gpbs",PhyNumber);
6535 break;
6536 default:
6537 snprintf(evStr, EVENT_DESCR_STR_SZ,
6538 "SAS PHY Link Status: Phy=%d", PhyNumber);
6539 break;
6541 break;
6543 case MPI_EVENT_SAS_DISCOVERY_ERROR:
6544 ds = "SAS Discovery Error";
6545 break;
6546 case MPI_EVENT_IR_RESYNC_UPDATE:
6548 u8 resync_complete = (u8)(evData0 >> 16);
6549 snprintf(evStr, EVENT_DESCR_STR_SZ,
6550 "IR Resync Update: Complete = %d:",resync_complete);
6551 break;
6553 case MPI_EVENT_IR2:
6555 u8 ReasonCode = (u8)(evData0 >> 16);
6556 switch (ReasonCode) {
6557 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
6558 ds = "IR2: LD State Changed";
6559 break;
6560 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
6561 ds = "IR2: PD State Changed";
6562 break;
6563 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
6564 ds = "IR2: Bad Block Table Full";
6565 break;
6566 case MPI_EVENT_IR2_RC_PD_INSERTED:
6567 ds = "IR2: PD Inserted";
6568 break;
6569 case MPI_EVENT_IR2_RC_PD_REMOVED:
6570 ds = "IR2: PD Removed";
6571 break;
6572 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
6573 ds = "IR2: Foreign CFG Detected";
6574 break;
6575 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
6576 ds = "IR2: Rebuild Medium Error";
6577 break;
6578 default:
6579 ds = "IR2";
6580 break;
6582 break;
6584 case MPI_EVENT_SAS_DISCOVERY:
6586 if (evData0)
6587 ds = "SAS Discovery: Start";
6588 else
6589 ds = "SAS Discovery: Stop";
6590 break;
6592 case MPI_EVENT_LOG_ENTRY_ADDED:
6593 ds = "SAS Log Entry Added";
6594 break;
6596 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
6598 u8 phy_num = (u8)(evData0);
6599 u8 port_num = (u8)(evData0 >> 8);
6600 u8 port_width = (u8)(evData0 >> 16);
6601 u8 primative = (u8)(evData0 >> 24);
6602 snprintf(evStr, EVENT_DESCR_STR_SZ,
6603 "SAS Broadcase Primative: phy=%d port=%d "
6604 "width=%d primative=0x%02x",
6605 phy_num, port_num, port_width, primative);
6606 break;
6609 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
6611 u8 reason = (u8)(evData0);
6612 u8 port_num = (u8)(evData0 >> 8);
6613 u16 handle = le16_to_cpu(evData0 >> 16);
6615 snprintf(evStr, EVENT_DESCR_STR_SZ,
6616 "SAS Initiator Device Status Change: reason=0x%02x "
6617 "port=%d handle=0x%04x",
6618 reason, port_num, handle);
6619 break;
6622 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6624 u8 max_init = (u8)(evData0);
6625 u8 current_init = (u8)(evData0 >> 8);
6627 snprintf(evStr, EVENT_DESCR_STR_SZ,
6628 "SAS Initiator Device Table Overflow: max initiators=%02d "
6629 "current initators=%02d",
6630 max_init, current_init);
6631 break;
6633 case MPI_EVENT_SAS_SMP_ERROR:
6635 u8 status = (u8)(evData0);
6636 u8 port_num = (u8)(evData0 >> 8);
6637 u8 result = (u8)(evData0 >> 16);
6639 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6640 snprintf(evStr, EVENT_DESCR_STR_SZ,
6641 "SAS SMP Error: port=%d result=0x%02x",
6642 port_num, result);
6643 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6644 snprintf(evStr, EVENT_DESCR_STR_SZ,
6645 "SAS SMP Error: port=%d : CRC Error",
6646 port_num);
6647 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6648 snprintf(evStr, EVENT_DESCR_STR_SZ,
6649 "SAS SMP Error: port=%d : Timeout",
6650 port_num);
6651 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6652 snprintf(evStr, EVENT_DESCR_STR_SZ,
6653 "SAS SMP Error: port=%d : No Destination",
6654 port_num);
6655 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6656 snprintf(evStr, EVENT_DESCR_STR_SZ,
6657 "SAS SMP Error: port=%d : Bad Destination",
6658 port_num);
6659 else
6660 snprintf(evStr, EVENT_DESCR_STR_SZ,
6661 "SAS SMP Error: port=%d : status=0x%02x",
6662 port_num, status);
6663 break;
6667 * MPT base "custom" events may be added here...
6669 default:
6670 ds = "Unknown";
6671 break;
6673 if (ds)
6674 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6677 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6679 * ProcessEventNotification - Route EventNotificationReply to all event handlers
6680 * @ioc: Pointer to MPT_ADAPTER structure
6681 * @pEventReply: Pointer to EventNotification reply frame
6682 * @evHandlers: Pointer to integer, number of event handlers
6684 * Routes a received EventNotificationReply to all currently registered
6685 * event handlers.
6686 * Returns sum of event handlers return values.
6688 static int
6689 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6691 u16 evDataLen;
6692 u32 evData0 = 0;
6693 // u32 evCtx;
6694 int ii;
6695 u8 cb_idx;
6696 int r = 0;
6697 int handlers = 0;
6698 char evStr[EVENT_DESCR_STR_SZ];
6699 u8 event;
6702 * Do platform normalization of values
6704 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6705 // evCtx = le32_to_cpu(pEventReply->EventContext);
6706 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6707 if (evDataLen) {
6708 evData0 = le32_to_cpu(pEventReply->Data[0]);
6711 EventDescriptionStr(event, evData0, evStr);
6712 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
6713 ioc->name,
6714 event,
6715 evStr));
6717 #ifdef CONFIG_FUSION_LOGGING
6718 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6719 ": Event data:\n", ioc->name));
6720 for (ii = 0; ii < evDataLen; ii++)
6721 devtverboseprintk(ioc, printk(" %08x",
6722 le32_to_cpu(pEventReply->Data[ii])));
6723 devtverboseprintk(ioc, printk("\n"));
6724 #endif
6727 * Do general / base driver event processing
6729 switch(event) {
6730 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6731 if (evDataLen) {
6732 u8 evState = evData0 & 0xFF;
6734 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6736 /* Update EventState field in cached IocFacts */
6737 if (ioc->facts.Function) {
6738 ioc->facts.EventState = evState;
6741 break;
6742 case MPI_EVENT_INTEGRATED_RAID:
6743 mptbase_raid_process_event_data(ioc,
6744 (MpiEventDataRaid_t *)pEventReply->Data);
6745 break;
6746 default:
6747 break;
6751 * Should this event be logged? Events are written sequentially.
6752 * When buffer is full, start again at the top.
6754 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6755 int idx;
6757 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6759 ioc->events[idx].event = event;
6760 ioc->events[idx].eventContext = ioc->eventContext;
6762 for (ii = 0; ii < 2; ii++) {
6763 if (ii < evDataLen)
6764 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6765 else
6766 ioc->events[idx].data[ii] = 0;
6769 ioc->eventContext++;
6774 * Call each currently registered protocol event handler.
6776 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6777 if (MptEvHandlers[cb_idx]) {
6778 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
6779 ioc->name, cb_idx));
6780 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
6781 handlers++;
6784 /* FIXME? Examine results here? */
6787 * If needed, send (a single) EventAck.
6789 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6790 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6791 "EventAck required\n",ioc->name));
6792 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6793 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
6794 ioc->name, ii));
6798 *evHandlers = handlers;
6799 return r;
6802 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6804 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6805 * @ioc: Pointer to MPT_ADAPTER structure
6806 * @log_info: U32 LogInfo reply word from the IOC
6808 * Refer to lsi/mpi_log_fc.h.
6810 static void
6811 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6813 char *desc = "unknown";
6815 switch (log_info & 0xFF000000) {
6816 case MPI_IOCLOGINFO_FC_INIT_BASE:
6817 desc = "FCP Initiator";
6818 break;
6819 case MPI_IOCLOGINFO_FC_TARGET_BASE:
6820 desc = "FCP Target";
6821 break;
6822 case MPI_IOCLOGINFO_FC_LAN_BASE:
6823 desc = "LAN";
6824 break;
6825 case MPI_IOCLOGINFO_FC_MSG_BASE:
6826 desc = "MPI Message Layer";
6827 break;
6828 case MPI_IOCLOGINFO_FC_LINK_BASE:
6829 desc = "FC Link";
6830 break;
6831 case MPI_IOCLOGINFO_FC_CTX_BASE:
6832 desc = "Context Manager";
6833 break;
6834 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
6835 desc = "Invalid Field Offset";
6836 break;
6837 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
6838 desc = "State Change Info";
6839 break;
6842 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6843 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
6846 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6848 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6849 * @ioc: Pointer to MPT_ADAPTER structure
6850 * @mr: Pointer to MPT reply frame
6851 * @log_info: U32 LogInfo word from the IOC
6853 * Refer to lsi/sp_log.h.
6855 static void
6856 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6858 u32 info = log_info & 0x00FF0000;
6859 char *desc = "unknown";
6861 switch (info) {
6862 case 0x00010000:
6863 desc = "bug! MID not found";
6864 if (ioc->reload_fw == 0)
6865 ioc->reload_fw++;
6866 break;
6868 case 0x00020000:
6869 desc = "Parity Error";
6870 break;
6872 case 0x00030000:
6873 desc = "ASYNC Outbound Overrun";
6874 break;
6876 case 0x00040000:
6877 desc = "SYNC Offset Error";
6878 break;
6880 case 0x00050000:
6881 desc = "BM Change";
6882 break;
6884 case 0x00060000:
6885 desc = "Msg In Overflow";
6886 break;
6888 case 0x00070000:
6889 desc = "DMA Error";
6890 break;
6892 case 0x00080000:
6893 desc = "Outbound DMA Overrun";
6894 break;
6896 case 0x00090000:
6897 desc = "Task Management";
6898 break;
6900 case 0x000A0000:
6901 desc = "Device Problem";
6902 break;
6904 case 0x000B0000:
6905 desc = "Invalid Phase Change";
6906 break;
6908 case 0x000C0000:
6909 desc = "Untagged Table Size";
6910 break;
6914 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6917 /* strings for sas loginfo */
6918 static char *originator_str[] = {
6919 "IOP", /* 00h */
6920 "PL", /* 01h */
6921 "IR" /* 02h */
6923 static char *iop_code_str[] = {
6924 NULL, /* 00h */
6925 "Invalid SAS Address", /* 01h */
6926 NULL, /* 02h */
6927 "Invalid Page", /* 03h */
6928 "Diag Message Error", /* 04h */
6929 "Task Terminated", /* 05h */
6930 "Enclosure Management", /* 06h */
6931 "Target Mode" /* 07h */
6933 static char *pl_code_str[] = {
6934 NULL, /* 00h */
6935 "Open Failure", /* 01h */
6936 "Invalid Scatter Gather List", /* 02h */
6937 "Wrong Relative Offset or Frame Length", /* 03h */
6938 "Frame Transfer Error", /* 04h */
6939 "Transmit Frame Connected Low", /* 05h */
6940 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6941 "SATA Read Log Receive Data Error", /* 07h */
6942 "SATA NCQ Fail All Commands After Error", /* 08h */
6943 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6944 "Receive Frame Invalid Message", /* 0Ah */
6945 "Receive Context Message Valid Error", /* 0Bh */
6946 "Receive Frame Current Frame Error", /* 0Ch */
6947 "SATA Link Down", /* 0Dh */
6948 "Discovery SATA Init W IOS", /* 0Eh */
6949 "Config Invalid Page", /* 0Fh */
6950 "Discovery SATA Init Timeout", /* 10h */
6951 "Reset", /* 11h */
6952 "Abort", /* 12h */
6953 "IO Not Yet Executed", /* 13h */
6954 "IO Executed", /* 14h */
6955 "Persistent Reservation Out Not Affiliation "
6956 "Owner", /* 15h */
6957 "Open Transmit DMA Abort", /* 16h */
6958 "IO Device Missing Delay Retry", /* 17h */
6959 "IO Cancelled Due to Recieve Error", /* 18h */
6960 NULL, /* 19h */
6961 NULL, /* 1Ah */
6962 NULL, /* 1Bh */
6963 NULL, /* 1Ch */
6964 NULL, /* 1Dh */
6965 NULL, /* 1Eh */
6966 NULL, /* 1Fh */
6967 "Enclosure Management" /* 20h */
6969 static char *ir_code_str[] = {
6970 "Raid Action Error", /* 00h */
6971 NULL, /* 00h */
6972 NULL, /* 01h */
6973 NULL, /* 02h */
6974 NULL, /* 03h */
6975 NULL, /* 04h */
6976 NULL, /* 05h */
6977 NULL, /* 06h */
6978 NULL /* 07h */
6980 static char *raid_sub_code_str[] = {
6981 NULL, /* 00h */
6982 "Volume Creation Failed: Data Passed too "
6983 "Large", /* 01h */
6984 "Volume Creation Failed: Duplicate Volumes "
6985 "Attempted", /* 02h */
6986 "Volume Creation Failed: Max Number "
6987 "Supported Volumes Exceeded", /* 03h */
6988 "Volume Creation Failed: DMA Error", /* 04h */
6989 "Volume Creation Failed: Invalid Volume Type", /* 05h */
6990 "Volume Creation Failed: Error Reading "
6991 "MFG Page 4", /* 06h */
6992 "Volume Creation Failed: Creating Internal "
6993 "Structures", /* 07h */
6994 NULL, /* 08h */
6995 NULL, /* 09h */
6996 NULL, /* 0Ah */
6997 NULL, /* 0Bh */
6998 NULL, /* 0Ch */
6999 NULL, /* 0Dh */
7000 NULL, /* 0Eh */
7001 NULL, /* 0Fh */
7002 "Activation failed: Already Active Volume", /* 10h */
7003 "Activation failed: Unsupported Volume Type", /* 11h */
7004 "Activation failed: Too Many Active Volumes", /* 12h */
7005 "Activation failed: Volume ID in Use", /* 13h */
7006 "Activation failed: Reported Failure", /* 14h */
7007 "Activation failed: Importing a Volume", /* 15h */
7008 NULL, /* 16h */
7009 NULL, /* 17h */
7010 NULL, /* 18h */
7011 NULL, /* 19h */
7012 NULL, /* 1Ah */
7013 NULL, /* 1Bh */
7014 NULL, /* 1Ch */
7015 NULL, /* 1Dh */
7016 NULL, /* 1Eh */
7017 NULL, /* 1Fh */
7018 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7019 "Phys Disk failed: Data Passed too Large", /* 21h */
7020 "Phys Disk failed: DMA Error", /* 22h */
7021 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7022 "Phys Disk failed: Creating Phys Disk Config "
7023 "Page", /* 24h */
7024 NULL, /* 25h */
7025 NULL, /* 26h */
7026 NULL, /* 27h */
7027 NULL, /* 28h */
7028 NULL, /* 29h */
7029 NULL, /* 2Ah */
7030 NULL, /* 2Bh */
7031 NULL, /* 2Ch */
7032 NULL, /* 2Dh */
7033 NULL, /* 2Eh */
7034 NULL, /* 2Fh */
7035 "Compatibility Error: IR Disabled", /* 30h */
7036 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7037 "Compatibility Error: Device not Direct Access "
7038 "Device ", /* 32h */
7039 "Compatibility Error: Removable Device Found", /* 33h */
7040 "Compatibility Error: Device SCSI Version not "
7041 "2 or Higher", /* 34h */
7042 "Compatibility Error: SATA Device, 48 BIT LBA "
7043 "not Supported", /* 35h */
7044 "Compatibility Error: Device doesn't have "
7045 "512 Byte Block Sizes", /* 36h */
7046 "Compatibility Error: Volume Type Check Failed", /* 37h */
7047 "Compatibility Error: Volume Type is "
7048 "Unsupported by FW", /* 38h */
7049 "Compatibility Error: Disk Drive too Small for "
7050 "use in Volume", /* 39h */
7051 "Compatibility Error: Phys Disk for Create "
7052 "Volume not Found", /* 3Ah */
7053 "Compatibility Error: Too Many or too Few "
7054 "Disks for Volume Type", /* 3Bh */
7055 "Compatibility Error: Disk stripe Sizes "
7056 "Must be 64KB", /* 3Ch */
7057 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7062 * mpt_sas_log_info - Log information returned from SAS IOC.
7063 * @ioc: Pointer to MPT_ADAPTER structure
7064 * @log_info: U32 LogInfo reply word from the IOC
7066 * Refer to lsi/mpi_log_sas.h.
7068 static void
7069 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7071 union loginfo_type {
7072 u32 loginfo;
7073 struct {
7074 u32 subcode:16;
7075 u32 code:8;
7076 u32 originator:4;
7077 u32 bus_type:4;
7078 }dw;
7080 union loginfo_type sas_loginfo;
7081 char *originator_desc = NULL;
7082 char *code_desc = NULL;
7083 char *sub_code_desc = NULL;
7085 sas_loginfo.loginfo = log_info;
7086 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7087 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
7088 return;
7090 originator_desc = originator_str[sas_loginfo.dw.originator];
7092 switch (sas_loginfo.dw.originator) {
7094 case 0: /* IOP */
7095 if (sas_loginfo.dw.code <
7096 sizeof(iop_code_str)/sizeof(char*))
7097 code_desc = iop_code_str[sas_loginfo.dw.code];
7098 break;
7099 case 1: /* PL */
7100 if (sas_loginfo.dw.code <
7101 sizeof(pl_code_str)/sizeof(char*))
7102 code_desc = pl_code_str[sas_loginfo.dw.code];
7103 break;
7104 case 2: /* IR */
7105 if (sas_loginfo.dw.code >=
7106 sizeof(ir_code_str)/sizeof(char*))
7107 break;
7108 code_desc = ir_code_str[sas_loginfo.dw.code];
7109 if (sas_loginfo.dw.subcode >=
7110 sizeof(raid_sub_code_str)/sizeof(char*))
7111 break;
7112 if (sas_loginfo.dw.code == 0)
7113 sub_code_desc =
7114 raid_sub_code_str[sas_loginfo.dw.subcode];
7115 break;
7116 default:
7117 return;
7120 if (sub_code_desc != NULL)
7121 printk(MYIOC_s_INFO_FMT
7122 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7123 " SubCode={%s}\n",
7124 ioc->name, log_info, originator_desc, code_desc,
7125 sub_code_desc);
7126 else if (code_desc != NULL)
7127 printk(MYIOC_s_INFO_FMT
7128 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7129 " SubCode(0x%04x)\n",
7130 ioc->name, log_info, originator_desc, code_desc,
7131 sas_loginfo.dw.subcode);
7132 else
7133 printk(MYIOC_s_INFO_FMT
7134 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7135 " SubCode(0x%04x)\n",
7136 ioc->name, log_info, originator_desc,
7137 sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7142 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7143 * @ioc: Pointer to MPT_ADAPTER structure
7144 * @ioc_status: U32 IOCStatus word from IOC
7145 * @mf: Pointer to MPT request frame
7147 * Refer to lsi/mpi.h.
7149 static void
7150 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7152 Config_t *pReq = (Config_t *)mf;
7153 char extend_desc[EVENT_DESCR_STR_SZ];
7154 char *desc = NULL;
7155 u32 form;
7156 u8 page_type;
7158 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7159 page_type = pReq->ExtPageType;
7160 else
7161 page_type = pReq->Header.PageType;
7164 * ignore invalid page messages for GET_NEXT_HANDLE
7166 form = le32_to_cpu(pReq->PageAddress);
7167 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7168 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7169 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7170 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7171 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7172 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7173 return;
7175 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7176 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7177 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7178 return;
7181 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7182 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7183 page_type, pReq->Header.PageNumber, pReq->Action, form);
7185 switch (ioc_status) {
7187 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7188 desc = "Config Page Invalid Action";
7189 break;
7191 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7192 desc = "Config Page Invalid Type";
7193 break;
7195 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7196 desc = "Config Page Invalid Page";
7197 break;
7199 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7200 desc = "Config Page Invalid Data";
7201 break;
7203 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7204 desc = "Config Page No Defaults";
7205 break;
7207 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7208 desc = "Config Page Can't Commit";
7209 break;
7212 if (!desc)
7213 return;
7215 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7216 ioc->name, ioc_status, desc, extend_desc));
7220 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7221 * @ioc: Pointer to MPT_ADAPTER structure
7222 * @ioc_status: U32 IOCStatus word from IOC
7223 * @mf: Pointer to MPT request frame
7225 * Refer to lsi/mpi.h.
7227 static void
7228 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7230 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
7231 char *desc = NULL;
7233 switch (status) {
7235 /****************************************************************************/
7236 /* Common IOCStatus values for all replies */
7237 /****************************************************************************/
7239 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
7240 desc = "Invalid Function";
7241 break;
7243 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
7244 desc = "Busy";
7245 break;
7247 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
7248 desc = "Invalid SGL";
7249 break;
7251 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
7252 desc = "Internal Error";
7253 break;
7255 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
7256 desc = "Reserved";
7257 break;
7259 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
7260 desc = "Insufficient Resources";
7261 break;
7263 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
7264 desc = "Invalid Field";
7265 break;
7267 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
7268 desc = "Invalid State";
7269 break;
7271 /****************************************************************************/
7272 /* Config IOCStatus values */
7273 /****************************************************************************/
7275 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7276 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7277 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7278 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7279 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7280 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7281 mpt_iocstatus_info_config(ioc, status, mf);
7282 break;
7284 /****************************************************************************/
7285 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
7286 /* */
7287 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7288 /* */
7289 /****************************************************************************/
7291 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
7292 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
7293 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
7294 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
7295 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
7296 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
7297 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
7298 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
7299 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
7300 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
7301 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
7302 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
7303 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
7304 break;
7306 /****************************************************************************/
7307 /* SCSI Target values */
7308 /****************************************************************************/
7310 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
7311 desc = "Target: Priority IO";
7312 break;
7314 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
7315 desc = "Target: Invalid Port";
7316 break;
7318 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
7319 desc = "Target Invalid IO Index:";
7320 break;
7322 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
7323 desc = "Target: Aborted";
7324 break;
7326 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
7327 desc = "Target: No Conn Retryable";
7328 break;
7330 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
7331 desc = "Target: No Connection";
7332 break;
7334 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
7335 desc = "Target: Transfer Count Mismatch";
7336 break;
7338 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
7339 desc = "Target: STS Data not Sent";
7340 break;
7342 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
7343 desc = "Target: Data Offset Error";
7344 break;
7346 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
7347 desc = "Target: Too Much Write Data";
7348 break;
7350 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
7351 desc = "Target: IU Too Short";
7352 break;
7354 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
7355 desc = "Target: ACK NAK Timeout";
7356 break;
7358 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
7359 desc = "Target: Nak Received";
7360 break;
7362 /****************************************************************************/
7363 /* Fibre Channel Direct Access values */
7364 /****************************************************************************/
7366 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
7367 desc = "FC: Aborted";
7368 break;
7370 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
7371 desc = "FC: RX ID Invalid";
7372 break;
7374 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
7375 desc = "FC: DID Invalid";
7376 break;
7378 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
7379 desc = "FC: Node Logged Out";
7380 break;
7382 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
7383 desc = "FC: Exchange Canceled";
7384 break;
7386 /****************************************************************************/
7387 /* LAN values */
7388 /****************************************************************************/
7390 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
7391 desc = "LAN: Device not Found";
7392 break;
7394 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
7395 desc = "LAN: Device Failure";
7396 break;
7398 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
7399 desc = "LAN: Transmit Error";
7400 break;
7402 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
7403 desc = "LAN: Transmit Aborted";
7404 break;
7406 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
7407 desc = "LAN: Receive Error";
7408 break;
7410 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
7411 desc = "LAN: Receive Aborted";
7412 break;
7414 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
7415 desc = "LAN: Partial Packet";
7416 break;
7418 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
7419 desc = "LAN: Canceled";
7420 break;
7422 /****************************************************************************/
7423 /* Serial Attached SCSI values */
7424 /****************************************************************************/
7426 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
7427 desc = "SAS: SMP Request Failed";
7428 break;
7430 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
7431 desc = "SAS: SMP Data Overrun";
7432 break;
7434 default:
7435 desc = "Others";
7436 break;
7439 if (!desc)
7440 return;
7442 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
7443 ioc->name, status, desc));
7446 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7447 EXPORT_SYMBOL(mpt_attach);
7448 EXPORT_SYMBOL(mpt_detach);
7449 #ifdef CONFIG_PM
7450 EXPORT_SYMBOL(mpt_resume);
7451 EXPORT_SYMBOL(mpt_suspend);
7452 #endif
7453 EXPORT_SYMBOL(ioc_list);
7454 EXPORT_SYMBOL(mpt_proc_root_dir);
7455 EXPORT_SYMBOL(mpt_register);
7456 EXPORT_SYMBOL(mpt_deregister);
7457 EXPORT_SYMBOL(mpt_event_register);
7458 EXPORT_SYMBOL(mpt_event_deregister);
7459 EXPORT_SYMBOL(mpt_reset_register);
7460 EXPORT_SYMBOL(mpt_reset_deregister);
7461 EXPORT_SYMBOL(mpt_device_driver_register);
7462 EXPORT_SYMBOL(mpt_device_driver_deregister);
7463 EXPORT_SYMBOL(mpt_get_msg_frame);
7464 EXPORT_SYMBOL(mpt_put_msg_frame);
7465 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
7466 EXPORT_SYMBOL(mpt_free_msg_frame);
7467 EXPORT_SYMBOL(mpt_add_sge);
7468 EXPORT_SYMBOL(mpt_send_handshake_request);
7469 EXPORT_SYMBOL(mpt_verify_adapter);
7470 EXPORT_SYMBOL(mpt_GetIocState);
7471 EXPORT_SYMBOL(mpt_print_ioc_summary);
7472 EXPORT_SYMBOL(mpt_HardResetHandler);
7473 EXPORT_SYMBOL(mpt_config);
7474 EXPORT_SYMBOL(mpt_findImVolumes);
7475 EXPORT_SYMBOL(mpt_alloc_fw_memory);
7476 EXPORT_SYMBOL(mpt_free_fw_memory);
7477 EXPORT_SYMBOL(mptbase_sas_persist_operation);
7478 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
7480 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7482 * fusion_init - Fusion MPT base driver initialization routine.
7484 * Returns 0 for success, non-zero for failure.
7486 static int __init
7487 fusion_init(void)
7489 u8 cb_idx;
7491 show_mptmod_ver(my_NAME, my_VERSION);
7492 printk(KERN_INFO COPYRIGHT "\n");
7494 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
7495 MptCallbacks[cb_idx] = NULL;
7496 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
7497 MptEvHandlers[cb_idx] = NULL;
7498 MptResetHandlers[cb_idx] = NULL;
7501 /* Register ourselves (mptbase) in order to facilitate
7502 * EventNotification handling.
7504 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
7506 /* Register for hard reset handling callbacks.
7508 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
7510 #ifdef CONFIG_PROC_FS
7511 (void) procmpt_create();
7512 #endif
7513 return 0;
7516 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7518 * fusion_exit - Perform driver unload cleanup.
7520 * This routine frees all resources associated with each MPT adapter
7521 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
7523 static void __exit
7524 fusion_exit(void)
7527 mpt_reset_deregister(mpt_base_index);
7529 #ifdef CONFIG_PROC_FS
7530 procmpt_destroy();
7531 #endif
7534 module_init(fusion_init);
7535 module_exit(fusion_exit);