dma-mapping: replace all DMA_64BIT_MASK macro with DMA_BIT_MASK(64)
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / message / fusion / mptbase.c
blob98026016a9353b1fa0358d9ae7b43cb7e8d1733f
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-2008 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
83 static int mpt_msi_enable_spi;
84 module_param(mpt_msi_enable_spi, int, 0);
85 MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI \
86 controllers (default=0)");
88 static int mpt_msi_enable_fc;
89 module_param(mpt_msi_enable_fc, int, 0);
90 MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \
91 controllers (default=0)");
93 static int mpt_msi_enable_sas;
94 module_param(mpt_msi_enable_sas, int, 0);
95 MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \
96 controllers (default=0)");
99 static int mpt_channel_mapping;
100 module_param(mpt_channel_mapping, int, 0);
101 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
103 static int mpt_debug_level;
104 static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
105 module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
106 &mpt_debug_level, 0600);
107 MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \
108 - (default=0)");
110 int mpt_fwfault_debug;
111 EXPORT_SYMBOL(mpt_fwfault_debug);
112 module_param_call(mpt_fwfault_debug, param_set_int, param_get_int,
113 &mpt_fwfault_debug, 0600);
114 MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault"
115 " and halt Firmware on fault - (default=0)");
119 #ifdef MFCNT
120 static int mfcounter = 0;
121 #define PRINT_MF_COUNT 20000
122 #endif
124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
126 * Public data...
129 static struct proc_dir_entry *mpt_proc_root_dir;
131 #define WHOINIT_UNKNOWN 0xAA
133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
135 * Private data...
137 /* Adapter link list */
138 LIST_HEAD(ioc_list);
139 /* Callback lookup table */
140 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
141 /* Protocol driver class lookup table */
142 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
143 /* Event handler lookup table */
144 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
145 /* Reset handler lookup table */
146 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
147 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
149 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
152 * Driver Callback Index's
154 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
155 static u8 last_drv_idx;
157 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
159 * Forward protos...
161 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
162 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
163 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
164 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
165 int sleepFlag);
166 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
167 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
168 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
169 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
171 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
172 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
173 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
174 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
175 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
176 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
177 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
178 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
179 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
180 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
181 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
182 static int PrimeIocFifos(MPT_ADAPTER *ioc);
183 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
184 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
185 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
186 static int GetLanConfigPages(MPT_ADAPTER *ioc);
187 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
188 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
189 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
190 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
191 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
192 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
193 static void mpt_timer_expired(unsigned long data);
194 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
195 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
196 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
197 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
198 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
200 #ifdef CONFIG_PROC_FS
201 static int procmpt_summary_read(char *buf, char **start, off_t offset,
202 int request, int *eof, void *data);
203 static int procmpt_version_read(char *buf, char **start, off_t offset,
204 int request, int *eof, void *data);
205 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
206 int request, int *eof, void *data);
207 #endif
208 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
210 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
211 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
212 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
213 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
214 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
215 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
216 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
217 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
219 /* module entry point */
220 static int __init fusion_init (void);
221 static void __exit fusion_exit (void);
223 #define CHIPREG_READ32(addr) readl_relaxed(addr)
224 #define CHIPREG_READ32_dmasync(addr) readl(addr)
225 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
226 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
227 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
229 static void
230 pci_disable_io_access(struct pci_dev *pdev)
232 u16 command_reg;
234 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
235 command_reg &= ~1;
236 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
239 static void
240 pci_enable_io_access(struct pci_dev *pdev)
242 u16 command_reg;
244 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
245 command_reg |= 1;
246 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
249 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
251 int ret = param_set_int(val, kp);
252 MPT_ADAPTER *ioc;
254 if (ret)
255 return ret;
257 list_for_each_entry(ioc, &ioc_list, list)
258 ioc->debug_level = mpt_debug_level;
259 return 0;
263 * mpt_get_cb_idx - obtain cb_idx for registered driver
264 * @dclass: class driver enum
266 * Returns cb_idx, or zero means it wasn't found
268 static u8
269 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
271 u8 cb_idx;
273 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
274 if (MptDriverClass[cb_idx] == dclass)
275 return cb_idx;
276 return 0;
280 * mpt_fault_reset_work - work performed on workq after ioc fault
281 * @work: input argument, used to derive ioc
284 static void
285 mpt_fault_reset_work(struct work_struct *work)
287 MPT_ADAPTER *ioc =
288 container_of(work, MPT_ADAPTER, fault_reset_work.work);
289 u32 ioc_raw_state;
290 int rc;
291 unsigned long flags;
293 if (ioc->diagPending || !ioc->active)
294 goto out;
296 ioc_raw_state = mpt_GetIocState(ioc, 0);
297 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
298 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
299 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
300 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
301 ioc->name, __func__);
302 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
303 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
304 __func__, (rc == 0) ? "success" : "failed");
305 ioc_raw_state = mpt_GetIocState(ioc, 0);
306 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
307 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
308 "reset (%04xh)\n", ioc->name, ioc_raw_state &
309 MPI_DOORBELL_DATA_MASK);
312 out:
314 * Take turns polling alternate controller
316 if (ioc->alt_ioc)
317 ioc = ioc->alt_ioc;
319 /* rearm the timer */
320 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
321 if (ioc->reset_work_q)
322 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
323 msecs_to_jiffies(MPT_POLLING_INTERVAL));
324 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
329 * Process turbo (context) reply...
331 static void
332 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
334 MPT_FRAME_HDR *mf = NULL;
335 MPT_FRAME_HDR *mr = NULL;
336 u16 req_idx = 0;
337 u8 cb_idx;
339 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
340 ioc->name, pa));
342 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
343 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
344 req_idx = pa & 0x0000FFFF;
345 cb_idx = (pa & 0x00FF0000) >> 16;
346 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
347 break;
348 case MPI_CONTEXT_REPLY_TYPE_LAN:
349 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
351 * Blind set of mf to NULL here was fatal
352 * after lan_reply says "freeme"
353 * Fix sort of combined with an optimization here;
354 * added explicit check for case where lan_reply
355 * was just returning 1 and doing nothing else.
356 * For this case skip the callback, but set up
357 * proper mf value first here:-)
359 if ((pa & 0x58000000) == 0x58000000) {
360 req_idx = pa & 0x0000FFFF;
361 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
362 mpt_free_msg_frame(ioc, mf);
363 mb();
364 return;
365 break;
367 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
368 break;
369 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
370 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
371 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
372 break;
373 default:
374 cb_idx = 0;
375 BUG();
378 /* Check for (valid) IO callback! */
379 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
380 MptCallbacks[cb_idx] == NULL) {
381 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
382 __func__, ioc->name, cb_idx);
383 goto out;
386 if (MptCallbacks[cb_idx](ioc, mf, mr))
387 mpt_free_msg_frame(ioc, mf);
388 out:
389 mb();
392 static void
393 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
395 MPT_FRAME_HDR *mf;
396 MPT_FRAME_HDR *mr;
397 u16 req_idx;
398 u8 cb_idx;
399 int freeme;
401 u32 reply_dma_low;
402 u16 ioc_stat;
404 /* non-TURBO reply! Hmmm, something may be up...
405 * Newest turbo reply mechanism; get address
406 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
409 /* Map DMA address of reply header to cpu address.
410 * pa is 32 bits - but the dma address may be 32 or 64 bits
411 * get offset based only only the low addresses
414 reply_dma_low = (pa <<= 1);
415 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
416 (reply_dma_low - ioc->reply_frames_low_dma));
418 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
419 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
420 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
422 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
423 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
424 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
426 /* Check/log IOC log info
428 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
429 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
430 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
431 if (ioc->bus_type == FC)
432 mpt_fc_log_info(ioc, log_info);
433 else if (ioc->bus_type == SPI)
434 mpt_spi_log_info(ioc, log_info);
435 else if (ioc->bus_type == SAS)
436 mpt_sas_log_info(ioc, log_info);
439 if (ioc_stat & MPI_IOCSTATUS_MASK)
440 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
442 /* Check for (valid) IO callback! */
443 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
444 MptCallbacks[cb_idx] == NULL) {
445 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
446 __func__, ioc->name, cb_idx);
447 freeme = 0;
448 goto out;
451 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
453 out:
454 /* Flush (non-TURBO) reply with a WRITE! */
455 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
457 if (freeme)
458 mpt_free_msg_frame(ioc, mf);
459 mb();
462 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
464 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
465 * @irq: irq number (not used)
466 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
468 * This routine is registered via the request_irq() kernel API call,
469 * and handles all interrupts generated from a specific MPT adapter
470 * (also referred to as a IO Controller or IOC).
471 * This routine must clear the interrupt from the adapter and does
472 * so by reading the reply FIFO. Multiple replies may be processed
473 * per single call to this routine.
475 * This routine handles register-level access of the adapter but
476 * dispatches (calls) a protocol-specific callback routine to handle
477 * the protocol-specific details of the MPT request completion.
479 static irqreturn_t
480 mpt_interrupt(int irq, void *bus_id)
482 MPT_ADAPTER *ioc = bus_id;
483 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
485 if (pa == 0xFFFFFFFF)
486 return IRQ_NONE;
489 * Drain the reply FIFO!
491 do {
492 if (pa & MPI_ADDRESS_REPLY_A_BIT)
493 mpt_reply(ioc, pa);
494 else
495 mpt_turbo_reply(ioc, pa);
496 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
497 } while (pa != 0xFFFFFFFF);
499 return IRQ_HANDLED;
502 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
504 * mpt_base_reply - MPT base driver's callback routine
505 * @ioc: Pointer to MPT_ADAPTER structure
506 * @mf: Pointer to original MPT request frame
507 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
509 * MPT base driver's callback routine; all base driver
510 * "internal" request/reply processing is routed here.
511 * Currently used for EventNotification and EventAck handling.
513 * Returns 1 indicating original alloc'd request frame ptr
514 * should be freed, or 0 if it shouldn't.
516 static int
517 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
519 int freereq = 1;
520 u8 func;
522 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
523 #ifdef CONFIG_FUSION_LOGGING
524 if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
525 !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
526 dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
527 ioc->name, mf));
528 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
530 #endif
532 func = reply->u.hdr.Function;
533 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
534 ioc->name, func));
536 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
537 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
538 int evHandlers = 0;
539 int results;
541 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
542 if (results != evHandlers) {
543 /* CHECKME! Any special handling needed here? */
544 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
545 ioc->name, evHandlers, results));
549 * Hmmm... It seems that EventNotificationReply is an exception
550 * to the rule of one reply per request.
552 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
553 freereq = 0;
554 } else {
555 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
556 ioc->name, pEvReply));
559 #ifdef CONFIG_PROC_FS
560 // LogEvent(ioc, pEvReply);
561 #endif
563 } else if (func == MPI_FUNCTION_EVENT_ACK) {
564 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
565 ioc->name));
566 } else if (func == MPI_FUNCTION_CONFIG) {
567 CONFIGPARMS *pCfg;
568 unsigned long flags;
570 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
571 ioc->name, mf, reply));
573 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
575 if (pCfg) {
576 /* disable timer and remove from linked list */
577 del_timer(&pCfg->timer);
579 spin_lock_irqsave(&ioc->FreeQlock, flags);
580 list_del(&pCfg->linkage);
581 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
584 * If IOC Status is SUCCESS, save the header
585 * and set the status code to GOOD.
587 pCfg->status = MPT_CONFIG_ERROR;
588 if (reply) {
589 ConfigReply_t *pReply = (ConfigReply_t *)reply;
590 u16 status;
592 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
593 dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
594 ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
596 pCfg->status = status;
597 if (status == MPI_IOCSTATUS_SUCCESS) {
598 if ((pReply->Header.PageType &
599 MPI_CONFIG_PAGETYPE_MASK) ==
600 MPI_CONFIG_PAGETYPE_EXTENDED) {
601 pCfg->cfghdr.ehdr->ExtPageLength =
602 le16_to_cpu(pReply->ExtPageLength);
603 pCfg->cfghdr.ehdr->ExtPageType =
604 pReply->ExtPageType;
606 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
608 /* If this is a regular header, save PageLength. */
609 /* LMP Do this better so not using a reserved field! */
610 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
611 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
612 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
617 * Wake up the original calling thread
619 pCfg->wait_done = 1;
620 wake_up(&mpt_waitq);
622 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
623 /* we should be always getting a reply frame */
624 memcpy(ioc->persist_reply_frame, reply,
625 min(MPT_DEFAULT_FRAME_SIZE,
626 4*reply->u.reply.MsgLength));
627 del_timer(&ioc->persist_timer);
628 ioc->persist_wait_done = 1;
629 wake_up(&mpt_waitq);
630 } else {
631 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
632 ioc->name, func);
636 * Conditionally tell caller to free the original
637 * EventNotification/EventAck/unexpected request frame!
639 return freereq;
642 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
644 * mpt_register - Register protocol-specific main callback handler.
645 * @cbfunc: callback function pointer
646 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
648 * This routine is called by a protocol-specific driver (SCSI host,
649 * LAN, SCSI target) to register its reply callback routine. Each
650 * protocol-specific driver must do this before it will be able to
651 * use any IOC resources, such as obtaining request frames.
653 * NOTES: The SCSI protocol driver currently calls this routine thrice
654 * in order to register separate callbacks; one for "normal" SCSI IO;
655 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
657 * Returns u8 valued "handle" in the range (and S.O.D. order)
658 * {N,...,7,6,5,...,1} if successful.
659 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
660 * considered an error by the caller.
663 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
665 u8 cb_idx;
666 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
669 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
670 * (slot/handle 0 is reserved!)
672 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
673 if (MptCallbacks[cb_idx] == NULL) {
674 MptCallbacks[cb_idx] = cbfunc;
675 MptDriverClass[cb_idx] = dclass;
676 MptEvHandlers[cb_idx] = NULL;
677 last_drv_idx = cb_idx;
678 break;
682 return last_drv_idx;
685 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
687 * mpt_deregister - Deregister a protocol drivers resources.
688 * @cb_idx: previously registered callback handle
690 * Each protocol-specific driver should call this routine when its
691 * module is unloaded.
693 void
694 mpt_deregister(u8 cb_idx)
696 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
697 MptCallbacks[cb_idx] = NULL;
698 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
699 MptEvHandlers[cb_idx] = NULL;
701 last_drv_idx++;
705 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
707 * mpt_event_register - Register protocol-specific event callback handler.
708 * @cb_idx: previously registered (via mpt_register) callback handle
709 * @ev_cbfunc: callback function
711 * This routine can be called by one or more protocol-specific drivers
712 * if/when they choose to be notified of MPT events.
714 * Returns 0 for success.
717 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
719 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
720 return -1;
722 MptEvHandlers[cb_idx] = ev_cbfunc;
723 return 0;
726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
728 * mpt_event_deregister - Deregister protocol-specific event callback handler
729 * @cb_idx: previously registered callback handle
731 * Each protocol-specific driver should call this routine
732 * when it does not (or can no longer) handle events,
733 * or when its module is unloaded.
735 void
736 mpt_event_deregister(u8 cb_idx)
738 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
739 return;
741 MptEvHandlers[cb_idx] = NULL;
744 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
746 * mpt_reset_register - Register protocol-specific IOC reset handler.
747 * @cb_idx: previously registered (via mpt_register) callback handle
748 * @reset_func: reset function
750 * This routine can be called by one or more protocol-specific drivers
751 * if/when they choose to be notified of IOC resets.
753 * Returns 0 for success.
756 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
758 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
759 return -1;
761 MptResetHandlers[cb_idx] = reset_func;
762 return 0;
765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
767 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
768 * @cb_idx: previously registered callback handle
770 * Each protocol-specific driver should call this routine
771 * when it does not (or can no longer) handle IOC reset handling,
772 * or when its module is unloaded.
774 void
775 mpt_reset_deregister(u8 cb_idx)
777 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
778 return;
780 MptResetHandlers[cb_idx] = NULL;
783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
785 * mpt_device_driver_register - Register device driver hooks
786 * @dd_cbfunc: driver callbacks struct
787 * @cb_idx: MPT protocol driver index
790 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
792 MPT_ADAPTER *ioc;
793 const struct pci_device_id *id;
795 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
796 return -EINVAL;
798 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
800 /* call per pci device probe entry point */
801 list_for_each_entry(ioc, &ioc_list, list) {
802 id = ioc->pcidev->driver ?
803 ioc->pcidev->driver->id_table : NULL;
804 if (dd_cbfunc->probe)
805 dd_cbfunc->probe(ioc->pcidev, id);
808 return 0;
811 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
813 * mpt_device_driver_deregister - DeRegister device driver hooks
814 * @cb_idx: MPT protocol driver index
816 void
817 mpt_device_driver_deregister(u8 cb_idx)
819 struct mpt_pci_driver *dd_cbfunc;
820 MPT_ADAPTER *ioc;
822 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
823 return;
825 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
827 list_for_each_entry(ioc, &ioc_list, list) {
828 if (dd_cbfunc->remove)
829 dd_cbfunc->remove(ioc->pcidev);
832 MptDeviceDriverHandlers[cb_idx] = NULL;
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
838 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
839 * @cb_idx: Handle of registered MPT protocol driver
840 * @ioc: Pointer to MPT adapter structure
842 * Obtain an MPT request frame from the pool (of 1024) that are
843 * allocated per MPT adapter.
845 * Returns pointer to a MPT request frame or %NULL if none are available
846 * or IOC is not active.
848 MPT_FRAME_HDR*
849 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
851 MPT_FRAME_HDR *mf;
852 unsigned long flags;
853 u16 req_idx; /* Request index */
855 /* validate handle and ioc identifier */
857 #ifdef MFCNT
858 if (!ioc->active)
859 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
860 "returning NULL!\n", ioc->name);
861 #endif
863 /* If interrupts are not attached, do not return a request frame */
864 if (!ioc->active)
865 return NULL;
867 spin_lock_irqsave(&ioc->FreeQlock, flags);
868 if (!list_empty(&ioc->FreeQ)) {
869 int req_offset;
871 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
872 u.frame.linkage.list);
873 list_del(&mf->u.frame.linkage.list);
874 mf->u.frame.linkage.arg1 = 0;
875 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
876 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
877 /* u16! */
878 req_idx = req_offset / ioc->req_sz;
879 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
880 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
881 /* Default, will be changed if necessary in SG generation */
882 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
883 #ifdef MFCNT
884 ioc->mfcnt++;
885 #endif
887 else
888 mf = NULL;
889 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
891 #ifdef MFCNT
892 if (mf == NULL)
893 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
894 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
895 ioc->req_depth);
896 mfcounter++;
897 if (mfcounter == PRINT_MF_COUNT)
898 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
899 ioc->mfcnt, ioc->req_depth);
900 #endif
902 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
903 ioc->name, cb_idx, ioc->id, mf));
904 return mf;
907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
909 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
910 * @cb_idx: Handle of registered MPT protocol driver
911 * @ioc: Pointer to MPT adapter structure
912 * @mf: Pointer to MPT request frame
914 * This routine posts an MPT request frame to the request post FIFO of a
915 * specific MPT adapter.
917 void
918 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
920 u32 mf_dma_addr;
921 int req_offset;
922 u16 req_idx; /* Request index */
924 /* ensure values are reset properly! */
925 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
926 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
927 /* u16! */
928 req_idx = req_offset / ioc->req_sz;
929 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
930 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
932 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
934 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
935 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
936 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
937 ioc->RequestNB[req_idx]));
938 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
942 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
943 * @cb_idx: Handle of registered MPT protocol driver
944 * @ioc: Pointer to MPT adapter structure
945 * @mf: Pointer to MPT request frame
947 * Send a protocol-specific MPT request frame to an IOC using
948 * hi-priority request queue.
950 * This routine posts an MPT request frame to the request post FIFO of a
951 * specific MPT adapter.
953 void
954 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
956 u32 mf_dma_addr;
957 int req_offset;
958 u16 req_idx; /* Request index */
960 /* ensure values are reset properly! */
961 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
962 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
963 req_idx = req_offset / ioc->req_sz;
964 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
965 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
967 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
969 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
970 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
971 ioc->name, mf_dma_addr, req_idx));
972 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
975 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
977 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
978 * @ioc: Pointer to MPT adapter structure
979 * @mf: Pointer to MPT request frame
981 * This routine places a MPT request frame back on the MPT adapter's
982 * FreeQ.
984 void
985 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
987 unsigned long flags;
989 /* Put Request back on FreeQ! */
990 spin_lock_irqsave(&ioc->FreeQlock, flags);
991 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
992 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
993 #ifdef MFCNT
994 ioc->mfcnt--;
995 #endif
996 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
999 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1001 * mpt_add_sge - Place a simple SGE at address pAddr.
1002 * @pAddr: virtual address for SGE
1003 * @flagslength: SGE flags and data transfer length
1004 * @dma_addr: Physical address
1006 * This routine places a MPT request frame back on the MPT adapter's
1007 * FreeQ.
1009 void
1010 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
1012 if (sizeof(dma_addr_t) == sizeof(u64)) {
1013 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1014 u32 tmp = dma_addr & 0xFFFFFFFF;
1016 pSge->FlagsLength = cpu_to_le32(flagslength);
1017 pSge->Address.Low = cpu_to_le32(tmp);
1018 tmp = (u32) ((u64)dma_addr >> 32);
1019 pSge->Address.High = cpu_to_le32(tmp);
1021 } else {
1022 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1023 pSge->FlagsLength = cpu_to_le32(flagslength);
1024 pSge->Address = cpu_to_le32(dma_addr);
1028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1030 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1031 * @cb_idx: Handle of registered MPT protocol driver
1032 * @ioc: Pointer to MPT adapter structure
1033 * @reqBytes: Size of the request in bytes
1034 * @req: Pointer to MPT request frame
1035 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1037 * This routine is used exclusively to send MptScsiTaskMgmt
1038 * requests since they are required to be sent via doorbell handshake.
1040 * NOTE: It is the callers responsibility to byte-swap fields in the
1041 * request which are greater than 1 byte in size.
1043 * Returns 0 for success, non-zero for failure.
1046 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1048 int r = 0;
1049 u8 *req_as_bytes;
1050 int ii;
1052 /* State is known to be good upon entering
1053 * this function so issue the bus reset
1054 * request.
1058 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1059 * setting cb_idx/req_idx. But ONLY if this request
1060 * is in proper (pre-alloc'd) request buffer range...
1062 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1063 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1064 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1065 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1066 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1069 /* Make sure there are no doorbells */
1070 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1072 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1073 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1074 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1076 /* Wait for IOC doorbell int */
1077 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1078 return ii;
1081 /* Read doorbell and check for active bit */
1082 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1083 return -5;
1085 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1086 ioc->name, ii));
1088 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1090 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1091 return -2;
1094 /* Send request via doorbell handshake */
1095 req_as_bytes = (u8 *) req;
1096 for (ii = 0; ii < reqBytes/4; ii++) {
1097 u32 word;
1099 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1100 (req_as_bytes[(ii*4) + 1] << 8) |
1101 (req_as_bytes[(ii*4) + 2] << 16) |
1102 (req_as_bytes[(ii*4) + 3] << 24));
1103 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1104 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1105 r = -3;
1106 break;
1110 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1111 r = 0;
1112 else
1113 r = -4;
1115 /* Make sure there are no doorbells */
1116 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1118 return r;
1121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1123 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1124 * @ioc: Pointer to MPT adapter structure
1125 * @access_control_value: define bits below
1126 * @sleepFlag: Specifies whether the process can sleep
1128 * Provides mechanism for the host driver to control the IOC's
1129 * Host Page Buffer access.
1131 * Access Control Value - bits[15:12]
1132 * 0h Reserved
1133 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1134 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1135 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1137 * Returns 0 for success, non-zero for failure.
1140 static int
1141 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1143 int r = 0;
1145 /* return if in use */
1146 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1147 & MPI_DOORBELL_ACTIVE)
1148 return -1;
1150 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1152 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1153 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1154 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1155 (access_control_value<<12)));
1157 /* Wait for IOC to clear Doorbell Status bit */
1158 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1159 return -2;
1160 }else
1161 return 0;
1164 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1166 * mpt_host_page_alloc - allocate system memory for the fw
1167 * @ioc: Pointer to pointer to IOC adapter
1168 * @ioc_init: Pointer to ioc init config page
1170 * If we already allocated memory in past, then resend the same pointer.
1171 * Returns 0 for success, non-zero for failure.
1173 static int
1174 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1176 char *psge;
1177 int flags_length;
1178 u32 host_page_buffer_sz=0;
1180 if(!ioc->HostPageBuffer) {
1182 host_page_buffer_sz =
1183 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1185 if(!host_page_buffer_sz)
1186 return 0; /* fw doesn't need any host buffers */
1188 /* spin till we get enough memory */
1189 while(host_page_buffer_sz > 0) {
1191 if((ioc->HostPageBuffer = pci_alloc_consistent(
1192 ioc->pcidev,
1193 host_page_buffer_sz,
1194 &ioc->HostPageBuffer_dma)) != NULL) {
1196 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1197 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1198 ioc->name, ioc->HostPageBuffer,
1199 (u32)ioc->HostPageBuffer_dma,
1200 host_page_buffer_sz));
1201 ioc->alloc_total += host_page_buffer_sz;
1202 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1203 break;
1206 host_page_buffer_sz -= (4*1024);
1210 if(!ioc->HostPageBuffer) {
1211 printk(MYIOC_s_ERR_FMT
1212 "Failed to alloc memory for host_page_buffer!\n",
1213 ioc->name);
1214 return -999;
1217 psge = (char *)&ioc_init->HostPageBufferSGE;
1218 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1219 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1220 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1221 MPI_SGE_FLAGS_HOST_TO_IOC |
1222 MPI_SGE_FLAGS_END_OF_BUFFER;
1223 if (sizeof(dma_addr_t) == sizeof(u64)) {
1224 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1226 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1227 flags_length |= ioc->HostPageBuffer_sz;
1228 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1229 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1231 return 0;
1234 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1236 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1237 * @iocid: IOC unique identifier (integer)
1238 * @iocpp: Pointer to pointer to IOC adapter
1240 * Given a unique IOC identifier, set pointer to the associated MPT
1241 * adapter structure.
1243 * Returns iocid and sets iocpp if iocid is found.
1244 * Returns -1 if iocid is not found.
1247 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1249 MPT_ADAPTER *ioc;
1251 list_for_each_entry(ioc,&ioc_list,list) {
1252 if (ioc->id == iocid) {
1253 *iocpp =ioc;
1254 return iocid;
1258 *iocpp = NULL;
1259 return -1;
1263 * mpt_get_product_name - returns product string
1264 * @vendor: pci vendor id
1265 * @device: pci device id
1266 * @revision: pci revision id
1267 * @prod_name: string returned
1269 * Returns product string displayed when driver loads,
1270 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1273 static void
1274 mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1276 char *product_str = NULL;
1278 if (vendor == PCI_VENDOR_ID_BROCADE) {
1279 switch (device)
1281 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1282 switch (revision)
1284 case 0x00:
1285 product_str = "BRE040 A0";
1286 break;
1287 case 0x01:
1288 product_str = "BRE040 A1";
1289 break;
1290 default:
1291 product_str = "BRE040";
1292 break;
1294 break;
1296 goto out;
1299 switch (device)
1301 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1302 product_str = "LSIFC909 B1";
1303 break;
1304 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1305 product_str = "LSIFC919 B0";
1306 break;
1307 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1308 product_str = "LSIFC929 B0";
1309 break;
1310 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1311 if (revision < 0x80)
1312 product_str = "LSIFC919X A0";
1313 else
1314 product_str = "LSIFC919XL A1";
1315 break;
1316 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1317 if (revision < 0x80)
1318 product_str = "LSIFC929X A0";
1319 else
1320 product_str = "LSIFC929XL A1";
1321 break;
1322 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1323 product_str = "LSIFC939X A1";
1324 break;
1325 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1326 product_str = "LSIFC949X A1";
1327 break;
1328 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1329 switch (revision)
1331 case 0x00:
1332 product_str = "LSIFC949E A0";
1333 break;
1334 case 0x01:
1335 product_str = "LSIFC949E A1";
1336 break;
1337 default:
1338 product_str = "LSIFC949E";
1339 break;
1341 break;
1342 case MPI_MANUFACTPAGE_DEVID_53C1030:
1343 switch (revision)
1345 case 0x00:
1346 product_str = "LSI53C1030 A0";
1347 break;
1348 case 0x01:
1349 product_str = "LSI53C1030 B0";
1350 break;
1351 case 0x03:
1352 product_str = "LSI53C1030 B1";
1353 break;
1354 case 0x07:
1355 product_str = "LSI53C1030 B2";
1356 break;
1357 case 0x08:
1358 product_str = "LSI53C1030 C0";
1359 break;
1360 case 0x80:
1361 product_str = "LSI53C1030T A0";
1362 break;
1363 case 0x83:
1364 product_str = "LSI53C1030T A2";
1365 break;
1366 case 0x87:
1367 product_str = "LSI53C1030T A3";
1368 break;
1369 case 0xc1:
1370 product_str = "LSI53C1020A A1";
1371 break;
1372 default:
1373 product_str = "LSI53C1030";
1374 break;
1376 break;
1377 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1378 switch (revision)
1380 case 0x03:
1381 product_str = "LSI53C1035 A2";
1382 break;
1383 case 0x04:
1384 product_str = "LSI53C1035 B0";
1385 break;
1386 default:
1387 product_str = "LSI53C1035";
1388 break;
1390 break;
1391 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1392 switch (revision)
1394 case 0x00:
1395 product_str = "LSISAS1064 A1";
1396 break;
1397 case 0x01:
1398 product_str = "LSISAS1064 A2";
1399 break;
1400 case 0x02:
1401 product_str = "LSISAS1064 A3";
1402 break;
1403 case 0x03:
1404 product_str = "LSISAS1064 A4";
1405 break;
1406 default:
1407 product_str = "LSISAS1064";
1408 break;
1410 break;
1411 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1412 switch (revision)
1414 case 0x00:
1415 product_str = "LSISAS1064E A0";
1416 break;
1417 case 0x01:
1418 product_str = "LSISAS1064E B0";
1419 break;
1420 case 0x02:
1421 product_str = "LSISAS1064E B1";
1422 break;
1423 case 0x04:
1424 product_str = "LSISAS1064E B2";
1425 break;
1426 case 0x08:
1427 product_str = "LSISAS1064E B3";
1428 break;
1429 default:
1430 product_str = "LSISAS1064E";
1431 break;
1433 break;
1434 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1435 switch (revision)
1437 case 0x00:
1438 product_str = "LSISAS1068 A0";
1439 break;
1440 case 0x01:
1441 product_str = "LSISAS1068 B0";
1442 break;
1443 case 0x02:
1444 product_str = "LSISAS1068 B1";
1445 break;
1446 default:
1447 product_str = "LSISAS1068";
1448 break;
1450 break;
1451 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1452 switch (revision)
1454 case 0x00:
1455 product_str = "LSISAS1068E A0";
1456 break;
1457 case 0x01:
1458 product_str = "LSISAS1068E B0";
1459 break;
1460 case 0x02:
1461 product_str = "LSISAS1068E B1";
1462 break;
1463 case 0x04:
1464 product_str = "LSISAS1068E B2";
1465 break;
1466 case 0x08:
1467 product_str = "LSISAS1068E B3";
1468 break;
1469 default:
1470 product_str = "LSISAS1068E";
1471 break;
1473 break;
1474 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1475 switch (revision)
1477 case 0x00:
1478 product_str = "LSISAS1078 A0";
1479 break;
1480 case 0x01:
1481 product_str = "LSISAS1078 B0";
1482 break;
1483 case 0x02:
1484 product_str = "LSISAS1078 C0";
1485 break;
1486 case 0x03:
1487 product_str = "LSISAS1078 C1";
1488 break;
1489 case 0x04:
1490 product_str = "LSISAS1078 C2";
1491 break;
1492 default:
1493 product_str = "LSISAS1078";
1494 break;
1496 break;
1499 out:
1500 if (product_str)
1501 sprintf(prod_name, "%s", product_str);
1505 * mpt_mapresources - map in memory mapped io
1506 * @ioc: Pointer to pointer to IOC adapter
1509 static int
1510 mpt_mapresources(MPT_ADAPTER *ioc)
1512 u8 __iomem *mem;
1513 int ii;
1514 unsigned long mem_phys;
1515 unsigned long port;
1516 u32 msize;
1517 u32 psize;
1518 u8 revision;
1519 int r = -ENODEV;
1520 struct pci_dev *pdev;
1522 pdev = ioc->pcidev;
1523 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1524 if (pci_enable_device_mem(pdev)) {
1525 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1526 "failed\n", ioc->name);
1527 return r;
1529 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1530 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1531 "MEM failed\n", ioc->name);
1532 return r;
1535 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1537 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1538 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
1539 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1540 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1541 ioc->name));
1542 } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
1543 && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
1544 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1545 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1546 ioc->name));
1547 } else {
1548 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1549 ioc->name, pci_name(pdev));
1550 pci_release_selected_regions(pdev, ioc->bars);
1551 return r;
1554 mem_phys = msize = 0;
1555 port = psize = 0;
1556 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1557 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1558 if (psize)
1559 continue;
1560 /* Get I/O space! */
1561 port = pci_resource_start(pdev, ii);
1562 psize = pci_resource_len(pdev, ii);
1563 } else {
1564 if (msize)
1565 continue;
1566 /* Get memmap */
1567 mem_phys = pci_resource_start(pdev, ii);
1568 msize = pci_resource_len(pdev, ii);
1571 ioc->mem_size = msize;
1573 mem = NULL;
1574 /* Get logical ptr for PciMem0 space */
1575 /*mem = ioremap(mem_phys, msize);*/
1576 mem = ioremap(mem_phys, msize);
1577 if (mem == NULL) {
1578 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1579 " memory!\n", ioc->name);
1580 return -EINVAL;
1582 ioc->memmap = mem;
1583 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
1584 ioc->name, mem, mem_phys));
1586 ioc->mem_phys = mem_phys;
1587 ioc->chip = (SYSIF_REGS __iomem *)mem;
1589 /* Save Port IO values in case we need to do downloadboot */
1590 ioc->pio_mem_phys = port;
1591 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1593 return 0;
1596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1598 * mpt_attach - Install a PCI intelligent MPT adapter.
1599 * @pdev: Pointer to pci_dev structure
1600 * @id: PCI device ID information
1602 * This routine performs all the steps necessary to bring the IOC of
1603 * a MPT adapter to a OPERATIONAL state. This includes registering
1604 * memory regions, registering the interrupt, and allocating request
1605 * and reply memory pools.
1607 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1608 * MPT adapter.
1610 * Returns 0 for success, non-zero for failure.
1612 * TODO: Add support for polled controllers
1615 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1617 MPT_ADAPTER *ioc;
1618 u8 cb_idx;
1619 int r = -ENODEV;
1620 u8 revision;
1621 u8 pcixcmd;
1622 static int mpt_ids = 0;
1623 #ifdef CONFIG_PROC_FS
1624 struct proc_dir_entry *dent, *ent;
1625 #endif
1627 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1628 if (ioc == NULL) {
1629 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1630 return -ENOMEM;
1633 ioc->id = mpt_ids++;
1634 sprintf(ioc->name, "ioc%d", ioc->id);
1637 * set initial debug level
1638 * (refer to mptdebug.h)
1641 ioc->debug_level = mpt_debug_level;
1642 if (mpt_debug_level)
1643 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1645 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1647 ioc->pcidev = pdev;
1648 if (mpt_mapresources(ioc)) {
1649 kfree(ioc);
1650 return r;
1653 ioc->alloc_total = sizeof(MPT_ADAPTER);
1654 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1655 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1657 ioc->pcidev = pdev;
1658 ioc->diagPending = 0;
1659 spin_lock_init(&ioc->diagLock);
1660 spin_lock_init(&ioc->initializing_hba_lock);
1662 /* Initialize the event logging.
1664 ioc->eventTypes = 0; /* None */
1665 ioc->eventContext = 0;
1666 ioc->eventLogSize = 0;
1667 ioc->events = NULL;
1669 #ifdef MFCNT
1670 ioc->mfcnt = 0;
1671 #endif
1673 ioc->cached_fw = NULL;
1675 /* Initilize SCSI Config Data structure
1677 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1679 /* Initialize the running configQ head.
1681 INIT_LIST_HEAD(&ioc->configQ);
1683 /* Initialize the fc rport list head.
1685 INIT_LIST_HEAD(&ioc->fc_rports);
1687 /* Find lookup slot. */
1688 INIT_LIST_HEAD(&ioc->list);
1691 /* Initialize workqueue */
1692 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1693 spin_lock_init(&ioc->fault_reset_work_lock);
1695 snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
1696 "mpt_poll_%d", ioc->id);
1697 ioc->reset_work_q =
1698 create_singlethread_workqueue(ioc->reset_work_q_name);
1699 if (!ioc->reset_work_q) {
1700 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1701 ioc->name);
1702 pci_release_selected_regions(pdev, ioc->bars);
1703 kfree(ioc);
1704 return -ENOMEM;
1707 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1708 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1710 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1711 mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1713 switch (pdev->device)
1715 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1716 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1717 ioc->errata_flag_1064 = 1;
1718 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1719 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1720 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1721 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1722 ioc->bus_type = FC;
1723 break;
1725 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1726 if (revision < XL_929) {
1727 /* 929X Chip Fix. Set Split transactions level
1728 * for PCIX. Set MOST bits to zero.
1730 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1731 pcixcmd &= 0x8F;
1732 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1733 } else {
1734 /* 929XL Chip Fix. Set MMRBC to 0x08.
1736 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1737 pcixcmd |= 0x08;
1738 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1740 ioc->bus_type = FC;
1741 break;
1743 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1744 /* 919X Chip Fix. Set Split transactions level
1745 * for PCIX. Set MOST bits to zero.
1747 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1748 pcixcmd &= 0x8F;
1749 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1750 ioc->bus_type = FC;
1751 break;
1753 case MPI_MANUFACTPAGE_DEVID_53C1030:
1754 /* 1030 Chip Fix. Disable Split transactions
1755 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1757 if (revision < C0_1030) {
1758 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1759 pcixcmd &= 0x8F;
1760 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1763 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1764 ioc->bus_type = SPI;
1765 break;
1767 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1768 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1769 ioc->errata_flag_1064 = 1;
1771 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1772 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1773 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1774 ioc->bus_type = SAS;
1778 switch (ioc->bus_type) {
1780 case SAS:
1781 ioc->msi_enable = mpt_msi_enable_sas;
1782 break;
1784 case SPI:
1785 ioc->msi_enable = mpt_msi_enable_spi;
1786 break;
1788 case FC:
1789 ioc->msi_enable = mpt_msi_enable_fc;
1790 break;
1792 default:
1793 ioc->msi_enable = 0;
1794 break;
1796 if (ioc->errata_flag_1064)
1797 pci_disable_io_access(pdev);
1799 spin_lock_init(&ioc->FreeQlock);
1801 /* Disable all! */
1802 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1803 ioc->active = 0;
1804 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1806 /* Set IOC ptr in the pcidev's driver data. */
1807 pci_set_drvdata(ioc->pcidev, ioc);
1809 /* Set lookup ptr. */
1810 list_add_tail(&ioc->list, &ioc_list);
1812 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1814 mpt_detect_bound_ports(ioc, pdev);
1816 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1817 CAN_SLEEP)) != 0){
1818 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1819 ioc->name, r);
1821 list_del(&ioc->list);
1822 if (ioc->alt_ioc)
1823 ioc->alt_ioc->alt_ioc = NULL;
1824 iounmap(ioc->memmap);
1825 if (r != -5)
1826 pci_release_selected_regions(pdev, ioc->bars);
1828 destroy_workqueue(ioc->reset_work_q);
1829 ioc->reset_work_q = NULL;
1831 kfree(ioc);
1832 pci_set_drvdata(pdev, NULL);
1833 return r;
1836 /* call per device driver probe entry point */
1837 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1838 if(MptDeviceDriverHandlers[cb_idx] &&
1839 MptDeviceDriverHandlers[cb_idx]->probe) {
1840 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1844 #ifdef CONFIG_PROC_FS
1846 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1848 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1849 if (dent) {
1850 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1851 if (ent) {
1852 ent->read_proc = procmpt_iocinfo_read;
1853 ent->data = ioc;
1855 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1856 if (ent) {
1857 ent->read_proc = procmpt_summary_read;
1858 ent->data = ioc;
1861 #endif
1863 if (!ioc->alt_ioc)
1864 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1865 msecs_to_jiffies(MPT_POLLING_INTERVAL));
1867 return 0;
1870 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1872 * mpt_detach - Remove a PCI intelligent MPT adapter.
1873 * @pdev: Pointer to pci_dev structure
1876 void
1877 mpt_detach(struct pci_dev *pdev)
1879 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1880 char pname[32];
1881 u8 cb_idx;
1882 unsigned long flags;
1883 struct workqueue_struct *wq;
1886 * Stop polling ioc for fault condition
1888 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
1889 wq = ioc->reset_work_q;
1890 ioc->reset_work_q = NULL;
1891 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
1892 cancel_delayed_work(&ioc->fault_reset_work);
1893 destroy_workqueue(wq);
1896 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1897 remove_proc_entry(pname, NULL);
1898 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1899 remove_proc_entry(pname, NULL);
1900 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1901 remove_proc_entry(pname, NULL);
1903 /* call per device driver remove entry point */
1904 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1905 if(MptDeviceDriverHandlers[cb_idx] &&
1906 MptDeviceDriverHandlers[cb_idx]->remove) {
1907 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
1911 /* Disable interrupts! */
1912 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1914 ioc->active = 0;
1915 synchronize_irq(pdev->irq);
1917 /* Clear any lingering interrupt */
1918 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1920 CHIPREG_READ32(&ioc->chip->IntStatus);
1922 mpt_adapter_dispose(ioc);
1924 pci_set_drvdata(pdev, NULL);
1927 /**************************************************************************
1928 * Power Management
1930 #ifdef CONFIG_PM
1931 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1933 * mpt_suspend - Fusion MPT base driver suspend routine.
1934 * @pdev: Pointer to pci_dev structure
1935 * @state: new state to enter
1938 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1940 u32 device_state;
1941 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1943 device_state = pci_choose_state(pdev, state);
1944 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
1945 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1946 device_state);
1948 /* put ioc into READY_STATE */
1949 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1950 printk(MYIOC_s_ERR_FMT
1951 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1954 /* disable interrupts */
1955 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1956 ioc->active = 0;
1958 /* Clear any lingering interrupt */
1959 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1961 free_irq(ioc->pci_irq, ioc);
1962 if (ioc->msi_enable)
1963 pci_disable_msi(ioc->pcidev);
1964 ioc->pci_irq = -1;
1965 pci_save_state(pdev);
1966 pci_disable_device(pdev);
1967 pci_release_selected_regions(pdev, ioc->bars);
1968 pci_set_power_state(pdev, device_state);
1969 return 0;
1972 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1974 * mpt_resume - Fusion MPT base driver resume routine.
1975 * @pdev: Pointer to pci_dev structure
1978 mpt_resume(struct pci_dev *pdev)
1980 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1981 u32 device_state = pdev->current_state;
1982 int recovery_state;
1983 int err;
1985 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
1986 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1987 device_state);
1989 pci_set_power_state(pdev, PCI_D0);
1990 pci_enable_wake(pdev, PCI_D0, 0);
1991 pci_restore_state(pdev);
1992 ioc->pcidev = pdev;
1993 err = mpt_mapresources(ioc);
1994 if (err)
1995 return err;
1997 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1998 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1999 CHIPREG_READ32(&ioc->chip->Doorbell));
2002 * Errata workaround for SAS pci express:
2003 * Upon returning to the D0 state, the contents of the doorbell will be
2004 * stale data, and this will incorrectly signal to the host driver that
2005 * the firmware is ready to process mpt commands. The workaround is
2006 * to issue a diagnostic reset.
2008 if (ioc->bus_type == SAS && (pdev->device ==
2009 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2010 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2011 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2012 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2013 ioc->name);
2014 goto out;
2018 /* bring ioc to operational state */
2019 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2020 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2021 CAN_SLEEP);
2022 if (recovery_state != 0)
2023 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2024 "error:[%x]\n", ioc->name, recovery_state);
2025 else
2026 printk(MYIOC_s_INFO_FMT
2027 "pci-resume: success\n", ioc->name);
2028 out:
2029 return 0;
2032 #endif
2034 static int
2035 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2037 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2038 ioc->bus_type != SPI) ||
2039 (MptDriverClass[index] == MPTFC_DRIVER &&
2040 ioc->bus_type != FC) ||
2041 (MptDriverClass[index] == MPTSAS_DRIVER &&
2042 ioc->bus_type != SAS))
2043 /* make sure we only call the relevant reset handler
2044 * for the bus */
2045 return 0;
2046 return (MptResetHandlers[index])(ioc, reset_phase);
2049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2051 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2052 * @ioc: Pointer to MPT adapter structure
2053 * @reason: Event word / reason
2054 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2056 * This routine performs all the steps necessary to bring the IOC
2057 * to a OPERATIONAL state.
2059 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2060 * MPT adapter.
2062 * Returns:
2063 * 0 for success
2064 * -1 if failed to get board READY
2065 * -2 if READY but IOCFacts Failed
2066 * -3 if READY but PrimeIOCFifos Failed
2067 * -4 if READY but IOCInit Failed
2068 * -5 if failed to enable_device and/or request_selected_regions
2069 * -6 if failed to upload firmware
2071 static int
2072 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2074 int hard_reset_done = 0;
2075 int alt_ioc_ready = 0;
2076 int hard;
2077 int rc=0;
2078 int ii;
2079 u8 cb_idx;
2080 int handlers;
2081 int ret = 0;
2082 int reset_alt_ioc_active = 0;
2083 int irq_allocated = 0;
2084 u8 *a;
2086 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2087 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2089 /* Disable reply interrupts (also blocks FreeQ) */
2090 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2091 ioc->active = 0;
2093 if (ioc->alt_ioc) {
2094 if (ioc->alt_ioc->active)
2095 reset_alt_ioc_active = 1;
2097 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
2098 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
2099 ioc->alt_ioc->active = 0;
2102 hard = 1;
2103 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2104 hard = 0;
2106 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2107 if (hard_reset_done == -4) {
2108 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2109 ioc->name);
2111 if (reset_alt_ioc_active && ioc->alt_ioc) {
2112 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2113 dprintk(ioc, printk(MYIOC_s_INFO_FMT
2114 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2115 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2116 ioc->alt_ioc->active = 1;
2119 } else {
2120 printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
2122 return -1;
2125 /* hard_reset_done = 0 if a soft reset was performed
2126 * and 1 if a hard reset was performed.
2128 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2129 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2130 alt_ioc_ready = 1;
2131 else
2132 printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
2135 for (ii=0; ii<5; ii++) {
2136 /* Get IOC facts! Allow 5 retries */
2137 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2138 break;
2142 if (ii == 5) {
2143 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2144 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2145 ret = -2;
2146 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2147 MptDisplayIocCapabilities(ioc);
2150 if (alt_ioc_ready) {
2151 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2152 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2153 "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
2154 /* Retry - alt IOC was initialized once
2156 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2158 if (rc) {
2159 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2160 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2161 alt_ioc_ready = 0;
2162 reset_alt_ioc_active = 0;
2163 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2164 MptDisplayIocCapabilities(ioc->alt_ioc);
2168 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2169 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2170 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2171 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2172 IORESOURCE_IO);
2173 if (pci_enable_device(ioc->pcidev))
2174 return -5;
2175 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2176 "mpt"))
2177 return -5;
2181 * Device is reset now. It must have de-asserted the interrupt line
2182 * (if it was asserted) and it should be safe to register for the
2183 * interrupt now.
2185 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2186 ioc->pci_irq = -1;
2187 if (ioc->pcidev->irq) {
2188 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2189 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2190 ioc->name);
2191 else
2192 ioc->msi_enable = 0;
2193 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2194 IRQF_SHARED, ioc->name, ioc);
2195 if (rc < 0) {
2196 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2197 "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
2198 if (ioc->msi_enable)
2199 pci_disable_msi(ioc->pcidev);
2200 return -EBUSY;
2202 irq_allocated = 1;
2203 ioc->pci_irq = ioc->pcidev->irq;
2204 pci_set_master(ioc->pcidev); /* ?? */
2205 dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
2206 "%d\n", ioc->name, ioc->pcidev->irq));
2210 /* Prime reply & request queues!
2211 * (mucho alloc's) Must be done prior to
2212 * init as upper addresses are needed for init.
2213 * If fails, continue with alt-ioc processing
2215 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2216 ret = -3;
2218 /* May need to check/upload firmware & data here!
2219 * If fails, continue with alt-ioc processing
2221 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2222 ret = -4;
2223 // NEW!
2224 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2225 printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
2226 ioc->alt_ioc->name, rc);
2227 alt_ioc_ready = 0;
2228 reset_alt_ioc_active = 0;
2231 if (alt_ioc_ready) {
2232 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2233 alt_ioc_ready = 0;
2234 reset_alt_ioc_active = 0;
2235 printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
2236 ioc->alt_ioc->name, rc);
2240 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2241 if (ioc->upload_fw) {
2242 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2243 "firmware upload required!\n", ioc->name));
2245 /* Controller is not operational, cannot do upload
2247 if (ret == 0) {
2248 rc = mpt_do_upload(ioc, sleepFlag);
2249 if (rc == 0) {
2250 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2252 * Maintain only one pointer to FW memory
2253 * so there will not be two attempt to
2254 * downloadboot onboard dual function
2255 * chips (mpt_adapter_disable,
2256 * mpt_diag_reset)
2258 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2259 "mpt_upload: alt_%s has cached_fw=%p \n",
2260 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2261 ioc->cached_fw = NULL;
2263 } else {
2264 printk(MYIOC_s_WARN_FMT
2265 "firmware upload failure!\n", ioc->name);
2266 ret = -6;
2272 if (ret == 0) {
2273 /* Enable! (reply interrupt) */
2274 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2275 ioc->active = 1;
2278 if (reset_alt_ioc_active && ioc->alt_ioc) {
2279 /* (re)Enable alt-IOC! (reply interrupt) */
2280 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
2281 ioc->alt_ioc->name));
2282 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2283 ioc->alt_ioc->active = 1;
2286 /* Enable MPT base driver management of EventNotification
2287 * and EventAck handling.
2289 if ((ret == 0) && (!ioc->facts.EventState))
2290 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
2292 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2293 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
2295 /* Add additional "reason" check before call to GetLanConfigPages
2296 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2297 * recursive scenario; GetLanConfigPages times out, timer expired
2298 * routine calls HardResetHandler, which calls into here again,
2299 * and we try GetLanConfigPages again...
2301 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2304 * Initalize link list for inactive raid volumes.
2306 mutex_init(&ioc->raid_data.inactive_list_mutex);
2307 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2309 if (ioc->bus_type == SAS) {
2311 /* clear persistency table */
2312 if(ioc->facts.IOCExceptions &
2313 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2314 ret = mptbase_sas_persist_operation(ioc,
2315 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2316 if(ret != 0)
2317 goto out;
2320 /* Find IM volumes
2322 mpt_findImVolumes(ioc);
2324 } else if (ioc->bus_type == FC) {
2325 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
2326 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2328 * Pre-fetch the ports LAN MAC address!
2329 * (LANPage1_t stuff)
2331 (void) GetLanConfigPages(ioc);
2332 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2333 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2334 "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2335 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
2338 } else {
2339 /* Get NVRAM and adapter maximums from SPP 0 and 2
2341 mpt_GetScsiPortSettings(ioc, 0);
2343 /* Get version and length of SDP 1
2345 mpt_readScsiDevicePageHeaders(ioc, 0);
2347 /* Find IM volumes
2349 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2350 mpt_findImVolumes(ioc);
2352 /* Check, and possibly reset, the coalescing value
2354 mpt_read_ioc_pg_1(ioc);
2356 mpt_read_ioc_pg_4(ioc);
2359 GetIoUnitPage2(ioc);
2360 mpt_get_manufacturing_pg_0(ioc);
2364 * Call each currently registered protocol IOC reset handler
2365 * with post-reset indication.
2366 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2367 * MptResetHandlers[] registered yet.
2369 if (hard_reset_done) {
2370 rc = handlers = 0;
2371 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2372 if ((ret == 0) && MptResetHandlers[cb_idx]) {
2373 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2374 "Calling IOC post_reset handler #%d\n",
2375 ioc->name, cb_idx));
2376 rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2377 handlers++;
2380 if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2381 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2382 "Calling IOC post_reset handler #%d\n",
2383 ioc->alt_ioc->name, cb_idx));
2384 rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2385 handlers++;
2388 /* FIXME? Examine results here? */
2391 out:
2392 if ((ret != 0) && irq_allocated) {
2393 free_irq(ioc->pci_irq, ioc);
2394 if (ioc->msi_enable)
2395 pci_disable_msi(ioc->pcidev);
2397 return ret;
2400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2402 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2403 * @ioc: Pointer to MPT adapter structure
2404 * @pdev: Pointer to (struct pci_dev) structure
2406 * Search for PCI bus/dev_function which matches
2407 * PCI bus/dev_function (+/-1) for newly discovered 929,
2408 * 929X, 1030 or 1035.
2410 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2411 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2413 static void
2414 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2416 struct pci_dev *peer=NULL;
2417 unsigned int slot = PCI_SLOT(pdev->devfn);
2418 unsigned int func = PCI_FUNC(pdev->devfn);
2419 MPT_ADAPTER *ioc_srch;
2421 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2422 " searching for devfn match on %x or %x\n",
2423 ioc->name, pci_name(pdev), pdev->bus->number,
2424 pdev->devfn, func-1, func+1));
2426 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2427 if (!peer) {
2428 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2429 if (!peer)
2430 return;
2433 list_for_each_entry(ioc_srch, &ioc_list, list) {
2434 struct pci_dev *_pcidev = ioc_srch->pcidev;
2435 if (_pcidev == peer) {
2436 /* Paranoia checks */
2437 if (ioc->alt_ioc != NULL) {
2438 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2439 ioc->name, ioc->alt_ioc->name);
2440 break;
2441 } else if (ioc_srch->alt_ioc != NULL) {
2442 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2443 ioc_srch->name, ioc_srch->alt_ioc->name);
2444 break;
2446 dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
2447 ioc->name, ioc_srch->name));
2448 ioc_srch->alt_ioc = ioc;
2449 ioc->alt_ioc = ioc_srch;
2452 pci_dev_put(peer);
2455 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2457 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2458 * @ioc: Pointer to MPT adapter structure
2460 static void
2461 mpt_adapter_disable(MPT_ADAPTER *ioc)
2463 int sz;
2464 int ret;
2466 if (ioc->cached_fw != NULL) {
2467 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2468 "adapter\n", __func__, ioc->name));
2469 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2470 ioc->cached_fw, CAN_SLEEP)) < 0) {
2471 printk(MYIOC_s_WARN_FMT
2472 ": firmware downloadboot failure (%d)!\n",
2473 ioc->name, ret);
2477 /* Disable adapter interrupts! */
2478 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2479 ioc->active = 0;
2480 /* Clear any lingering interrupt */
2481 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2483 if (ioc->alloc != NULL) {
2484 sz = ioc->alloc_sz;
2485 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2486 ioc->name, ioc->alloc, ioc->alloc_sz));
2487 pci_free_consistent(ioc->pcidev, sz,
2488 ioc->alloc, ioc->alloc_dma);
2489 ioc->reply_frames = NULL;
2490 ioc->req_frames = NULL;
2491 ioc->alloc = NULL;
2492 ioc->alloc_total -= sz;
2495 if (ioc->sense_buf_pool != NULL) {
2496 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2497 pci_free_consistent(ioc->pcidev, sz,
2498 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2499 ioc->sense_buf_pool = NULL;
2500 ioc->alloc_total -= sz;
2503 if (ioc->events != NULL){
2504 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2505 kfree(ioc->events);
2506 ioc->events = NULL;
2507 ioc->alloc_total -= sz;
2510 mpt_free_fw_memory(ioc);
2512 kfree(ioc->spi_data.nvram);
2513 mpt_inactive_raid_list_free(ioc);
2514 kfree(ioc->raid_data.pIocPg2);
2515 kfree(ioc->raid_data.pIocPg3);
2516 ioc->spi_data.nvram = NULL;
2517 ioc->raid_data.pIocPg3 = NULL;
2519 if (ioc->spi_data.pIocPg4 != NULL) {
2520 sz = ioc->spi_data.IocPg4Sz;
2521 pci_free_consistent(ioc->pcidev, sz,
2522 ioc->spi_data.pIocPg4,
2523 ioc->spi_data.IocPg4_dma);
2524 ioc->spi_data.pIocPg4 = NULL;
2525 ioc->alloc_total -= sz;
2528 if (ioc->ReqToChain != NULL) {
2529 kfree(ioc->ReqToChain);
2530 kfree(ioc->RequestNB);
2531 ioc->ReqToChain = NULL;
2534 kfree(ioc->ChainToChain);
2535 ioc->ChainToChain = NULL;
2537 if (ioc->HostPageBuffer != NULL) {
2538 if((ret = mpt_host_page_access_control(ioc,
2539 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2540 printk(MYIOC_s_ERR_FMT
2541 "host page buffers free failed (%d)!\n",
2542 ioc->name, ret);
2544 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n",
2545 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2546 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2547 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2548 ioc->HostPageBuffer = NULL;
2549 ioc->HostPageBuffer_sz = 0;
2550 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2554 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2556 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2557 * @ioc: Pointer to MPT adapter structure
2559 * This routine unregisters h/w resources and frees all alloc'd memory
2560 * associated with a MPT adapter structure.
2562 static void
2563 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2565 int sz_first, sz_last;
2567 if (ioc == NULL)
2568 return;
2570 sz_first = ioc->alloc_total;
2572 mpt_adapter_disable(ioc);
2574 if (ioc->pci_irq != -1) {
2575 free_irq(ioc->pci_irq, ioc);
2576 if (ioc->msi_enable)
2577 pci_disable_msi(ioc->pcidev);
2578 ioc->pci_irq = -1;
2581 if (ioc->memmap != NULL) {
2582 iounmap(ioc->memmap);
2583 ioc->memmap = NULL;
2586 pci_disable_device(ioc->pcidev);
2587 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2589 #if defined(CONFIG_MTRR) && 0
2590 if (ioc->mtrr_reg > 0) {
2591 mtrr_del(ioc->mtrr_reg, 0, 0);
2592 dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2594 #endif
2596 /* Zap the adapter lookup ptr! */
2597 list_del(&ioc->list);
2599 sz_last = ioc->alloc_total;
2600 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2601 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2603 if (ioc->alt_ioc)
2604 ioc->alt_ioc->alt_ioc = NULL;
2606 kfree(ioc);
2609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2611 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2612 * @ioc: Pointer to MPT adapter structure
2614 static void
2615 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2617 int i = 0;
2619 printk(KERN_INFO "%s: ", ioc->name);
2620 if (ioc->prod_name)
2621 printk("%s: ", ioc->prod_name);
2622 printk("Capabilities={");
2624 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2625 printk("Initiator");
2626 i++;
2629 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2630 printk("%sTarget", i ? "," : "");
2631 i++;
2634 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2635 printk("%sLAN", i ? "," : "");
2636 i++;
2639 #if 0
2641 * This would probably evoke more questions than it's worth
2643 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2644 printk("%sLogBusAddr", i ? "," : "");
2645 i++;
2647 #endif
2649 printk("}\n");
2652 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2654 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2655 * @ioc: Pointer to MPT_ADAPTER structure
2656 * @force: Force hard KickStart of IOC
2657 * @sleepFlag: Specifies whether the process can sleep
2659 * Returns:
2660 * 1 - DIAG reset and READY
2661 * 0 - READY initially OR soft reset and READY
2662 * -1 - Any failure on KickStart
2663 * -2 - Msg Unit Reset Failed
2664 * -3 - IO Unit Reset Failed
2665 * -4 - IOC owned by a PEER
2667 static int
2668 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2670 u32 ioc_state;
2671 int statefault = 0;
2672 int cntdn;
2673 int hard_reset_done = 0;
2674 int r;
2675 int ii;
2676 int whoinit;
2678 /* Get current [raw] IOC state */
2679 ioc_state = mpt_GetIocState(ioc, 0);
2680 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2683 * Check to see if IOC got left/stuck in doorbell handshake
2684 * grip of death. If so, hard reset the IOC.
2686 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2687 statefault = 1;
2688 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2689 ioc->name);
2692 /* Is it already READY? */
2693 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2694 return 0;
2697 * Check to see if IOC is in FAULT state.
2699 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2700 statefault = 2;
2701 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2702 ioc->name);
2703 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2704 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2708 * Hmmm... Did it get left operational?
2710 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2711 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2712 ioc->name));
2714 /* Check WhoInit.
2715 * If PCI Peer, exit.
2716 * Else, if no fault conditions are present, issue a MessageUnitReset
2717 * Else, fall through to KickStart case
2719 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2720 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2721 "whoinit 0x%x statefault %d force %d\n",
2722 ioc->name, whoinit, statefault, force));
2723 if (whoinit == MPI_WHOINIT_PCI_PEER)
2724 return -4;
2725 else {
2726 if ((statefault == 0 ) && (force == 0)) {
2727 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2728 return 0;
2730 statefault = 3;
2734 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2735 if (hard_reset_done < 0)
2736 return -1;
2739 * Loop here waiting for IOC to come READY.
2741 ii = 0;
2742 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2744 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2745 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2747 * BIOS or previous driver load left IOC in OP state.
2748 * Reset messaging FIFOs.
2750 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2751 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2752 return -2;
2754 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2756 * Something is wrong. Try to get IOC back
2757 * to a known state.
2759 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2760 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2761 return -3;
2765 ii++; cntdn--;
2766 if (!cntdn) {
2767 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2768 ioc->name, (int)((ii+5)/HZ));
2769 return -ETIME;
2772 if (sleepFlag == CAN_SLEEP) {
2773 msleep(1);
2774 } else {
2775 mdelay (1); /* 1 msec delay */
2780 if (statefault < 3) {
2781 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2782 ioc->name,
2783 statefault==1 ? "stuck handshake" : "IOC FAULT");
2786 return hard_reset_done;
2789 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2791 * mpt_GetIocState - Get the current state of a MPT adapter.
2792 * @ioc: Pointer to MPT_ADAPTER structure
2793 * @cooked: Request raw or cooked IOC state
2795 * Returns all IOC Doorbell register bits if cooked==0, else just the
2796 * Doorbell bits in MPI_IOC_STATE_MASK.
2799 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2801 u32 s, sc;
2803 /* Get! */
2804 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2805 sc = s & MPI_IOC_STATE_MASK;
2807 /* Save! */
2808 ioc->last_state = sc;
2810 return cooked ? sc : s;
2813 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2815 * GetIocFacts - Send IOCFacts request to MPT adapter.
2816 * @ioc: Pointer to MPT_ADAPTER structure
2817 * @sleepFlag: Specifies whether the process can sleep
2818 * @reason: If recovery, only update facts.
2820 * Returns 0 for success, non-zero for failure.
2822 static int
2823 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2825 IOCFacts_t get_facts;
2826 IOCFactsReply_t *facts;
2827 int r;
2828 int req_sz;
2829 int reply_sz;
2830 int sz;
2831 u32 status, vv;
2832 u8 shiftFactor=1;
2834 /* IOC *must* NOT be in RESET state! */
2835 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2836 printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
2837 ioc->name, ioc->last_state );
2838 return -44;
2841 facts = &ioc->facts;
2843 /* Destination (reply area)... */
2844 reply_sz = sizeof(*facts);
2845 memset(facts, 0, reply_sz);
2847 /* Request area (get_facts on the stack right now!) */
2848 req_sz = sizeof(get_facts);
2849 memset(&get_facts, 0, req_sz);
2851 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2852 /* Assert: All other get_facts fields are zero! */
2854 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2855 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2856 ioc->name, req_sz, reply_sz));
2858 /* No non-zero fields in the get_facts request are greater than
2859 * 1 byte in size, so we can just fire it off as is.
2861 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2862 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2863 if (r != 0)
2864 return r;
2867 * Now byte swap (GRRR) the necessary fields before any further
2868 * inspection of reply contents.
2870 * But need to do some sanity checks on MsgLength (byte) field
2871 * to make sure we don't zero IOC's req_sz!
2873 /* Did we get a valid reply? */
2874 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2875 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2877 * If not been here, done that, save off first WhoInit value
2879 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2880 ioc->FirstWhoInit = facts->WhoInit;
2883 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2884 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2885 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2886 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2887 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2888 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2889 /* CHECKME! IOCStatus, IOCLogInfo */
2891 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2892 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2895 * FC f/w version changed between 1.1 and 1.2
2896 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2897 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2899 if (facts->MsgVersion < 0x0102) {
2901 * Handle old FC f/w style, convert to new...
2903 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2904 facts->FWVersion.Word =
2905 ((oldv<<12) & 0xFF000000) |
2906 ((oldv<<8) & 0x000FFF00);
2907 } else
2908 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2910 facts->ProductID = le16_to_cpu(facts->ProductID);
2911 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2912 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
2913 ioc->ir_firmware = 1;
2914 facts->CurrentHostMfaHighAddr =
2915 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2916 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2917 facts->CurrentSenseBufferHighAddr =
2918 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2919 facts->CurReplyFrameSize =
2920 le16_to_cpu(facts->CurReplyFrameSize);
2921 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2924 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2925 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2926 * to 14 in MPI-1.01.0x.
2928 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2929 facts->MsgVersion > 0x0100) {
2930 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2933 sz = facts->FWImageSize;
2934 if ( sz & 0x01 )
2935 sz += 1;
2936 if ( sz & 0x02 )
2937 sz += 2;
2938 facts->FWImageSize = sz;
2940 if (!facts->RequestFrameSize) {
2941 /* Something is wrong! */
2942 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2943 ioc->name);
2944 return -55;
2947 r = sz = facts->BlockSize;
2948 vv = ((63 / (sz * 4)) + 1) & 0x03;
2949 ioc->NB_for_64_byte_frame = vv;
2950 while ( sz )
2952 shiftFactor++;
2953 sz = sz >> 1;
2955 ioc->NBShiftFactor = shiftFactor;
2956 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2957 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2958 ioc->name, vv, shiftFactor, r));
2960 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2962 * Set values for this IOC's request & reply frame sizes,
2963 * and request & reply queue depths...
2965 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2966 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2967 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2968 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2970 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
2971 ioc->name, ioc->reply_sz, ioc->reply_depth));
2972 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
2973 ioc->name, ioc->req_sz, ioc->req_depth));
2975 /* Get port facts! */
2976 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2977 return r;
2979 } else {
2980 printk(MYIOC_s_ERR_FMT
2981 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2982 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2983 RequestFrameSize)/sizeof(u32)));
2984 return -66;
2987 return 0;
2990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2992 * GetPortFacts - Send PortFacts request to MPT adapter.
2993 * @ioc: Pointer to MPT_ADAPTER structure
2994 * @portnum: Port number
2995 * @sleepFlag: Specifies whether the process can sleep
2997 * Returns 0 for success, non-zero for failure.
2999 static int
3000 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3002 PortFacts_t get_pfacts;
3003 PortFactsReply_t *pfacts;
3004 int ii;
3005 int req_sz;
3006 int reply_sz;
3007 int max_id;
3009 /* IOC *must* NOT be in RESET state! */
3010 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3011 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3012 ioc->name, ioc->last_state );
3013 return -4;
3016 pfacts = &ioc->pfacts[portnum];
3018 /* Destination (reply area)... */
3019 reply_sz = sizeof(*pfacts);
3020 memset(pfacts, 0, reply_sz);
3022 /* Request area (get_pfacts on the stack right now!) */
3023 req_sz = sizeof(get_pfacts);
3024 memset(&get_pfacts, 0, req_sz);
3026 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3027 get_pfacts.PortNumber = portnum;
3028 /* Assert: All other get_pfacts fields are zero! */
3030 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3031 ioc->name, portnum));
3033 /* No non-zero fields in the get_pfacts request are greater than
3034 * 1 byte in size, so we can just fire it off as is.
3036 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3037 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3038 if (ii != 0)
3039 return ii;
3041 /* Did we get a valid reply? */
3043 /* Now byte swap the necessary fields in the response. */
3044 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3045 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3046 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3047 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3048 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3049 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3050 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3051 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3052 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3054 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3055 pfacts->MaxDevices;
3056 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3057 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3060 * Place all the devices on channels
3062 * (for debuging)
3064 if (mpt_channel_mapping) {
3065 ioc->devices_per_bus = 1;
3066 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3069 return 0;
3072 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3074 * SendIocInit - Send IOCInit request to MPT adapter.
3075 * @ioc: Pointer to MPT_ADAPTER structure
3076 * @sleepFlag: Specifies whether the process can sleep
3078 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3080 * Returns 0 for success, non-zero for failure.
3082 static int
3083 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3085 IOCInit_t ioc_init;
3086 MPIDefaultReply_t init_reply;
3087 u32 state;
3088 int r;
3089 int count;
3090 int cntdn;
3092 memset(&ioc_init, 0, sizeof(ioc_init));
3093 memset(&init_reply, 0, sizeof(init_reply));
3095 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3096 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3098 /* If we are in a recovery mode and we uploaded the FW image,
3099 * then this pointer is not NULL. Skip the upload a second time.
3100 * Set this flag if cached_fw set for either IOC.
3102 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3103 ioc->upload_fw = 1;
3104 else
3105 ioc->upload_fw = 0;
3106 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3107 ioc->name, ioc->upload_fw, ioc->facts.Flags));
3109 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3110 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3111 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3112 ioc->name, ioc->facts.MsgVersion));
3113 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3114 // set MsgVersion and HeaderVersion host driver was built with
3115 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3116 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3118 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3119 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3120 } else if(mpt_host_page_alloc(ioc, &ioc_init))
3121 return -99;
3123 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3125 if (sizeof(dma_addr_t) == sizeof(u64)) {
3126 /* Save the upper 32-bits of the request
3127 * (reply) and sense buffers.
3129 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3130 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3131 } else {
3132 /* Force 32-bit addressing */
3133 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3134 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3137 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3138 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3139 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3140 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3142 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3143 ioc->name, &ioc_init));
3145 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3146 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3147 if (r != 0) {
3148 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3149 return r;
3152 /* No need to byte swap the multibyte fields in the reply
3153 * since we don't even look at its contents.
3156 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3157 ioc->name, &ioc_init));
3159 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3160 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3161 return r;
3164 /* YIKES! SUPER IMPORTANT!!!
3165 * Poll IocState until _OPERATIONAL while IOC is doing
3166 * LoopInit and TargetDiscovery!
3168 count = 0;
3169 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3170 state = mpt_GetIocState(ioc, 1);
3171 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3172 if (sleepFlag == CAN_SLEEP) {
3173 msleep(1);
3174 } else {
3175 mdelay(1);
3178 if (!cntdn) {
3179 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3180 ioc->name, (int)((count+5)/HZ));
3181 return -9;
3184 state = mpt_GetIocState(ioc, 1);
3185 count++;
3187 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3188 ioc->name, count));
3190 ioc->aen_event_read_flag=0;
3191 return r;
3194 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3196 * SendPortEnable - Send PortEnable request to MPT adapter port.
3197 * @ioc: Pointer to MPT_ADAPTER structure
3198 * @portnum: Port number to enable
3199 * @sleepFlag: Specifies whether the process can sleep
3201 * Send PortEnable to bring IOC to OPERATIONAL state.
3203 * Returns 0 for success, non-zero for failure.
3205 static int
3206 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3208 PortEnable_t port_enable;
3209 MPIDefaultReply_t reply_buf;
3210 int rc;
3211 int req_sz;
3212 int reply_sz;
3214 /* Destination... */
3215 reply_sz = sizeof(MPIDefaultReply_t);
3216 memset(&reply_buf, 0, reply_sz);
3218 req_sz = sizeof(PortEnable_t);
3219 memset(&port_enable, 0, req_sz);
3221 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3222 port_enable.PortNumber = portnum;
3223 /* port_enable.ChainOffset = 0; */
3224 /* port_enable.MsgFlags = 0; */
3225 /* port_enable.MsgContext = 0; */
3227 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3228 ioc->name, portnum, &port_enable));
3230 /* RAID FW may take a long time to enable
3232 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3233 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3234 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3235 300 /*seconds*/, sleepFlag);
3236 } else {
3237 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3238 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3239 30 /*seconds*/, sleepFlag);
3241 return rc;
3245 * mpt_alloc_fw_memory - allocate firmware memory
3246 * @ioc: Pointer to MPT_ADAPTER structure
3247 * @size: total FW bytes
3249 * If memory has already been allocated, the same (cached) value
3250 * is returned.
3252 * Return 0 if successfull, or non-zero for failure
3255 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3257 int rc;
3259 if (ioc->cached_fw) {
3260 rc = 0; /* use already allocated memory */
3261 goto out;
3263 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3264 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3265 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3266 rc = 0;
3267 goto out;
3269 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3270 if (!ioc->cached_fw) {
3271 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3272 ioc->name);
3273 rc = -1;
3274 } else {
3275 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3276 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3277 ioc->alloc_total += size;
3278 rc = 0;
3280 out:
3281 return rc;
3285 * mpt_free_fw_memory - free firmware memory
3286 * @ioc: Pointer to MPT_ADAPTER structure
3288 * If alt_img is NULL, delete from ioc structure.
3289 * Else, delete a secondary image in same format.
3291 void
3292 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3294 int sz;
3296 if (!ioc->cached_fw)
3297 return;
3299 sz = ioc->facts.FWImageSize;
3300 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3301 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3302 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3303 ioc->alloc_total -= sz;
3304 ioc->cached_fw = NULL;
3307 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3309 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3310 * @ioc: Pointer to MPT_ADAPTER structure
3311 * @sleepFlag: Specifies whether the process can sleep
3313 * Returns 0 for success, >0 for handshake failure
3314 * <0 for fw upload failure.
3316 * Remark: If bound IOC and a successful FWUpload was performed
3317 * on the bound IOC, the second image is discarded
3318 * and memory is free'd. Both channels must upload to prevent
3319 * IOC from running in degraded mode.
3321 static int
3322 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3324 u8 reply[sizeof(FWUploadReply_t)];
3325 FWUpload_t *prequest;
3326 FWUploadReply_t *preply;
3327 FWUploadTCSGE_t *ptcsge;
3328 int sgeoffset;
3329 u32 flagsLength;
3330 int ii, sz, reply_sz;
3331 int cmdStatus;
3333 /* If the image size is 0, we are done.
3335 if ((sz = ioc->facts.FWImageSize) == 0)
3336 return 0;
3338 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3339 return -ENOMEM;
3341 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3342 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3344 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3345 kzalloc(ioc->req_sz, GFP_KERNEL);
3346 if (!prequest) {
3347 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3348 "while allocating memory \n", ioc->name));
3349 mpt_free_fw_memory(ioc);
3350 return -ENOMEM;
3353 preply = (FWUploadReply_t *)&reply;
3355 reply_sz = sizeof(reply);
3356 memset(preply, 0, reply_sz);
3358 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3359 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3361 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3362 ptcsge->DetailsLength = 12;
3363 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3364 ptcsge->ImageSize = cpu_to_le32(sz);
3365 ptcsge++;
3367 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
3369 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3370 mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3372 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
3373 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3374 ioc->name, prequest, sgeoffset));
3375 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3377 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
3378 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3380 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
3382 cmdStatus = -EFAULT;
3383 if (ii == 0) {
3384 /* Handshake transfer was complete and successful.
3385 * Check the Reply Frame.
3387 int status, transfer_sz;
3388 status = le16_to_cpu(preply->IOCStatus);
3389 if (status == MPI_IOCSTATUS_SUCCESS) {
3390 transfer_sz = le32_to_cpu(preply->ActualImageSize);
3391 if (transfer_sz == sz)
3392 cmdStatus = 0;
3395 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3396 ioc->name, cmdStatus));
3399 if (cmdStatus) {
3401 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
3402 ioc->name));
3403 mpt_free_fw_memory(ioc);
3405 kfree(prequest);
3407 return cmdStatus;
3410 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3412 * mpt_downloadboot - DownloadBoot code
3413 * @ioc: Pointer to MPT_ADAPTER structure
3414 * @pFwHeader: Pointer to firmware header info
3415 * @sleepFlag: Specifies whether the process can sleep
3417 * FwDownloadBoot requires Programmed IO access.
3419 * Returns 0 for success
3420 * -1 FW Image size is 0
3421 * -2 No valid cached_fw Pointer
3422 * <0 for fw upload failure.
3424 static int
3425 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3427 MpiExtImageHeader_t *pExtImage;
3428 u32 fwSize;
3429 u32 diag0val;
3430 int count;
3431 u32 *ptrFw;
3432 u32 diagRwData;
3433 u32 nextImage;
3434 u32 load_addr;
3435 u32 ioc_state=0;
3437 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3438 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3440 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3441 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3442 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3443 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3444 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3445 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3447 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3449 /* wait 1 msec */
3450 if (sleepFlag == CAN_SLEEP) {
3451 msleep(1);
3452 } else {
3453 mdelay (1);
3456 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3457 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3459 for (count = 0; count < 30; count ++) {
3460 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3461 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3462 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3463 ioc->name, count));
3464 break;
3466 /* wait .1 sec */
3467 if (sleepFlag == CAN_SLEEP) {
3468 msleep (100);
3469 } else {
3470 mdelay (100);
3474 if ( count == 30 ) {
3475 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3476 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3477 ioc->name, diag0val));
3478 return -3;
3481 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3482 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3483 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3484 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3485 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3486 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3488 /* Set the DiagRwEn and Disable ARM bits */
3489 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3491 fwSize = (pFwHeader->ImageSize + 3)/4;
3492 ptrFw = (u32 *) pFwHeader;
3494 /* Write the LoadStartAddress to the DiagRw Address Register
3495 * using Programmed IO
3497 if (ioc->errata_flag_1064)
3498 pci_enable_io_access(ioc->pcidev);
3500 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3501 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3502 ioc->name, pFwHeader->LoadStartAddress));
3504 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3505 ioc->name, fwSize*4, ptrFw));
3506 while (fwSize--) {
3507 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3510 nextImage = pFwHeader->NextImageHeaderOffset;
3511 while (nextImage) {
3512 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3514 load_addr = pExtImage->LoadStartAddress;
3516 fwSize = (pExtImage->ImageSize + 3) >> 2;
3517 ptrFw = (u32 *)pExtImage;
3519 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3520 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3521 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3523 while (fwSize--) {
3524 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3526 nextImage = pExtImage->NextImageHeaderOffset;
3529 /* Write the IopResetVectorRegAddr */
3530 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3531 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3533 /* Write the IopResetVectorValue */
3534 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3535 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3537 /* Clear the internal flash bad bit - autoincrementing register,
3538 * so must do two writes.
3540 if (ioc->bus_type == SPI) {
3542 * 1030 and 1035 H/W errata, workaround to access
3543 * the ClearFlashBadSignatureBit
3545 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3546 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3547 diagRwData |= 0x40000000;
3548 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3549 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3551 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3552 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3553 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3554 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3556 /* wait 1 msec */
3557 if (sleepFlag == CAN_SLEEP) {
3558 msleep (1);
3559 } else {
3560 mdelay (1);
3564 if (ioc->errata_flag_1064)
3565 pci_disable_io_access(ioc->pcidev);
3567 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3568 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3569 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3570 ioc->name, diag0val));
3571 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3572 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3573 ioc->name, diag0val));
3574 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3576 /* Write 0xFF to reset the sequencer */
3577 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3579 if (ioc->bus_type == SAS) {
3580 ioc_state = mpt_GetIocState(ioc, 0);
3581 if ( (GetIocFacts(ioc, sleepFlag,
3582 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3583 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3584 ioc->name, ioc_state));
3585 return -EFAULT;
3589 for (count=0; count<HZ*20; count++) {
3590 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3591 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3592 "downloadboot successful! (count=%d) IocState=%x\n",
3593 ioc->name, count, ioc_state));
3594 if (ioc->bus_type == SAS) {
3595 return 0;
3597 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3598 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3599 "downloadboot: SendIocInit failed\n",
3600 ioc->name));
3601 return -EFAULT;
3603 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3604 "downloadboot: SendIocInit successful\n",
3605 ioc->name));
3606 return 0;
3608 if (sleepFlag == CAN_SLEEP) {
3609 msleep (10);
3610 } else {
3611 mdelay (10);
3614 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3615 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3616 return -EFAULT;
3619 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3621 * KickStart - Perform hard reset of MPT adapter.
3622 * @ioc: Pointer to MPT_ADAPTER structure
3623 * @force: Force hard reset
3624 * @sleepFlag: Specifies whether the process can sleep
3626 * This routine places MPT adapter in diagnostic mode via the
3627 * WriteSequence register, and then performs a hard reset of adapter
3628 * via the Diagnostic register.
3630 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3631 * or NO_SLEEP (interrupt thread, use mdelay)
3632 * force - 1 if doorbell active, board fault state
3633 * board operational, IOC_RECOVERY or
3634 * IOC_BRINGUP and there is an alt_ioc.
3635 * 0 else
3637 * Returns:
3638 * 1 - hard reset, READY
3639 * 0 - no reset due to History bit, READY
3640 * -1 - no reset due to History bit but not READY
3641 * OR reset but failed to come READY
3642 * -2 - no reset, could not enter DIAG mode
3643 * -3 - reset but bad FW bit
3645 static int
3646 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3648 int hard_reset_done = 0;
3649 u32 ioc_state=0;
3650 int cnt,cntdn;
3652 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3653 if (ioc->bus_type == SPI) {
3654 /* Always issue a Msg Unit Reset first. This will clear some
3655 * SCSI bus hang conditions.
3657 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3659 if (sleepFlag == CAN_SLEEP) {
3660 msleep (1000);
3661 } else {
3662 mdelay (1000);
3666 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3667 if (hard_reset_done < 0)
3668 return hard_reset_done;
3670 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3671 ioc->name));
3673 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3674 for (cnt=0; cnt<cntdn; cnt++) {
3675 ioc_state = mpt_GetIocState(ioc, 1);
3676 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3677 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3678 ioc->name, cnt));
3679 return hard_reset_done;
3681 if (sleepFlag == CAN_SLEEP) {
3682 msleep (10);
3683 } else {
3684 mdelay (10);
3688 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3689 ioc->name, mpt_GetIocState(ioc, 0)));
3690 return -1;
3693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3695 * mpt_diag_reset - Perform hard reset of the adapter.
3696 * @ioc: Pointer to MPT_ADAPTER structure
3697 * @ignore: Set if to honor and clear to ignore
3698 * the reset history bit
3699 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3700 * else set to NO_SLEEP (use mdelay instead)
3702 * This routine places the adapter in diagnostic mode via the
3703 * WriteSequence register and then performs a hard reset of adapter
3704 * via the Diagnostic register. Adapter should be in ready state
3705 * upon successful completion.
3707 * Returns: 1 hard reset successful
3708 * 0 no reset performed because reset history bit set
3709 * -2 enabling diagnostic mode failed
3710 * -3 diagnostic reset failed
3712 static int
3713 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3715 u32 diag0val;
3716 u32 doorbell;
3717 int hard_reset_done = 0;
3718 int count = 0;
3719 u32 diag1val = 0;
3720 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3722 /* Clear any existing interrupts */
3723 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3725 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3726 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3727 "address=%p\n", ioc->name, __func__,
3728 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3729 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3730 if (sleepFlag == CAN_SLEEP)
3731 msleep(1);
3732 else
3733 mdelay(1);
3735 for (count = 0; count < 60; count ++) {
3736 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3737 doorbell &= MPI_IOC_STATE_MASK;
3739 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3740 "looking for READY STATE: doorbell=%x"
3741 " count=%d\n",
3742 ioc->name, doorbell, count));
3743 if (doorbell == MPI_IOC_STATE_READY) {
3744 return 1;
3747 /* wait 1 sec */
3748 if (sleepFlag == CAN_SLEEP)
3749 msleep(1000);
3750 else
3751 mdelay(1000);
3753 return -1;
3756 /* Use "Diagnostic reset" method! (only thing available!) */
3757 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3759 if (ioc->debug_level & MPT_DEBUG) {
3760 if (ioc->alt_ioc)
3761 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3762 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3763 ioc->name, diag0val, diag1val));
3766 /* Do the reset if we are told to ignore the reset history
3767 * or if the reset history is 0
3769 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3770 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3771 /* Write magic sequence to WriteSequence register
3772 * Loop until in diagnostic mode
3774 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3775 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3776 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3777 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3778 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3779 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3781 /* wait 100 msec */
3782 if (sleepFlag == CAN_SLEEP) {
3783 msleep (100);
3784 } else {
3785 mdelay (100);
3788 count++;
3789 if (count > 20) {
3790 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3791 ioc->name, diag0val);
3792 return -2;
3796 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3798 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3799 ioc->name, diag0val));
3802 if (ioc->debug_level & MPT_DEBUG) {
3803 if (ioc->alt_ioc)
3804 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3805 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3806 ioc->name, diag0val, diag1val));
3809 * Disable the ARM (Bug fix)
3812 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3813 mdelay(1);
3816 * Now hit the reset bit in the Diagnostic register
3817 * (THE BIG HAMMER!) (Clears DRWE bit).
3819 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3820 hard_reset_done = 1;
3821 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3822 ioc->name));
3825 * Call each currently registered protocol IOC reset handler
3826 * with pre-reset indication.
3827 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3828 * MptResetHandlers[] registered yet.
3831 u8 cb_idx;
3832 int r = 0;
3834 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3835 if (MptResetHandlers[cb_idx]) {
3836 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3837 "Calling IOC pre_reset handler #%d\n",
3838 ioc->name, cb_idx));
3839 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
3840 if (ioc->alt_ioc) {
3841 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3842 "Calling alt-%s pre_reset handler #%d\n",
3843 ioc->name, ioc->alt_ioc->name, cb_idx));
3844 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3848 /* FIXME? Examine results here? */
3851 if (ioc->cached_fw)
3852 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3853 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3854 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3855 else
3856 cached_fw = NULL;
3857 if (cached_fw) {
3858 /* If the DownloadBoot operation fails, the
3859 * IOC will be left unusable. This is a fatal error
3860 * case. _diag_reset will return < 0
3862 for (count = 0; count < 30; count ++) {
3863 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3864 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3865 break;
3868 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3869 ioc->name, diag0val, count));
3870 /* wait 1 sec */
3871 if (sleepFlag == CAN_SLEEP) {
3872 msleep (1000);
3873 } else {
3874 mdelay (1000);
3877 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3878 printk(MYIOC_s_WARN_FMT
3879 "firmware downloadboot failure (%d)!\n", ioc->name, count);
3882 } else {
3883 /* Wait for FW to reload and for board
3884 * to go to the READY state.
3885 * Maximum wait is 60 seconds.
3886 * If fail, no error will check again
3887 * with calling program.
3889 for (count = 0; count < 60; count ++) {
3890 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3891 doorbell &= MPI_IOC_STATE_MASK;
3893 if (doorbell == MPI_IOC_STATE_READY) {
3894 break;
3897 /* wait 1 sec */
3898 if (sleepFlag == CAN_SLEEP) {
3899 msleep (1000);
3900 } else {
3901 mdelay (1000);
3907 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3908 if (ioc->debug_level & MPT_DEBUG) {
3909 if (ioc->alt_ioc)
3910 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3911 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3912 ioc->name, diag0val, diag1val));
3915 /* Clear RESET_HISTORY bit! Place board in the
3916 * diagnostic mode to update the diag register.
3918 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3919 count = 0;
3920 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3921 /* Write magic sequence to WriteSequence register
3922 * Loop until in diagnostic mode
3924 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3925 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3926 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3927 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3928 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3929 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3931 /* wait 100 msec */
3932 if (sleepFlag == CAN_SLEEP) {
3933 msleep (100);
3934 } else {
3935 mdelay (100);
3938 count++;
3939 if (count > 20) {
3940 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3941 ioc->name, diag0val);
3942 break;
3944 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3946 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3947 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3948 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3949 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3950 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3951 ioc->name);
3954 /* Disable Diagnostic Mode
3956 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3958 /* Check FW reload status flags.
3960 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3961 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3962 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3963 ioc->name, diag0val);
3964 return -3;
3967 if (ioc->debug_level & MPT_DEBUG) {
3968 if (ioc->alt_ioc)
3969 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3970 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3971 ioc->name, diag0val, diag1val));
3975 * Reset flag that says we've enabled event notification
3977 ioc->facts.EventState = 0;
3979 if (ioc->alt_ioc)
3980 ioc->alt_ioc->facts.EventState = 0;
3982 return hard_reset_done;
3985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3987 * SendIocReset - Send IOCReset request to MPT adapter.
3988 * @ioc: Pointer to MPT_ADAPTER structure
3989 * @reset_type: reset type, expected values are
3990 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3991 * @sleepFlag: Specifies whether the process can sleep
3993 * Send IOCReset request to the MPT adapter.
3995 * Returns 0 for success, non-zero for failure.
3997 static int
3998 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4000 int r;
4001 u32 state;
4002 int cntdn, count;
4004 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4005 ioc->name, reset_type));
4006 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4007 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4008 return r;
4010 /* FW ACK'd request, wait for READY state
4012 count = 0;
4013 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
4015 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4016 cntdn--;
4017 count++;
4018 if (!cntdn) {
4019 if (sleepFlag != CAN_SLEEP)
4020 count *= 10;
4022 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
4023 ioc->name, (int)((count+5)/HZ));
4024 return -ETIME;
4027 if (sleepFlag == CAN_SLEEP) {
4028 msleep(1);
4029 } else {
4030 mdelay (1); /* 1 msec delay */
4034 /* TODO!
4035 * Cleanup all event stuff for this IOC; re-issue EventNotification
4036 * request if needed.
4038 if (ioc->facts.Function)
4039 ioc->facts.EventState = 0;
4041 return 0;
4044 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4046 * initChainBuffers - Allocate memory for and initialize chain buffers
4047 * @ioc: Pointer to MPT_ADAPTER structure
4049 * Allocates memory for and initializes chain buffers,
4050 * chain buffer control arrays and spinlock.
4052 static int
4053 initChainBuffers(MPT_ADAPTER *ioc)
4055 u8 *mem;
4056 int sz, ii, num_chain;
4057 int scale, num_sge, numSGE;
4059 /* ReqToChain size must equal the req_depth
4060 * index = req_idx
4062 if (ioc->ReqToChain == NULL) {
4063 sz = ioc->req_depth * sizeof(int);
4064 mem = kmalloc(sz, GFP_ATOMIC);
4065 if (mem == NULL)
4066 return -1;
4068 ioc->ReqToChain = (int *) mem;
4069 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
4070 ioc->name, mem, sz));
4071 mem = kmalloc(sz, GFP_ATOMIC);
4072 if (mem == NULL)
4073 return -1;
4075 ioc->RequestNB = (int *) mem;
4076 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
4077 ioc->name, mem, sz));
4079 for (ii = 0; ii < ioc->req_depth; ii++) {
4080 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4083 /* ChainToChain size must equal the total number
4084 * of chain buffers to be allocated.
4085 * index = chain_idx
4087 * Calculate the number of chain buffers needed(plus 1) per I/O
4088 * then multiply the maximum number of simultaneous cmds
4090 * num_sge = num sge in request frame + last chain buffer
4091 * scale = num sge per chain buffer if no chain element
4093 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
4094 if (sizeof(dma_addr_t) == sizeof(u64))
4095 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4096 else
4097 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4099 if (sizeof(dma_addr_t) == sizeof(u64)) {
4100 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4101 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4102 } else {
4103 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4104 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4106 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4107 ioc->name, num_sge, numSGE));
4109 if ( numSGE > MPT_SCSI_SG_DEPTH )
4110 numSGE = MPT_SCSI_SG_DEPTH;
4112 num_chain = 1;
4113 while (numSGE - num_sge > 0) {
4114 num_chain++;
4115 num_sge += (scale - 1);
4117 num_chain++;
4119 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4120 ioc->name, numSGE, num_sge, num_chain));
4122 if (ioc->bus_type == SPI)
4123 num_chain *= MPT_SCSI_CAN_QUEUE;
4124 else
4125 num_chain *= MPT_FC_CAN_QUEUE;
4127 ioc->num_chain = num_chain;
4129 sz = num_chain * sizeof(int);
4130 if (ioc->ChainToChain == NULL) {
4131 mem = kmalloc(sz, GFP_ATOMIC);
4132 if (mem == NULL)
4133 return -1;
4135 ioc->ChainToChain = (int *) mem;
4136 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4137 ioc->name, mem, sz));
4138 } else {
4139 mem = (u8 *) ioc->ChainToChain;
4141 memset(mem, 0xFF, sz);
4142 return num_chain;
4145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4147 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4148 * @ioc: Pointer to MPT_ADAPTER structure
4150 * This routine allocates memory for the MPT reply and request frame
4151 * pools (if necessary), and primes the IOC reply FIFO with
4152 * reply frames.
4154 * Returns 0 for success, non-zero for failure.
4156 static int
4157 PrimeIocFifos(MPT_ADAPTER *ioc)
4159 MPT_FRAME_HDR *mf;
4160 unsigned long flags;
4161 dma_addr_t alloc_dma;
4162 u8 *mem;
4163 int i, reply_sz, sz, total_size, num_chain;
4165 /* Prime reply FIFO... */
4167 if (ioc->reply_frames == NULL) {
4168 if ( (num_chain = initChainBuffers(ioc)) < 0)
4169 return -1;
4171 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4172 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4173 ioc->name, ioc->reply_sz, ioc->reply_depth));
4174 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4175 ioc->name, reply_sz, reply_sz));
4177 sz = (ioc->req_sz * ioc->req_depth);
4178 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4179 ioc->name, ioc->req_sz, ioc->req_depth));
4180 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4181 ioc->name, sz, sz));
4182 total_size += sz;
4184 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4185 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4186 ioc->name, ioc->req_sz, num_chain));
4187 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4188 ioc->name, sz, sz, num_chain));
4190 total_size += sz;
4191 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4192 if (mem == NULL) {
4193 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4194 ioc->name);
4195 goto out_fail;
4198 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4199 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4201 memset(mem, 0, total_size);
4202 ioc->alloc_total += total_size;
4203 ioc->alloc = mem;
4204 ioc->alloc_dma = alloc_dma;
4205 ioc->alloc_sz = total_size;
4206 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4207 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4209 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4210 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4212 alloc_dma += reply_sz;
4213 mem += reply_sz;
4215 /* Request FIFO - WE manage this! */
4217 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4218 ioc->req_frames_dma = alloc_dma;
4220 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4221 ioc->name, mem, (void *)(ulong)alloc_dma));
4223 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4225 #if defined(CONFIG_MTRR) && 0
4227 * Enable Write Combining MTRR for IOC's memory region.
4228 * (at least as much as we can; "size and base must be
4229 * multiples of 4 kiB"
4231 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4233 MTRR_TYPE_WRCOMB, 1);
4234 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4235 ioc->name, ioc->req_frames_dma, sz));
4236 #endif
4238 for (i = 0; i < ioc->req_depth; i++) {
4239 alloc_dma += ioc->req_sz;
4240 mem += ioc->req_sz;
4243 ioc->ChainBuffer = mem;
4244 ioc->ChainBufferDMA = alloc_dma;
4246 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4247 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4249 /* Initialize the free chain Q.
4252 INIT_LIST_HEAD(&ioc->FreeChainQ);
4254 /* Post the chain buffers to the FreeChainQ.
4256 mem = (u8 *)ioc->ChainBuffer;
4257 for (i=0; i < num_chain; i++) {
4258 mf = (MPT_FRAME_HDR *) mem;
4259 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4260 mem += ioc->req_sz;
4263 /* Initialize Request frames linked list
4265 alloc_dma = ioc->req_frames_dma;
4266 mem = (u8 *) ioc->req_frames;
4268 spin_lock_irqsave(&ioc->FreeQlock, flags);
4269 INIT_LIST_HEAD(&ioc->FreeQ);
4270 for (i = 0; i < ioc->req_depth; i++) {
4271 mf = (MPT_FRAME_HDR *) mem;
4273 /* Queue REQUESTs *internally*! */
4274 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4276 mem += ioc->req_sz;
4278 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4280 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4281 ioc->sense_buf_pool =
4282 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4283 if (ioc->sense_buf_pool == NULL) {
4284 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4285 ioc->name);
4286 goto out_fail;
4289 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4290 ioc->alloc_total += sz;
4291 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4292 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4296 /* Post Reply frames to FIFO
4298 alloc_dma = ioc->alloc_dma;
4299 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4300 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4302 for (i = 0; i < ioc->reply_depth; i++) {
4303 /* Write each address to the IOC! */
4304 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4305 alloc_dma += ioc->reply_sz;
4308 return 0;
4310 out_fail:
4311 if (ioc->alloc != NULL) {
4312 sz = ioc->alloc_sz;
4313 pci_free_consistent(ioc->pcidev,
4315 ioc->alloc, ioc->alloc_dma);
4316 ioc->reply_frames = NULL;
4317 ioc->req_frames = NULL;
4318 ioc->alloc_total -= sz;
4320 if (ioc->sense_buf_pool != NULL) {
4321 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4322 pci_free_consistent(ioc->pcidev,
4324 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4325 ioc->sense_buf_pool = NULL;
4327 return -1;
4330 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4332 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4333 * from IOC via doorbell handshake method.
4334 * @ioc: Pointer to MPT_ADAPTER structure
4335 * @reqBytes: Size of the request in bytes
4336 * @req: Pointer to MPT request frame
4337 * @replyBytes: Expected size of the reply in bytes
4338 * @u16reply: Pointer to area where reply should be written
4339 * @maxwait: Max wait time for a reply (in seconds)
4340 * @sleepFlag: Specifies whether the process can sleep
4342 * NOTES: It is the callers responsibility to byte-swap fields in the
4343 * request which are greater than 1 byte in size. It is also the
4344 * callers responsibility to byte-swap response fields which are
4345 * greater than 1 byte in size.
4347 * Returns 0 for success, non-zero for failure.
4349 static int
4350 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4351 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4353 MPIDefaultReply_t *mptReply;
4354 int failcnt = 0;
4355 int t;
4358 * Get ready to cache a handshake reply
4360 ioc->hs_reply_idx = 0;
4361 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4362 mptReply->MsgLength = 0;
4365 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4366 * then tell IOC that we want to handshake a request of N words.
4367 * (WRITE u32val to Doorbell reg).
4369 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4370 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4371 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4372 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4375 * Wait for IOC's doorbell handshake int
4377 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4378 failcnt++;
4380 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4381 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4383 /* Read doorbell and check for active bit */
4384 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4385 return -1;
4388 * Clear doorbell int (WRITE 0 to IntStatus reg),
4389 * then wait for IOC to ACKnowledge that it's ready for
4390 * our handshake request.
4392 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4393 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4394 failcnt++;
4396 if (!failcnt) {
4397 int ii;
4398 u8 *req_as_bytes = (u8 *) req;
4401 * Stuff request words via doorbell handshake,
4402 * with ACK from IOC for each.
4404 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4405 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4406 (req_as_bytes[(ii*4) + 1] << 8) |
4407 (req_as_bytes[(ii*4) + 2] << 16) |
4408 (req_as_bytes[(ii*4) + 3] << 24));
4410 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4411 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4412 failcnt++;
4415 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4416 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4418 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4419 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4422 * Wait for completion of doorbell handshake reply from the IOC
4424 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4425 failcnt++;
4427 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4428 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4431 * Copy out the cached reply...
4433 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4434 u16reply[ii] = ioc->hs_reply[ii];
4435 } else {
4436 return -99;
4439 return -failcnt;
4442 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4444 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4445 * @ioc: Pointer to MPT_ADAPTER structure
4446 * @howlong: How long to wait (in seconds)
4447 * @sleepFlag: Specifies whether the process can sleep
4449 * This routine waits (up to ~2 seconds max) for IOC doorbell
4450 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4451 * bit in its IntStatus register being clear.
4453 * Returns a negative value on failure, else wait loop count.
4455 static int
4456 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4458 int cntdn;
4459 int count = 0;
4460 u32 intstat=0;
4462 cntdn = 1000 * howlong;
4464 if (sleepFlag == CAN_SLEEP) {
4465 while (--cntdn) {
4466 msleep (1);
4467 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4468 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4469 break;
4470 count++;
4472 } else {
4473 while (--cntdn) {
4474 udelay (1000);
4475 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4476 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4477 break;
4478 count++;
4482 if (cntdn) {
4483 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4484 ioc->name, count));
4485 return count;
4488 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4489 ioc->name, count, intstat);
4490 return -1;
4493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4495 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4496 * @ioc: Pointer to MPT_ADAPTER structure
4497 * @howlong: How long to wait (in seconds)
4498 * @sleepFlag: Specifies whether the process can sleep
4500 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4501 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4503 * Returns a negative value on failure, else wait loop count.
4505 static int
4506 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4508 int cntdn;
4509 int count = 0;
4510 u32 intstat=0;
4512 cntdn = 1000 * howlong;
4513 if (sleepFlag == CAN_SLEEP) {
4514 while (--cntdn) {
4515 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4516 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4517 break;
4518 msleep(1);
4519 count++;
4521 } else {
4522 while (--cntdn) {
4523 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4524 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4525 break;
4526 udelay (1000);
4527 count++;
4531 if (cntdn) {
4532 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4533 ioc->name, count, howlong));
4534 return count;
4537 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4538 ioc->name, count, intstat);
4539 return -1;
4542 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4544 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4545 * @ioc: Pointer to MPT_ADAPTER structure
4546 * @howlong: How long to wait (in seconds)
4547 * @sleepFlag: Specifies whether the process can sleep
4549 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4550 * Reply is cached to IOC private area large enough to hold a maximum
4551 * of 128 bytes of reply data.
4553 * Returns a negative value on failure, else size of reply in WORDS.
4555 static int
4556 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4558 int u16cnt = 0;
4559 int failcnt = 0;
4560 int t;
4561 u16 *hs_reply = ioc->hs_reply;
4562 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4563 u16 hword;
4565 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4568 * Get first two u16's so we can look at IOC's intended reply MsgLength
4570 u16cnt=0;
4571 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4572 failcnt++;
4573 } else {
4574 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4575 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4576 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4577 failcnt++;
4578 else {
4579 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4580 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4584 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4585 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4586 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4589 * If no error (and IOC said MsgLength is > 0), piece together
4590 * reply 16 bits at a time.
4592 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4593 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4594 failcnt++;
4595 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4596 /* don't overflow our IOC hs_reply[] buffer! */
4597 if (u16cnt < ARRAY_SIZE(ioc->hs_reply))
4598 hs_reply[u16cnt] = hword;
4599 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4602 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4603 failcnt++;
4604 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4606 if (failcnt) {
4607 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4608 ioc->name);
4609 return -failcnt;
4611 #if 0
4612 else if (u16cnt != (2 * mptReply->MsgLength)) {
4613 return -101;
4615 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4616 return -102;
4618 #endif
4620 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4621 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4623 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4624 ioc->name, t, u16cnt/2));
4625 return u16cnt/2;
4628 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4630 * GetLanConfigPages - Fetch LANConfig pages.
4631 * @ioc: Pointer to MPT_ADAPTER structure
4633 * Return: 0 for success
4634 * -ENOMEM if no memory available
4635 * -EPERM if not allowed due to ISR context
4636 * -EAGAIN if no msg frames currently available
4637 * -EFAULT for non-successful reply or no reply (timeout)
4639 static int
4640 GetLanConfigPages(MPT_ADAPTER *ioc)
4642 ConfigPageHeader_t hdr;
4643 CONFIGPARMS cfg;
4644 LANPage0_t *ppage0_alloc;
4645 dma_addr_t page0_dma;
4646 LANPage1_t *ppage1_alloc;
4647 dma_addr_t page1_dma;
4648 int rc = 0;
4649 int data_sz;
4650 int copy_sz;
4652 /* Get LAN Page 0 header */
4653 hdr.PageVersion = 0;
4654 hdr.PageLength = 0;
4655 hdr.PageNumber = 0;
4656 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4657 cfg.cfghdr.hdr = &hdr;
4658 cfg.physAddr = -1;
4659 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4660 cfg.dir = 0;
4661 cfg.pageAddr = 0;
4662 cfg.timeout = 0;
4664 if ((rc = mpt_config(ioc, &cfg)) != 0)
4665 return rc;
4667 if (hdr.PageLength > 0) {
4668 data_sz = hdr.PageLength * 4;
4669 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4670 rc = -ENOMEM;
4671 if (ppage0_alloc) {
4672 memset((u8 *)ppage0_alloc, 0, data_sz);
4673 cfg.physAddr = page0_dma;
4674 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4676 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4677 /* save the data */
4678 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4679 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4683 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4685 /* FIXME!
4686 * Normalize endianness of structure data,
4687 * by byte-swapping all > 1 byte fields!
4692 if (rc)
4693 return rc;
4696 /* Get LAN Page 1 header */
4697 hdr.PageVersion = 0;
4698 hdr.PageLength = 0;
4699 hdr.PageNumber = 1;
4700 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4701 cfg.cfghdr.hdr = &hdr;
4702 cfg.physAddr = -1;
4703 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4704 cfg.dir = 0;
4705 cfg.pageAddr = 0;
4707 if ((rc = mpt_config(ioc, &cfg)) != 0)
4708 return rc;
4710 if (hdr.PageLength == 0)
4711 return 0;
4713 data_sz = hdr.PageLength * 4;
4714 rc = -ENOMEM;
4715 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4716 if (ppage1_alloc) {
4717 memset((u8 *)ppage1_alloc, 0, data_sz);
4718 cfg.physAddr = page1_dma;
4719 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4721 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4722 /* save the data */
4723 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4724 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4727 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4729 /* FIXME!
4730 * Normalize endianness of structure data,
4731 * by byte-swapping all > 1 byte fields!
4736 return rc;
4739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4741 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4742 * @ioc: Pointer to MPT_ADAPTER structure
4743 * @persist_opcode: see below
4745 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4746 * devices not currently present.
4747 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4749 * NOTE: Don't use not this function during interrupt time.
4751 * Returns 0 for success, non-zero error
4754 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4756 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4758 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4759 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4760 MPT_FRAME_HDR *mf = NULL;
4761 MPIHeader_t *mpi_hdr;
4764 /* insure garbage is not sent to fw */
4765 switch(persist_opcode) {
4767 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4768 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4769 break;
4771 default:
4772 return -1;
4773 break;
4776 printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
4778 /* Get a MF for this command.
4780 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4781 printk("%s: no msg frames!\n",__func__);
4782 return -1;
4785 mpi_hdr = (MPIHeader_t *) mf;
4786 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4787 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4788 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4789 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4790 sasIoUnitCntrReq->Operation = persist_opcode;
4792 init_timer(&ioc->persist_timer);
4793 ioc->persist_timer.data = (unsigned long) ioc;
4794 ioc->persist_timer.function = mpt_timer_expired;
4795 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4796 ioc->persist_wait_done=0;
4797 add_timer(&ioc->persist_timer);
4798 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4799 wait_event(mpt_waitq, ioc->persist_wait_done);
4801 sasIoUnitCntrReply =
4802 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4803 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4804 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4805 __func__,
4806 sasIoUnitCntrReply->IOCStatus,
4807 sasIoUnitCntrReply->IOCLogInfo);
4808 return -1;
4811 printk("%s: success\n",__func__);
4812 return 0;
4815 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4817 static void
4818 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4819 MpiEventDataRaid_t * pRaidEventData)
4821 int volume;
4822 int reason;
4823 int disk;
4824 int status;
4825 int flags;
4826 int state;
4828 volume = pRaidEventData->VolumeID;
4829 reason = pRaidEventData->ReasonCode;
4830 disk = pRaidEventData->PhysDiskNum;
4831 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4832 flags = (status >> 0) & 0xff;
4833 state = (status >> 8) & 0xff;
4835 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4836 return;
4839 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4840 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4841 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4842 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4843 ioc->name, disk, volume);
4844 } else {
4845 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4846 ioc->name, volume);
4849 switch(reason) {
4850 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4851 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4852 ioc->name);
4853 break;
4855 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4857 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4858 ioc->name);
4859 break;
4861 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4862 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4863 ioc->name);
4864 break;
4866 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4867 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4868 ioc->name,
4869 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4870 ? "optimal"
4871 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4872 ? "degraded"
4873 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4874 ? "failed"
4875 : "state unknown",
4876 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4877 ? ", enabled" : "",
4878 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4879 ? ", quiesced" : "",
4880 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4881 ? ", resync in progress" : "" );
4882 break;
4884 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4885 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4886 ioc->name, disk);
4887 break;
4889 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4890 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4891 ioc->name);
4892 break;
4894 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4895 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4896 ioc->name);
4897 break;
4899 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4900 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4901 ioc->name);
4902 break;
4904 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4905 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4906 ioc->name,
4907 state == MPI_PHYSDISK0_STATUS_ONLINE
4908 ? "online"
4909 : state == MPI_PHYSDISK0_STATUS_MISSING
4910 ? "missing"
4911 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4912 ? "not compatible"
4913 : state == MPI_PHYSDISK0_STATUS_FAILED
4914 ? "failed"
4915 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4916 ? "initializing"
4917 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4918 ? "offline requested"
4919 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4920 ? "failed requested"
4921 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4922 ? "offline"
4923 : "state unknown",
4924 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4925 ? ", out of sync" : "",
4926 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4927 ? ", quiesced" : "" );
4928 break;
4930 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4931 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4932 ioc->name, disk);
4933 break;
4935 case MPI_EVENT_RAID_RC_SMART_DATA:
4936 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4937 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4938 break;
4940 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4941 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4942 ioc->name, disk);
4943 break;
4947 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4949 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4950 * @ioc: Pointer to MPT_ADAPTER structure
4952 * Returns: 0 for success
4953 * -ENOMEM if no memory available
4954 * -EPERM if not allowed due to ISR context
4955 * -EAGAIN if no msg frames currently available
4956 * -EFAULT for non-successful reply or no reply (timeout)
4958 static int
4959 GetIoUnitPage2(MPT_ADAPTER *ioc)
4961 ConfigPageHeader_t hdr;
4962 CONFIGPARMS cfg;
4963 IOUnitPage2_t *ppage_alloc;
4964 dma_addr_t page_dma;
4965 int data_sz;
4966 int rc;
4968 /* Get the page header */
4969 hdr.PageVersion = 0;
4970 hdr.PageLength = 0;
4971 hdr.PageNumber = 2;
4972 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4973 cfg.cfghdr.hdr = &hdr;
4974 cfg.physAddr = -1;
4975 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4976 cfg.dir = 0;
4977 cfg.pageAddr = 0;
4978 cfg.timeout = 0;
4980 if ((rc = mpt_config(ioc, &cfg)) != 0)
4981 return rc;
4983 if (hdr.PageLength == 0)
4984 return 0;
4986 /* Read the config page */
4987 data_sz = hdr.PageLength * 4;
4988 rc = -ENOMEM;
4989 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4990 if (ppage_alloc) {
4991 memset((u8 *)ppage_alloc, 0, data_sz);
4992 cfg.physAddr = page_dma;
4993 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4995 /* If Good, save data */
4996 if ((rc = mpt_config(ioc, &cfg)) == 0)
4997 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4999 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
5002 return rc;
5005 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5007 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5008 * @ioc: Pointer to a Adapter Strucutre
5009 * @portnum: IOC port number
5011 * Return: -EFAULT if read of config page header fails
5012 * or if no nvram
5013 * If read of SCSI Port Page 0 fails,
5014 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5015 * Adapter settings: async, narrow
5016 * Return 1
5017 * If read of SCSI Port Page 2 fails,
5018 * Adapter settings valid
5019 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5020 * Return 1
5021 * Else
5022 * Both valid
5023 * Return 0
5024 * CHECK - what type of locking mechanisms should be used????
5026 static int
5027 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
5029 u8 *pbuf;
5030 dma_addr_t buf_dma;
5031 CONFIGPARMS cfg;
5032 ConfigPageHeader_t header;
5033 int ii;
5034 int data, rc = 0;
5036 /* Allocate memory
5038 if (!ioc->spi_data.nvram) {
5039 int sz;
5040 u8 *mem;
5041 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5042 mem = kmalloc(sz, GFP_ATOMIC);
5043 if (mem == NULL)
5044 return -EFAULT;
5046 ioc->spi_data.nvram = (int *) mem;
5048 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5049 ioc->name, ioc->spi_data.nvram, sz));
5052 /* Invalidate NVRAM information
5054 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5055 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5058 /* Read SPP0 header, allocate memory, then read page.
5060 header.PageVersion = 0;
5061 header.PageLength = 0;
5062 header.PageNumber = 0;
5063 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5064 cfg.cfghdr.hdr = &header;
5065 cfg.physAddr = -1;
5066 cfg.pageAddr = portnum;
5067 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5068 cfg.dir = 0;
5069 cfg.timeout = 0; /* use default */
5070 if (mpt_config(ioc, &cfg) != 0)
5071 return -EFAULT;
5073 if (header.PageLength > 0) {
5074 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5075 if (pbuf) {
5076 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5077 cfg.physAddr = buf_dma;
5078 if (mpt_config(ioc, &cfg) != 0) {
5079 ioc->spi_data.maxBusWidth = MPT_NARROW;
5080 ioc->spi_data.maxSyncOffset = 0;
5081 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5082 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5083 rc = 1;
5084 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5085 "Unable to read PortPage0 minSyncFactor=%x\n",
5086 ioc->name, ioc->spi_data.minSyncFactor));
5087 } else {
5088 /* Save the Port Page 0 data
5090 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
5091 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5092 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5094 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5095 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5096 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5097 "noQas due to Capabilities=%x\n",
5098 ioc->name, pPP0->Capabilities));
5100 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5101 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5102 if (data) {
5103 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5104 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5105 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5106 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5107 "PortPage0 minSyncFactor=%x\n",
5108 ioc->name, ioc->spi_data.minSyncFactor));
5109 } else {
5110 ioc->spi_data.maxSyncOffset = 0;
5111 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5114 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5116 /* Update the minSyncFactor based on bus type.
5118 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5119 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
5121 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5122 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5123 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5124 "HVD or SE detected, minSyncFactor=%x\n",
5125 ioc->name, ioc->spi_data.minSyncFactor));
5129 if (pbuf) {
5130 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5135 /* SCSI Port Page 2 - Read the header then the page.
5137 header.PageVersion = 0;
5138 header.PageLength = 0;
5139 header.PageNumber = 2;
5140 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5141 cfg.cfghdr.hdr = &header;
5142 cfg.physAddr = -1;
5143 cfg.pageAddr = portnum;
5144 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5145 cfg.dir = 0;
5146 if (mpt_config(ioc, &cfg) != 0)
5147 return -EFAULT;
5149 if (header.PageLength > 0) {
5150 /* Allocate memory and read SCSI Port Page 2
5152 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5153 if (pbuf) {
5154 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5155 cfg.physAddr = buf_dma;
5156 if (mpt_config(ioc, &cfg) != 0) {
5157 /* Nvram data is left with INVALID mark
5159 rc = 1;
5160 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5162 /* This is an ATTO adapter, read Page2 accordingly
5164 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5165 ATTODeviceInfo_t *pdevice = NULL;
5166 u16 ATTOFlags;
5168 /* Save the Port Page 2 data
5169 * (reformat into a 32bit quantity)
5171 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5172 pdevice = &pPP2->DeviceSettings[ii];
5173 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5174 data = 0;
5176 /* Translate ATTO device flags to LSI format
5178 if (ATTOFlags & ATTOFLAG_DISC)
5179 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5180 if (ATTOFlags & ATTOFLAG_ID_ENB)
5181 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5182 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5183 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5184 if (ATTOFlags & ATTOFLAG_TAGGED)
5185 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5186 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5187 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5189 data = (data << 16) | (pdevice->Period << 8) | 10;
5190 ioc->spi_data.nvram[ii] = data;
5192 } else {
5193 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5194 MpiDeviceInfo_t *pdevice = NULL;
5197 * Save "Set to Avoid SCSI Bus Resets" flag
5199 ioc->spi_data.bus_reset =
5200 (le32_to_cpu(pPP2->PortFlags) &
5201 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5202 0 : 1 ;
5204 /* Save the Port Page 2 data
5205 * (reformat into a 32bit quantity)
5207 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5208 ioc->spi_data.PortFlags = data;
5209 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5210 pdevice = &pPP2->DeviceSettings[ii];
5211 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5212 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5213 ioc->spi_data.nvram[ii] = data;
5217 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5221 /* Update Adapter limits with those from NVRAM
5222 * Comment: Don't need to do this. Target performance
5223 * parameters will never exceed the adapters limits.
5226 return rc;
5229 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5231 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5232 * @ioc: Pointer to a Adapter Strucutre
5233 * @portnum: IOC port number
5235 * Return: -EFAULT if read of config page header fails
5236 * or 0 if success.
5238 static int
5239 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5241 CONFIGPARMS cfg;
5242 ConfigPageHeader_t header;
5244 /* Read the SCSI Device Page 1 header
5246 header.PageVersion = 0;
5247 header.PageLength = 0;
5248 header.PageNumber = 1;
5249 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5250 cfg.cfghdr.hdr = &header;
5251 cfg.physAddr = -1;
5252 cfg.pageAddr = portnum;
5253 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5254 cfg.dir = 0;
5255 cfg.timeout = 0;
5256 if (mpt_config(ioc, &cfg) != 0)
5257 return -EFAULT;
5259 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5260 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5262 header.PageVersion = 0;
5263 header.PageLength = 0;
5264 header.PageNumber = 0;
5265 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5266 if (mpt_config(ioc, &cfg) != 0)
5267 return -EFAULT;
5269 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5270 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5272 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5273 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5275 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5276 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5277 return 0;
5281 * mpt_inactive_raid_list_free - This clears this link list.
5282 * @ioc : pointer to per adapter structure
5284 static void
5285 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5287 struct inactive_raid_component_info *component_info, *pNext;
5289 if (list_empty(&ioc->raid_data.inactive_list))
5290 return;
5292 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5293 list_for_each_entry_safe(component_info, pNext,
5294 &ioc->raid_data.inactive_list, list) {
5295 list_del(&component_info->list);
5296 kfree(component_info);
5298 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5302 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5304 * @ioc : pointer to per adapter structure
5305 * @channel : volume channel
5306 * @id : volume target id
5308 static void
5309 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5311 CONFIGPARMS cfg;
5312 ConfigPageHeader_t hdr;
5313 dma_addr_t dma_handle;
5314 pRaidVolumePage0_t buffer = NULL;
5315 int i;
5316 RaidPhysDiskPage0_t phys_disk;
5317 struct inactive_raid_component_info *component_info;
5318 int handle_inactive_volumes;
5320 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5321 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5322 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5323 cfg.pageAddr = (channel << 8) + id;
5324 cfg.cfghdr.hdr = &hdr;
5325 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5327 if (mpt_config(ioc, &cfg) != 0)
5328 goto out;
5330 if (!hdr.PageLength)
5331 goto out;
5333 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5334 &dma_handle);
5336 if (!buffer)
5337 goto out;
5339 cfg.physAddr = dma_handle;
5340 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5342 if (mpt_config(ioc, &cfg) != 0)
5343 goto out;
5345 if (!buffer->NumPhysDisks)
5346 goto out;
5348 handle_inactive_volumes =
5349 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5350 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5351 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5352 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5354 if (!handle_inactive_volumes)
5355 goto out;
5357 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5358 for (i = 0; i < buffer->NumPhysDisks; i++) {
5359 if(mpt_raid_phys_disk_pg0(ioc,
5360 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5361 continue;
5363 if ((component_info = kmalloc(sizeof (*component_info),
5364 GFP_KERNEL)) == NULL)
5365 continue;
5367 component_info->volumeID = id;
5368 component_info->volumeBus = channel;
5369 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5370 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5371 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5372 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5374 list_add_tail(&component_info->list,
5375 &ioc->raid_data.inactive_list);
5377 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5379 out:
5380 if (buffer)
5381 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5382 dma_handle);
5386 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5387 * @ioc: Pointer to a Adapter Structure
5388 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5389 * @phys_disk: requested payload data returned
5391 * Return:
5392 * 0 on success
5393 * -EFAULT if read of config page header fails or data pointer not NULL
5394 * -ENOMEM if pci_alloc failed
5397 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
5399 CONFIGPARMS cfg;
5400 ConfigPageHeader_t hdr;
5401 dma_addr_t dma_handle;
5402 pRaidPhysDiskPage0_t buffer = NULL;
5403 int rc;
5405 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5406 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5408 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5409 cfg.cfghdr.hdr = &hdr;
5410 cfg.physAddr = -1;
5411 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5413 if (mpt_config(ioc, &cfg) != 0) {
5414 rc = -EFAULT;
5415 goto out;
5418 if (!hdr.PageLength) {
5419 rc = -EFAULT;
5420 goto out;
5423 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5424 &dma_handle);
5426 if (!buffer) {
5427 rc = -ENOMEM;
5428 goto out;
5431 cfg.physAddr = dma_handle;
5432 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5433 cfg.pageAddr = phys_disk_num;
5435 if (mpt_config(ioc, &cfg) != 0) {
5436 rc = -EFAULT;
5437 goto out;
5440 rc = 0;
5441 memcpy(phys_disk, buffer, sizeof(*buffer));
5442 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5444 out:
5446 if (buffer)
5447 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5448 dma_handle);
5450 return rc;
5454 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5455 * @ioc: Pointer to a Adapter Strucutre
5457 * Return:
5458 * 0 on success
5459 * -EFAULT if read of config page header fails or data pointer not NULL
5460 * -ENOMEM if pci_alloc failed
5463 mpt_findImVolumes(MPT_ADAPTER *ioc)
5465 IOCPage2_t *pIoc2;
5466 u8 *mem;
5467 dma_addr_t ioc2_dma;
5468 CONFIGPARMS cfg;
5469 ConfigPageHeader_t header;
5470 int rc = 0;
5471 int iocpage2sz;
5472 int i;
5474 if (!ioc->ir_firmware)
5475 return 0;
5477 /* Free the old page
5479 kfree(ioc->raid_data.pIocPg2);
5480 ioc->raid_data.pIocPg2 = NULL;
5481 mpt_inactive_raid_list_free(ioc);
5483 /* Read IOCP2 header then the page.
5485 header.PageVersion = 0;
5486 header.PageLength = 0;
5487 header.PageNumber = 2;
5488 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5489 cfg.cfghdr.hdr = &header;
5490 cfg.physAddr = -1;
5491 cfg.pageAddr = 0;
5492 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5493 cfg.dir = 0;
5494 cfg.timeout = 0;
5495 if (mpt_config(ioc, &cfg) != 0)
5496 return -EFAULT;
5498 if (header.PageLength == 0)
5499 return -EFAULT;
5501 iocpage2sz = header.PageLength * 4;
5502 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5503 if (!pIoc2)
5504 return -ENOMEM;
5506 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5507 cfg.physAddr = ioc2_dma;
5508 if (mpt_config(ioc, &cfg) != 0)
5509 goto out;
5511 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5512 if (!mem)
5513 goto out;
5515 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5516 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5518 mpt_read_ioc_pg_3(ioc);
5520 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5521 mpt_inactive_raid_volumes(ioc,
5522 pIoc2->RaidVolume[i].VolumeBus,
5523 pIoc2->RaidVolume[i].VolumeID);
5525 out:
5526 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5528 return rc;
5531 static int
5532 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5534 IOCPage3_t *pIoc3;
5535 u8 *mem;
5536 CONFIGPARMS cfg;
5537 ConfigPageHeader_t header;
5538 dma_addr_t ioc3_dma;
5539 int iocpage3sz = 0;
5541 /* Free the old page
5543 kfree(ioc->raid_data.pIocPg3);
5544 ioc->raid_data.pIocPg3 = NULL;
5546 /* There is at least one physical disk.
5547 * Read and save IOC Page 3
5549 header.PageVersion = 0;
5550 header.PageLength = 0;
5551 header.PageNumber = 3;
5552 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5553 cfg.cfghdr.hdr = &header;
5554 cfg.physAddr = -1;
5555 cfg.pageAddr = 0;
5556 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5557 cfg.dir = 0;
5558 cfg.timeout = 0;
5559 if (mpt_config(ioc, &cfg) != 0)
5560 return 0;
5562 if (header.PageLength == 0)
5563 return 0;
5565 /* Read Header good, alloc memory
5567 iocpage3sz = header.PageLength * 4;
5568 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5569 if (!pIoc3)
5570 return 0;
5572 /* Read the Page and save the data
5573 * into malloc'd memory.
5575 cfg.physAddr = ioc3_dma;
5576 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5577 if (mpt_config(ioc, &cfg) == 0) {
5578 mem = kmalloc(iocpage3sz, GFP_KERNEL);
5579 if (mem) {
5580 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5581 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5585 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5587 return 0;
5590 static void
5591 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5593 IOCPage4_t *pIoc4;
5594 CONFIGPARMS cfg;
5595 ConfigPageHeader_t header;
5596 dma_addr_t ioc4_dma;
5597 int iocpage4sz;
5599 /* Read and save IOC Page 4
5601 header.PageVersion = 0;
5602 header.PageLength = 0;
5603 header.PageNumber = 4;
5604 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5605 cfg.cfghdr.hdr = &header;
5606 cfg.physAddr = -1;
5607 cfg.pageAddr = 0;
5608 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5609 cfg.dir = 0;
5610 cfg.timeout = 0;
5611 if (mpt_config(ioc, &cfg) != 0)
5612 return;
5614 if (header.PageLength == 0)
5615 return;
5617 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5618 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5619 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5620 if (!pIoc4)
5621 return;
5622 ioc->alloc_total += iocpage4sz;
5623 } else {
5624 ioc4_dma = ioc->spi_data.IocPg4_dma;
5625 iocpage4sz = ioc->spi_data.IocPg4Sz;
5628 /* Read the Page into dma memory.
5630 cfg.physAddr = ioc4_dma;
5631 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5632 if (mpt_config(ioc, &cfg) == 0) {
5633 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5634 ioc->spi_data.IocPg4_dma = ioc4_dma;
5635 ioc->spi_data.IocPg4Sz = iocpage4sz;
5636 } else {
5637 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5638 ioc->spi_data.pIocPg4 = NULL;
5639 ioc->alloc_total -= iocpage4sz;
5643 static void
5644 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5646 IOCPage1_t *pIoc1;
5647 CONFIGPARMS cfg;
5648 ConfigPageHeader_t header;
5649 dma_addr_t ioc1_dma;
5650 int iocpage1sz = 0;
5651 u32 tmp;
5653 /* Check the Coalescing Timeout in IOC Page 1
5655 header.PageVersion = 0;
5656 header.PageLength = 0;
5657 header.PageNumber = 1;
5658 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5659 cfg.cfghdr.hdr = &header;
5660 cfg.physAddr = -1;
5661 cfg.pageAddr = 0;
5662 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5663 cfg.dir = 0;
5664 cfg.timeout = 0;
5665 if (mpt_config(ioc, &cfg) != 0)
5666 return;
5668 if (header.PageLength == 0)
5669 return;
5671 /* Read Header good, alloc memory
5673 iocpage1sz = header.PageLength * 4;
5674 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5675 if (!pIoc1)
5676 return;
5678 /* Read the Page and check coalescing timeout
5680 cfg.physAddr = ioc1_dma;
5681 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5682 if (mpt_config(ioc, &cfg) == 0) {
5684 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5685 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5686 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5688 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
5689 ioc->name, tmp));
5691 if (tmp > MPT_COALESCING_TIMEOUT) {
5692 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5694 /* Write NVRAM and current
5696 cfg.dir = 1;
5697 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5698 if (mpt_config(ioc, &cfg) == 0) {
5699 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
5700 ioc->name, MPT_COALESCING_TIMEOUT));
5702 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5703 if (mpt_config(ioc, &cfg) == 0) {
5704 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5705 "Reset NVRAM Coalescing Timeout to = %d\n",
5706 ioc->name, MPT_COALESCING_TIMEOUT));
5707 } else {
5708 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5709 "Reset NVRAM Coalescing Timeout Failed\n",
5710 ioc->name));
5713 } else {
5714 dprintk(ioc, printk(MYIOC_s_WARN_FMT
5715 "Reset of Current Coalescing Timeout Failed!\n",
5716 ioc->name));
5720 } else {
5721 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5725 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5727 return;
5730 static void
5731 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
5733 CONFIGPARMS cfg;
5734 ConfigPageHeader_t hdr;
5735 dma_addr_t buf_dma;
5736 ManufacturingPage0_t *pbuf = NULL;
5738 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5739 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5741 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5742 cfg.cfghdr.hdr = &hdr;
5743 cfg.physAddr = -1;
5744 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5745 cfg.timeout = 10;
5747 if (mpt_config(ioc, &cfg) != 0)
5748 goto out;
5750 if (!cfg.cfghdr.hdr->PageLength)
5751 goto out;
5753 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5754 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
5755 if (!pbuf)
5756 goto out;
5758 cfg.physAddr = buf_dma;
5760 if (mpt_config(ioc, &cfg) != 0)
5761 goto out;
5763 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
5764 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
5765 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
5767 out:
5769 if (pbuf)
5770 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
5773 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5775 * SendEventNotification - Send EventNotification (on or off) request to adapter
5776 * @ioc: Pointer to MPT_ADAPTER structure
5777 * @EvSwitch: Event switch flags
5779 static int
5780 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5782 EventNotification_t *evnp;
5784 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5785 if (evnp == NULL) {
5786 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5787 ioc->name));
5788 return 0;
5790 memset(evnp, 0, sizeof(*evnp));
5792 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5794 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5795 evnp->ChainOffset = 0;
5796 evnp->MsgFlags = 0;
5797 evnp->Switch = EvSwitch;
5799 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5801 return 0;
5804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5806 * SendEventAck - Send EventAck request to MPT adapter.
5807 * @ioc: Pointer to MPT_ADAPTER structure
5808 * @evnp: Pointer to original EventNotification request
5810 static int
5811 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5813 EventAck_t *pAck;
5815 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5816 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5817 ioc->name,__func__));
5818 return -1;
5821 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
5823 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5824 pAck->ChainOffset = 0;
5825 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5826 pAck->MsgFlags = 0;
5827 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5828 pAck->Event = evnp->Event;
5829 pAck->EventContext = evnp->EventContext;
5831 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5833 return 0;
5836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5838 * mpt_config - Generic function to issue config message
5839 * @ioc: Pointer to an adapter structure
5840 * @pCfg: Pointer to a configuration structure. Struct contains
5841 * action, page address, direction, physical address
5842 * and pointer to a configuration page header
5843 * Page header is updated.
5845 * Returns 0 for success
5846 * -EPERM if not allowed due to ISR context
5847 * -EAGAIN if no msg frames currently available
5848 * -EFAULT for non-successful reply or no reply (timeout)
5851 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5853 Config_t *pReq;
5854 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5855 MPT_FRAME_HDR *mf;
5856 unsigned long flags;
5857 int ii, rc;
5858 int flagsLength;
5859 int in_isr;
5861 /* Prevent calling wait_event() (below), if caller happens
5862 * to be in ISR context, because that is fatal!
5864 in_isr = in_interrupt();
5865 if (in_isr) {
5866 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5867 ioc->name));
5868 return -EPERM;
5871 /* Get and Populate a free Frame
5873 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5874 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5875 ioc->name));
5876 return -EAGAIN;
5878 pReq = (Config_t *)mf;
5879 pReq->Action = pCfg->action;
5880 pReq->Reserved = 0;
5881 pReq->ChainOffset = 0;
5882 pReq->Function = MPI_FUNCTION_CONFIG;
5884 /* Assume page type is not extended and clear "reserved" fields. */
5885 pReq->ExtPageLength = 0;
5886 pReq->ExtPageType = 0;
5887 pReq->MsgFlags = 0;
5889 for (ii=0; ii < 8; ii++)
5890 pReq->Reserved2[ii] = 0;
5892 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5893 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5894 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5895 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5897 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5898 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5899 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5900 pReq->ExtPageType = pExtHdr->ExtPageType;
5901 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5903 /* Page Length must be treated as a reserved field for the extended header. */
5904 pReq->Header.PageLength = 0;
5907 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5909 /* Add a SGE to the config request.
5911 if (pCfg->dir)
5912 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5913 else
5914 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5916 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5917 flagsLength |= pExtHdr->ExtPageLength * 4;
5919 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5920 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5922 else {
5923 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5925 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5926 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5929 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5931 /* Append pCfg pointer to end of mf
5933 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5935 /* Initalize the timer
5937 init_timer(&pCfg->timer);
5938 pCfg->timer.data = (unsigned long) ioc;
5939 pCfg->timer.function = mpt_timer_expired;
5940 pCfg->wait_done = 0;
5942 /* Set the timer; ensure 10 second minimum */
5943 if (pCfg->timeout < 10)
5944 pCfg->timer.expires = jiffies + HZ*10;
5945 else
5946 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5948 /* Add to end of Q, set timer and then issue this command */
5949 spin_lock_irqsave(&ioc->FreeQlock, flags);
5950 list_add_tail(&pCfg->linkage, &ioc->configQ);
5951 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5953 add_timer(&pCfg->timer);
5954 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5955 wait_event(mpt_waitq, pCfg->wait_done);
5957 /* mf has been freed - do not access */
5959 rc = pCfg->status;
5961 return rc;
5964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5966 * mpt_timer_expired - Callback for timer process.
5967 * Used only internal config functionality.
5968 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5970 static void
5971 mpt_timer_expired(unsigned long data)
5973 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5975 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
5977 /* Perform a FW reload */
5978 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5979 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5981 /* No more processing.
5982 * Hard reset clean-up will wake up
5983 * process and free all resources.
5985 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
5987 return;
5990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5992 * mpt_ioc_reset - Base cleanup for hard reset
5993 * @ioc: Pointer to the adapter structure
5994 * @reset_phase: Indicates pre- or post-reset functionality
5996 * Remark: Frees resources with internally generated commands.
5998 static int
5999 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
6001 CONFIGPARMS *pCfg;
6002 unsigned long flags;
6004 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6005 ": IOC %s_reset routed to MPT base driver!\n",
6006 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
6007 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
6009 if (reset_phase == MPT_IOC_SETUP_RESET) {
6011 } else if (reset_phase == MPT_IOC_PRE_RESET) {
6012 /* If the internal config Q is not empty -
6013 * delete timer. MF resources will be freed when
6014 * the FIFO's are primed.
6016 spin_lock_irqsave(&ioc->FreeQlock, flags);
6017 list_for_each_entry(pCfg, &ioc->configQ, linkage)
6018 del_timer(&pCfg->timer);
6019 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
6021 } else {
6022 CONFIGPARMS *pNext;
6024 /* Search the configQ for internal commands.
6025 * Flush the Q, and wake up all suspended threads.
6027 spin_lock_irqsave(&ioc->FreeQlock, flags);
6028 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
6029 list_del(&pCfg->linkage);
6031 pCfg->status = MPT_CONFIG_ERROR;
6032 pCfg->wait_done = 1;
6033 wake_up(&mpt_waitq);
6035 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
6038 return 1; /* currently means nothing really */
6042 #ifdef CONFIG_PROC_FS /* { */
6043 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6045 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6047 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6049 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6051 * Returns 0 for success, non-zero for failure.
6053 static int
6054 procmpt_create(void)
6056 struct proc_dir_entry *ent;
6058 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6059 if (mpt_proc_root_dir == NULL)
6060 return -ENOTDIR;
6062 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6063 if (ent)
6064 ent->read_proc = procmpt_summary_read;
6066 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6067 if (ent)
6068 ent->read_proc = procmpt_version_read;
6070 return 0;
6073 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6075 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6077 * Returns 0 for success, non-zero for failure.
6079 static void
6080 procmpt_destroy(void)
6082 remove_proc_entry("version", mpt_proc_root_dir);
6083 remove_proc_entry("summary", mpt_proc_root_dir);
6084 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6089 * procmpt_summary_read - Handle read request of a summary file
6090 * @buf: Pointer to area to write information
6091 * @start: Pointer to start pointer
6092 * @offset: Offset to start writing
6093 * @request: Amount of read data requested
6094 * @eof: Pointer to EOF integer
6095 * @data: Pointer
6097 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6098 * Returns number of characters written to process performing the read.
6100 static int
6101 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6103 MPT_ADAPTER *ioc;
6104 char *out = buf;
6105 int len;
6107 if (data) {
6108 int more = 0;
6110 ioc = data;
6111 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6113 out += more;
6114 } else {
6115 list_for_each_entry(ioc, &ioc_list, list) {
6116 int more = 0;
6118 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6120 out += more;
6121 if ((out-buf) >= request)
6122 break;
6126 len = out - buf;
6128 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6133 * procmpt_version_read - Handle read request from /proc/mpt/version.
6134 * @buf: Pointer to area to write information
6135 * @start: Pointer to start pointer
6136 * @offset: Offset to start writing
6137 * @request: Amount of read data requested
6138 * @eof: Pointer to EOF integer
6139 * @data: Pointer
6141 * Returns number of characters written to process performing the read.
6143 static int
6144 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6146 u8 cb_idx;
6147 int scsi, fc, sas, lan, ctl, targ, dmp;
6148 char *drvname;
6149 int len;
6151 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6152 len += sprintf(buf+len, " Fusion MPT base driver\n");
6154 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6155 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6156 drvname = NULL;
6157 if (MptCallbacks[cb_idx]) {
6158 switch (MptDriverClass[cb_idx]) {
6159 case MPTSPI_DRIVER:
6160 if (!scsi++) drvname = "SPI host";
6161 break;
6162 case MPTFC_DRIVER:
6163 if (!fc++) drvname = "FC host";
6164 break;
6165 case MPTSAS_DRIVER:
6166 if (!sas++) drvname = "SAS host";
6167 break;
6168 case MPTLAN_DRIVER:
6169 if (!lan++) drvname = "LAN";
6170 break;
6171 case MPTSTM_DRIVER:
6172 if (!targ++) drvname = "SCSI target";
6173 break;
6174 case MPTCTL_DRIVER:
6175 if (!ctl++) drvname = "ioctl";
6176 break;
6179 if (drvname)
6180 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
6184 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6187 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6189 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6190 * @buf: Pointer to area to write information
6191 * @start: Pointer to start pointer
6192 * @offset: Offset to start writing
6193 * @request: Amount of read data requested
6194 * @eof: Pointer to EOF integer
6195 * @data: Pointer
6197 * Returns number of characters written to process performing the read.
6199 static int
6200 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6202 MPT_ADAPTER *ioc = data;
6203 int len;
6204 char expVer[32];
6205 int sz;
6206 int p;
6208 mpt_get_fw_exp_ver(expVer, ioc);
6210 len = sprintf(buf, "%s:", ioc->name);
6211 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6212 len += sprintf(buf+len, " (f/w download boot flag set)");
6213 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6214 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6216 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
6217 ioc->facts.ProductID,
6218 ioc->prod_name);
6219 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6220 if (ioc->facts.FWImageSize)
6221 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6222 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6223 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6224 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
6226 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
6227 ioc->facts.CurrentHostMfaHighAddr);
6228 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
6229 ioc->facts.CurrentSenseBufferHighAddr);
6231 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6232 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6234 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6235 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6237 * Rounding UP to nearest 4-kB boundary here...
6239 sz = (ioc->req_sz * ioc->req_depth) + 128;
6240 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6241 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6242 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6243 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6244 4*ioc->facts.RequestFrameSize,
6245 ioc->facts.GlobalCredits);
6247 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
6248 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6249 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6250 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6251 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6252 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6253 ioc->facts.CurReplyFrameSize,
6254 ioc->facts.ReplyQueueDepth);
6256 len += sprintf(buf+len, " MaxDevices = %d\n",
6257 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6258 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6260 /* per-port info */
6261 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6262 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
6263 p+1,
6264 ioc->facts.NumberOfPorts);
6265 if (ioc->bus_type == FC) {
6266 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6267 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6268 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6269 a[5], a[4], a[3], a[2], a[1], a[0]);
6271 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
6272 ioc->fc_port_page0[p].WWNN.High,
6273 ioc->fc_port_page0[p].WWNN.Low,
6274 ioc->fc_port_page0[p].WWPN.High,
6275 ioc->fc_port_page0[p].WWPN.Low);
6279 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6282 #endif /* CONFIG_PROC_FS } */
6284 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6285 static void
6286 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6288 buf[0] ='\0';
6289 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6290 sprintf(buf, " (Exp %02d%02d)",
6291 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6292 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6294 /* insider hack! */
6295 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6296 strcat(buf, " [MDBG]");
6300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6302 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6303 * @ioc: Pointer to MPT_ADAPTER structure
6304 * @buffer: Pointer to buffer where IOC summary info should be written
6305 * @size: Pointer to number of bytes we wrote (set by this routine)
6306 * @len: Offset at which to start writing in buffer
6307 * @showlan: Display LAN stuff?
6309 * This routine writes (english readable) ASCII text, which represents
6310 * a summary of IOC information, to a buffer.
6312 void
6313 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6315 char expVer[32];
6316 int y;
6318 mpt_get_fw_exp_ver(expVer, ioc);
6321 * Shorter summary of attached ioc's...
6323 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6324 ioc->name,
6325 ioc->prod_name,
6326 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6327 ioc->facts.FWVersion.Word,
6328 expVer,
6329 ioc->facts.NumberOfPorts,
6330 ioc->req_depth);
6332 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6333 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6334 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6335 a[5], a[4], a[3], a[2], a[1], a[0]);
6338 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6340 if (!ioc->active)
6341 y += sprintf(buffer+len+y, " (disabled)");
6343 y += sprintf(buffer+len+y, "\n");
6345 *size = y;
6350 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6351 * the kernel
6352 * @ioc: Pointer to MPT_ADAPTER structure
6355 void
6356 mpt_halt_firmware(MPT_ADAPTER *ioc)
6358 u32 ioc_raw_state;
6360 ioc_raw_state = mpt_GetIocState(ioc, 0);
6362 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6363 printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6364 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6365 panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6366 ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6367 } else {
6368 CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6369 panic("%s: Firmware is halted due to command timeout\n",
6370 ioc->name);
6373 EXPORT_SYMBOL(mpt_halt_firmware);
6375 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6377 * Reset Handling
6379 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6381 * mpt_HardResetHandler - Generic reset handler
6382 * @ioc: Pointer to MPT_ADAPTER structure
6383 * @sleepFlag: Indicates if sleep or schedule must be called.
6385 * Issues SCSI Task Management call based on input arg values.
6386 * If TaskMgmt fails, returns associated SCSI request.
6388 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6389 * or a non-interrupt thread. In the former, must not call schedule().
6391 * Note: A return of -1 is a FATAL error case, as it means a
6392 * FW reload/initialization failed.
6394 * Returns 0 for SUCCESS or -1 if FAILED.
6397 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6399 int rc;
6400 unsigned long flags;
6402 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6403 #ifdef MFCNT
6404 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6405 printk("MF count 0x%x !\n", ioc->mfcnt);
6406 #endif
6407 if (mpt_fwfault_debug)
6408 mpt_halt_firmware(ioc);
6410 /* Reset the adapter. Prevent more than 1 call to
6411 * mpt_do_ioc_recovery at any instant in time.
6413 spin_lock_irqsave(&ioc->diagLock, flags);
6414 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
6415 spin_unlock_irqrestore(&ioc->diagLock, flags);
6416 return 0;
6417 } else {
6418 ioc->diagPending = 1;
6420 spin_unlock_irqrestore(&ioc->diagLock, flags);
6422 /* FIXME: If do_ioc_recovery fails, repeat....
6425 /* The SCSI driver needs to adjust timeouts on all current
6426 * commands prior to the diagnostic reset being issued.
6427 * Prevents timeouts occurring during a diagnostic reset...very bad.
6428 * For all other protocol drivers, this is a no-op.
6431 u8 cb_idx;
6432 int r = 0;
6434 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6435 if (MptResetHandlers[cb_idx]) {
6436 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
6437 ioc->name, cb_idx));
6438 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6439 if (ioc->alt_ioc) {
6440 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
6441 ioc->name, ioc->alt_ioc->name, cb_idx));
6442 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
6448 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
6449 printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
6451 ioc->reload_fw = 0;
6452 if (ioc->alt_ioc)
6453 ioc->alt_ioc->reload_fw = 0;
6455 spin_lock_irqsave(&ioc->diagLock, flags);
6456 ioc->diagPending = 0;
6457 if (ioc->alt_ioc)
6458 ioc->alt_ioc->diagPending = 0;
6459 spin_unlock_irqrestore(&ioc->diagLock, flags);
6461 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
6463 return rc;
6466 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6467 static void
6468 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
6470 char *ds = NULL;
6472 switch(event) {
6473 case MPI_EVENT_NONE:
6474 ds = "None";
6475 break;
6476 case MPI_EVENT_LOG_DATA:
6477 ds = "Log Data";
6478 break;
6479 case MPI_EVENT_STATE_CHANGE:
6480 ds = "State Change";
6481 break;
6482 case MPI_EVENT_UNIT_ATTENTION:
6483 ds = "Unit Attention";
6484 break;
6485 case MPI_EVENT_IOC_BUS_RESET:
6486 ds = "IOC Bus Reset";
6487 break;
6488 case MPI_EVENT_EXT_BUS_RESET:
6489 ds = "External Bus Reset";
6490 break;
6491 case MPI_EVENT_RESCAN:
6492 ds = "Bus Rescan Event";
6493 break;
6494 case MPI_EVENT_LINK_STATUS_CHANGE:
6495 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
6496 ds = "Link Status(FAILURE) Change";
6497 else
6498 ds = "Link Status(ACTIVE) Change";
6499 break;
6500 case MPI_EVENT_LOOP_STATE_CHANGE:
6501 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
6502 ds = "Loop State(LIP) Change";
6503 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
6504 ds = "Loop State(LPE) Change"; /* ??? */
6505 else
6506 ds = "Loop State(LPB) Change"; /* ??? */
6507 break;
6508 case MPI_EVENT_LOGOUT:
6509 ds = "Logout";
6510 break;
6511 case MPI_EVENT_EVENT_CHANGE:
6512 if (evData0)
6513 ds = "Events ON";
6514 else
6515 ds = "Events OFF";
6516 break;
6517 case MPI_EVENT_INTEGRATED_RAID:
6519 u8 ReasonCode = (u8)(evData0 >> 16);
6520 switch (ReasonCode) {
6521 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
6522 ds = "Integrated Raid: Volume Created";
6523 break;
6524 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
6525 ds = "Integrated Raid: Volume Deleted";
6526 break;
6527 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
6528 ds = "Integrated Raid: Volume Settings Changed";
6529 break;
6530 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
6531 ds = "Integrated Raid: Volume Status Changed";
6532 break;
6533 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
6534 ds = "Integrated Raid: Volume Physdisk Changed";
6535 break;
6536 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
6537 ds = "Integrated Raid: Physdisk Created";
6538 break;
6539 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
6540 ds = "Integrated Raid: Physdisk Deleted";
6541 break;
6542 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
6543 ds = "Integrated Raid: Physdisk Settings Changed";
6544 break;
6545 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
6546 ds = "Integrated Raid: Physdisk Status Changed";
6547 break;
6548 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
6549 ds = "Integrated Raid: Domain Validation Needed";
6550 break;
6551 case MPI_EVENT_RAID_RC_SMART_DATA :
6552 ds = "Integrated Raid; Smart Data";
6553 break;
6554 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
6555 ds = "Integrated Raid: Replace Action Started";
6556 break;
6557 default:
6558 ds = "Integrated Raid";
6559 break;
6561 break;
6563 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
6564 ds = "SCSI Device Status Change";
6565 break;
6566 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
6568 u8 id = (u8)(evData0);
6569 u8 channel = (u8)(evData0 >> 8);
6570 u8 ReasonCode = (u8)(evData0 >> 16);
6571 switch (ReasonCode) {
6572 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
6573 snprintf(evStr, EVENT_DESCR_STR_SZ,
6574 "SAS Device Status Change: Added: "
6575 "id=%d channel=%d", id, channel);
6576 break;
6577 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
6578 snprintf(evStr, EVENT_DESCR_STR_SZ,
6579 "SAS Device Status Change: Deleted: "
6580 "id=%d channel=%d", id, channel);
6581 break;
6582 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
6583 snprintf(evStr, EVENT_DESCR_STR_SZ,
6584 "SAS Device Status Change: SMART Data: "
6585 "id=%d channel=%d", id, channel);
6586 break;
6587 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
6588 snprintf(evStr, EVENT_DESCR_STR_SZ,
6589 "SAS Device Status Change: No Persistancy: "
6590 "id=%d channel=%d", id, channel);
6591 break;
6592 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
6593 snprintf(evStr, EVENT_DESCR_STR_SZ,
6594 "SAS Device Status Change: Unsupported Device "
6595 "Discovered : id=%d channel=%d", id, channel);
6596 break;
6597 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
6598 snprintf(evStr, EVENT_DESCR_STR_SZ,
6599 "SAS Device Status Change: Internal Device "
6600 "Reset : id=%d channel=%d", id, channel);
6601 break;
6602 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
6603 snprintf(evStr, EVENT_DESCR_STR_SZ,
6604 "SAS Device Status Change: Internal Task "
6605 "Abort : id=%d channel=%d", id, channel);
6606 break;
6607 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
6608 snprintf(evStr, EVENT_DESCR_STR_SZ,
6609 "SAS Device Status Change: Internal Abort "
6610 "Task Set : id=%d channel=%d", id, channel);
6611 break;
6612 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
6613 snprintf(evStr, EVENT_DESCR_STR_SZ,
6614 "SAS Device Status Change: Internal Clear "
6615 "Task Set : id=%d channel=%d", id, channel);
6616 break;
6617 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
6618 snprintf(evStr, EVENT_DESCR_STR_SZ,
6619 "SAS Device Status Change: Internal Query "
6620 "Task : id=%d channel=%d", id, channel);
6621 break;
6622 default:
6623 snprintf(evStr, EVENT_DESCR_STR_SZ,
6624 "SAS Device Status Change: Unknown: "
6625 "id=%d channel=%d", id, channel);
6626 break;
6628 break;
6630 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
6631 ds = "Bus Timer Expired";
6632 break;
6633 case MPI_EVENT_QUEUE_FULL:
6635 u16 curr_depth = (u16)(evData0 >> 16);
6636 u8 channel = (u8)(evData0 >> 8);
6637 u8 id = (u8)(evData0);
6639 snprintf(evStr, EVENT_DESCR_STR_SZ,
6640 "Queue Full: channel=%d id=%d depth=%d",
6641 channel, id, curr_depth);
6642 break;
6644 case MPI_EVENT_SAS_SES:
6645 ds = "SAS SES Event";
6646 break;
6647 case MPI_EVENT_PERSISTENT_TABLE_FULL:
6648 ds = "Persistent Table Full";
6649 break;
6650 case MPI_EVENT_SAS_PHY_LINK_STATUS:
6652 u8 LinkRates = (u8)(evData0 >> 8);
6653 u8 PhyNumber = (u8)(evData0);
6654 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
6655 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
6656 switch (LinkRates) {
6657 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
6658 snprintf(evStr, EVENT_DESCR_STR_SZ,
6659 "SAS PHY Link Status: Phy=%d:"
6660 " Rate Unknown",PhyNumber);
6661 break;
6662 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
6663 snprintf(evStr, EVENT_DESCR_STR_SZ,
6664 "SAS PHY Link Status: Phy=%d:"
6665 " Phy Disabled",PhyNumber);
6666 break;
6667 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
6668 snprintf(evStr, EVENT_DESCR_STR_SZ,
6669 "SAS PHY Link Status: Phy=%d:"
6670 " Failed Speed Nego",PhyNumber);
6671 break;
6672 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
6673 snprintf(evStr, EVENT_DESCR_STR_SZ,
6674 "SAS PHY Link Status: Phy=%d:"
6675 " Sata OOB Completed",PhyNumber);
6676 break;
6677 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
6678 snprintf(evStr, EVENT_DESCR_STR_SZ,
6679 "SAS PHY Link Status: Phy=%d:"
6680 " Rate 1.5 Gbps",PhyNumber);
6681 break;
6682 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
6683 snprintf(evStr, EVENT_DESCR_STR_SZ,
6684 "SAS PHY Link Status: Phy=%d:"
6685 " Rate 3.0 Gpbs",PhyNumber);
6686 break;
6687 default:
6688 snprintf(evStr, EVENT_DESCR_STR_SZ,
6689 "SAS PHY Link Status: Phy=%d", PhyNumber);
6690 break;
6692 break;
6694 case MPI_EVENT_SAS_DISCOVERY_ERROR:
6695 ds = "SAS Discovery Error";
6696 break;
6697 case MPI_EVENT_IR_RESYNC_UPDATE:
6699 u8 resync_complete = (u8)(evData0 >> 16);
6700 snprintf(evStr, EVENT_DESCR_STR_SZ,
6701 "IR Resync Update: Complete = %d:",resync_complete);
6702 break;
6704 case MPI_EVENT_IR2:
6706 u8 ReasonCode = (u8)(evData0 >> 16);
6707 switch (ReasonCode) {
6708 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
6709 ds = "IR2: LD State Changed";
6710 break;
6711 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
6712 ds = "IR2: PD State Changed";
6713 break;
6714 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
6715 ds = "IR2: Bad Block Table Full";
6716 break;
6717 case MPI_EVENT_IR2_RC_PD_INSERTED:
6718 ds = "IR2: PD Inserted";
6719 break;
6720 case MPI_EVENT_IR2_RC_PD_REMOVED:
6721 ds = "IR2: PD Removed";
6722 break;
6723 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
6724 ds = "IR2: Foreign CFG Detected";
6725 break;
6726 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
6727 ds = "IR2: Rebuild Medium Error";
6728 break;
6729 default:
6730 ds = "IR2";
6731 break;
6733 break;
6735 case MPI_EVENT_SAS_DISCOVERY:
6737 if (evData0)
6738 ds = "SAS Discovery: Start";
6739 else
6740 ds = "SAS Discovery: Stop";
6741 break;
6743 case MPI_EVENT_LOG_ENTRY_ADDED:
6744 ds = "SAS Log Entry Added";
6745 break;
6747 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
6749 u8 phy_num = (u8)(evData0);
6750 u8 port_num = (u8)(evData0 >> 8);
6751 u8 port_width = (u8)(evData0 >> 16);
6752 u8 primative = (u8)(evData0 >> 24);
6753 snprintf(evStr, EVENT_DESCR_STR_SZ,
6754 "SAS Broadcase Primative: phy=%d port=%d "
6755 "width=%d primative=0x%02x",
6756 phy_num, port_num, port_width, primative);
6757 break;
6760 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
6762 u8 reason = (u8)(evData0);
6763 u8 port_num = (u8)(evData0 >> 8);
6764 u16 handle = le16_to_cpu(evData0 >> 16);
6766 snprintf(evStr, EVENT_DESCR_STR_SZ,
6767 "SAS Initiator Device Status Change: reason=0x%02x "
6768 "port=%d handle=0x%04x",
6769 reason, port_num, handle);
6770 break;
6773 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6775 u8 max_init = (u8)(evData0);
6776 u8 current_init = (u8)(evData0 >> 8);
6778 snprintf(evStr, EVENT_DESCR_STR_SZ,
6779 "SAS Initiator Device Table Overflow: max initiators=%02d "
6780 "current initators=%02d",
6781 max_init, current_init);
6782 break;
6784 case MPI_EVENT_SAS_SMP_ERROR:
6786 u8 status = (u8)(evData0);
6787 u8 port_num = (u8)(evData0 >> 8);
6788 u8 result = (u8)(evData0 >> 16);
6790 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6791 snprintf(evStr, EVENT_DESCR_STR_SZ,
6792 "SAS SMP Error: port=%d result=0x%02x",
6793 port_num, result);
6794 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6795 snprintf(evStr, EVENT_DESCR_STR_SZ,
6796 "SAS SMP Error: port=%d : CRC Error",
6797 port_num);
6798 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6799 snprintf(evStr, EVENT_DESCR_STR_SZ,
6800 "SAS SMP Error: port=%d : Timeout",
6801 port_num);
6802 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6803 snprintf(evStr, EVENT_DESCR_STR_SZ,
6804 "SAS SMP Error: port=%d : No Destination",
6805 port_num);
6806 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6807 snprintf(evStr, EVENT_DESCR_STR_SZ,
6808 "SAS SMP Error: port=%d : Bad Destination",
6809 port_num);
6810 else
6811 snprintf(evStr, EVENT_DESCR_STR_SZ,
6812 "SAS SMP Error: port=%d : status=0x%02x",
6813 port_num, status);
6814 break;
6818 * MPT base "custom" events may be added here...
6820 default:
6821 ds = "Unknown";
6822 break;
6824 if (ds)
6825 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6828 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6830 * ProcessEventNotification - Route EventNotificationReply to all event handlers
6831 * @ioc: Pointer to MPT_ADAPTER structure
6832 * @pEventReply: Pointer to EventNotification reply frame
6833 * @evHandlers: Pointer to integer, number of event handlers
6835 * Routes a received EventNotificationReply to all currently registered
6836 * event handlers.
6837 * Returns sum of event handlers return values.
6839 static int
6840 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6842 u16 evDataLen;
6843 u32 evData0 = 0;
6844 // u32 evCtx;
6845 int ii;
6846 u8 cb_idx;
6847 int r = 0;
6848 int handlers = 0;
6849 char evStr[EVENT_DESCR_STR_SZ];
6850 u8 event;
6853 * Do platform normalization of values
6855 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6856 // evCtx = le32_to_cpu(pEventReply->EventContext);
6857 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6858 if (evDataLen) {
6859 evData0 = le32_to_cpu(pEventReply->Data[0]);
6862 EventDescriptionStr(event, evData0, evStr);
6863 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
6864 ioc->name,
6865 event,
6866 evStr));
6868 #ifdef CONFIG_FUSION_LOGGING
6869 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6870 ": Event data:\n", ioc->name));
6871 for (ii = 0; ii < evDataLen; ii++)
6872 devtverboseprintk(ioc, printk(" %08x",
6873 le32_to_cpu(pEventReply->Data[ii])));
6874 devtverboseprintk(ioc, printk("\n"));
6875 #endif
6878 * Do general / base driver event processing
6880 switch(event) {
6881 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6882 if (evDataLen) {
6883 u8 evState = evData0 & 0xFF;
6885 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6887 /* Update EventState field in cached IocFacts */
6888 if (ioc->facts.Function) {
6889 ioc->facts.EventState = evState;
6892 break;
6893 case MPI_EVENT_INTEGRATED_RAID:
6894 mptbase_raid_process_event_data(ioc,
6895 (MpiEventDataRaid_t *)pEventReply->Data);
6896 break;
6897 default:
6898 break;
6902 * Should this event be logged? Events are written sequentially.
6903 * When buffer is full, start again at the top.
6905 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6906 int idx;
6908 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6910 ioc->events[idx].event = event;
6911 ioc->events[idx].eventContext = ioc->eventContext;
6913 for (ii = 0; ii < 2; ii++) {
6914 if (ii < evDataLen)
6915 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6916 else
6917 ioc->events[idx].data[ii] = 0;
6920 ioc->eventContext++;
6925 * Call each currently registered protocol event handler.
6927 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6928 if (MptEvHandlers[cb_idx]) {
6929 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
6930 ioc->name, cb_idx));
6931 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
6932 handlers++;
6935 /* FIXME? Examine results here? */
6938 * If needed, send (a single) EventAck.
6940 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6941 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6942 "EventAck required\n",ioc->name));
6943 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6944 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
6945 ioc->name, ii));
6949 *evHandlers = handlers;
6950 return r;
6953 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6955 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6956 * @ioc: Pointer to MPT_ADAPTER structure
6957 * @log_info: U32 LogInfo reply word from the IOC
6959 * Refer to lsi/mpi_log_fc.h.
6961 static void
6962 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6964 char *desc = "unknown";
6966 switch (log_info & 0xFF000000) {
6967 case MPI_IOCLOGINFO_FC_INIT_BASE:
6968 desc = "FCP Initiator";
6969 break;
6970 case MPI_IOCLOGINFO_FC_TARGET_BASE:
6971 desc = "FCP Target";
6972 break;
6973 case MPI_IOCLOGINFO_FC_LAN_BASE:
6974 desc = "LAN";
6975 break;
6976 case MPI_IOCLOGINFO_FC_MSG_BASE:
6977 desc = "MPI Message Layer";
6978 break;
6979 case MPI_IOCLOGINFO_FC_LINK_BASE:
6980 desc = "FC Link";
6981 break;
6982 case MPI_IOCLOGINFO_FC_CTX_BASE:
6983 desc = "Context Manager";
6984 break;
6985 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
6986 desc = "Invalid Field Offset";
6987 break;
6988 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
6989 desc = "State Change Info";
6990 break;
6993 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6994 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
6997 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6999 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7000 * @ioc: Pointer to MPT_ADAPTER structure
7001 * @log_info: U32 LogInfo word from the IOC
7003 * Refer to lsi/sp_log.h.
7005 static void
7006 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7008 u32 info = log_info & 0x00FF0000;
7009 char *desc = "unknown";
7011 switch (info) {
7012 case 0x00010000:
7013 desc = "bug! MID not found";
7014 if (ioc->reload_fw == 0)
7015 ioc->reload_fw++;
7016 break;
7018 case 0x00020000:
7019 desc = "Parity Error";
7020 break;
7022 case 0x00030000:
7023 desc = "ASYNC Outbound Overrun";
7024 break;
7026 case 0x00040000:
7027 desc = "SYNC Offset Error";
7028 break;
7030 case 0x00050000:
7031 desc = "BM Change";
7032 break;
7034 case 0x00060000:
7035 desc = "Msg In Overflow";
7036 break;
7038 case 0x00070000:
7039 desc = "DMA Error";
7040 break;
7042 case 0x00080000:
7043 desc = "Outbound DMA Overrun";
7044 break;
7046 case 0x00090000:
7047 desc = "Task Management";
7048 break;
7050 case 0x000A0000:
7051 desc = "Device Problem";
7052 break;
7054 case 0x000B0000:
7055 desc = "Invalid Phase Change";
7056 break;
7058 case 0x000C0000:
7059 desc = "Untagged Table Size";
7060 break;
7064 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7067 /* strings for sas loginfo */
7068 static char *originator_str[] = {
7069 "IOP", /* 00h */
7070 "PL", /* 01h */
7071 "IR" /* 02h */
7073 static char *iop_code_str[] = {
7074 NULL, /* 00h */
7075 "Invalid SAS Address", /* 01h */
7076 NULL, /* 02h */
7077 "Invalid Page", /* 03h */
7078 "Diag Message Error", /* 04h */
7079 "Task Terminated", /* 05h */
7080 "Enclosure Management", /* 06h */
7081 "Target Mode" /* 07h */
7083 static char *pl_code_str[] = {
7084 NULL, /* 00h */
7085 "Open Failure", /* 01h */
7086 "Invalid Scatter Gather List", /* 02h */
7087 "Wrong Relative Offset or Frame Length", /* 03h */
7088 "Frame Transfer Error", /* 04h */
7089 "Transmit Frame Connected Low", /* 05h */
7090 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7091 "SATA Read Log Receive Data Error", /* 07h */
7092 "SATA NCQ Fail All Commands After Error", /* 08h */
7093 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7094 "Receive Frame Invalid Message", /* 0Ah */
7095 "Receive Context Message Valid Error", /* 0Bh */
7096 "Receive Frame Current Frame Error", /* 0Ch */
7097 "SATA Link Down", /* 0Dh */
7098 "Discovery SATA Init W IOS", /* 0Eh */
7099 "Config Invalid Page", /* 0Fh */
7100 "Discovery SATA Init Timeout", /* 10h */
7101 "Reset", /* 11h */
7102 "Abort", /* 12h */
7103 "IO Not Yet Executed", /* 13h */
7104 "IO Executed", /* 14h */
7105 "Persistent Reservation Out Not Affiliation "
7106 "Owner", /* 15h */
7107 "Open Transmit DMA Abort", /* 16h */
7108 "IO Device Missing Delay Retry", /* 17h */
7109 "IO Cancelled Due to Recieve Error", /* 18h */
7110 NULL, /* 19h */
7111 NULL, /* 1Ah */
7112 NULL, /* 1Bh */
7113 NULL, /* 1Ch */
7114 NULL, /* 1Dh */
7115 NULL, /* 1Eh */
7116 NULL, /* 1Fh */
7117 "Enclosure Management" /* 20h */
7119 static char *ir_code_str[] = {
7120 "Raid Action Error", /* 00h */
7121 NULL, /* 00h */
7122 NULL, /* 01h */
7123 NULL, /* 02h */
7124 NULL, /* 03h */
7125 NULL, /* 04h */
7126 NULL, /* 05h */
7127 NULL, /* 06h */
7128 NULL /* 07h */
7130 static char *raid_sub_code_str[] = {
7131 NULL, /* 00h */
7132 "Volume Creation Failed: Data Passed too "
7133 "Large", /* 01h */
7134 "Volume Creation Failed: Duplicate Volumes "
7135 "Attempted", /* 02h */
7136 "Volume Creation Failed: Max Number "
7137 "Supported Volumes Exceeded", /* 03h */
7138 "Volume Creation Failed: DMA Error", /* 04h */
7139 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7140 "Volume Creation Failed: Error Reading "
7141 "MFG Page 4", /* 06h */
7142 "Volume Creation Failed: Creating Internal "
7143 "Structures", /* 07h */
7144 NULL, /* 08h */
7145 NULL, /* 09h */
7146 NULL, /* 0Ah */
7147 NULL, /* 0Bh */
7148 NULL, /* 0Ch */
7149 NULL, /* 0Dh */
7150 NULL, /* 0Eh */
7151 NULL, /* 0Fh */
7152 "Activation failed: Already Active Volume", /* 10h */
7153 "Activation failed: Unsupported Volume Type", /* 11h */
7154 "Activation failed: Too Many Active Volumes", /* 12h */
7155 "Activation failed: Volume ID in Use", /* 13h */
7156 "Activation failed: Reported Failure", /* 14h */
7157 "Activation failed: Importing a Volume", /* 15h */
7158 NULL, /* 16h */
7159 NULL, /* 17h */
7160 NULL, /* 18h */
7161 NULL, /* 19h */
7162 NULL, /* 1Ah */
7163 NULL, /* 1Bh */
7164 NULL, /* 1Ch */
7165 NULL, /* 1Dh */
7166 NULL, /* 1Eh */
7167 NULL, /* 1Fh */
7168 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7169 "Phys Disk failed: Data Passed too Large", /* 21h */
7170 "Phys Disk failed: DMA Error", /* 22h */
7171 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7172 "Phys Disk failed: Creating Phys Disk Config "
7173 "Page", /* 24h */
7174 NULL, /* 25h */
7175 NULL, /* 26h */
7176 NULL, /* 27h */
7177 NULL, /* 28h */
7178 NULL, /* 29h */
7179 NULL, /* 2Ah */
7180 NULL, /* 2Bh */
7181 NULL, /* 2Ch */
7182 NULL, /* 2Dh */
7183 NULL, /* 2Eh */
7184 NULL, /* 2Fh */
7185 "Compatibility Error: IR Disabled", /* 30h */
7186 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7187 "Compatibility Error: Device not Direct Access "
7188 "Device ", /* 32h */
7189 "Compatibility Error: Removable Device Found", /* 33h */
7190 "Compatibility Error: Device SCSI Version not "
7191 "2 or Higher", /* 34h */
7192 "Compatibility Error: SATA Device, 48 BIT LBA "
7193 "not Supported", /* 35h */
7194 "Compatibility Error: Device doesn't have "
7195 "512 Byte Block Sizes", /* 36h */
7196 "Compatibility Error: Volume Type Check Failed", /* 37h */
7197 "Compatibility Error: Volume Type is "
7198 "Unsupported by FW", /* 38h */
7199 "Compatibility Error: Disk Drive too Small for "
7200 "use in Volume", /* 39h */
7201 "Compatibility Error: Phys Disk for Create "
7202 "Volume not Found", /* 3Ah */
7203 "Compatibility Error: Too Many or too Few "
7204 "Disks for Volume Type", /* 3Bh */
7205 "Compatibility Error: Disk stripe Sizes "
7206 "Must be 64KB", /* 3Ch */
7207 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7212 * mpt_sas_log_info - Log information returned from SAS IOC.
7213 * @ioc: Pointer to MPT_ADAPTER structure
7214 * @log_info: U32 LogInfo reply word from the IOC
7216 * Refer to lsi/mpi_log_sas.h.
7218 static void
7219 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7221 union loginfo_type {
7222 u32 loginfo;
7223 struct {
7224 u32 subcode:16;
7225 u32 code:8;
7226 u32 originator:4;
7227 u32 bus_type:4;
7228 }dw;
7230 union loginfo_type sas_loginfo;
7231 char *originator_desc = NULL;
7232 char *code_desc = NULL;
7233 char *sub_code_desc = NULL;
7235 sas_loginfo.loginfo = log_info;
7236 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7237 (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
7238 return;
7240 originator_desc = originator_str[sas_loginfo.dw.originator];
7242 switch (sas_loginfo.dw.originator) {
7244 case 0: /* IOP */
7245 if (sas_loginfo.dw.code <
7246 ARRAY_SIZE(iop_code_str))
7247 code_desc = iop_code_str[sas_loginfo.dw.code];
7248 break;
7249 case 1: /* PL */
7250 if (sas_loginfo.dw.code <
7251 ARRAY_SIZE(pl_code_str))
7252 code_desc = pl_code_str[sas_loginfo.dw.code];
7253 break;
7254 case 2: /* IR */
7255 if (sas_loginfo.dw.code >=
7256 ARRAY_SIZE(ir_code_str))
7257 break;
7258 code_desc = ir_code_str[sas_loginfo.dw.code];
7259 if (sas_loginfo.dw.subcode >=
7260 ARRAY_SIZE(raid_sub_code_str))
7261 break;
7262 if (sas_loginfo.dw.code == 0)
7263 sub_code_desc =
7264 raid_sub_code_str[sas_loginfo.dw.subcode];
7265 break;
7266 default:
7267 return;
7270 if (sub_code_desc != NULL)
7271 printk(MYIOC_s_INFO_FMT
7272 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7273 " SubCode={%s}\n",
7274 ioc->name, log_info, originator_desc, code_desc,
7275 sub_code_desc);
7276 else if (code_desc != NULL)
7277 printk(MYIOC_s_INFO_FMT
7278 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7279 " SubCode(0x%04x)\n",
7280 ioc->name, log_info, originator_desc, code_desc,
7281 sas_loginfo.dw.subcode);
7282 else
7283 printk(MYIOC_s_INFO_FMT
7284 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7285 " SubCode(0x%04x)\n",
7286 ioc->name, log_info, originator_desc,
7287 sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7290 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7292 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7293 * @ioc: Pointer to MPT_ADAPTER structure
7294 * @ioc_status: U32 IOCStatus word from IOC
7295 * @mf: Pointer to MPT request frame
7297 * Refer to lsi/mpi.h.
7299 static void
7300 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7302 Config_t *pReq = (Config_t *)mf;
7303 char extend_desc[EVENT_DESCR_STR_SZ];
7304 char *desc = NULL;
7305 u32 form;
7306 u8 page_type;
7308 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7309 page_type = pReq->ExtPageType;
7310 else
7311 page_type = pReq->Header.PageType;
7314 * ignore invalid page messages for GET_NEXT_HANDLE
7316 form = le32_to_cpu(pReq->PageAddress);
7317 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7318 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7319 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7320 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7321 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7322 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7323 return;
7325 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7326 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7327 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7328 return;
7331 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7332 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7333 page_type, pReq->Header.PageNumber, pReq->Action, form);
7335 switch (ioc_status) {
7337 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7338 desc = "Config Page Invalid Action";
7339 break;
7341 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7342 desc = "Config Page Invalid Type";
7343 break;
7345 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7346 desc = "Config Page Invalid Page";
7347 break;
7349 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7350 desc = "Config Page Invalid Data";
7351 break;
7353 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7354 desc = "Config Page No Defaults";
7355 break;
7357 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7358 desc = "Config Page Can't Commit";
7359 break;
7362 if (!desc)
7363 return;
7365 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7366 ioc->name, ioc_status, desc, extend_desc));
7370 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7371 * @ioc: Pointer to MPT_ADAPTER structure
7372 * @ioc_status: U32 IOCStatus word from IOC
7373 * @mf: Pointer to MPT request frame
7375 * Refer to lsi/mpi.h.
7377 static void
7378 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7380 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
7381 char *desc = NULL;
7383 switch (status) {
7385 /****************************************************************************/
7386 /* Common IOCStatus values for all replies */
7387 /****************************************************************************/
7389 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
7390 desc = "Invalid Function";
7391 break;
7393 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
7394 desc = "Busy";
7395 break;
7397 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
7398 desc = "Invalid SGL";
7399 break;
7401 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
7402 desc = "Internal Error";
7403 break;
7405 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
7406 desc = "Reserved";
7407 break;
7409 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
7410 desc = "Insufficient Resources";
7411 break;
7413 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
7414 desc = "Invalid Field";
7415 break;
7417 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
7418 desc = "Invalid State";
7419 break;
7421 /****************************************************************************/
7422 /* Config IOCStatus values */
7423 /****************************************************************************/
7425 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7426 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7427 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7428 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7429 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7430 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7431 mpt_iocstatus_info_config(ioc, status, mf);
7432 break;
7434 /****************************************************************************/
7435 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
7436 /* */
7437 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7438 /* */
7439 /****************************************************************************/
7441 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
7442 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
7443 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
7444 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
7445 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
7446 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
7447 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
7448 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
7449 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
7450 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
7451 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
7452 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
7453 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
7454 break;
7456 /****************************************************************************/
7457 /* SCSI Target values */
7458 /****************************************************************************/
7460 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
7461 desc = "Target: Priority IO";
7462 break;
7464 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
7465 desc = "Target: Invalid Port";
7466 break;
7468 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
7469 desc = "Target Invalid IO Index:";
7470 break;
7472 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
7473 desc = "Target: Aborted";
7474 break;
7476 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
7477 desc = "Target: No Conn Retryable";
7478 break;
7480 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
7481 desc = "Target: No Connection";
7482 break;
7484 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
7485 desc = "Target: Transfer Count Mismatch";
7486 break;
7488 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
7489 desc = "Target: STS Data not Sent";
7490 break;
7492 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
7493 desc = "Target: Data Offset Error";
7494 break;
7496 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
7497 desc = "Target: Too Much Write Data";
7498 break;
7500 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
7501 desc = "Target: IU Too Short";
7502 break;
7504 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
7505 desc = "Target: ACK NAK Timeout";
7506 break;
7508 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
7509 desc = "Target: Nak Received";
7510 break;
7512 /****************************************************************************/
7513 /* Fibre Channel Direct Access values */
7514 /****************************************************************************/
7516 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
7517 desc = "FC: Aborted";
7518 break;
7520 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
7521 desc = "FC: RX ID Invalid";
7522 break;
7524 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
7525 desc = "FC: DID Invalid";
7526 break;
7528 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
7529 desc = "FC: Node Logged Out";
7530 break;
7532 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
7533 desc = "FC: Exchange Canceled";
7534 break;
7536 /****************************************************************************/
7537 /* LAN values */
7538 /****************************************************************************/
7540 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
7541 desc = "LAN: Device not Found";
7542 break;
7544 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
7545 desc = "LAN: Device Failure";
7546 break;
7548 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
7549 desc = "LAN: Transmit Error";
7550 break;
7552 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
7553 desc = "LAN: Transmit Aborted";
7554 break;
7556 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
7557 desc = "LAN: Receive Error";
7558 break;
7560 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
7561 desc = "LAN: Receive Aborted";
7562 break;
7564 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
7565 desc = "LAN: Partial Packet";
7566 break;
7568 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
7569 desc = "LAN: Canceled";
7570 break;
7572 /****************************************************************************/
7573 /* Serial Attached SCSI values */
7574 /****************************************************************************/
7576 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
7577 desc = "SAS: SMP Request Failed";
7578 break;
7580 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
7581 desc = "SAS: SMP Data Overrun";
7582 break;
7584 default:
7585 desc = "Others";
7586 break;
7589 if (!desc)
7590 return;
7592 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
7593 ioc->name, status, desc));
7596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7597 EXPORT_SYMBOL(mpt_attach);
7598 EXPORT_SYMBOL(mpt_detach);
7599 #ifdef CONFIG_PM
7600 EXPORT_SYMBOL(mpt_resume);
7601 EXPORT_SYMBOL(mpt_suspend);
7602 #endif
7603 EXPORT_SYMBOL(ioc_list);
7604 EXPORT_SYMBOL(mpt_register);
7605 EXPORT_SYMBOL(mpt_deregister);
7606 EXPORT_SYMBOL(mpt_event_register);
7607 EXPORT_SYMBOL(mpt_event_deregister);
7608 EXPORT_SYMBOL(mpt_reset_register);
7609 EXPORT_SYMBOL(mpt_reset_deregister);
7610 EXPORT_SYMBOL(mpt_device_driver_register);
7611 EXPORT_SYMBOL(mpt_device_driver_deregister);
7612 EXPORT_SYMBOL(mpt_get_msg_frame);
7613 EXPORT_SYMBOL(mpt_put_msg_frame);
7614 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
7615 EXPORT_SYMBOL(mpt_free_msg_frame);
7616 EXPORT_SYMBOL(mpt_add_sge);
7617 EXPORT_SYMBOL(mpt_send_handshake_request);
7618 EXPORT_SYMBOL(mpt_verify_adapter);
7619 EXPORT_SYMBOL(mpt_GetIocState);
7620 EXPORT_SYMBOL(mpt_print_ioc_summary);
7621 EXPORT_SYMBOL(mpt_HardResetHandler);
7622 EXPORT_SYMBOL(mpt_config);
7623 EXPORT_SYMBOL(mpt_findImVolumes);
7624 EXPORT_SYMBOL(mpt_alloc_fw_memory);
7625 EXPORT_SYMBOL(mpt_free_fw_memory);
7626 EXPORT_SYMBOL(mptbase_sas_persist_operation);
7627 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
7629 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7631 * fusion_init - Fusion MPT base driver initialization routine.
7633 * Returns 0 for success, non-zero for failure.
7635 static int __init
7636 fusion_init(void)
7638 u8 cb_idx;
7640 show_mptmod_ver(my_NAME, my_VERSION);
7641 printk(KERN_INFO COPYRIGHT "\n");
7643 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
7644 MptCallbacks[cb_idx] = NULL;
7645 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
7646 MptEvHandlers[cb_idx] = NULL;
7647 MptResetHandlers[cb_idx] = NULL;
7650 /* Register ourselves (mptbase) in order to facilitate
7651 * EventNotification handling.
7653 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
7655 /* Register for hard reset handling callbacks.
7657 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
7659 #ifdef CONFIG_PROC_FS
7660 (void) procmpt_create();
7661 #endif
7662 return 0;
7665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7667 * fusion_exit - Perform driver unload cleanup.
7669 * This routine frees all resources associated with each MPT adapter
7670 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
7672 static void __exit
7673 fusion_exit(void)
7676 mpt_reset_deregister(mpt_base_index);
7678 #ifdef CONFIG_PROC_FS
7679 procmpt_destroy();
7680 #endif
7683 module_init(fusion_init);
7684 module_exit(fusion_exit);