added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / message / fusion / mptbase.c
blobeaee1823f3886aa8e00b2731fa2097f3c1409596
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 #ifdef CONFIG_PROC_FS
130 static struct proc_dir_entry *mpt_proc_root_dir;
131 #endif
133 #define WHOINIT_UNKNOWN 0xAA
135 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
137 * Private data...
139 /* Adapter link list */
140 LIST_HEAD(ioc_list);
141 /* Callback lookup table */
142 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
143 /* Protocol driver class lookup table */
144 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
145 /* Event handler lookup table */
146 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
147 /* Reset handler lookup table */
148 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
149 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
151 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
154 * Driver Callback Index's
156 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
157 static u8 last_drv_idx;
159 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
161 * Forward protos...
163 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
164 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
165 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
166 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
167 int sleepFlag);
168 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
169 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
170 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
171 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
173 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
174 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
175 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
176 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
177 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
178 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
179 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
180 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
181 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
182 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
183 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
184 static int PrimeIocFifos(MPT_ADAPTER *ioc);
185 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
186 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
187 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
188 static int GetLanConfigPages(MPT_ADAPTER *ioc);
189 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
190 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
191 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
192 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
193 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
194 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
195 static void mpt_timer_expired(unsigned long data);
196 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
197 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
198 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
199 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
200 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
202 #ifdef CONFIG_PROC_FS
203 static int procmpt_summary_read(char *buf, char **start, off_t offset,
204 int request, int *eof, void *data);
205 static int procmpt_version_read(char *buf, char **start, off_t offset,
206 int request, int *eof, void *data);
207 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
208 int request, int *eof, void *data);
209 #endif
210 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
212 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
213 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
214 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
215 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
216 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
217 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
218 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
219 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
221 /* module entry point */
222 static int __init fusion_init (void);
223 static void __exit fusion_exit (void);
225 #define CHIPREG_READ32(addr) readl_relaxed(addr)
226 #define CHIPREG_READ32_dmasync(addr) readl(addr)
227 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
228 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
229 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
231 static void
232 pci_disable_io_access(struct pci_dev *pdev)
234 u16 command_reg;
236 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
237 command_reg &= ~1;
238 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
241 static void
242 pci_enable_io_access(struct pci_dev *pdev)
244 u16 command_reg;
246 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
247 command_reg |= 1;
248 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
251 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
253 int ret = param_set_int(val, kp);
254 MPT_ADAPTER *ioc;
256 if (ret)
257 return ret;
259 list_for_each_entry(ioc, &ioc_list, list)
260 ioc->debug_level = mpt_debug_level;
261 return 0;
265 * mpt_get_cb_idx - obtain cb_idx for registered driver
266 * @dclass: class driver enum
268 * Returns cb_idx, or zero means it wasn't found
270 static u8
271 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
273 u8 cb_idx;
275 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
276 if (MptDriverClass[cb_idx] == dclass)
277 return cb_idx;
278 return 0;
282 * mpt_fault_reset_work - work performed on workq after ioc fault
283 * @work: input argument, used to derive ioc
286 static void
287 mpt_fault_reset_work(struct work_struct *work)
289 MPT_ADAPTER *ioc =
290 container_of(work, MPT_ADAPTER, fault_reset_work.work);
291 u32 ioc_raw_state;
292 int rc;
293 unsigned long flags;
295 if (ioc->diagPending || !ioc->active)
296 goto out;
298 ioc_raw_state = mpt_GetIocState(ioc, 0);
299 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
300 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
301 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
302 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
303 ioc->name, __func__);
304 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
305 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
306 __func__, (rc == 0) ? "success" : "failed");
307 ioc_raw_state = mpt_GetIocState(ioc, 0);
308 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
309 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
310 "reset (%04xh)\n", ioc->name, ioc_raw_state &
311 MPI_DOORBELL_DATA_MASK);
314 out:
316 * Take turns polling alternate controller
318 if (ioc->alt_ioc)
319 ioc = ioc->alt_ioc;
321 /* rearm the timer */
322 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
323 if (ioc->reset_work_q)
324 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
325 msecs_to_jiffies(MPT_POLLING_INTERVAL));
326 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
331 * Process turbo (context) reply...
333 static void
334 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
336 MPT_FRAME_HDR *mf = NULL;
337 MPT_FRAME_HDR *mr = NULL;
338 u16 req_idx = 0;
339 u8 cb_idx;
341 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
342 ioc->name, pa));
344 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
345 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
346 req_idx = pa & 0x0000FFFF;
347 cb_idx = (pa & 0x00FF0000) >> 16;
348 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
349 break;
350 case MPI_CONTEXT_REPLY_TYPE_LAN:
351 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
353 * Blind set of mf to NULL here was fatal
354 * after lan_reply says "freeme"
355 * Fix sort of combined with an optimization here;
356 * added explicit check for case where lan_reply
357 * was just returning 1 and doing nothing else.
358 * For this case skip the callback, but set up
359 * proper mf value first here:-)
361 if ((pa & 0x58000000) == 0x58000000) {
362 req_idx = pa & 0x0000FFFF;
363 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
364 mpt_free_msg_frame(ioc, mf);
365 mb();
366 return;
367 break;
369 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
370 break;
371 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
372 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
373 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
374 break;
375 default:
376 cb_idx = 0;
377 BUG();
380 /* Check for (valid) IO callback! */
381 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
382 MptCallbacks[cb_idx] == NULL) {
383 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
384 __func__, ioc->name, cb_idx);
385 goto out;
388 if (MptCallbacks[cb_idx](ioc, mf, mr))
389 mpt_free_msg_frame(ioc, mf);
390 out:
391 mb();
394 static void
395 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
397 MPT_FRAME_HDR *mf;
398 MPT_FRAME_HDR *mr;
399 u16 req_idx;
400 u8 cb_idx;
401 int freeme;
403 u32 reply_dma_low;
404 u16 ioc_stat;
406 /* non-TURBO reply! Hmmm, something may be up...
407 * Newest turbo reply mechanism; get address
408 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
411 /* Map DMA address of reply header to cpu address.
412 * pa is 32 bits - but the dma address may be 32 or 64 bits
413 * get offset based only only the low addresses
416 reply_dma_low = (pa <<= 1);
417 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
418 (reply_dma_low - ioc->reply_frames_low_dma));
420 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
421 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
422 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
424 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
425 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
426 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
428 /* Check/log IOC log info
430 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
431 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
432 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
433 if (ioc->bus_type == FC)
434 mpt_fc_log_info(ioc, log_info);
435 else if (ioc->bus_type == SPI)
436 mpt_spi_log_info(ioc, log_info);
437 else if (ioc->bus_type == SAS)
438 mpt_sas_log_info(ioc, log_info);
441 if (ioc_stat & MPI_IOCSTATUS_MASK)
442 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
444 /* Check for (valid) IO callback! */
445 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
446 MptCallbacks[cb_idx] == NULL) {
447 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
448 __func__, ioc->name, cb_idx);
449 freeme = 0;
450 goto out;
453 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
455 out:
456 /* Flush (non-TURBO) reply with a WRITE! */
457 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
459 if (freeme)
460 mpt_free_msg_frame(ioc, mf);
461 mb();
464 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
466 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
467 * @irq: irq number (not used)
468 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
470 * This routine is registered via the request_irq() kernel API call,
471 * and handles all interrupts generated from a specific MPT adapter
472 * (also referred to as a IO Controller or IOC).
473 * This routine must clear the interrupt from the adapter and does
474 * so by reading the reply FIFO. Multiple replies may be processed
475 * per single call to this routine.
477 * This routine handles register-level access of the adapter but
478 * dispatches (calls) a protocol-specific callback routine to handle
479 * the protocol-specific details of the MPT request completion.
481 static irqreturn_t
482 mpt_interrupt(int irq, void *bus_id)
484 MPT_ADAPTER *ioc = bus_id;
485 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
487 if (pa == 0xFFFFFFFF)
488 return IRQ_NONE;
491 * Drain the reply FIFO!
493 do {
494 if (pa & MPI_ADDRESS_REPLY_A_BIT)
495 mpt_reply(ioc, pa);
496 else
497 mpt_turbo_reply(ioc, pa);
498 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
499 } while (pa != 0xFFFFFFFF);
501 return IRQ_HANDLED;
504 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
506 * mpt_base_reply - MPT base driver's callback routine
507 * @ioc: Pointer to MPT_ADAPTER structure
508 * @mf: Pointer to original MPT request frame
509 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
511 * MPT base driver's callback routine; all base driver
512 * "internal" request/reply processing is routed here.
513 * Currently used for EventNotification and EventAck handling.
515 * Returns 1 indicating original alloc'd request frame ptr
516 * should be freed, or 0 if it shouldn't.
518 static int
519 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
521 int freereq = 1;
522 u8 func;
524 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
525 #ifdef CONFIG_FUSION_LOGGING
526 if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
527 !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
528 dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
529 ioc->name, mf));
530 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
532 #endif
534 func = reply->u.hdr.Function;
535 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
536 ioc->name, func));
538 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
539 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
540 int evHandlers = 0;
541 int results;
543 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
544 if (results != evHandlers) {
545 /* CHECKME! Any special handling needed here? */
546 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
547 ioc->name, evHandlers, results));
551 * Hmmm... It seems that EventNotificationReply is an exception
552 * to the rule of one reply per request.
554 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
555 freereq = 0;
556 } else {
557 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
558 ioc->name, pEvReply));
561 #ifdef CONFIG_PROC_FS
562 // LogEvent(ioc, pEvReply);
563 #endif
565 } else if (func == MPI_FUNCTION_EVENT_ACK) {
566 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
567 ioc->name));
568 } else if (func == MPI_FUNCTION_CONFIG) {
569 CONFIGPARMS *pCfg;
570 unsigned long flags;
572 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
573 ioc->name, mf, reply));
575 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
577 if (pCfg) {
578 /* disable timer and remove from linked list */
579 del_timer(&pCfg->timer);
581 spin_lock_irqsave(&ioc->FreeQlock, flags);
582 list_del(&pCfg->linkage);
583 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
586 * If IOC Status is SUCCESS, save the header
587 * and set the status code to GOOD.
589 pCfg->status = MPT_CONFIG_ERROR;
590 if (reply) {
591 ConfigReply_t *pReply = (ConfigReply_t *)reply;
592 u16 status;
594 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
595 dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
596 ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
598 pCfg->status = status;
599 if (status == MPI_IOCSTATUS_SUCCESS) {
600 if ((pReply->Header.PageType &
601 MPI_CONFIG_PAGETYPE_MASK) ==
602 MPI_CONFIG_PAGETYPE_EXTENDED) {
603 pCfg->cfghdr.ehdr->ExtPageLength =
604 le16_to_cpu(pReply->ExtPageLength);
605 pCfg->cfghdr.ehdr->ExtPageType =
606 pReply->ExtPageType;
608 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
610 /* If this is a regular header, save PageLength. */
611 /* LMP Do this better so not using a reserved field! */
612 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
613 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
614 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
619 * Wake up the original calling thread
621 pCfg->wait_done = 1;
622 wake_up(&mpt_waitq);
624 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
625 /* we should be always getting a reply frame */
626 memcpy(ioc->persist_reply_frame, reply,
627 min(MPT_DEFAULT_FRAME_SIZE,
628 4*reply->u.reply.MsgLength));
629 del_timer(&ioc->persist_timer);
630 ioc->persist_wait_done = 1;
631 wake_up(&mpt_waitq);
632 } else {
633 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
634 ioc->name, func);
638 * Conditionally tell caller to free the original
639 * EventNotification/EventAck/unexpected request frame!
641 return freereq;
644 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
646 * mpt_register - Register protocol-specific main callback handler.
647 * @cbfunc: callback function pointer
648 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
650 * This routine is called by a protocol-specific driver (SCSI host,
651 * LAN, SCSI target) to register its reply callback routine. Each
652 * protocol-specific driver must do this before it will be able to
653 * use any IOC resources, such as obtaining request frames.
655 * NOTES: The SCSI protocol driver currently calls this routine thrice
656 * in order to register separate callbacks; one for "normal" SCSI IO;
657 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
659 * Returns u8 valued "handle" in the range (and S.O.D. order)
660 * {N,...,7,6,5,...,1} if successful.
661 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
662 * considered an error by the caller.
665 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
667 u8 cb_idx;
668 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
671 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
672 * (slot/handle 0 is reserved!)
674 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
675 if (MptCallbacks[cb_idx] == NULL) {
676 MptCallbacks[cb_idx] = cbfunc;
677 MptDriverClass[cb_idx] = dclass;
678 MptEvHandlers[cb_idx] = NULL;
679 last_drv_idx = cb_idx;
680 break;
684 return last_drv_idx;
687 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
689 * mpt_deregister - Deregister a protocol drivers resources.
690 * @cb_idx: previously registered callback handle
692 * Each protocol-specific driver should call this routine when its
693 * module is unloaded.
695 void
696 mpt_deregister(u8 cb_idx)
698 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
699 MptCallbacks[cb_idx] = NULL;
700 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
701 MptEvHandlers[cb_idx] = NULL;
703 last_drv_idx++;
707 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
709 * mpt_event_register - Register protocol-specific event callback handler.
710 * @cb_idx: previously registered (via mpt_register) callback handle
711 * @ev_cbfunc: callback function
713 * This routine can be called by one or more protocol-specific drivers
714 * if/when they choose to be notified of MPT events.
716 * Returns 0 for success.
719 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
721 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
722 return -1;
724 MptEvHandlers[cb_idx] = ev_cbfunc;
725 return 0;
728 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
730 * mpt_event_deregister - Deregister protocol-specific event callback handler
731 * @cb_idx: previously registered callback handle
733 * Each protocol-specific driver should call this routine
734 * when it does not (or can no longer) handle events,
735 * or when its module is unloaded.
737 void
738 mpt_event_deregister(u8 cb_idx)
740 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
741 return;
743 MptEvHandlers[cb_idx] = NULL;
746 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
748 * mpt_reset_register - Register protocol-specific IOC reset handler.
749 * @cb_idx: previously registered (via mpt_register) callback handle
750 * @reset_func: reset function
752 * This routine can be called by one or more protocol-specific drivers
753 * if/when they choose to be notified of IOC resets.
755 * Returns 0 for success.
758 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
760 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
761 return -1;
763 MptResetHandlers[cb_idx] = reset_func;
764 return 0;
767 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
769 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
770 * @cb_idx: previously registered callback handle
772 * Each protocol-specific driver should call this routine
773 * when it does not (or can no longer) handle IOC reset handling,
774 * or when its module is unloaded.
776 void
777 mpt_reset_deregister(u8 cb_idx)
779 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
780 return;
782 MptResetHandlers[cb_idx] = NULL;
785 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
787 * mpt_device_driver_register - Register device driver hooks
788 * @dd_cbfunc: driver callbacks struct
789 * @cb_idx: MPT protocol driver index
792 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
794 MPT_ADAPTER *ioc;
795 const struct pci_device_id *id;
797 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
798 return -EINVAL;
800 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
802 /* call per pci device probe entry point */
803 list_for_each_entry(ioc, &ioc_list, list) {
804 id = ioc->pcidev->driver ?
805 ioc->pcidev->driver->id_table : NULL;
806 if (dd_cbfunc->probe)
807 dd_cbfunc->probe(ioc->pcidev, id);
810 return 0;
813 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
815 * mpt_device_driver_deregister - DeRegister device driver hooks
816 * @cb_idx: MPT protocol driver index
818 void
819 mpt_device_driver_deregister(u8 cb_idx)
821 struct mpt_pci_driver *dd_cbfunc;
822 MPT_ADAPTER *ioc;
824 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
825 return;
827 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
829 list_for_each_entry(ioc, &ioc_list, list) {
830 if (dd_cbfunc->remove)
831 dd_cbfunc->remove(ioc->pcidev);
834 MptDeviceDriverHandlers[cb_idx] = NULL;
838 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
840 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
841 * @cb_idx: Handle of registered MPT protocol driver
842 * @ioc: Pointer to MPT adapter structure
844 * Obtain an MPT request frame from the pool (of 1024) that are
845 * allocated per MPT adapter.
847 * Returns pointer to a MPT request frame or %NULL if none are available
848 * or IOC is not active.
850 MPT_FRAME_HDR*
851 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
853 MPT_FRAME_HDR *mf;
854 unsigned long flags;
855 u16 req_idx; /* Request index */
857 /* validate handle and ioc identifier */
859 #ifdef MFCNT
860 if (!ioc->active)
861 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
862 "returning NULL!\n", ioc->name);
863 #endif
865 /* If interrupts are not attached, do not return a request frame */
866 if (!ioc->active)
867 return NULL;
869 spin_lock_irqsave(&ioc->FreeQlock, flags);
870 if (!list_empty(&ioc->FreeQ)) {
871 int req_offset;
873 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
874 u.frame.linkage.list);
875 list_del(&mf->u.frame.linkage.list);
876 mf->u.frame.linkage.arg1 = 0;
877 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
878 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
879 /* u16! */
880 req_idx = req_offset / ioc->req_sz;
881 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
882 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
883 /* Default, will be changed if necessary in SG generation */
884 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
885 #ifdef MFCNT
886 ioc->mfcnt++;
887 #endif
889 else
890 mf = NULL;
891 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
893 #ifdef MFCNT
894 if (mf == NULL)
895 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
896 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
897 ioc->req_depth);
898 mfcounter++;
899 if (mfcounter == PRINT_MF_COUNT)
900 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
901 ioc->mfcnt, ioc->req_depth);
902 #endif
904 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
905 ioc->name, cb_idx, ioc->id, mf));
906 return mf;
909 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
911 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
912 * @cb_idx: Handle of registered MPT protocol driver
913 * @ioc: Pointer to MPT adapter structure
914 * @mf: Pointer to MPT request frame
916 * This routine posts an MPT request frame to the request post FIFO of a
917 * specific MPT adapter.
919 void
920 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
922 u32 mf_dma_addr;
923 int req_offset;
924 u16 req_idx; /* Request index */
926 /* ensure values are reset properly! */
927 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
928 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
929 /* u16! */
930 req_idx = req_offset / ioc->req_sz;
931 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
932 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
934 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
936 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
937 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
938 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
939 ioc->RequestNB[req_idx]));
940 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
944 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
945 * @cb_idx: Handle of registered MPT protocol driver
946 * @ioc: Pointer to MPT adapter structure
947 * @mf: Pointer to MPT request frame
949 * Send a protocol-specific MPT request frame to an IOC using
950 * hi-priority request queue.
952 * This routine posts an MPT request frame to the request post FIFO of a
953 * specific MPT adapter.
955 void
956 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
958 u32 mf_dma_addr;
959 int req_offset;
960 u16 req_idx; /* Request index */
962 /* ensure values are reset properly! */
963 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
964 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
965 req_idx = req_offset / ioc->req_sz;
966 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
967 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
969 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
971 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
972 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
973 ioc->name, mf_dma_addr, req_idx));
974 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
977 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
979 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
980 * @ioc: Pointer to MPT adapter structure
981 * @mf: Pointer to MPT request frame
983 * This routine places a MPT request frame back on the MPT adapter's
984 * FreeQ.
986 void
987 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
989 unsigned long flags;
991 /* Put Request back on FreeQ! */
992 spin_lock_irqsave(&ioc->FreeQlock, flags);
993 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
994 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
995 #ifdef MFCNT
996 ioc->mfcnt--;
997 #endif
998 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1001 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1003 * mpt_add_sge - Place a simple SGE at address pAddr.
1004 * @pAddr: virtual address for SGE
1005 * @flagslength: SGE flags and data transfer length
1006 * @dma_addr: Physical address
1008 * This routine places a MPT request frame back on the MPT adapter's
1009 * FreeQ.
1011 void
1012 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
1014 if (sizeof(dma_addr_t) == sizeof(u64)) {
1015 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1016 u32 tmp = dma_addr & 0xFFFFFFFF;
1018 pSge->FlagsLength = cpu_to_le32(flagslength);
1019 pSge->Address.Low = cpu_to_le32(tmp);
1020 tmp = (u32) ((u64)dma_addr >> 32);
1021 pSge->Address.High = cpu_to_le32(tmp);
1023 } else {
1024 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1025 pSge->FlagsLength = cpu_to_le32(flagslength);
1026 pSge->Address = cpu_to_le32(dma_addr);
1030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1032 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1033 * @cb_idx: Handle of registered MPT protocol driver
1034 * @ioc: Pointer to MPT adapter structure
1035 * @reqBytes: Size of the request in bytes
1036 * @req: Pointer to MPT request frame
1037 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1039 * This routine is used exclusively to send MptScsiTaskMgmt
1040 * requests since they are required to be sent via doorbell handshake.
1042 * NOTE: It is the callers responsibility to byte-swap fields in the
1043 * request which are greater than 1 byte in size.
1045 * Returns 0 for success, non-zero for failure.
1048 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1050 int r = 0;
1051 u8 *req_as_bytes;
1052 int ii;
1054 /* State is known to be good upon entering
1055 * this function so issue the bus reset
1056 * request.
1060 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1061 * setting cb_idx/req_idx. But ONLY if this request
1062 * is in proper (pre-alloc'd) request buffer range...
1064 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1065 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1066 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1067 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1068 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1071 /* Make sure there are no doorbells */
1072 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1074 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1075 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1076 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1078 /* Wait for IOC doorbell int */
1079 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1080 return ii;
1083 /* Read doorbell and check for active bit */
1084 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1085 return -5;
1087 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1088 ioc->name, ii));
1090 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1092 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1093 return -2;
1096 /* Send request via doorbell handshake */
1097 req_as_bytes = (u8 *) req;
1098 for (ii = 0; ii < reqBytes/4; ii++) {
1099 u32 word;
1101 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1102 (req_as_bytes[(ii*4) + 1] << 8) |
1103 (req_as_bytes[(ii*4) + 2] << 16) |
1104 (req_as_bytes[(ii*4) + 3] << 24));
1105 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1106 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1107 r = -3;
1108 break;
1112 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1113 r = 0;
1114 else
1115 r = -4;
1117 /* Make sure there are no doorbells */
1118 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1120 return r;
1123 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1125 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1126 * @ioc: Pointer to MPT adapter structure
1127 * @access_control_value: define bits below
1128 * @sleepFlag: Specifies whether the process can sleep
1130 * Provides mechanism for the host driver to control the IOC's
1131 * Host Page Buffer access.
1133 * Access Control Value - bits[15:12]
1134 * 0h Reserved
1135 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1136 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1137 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1139 * Returns 0 for success, non-zero for failure.
1142 static int
1143 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1145 int r = 0;
1147 /* return if in use */
1148 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1149 & MPI_DOORBELL_ACTIVE)
1150 return -1;
1152 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1154 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1155 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1156 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1157 (access_control_value<<12)));
1159 /* Wait for IOC to clear Doorbell Status bit */
1160 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1161 return -2;
1162 }else
1163 return 0;
1166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1168 * mpt_host_page_alloc - allocate system memory for the fw
1169 * @ioc: Pointer to pointer to IOC adapter
1170 * @ioc_init: Pointer to ioc init config page
1172 * If we already allocated memory in past, then resend the same pointer.
1173 * Returns 0 for success, non-zero for failure.
1175 static int
1176 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1178 char *psge;
1179 int flags_length;
1180 u32 host_page_buffer_sz=0;
1182 if(!ioc->HostPageBuffer) {
1184 host_page_buffer_sz =
1185 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1187 if(!host_page_buffer_sz)
1188 return 0; /* fw doesn't need any host buffers */
1190 /* spin till we get enough memory */
1191 while(host_page_buffer_sz > 0) {
1193 if((ioc->HostPageBuffer = pci_alloc_consistent(
1194 ioc->pcidev,
1195 host_page_buffer_sz,
1196 &ioc->HostPageBuffer_dma)) != NULL) {
1198 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1199 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1200 ioc->name, ioc->HostPageBuffer,
1201 (u32)ioc->HostPageBuffer_dma,
1202 host_page_buffer_sz));
1203 ioc->alloc_total += host_page_buffer_sz;
1204 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1205 break;
1208 host_page_buffer_sz -= (4*1024);
1212 if(!ioc->HostPageBuffer) {
1213 printk(MYIOC_s_ERR_FMT
1214 "Failed to alloc memory for host_page_buffer!\n",
1215 ioc->name);
1216 return -999;
1219 psge = (char *)&ioc_init->HostPageBufferSGE;
1220 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1221 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1222 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1223 MPI_SGE_FLAGS_HOST_TO_IOC |
1224 MPI_SGE_FLAGS_END_OF_BUFFER;
1225 if (sizeof(dma_addr_t) == sizeof(u64)) {
1226 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1228 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1229 flags_length |= ioc->HostPageBuffer_sz;
1230 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1231 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1233 return 0;
1236 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1238 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1239 * @iocid: IOC unique identifier (integer)
1240 * @iocpp: Pointer to pointer to IOC adapter
1242 * Given a unique IOC identifier, set pointer to the associated MPT
1243 * adapter structure.
1245 * Returns iocid and sets iocpp if iocid is found.
1246 * Returns -1 if iocid is not found.
1249 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1251 MPT_ADAPTER *ioc;
1253 list_for_each_entry(ioc,&ioc_list,list) {
1254 if (ioc->id == iocid) {
1255 *iocpp =ioc;
1256 return iocid;
1260 *iocpp = NULL;
1261 return -1;
1265 * mpt_get_product_name - returns product string
1266 * @vendor: pci vendor id
1267 * @device: pci device id
1268 * @revision: pci revision id
1269 * @prod_name: string returned
1271 * Returns product string displayed when driver loads,
1272 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1275 static void
1276 mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1278 char *product_str = NULL;
1280 if (vendor == PCI_VENDOR_ID_BROCADE) {
1281 switch (device)
1283 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1284 switch (revision)
1286 case 0x00:
1287 product_str = "BRE040 A0";
1288 break;
1289 case 0x01:
1290 product_str = "BRE040 A1";
1291 break;
1292 default:
1293 product_str = "BRE040";
1294 break;
1296 break;
1298 goto out;
1301 switch (device)
1303 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1304 product_str = "LSIFC909 B1";
1305 break;
1306 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1307 product_str = "LSIFC919 B0";
1308 break;
1309 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1310 product_str = "LSIFC929 B0";
1311 break;
1312 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1313 if (revision < 0x80)
1314 product_str = "LSIFC919X A0";
1315 else
1316 product_str = "LSIFC919XL A1";
1317 break;
1318 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1319 if (revision < 0x80)
1320 product_str = "LSIFC929X A0";
1321 else
1322 product_str = "LSIFC929XL A1";
1323 break;
1324 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1325 product_str = "LSIFC939X A1";
1326 break;
1327 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1328 product_str = "LSIFC949X A1";
1329 break;
1330 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1331 switch (revision)
1333 case 0x00:
1334 product_str = "LSIFC949E A0";
1335 break;
1336 case 0x01:
1337 product_str = "LSIFC949E A1";
1338 break;
1339 default:
1340 product_str = "LSIFC949E";
1341 break;
1343 break;
1344 case MPI_MANUFACTPAGE_DEVID_53C1030:
1345 switch (revision)
1347 case 0x00:
1348 product_str = "LSI53C1030 A0";
1349 break;
1350 case 0x01:
1351 product_str = "LSI53C1030 B0";
1352 break;
1353 case 0x03:
1354 product_str = "LSI53C1030 B1";
1355 break;
1356 case 0x07:
1357 product_str = "LSI53C1030 B2";
1358 break;
1359 case 0x08:
1360 product_str = "LSI53C1030 C0";
1361 break;
1362 case 0x80:
1363 product_str = "LSI53C1030T A0";
1364 break;
1365 case 0x83:
1366 product_str = "LSI53C1030T A2";
1367 break;
1368 case 0x87:
1369 product_str = "LSI53C1030T A3";
1370 break;
1371 case 0xc1:
1372 product_str = "LSI53C1020A A1";
1373 break;
1374 default:
1375 product_str = "LSI53C1030";
1376 break;
1378 break;
1379 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1380 switch (revision)
1382 case 0x03:
1383 product_str = "LSI53C1035 A2";
1384 break;
1385 case 0x04:
1386 product_str = "LSI53C1035 B0";
1387 break;
1388 default:
1389 product_str = "LSI53C1035";
1390 break;
1392 break;
1393 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1394 switch (revision)
1396 case 0x00:
1397 product_str = "LSISAS1064 A1";
1398 break;
1399 case 0x01:
1400 product_str = "LSISAS1064 A2";
1401 break;
1402 case 0x02:
1403 product_str = "LSISAS1064 A3";
1404 break;
1405 case 0x03:
1406 product_str = "LSISAS1064 A4";
1407 break;
1408 default:
1409 product_str = "LSISAS1064";
1410 break;
1412 break;
1413 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1414 switch (revision)
1416 case 0x00:
1417 product_str = "LSISAS1064E A0";
1418 break;
1419 case 0x01:
1420 product_str = "LSISAS1064E B0";
1421 break;
1422 case 0x02:
1423 product_str = "LSISAS1064E B1";
1424 break;
1425 case 0x04:
1426 product_str = "LSISAS1064E B2";
1427 break;
1428 case 0x08:
1429 product_str = "LSISAS1064E B3";
1430 break;
1431 default:
1432 product_str = "LSISAS1064E";
1433 break;
1435 break;
1436 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1437 switch (revision)
1439 case 0x00:
1440 product_str = "LSISAS1068 A0";
1441 break;
1442 case 0x01:
1443 product_str = "LSISAS1068 B0";
1444 break;
1445 case 0x02:
1446 product_str = "LSISAS1068 B1";
1447 break;
1448 default:
1449 product_str = "LSISAS1068";
1450 break;
1452 break;
1453 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1454 switch (revision)
1456 case 0x00:
1457 product_str = "LSISAS1068E A0";
1458 break;
1459 case 0x01:
1460 product_str = "LSISAS1068E B0";
1461 break;
1462 case 0x02:
1463 product_str = "LSISAS1068E B1";
1464 break;
1465 case 0x04:
1466 product_str = "LSISAS1068E B2";
1467 break;
1468 case 0x08:
1469 product_str = "LSISAS1068E B3";
1470 break;
1471 default:
1472 product_str = "LSISAS1068E";
1473 break;
1475 break;
1476 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1477 switch (revision)
1479 case 0x00:
1480 product_str = "LSISAS1078 A0";
1481 break;
1482 case 0x01:
1483 product_str = "LSISAS1078 B0";
1484 break;
1485 case 0x02:
1486 product_str = "LSISAS1078 C0";
1487 break;
1488 case 0x03:
1489 product_str = "LSISAS1078 C1";
1490 break;
1491 case 0x04:
1492 product_str = "LSISAS1078 C2";
1493 break;
1494 default:
1495 product_str = "LSISAS1078";
1496 break;
1498 break;
1501 out:
1502 if (product_str)
1503 sprintf(prod_name, "%s", product_str);
1507 * mpt_mapresources - map in memory mapped io
1508 * @ioc: Pointer to pointer to IOC adapter
1511 static int
1512 mpt_mapresources(MPT_ADAPTER *ioc)
1514 u8 __iomem *mem;
1515 int ii;
1516 unsigned long mem_phys;
1517 unsigned long port;
1518 u32 msize;
1519 u32 psize;
1520 u8 revision;
1521 int r = -ENODEV;
1522 struct pci_dev *pdev;
1524 pdev = ioc->pcidev;
1525 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1526 if (pci_enable_device_mem(pdev)) {
1527 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1528 "failed\n", ioc->name);
1529 return r;
1531 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1532 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1533 "MEM failed\n", ioc->name);
1534 return r;
1537 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1539 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
1540 && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
1541 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1542 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1543 ioc->name));
1544 } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
1545 && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
1546 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1547 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1548 ioc->name));
1549 } else {
1550 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1551 ioc->name, pci_name(pdev));
1552 pci_release_selected_regions(pdev, ioc->bars);
1553 return r;
1556 mem_phys = msize = 0;
1557 port = psize = 0;
1558 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1559 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1560 if (psize)
1561 continue;
1562 /* Get I/O space! */
1563 port = pci_resource_start(pdev, ii);
1564 psize = pci_resource_len(pdev, ii);
1565 } else {
1566 if (msize)
1567 continue;
1568 /* Get memmap */
1569 mem_phys = pci_resource_start(pdev, ii);
1570 msize = pci_resource_len(pdev, ii);
1573 ioc->mem_size = msize;
1575 mem = NULL;
1576 /* Get logical ptr for PciMem0 space */
1577 /*mem = ioremap(mem_phys, msize);*/
1578 mem = ioremap(mem_phys, msize);
1579 if (mem == NULL) {
1580 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1581 " memory!\n", ioc->name);
1582 return -EINVAL;
1584 ioc->memmap = mem;
1585 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
1586 ioc->name, mem, mem_phys));
1588 ioc->mem_phys = mem_phys;
1589 ioc->chip = (SYSIF_REGS __iomem *)mem;
1591 /* Save Port IO values in case we need to do downloadboot */
1592 ioc->pio_mem_phys = port;
1593 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1595 return 0;
1598 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1600 * mpt_attach - Install a PCI intelligent MPT adapter.
1601 * @pdev: Pointer to pci_dev structure
1602 * @id: PCI device ID information
1604 * This routine performs all the steps necessary to bring the IOC of
1605 * a MPT adapter to a OPERATIONAL state. This includes registering
1606 * memory regions, registering the interrupt, and allocating request
1607 * and reply memory pools.
1609 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1610 * MPT adapter.
1612 * Returns 0 for success, non-zero for failure.
1614 * TODO: Add support for polled controllers
1617 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1619 MPT_ADAPTER *ioc;
1620 u8 cb_idx;
1621 int r = -ENODEV;
1622 u8 revision;
1623 u8 pcixcmd;
1624 static int mpt_ids = 0;
1625 #ifdef CONFIG_PROC_FS
1626 struct proc_dir_entry *dent, *ent;
1627 #endif
1629 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1630 if (ioc == NULL) {
1631 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1632 return -ENOMEM;
1635 ioc->id = mpt_ids++;
1636 sprintf(ioc->name, "ioc%d", ioc->id);
1639 * set initial debug level
1640 * (refer to mptdebug.h)
1643 ioc->debug_level = mpt_debug_level;
1644 if (mpt_debug_level)
1645 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1647 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1649 ioc->pcidev = pdev;
1650 if (mpt_mapresources(ioc)) {
1651 kfree(ioc);
1652 return r;
1655 ioc->alloc_total = sizeof(MPT_ADAPTER);
1656 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1657 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1659 ioc->pcidev = pdev;
1660 ioc->diagPending = 0;
1661 spin_lock_init(&ioc->diagLock);
1662 spin_lock_init(&ioc->initializing_hba_lock);
1664 /* Initialize the event logging.
1666 ioc->eventTypes = 0; /* None */
1667 ioc->eventContext = 0;
1668 ioc->eventLogSize = 0;
1669 ioc->events = NULL;
1671 #ifdef MFCNT
1672 ioc->mfcnt = 0;
1673 #endif
1675 ioc->cached_fw = NULL;
1677 /* Initilize SCSI Config Data structure
1679 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1681 /* Initialize the running configQ head.
1683 INIT_LIST_HEAD(&ioc->configQ);
1685 /* Initialize the fc rport list head.
1687 INIT_LIST_HEAD(&ioc->fc_rports);
1689 /* Find lookup slot. */
1690 INIT_LIST_HEAD(&ioc->list);
1693 /* Initialize workqueue */
1694 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1695 spin_lock_init(&ioc->fault_reset_work_lock);
1697 snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
1698 "mpt_poll_%d", ioc->id);
1699 ioc->reset_work_q =
1700 create_singlethread_workqueue(ioc->reset_work_q_name);
1701 if (!ioc->reset_work_q) {
1702 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1703 ioc->name);
1704 pci_release_selected_regions(pdev, ioc->bars);
1705 kfree(ioc);
1706 return -ENOMEM;
1709 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1710 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1712 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1713 mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1715 switch (pdev->device)
1717 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1718 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1719 ioc->errata_flag_1064 = 1;
1720 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1721 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1722 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1723 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1724 ioc->bus_type = FC;
1725 break;
1727 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1728 if (revision < XL_929) {
1729 /* 929X Chip Fix. Set Split transactions level
1730 * for PCIX. Set MOST bits to zero.
1732 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1733 pcixcmd &= 0x8F;
1734 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1735 } else {
1736 /* 929XL Chip Fix. Set MMRBC to 0x08.
1738 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1739 pcixcmd |= 0x08;
1740 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1742 ioc->bus_type = FC;
1743 break;
1745 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1746 /* 919X Chip Fix. Set Split transactions level
1747 * for PCIX. Set MOST bits to zero.
1749 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1750 pcixcmd &= 0x8F;
1751 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1752 ioc->bus_type = FC;
1753 break;
1755 case MPI_MANUFACTPAGE_DEVID_53C1030:
1756 /* 1030 Chip Fix. Disable Split transactions
1757 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1759 if (revision < C0_1030) {
1760 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1761 pcixcmd &= 0x8F;
1762 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1765 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1766 ioc->bus_type = SPI;
1767 break;
1769 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1770 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1771 ioc->errata_flag_1064 = 1;
1773 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1774 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1775 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1776 ioc->bus_type = SAS;
1780 switch (ioc->bus_type) {
1782 case SAS:
1783 ioc->msi_enable = mpt_msi_enable_sas;
1784 break;
1786 case SPI:
1787 ioc->msi_enable = mpt_msi_enable_spi;
1788 break;
1790 case FC:
1791 ioc->msi_enable = mpt_msi_enable_fc;
1792 break;
1794 default:
1795 ioc->msi_enable = 0;
1796 break;
1798 if (ioc->errata_flag_1064)
1799 pci_disable_io_access(pdev);
1801 spin_lock_init(&ioc->FreeQlock);
1803 /* Disable all! */
1804 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1805 ioc->active = 0;
1806 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1808 /* Set IOC ptr in the pcidev's driver data. */
1809 pci_set_drvdata(ioc->pcidev, ioc);
1811 /* Set lookup ptr. */
1812 list_add_tail(&ioc->list, &ioc_list);
1814 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1816 mpt_detect_bound_ports(ioc, pdev);
1818 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1819 CAN_SLEEP)) != 0){
1820 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1821 ioc->name, r);
1823 list_del(&ioc->list);
1824 if (ioc->alt_ioc)
1825 ioc->alt_ioc->alt_ioc = NULL;
1826 iounmap(ioc->memmap);
1827 if (r != -5)
1828 pci_release_selected_regions(pdev, ioc->bars);
1830 destroy_workqueue(ioc->reset_work_q);
1831 ioc->reset_work_q = NULL;
1833 kfree(ioc);
1834 pci_set_drvdata(pdev, NULL);
1835 return r;
1838 /* call per device driver probe entry point */
1839 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1840 if(MptDeviceDriverHandlers[cb_idx] &&
1841 MptDeviceDriverHandlers[cb_idx]->probe) {
1842 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1846 #ifdef CONFIG_PROC_FS
1848 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1850 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1851 if (dent) {
1852 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1853 if (ent) {
1854 ent->read_proc = procmpt_iocinfo_read;
1855 ent->data = ioc;
1857 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1858 if (ent) {
1859 ent->read_proc = procmpt_summary_read;
1860 ent->data = ioc;
1863 #endif
1865 if (!ioc->alt_ioc)
1866 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1867 msecs_to_jiffies(MPT_POLLING_INTERVAL));
1869 return 0;
1872 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1874 * mpt_detach - Remove a PCI intelligent MPT adapter.
1875 * @pdev: Pointer to pci_dev structure
1878 void
1879 mpt_detach(struct pci_dev *pdev)
1881 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1882 char pname[32];
1883 u8 cb_idx;
1884 unsigned long flags;
1885 struct workqueue_struct *wq;
1888 * Stop polling ioc for fault condition
1890 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
1891 wq = ioc->reset_work_q;
1892 ioc->reset_work_q = NULL;
1893 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
1894 cancel_delayed_work(&ioc->fault_reset_work);
1895 destroy_workqueue(wq);
1898 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1899 remove_proc_entry(pname, NULL);
1900 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1901 remove_proc_entry(pname, NULL);
1902 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1903 remove_proc_entry(pname, NULL);
1905 /* call per device driver remove entry point */
1906 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1907 if(MptDeviceDriverHandlers[cb_idx] &&
1908 MptDeviceDriverHandlers[cb_idx]->remove) {
1909 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
1913 /* Disable interrupts! */
1914 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1916 ioc->active = 0;
1917 synchronize_irq(pdev->irq);
1919 /* Clear any lingering interrupt */
1920 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1922 CHIPREG_READ32(&ioc->chip->IntStatus);
1924 mpt_adapter_dispose(ioc);
1926 pci_set_drvdata(pdev, NULL);
1929 /**************************************************************************
1930 * Power Management
1932 #ifdef CONFIG_PM
1933 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1935 * mpt_suspend - Fusion MPT base driver suspend routine.
1936 * @pdev: Pointer to pci_dev structure
1937 * @state: new state to enter
1940 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1942 u32 device_state;
1943 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1945 device_state = pci_choose_state(pdev, state);
1946 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
1947 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1948 device_state);
1950 /* put ioc into READY_STATE */
1951 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1952 printk(MYIOC_s_ERR_FMT
1953 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1956 /* disable interrupts */
1957 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1958 ioc->active = 0;
1960 /* Clear any lingering interrupt */
1961 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1963 free_irq(ioc->pci_irq, ioc);
1964 if (ioc->msi_enable)
1965 pci_disable_msi(ioc->pcidev);
1966 ioc->pci_irq = -1;
1967 pci_save_state(pdev);
1968 pci_disable_device(pdev);
1969 pci_release_selected_regions(pdev, ioc->bars);
1970 pci_set_power_state(pdev, device_state);
1971 return 0;
1974 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1976 * mpt_resume - Fusion MPT base driver resume routine.
1977 * @pdev: Pointer to pci_dev structure
1980 mpt_resume(struct pci_dev *pdev)
1982 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1983 u32 device_state = pdev->current_state;
1984 int recovery_state;
1985 int err;
1987 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
1988 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1989 device_state);
1991 pci_set_power_state(pdev, PCI_D0);
1992 pci_enable_wake(pdev, PCI_D0, 0);
1993 pci_restore_state(pdev);
1994 ioc->pcidev = pdev;
1995 err = mpt_mapresources(ioc);
1996 if (err)
1997 return err;
1999 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
2000 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
2001 CHIPREG_READ32(&ioc->chip->Doorbell));
2004 * Errata workaround for SAS pci express:
2005 * Upon returning to the D0 state, the contents of the doorbell will be
2006 * stale data, and this will incorrectly signal to the host driver that
2007 * the firmware is ready to process mpt commands. The workaround is
2008 * to issue a diagnostic reset.
2010 if (ioc->bus_type == SAS && (pdev->device ==
2011 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2012 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2013 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2014 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2015 ioc->name);
2016 goto out;
2020 /* bring ioc to operational state */
2021 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2022 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2023 CAN_SLEEP);
2024 if (recovery_state != 0)
2025 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2026 "error:[%x]\n", ioc->name, recovery_state);
2027 else
2028 printk(MYIOC_s_INFO_FMT
2029 "pci-resume: success\n", ioc->name);
2030 out:
2031 return 0;
2034 #endif
2036 static int
2037 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2039 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2040 ioc->bus_type != SPI) ||
2041 (MptDriverClass[index] == MPTFC_DRIVER &&
2042 ioc->bus_type != FC) ||
2043 (MptDriverClass[index] == MPTSAS_DRIVER &&
2044 ioc->bus_type != SAS))
2045 /* make sure we only call the relevant reset handler
2046 * for the bus */
2047 return 0;
2048 return (MptResetHandlers[index])(ioc, reset_phase);
2051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2053 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2054 * @ioc: Pointer to MPT adapter structure
2055 * @reason: Event word / reason
2056 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2058 * This routine performs all the steps necessary to bring the IOC
2059 * to a OPERATIONAL state.
2061 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2062 * MPT adapter.
2064 * Returns:
2065 * 0 for success
2066 * -1 if failed to get board READY
2067 * -2 if READY but IOCFacts Failed
2068 * -3 if READY but PrimeIOCFifos Failed
2069 * -4 if READY but IOCInit Failed
2070 * -5 if failed to enable_device and/or request_selected_regions
2071 * -6 if failed to upload firmware
2073 static int
2074 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2076 int hard_reset_done = 0;
2077 int alt_ioc_ready = 0;
2078 int hard;
2079 int rc=0;
2080 int ii;
2081 u8 cb_idx;
2082 int handlers;
2083 int ret = 0;
2084 int reset_alt_ioc_active = 0;
2085 int irq_allocated = 0;
2086 u8 *a;
2088 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2089 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2091 /* Disable reply interrupts (also blocks FreeQ) */
2092 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2093 ioc->active = 0;
2095 if (ioc->alt_ioc) {
2096 if (ioc->alt_ioc->active)
2097 reset_alt_ioc_active = 1;
2099 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
2100 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
2101 ioc->alt_ioc->active = 0;
2104 hard = 1;
2105 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2106 hard = 0;
2108 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2109 if (hard_reset_done == -4) {
2110 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2111 ioc->name);
2113 if (reset_alt_ioc_active && ioc->alt_ioc) {
2114 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2115 dprintk(ioc, printk(MYIOC_s_INFO_FMT
2116 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2117 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2118 ioc->alt_ioc->active = 1;
2121 } else {
2122 printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
2124 return -1;
2127 /* hard_reset_done = 0 if a soft reset was performed
2128 * and 1 if a hard reset was performed.
2130 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2131 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2132 alt_ioc_ready = 1;
2133 else
2134 printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
2137 for (ii=0; ii<5; ii++) {
2138 /* Get IOC facts! Allow 5 retries */
2139 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2140 break;
2144 if (ii == 5) {
2145 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2146 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2147 ret = -2;
2148 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2149 MptDisplayIocCapabilities(ioc);
2152 if (alt_ioc_ready) {
2153 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2154 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2155 "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
2156 /* Retry - alt IOC was initialized once
2158 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2160 if (rc) {
2161 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2162 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2163 alt_ioc_ready = 0;
2164 reset_alt_ioc_active = 0;
2165 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2166 MptDisplayIocCapabilities(ioc->alt_ioc);
2170 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2171 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2172 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2173 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2174 IORESOURCE_IO);
2175 if (pci_enable_device(ioc->pcidev))
2176 return -5;
2177 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2178 "mpt"))
2179 return -5;
2183 * Device is reset now. It must have de-asserted the interrupt line
2184 * (if it was asserted) and it should be safe to register for the
2185 * interrupt now.
2187 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2188 ioc->pci_irq = -1;
2189 if (ioc->pcidev->irq) {
2190 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2191 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2192 ioc->name);
2193 else
2194 ioc->msi_enable = 0;
2195 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2196 IRQF_SHARED, ioc->name, ioc);
2197 if (rc < 0) {
2198 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2199 "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
2200 if (ioc->msi_enable)
2201 pci_disable_msi(ioc->pcidev);
2202 return -EBUSY;
2204 irq_allocated = 1;
2205 ioc->pci_irq = ioc->pcidev->irq;
2206 pci_set_master(ioc->pcidev); /* ?? */
2207 dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
2208 "%d\n", ioc->name, ioc->pcidev->irq));
2212 /* Prime reply & request queues!
2213 * (mucho alloc's) Must be done prior to
2214 * init as upper addresses are needed for init.
2215 * If fails, continue with alt-ioc processing
2217 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2218 ret = -3;
2220 /* May need to check/upload firmware & data here!
2221 * If fails, continue with alt-ioc processing
2223 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2224 ret = -4;
2225 // NEW!
2226 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2227 printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
2228 ioc->alt_ioc->name, rc);
2229 alt_ioc_ready = 0;
2230 reset_alt_ioc_active = 0;
2233 if (alt_ioc_ready) {
2234 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2235 alt_ioc_ready = 0;
2236 reset_alt_ioc_active = 0;
2237 printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
2238 ioc->alt_ioc->name, rc);
2242 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2243 if (ioc->upload_fw) {
2244 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2245 "firmware upload required!\n", ioc->name));
2247 /* Controller is not operational, cannot do upload
2249 if (ret == 0) {
2250 rc = mpt_do_upload(ioc, sleepFlag);
2251 if (rc == 0) {
2252 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2254 * Maintain only one pointer to FW memory
2255 * so there will not be two attempt to
2256 * downloadboot onboard dual function
2257 * chips (mpt_adapter_disable,
2258 * mpt_diag_reset)
2260 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2261 "mpt_upload: alt_%s has cached_fw=%p \n",
2262 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2263 ioc->cached_fw = NULL;
2265 } else {
2266 printk(MYIOC_s_WARN_FMT
2267 "firmware upload failure!\n", ioc->name);
2268 ret = -6;
2274 if (ret == 0) {
2275 /* Enable! (reply interrupt) */
2276 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2277 ioc->active = 1;
2280 if (reset_alt_ioc_active && ioc->alt_ioc) {
2281 /* (re)Enable alt-IOC! (reply interrupt) */
2282 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
2283 ioc->alt_ioc->name));
2284 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2285 ioc->alt_ioc->active = 1;
2288 /* Enable MPT base driver management of EventNotification
2289 * and EventAck handling.
2291 if ((ret == 0) && (!ioc->facts.EventState))
2292 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
2294 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2295 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
2297 /* Add additional "reason" check before call to GetLanConfigPages
2298 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2299 * recursive scenario; GetLanConfigPages times out, timer expired
2300 * routine calls HardResetHandler, which calls into here again,
2301 * and we try GetLanConfigPages again...
2303 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2306 * Initalize link list for inactive raid volumes.
2308 mutex_init(&ioc->raid_data.inactive_list_mutex);
2309 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2311 if (ioc->bus_type == SAS) {
2313 /* clear persistency table */
2314 if(ioc->facts.IOCExceptions &
2315 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2316 ret = mptbase_sas_persist_operation(ioc,
2317 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2318 if(ret != 0)
2319 goto out;
2322 /* Find IM volumes
2324 mpt_findImVolumes(ioc);
2326 } else if (ioc->bus_type == FC) {
2327 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
2328 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2330 * Pre-fetch the ports LAN MAC address!
2331 * (LANPage1_t stuff)
2333 (void) GetLanConfigPages(ioc);
2334 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2335 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2336 "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2337 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
2340 } else {
2341 /* Get NVRAM and adapter maximums from SPP 0 and 2
2343 mpt_GetScsiPortSettings(ioc, 0);
2345 /* Get version and length of SDP 1
2347 mpt_readScsiDevicePageHeaders(ioc, 0);
2349 /* Find IM volumes
2351 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2352 mpt_findImVolumes(ioc);
2354 /* Check, and possibly reset, the coalescing value
2356 mpt_read_ioc_pg_1(ioc);
2358 mpt_read_ioc_pg_4(ioc);
2361 GetIoUnitPage2(ioc);
2362 mpt_get_manufacturing_pg_0(ioc);
2366 * Call each currently registered protocol IOC reset handler
2367 * with post-reset indication.
2368 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2369 * MptResetHandlers[] registered yet.
2371 if (hard_reset_done) {
2372 rc = handlers = 0;
2373 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2374 if ((ret == 0) && MptResetHandlers[cb_idx]) {
2375 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2376 "Calling IOC post_reset handler #%d\n",
2377 ioc->name, cb_idx));
2378 rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2379 handlers++;
2382 if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2383 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2384 "Calling IOC post_reset handler #%d\n",
2385 ioc->alt_ioc->name, cb_idx));
2386 rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2387 handlers++;
2390 /* FIXME? Examine results here? */
2393 out:
2394 if ((ret != 0) && irq_allocated) {
2395 free_irq(ioc->pci_irq, ioc);
2396 if (ioc->msi_enable)
2397 pci_disable_msi(ioc->pcidev);
2399 return ret;
2402 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2404 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2405 * @ioc: Pointer to MPT adapter structure
2406 * @pdev: Pointer to (struct pci_dev) structure
2408 * Search for PCI bus/dev_function which matches
2409 * PCI bus/dev_function (+/-1) for newly discovered 929,
2410 * 929X, 1030 or 1035.
2412 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2413 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2415 static void
2416 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2418 struct pci_dev *peer=NULL;
2419 unsigned int slot = PCI_SLOT(pdev->devfn);
2420 unsigned int func = PCI_FUNC(pdev->devfn);
2421 MPT_ADAPTER *ioc_srch;
2423 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2424 " searching for devfn match on %x or %x\n",
2425 ioc->name, pci_name(pdev), pdev->bus->number,
2426 pdev->devfn, func-1, func+1));
2428 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2429 if (!peer) {
2430 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2431 if (!peer)
2432 return;
2435 list_for_each_entry(ioc_srch, &ioc_list, list) {
2436 struct pci_dev *_pcidev = ioc_srch->pcidev;
2437 if (_pcidev == peer) {
2438 /* Paranoia checks */
2439 if (ioc->alt_ioc != NULL) {
2440 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2441 ioc->name, ioc->alt_ioc->name);
2442 break;
2443 } else if (ioc_srch->alt_ioc != NULL) {
2444 printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2445 ioc_srch->name, ioc_srch->alt_ioc->name);
2446 break;
2448 dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
2449 ioc->name, ioc_srch->name));
2450 ioc_srch->alt_ioc = ioc;
2451 ioc->alt_ioc = ioc_srch;
2454 pci_dev_put(peer);
2457 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2459 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2460 * @ioc: Pointer to MPT adapter structure
2462 static void
2463 mpt_adapter_disable(MPT_ADAPTER *ioc)
2465 int sz;
2466 int ret;
2468 if (ioc->cached_fw != NULL) {
2469 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2470 "adapter\n", __func__, ioc->name));
2471 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2472 ioc->cached_fw, CAN_SLEEP)) < 0) {
2473 printk(MYIOC_s_WARN_FMT
2474 ": firmware downloadboot failure (%d)!\n",
2475 ioc->name, ret);
2479 /* Disable adapter interrupts! */
2480 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2481 ioc->active = 0;
2482 /* Clear any lingering interrupt */
2483 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2485 if (ioc->alloc != NULL) {
2486 sz = ioc->alloc_sz;
2487 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2488 ioc->name, ioc->alloc, ioc->alloc_sz));
2489 pci_free_consistent(ioc->pcidev, sz,
2490 ioc->alloc, ioc->alloc_dma);
2491 ioc->reply_frames = NULL;
2492 ioc->req_frames = NULL;
2493 ioc->alloc = NULL;
2494 ioc->alloc_total -= sz;
2497 if (ioc->sense_buf_pool != NULL) {
2498 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2499 pci_free_consistent(ioc->pcidev, sz,
2500 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2501 ioc->sense_buf_pool = NULL;
2502 ioc->alloc_total -= sz;
2505 if (ioc->events != NULL){
2506 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2507 kfree(ioc->events);
2508 ioc->events = NULL;
2509 ioc->alloc_total -= sz;
2512 mpt_free_fw_memory(ioc);
2514 kfree(ioc->spi_data.nvram);
2515 mpt_inactive_raid_list_free(ioc);
2516 kfree(ioc->raid_data.pIocPg2);
2517 kfree(ioc->raid_data.pIocPg3);
2518 ioc->spi_data.nvram = NULL;
2519 ioc->raid_data.pIocPg3 = NULL;
2521 if (ioc->spi_data.pIocPg4 != NULL) {
2522 sz = ioc->spi_data.IocPg4Sz;
2523 pci_free_consistent(ioc->pcidev, sz,
2524 ioc->spi_data.pIocPg4,
2525 ioc->spi_data.IocPg4_dma);
2526 ioc->spi_data.pIocPg4 = NULL;
2527 ioc->alloc_total -= sz;
2530 if (ioc->ReqToChain != NULL) {
2531 kfree(ioc->ReqToChain);
2532 kfree(ioc->RequestNB);
2533 ioc->ReqToChain = NULL;
2536 kfree(ioc->ChainToChain);
2537 ioc->ChainToChain = NULL;
2539 if (ioc->HostPageBuffer != NULL) {
2540 if((ret = mpt_host_page_access_control(ioc,
2541 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2542 printk(MYIOC_s_ERR_FMT
2543 "host page buffers free failed (%d)!\n",
2544 ioc->name, ret);
2546 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n",
2547 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2548 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2549 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2550 ioc->HostPageBuffer = NULL;
2551 ioc->HostPageBuffer_sz = 0;
2552 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2556 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2558 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2559 * @ioc: Pointer to MPT adapter structure
2561 * This routine unregisters h/w resources and frees all alloc'd memory
2562 * associated with a MPT adapter structure.
2564 static void
2565 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2567 int sz_first, sz_last;
2569 if (ioc == NULL)
2570 return;
2572 sz_first = ioc->alloc_total;
2574 mpt_adapter_disable(ioc);
2576 if (ioc->pci_irq != -1) {
2577 free_irq(ioc->pci_irq, ioc);
2578 if (ioc->msi_enable)
2579 pci_disable_msi(ioc->pcidev);
2580 ioc->pci_irq = -1;
2583 if (ioc->memmap != NULL) {
2584 iounmap(ioc->memmap);
2585 ioc->memmap = NULL;
2588 pci_disable_device(ioc->pcidev);
2589 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2591 #if defined(CONFIG_MTRR) && 0
2592 if (ioc->mtrr_reg > 0) {
2593 mtrr_del(ioc->mtrr_reg, 0, 0);
2594 dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2596 #endif
2598 /* Zap the adapter lookup ptr! */
2599 list_del(&ioc->list);
2601 sz_last = ioc->alloc_total;
2602 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2603 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2605 if (ioc->alt_ioc)
2606 ioc->alt_ioc->alt_ioc = NULL;
2608 kfree(ioc);
2611 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2613 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2614 * @ioc: Pointer to MPT adapter structure
2616 static void
2617 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2619 int i = 0;
2621 printk(KERN_INFO "%s: ", ioc->name);
2622 if (ioc->prod_name)
2623 printk("%s: ", ioc->prod_name);
2624 printk("Capabilities={");
2626 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2627 printk("Initiator");
2628 i++;
2631 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2632 printk("%sTarget", i ? "," : "");
2633 i++;
2636 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2637 printk("%sLAN", i ? "," : "");
2638 i++;
2641 #if 0
2643 * This would probably evoke more questions than it's worth
2645 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2646 printk("%sLogBusAddr", i ? "," : "");
2647 i++;
2649 #endif
2651 printk("}\n");
2654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2656 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2657 * @ioc: Pointer to MPT_ADAPTER structure
2658 * @force: Force hard KickStart of IOC
2659 * @sleepFlag: Specifies whether the process can sleep
2661 * Returns:
2662 * 1 - DIAG reset and READY
2663 * 0 - READY initially OR soft reset and READY
2664 * -1 - Any failure on KickStart
2665 * -2 - Msg Unit Reset Failed
2666 * -3 - IO Unit Reset Failed
2667 * -4 - IOC owned by a PEER
2669 static int
2670 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2672 u32 ioc_state;
2673 int statefault = 0;
2674 int cntdn;
2675 int hard_reset_done = 0;
2676 int r;
2677 int ii;
2678 int whoinit;
2680 /* Get current [raw] IOC state */
2681 ioc_state = mpt_GetIocState(ioc, 0);
2682 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2685 * Check to see if IOC got left/stuck in doorbell handshake
2686 * grip of death. If so, hard reset the IOC.
2688 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2689 statefault = 1;
2690 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2691 ioc->name);
2694 /* Is it already READY? */
2695 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2696 return 0;
2699 * Check to see if IOC is in FAULT state.
2701 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2702 statefault = 2;
2703 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2704 ioc->name);
2705 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2706 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2710 * Hmmm... Did it get left operational?
2712 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2713 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2714 ioc->name));
2716 /* Check WhoInit.
2717 * If PCI Peer, exit.
2718 * Else, if no fault conditions are present, issue a MessageUnitReset
2719 * Else, fall through to KickStart case
2721 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2722 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2723 "whoinit 0x%x statefault %d force %d\n",
2724 ioc->name, whoinit, statefault, force));
2725 if (whoinit == MPI_WHOINIT_PCI_PEER)
2726 return -4;
2727 else {
2728 if ((statefault == 0 ) && (force == 0)) {
2729 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2730 return 0;
2732 statefault = 3;
2736 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2737 if (hard_reset_done < 0)
2738 return -1;
2741 * Loop here waiting for IOC to come READY.
2743 ii = 0;
2744 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2746 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2747 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2749 * BIOS or previous driver load left IOC in OP state.
2750 * Reset messaging FIFOs.
2752 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2753 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2754 return -2;
2756 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2758 * Something is wrong. Try to get IOC back
2759 * to a known state.
2761 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2762 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2763 return -3;
2767 ii++; cntdn--;
2768 if (!cntdn) {
2769 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2770 ioc->name, (int)((ii+5)/HZ));
2771 return -ETIME;
2774 if (sleepFlag == CAN_SLEEP) {
2775 msleep(1);
2776 } else {
2777 mdelay (1); /* 1 msec delay */
2782 if (statefault < 3) {
2783 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2784 ioc->name,
2785 statefault==1 ? "stuck handshake" : "IOC FAULT");
2788 return hard_reset_done;
2791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2793 * mpt_GetIocState - Get the current state of a MPT adapter.
2794 * @ioc: Pointer to MPT_ADAPTER structure
2795 * @cooked: Request raw or cooked IOC state
2797 * Returns all IOC Doorbell register bits if cooked==0, else just the
2798 * Doorbell bits in MPI_IOC_STATE_MASK.
2801 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2803 u32 s, sc;
2805 /* Get! */
2806 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2807 sc = s & MPI_IOC_STATE_MASK;
2809 /* Save! */
2810 ioc->last_state = sc;
2812 return cooked ? sc : s;
2815 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2817 * GetIocFacts - Send IOCFacts request to MPT adapter.
2818 * @ioc: Pointer to MPT_ADAPTER structure
2819 * @sleepFlag: Specifies whether the process can sleep
2820 * @reason: If recovery, only update facts.
2822 * Returns 0 for success, non-zero for failure.
2824 static int
2825 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2827 IOCFacts_t get_facts;
2828 IOCFactsReply_t *facts;
2829 int r;
2830 int req_sz;
2831 int reply_sz;
2832 int sz;
2833 u32 status, vv;
2834 u8 shiftFactor=1;
2836 /* IOC *must* NOT be in RESET state! */
2837 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2838 printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
2839 ioc->name, ioc->last_state );
2840 return -44;
2843 facts = &ioc->facts;
2845 /* Destination (reply area)... */
2846 reply_sz = sizeof(*facts);
2847 memset(facts, 0, reply_sz);
2849 /* Request area (get_facts on the stack right now!) */
2850 req_sz = sizeof(get_facts);
2851 memset(&get_facts, 0, req_sz);
2853 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2854 /* Assert: All other get_facts fields are zero! */
2856 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2857 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2858 ioc->name, req_sz, reply_sz));
2860 /* No non-zero fields in the get_facts request are greater than
2861 * 1 byte in size, so we can just fire it off as is.
2863 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2864 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2865 if (r != 0)
2866 return r;
2869 * Now byte swap (GRRR) the necessary fields before any further
2870 * inspection of reply contents.
2872 * But need to do some sanity checks on MsgLength (byte) field
2873 * to make sure we don't zero IOC's req_sz!
2875 /* Did we get a valid reply? */
2876 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2877 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2879 * If not been here, done that, save off first WhoInit value
2881 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2882 ioc->FirstWhoInit = facts->WhoInit;
2885 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2886 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2887 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2888 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2889 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2890 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2891 /* CHECKME! IOCStatus, IOCLogInfo */
2893 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2894 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2897 * FC f/w version changed between 1.1 and 1.2
2898 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2899 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2901 if (facts->MsgVersion < 0x0102) {
2903 * Handle old FC f/w style, convert to new...
2905 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2906 facts->FWVersion.Word =
2907 ((oldv<<12) & 0xFF000000) |
2908 ((oldv<<8) & 0x000FFF00);
2909 } else
2910 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2912 facts->ProductID = le16_to_cpu(facts->ProductID);
2913 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2914 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
2915 ioc->ir_firmware = 1;
2916 facts->CurrentHostMfaHighAddr =
2917 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2918 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2919 facts->CurrentSenseBufferHighAddr =
2920 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2921 facts->CurReplyFrameSize =
2922 le16_to_cpu(facts->CurReplyFrameSize);
2923 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2926 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2927 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2928 * to 14 in MPI-1.01.0x.
2930 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2931 facts->MsgVersion > 0x0100) {
2932 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2935 sz = facts->FWImageSize;
2936 if ( sz & 0x01 )
2937 sz += 1;
2938 if ( sz & 0x02 )
2939 sz += 2;
2940 facts->FWImageSize = sz;
2942 if (!facts->RequestFrameSize) {
2943 /* Something is wrong! */
2944 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2945 ioc->name);
2946 return -55;
2949 r = sz = facts->BlockSize;
2950 vv = ((63 / (sz * 4)) + 1) & 0x03;
2951 ioc->NB_for_64_byte_frame = vv;
2952 while ( sz )
2954 shiftFactor++;
2955 sz = sz >> 1;
2957 ioc->NBShiftFactor = shiftFactor;
2958 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2959 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2960 ioc->name, vv, shiftFactor, r));
2962 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2964 * Set values for this IOC's request & reply frame sizes,
2965 * and request & reply queue depths...
2967 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2968 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2969 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2970 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2972 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
2973 ioc->name, ioc->reply_sz, ioc->reply_depth));
2974 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
2975 ioc->name, ioc->req_sz, ioc->req_depth));
2977 /* Get port facts! */
2978 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2979 return r;
2981 } else {
2982 printk(MYIOC_s_ERR_FMT
2983 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2984 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2985 RequestFrameSize)/sizeof(u32)));
2986 return -66;
2989 return 0;
2992 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2994 * GetPortFacts - Send PortFacts request to MPT adapter.
2995 * @ioc: Pointer to MPT_ADAPTER structure
2996 * @portnum: Port number
2997 * @sleepFlag: Specifies whether the process can sleep
2999 * Returns 0 for success, non-zero for failure.
3001 static int
3002 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3004 PortFacts_t get_pfacts;
3005 PortFactsReply_t *pfacts;
3006 int ii;
3007 int req_sz;
3008 int reply_sz;
3009 int max_id;
3011 /* IOC *must* NOT be in RESET state! */
3012 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3013 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3014 ioc->name, ioc->last_state );
3015 return -4;
3018 pfacts = &ioc->pfacts[portnum];
3020 /* Destination (reply area)... */
3021 reply_sz = sizeof(*pfacts);
3022 memset(pfacts, 0, reply_sz);
3024 /* Request area (get_pfacts on the stack right now!) */
3025 req_sz = sizeof(get_pfacts);
3026 memset(&get_pfacts, 0, req_sz);
3028 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3029 get_pfacts.PortNumber = portnum;
3030 /* Assert: All other get_pfacts fields are zero! */
3032 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3033 ioc->name, portnum));
3035 /* No non-zero fields in the get_pfacts request are greater than
3036 * 1 byte in size, so we can just fire it off as is.
3038 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3039 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3040 if (ii != 0)
3041 return ii;
3043 /* Did we get a valid reply? */
3045 /* Now byte swap the necessary fields in the response. */
3046 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3047 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3048 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3049 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3050 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3051 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3052 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3053 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3054 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3056 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3057 pfacts->MaxDevices;
3058 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3059 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3062 * Place all the devices on channels
3064 * (for debuging)
3066 if (mpt_channel_mapping) {
3067 ioc->devices_per_bus = 1;
3068 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3071 return 0;
3074 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3076 * SendIocInit - Send IOCInit request to MPT adapter.
3077 * @ioc: Pointer to MPT_ADAPTER structure
3078 * @sleepFlag: Specifies whether the process can sleep
3080 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3082 * Returns 0 for success, non-zero for failure.
3084 static int
3085 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3087 IOCInit_t ioc_init;
3088 MPIDefaultReply_t init_reply;
3089 u32 state;
3090 int r;
3091 int count;
3092 int cntdn;
3094 memset(&ioc_init, 0, sizeof(ioc_init));
3095 memset(&init_reply, 0, sizeof(init_reply));
3097 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3098 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3100 /* If we are in a recovery mode and we uploaded the FW image,
3101 * then this pointer is not NULL. Skip the upload a second time.
3102 * Set this flag if cached_fw set for either IOC.
3104 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3105 ioc->upload_fw = 1;
3106 else
3107 ioc->upload_fw = 0;
3108 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3109 ioc->name, ioc->upload_fw, ioc->facts.Flags));
3111 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3112 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3113 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3114 ioc->name, ioc->facts.MsgVersion));
3115 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3116 // set MsgVersion and HeaderVersion host driver was built with
3117 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3118 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3120 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3121 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3122 } else if(mpt_host_page_alloc(ioc, &ioc_init))
3123 return -99;
3125 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3127 if (sizeof(dma_addr_t) == sizeof(u64)) {
3128 /* Save the upper 32-bits of the request
3129 * (reply) and sense buffers.
3131 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3132 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3133 } else {
3134 /* Force 32-bit addressing */
3135 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3136 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3139 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3140 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3141 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3142 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3144 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3145 ioc->name, &ioc_init));
3147 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3148 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3149 if (r != 0) {
3150 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3151 return r;
3154 /* No need to byte swap the multibyte fields in the reply
3155 * since we don't even look at its contents.
3158 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3159 ioc->name, &ioc_init));
3161 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3162 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3163 return r;
3166 /* YIKES! SUPER IMPORTANT!!!
3167 * Poll IocState until _OPERATIONAL while IOC is doing
3168 * LoopInit and TargetDiscovery!
3170 count = 0;
3171 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3172 state = mpt_GetIocState(ioc, 1);
3173 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3174 if (sleepFlag == CAN_SLEEP) {
3175 msleep(1);
3176 } else {
3177 mdelay(1);
3180 if (!cntdn) {
3181 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3182 ioc->name, (int)((count+5)/HZ));
3183 return -9;
3186 state = mpt_GetIocState(ioc, 1);
3187 count++;
3189 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3190 ioc->name, count));
3192 ioc->aen_event_read_flag=0;
3193 return r;
3196 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3198 * SendPortEnable - Send PortEnable request to MPT adapter port.
3199 * @ioc: Pointer to MPT_ADAPTER structure
3200 * @portnum: Port number to enable
3201 * @sleepFlag: Specifies whether the process can sleep
3203 * Send PortEnable to bring IOC to OPERATIONAL state.
3205 * Returns 0 for success, non-zero for failure.
3207 static int
3208 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3210 PortEnable_t port_enable;
3211 MPIDefaultReply_t reply_buf;
3212 int rc;
3213 int req_sz;
3214 int reply_sz;
3216 /* Destination... */
3217 reply_sz = sizeof(MPIDefaultReply_t);
3218 memset(&reply_buf, 0, reply_sz);
3220 req_sz = sizeof(PortEnable_t);
3221 memset(&port_enable, 0, req_sz);
3223 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3224 port_enable.PortNumber = portnum;
3225 /* port_enable.ChainOffset = 0; */
3226 /* port_enable.MsgFlags = 0; */
3227 /* port_enable.MsgContext = 0; */
3229 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3230 ioc->name, portnum, &port_enable));
3232 /* RAID FW may take a long time to enable
3234 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3235 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3236 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3237 300 /*seconds*/, sleepFlag);
3238 } else {
3239 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3240 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3241 30 /*seconds*/, sleepFlag);
3243 return rc;
3247 * mpt_alloc_fw_memory - allocate firmware memory
3248 * @ioc: Pointer to MPT_ADAPTER structure
3249 * @size: total FW bytes
3251 * If memory has already been allocated, the same (cached) value
3252 * is returned.
3254 * Return 0 if successfull, or non-zero for failure
3257 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3259 int rc;
3261 if (ioc->cached_fw) {
3262 rc = 0; /* use already allocated memory */
3263 goto out;
3265 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3266 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3267 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3268 rc = 0;
3269 goto out;
3271 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3272 if (!ioc->cached_fw) {
3273 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3274 ioc->name);
3275 rc = -1;
3276 } else {
3277 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3278 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3279 ioc->alloc_total += size;
3280 rc = 0;
3282 out:
3283 return rc;
3287 * mpt_free_fw_memory - free firmware memory
3288 * @ioc: Pointer to MPT_ADAPTER structure
3290 * If alt_img is NULL, delete from ioc structure.
3291 * Else, delete a secondary image in same format.
3293 void
3294 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3296 int sz;
3298 if (!ioc->cached_fw)
3299 return;
3301 sz = ioc->facts.FWImageSize;
3302 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3303 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3304 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3305 ioc->alloc_total -= sz;
3306 ioc->cached_fw = NULL;
3309 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3311 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3312 * @ioc: Pointer to MPT_ADAPTER structure
3313 * @sleepFlag: Specifies whether the process can sleep
3315 * Returns 0 for success, >0 for handshake failure
3316 * <0 for fw upload failure.
3318 * Remark: If bound IOC and a successful FWUpload was performed
3319 * on the bound IOC, the second image is discarded
3320 * and memory is free'd. Both channels must upload to prevent
3321 * IOC from running in degraded mode.
3323 static int
3324 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3326 u8 reply[sizeof(FWUploadReply_t)];
3327 FWUpload_t *prequest;
3328 FWUploadReply_t *preply;
3329 FWUploadTCSGE_t *ptcsge;
3330 int sgeoffset;
3331 u32 flagsLength;
3332 int ii, sz, reply_sz;
3333 int cmdStatus;
3335 /* If the image size is 0, we are done.
3337 if ((sz = ioc->facts.FWImageSize) == 0)
3338 return 0;
3340 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3341 return -ENOMEM;
3343 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3344 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3346 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3347 kzalloc(ioc->req_sz, GFP_KERNEL);
3348 if (!prequest) {
3349 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3350 "while allocating memory \n", ioc->name));
3351 mpt_free_fw_memory(ioc);
3352 return -ENOMEM;
3355 preply = (FWUploadReply_t *)&reply;
3357 reply_sz = sizeof(reply);
3358 memset(preply, 0, reply_sz);
3360 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3361 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3363 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3364 ptcsge->DetailsLength = 12;
3365 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3366 ptcsge->ImageSize = cpu_to_le32(sz);
3367 ptcsge++;
3369 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
3371 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3372 mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3374 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
3375 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3376 ioc->name, prequest, sgeoffset));
3377 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3379 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
3380 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3382 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
3384 cmdStatus = -EFAULT;
3385 if (ii == 0) {
3386 /* Handshake transfer was complete and successful.
3387 * Check the Reply Frame.
3389 int status, transfer_sz;
3390 status = le16_to_cpu(preply->IOCStatus);
3391 if (status == MPI_IOCSTATUS_SUCCESS) {
3392 transfer_sz = le32_to_cpu(preply->ActualImageSize);
3393 if (transfer_sz == sz)
3394 cmdStatus = 0;
3397 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3398 ioc->name, cmdStatus));
3401 if (cmdStatus) {
3403 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
3404 ioc->name));
3405 mpt_free_fw_memory(ioc);
3407 kfree(prequest);
3409 return cmdStatus;
3412 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3414 * mpt_downloadboot - DownloadBoot code
3415 * @ioc: Pointer to MPT_ADAPTER structure
3416 * @pFwHeader: Pointer to firmware header info
3417 * @sleepFlag: Specifies whether the process can sleep
3419 * FwDownloadBoot requires Programmed IO access.
3421 * Returns 0 for success
3422 * -1 FW Image size is 0
3423 * -2 No valid cached_fw Pointer
3424 * <0 for fw upload failure.
3426 static int
3427 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3429 MpiExtImageHeader_t *pExtImage;
3430 u32 fwSize;
3431 u32 diag0val;
3432 int count;
3433 u32 *ptrFw;
3434 u32 diagRwData;
3435 u32 nextImage;
3436 u32 load_addr;
3437 u32 ioc_state=0;
3439 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3440 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3442 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3443 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3444 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3445 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3446 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3447 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3449 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3451 /* wait 1 msec */
3452 if (sleepFlag == CAN_SLEEP) {
3453 msleep(1);
3454 } else {
3455 mdelay (1);
3458 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3459 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3461 for (count = 0; count < 30; count ++) {
3462 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3463 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3464 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3465 ioc->name, count));
3466 break;
3468 /* wait .1 sec */
3469 if (sleepFlag == CAN_SLEEP) {
3470 msleep (100);
3471 } else {
3472 mdelay (100);
3476 if ( count == 30 ) {
3477 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3478 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3479 ioc->name, diag0val));
3480 return -3;
3483 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3484 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3485 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3486 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3487 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3488 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3490 /* Set the DiagRwEn and Disable ARM bits */
3491 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3493 fwSize = (pFwHeader->ImageSize + 3)/4;
3494 ptrFw = (u32 *) pFwHeader;
3496 /* Write the LoadStartAddress to the DiagRw Address Register
3497 * using Programmed IO
3499 if (ioc->errata_flag_1064)
3500 pci_enable_io_access(ioc->pcidev);
3502 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3503 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3504 ioc->name, pFwHeader->LoadStartAddress));
3506 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3507 ioc->name, fwSize*4, ptrFw));
3508 while (fwSize--) {
3509 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3512 nextImage = pFwHeader->NextImageHeaderOffset;
3513 while (nextImage) {
3514 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3516 load_addr = pExtImage->LoadStartAddress;
3518 fwSize = (pExtImage->ImageSize + 3) >> 2;
3519 ptrFw = (u32 *)pExtImage;
3521 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3522 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3523 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3525 while (fwSize--) {
3526 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3528 nextImage = pExtImage->NextImageHeaderOffset;
3531 /* Write the IopResetVectorRegAddr */
3532 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3533 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3535 /* Write the IopResetVectorValue */
3536 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3537 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3539 /* Clear the internal flash bad bit - autoincrementing register,
3540 * so must do two writes.
3542 if (ioc->bus_type == SPI) {
3544 * 1030 and 1035 H/W errata, workaround to access
3545 * the ClearFlashBadSignatureBit
3547 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3548 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3549 diagRwData |= 0x40000000;
3550 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3551 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3553 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3554 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3555 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3556 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3558 /* wait 1 msec */
3559 if (sleepFlag == CAN_SLEEP) {
3560 msleep (1);
3561 } else {
3562 mdelay (1);
3566 if (ioc->errata_flag_1064)
3567 pci_disable_io_access(ioc->pcidev);
3569 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3570 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3571 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3572 ioc->name, diag0val));
3573 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3574 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3575 ioc->name, diag0val));
3576 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3578 /* Write 0xFF to reset the sequencer */
3579 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3581 if (ioc->bus_type == SAS) {
3582 ioc_state = mpt_GetIocState(ioc, 0);
3583 if ( (GetIocFacts(ioc, sleepFlag,
3584 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3585 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3586 ioc->name, ioc_state));
3587 return -EFAULT;
3591 for (count=0; count<HZ*20; count++) {
3592 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3593 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3594 "downloadboot successful! (count=%d) IocState=%x\n",
3595 ioc->name, count, ioc_state));
3596 if (ioc->bus_type == SAS) {
3597 return 0;
3599 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3600 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3601 "downloadboot: SendIocInit failed\n",
3602 ioc->name));
3603 return -EFAULT;
3605 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3606 "downloadboot: SendIocInit successful\n",
3607 ioc->name));
3608 return 0;
3610 if (sleepFlag == CAN_SLEEP) {
3611 msleep (10);
3612 } else {
3613 mdelay (10);
3616 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3617 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3618 return -EFAULT;
3621 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3623 * KickStart - Perform hard reset of MPT adapter.
3624 * @ioc: Pointer to MPT_ADAPTER structure
3625 * @force: Force hard reset
3626 * @sleepFlag: Specifies whether the process can sleep
3628 * This routine places MPT adapter in diagnostic mode via the
3629 * WriteSequence register, and then performs a hard reset of adapter
3630 * via the Diagnostic register.
3632 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3633 * or NO_SLEEP (interrupt thread, use mdelay)
3634 * force - 1 if doorbell active, board fault state
3635 * board operational, IOC_RECOVERY or
3636 * IOC_BRINGUP and there is an alt_ioc.
3637 * 0 else
3639 * Returns:
3640 * 1 - hard reset, READY
3641 * 0 - no reset due to History bit, READY
3642 * -1 - no reset due to History bit but not READY
3643 * OR reset but failed to come READY
3644 * -2 - no reset, could not enter DIAG mode
3645 * -3 - reset but bad FW bit
3647 static int
3648 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3650 int hard_reset_done = 0;
3651 u32 ioc_state=0;
3652 int cnt,cntdn;
3654 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3655 if (ioc->bus_type == SPI) {
3656 /* Always issue a Msg Unit Reset first. This will clear some
3657 * SCSI bus hang conditions.
3659 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3661 if (sleepFlag == CAN_SLEEP) {
3662 msleep (1000);
3663 } else {
3664 mdelay (1000);
3668 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3669 if (hard_reset_done < 0)
3670 return hard_reset_done;
3672 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3673 ioc->name));
3675 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3676 for (cnt=0; cnt<cntdn; cnt++) {
3677 ioc_state = mpt_GetIocState(ioc, 1);
3678 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3679 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3680 ioc->name, cnt));
3681 return hard_reset_done;
3683 if (sleepFlag == CAN_SLEEP) {
3684 msleep (10);
3685 } else {
3686 mdelay (10);
3690 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3691 ioc->name, mpt_GetIocState(ioc, 0)));
3692 return -1;
3695 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3697 * mpt_diag_reset - Perform hard reset of the adapter.
3698 * @ioc: Pointer to MPT_ADAPTER structure
3699 * @ignore: Set if to honor and clear to ignore
3700 * the reset history bit
3701 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3702 * else set to NO_SLEEP (use mdelay instead)
3704 * This routine places the adapter in diagnostic mode via the
3705 * WriteSequence register and then performs a hard reset of adapter
3706 * via the Diagnostic register. Adapter should be in ready state
3707 * upon successful completion.
3709 * Returns: 1 hard reset successful
3710 * 0 no reset performed because reset history bit set
3711 * -2 enabling diagnostic mode failed
3712 * -3 diagnostic reset failed
3714 static int
3715 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3717 u32 diag0val;
3718 u32 doorbell;
3719 int hard_reset_done = 0;
3720 int count = 0;
3721 u32 diag1val = 0;
3722 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3724 /* Clear any existing interrupts */
3725 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3727 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3728 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3729 "address=%p\n", ioc->name, __func__,
3730 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3731 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3732 if (sleepFlag == CAN_SLEEP)
3733 msleep(1);
3734 else
3735 mdelay(1);
3737 for (count = 0; count < 60; count ++) {
3738 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3739 doorbell &= MPI_IOC_STATE_MASK;
3741 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3742 "looking for READY STATE: doorbell=%x"
3743 " count=%d\n",
3744 ioc->name, doorbell, count));
3745 if (doorbell == MPI_IOC_STATE_READY) {
3746 return 1;
3749 /* wait 1 sec */
3750 if (sleepFlag == CAN_SLEEP)
3751 msleep(1000);
3752 else
3753 mdelay(1000);
3755 return -1;
3758 /* Use "Diagnostic reset" method! (only thing available!) */
3759 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3761 if (ioc->debug_level & MPT_DEBUG) {
3762 if (ioc->alt_ioc)
3763 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3764 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3765 ioc->name, diag0val, diag1val));
3768 /* Do the reset if we are told to ignore the reset history
3769 * or if the reset history is 0
3771 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3772 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3773 /* Write magic sequence to WriteSequence register
3774 * Loop until in diagnostic mode
3776 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3777 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3778 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3779 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3780 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3781 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3783 /* wait 100 msec */
3784 if (sleepFlag == CAN_SLEEP) {
3785 msleep (100);
3786 } else {
3787 mdelay (100);
3790 count++;
3791 if (count > 20) {
3792 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3793 ioc->name, diag0val);
3794 return -2;
3798 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3800 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3801 ioc->name, diag0val));
3804 if (ioc->debug_level & MPT_DEBUG) {
3805 if (ioc->alt_ioc)
3806 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3807 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3808 ioc->name, diag0val, diag1val));
3811 * Disable the ARM (Bug fix)
3814 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3815 mdelay(1);
3818 * Now hit the reset bit in the Diagnostic register
3819 * (THE BIG HAMMER!) (Clears DRWE bit).
3821 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3822 hard_reset_done = 1;
3823 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3824 ioc->name));
3827 * Call each currently registered protocol IOC reset handler
3828 * with pre-reset indication.
3829 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3830 * MptResetHandlers[] registered yet.
3833 u8 cb_idx;
3834 int r = 0;
3836 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3837 if (MptResetHandlers[cb_idx]) {
3838 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3839 "Calling IOC pre_reset handler #%d\n",
3840 ioc->name, cb_idx));
3841 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
3842 if (ioc->alt_ioc) {
3843 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3844 "Calling alt-%s pre_reset handler #%d\n",
3845 ioc->name, ioc->alt_ioc->name, cb_idx));
3846 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3850 /* FIXME? Examine results here? */
3853 if (ioc->cached_fw)
3854 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3855 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3856 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3857 else
3858 cached_fw = NULL;
3859 if (cached_fw) {
3860 /* If the DownloadBoot operation fails, the
3861 * IOC will be left unusable. This is a fatal error
3862 * case. _diag_reset will return < 0
3864 for (count = 0; count < 30; count ++) {
3865 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3866 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3867 break;
3870 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3871 ioc->name, diag0val, count));
3872 /* wait 1 sec */
3873 if (sleepFlag == CAN_SLEEP) {
3874 msleep (1000);
3875 } else {
3876 mdelay (1000);
3879 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3880 printk(MYIOC_s_WARN_FMT
3881 "firmware downloadboot failure (%d)!\n", ioc->name, count);
3884 } else {
3885 /* Wait for FW to reload and for board
3886 * to go to the READY state.
3887 * Maximum wait is 60 seconds.
3888 * If fail, no error will check again
3889 * with calling program.
3891 for (count = 0; count < 60; count ++) {
3892 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3893 doorbell &= MPI_IOC_STATE_MASK;
3895 if (doorbell == MPI_IOC_STATE_READY) {
3896 break;
3899 /* wait 1 sec */
3900 if (sleepFlag == CAN_SLEEP) {
3901 msleep (1000);
3902 } else {
3903 mdelay (1000);
3909 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3910 if (ioc->debug_level & MPT_DEBUG) {
3911 if (ioc->alt_ioc)
3912 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3913 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3914 ioc->name, diag0val, diag1val));
3917 /* Clear RESET_HISTORY bit! Place board in the
3918 * diagnostic mode to update the diag register.
3920 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3921 count = 0;
3922 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3923 /* Write magic sequence to WriteSequence register
3924 * Loop until in diagnostic mode
3926 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3927 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3928 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3929 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3930 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3931 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3933 /* wait 100 msec */
3934 if (sleepFlag == CAN_SLEEP) {
3935 msleep (100);
3936 } else {
3937 mdelay (100);
3940 count++;
3941 if (count > 20) {
3942 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3943 ioc->name, diag0val);
3944 break;
3946 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3948 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3949 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3950 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3951 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3952 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3953 ioc->name);
3956 /* Disable Diagnostic Mode
3958 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3960 /* Check FW reload status flags.
3962 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3963 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3964 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3965 ioc->name, diag0val);
3966 return -3;
3969 if (ioc->debug_level & MPT_DEBUG) {
3970 if (ioc->alt_ioc)
3971 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3972 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3973 ioc->name, diag0val, diag1val));
3977 * Reset flag that says we've enabled event notification
3979 ioc->facts.EventState = 0;
3981 if (ioc->alt_ioc)
3982 ioc->alt_ioc->facts.EventState = 0;
3984 return hard_reset_done;
3987 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3989 * SendIocReset - Send IOCReset request to MPT adapter.
3990 * @ioc: Pointer to MPT_ADAPTER structure
3991 * @reset_type: reset type, expected values are
3992 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3993 * @sleepFlag: Specifies whether the process can sleep
3995 * Send IOCReset request to the MPT adapter.
3997 * Returns 0 for success, non-zero for failure.
3999 static int
4000 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4002 int r;
4003 u32 state;
4004 int cntdn, count;
4006 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4007 ioc->name, reset_type));
4008 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4009 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4010 return r;
4012 /* FW ACK'd request, wait for READY state
4014 count = 0;
4015 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
4017 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4018 cntdn--;
4019 count++;
4020 if (!cntdn) {
4021 if (sleepFlag != CAN_SLEEP)
4022 count *= 10;
4024 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
4025 ioc->name, (int)((count+5)/HZ));
4026 return -ETIME;
4029 if (sleepFlag == CAN_SLEEP) {
4030 msleep(1);
4031 } else {
4032 mdelay (1); /* 1 msec delay */
4036 /* TODO!
4037 * Cleanup all event stuff for this IOC; re-issue EventNotification
4038 * request if needed.
4040 if (ioc->facts.Function)
4041 ioc->facts.EventState = 0;
4043 return 0;
4046 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4048 * initChainBuffers - Allocate memory for and initialize chain buffers
4049 * @ioc: Pointer to MPT_ADAPTER structure
4051 * Allocates memory for and initializes chain buffers,
4052 * chain buffer control arrays and spinlock.
4054 static int
4055 initChainBuffers(MPT_ADAPTER *ioc)
4057 u8 *mem;
4058 int sz, ii, num_chain;
4059 int scale, num_sge, numSGE;
4061 /* ReqToChain size must equal the req_depth
4062 * index = req_idx
4064 if (ioc->ReqToChain == NULL) {
4065 sz = ioc->req_depth * sizeof(int);
4066 mem = kmalloc(sz, GFP_ATOMIC);
4067 if (mem == NULL)
4068 return -1;
4070 ioc->ReqToChain = (int *) mem;
4071 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
4072 ioc->name, mem, sz));
4073 mem = kmalloc(sz, GFP_ATOMIC);
4074 if (mem == NULL)
4075 return -1;
4077 ioc->RequestNB = (int *) mem;
4078 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
4079 ioc->name, mem, sz));
4081 for (ii = 0; ii < ioc->req_depth; ii++) {
4082 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4085 /* ChainToChain size must equal the total number
4086 * of chain buffers to be allocated.
4087 * index = chain_idx
4089 * Calculate the number of chain buffers needed(plus 1) per I/O
4090 * then multiply the maximum number of simultaneous cmds
4092 * num_sge = num sge in request frame + last chain buffer
4093 * scale = num sge per chain buffer if no chain element
4095 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
4096 if (sizeof(dma_addr_t) == sizeof(u64))
4097 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4098 else
4099 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4101 if (sizeof(dma_addr_t) == sizeof(u64)) {
4102 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4103 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4104 } else {
4105 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4106 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4108 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4109 ioc->name, num_sge, numSGE));
4111 if ( numSGE > MPT_SCSI_SG_DEPTH )
4112 numSGE = MPT_SCSI_SG_DEPTH;
4114 num_chain = 1;
4115 while (numSGE - num_sge > 0) {
4116 num_chain++;
4117 num_sge += (scale - 1);
4119 num_chain++;
4121 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4122 ioc->name, numSGE, num_sge, num_chain));
4124 if (ioc->bus_type == SPI)
4125 num_chain *= MPT_SCSI_CAN_QUEUE;
4126 else
4127 num_chain *= MPT_FC_CAN_QUEUE;
4129 ioc->num_chain = num_chain;
4131 sz = num_chain * sizeof(int);
4132 if (ioc->ChainToChain == NULL) {
4133 mem = kmalloc(sz, GFP_ATOMIC);
4134 if (mem == NULL)
4135 return -1;
4137 ioc->ChainToChain = (int *) mem;
4138 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4139 ioc->name, mem, sz));
4140 } else {
4141 mem = (u8 *) ioc->ChainToChain;
4143 memset(mem, 0xFF, sz);
4144 return num_chain;
4147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4149 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4150 * @ioc: Pointer to MPT_ADAPTER structure
4152 * This routine allocates memory for the MPT reply and request frame
4153 * pools (if necessary), and primes the IOC reply FIFO with
4154 * reply frames.
4156 * Returns 0 for success, non-zero for failure.
4158 static int
4159 PrimeIocFifos(MPT_ADAPTER *ioc)
4161 MPT_FRAME_HDR *mf;
4162 unsigned long flags;
4163 dma_addr_t alloc_dma;
4164 u8 *mem;
4165 int i, reply_sz, sz, total_size, num_chain;
4167 /* Prime reply FIFO... */
4169 if (ioc->reply_frames == NULL) {
4170 if ( (num_chain = initChainBuffers(ioc)) < 0)
4171 return -1;
4173 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4174 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4175 ioc->name, ioc->reply_sz, ioc->reply_depth));
4176 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4177 ioc->name, reply_sz, reply_sz));
4179 sz = (ioc->req_sz * ioc->req_depth);
4180 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4181 ioc->name, ioc->req_sz, ioc->req_depth));
4182 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4183 ioc->name, sz, sz));
4184 total_size += sz;
4186 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4187 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4188 ioc->name, ioc->req_sz, num_chain));
4189 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4190 ioc->name, sz, sz, num_chain));
4192 total_size += sz;
4193 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4194 if (mem == NULL) {
4195 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4196 ioc->name);
4197 goto out_fail;
4200 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4201 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4203 memset(mem, 0, total_size);
4204 ioc->alloc_total += total_size;
4205 ioc->alloc = mem;
4206 ioc->alloc_dma = alloc_dma;
4207 ioc->alloc_sz = total_size;
4208 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4209 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4211 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4212 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4214 alloc_dma += reply_sz;
4215 mem += reply_sz;
4217 /* Request FIFO - WE manage this! */
4219 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4220 ioc->req_frames_dma = alloc_dma;
4222 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4223 ioc->name, mem, (void *)(ulong)alloc_dma));
4225 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4227 #if defined(CONFIG_MTRR) && 0
4229 * Enable Write Combining MTRR for IOC's memory region.
4230 * (at least as much as we can; "size and base must be
4231 * multiples of 4 kiB"
4233 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4235 MTRR_TYPE_WRCOMB, 1);
4236 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4237 ioc->name, ioc->req_frames_dma, sz));
4238 #endif
4240 for (i = 0; i < ioc->req_depth; i++) {
4241 alloc_dma += ioc->req_sz;
4242 mem += ioc->req_sz;
4245 ioc->ChainBuffer = mem;
4246 ioc->ChainBufferDMA = alloc_dma;
4248 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4249 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4251 /* Initialize the free chain Q.
4254 INIT_LIST_HEAD(&ioc->FreeChainQ);
4256 /* Post the chain buffers to the FreeChainQ.
4258 mem = (u8 *)ioc->ChainBuffer;
4259 for (i=0; i < num_chain; i++) {
4260 mf = (MPT_FRAME_HDR *) mem;
4261 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4262 mem += ioc->req_sz;
4265 /* Initialize Request frames linked list
4267 alloc_dma = ioc->req_frames_dma;
4268 mem = (u8 *) ioc->req_frames;
4270 spin_lock_irqsave(&ioc->FreeQlock, flags);
4271 INIT_LIST_HEAD(&ioc->FreeQ);
4272 for (i = 0; i < ioc->req_depth; i++) {
4273 mf = (MPT_FRAME_HDR *) mem;
4275 /* Queue REQUESTs *internally*! */
4276 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4278 mem += ioc->req_sz;
4280 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4282 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4283 ioc->sense_buf_pool =
4284 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4285 if (ioc->sense_buf_pool == NULL) {
4286 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4287 ioc->name);
4288 goto out_fail;
4291 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4292 ioc->alloc_total += sz;
4293 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4294 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4298 /* Post Reply frames to FIFO
4300 alloc_dma = ioc->alloc_dma;
4301 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4302 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4304 for (i = 0; i < ioc->reply_depth; i++) {
4305 /* Write each address to the IOC! */
4306 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4307 alloc_dma += ioc->reply_sz;
4310 return 0;
4312 out_fail:
4313 if (ioc->alloc != NULL) {
4314 sz = ioc->alloc_sz;
4315 pci_free_consistent(ioc->pcidev,
4317 ioc->alloc, ioc->alloc_dma);
4318 ioc->reply_frames = NULL;
4319 ioc->req_frames = NULL;
4320 ioc->alloc_total -= sz;
4322 if (ioc->sense_buf_pool != NULL) {
4323 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4324 pci_free_consistent(ioc->pcidev,
4326 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4327 ioc->sense_buf_pool = NULL;
4329 return -1;
4332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4334 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4335 * from IOC via doorbell handshake method.
4336 * @ioc: Pointer to MPT_ADAPTER structure
4337 * @reqBytes: Size of the request in bytes
4338 * @req: Pointer to MPT request frame
4339 * @replyBytes: Expected size of the reply in bytes
4340 * @u16reply: Pointer to area where reply should be written
4341 * @maxwait: Max wait time for a reply (in seconds)
4342 * @sleepFlag: Specifies whether the process can sleep
4344 * NOTES: It is the callers responsibility to byte-swap fields in the
4345 * request which are greater than 1 byte in size. It is also the
4346 * callers responsibility to byte-swap response fields which are
4347 * greater than 1 byte in size.
4349 * Returns 0 for success, non-zero for failure.
4351 static int
4352 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4353 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4355 MPIDefaultReply_t *mptReply;
4356 int failcnt = 0;
4357 int t;
4360 * Get ready to cache a handshake reply
4362 ioc->hs_reply_idx = 0;
4363 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4364 mptReply->MsgLength = 0;
4367 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4368 * then tell IOC that we want to handshake a request of N words.
4369 * (WRITE u32val to Doorbell reg).
4371 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4372 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4373 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4374 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4377 * Wait for IOC's doorbell handshake int
4379 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4380 failcnt++;
4382 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4383 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4385 /* Read doorbell and check for active bit */
4386 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4387 return -1;
4390 * Clear doorbell int (WRITE 0 to IntStatus reg),
4391 * then wait for IOC to ACKnowledge that it's ready for
4392 * our handshake request.
4394 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4395 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4396 failcnt++;
4398 if (!failcnt) {
4399 int ii;
4400 u8 *req_as_bytes = (u8 *) req;
4403 * Stuff request words via doorbell handshake,
4404 * with ACK from IOC for each.
4406 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4407 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4408 (req_as_bytes[(ii*4) + 1] << 8) |
4409 (req_as_bytes[(ii*4) + 2] << 16) |
4410 (req_as_bytes[(ii*4) + 3] << 24));
4412 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4413 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4414 failcnt++;
4417 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4418 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4420 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4421 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4424 * Wait for completion of doorbell handshake reply from the IOC
4426 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4427 failcnt++;
4429 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4430 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4433 * Copy out the cached reply...
4435 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4436 u16reply[ii] = ioc->hs_reply[ii];
4437 } else {
4438 return -99;
4441 return -failcnt;
4444 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4446 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4447 * @ioc: Pointer to MPT_ADAPTER structure
4448 * @howlong: How long to wait (in seconds)
4449 * @sleepFlag: Specifies whether the process can sleep
4451 * This routine waits (up to ~2 seconds max) for IOC doorbell
4452 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4453 * bit in its IntStatus register being clear.
4455 * Returns a negative value on failure, else wait loop count.
4457 static int
4458 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4460 int cntdn;
4461 int count = 0;
4462 u32 intstat=0;
4464 cntdn = 1000 * howlong;
4466 if (sleepFlag == CAN_SLEEP) {
4467 while (--cntdn) {
4468 msleep (1);
4469 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4470 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4471 break;
4472 count++;
4474 } else {
4475 while (--cntdn) {
4476 udelay (1000);
4477 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4478 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4479 break;
4480 count++;
4484 if (cntdn) {
4485 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4486 ioc->name, count));
4487 return count;
4490 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4491 ioc->name, count, intstat);
4492 return -1;
4495 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4497 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4498 * @ioc: Pointer to MPT_ADAPTER structure
4499 * @howlong: How long to wait (in seconds)
4500 * @sleepFlag: Specifies whether the process can sleep
4502 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4503 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4505 * Returns a negative value on failure, else wait loop count.
4507 static int
4508 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4510 int cntdn;
4511 int count = 0;
4512 u32 intstat=0;
4514 cntdn = 1000 * howlong;
4515 if (sleepFlag == CAN_SLEEP) {
4516 while (--cntdn) {
4517 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4518 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4519 break;
4520 msleep(1);
4521 count++;
4523 } else {
4524 while (--cntdn) {
4525 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4526 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4527 break;
4528 udelay (1000);
4529 count++;
4533 if (cntdn) {
4534 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4535 ioc->name, count, howlong));
4536 return count;
4539 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4540 ioc->name, count, intstat);
4541 return -1;
4544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4546 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4547 * @ioc: Pointer to MPT_ADAPTER structure
4548 * @howlong: How long to wait (in seconds)
4549 * @sleepFlag: Specifies whether the process can sleep
4551 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4552 * Reply is cached to IOC private area large enough to hold a maximum
4553 * of 128 bytes of reply data.
4555 * Returns a negative value on failure, else size of reply in WORDS.
4557 static int
4558 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4560 int u16cnt = 0;
4561 int failcnt = 0;
4562 int t;
4563 u16 *hs_reply = ioc->hs_reply;
4564 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4565 u16 hword;
4567 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4570 * Get first two u16's so we can look at IOC's intended reply MsgLength
4572 u16cnt=0;
4573 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4574 failcnt++;
4575 } else {
4576 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4577 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4578 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4579 failcnt++;
4580 else {
4581 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4582 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4586 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4587 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4588 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4591 * If no error (and IOC said MsgLength is > 0), piece together
4592 * reply 16 bits at a time.
4594 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4595 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4596 failcnt++;
4597 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4598 /* don't overflow our IOC hs_reply[] buffer! */
4599 if (u16cnt < ARRAY_SIZE(ioc->hs_reply))
4600 hs_reply[u16cnt] = hword;
4601 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4604 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4605 failcnt++;
4606 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4608 if (failcnt) {
4609 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4610 ioc->name);
4611 return -failcnt;
4613 #if 0
4614 else if (u16cnt != (2 * mptReply->MsgLength)) {
4615 return -101;
4617 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4618 return -102;
4620 #endif
4622 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4623 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4625 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4626 ioc->name, t, u16cnt/2));
4627 return u16cnt/2;
4630 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4632 * GetLanConfigPages - Fetch LANConfig pages.
4633 * @ioc: Pointer to MPT_ADAPTER structure
4635 * Return: 0 for success
4636 * -ENOMEM if no memory available
4637 * -EPERM if not allowed due to ISR context
4638 * -EAGAIN if no msg frames currently available
4639 * -EFAULT for non-successful reply or no reply (timeout)
4641 static int
4642 GetLanConfigPages(MPT_ADAPTER *ioc)
4644 ConfigPageHeader_t hdr;
4645 CONFIGPARMS cfg;
4646 LANPage0_t *ppage0_alloc;
4647 dma_addr_t page0_dma;
4648 LANPage1_t *ppage1_alloc;
4649 dma_addr_t page1_dma;
4650 int rc = 0;
4651 int data_sz;
4652 int copy_sz;
4654 /* Get LAN Page 0 header */
4655 hdr.PageVersion = 0;
4656 hdr.PageLength = 0;
4657 hdr.PageNumber = 0;
4658 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4659 cfg.cfghdr.hdr = &hdr;
4660 cfg.physAddr = -1;
4661 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4662 cfg.dir = 0;
4663 cfg.pageAddr = 0;
4664 cfg.timeout = 0;
4666 if ((rc = mpt_config(ioc, &cfg)) != 0)
4667 return rc;
4669 if (hdr.PageLength > 0) {
4670 data_sz = hdr.PageLength * 4;
4671 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4672 rc = -ENOMEM;
4673 if (ppage0_alloc) {
4674 memset((u8 *)ppage0_alloc, 0, data_sz);
4675 cfg.physAddr = page0_dma;
4676 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4678 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4679 /* save the data */
4680 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4681 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4685 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4687 /* FIXME!
4688 * Normalize endianness of structure data,
4689 * by byte-swapping all > 1 byte fields!
4694 if (rc)
4695 return rc;
4698 /* Get LAN Page 1 header */
4699 hdr.PageVersion = 0;
4700 hdr.PageLength = 0;
4701 hdr.PageNumber = 1;
4702 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4703 cfg.cfghdr.hdr = &hdr;
4704 cfg.physAddr = -1;
4705 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4706 cfg.dir = 0;
4707 cfg.pageAddr = 0;
4709 if ((rc = mpt_config(ioc, &cfg)) != 0)
4710 return rc;
4712 if (hdr.PageLength == 0)
4713 return 0;
4715 data_sz = hdr.PageLength * 4;
4716 rc = -ENOMEM;
4717 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4718 if (ppage1_alloc) {
4719 memset((u8 *)ppage1_alloc, 0, data_sz);
4720 cfg.physAddr = page1_dma;
4721 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4723 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4724 /* save the data */
4725 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4726 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4729 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4731 /* FIXME!
4732 * Normalize endianness of structure data,
4733 * by byte-swapping all > 1 byte fields!
4738 return rc;
4741 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4743 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4744 * @ioc: Pointer to MPT_ADAPTER structure
4745 * @persist_opcode: see below
4747 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4748 * devices not currently present.
4749 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4751 * NOTE: Don't use not this function during interrupt time.
4753 * Returns 0 for success, non-zero error
4756 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4758 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4760 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4761 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4762 MPT_FRAME_HDR *mf = NULL;
4763 MPIHeader_t *mpi_hdr;
4766 /* insure garbage is not sent to fw */
4767 switch(persist_opcode) {
4769 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4770 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4771 break;
4773 default:
4774 return -1;
4775 break;
4778 printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
4780 /* Get a MF for this command.
4782 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4783 printk("%s: no msg frames!\n",__func__);
4784 return -1;
4787 mpi_hdr = (MPIHeader_t *) mf;
4788 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4789 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4790 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4791 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4792 sasIoUnitCntrReq->Operation = persist_opcode;
4794 init_timer(&ioc->persist_timer);
4795 ioc->persist_timer.data = (unsigned long) ioc;
4796 ioc->persist_timer.function = mpt_timer_expired;
4797 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4798 ioc->persist_wait_done=0;
4799 add_timer(&ioc->persist_timer);
4800 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4801 wait_event(mpt_waitq, ioc->persist_wait_done);
4803 sasIoUnitCntrReply =
4804 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4805 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4806 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4807 __func__,
4808 sasIoUnitCntrReply->IOCStatus,
4809 sasIoUnitCntrReply->IOCLogInfo);
4810 return -1;
4813 printk("%s: success\n",__func__);
4814 return 0;
4817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4819 static void
4820 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4821 MpiEventDataRaid_t * pRaidEventData)
4823 int volume;
4824 int reason;
4825 int disk;
4826 int status;
4827 int flags;
4828 int state;
4830 volume = pRaidEventData->VolumeID;
4831 reason = pRaidEventData->ReasonCode;
4832 disk = pRaidEventData->PhysDiskNum;
4833 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4834 flags = (status >> 0) & 0xff;
4835 state = (status >> 8) & 0xff;
4837 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4838 return;
4841 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4842 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4843 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4844 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4845 ioc->name, disk, volume);
4846 } else {
4847 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4848 ioc->name, volume);
4851 switch(reason) {
4852 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4853 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4854 ioc->name);
4855 break;
4857 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4859 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4860 ioc->name);
4861 break;
4863 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4864 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4865 ioc->name);
4866 break;
4868 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4869 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4870 ioc->name,
4871 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4872 ? "optimal"
4873 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4874 ? "degraded"
4875 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4876 ? "failed"
4877 : "state unknown",
4878 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4879 ? ", enabled" : "",
4880 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4881 ? ", quiesced" : "",
4882 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4883 ? ", resync in progress" : "" );
4884 break;
4886 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4887 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4888 ioc->name, disk);
4889 break;
4891 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4892 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4893 ioc->name);
4894 break;
4896 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4897 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4898 ioc->name);
4899 break;
4901 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4902 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4903 ioc->name);
4904 break;
4906 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4907 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4908 ioc->name,
4909 state == MPI_PHYSDISK0_STATUS_ONLINE
4910 ? "online"
4911 : state == MPI_PHYSDISK0_STATUS_MISSING
4912 ? "missing"
4913 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4914 ? "not compatible"
4915 : state == MPI_PHYSDISK0_STATUS_FAILED
4916 ? "failed"
4917 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4918 ? "initializing"
4919 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4920 ? "offline requested"
4921 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4922 ? "failed requested"
4923 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4924 ? "offline"
4925 : "state unknown",
4926 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4927 ? ", out of sync" : "",
4928 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4929 ? ", quiesced" : "" );
4930 break;
4932 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4933 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4934 ioc->name, disk);
4935 break;
4937 case MPI_EVENT_RAID_RC_SMART_DATA:
4938 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4939 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4940 break;
4942 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4943 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4944 ioc->name, disk);
4945 break;
4949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4951 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4952 * @ioc: Pointer to MPT_ADAPTER structure
4954 * Returns: 0 for success
4955 * -ENOMEM if no memory available
4956 * -EPERM if not allowed due to ISR context
4957 * -EAGAIN if no msg frames currently available
4958 * -EFAULT for non-successful reply or no reply (timeout)
4960 static int
4961 GetIoUnitPage2(MPT_ADAPTER *ioc)
4963 ConfigPageHeader_t hdr;
4964 CONFIGPARMS cfg;
4965 IOUnitPage2_t *ppage_alloc;
4966 dma_addr_t page_dma;
4967 int data_sz;
4968 int rc;
4970 /* Get the page header */
4971 hdr.PageVersion = 0;
4972 hdr.PageLength = 0;
4973 hdr.PageNumber = 2;
4974 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4975 cfg.cfghdr.hdr = &hdr;
4976 cfg.physAddr = -1;
4977 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4978 cfg.dir = 0;
4979 cfg.pageAddr = 0;
4980 cfg.timeout = 0;
4982 if ((rc = mpt_config(ioc, &cfg)) != 0)
4983 return rc;
4985 if (hdr.PageLength == 0)
4986 return 0;
4988 /* Read the config page */
4989 data_sz = hdr.PageLength * 4;
4990 rc = -ENOMEM;
4991 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4992 if (ppage_alloc) {
4993 memset((u8 *)ppage_alloc, 0, data_sz);
4994 cfg.physAddr = page_dma;
4995 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4997 /* If Good, save data */
4998 if ((rc = mpt_config(ioc, &cfg)) == 0)
4999 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
5001 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
5004 return rc;
5007 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5009 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5010 * @ioc: Pointer to a Adapter Strucutre
5011 * @portnum: IOC port number
5013 * Return: -EFAULT if read of config page header fails
5014 * or if no nvram
5015 * If read of SCSI Port Page 0 fails,
5016 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5017 * Adapter settings: async, narrow
5018 * Return 1
5019 * If read of SCSI Port Page 2 fails,
5020 * Adapter settings valid
5021 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5022 * Return 1
5023 * Else
5024 * Both valid
5025 * Return 0
5026 * CHECK - what type of locking mechanisms should be used????
5028 static int
5029 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
5031 u8 *pbuf;
5032 dma_addr_t buf_dma;
5033 CONFIGPARMS cfg;
5034 ConfigPageHeader_t header;
5035 int ii;
5036 int data, rc = 0;
5038 /* Allocate memory
5040 if (!ioc->spi_data.nvram) {
5041 int sz;
5042 u8 *mem;
5043 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5044 mem = kmalloc(sz, GFP_ATOMIC);
5045 if (mem == NULL)
5046 return -EFAULT;
5048 ioc->spi_data.nvram = (int *) mem;
5050 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5051 ioc->name, ioc->spi_data.nvram, sz));
5054 /* Invalidate NVRAM information
5056 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5057 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5060 /* Read SPP0 header, allocate memory, then read page.
5062 header.PageVersion = 0;
5063 header.PageLength = 0;
5064 header.PageNumber = 0;
5065 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5066 cfg.cfghdr.hdr = &header;
5067 cfg.physAddr = -1;
5068 cfg.pageAddr = portnum;
5069 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5070 cfg.dir = 0;
5071 cfg.timeout = 0; /* use default */
5072 if (mpt_config(ioc, &cfg) != 0)
5073 return -EFAULT;
5075 if (header.PageLength > 0) {
5076 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5077 if (pbuf) {
5078 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5079 cfg.physAddr = buf_dma;
5080 if (mpt_config(ioc, &cfg) != 0) {
5081 ioc->spi_data.maxBusWidth = MPT_NARROW;
5082 ioc->spi_data.maxSyncOffset = 0;
5083 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5084 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5085 rc = 1;
5086 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5087 "Unable to read PortPage0 minSyncFactor=%x\n",
5088 ioc->name, ioc->spi_data.minSyncFactor));
5089 } else {
5090 /* Save the Port Page 0 data
5092 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
5093 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5094 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5096 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5097 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5098 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5099 "noQas due to Capabilities=%x\n",
5100 ioc->name, pPP0->Capabilities));
5102 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5103 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5104 if (data) {
5105 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5106 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5107 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5108 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5109 "PortPage0 minSyncFactor=%x\n",
5110 ioc->name, ioc->spi_data.minSyncFactor));
5111 } else {
5112 ioc->spi_data.maxSyncOffset = 0;
5113 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5116 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5118 /* Update the minSyncFactor based on bus type.
5120 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5121 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
5123 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5124 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5125 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5126 "HVD or SE detected, minSyncFactor=%x\n",
5127 ioc->name, ioc->spi_data.minSyncFactor));
5131 if (pbuf) {
5132 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5137 /* SCSI Port Page 2 - Read the header then the page.
5139 header.PageVersion = 0;
5140 header.PageLength = 0;
5141 header.PageNumber = 2;
5142 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5143 cfg.cfghdr.hdr = &header;
5144 cfg.physAddr = -1;
5145 cfg.pageAddr = portnum;
5146 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5147 cfg.dir = 0;
5148 if (mpt_config(ioc, &cfg) != 0)
5149 return -EFAULT;
5151 if (header.PageLength > 0) {
5152 /* Allocate memory and read SCSI Port Page 2
5154 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5155 if (pbuf) {
5156 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5157 cfg.physAddr = buf_dma;
5158 if (mpt_config(ioc, &cfg) != 0) {
5159 /* Nvram data is left with INVALID mark
5161 rc = 1;
5162 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5164 /* This is an ATTO adapter, read Page2 accordingly
5166 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5167 ATTODeviceInfo_t *pdevice = NULL;
5168 u16 ATTOFlags;
5170 /* Save the Port Page 2 data
5171 * (reformat into a 32bit quantity)
5173 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5174 pdevice = &pPP2->DeviceSettings[ii];
5175 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5176 data = 0;
5178 /* Translate ATTO device flags to LSI format
5180 if (ATTOFlags & ATTOFLAG_DISC)
5181 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5182 if (ATTOFlags & ATTOFLAG_ID_ENB)
5183 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5184 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5185 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5186 if (ATTOFlags & ATTOFLAG_TAGGED)
5187 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5188 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5189 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5191 data = (data << 16) | (pdevice->Period << 8) | 10;
5192 ioc->spi_data.nvram[ii] = data;
5194 } else {
5195 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5196 MpiDeviceInfo_t *pdevice = NULL;
5199 * Save "Set to Avoid SCSI Bus Resets" flag
5201 ioc->spi_data.bus_reset =
5202 (le32_to_cpu(pPP2->PortFlags) &
5203 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5204 0 : 1 ;
5206 /* Save the Port Page 2 data
5207 * (reformat into a 32bit quantity)
5209 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5210 ioc->spi_data.PortFlags = data;
5211 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5212 pdevice = &pPP2->DeviceSettings[ii];
5213 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5214 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5215 ioc->spi_data.nvram[ii] = data;
5219 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5223 /* Update Adapter limits with those from NVRAM
5224 * Comment: Don't need to do this. Target performance
5225 * parameters will never exceed the adapters limits.
5228 return rc;
5231 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5233 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5234 * @ioc: Pointer to a Adapter Strucutre
5235 * @portnum: IOC port number
5237 * Return: -EFAULT if read of config page header fails
5238 * or 0 if success.
5240 static int
5241 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5243 CONFIGPARMS cfg;
5244 ConfigPageHeader_t header;
5246 /* Read the SCSI Device Page 1 header
5248 header.PageVersion = 0;
5249 header.PageLength = 0;
5250 header.PageNumber = 1;
5251 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5252 cfg.cfghdr.hdr = &header;
5253 cfg.physAddr = -1;
5254 cfg.pageAddr = portnum;
5255 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5256 cfg.dir = 0;
5257 cfg.timeout = 0;
5258 if (mpt_config(ioc, &cfg) != 0)
5259 return -EFAULT;
5261 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5262 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5264 header.PageVersion = 0;
5265 header.PageLength = 0;
5266 header.PageNumber = 0;
5267 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5268 if (mpt_config(ioc, &cfg) != 0)
5269 return -EFAULT;
5271 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5272 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5274 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5275 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5277 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5278 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5279 return 0;
5283 * mpt_inactive_raid_list_free - This clears this link list.
5284 * @ioc : pointer to per adapter structure
5286 static void
5287 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5289 struct inactive_raid_component_info *component_info, *pNext;
5291 if (list_empty(&ioc->raid_data.inactive_list))
5292 return;
5294 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5295 list_for_each_entry_safe(component_info, pNext,
5296 &ioc->raid_data.inactive_list, list) {
5297 list_del(&component_info->list);
5298 kfree(component_info);
5300 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5304 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5306 * @ioc : pointer to per adapter structure
5307 * @channel : volume channel
5308 * @id : volume target id
5310 static void
5311 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5313 CONFIGPARMS cfg;
5314 ConfigPageHeader_t hdr;
5315 dma_addr_t dma_handle;
5316 pRaidVolumePage0_t buffer = NULL;
5317 int i;
5318 RaidPhysDiskPage0_t phys_disk;
5319 struct inactive_raid_component_info *component_info;
5320 int handle_inactive_volumes;
5322 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5323 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5324 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5325 cfg.pageAddr = (channel << 8) + id;
5326 cfg.cfghdr.hdr = &hdr;
5327 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5329 if (mpt_config(ioc, &cfg) != 0)
5330 goto out;
5332 if (!hdr.PageLength)
5333 goto out;
5335 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5336 &dma_handle);
5338 if (!buffer)
5339 goto out;
5341 cfg.physAddr = dma_handle;
5342 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5344 if (mpt_config(ioc, &cfg) != 0)
5345 goto out;
5347 if (!buffer->NumPhysDisks)
5348 goto out;
5350 handle_inactive_volumes =
5351 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5352 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5353 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5354 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5356 if (!handle_inactive_volumes)
5357 goto out;
5359 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5360 for (i = 0; i < buffer->NumPhysDisks; i++) {
5361 if(mpt_raid_phys_disk_pg0(ioc,
5362 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5363 continue;
5365 if ((component_info = kmalloc(sizeof (*component_info),
5366 GFP_KERNEL)) == NULL)
5367 continue;
5369 component_info->volumeID = id;
5370 component_info->volumeBus = channel;
5371 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5372 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5373 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5374 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5376 list_add_tail(&component_info->list,
5377 &ioc->raid_data.inactive_list);
5379 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5381 out:
5382 if (buffer)
5383 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5384 dma_handle);
5388 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5389 * @ioc: Pointer to a Adapter Structure
5390 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5391 * @phys_disk: requested payload data returned
5393 * Return:
5394 * 0 on success
5395 * -EFAULT if read of config page header fails or data pointer not NULL
5396 * -ENOMEM if pci_alloc failed
5399 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
5401 CONFIGPARMS cfg;
5402 ConfigPageHeader_t hdr;
5403 dma_addr_t dma_handle;
5404 pRaidPhysDiskPage0_t buffer = NULL;
5405 int rc;
5407 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5408 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5410 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5411 cfg.cfghdr.hdr = &hdr;
5412 cfg.physAddr = -1;
5413 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5415 if (mpt_config(ioc, &cfg) != 0) {
5416 rc = -EFAULT;
5417 goto out;
5420 if (!hdr.PageLength) {
5421 rc = -EFAULT;
5422 goto out;
5425 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5426 &dma_handle);
5428 if (!buffer) {
5429 rc = -ENOMEM;
5430 goto out;
5433 cfg.physAddr = dma_handle;
5434 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5435 cfg.pageAddr = phys_disk_num;
5437 if (mpt_config(ioc, &cfg) != 0) {
5438 rc = -EFAULT;
5439 goto out;
5442 rc = 0;
5443 memcpy(phys_disk, buffer, sizeof(*buffer));
5444 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5446 out:
5448 if (buffer)
5449 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5450 dma_handle);
5452 return rc;
5456 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5457 * @ioc: Pointer to a Adapter Strucutre
5459 * Return:
5460 * 0 on success
5461 * -EFAULT if read of config page header fails or data pointer not NULL
5462 * -ENOMEM if pci_alloc failed
5465 mpt_findImVolumes(MPT_ADAPTER *ioc)
5467 IOCPage2_t *pIoc2;
5468 u8 *mem;
5469 dma_addr_t ioc2_dma;
5470 CONFIGPARMS cfg;
5471 ConfigPageHeader_t header;
5472 int rc = 0;
5473 int iocpage2sz;
5474 int i;
5476 if (!ioc->ir_firmware)
5477 return 0;
5479 /* Free the old page
5481 kfree(ioc->raid_data.pIocPg2);
5482 ioc->raid_data.pIocPg2 = NULL;
5483 mpt_inactive_raid_list_free(ioc);
5485 /* Read IOCP2 header then the page.
5487 header.PageVersion = 0;
5488 header.PageLength = 0;
5489 header.PageNumber = 2;
5490 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5491 cfg.cfghdr.hdr = &header;
5492 cfg.physAddr = -1;
5493 cfg.pageAddr = 0;
5494 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5495 cfg.dir = 0;
5496 cfg.timeout = 0;
5497 if (mpt_config(ioc, &cfg) != 0)
5498 return -EFAULT;
5500 if (header.PageLength == 0)
5501 return -EFAULT;
5503 iocpage2sz = header.PageLength * 4;
5504 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5505 if (!pIoc2)
5506 return -ENOMEM;
5508 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5509 cfg.physAddr = ioc2_dma;
5510 if (mpt_config(ioc, &cfg) != 0)
5511 goto out;
5513 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5514 if (!mem)
5515 goto out;
5517 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5518 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5520 mpt_read_ioc_pg_3(ioc);
5522 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5523 mpt_inactive_raid_volumes(ioc,
5524 pIoc2->RaidVolume[i].VolumeBus,
5525 pIoc2->RaidVolume[i].VolumeID);
5527 out:
5528 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5530 return rc;
5533 static int
5534 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5536 IOCPage3_t *pIoc3;
5537 u8 *mem;
5538 CONFIGPARMS cfg;
5539 ConfigPageHeader_t header;
5540 dma_addr_t ioc3_dma;
5541 int iocpage3sz = 0;
5543 /* Free the old page
5545 kfree(ioc->raid_data.pIocPg3);
5546 ioc->raid_data.pIocPg3 = NULL;
5548 /* There is at least one physical disk.
5549 * Read and save IOC Page 3
5551 header.PageVersion = 0;
5552 header.PageLength = 0;
5553 header.PageNumber = 3;
5554 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5555 cfg.cfghdr.hdr = &header;
5556 cfg.physAddr = -1;
5557 cfg.pageAddr = 0;
5558 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5559 cfg.dir = 0;
5560 cfg.timeout = 0;
5561 if (mpt_config(ioc, &cfg) != 0)
5562 return 0;
5564 if (header.PageLength == 0)
5565 return 0;
5567 /* Read Header good, alloc memory
5569 iocpage3sz = header.PageLength * 4;
5570 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5571 if (!pIoc3)
5572 return 0;
5574 /* Read the Page and save the data
5575 * into malloc'd memory.
5577 cfg.physAddr = ioc3_dma;
5578 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5579 if (mpt_config(ioc, &cfg) == 0) {
5580 mem = kmalloc(iocpage3sz, GFP_KERNEL);
5581 if (mem) {
5582 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5583 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5587 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5589 return 0;
5592 static void
5593 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5595 IOCPage4_t *pIoc4;
5596 CONFIGPARMS cfg;
5597 ConfigPageHeader_t header;
5598 dma_addr_t ioc4_dma;
5599 int iocpage4sz;
5601 /* Read and save IOC Page 4
5603 header.PageVersion = 0;
5604 header.PageLength = 0;
5605 header.PageNumber = 4;
5606 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5607 cfg.cfghdr.hdr = &header;
5608 cfg.physAddr = -1;
5609 cfg.pageAddr = 0;
5610 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5611 cfg.dir = 0;
5612 cfg.timeout = 0;
5613 if (mpt_config(ioc, &cfg) != 0)
5614 return;
5616 if (header.PageLength == 0)
5617 return;
5619 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5620 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5621 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5622 if (!pIoc4)
5623 return;
5624 ioc->alloc_total += iocpage4sz;
5625 } else {
5626 ioc4_dma = ioc->spi_data.IocPg4_dma;
5627 iocpage4sz = ioc->spi_data.IocPg4Sz;
5630 /* Read the Page into dma memory.
5632 cfg.physAddr = ioc4_dma;
5633 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5634 if (mpt_config(ioc, &cfg) == 0) {
5635 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5636 ioc->spi_data.IocPg4_dma = ioc4_dma;
5637 ioc->spi_data.IocPg4Sz = iocpage4sz;
5638 } else {
5639 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5640 ioc->spi_data.pIocPg4 = NULL;
5641 ioc->alloc_total -= iocpage4sz;
5645 static void
5646 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5648 IOCPage1_t *pIoc1;
5649 CONFIGPARMS cfg;
5650 ConfigPageHeader_t header;
5651 dma_addr_t ioc1_dma;
5652 int iocpage1sz = 0;
5653 u32 tmp;
5655 /* Check the Coalescing Timeout in IOC Page 1
5657 header.PageVersion = 0;
5658 header.PageLength = 0;
5659 header.PageNumber = 1;
5660 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5661 cfg.cfghdr.hdr = &header;
5662 cfg.physAddr = -1;
5663 cfg.pageAddr = 0;
5664 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5665 cfg.dir = 0;
5666 cfg.timeout = 0;
5667 if (mpt_config(ioc, &cfg) != 0)
5668 return;
5670 if (header.PageLength == 0)
5671 return;
5673 /* Read Header good, alloc memory
5675 iocpage1sz = header.PageLength * 4;
5676 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5677 if (!pIoc1)
5678 return;
5680 /* Read the Page and check coalescing timeout
5682 cfg.physAddr = ioc1_dma;
5683 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5684 if (mpt_config(ioc, &cfg) == 0) {
5686 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5687 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5688 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5690 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
5691 ioc->name, tmp));
5693 if (tmp > MPT_COALESCING_TIMEOUT) {
5694 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5696 /* Write NVRAM and current
5698 cfg.dir = 1;
5699 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5700 if (mpt_config(ioc, &cfg) == 0) {
5701 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
5702 ioc->name, MPT_COALESCING_TIMEOUT));
5704 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5705 if (mpt_config(ioc, &cfg) == 0) {
5706 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5707 "Reset NVRAM Coalescing Timeout to = %d\n",
5708 ioc->name, MPT_COALESCING_TIMEOUT));
5709 } else {
5710 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5711 "Reset NVRAM Coalescing Timeout Failed\n",
5712 ioc->name));
5715 } else {
5716 dprintk(ioc, printk(MYIOC_s_WARN_FMT
5717 "Reset of Current Coalescing Timeout Failed!\n",
5718 ioc->name));
5722 } else {
5723 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5727 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5729 return;
5732 static void
5733 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
5735 CONFIGPARMS cfg;
5736 ConfigPageHeader_t hdr;
5737 dma_addr_t buf_dma;
5738 ManufacturingPage0_t *pbuf = NULL;
5740 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5741 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5743 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5744 cfg.cfghdr.hdr = &hdr;
5745 cfg.physAddr = -1;
5746 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5747 cfg.timeout = 10;
5749 if (mpt_config(ioc, &cfg) != 0)
5750 goto out;
5752 if (!cfg.cfghdr.hdr->PageLength)
5753 goto out;
5755 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5756 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
5757 if (!pbuf)
5758 goto out;
5760 cfg.physAddr = buf_dma;
5762 if (mpt_config(ioc, &cfg) != 0)
5763 goto out;
5765 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
5766 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
5767 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
5769 out:
5771 if (pbuf)
5772 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
5775 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5777 * SendEventNotification - Send EventNotification (on or off) request to adapter
5778 * @ioc: Pointer to MPT_ADAPTER structure
5779 * @EvSwitch: Event switch flags
5781 static int
5782 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5784 EventNotification_t *evnp;
5786 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5787 if (evnp == NULL) {
5788 devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5789 ioc->name));
5790 return 0;
5792 memset(evnp, 0, sizeof(*evnp));
5794 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5796 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5797 evnp->ChainOffset = 0;
5798 evnp->MsgFlags = 0;
5799 evnp->Switch = EvSwitch;
5801 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5803 return 0;
5806 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5808 * SendEventAck - Send EventAck request to MPT adapter.
5809 * @ioc: Pointer to MPT_ADAPTER structure
5810 * @evnp: Pointer to original EventNotification request
5812 static int
5813 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5815 EventAck_t *pAck;
5817 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5818 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5819 ioc->name,__func__));
5820 return -1;
5823 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
5825 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5826 pAck->ChainOffset = 0;
5827 pAck->Reserved[0] = pAck->Reserved[1] = 0;
5828 pAck->MsgFlags = 0;
5829 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5830 pAck->Event = evnp->Event;
5831 pAck->EventContext = evnp->EventContext;
5833 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5835 return 0;
5838 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5840 * mpt_config - Generic function to issue config message
5841 * @ioc: Pointer to an adapter structure
5842 * @pCfg: Pointer to a configuration structure. Struct contains
5843 * action, page address, direction, physical address
5844 * and pointer to a configuration page header
5845 * Page header is updated.
5847 * Returns 0 for success
5848 * -EPERM if not allowed due to ISR context
5849 * -EAGAIN if no msg frames currently available
5850 * -EFAULT for non-successful reply or no reply (timeout)
5853 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5855 Config_t *pReq;
5856 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5857 MPT_FRAME_HDR *mf;
5858 unsigned long flags;
5859 int ii, rc;
5860 int flagsLength;
5861 int in_isr;
5863 /* Prevent calling wait_event() (below), if caller happens
5864 * to be in ISR context, because that is fatal!
5866 in_isr = in_interrupt();
5867 if (in_isr) {
5868 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5869 ioc->name));
5870 return -EPERM;
5873 /* Get and Populate a free Frame
5875 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5876 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5877 ioc->name));
5878 return -EAGAIN;
5880 pReq = (Config_t *)mf;
5881 pReq->Action = pCfg->action;
5882 pReq->Reserved = 0;
5883 pReq->ChainOffset = 0;
5884 pReq->Function = MPI_FUNCTION_CONFIG;
5886 /* Assume page type is not extended and clear "reserved" fields. */
5887 pReq->ExtPageLength = 0;
5888 pReq->ExtPageType = 0;
5889 pReq->MsgFlags = 0;
5891 for (ii=0; ii < 8; ii++)
5892 pReq->Reserved2[ii] = 0;
5894 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5895 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5896 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5897 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5899 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5900 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5901 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5902 pReq->ExtPageType = pExtHdr->ExtPageType;
5903 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5905 /* Page Length must be treated as a reserved field for the extended header. */
5906 pReq->Header.PageLength = 0;
5909 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5911 /* Add a SGE to the config request.
5913 if (pCfg->dir)
5914 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5915 else
5916 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5918 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5919 flagsLength |= pExtHdr->ExtPageLength * 4;
5921 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5922 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5924 else {
5925 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5927 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5928 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5931 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5933 /* Append pCfg pointer to end of mf
5935 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5937 /* Initalize the timer
5939 init_timer_on_stack(&pCfg->timer);
5940 pCfg->timer.data = (unsigned long) ioc;
5941 pCfg->timer.function = mpt_timer_expired;
5942 pCfg->wait_done = 0;
5944 /* Set the timer; ensure 10 second minimum */
5945 if (pCfg->timeout < 10)
5946 pCfg->timer.expires = jiffies + HZ*10;
5947 else
5948 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5950 /* Add to end of Q, set timer and then issue this command */
5951 spin_lock_irqsave(&ioc->FreeQlock, flags);
5952 list_add_tail(&pCfg->linkage, &ioc->configQ);
5953 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5955 add_timer(&pCfg->timer);
5956 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5957 wait_event(mpt_waitq, pCfg->wait_done);
5959 /* mf has been freed - do not access */
5961 rc = pCfg->status;
5963 return rc;
5966 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5968 * mpt_timer_expired - Callback for timer process.
5969 * Used only internal config functionality.
5970 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5972 static void
5973 mpt_timer_expired(unsigned long data)
5975 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5977 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
5979 /* Perform a FW reload */
5980 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5981 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5983 /* No more processing.
5984 * Hard reset clean-up will wake up
5985 * process and free all resources.
5987 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
5989 return;
5992 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5994 * mpt_ioc_reset - Base cleanup for hard reset
5995 * @ioc: Pointer to the adapter structure
5996 * @reset_phase: Indicates pre- or post-reset functionality
5998 * Remark: Frees resources with internally generated commands.
6000 static int
6001 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
6003 CONFIGPARMS *pCfg;
6004 unsigned long flags;
6006 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6007 ": IOC %s_reset routed to MPT base driver!\n",
6008 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
6009 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
6011 if (reset_phase == MPT_IOC_SETUP_RESET) {
6013 } else if (reset_phase == MPT_IOC_PRE_RESET) {
6014 /* If the internal config Q is not empty -
6015 * delete timer. MF resources will be freed when
6016 * the FIFO's are primed.
6018 spin_lock_irqsave(&ioc->FreeQlock, flags);
6019 list_for_each_entry(pCfg, &ioc->configQ, linkage)
6020 del_timer(&pCfg->timer);
6021 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
6023 } else {
6024 CONFIGPARMS *pNext;
6026 /* Search the configQ for internal commands.
6027 * Flush the Q, and wake up all suspended threads.
6029 spin_lock_irqsave(&ioc->FreeQlock, flags);
6030 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
6031 list_del(&pCfg->linkage);
6033 pCfg->status = MPT_CONFIG_ERROR;
6034 pCfg->wait_done = 1;
6035 wake_up(&mpt_waitq);
6037 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
6040 return 1; /* currently means nothing really */
6044 #ifdef CONFIG_PROC_FS /* { */
6045 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6047 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6051 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6053 * Returns 0 for success, non-zero for failure.
6055 static int
6056 procmpt_create(void)
6058 struct proc_dir_entry *ent;
6060 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6061 if (mpt_proc_root_dir == NULL)
6062 return -ENOTDIR;
6064 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6065 if (ent)
6066 ent->read_proc = procmpt_summary_read;
6068 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6069 if (ent)
6070 ent->read_proc = procmpt_version_read;
6072 return 0;
6075 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6077 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6079 * Returns 0 for success, non-zero for failure.
6081 static void
6082 procmpt_destroy(void)
6084 remove_proc_entry("version", mpt_proc_root_dir);
6085 remove_proc_entry("summary", mpt_proc_root_dir);
6086 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6089 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6091 * procmpt_summary_read - Handle read request of a summary file
6092 * @buf: Pointer to area to write information
6093 * @start: Pointer to start pointer
6094 * @offset: Offset to start writing
6095 * @request: Amount of read data requested
6096 * @eof: Pointer to EOF integer
6097 * @data: Pointer
6099 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6100 * Returns number of characters written to process performing the read.
6102 static int
6103 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6105 MPT_ADAPTER *ioc;
6106 char *out = buf;
6107 int len;
6109 if (data) {
6110 int more = 0;
6112 ioc = data;
6113 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6115 out += more;
6116 } else {
6117 list_for_each_entry(ioc, &ioc_list, list) {
6118 int more = 0;
6120 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6122 out += more;
6123 if ((out-buf) >= request)
6124 break;
6128 len = out - buf;
6130 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6135 * procmpt_version_read - Handle read request from /proc/mpt/version.
6136 * @buf: Pointer to area to write information
6137 * @start: Pointer to start pointer
6138 * @offset: Offset to start writing
6139 * @request: Amount of read data requested
6140 * @eof: Pointer to EOF integer
6141 * @data: Pointer
6143 * Returns number of characters written to process performing the read.
6145 static int
6146 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6148 u8 cb_idx;
6149 int scsi, fc, sas, lan, ctl, targ, dmp;
6150 char *drvname;
6151 int len;
6153 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6154 len += sprintf(buf+len, " Fusion MPT base driver\n");
6156 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6157 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6158 drvname = NULL;
6159 if (MptCallbacks[cb_idx]) {
6160 switch (MptDriverClass[cb_idx]) {
6161 case MPTSPI_DRIVER:
6162 if (!scsi++) drvname = "SPI host";
6163 break;
6164 case MPTFC_DRIVER:
6165 if (!fc++) drvname = "FC host";
6166 break;
6167 case MPTSAS_DRIVER:
6168 if (!sas++) drvname = "SAS host";
6169 break;
6170 case MPTLAN_DRIVER:
6171 if (!lan++) drvname = "LAN";
6172 break;
6173 case MPTSTM_DRIVER:
6174 if (!targ++) drvname = "SCSI target";
6175 break;
6176 case MPTCTL_DRIVER:
6177 if (!ctl++) drvname = "ioctl";
6178 break;
6181 if (drvname)
6182 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
6186 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6189 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6191 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6192 * @buf: Pointer to area to write information
6193 * @start: Pointer to start pointer
6194 * @offset: Offset to start writing
6195 * @request: Amount of read data requested
6196 * @eof: Pointer to EOF integer
6197 * @data: Pointer
6199 * Returns number of characters written to process performing the read.
6201 static int
6202 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6204 MPT_ADAPTER *ioc = data;
6205 int len;
6206 char expVer[32];
6207 int sz;
6208 int p;
6210 mpt_get_fw_exp_ver(expVer, ioc);
6212 len = sprintf(buf, "%s:", ioc->name);
6213 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6214 len += sprintf(buf+len, " (f/w download boot flag set)");
6215 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6216 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6218 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
6219 ioc->facts.ProductID,
6220 ioc->prod_name);
6221 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6222 if (ioc->facts.FWImageSize)
6223 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6224 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6225 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6226 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
6228 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
6229 ioc->facts.CurrentHostMfaHighAddr);
6230 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
6231 ioc->facts.CurrentSenseBufferHighAddr);
6233 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6234 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6236 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6237 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6239 * Rounding UP to nearest 4-kB boundary here...
6241 sz = (ioc->req_sz * ioc->req_depth) + 128;
6242 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6243 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6244 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6245 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6246 4*ioc->facts.RequestFrameSize,
6247 ioc->facts.GlobalCredits);
6249 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
6250 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6251 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6252 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6253 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6254 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6255 ioc->facts.CurReplyFrameSize,
6256 ioc->facts.ReplyQueueDepth);
6258 len += sprintf(buf+len, " MaxDevices = %d\n",
6259 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6260 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6262 /* per-port info */
6263 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6264 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
6265 p+1,
6266 ioc->facts.NumberOfPorts);
6267 if (ioc->bus_type == FC) {
6268 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6269 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6270 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6271 a[5], a[4], a[3], a[2], a[1], a[0]);
6273 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
6274 ioc->fc_port_page0[p].WWNN.High,
6275 ioc->fc_port_page0[p].WWNN.Low,
6276 ioc->fc_port_page0[p].WWPN.High,
6277 ioc->fc_port_page0[p].WWPN.Low);
6281 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6284 #endif /* CONFIG_PROC_FS } */
6286 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6287 static void
6288 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6290 buf[0] ='\0';
6291 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6292 sprintf(buf, " (Exp %02d%02d)",
6293 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6294 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6296 /* insider hack! */
6297 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6298 strcat(buf, " [MDBG]");
6302 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6304 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6305 * @ioc: Pointer to MPT_ADAPTER structure
6306 * @buffer: Pointer to buffer where IOC summary info should be written
6307 * @size: Pointer to number of bytes we wrote (set by this routine)
6308 * @len: Offset at which to start writing in buffer
6309 * @showlan: Display LAN stuff?
6311 * This routine writes (english readable) ASCII text, which represents
6312 * a summary of IOC information, to a buffer.
6314 void
6315 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6317 char expVer[32];
6318 int y;
6320 mpt_get_fw_exp_ver(expVer, ioc);
6323 * Shorter summary of attached ioc's...
6325 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6326 ioc->name,
6327 ioc->prod_name,
6328 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6329 ioc->facts.FWVersion.Word,
6330 expVer,
6331 ioc->facts.NumberOfPorts,
6332 ioc->req_depth);
6334 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6335 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6336 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6337 a[5], a[4], a[3], a[2], a[1], a[0]);
6340 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6342 if (!ioc->active)
6343 y += sprintf(buffer+len+y, " (disabled)");
6345 y += sprintf(buffer+len+y, "\n");
6347 *size = y;
6352 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6353 * the kernel
6354 * @ioc: Pointer to MPT_ADAPTER structure
6357 void
6358 mpt_halt_firmware(MPT_ADAPTER *ioc)
6360 u32 ioc_raw_state;
6362 ioc_raw_state = mpt_GetIocState(ioc, 0);
6364 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6365 printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6366 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6367 panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6368 ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6369 } else {
6370 CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6371 panic("%s: Firmware is halted due to command timeout\n",
6372 ioc->name);
6375 EXPORT_SYMBOL(mpt_halt_firmware);
6377 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6379 * Reset Handling
6381 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6383 * mpt_HardResetHandler - Generic reset handler
6384 * @ioc: Pointer to MPT_ADAPTER structure
6385 * @sleepFlag: Indicates if sleep or schedule must be called.
6387 * Issues SCSI Task Management call based on input arg values.
6388 * If TaskMgmt fails, returns associated SCSI request.
6390 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6391 * or a non-interrupt thread. In the former, must not call schedule().
6393 * Note: A return of -1 is a FATAL error case, as it means a
6394 * FW reload/initialization failed.
6396 * Returns 0 for SUCCESS or -1 if FAILED.
6399 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6401 int rc;
6402 unsigned long flags;
6404 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6405 #ifdef MFCNT
6406 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6407 printk("MF count 0x%x !\n", ioc->mfcnt);
6408 #endif
6409 if (mpt_fwfault_debug)
6410 mpt_halt_firmware(ioc);
6412 /* Reset the adapter. Prevent more than 1 call to
6413 * mpt_do_ioc_recovery at any instant in time.
6415 spin_lock_irqsave(&ioc->diagLock, flags);
6416 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
6417 spin_unlock_irqrestore(&ioc->diagLock, flags);
6418 return 0;
6419 } else {
6420 ioc->diagPending = 1;
6422 spin_unlock_irqrestore(&ioc->diagLock, flags);
6424 /* FIXME: If do_ioc_recovery fails, repeat....
6427 /* The SCSI driver needs to adjust timeouts on all current
6428 * commands prior to the diagnostic reset being issued.
6429 * Prevents timeouts occurring during a diagnostic reset...very bad.
6430 * For all other protocol drivers, this is a no-op.
6433 u8 cb_idx;
6434 int r = 0;
6436 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6437 if (MptResetHandlers[cb_idx]) {
6438 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
6439 ioc->name, cb_idx));
6440 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6441 if (ioc->alt_ioc) {
6442 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
6443 ioc->name, ioc->alt_ioc->name, cb_idx));
6444 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
6450 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
6451 printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
6453 ioc->reload_fw = 0;
6454 if (ioc->alt_ioc)
6455 ioc->alt_ioc->reload_fw = 0;
6457 spin_lock_irqsave(&ioc->diagLock, flags);
6458 ioc->diagPending = 0;
6459 if (ioc->alt_ioc)
6460 ioc->alt_ioc->diagPending = 0;
6461 spin_unlock_irqrestore(&ioc->diagLock, flags);
6463 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
6465 return rc;
6468 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6469 static void
6470 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
6472 char *ds = NULL;
6474 switch(event) {
6475 case MPI_EVENT_NONE:
6476 ds = "None";
6477 break;
6478 case MPI_EVENT_LOG_DATA:
6479 ds = "Log Data";
6480 break;
6481 case MPI_EVENT_STATE_CHANGE:
6482 ds = "State Change";
6483 break;
6484 case MPI_EVENT_UNIT_ATTENTION:
6485 ds = "Unit Attention";
6486 break;
6487 case MPI_EVENT_IOC_BUS_RESET:
6488 ds = "IOC Bus Reset";
6489 break;
6490 case MPI_EVENT_EXT_BUS_RESET:
6491 ds = "External Bus Reset";
6492 break;
6493 case MPI_EVENT_RESCAN:
6494 ds = "Bus Rescan Event";
6495 break;
6496 case MPI_EVENT_LINK_STATUS_CHANGE:
6497 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
6498 ds = "Link Status(FAILURE) Change";
6499 else
6500 ds = "Link Status(ACTIVE) Change";
6501 break;
6502 case MPI_EVENT_LOOP_STATE_CHANGE:
6503 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
6504 ds = "Loop State(LIP) Change";
6505 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
6506 ds = "Loop State(LPE) Change"; /* ??? */
6507 else
6508 ds = "Loop State(LPB) Change"; /* ??? */
6509 break;
6510 case MPI_EVENT_LOGOUT:
6511 ds = "Logout";
6512 break;
6513 case MPI_EVENT_EVENT_CHANGE:
6514 if (evData0)
6515 ds = "Events ON";
6516 else
6517 ds = "Events OFF";
6518 break;
6519 case MPI_EVENT_INTEGRATED_RAID:
6521 u8 ReasonCode = (u8)(evData0 >> 16);
6522 switch (ReasonCode) {
6523 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
6524 ds = "Integrated Raid: Volume Created";
6525 break;
6526 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
6527 ds = "Integrated Raid: Volume Deleted";
6528 break;
6529 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
6530 ds = "Integrated Raid: Volume Settings Changed";
6531 break;
6532 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
6533 ds = "Integrated Raid: Volume Status Changed";
6534 break;
6535 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
6536 ds = "Integrated Raid: Volume Physdisk Changed";
6537 break;
6538 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
6539 ds = "Integrated Raid: Physdisk Created";
6540 break;
6541 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
6542 ds = "Integrated Raid: Physdisk Deleted";
6543 break;
6544 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
6545 ds = "Integrated Raid: Physdisk Settings Changed";
6546 break;
6547 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
6548 ds = "Integrated Raid: Physdisk Status Changed";
6549 break;
6550 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
6551 ds = "Integrated Raid: Domain Validation Needed";
6552 break;
6553 case MPI_EVENT_RAID_RC_SMART_DATA :
6554 ds = "Integrated Raid; Smart Data";
6555 break;
6556 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
6557 ds = "Integrated Raid: Replace Action Started";
6558 break;
6559 default:
6560 ds = "Integrated Raid";
6561 break;
6563 break;
6565 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
6566 ds = "SCSI Device Status Change";
6567 break;
6568 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
6570 u8 id = (u8)(evData0);
6571 u8 channel = (u8)(evData0 >> 8);
6572 u8 ReasonCode = (u8)(evData0 >> 16);
6573 switch (ReasonCode) {
6574 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
6575 snprintf(evStr, EVENT_DESCR_STR_SZ,
6576 "SAS Device Status Change: Added: "
6577 "id=%d channel=%d", id, channel);
6578 break;
6579 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
6580 snprintf(evStr, EVENT_DESCR_STR_SZ,
6581 "SAS Device Status Change: Deleted: "
6582 "id=%d channel=%d", id, channel);
6583 break;
6584 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
6585 snprintf(evStr, EVENT_DESCR_STR_SZ,
6586 "SAS Device Status Change: SMART Data: "
6587 "id=%d channel=%d", id, channel);
6588 break;
6589 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
6590 snprintf(evStr, EVENT_DESCR_STR_SZ,
6591 "SAS Device Status Change: No Persistancy: "
6592 "id=%d channel=%d", id, channel);
6593 break;
6594 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
6595 snprintf(evStr, EVENT_DESCR_STR_SZ,
6596 "SAS Device Status Change: Unsupported Device "
6597 "Discovered : id=%d channel=%d", id, channel);
6598 break;
6599 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
6600 snprintf(evStr, EVENT_DESCR_STR_SZ,
6601 "SAS Device Status Change: Internal Device "
6602 "Reset : id=%d channel=%d", id, channel);
6603 break;
6604 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
6605 snprintf(evStr, EVENT_DESCR_STR_SZ,
6606 "SAS Device Status Change: Internal Task "
6607 "Abort : id=%d channel=%d", id, channel);
6608 break;
6609 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
6610 snprintf(evStr, EVENT_DESCR_STR_SZ,
6611 "SAS Device Status Change: Internal Abort "
6612 "Task Set : id=%d channel=%d", id, channel);
6613 break;
6614 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
6615 snprintf(evStr, EVENT_DESCR_STR_SZ,
6616 "SAS Device Status Change: Internal Clear "
6617 "Task Set : id=%d channel=%d", id, channel);
6618 break;
6619 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
6620 snprintf(evStr, EVENT_DESCR_STR_SZ,
6621 "SAS Device Status Change: Internal Query "
6622 "Task : id=%d channel=%d", id, channel);
6623 break;
6624 default:
6625 snprintf(evStr, EVENT_DESCR_STR_SZ,
6626 "SAS Device Status Change: Unknown: "
6627 "id=%d channel=%d", id, channel);
6628 break;
6630 break;
6632 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
6633 ds = "Bus Timer Expired";
6634 break;
6635 case MPI_EVENT_QUEUE_FULL:
6637 u16 curr_depth = (u16)(evData0 >> 16);
6638 u8 channel = (u8)(evData0 >> 8);
6639 u8 id = (u8)(evData0);
6641 snprintf(evStr, EVENT_DESCR_STR_SZ,
6642 "Queue Full: channel=%d id=%d depth=%d",
6643 channel, id, curr_depth);
6644 break;
6646 case MPI_EVENT_SAS_SES:
6647 ds = "SAS SES Event";
6648 break;
6649 case MPI_EVENT_PERSISTENT_TABLE_FULL:
6650 ds = "Persistent Table Full";
6651 break;
6652 case MPI_EVENT_SAS_PHY_LINK_STATUS:
6654 u8 LinkRates = (u8)(evData0 >> 8);
6655 u8 PhyNumber = (u8)(evData0);
6656 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
6657 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
6658 switch (LinkRates) {
6659 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
6660 snprintf(evStr, EVENT_DESCR_STR_SZ,
6661 "SAS PHY Link Status: Phy=%d:"
6662 " Rate Unknown",PhyNumber);
6663 break;
6664 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
6665 snprintf(evStr, EVENT_DESCR_STR_SZ,
6666 "SAS PHY Link Status: Phy=%d:"
6667 " Phy Disabled",PhyNumber);
6668 break;
6669 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
6670 snprintf(evStr, EVENT_DESCR_STR_SZ,
6671 "SAS PHY Link Status: Phy=%d:"
6672 " Failed Speed Nego",PhyNumber);
6673 break;
6674 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
6675 snprintf(evStr, EVENT_DESCR_STR_SZ,
6676 "SAS PHY Link Status: Phy=%d:"
6677 " Sata OOB Completed",PhyNumber);
6678 break;
6679 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
6680 snprintf(evStr, EVENT_DESCR_STR_SZ,
6681 "SAS PHY Link Status: Phy=%d:"
6682 " Rate 1.5 Gbps",PhyNumber);
6683 break;
6684 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
6685 snprintf(evStr, EVENT_DESCR_STR_SZ,
6686 "SAS PHY Link Status: Phy=%d:"
6687 " Rate 3.0 Gpbs",PhyNumber);
6688 break;
6689 default:
6690 snprintf(evStr, EVENT_DESCR_STR_SZ,
6691 "SAS PHY Link Status: Phy=%d", PhyNumber);
6692 break;
6694 break;
6696 case MPI_EVENT_SAS_DISCOVERY_ERROR:
6697 ds = "SAS Discovery Error";
6698 break;
6699 case MPI_EVENT_IR_RESYNC_UPDATE:
6701 u8 resync_complete = (u8)(evData0 >> 16);
6702 snprintf(evStr, EVENT_DESCR_STR_SZ,
6703 "IR Resync Update: Complete = %d:",resync_complete);
6704 break;
6706 case MPI_EVENT_IR2:
6708 u8 ReasonCode = (u8)(evData0 >> 16);
6709 switch (ReasonCode) {
6710 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
6711 ds = "IR2: LD State Changed";
6712 break;
6713 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
6714 ds = "IR2: PD State Changed";
6715 break;
6716 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
6717 ds = "IR2: Bad Block Table Full";
6718 break;
6719 case MPI_EVENT_IR2_RC_PD_INSERTED:
6720 ds = "IR2: PD Inserted";
6721 break;
6722 case MPI_EVENT_IR2_RC_PD_REMOVED:
6723 ds = "IR2: PD Removed";
6724 break;
6725 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
6726 ds = "IR2: Foreign CFG Detected";
6727 break;
6728 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
6729 ds = "IR2: Rebuild Medium Error";
6730 break;
6731 default:
6732 ds = "IR2";
6733 break;
6735 break;
6737 case MPI_EVENT_SAS_DISCOVERY:
6739 if (evData0)
6740 ds = "SAS Discovery: Start";
6741 else
6742 ds = "SAS Discovery: Stop";
6743 break;
6745 case MPI_EVENT_LOG_ENTRY_ADDED:
6746 ds = "SAS Log Entry Added";
6747 break;
6749 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
6751 u8 phy_num = (u8)(evData0);
6752 u8 port_num = (u8)(evData0 >> 8);
6753 u8 port_width = (u8)(evData0 >> 16);
6754 u8 primative = (u8)(evData0 >> 24);
6755 snprintf(evStr, EVENT_DESCR_STR_SZ,
6756 "SAS Broadcase Primative: phy=%d port=%d "
6757 "width=%d primative=0x%02x",
6758 phy_num, port_num, port_width, primative);
6759 break;
6762 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
6764 u8 reason = (u8)(evData0);
6765 u8 port_num = (u8)(evData0 >> 8);
6766 u16 handle = le16_to_cpu(evData0 >> 16);
6768 snprintf(evStr, EVENT_DESCR_STR_SZ,
6769 "SAS Initiator Device Status Change: reason=0x%02x "
6770 "port=%d handle=0x%04x",
6771 reason, port_num, handle);
6772 break;
6775 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6777 u8 max_init = (u8)(evData0);
6778 u8 current_init = (u8)(evData0 >> 8);
6780 snprintf(evStr, EVENT_DESCR_STR_SZ,
6781 "SAS Initiator Device Table Overflow: max initiators=%02d "
6782 "current initators=%02d",
6783 max_init, current_init);
6784 break;
6786 case MPI_EVENT_SAS_SMP_ERROR:
6788 u8 status = (u8)(evData0);
6789 u8 port_num = (u8)(evData0 >> 8);
6790 u8 result = (u8)(evData0 >> 16);
6792 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6793 snprintf(evStr, EVENT_DESCR_STR_SZ,
6794 "SAS SMP Error: port=%d result=0x%02x",
6795 port_num, result);
6796 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6797 snprintf(evStr, EVENT_DESCR_STR_SZ,
6798 "SAS SMP Error: port=%d : CRC Error",
6799 port_num);
6800 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6801 snprintf(evStr, EVENT_DESCR_STR_SZ,
6802 "SAS SMP Error: port=%d : Timeout",
6803 port_num);
6804 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6805 snprintf(evStr, EVENT_DESCR_STR_SZ,
6806 "SAS SMP Error: port=%d : No Destination",
6807 port_num);
6808 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6809 snprintf(evStr, EVENT_DESCR_STR_SZ,
6810 "SAS SMP Error: port=%d : Bad Destination",
6811 port_num);
6812 else
6813 snprintf(evStr, EVENT_DESCR_STR_SZ,
6814 "SAS SMP Error: port=%d : status=0x%02x",
6815 port_num, status);
6816 break;
6820 * MPT base "custom" events may be added here...
6822 default:
6823 ds = "Unknown";
6824 break;
6826 if (ds)
6827 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6830 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6832 * ProcessEventNotification - Route EventNotificationReply to all event handlers
6833 * @ioc: Pointer to MPT_ADAPTER structure
6834 * @pEventReply: Pointer to EventNotification reply frame
6835 * @evHandlers: Pointer to integer, number of event handlers
6837 * Routes a received EventNotificationReply to all currently registered
6838 * event handlers.
6839 * Returns sum of event handlers return values.
6841 static int
6842 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6844 u16 evDataLen;
6845 u32 evData0 = 0;
6846 // u32 evCtx;
6847 int ii;
6848 u8 cb_idx;
6849 int r = 0;
6850 int handlers = 0;
6851 char evStr[EVENT_DESCR_STR_SZ];
6852 u8 event;
6855 * Do platform normalization of values
6857 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6858 // evCtx = le32_to_cpu(pEventReply->EventContext);
6859 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6860 if (evDataLen) {
6861 evData0 = le32_to_cpu(pEventReply->Data[0]);
6864 EventDescriptionStr(event, evData0, evStr);
6865 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
6866 ioc->name,
6867 event,
6868 evStr));
6870 #ifdef CONFIG_FUSION_LOGGING
6871 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6872 ": Event data:\n", ioc->name));
6873 for (ii = 0; ii < evDataLen; ii++)
6874 devtverboseprintk(ioc, printk(" %08x",
6875 le32_to_cpu(pEventReply->Data[ii])));
6876 devtverboseprintk(ioc, printk("\n"));
6877 #endif
6880 * Do general / base driver event processing
6882 switch(event) {
6883 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6884 if (evDataLen) {
6885 u8 evState = evData0 & 0xFF;
6887 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6889 /* Update EventState field in cached IocFacts */
6890 if (ioc->facts.Function) {
6891 ioc->facts.EventState = evState;
6894 break;
6895 case MPI_EVENT_INTEGRATED_RAID:
6896 mptbase_raid_process_event_data(ioc,
6897 (MpiEventDataRaid_t *)pEventReply->Data);
6898 break;
6899 default:
6900 break;
6904 * Should this event be logged? Events are written sequentially.
6905 * When buffer is full, start again at the top.
6907 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6908 int idx;
6910 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6912 ioc->events[idx].event = event;
6913 ioc->events[idx].eventContext = ioc->eventContext;
6915 for (ii = 0; ii < 2; ii++) {
6916 if (ii < evDataLen)
6917 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6918 else
6919 ioc->events[idx].data[ii] = 0;
6922 ioc->eventContext++;
6927 * Call each currently registered protocol event handler.
6929 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6930 if (MptEvHandlers[cb_idx]) {
6931 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
6932 ioc->name, cb_idx));
6933 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
6934 handlers++;
6937 /* FIXME? Examine results here? */
6940 * If needed, send (a single) EventAck.
6942 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6943 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6944 "EventAck required\n",ioc->name));
6945 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6946 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
6947 ioc->name, ii));
6951 *evHandlers = handlers;
6952 return r;
6955 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6957 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6958 * @ioc: Pointer to MPT_ADAPTER structure
6959 * @log_info: U32 LogInfo reply word from the IOC
6961 * Refer to lsi/mpi_log_fc.h.
6963 static void
6964 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6966 char *desc = "unknown";
6968 switch (log_info & 0xFF000000) {
6969 case MPI_IOCLOGINFO_FC_INIT_BASE:
6970 desc = "FCP Initiator";
6971 break;
6972 case MPI_IOCLOGINFO_FC_TARGET_BASE:
6973 desc = "FCP Target";
6974 break;
6975 case MPI_IOCLOGINFO_FC_LAN_BASE:
6976 desc = "LAN";
6977 break;
6978 case MPI_IOCLOGINFO_FC_MSG_BASE:
6979 desc = "MPI Message Layer";
6980 break;
6981 case MPI_IOCLOGINFO_FC_LINK_BASE:
6982 desc = "FC Link";
6983 break;
6984 case MPI_IOCLOGINFO_FC_CTX_BASE:
6985 desc = "Context Manager";
6986 break;
6987 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
6988 desc = "Invalid Field Offset";
6989 break;
6990 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
6991 desc = "State Change Info";
6992 break;
6995 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6996 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
6999 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7001 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7002 * @ioc: Pointer to MPT_ADAPTER structure
7003 * @log_info: U32 LogInfo word from the IOC
7005 * Refer to lsi/sp_log.h.
7007 static void
7008 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7010 u32 info = log_info & 0x00FF0000;
7011 char *desc = "unknown";
7013 switch (info) {
7014 case 0x00010000:
7015 desc = "bug! MID not found";
7016 if (ioc->reload_fw == 0)
7017 ioc->reload_fw++;
7018 break;
7020 case 0x00020000:
7021 desc = "Parity Error";
7022 break;
7024 case 0x00030000:
7025 desc = "ASYNC Outbound Overrun";
7026 break;
7028 case 0x00040000:
7029 desc = "SYNC Offset Error";
7030 break;
7032 case 0x00050000:
7033 desc = "BM Change";
7034 break;
7036 case 0x00060000:
7037 desc = "Msg In Overflow";
7038 break;
7040 case 0x00070000:
7041 desc = "DMA Error";
7042 break;
7044 case 0x00080000:
7045 desc = "Outbound DMA Overrun";
7046 break;
7048 case 0x00090000:
7049 desc = "Task Management";
7050 break;
7052 case 0x000A0000:
7053 desc = "Device Problem";
7054 break;
7056 case 0x000B0000:
7057 desc = "Invalid Phase Change";
7058 break;
7060 case 0x000C0000:
7061 desc = "Untagged Table Size";
7062 break;
7066 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7069 /* strings for sas loginfo */
7070 static char *originator_str[] = {
7071 "IOP", /* 00h */
7072 "PL", /* 01h */
7073 "IR" /* 02h */
7075 static char *iop_code_str[] = {
7076 NULL, /* 00h */
7077 "Invalid SAS Address", /* 01h */
7078 NULL, /* 02h */
7079 "Invalid Page", /* 03h */
7080 "Diag Message Error", /* 04h */
7081 "Task Terminated", /* 05h */
7082 "Enclosure Management", /* 06h */
7083 "Target Mode" /* 07h */
7085 static char *pl_code_str[] = {
7086 NULL, /* 00h */
7087 "Open Failure", /* 01h */
7088 "Invalid Scatter Gather List", /* 02h */
7089 "Wrong Relative Offset or Frame Length", /* 03h */
7090 "Frame Transfer Error", /* 04h */
7091 "Transmit Frame Connected Low", /* 05h */
7092 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7093 "SATA Read Log Receive Data Error", /* 07h */
7094 "SATA NCQ Fail All Commands After Error", /* 08h */
7095 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7096 "Receive Frame Invalid Message", /* 0Ah */
7097 "Receive Context Message Valid Error", /* 0Bh */
7098 "Receive Frame Current Frame Error", /* 0Ch */
7099 "SATA Link Down", /* 0Dh */
7100 "Discovery SATA Init W IOS", /* 0Eh */
7101 "Config Invalid Page", /* 0Fh */
7102 "Discovery SATA Init Timeout", /* 10h */
7103 "Reset", /* 11h */
7104 "Abort", /* 12h */
7105 "IO Not Yet Executed", /* 13h */
7106 "IO Executed", /* 14h */
7107 "Persistent Reservation Out Not Affiliation "
7108 "Owner", /* 15h */
7109 "Open Transmit DMA Abort", /* 16h */
7110 "IO Device Missing Delay Retry", /* 17h */
7111 "IO Cancelled Due to Recieve Error", /* 18h */
7112 NULL, /* 19h */
7113 NULL, /* 1Ah */
7114 NULL, /* 1Bh */
7115 NULL, /* 1Ch */
7116 NULL, /* 1Dh */
7117 NULL, /* 1Eh */
7118 NULL, /* 1Fh */
7119 "Enclosure Management" /* 20h */
7121 static char *ir_code_str[] = {
7122 "Raid Action Error", /* 00h */
7123 NULL, /* 00h */
7124 NULL, /* 01h */
7125 NULL, /* 02h */
7126 NULL, /* 03h */
7127 NULL, /* 04h */
7128 NULL, /* 05h */
7129 NULL, /* 06h */
7130 NULL /* 07h */
7132 static char *raid_sub_code_str[] = {
7133 NULL, /* 00h */
7134 "Volume Creation Failed: Data Passed too "
7135 "Large", /* 01h */
7136 "Volume Creation Failed: Duplicate Volumes "
7137 "Attempted", /* 02h */
7138 "Volume Creation Failed: Max Number "
7139 "Supported Volumes Exceeded", /* 03h */
7140 "Volume Creation Failed: DMA Error", /* 04h */
7141 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7142 "Volume Creation Failed: Error Reading "
7143 "MFG Page 4", /* 06h */
7144 "Volume Creation Failed: Creating Internal "
7145 "Structures", /* 07h */
7146 NULL, /* 08h */
7147 NULL, /* 09h */
7148 NULL, /* 0Ah */
7149 NULL, /* 0Bh */
7150 NULL, /* 0Ch */
7151 NULL, /* 0Dh */
7152 NULL, /* 0Eh */
7153 NULL, /* 0Fh */
7154 "Activation failed: Already Active Volume", /* 10h */
7155 "Activation failed: Unsupported Volume Type", /* 11h */
7156 "Activation failed: Too Many Active Volumes", /* 12h */
7157 "Activation failed: Volume ID in Use", /* 13h */
7158 "Activation failed: Reported Failure", /* 14h */
7159 "Activation failed: Importing a Volume", /* 15h */
7160 NULL, /* 16h */
7161 NULL, /* 17h */
7162 NULL, /* 18h */
7163 NULL, /* 19h */
7164 NULL, /* 1Ah */
7165 NULL, /* 1Bh */
7166 NULL, /* 1Ch */
7167 NULL, /* 1Dh */
7168 NULL, /* 1Eh */
7169 NULL, /* 1Fh */
7170 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7171 "Phys Disk failed: Data Passed too Large", /* 21h */
7172 "Phys Disk failed: DMA Error", /* 22h */
7173 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7174 "Phys Disk failed: Creating Phys Disk Config "
7175 "Page", /* 24h */
7176 NULL, /* 25h */
7177 NULL, /* 26h */
7178 NULL, /* 27h */
7179 NULL, /* 28h */
7180 NULL, /* 29h */
7181 NULL, /* 2Ah */
7182 NULL, /* 2Bh */
7183 NULL, /* 2Ch */
7184 NULL, /* 2Dh */
7185 NULL, /* 2Eh */
7186 NULL, /* 2Fh */
7187 "Compatibility Error: IR Disabled", /* 30h */
7188 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7189 "Compatibility Error: Device not Direct Access "
7190 "Device ", /* 32h */
7191 "Compatibility Error: Removable Device Found", /* 33h */
7192 "Compatibility Error: Device SCSI Version not "
7193 "2 or Higher", /* 34h */
7194 "Compatibility Error: SATA Device, 48 BIT LBA "
7195 "not Supported", /* 35h */
7196 "Compatibility Error: Device doesn't have "
7197 "512 Byte Block Sizes", /* 36h */
7198 "Compatibility Error: Volume Type Check Failed", /* 37h */
7199 "Compatibility Error: Volume Type is "
7200 "Unsupported by FW", /* 38h */
7201 "Compatibility Error: Disk Drive too Small for "
7202 "use in Volume", /* 39h */
7203 "Compatibility Error: Phys Disk for Create "
7204 "Volume not Found", /* 3Ah */
7205 "Compatibility Error: Too Many or too Few "
7206 "Disks for Volume Type", /* 3Bh */
7207 "Compatibility Error: Disk stripe Sizes "
7208 "Must be 64KB", /* 3Ch */
7209 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7212 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7214 * mpt_sas_log_info - Log information returned from SAS IOC.
7215 * @ioc: Pointer to MPT_ADAPTER structure
7216 * @log_info: U32 LogInfo reply word from the IOC
7218 * Refer to lsi/mpi_log_sas.h.
7220 static void
7221 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7223 union loginfo_type {
7224 u32 loginfo;
7225 struct {
7226 u32 subcode:16;
7227 u32 code:8;
7228 u32 originator:4;
7229 u32 bus_type:4;
7230 }dw;
7232 union loginfo_type sas_loginfo;
7233 char *originator_desc = NULL;
7234 char *code_desc = NULL;
7235 char *sub_code_desc = NULL;
7237 sas_loginfo.loginfo = log_info;
7238 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7239 (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
7240 return;
7242 originator_desc = originator_str[sas_loginfo.dw.originator];
7244 switch (sas_loginfo.dw.originator) {
7246 case 0: /* IOP */
7247 if (sas_loginfo.dw.code <
7248 ARRAY_SIZE(iop_code_str))
7249 code_desc = iop_code_str[sas_loginfo.dw.code];
7250 break;
7251 case 1: /* PL */
7252 if (sas_loginfo.dw.code <
7253 ARRAY_SIZE(pl_code_str))
7254 code_desc = pl_code_str[sas_loginfo.dw.code];
7255 break;
7256 case 2: /* IR */
7257 if (sas_loginfo.dw.code >=
7258 ARRAY_SIZE(ir_code_str))
7259 break;
7260 code_desc = ir_code_str[sas_loginfo.dw.code];
7261 if (sas_loginfo.dw.subcode >=
7262 ARRAY_SIZE(raid_sub_code_str))
7263 break;
7264 if (sas_loginfo.dw.code == 0)
7265 sub_code_desc =
7266 raid_sub_code_str[sas_loginfo.dw.subcode];
7267 break;
7268 default:
7269 return;
7272 if (sub_code_desc != NULL)
7273 printk(MYIOC_s_INFO_FMT
7274 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7275 " SubCode={%s}\n",
7276 ioc->name, log_info, originator_desc, code_desc,
7277 sub_code_desc);
7278 else if (code_desc != NULL)
7279 printk(MYIOC_s_INFO_FMT
7280 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7281 " SubCode(0x%04x)\n",
7282 ioc->name, log_info, originator_desc, code_desc,
7283 sas_loginfo.dw.subcode);
7284 else
7285 printk(MYIOC_s_INFO_FMT
7286 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7287 " SubCode(0x%04x)\n",
7288 ioc->name, log_info, originator_desc,
7289 sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7292 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7294 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7295 * @ioc: Pointer to MPT_ADAPTER structure
7296 * @ioc_status: U32 IOCStatus word from IOC
7297 * @mf: Pointer to MPT request frame
7299 * Refer to lsi/mpi.h.
7301 static void
7302 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7304 Config_t *pReq = (Config_t *)mf;
7305 char extend_desc[EVENT_DESCR_STR_SZ];
7306 char *desc = NULL;
7307 u32 form;
7308 u8 page_type;
7310 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7311 page_type = pReq->ExtPageType;
7312 else
7313 page_type = pReq->Header.PageType;
7316 * ignore invalid page messages for GET_NEXT_HANDLE
7318 form = le32_to_cpu(pReq->PageAddress);
7319 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7320 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7321 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7322 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7323 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7324 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7325 return;
7327 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7328 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7329 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7330 return;
7333 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7334 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7335 page_type, pReq->Header.PageNumber, pReq->Action, form);
7337 switch (ioc_status) {
7339 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7340 desc = "Config Page Invalid Action";
7341 break;
7343 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7344 desc = "Config Page Invalid Type";
7345 break;
7347 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7348 desc = "Config Page Invalid Page";
7349 break;
7351 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7352 desc = "Config Page Invalid Data";
7353 break;
7355 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7356 desc = "Config Page No Defaults";
7357 break;
7359 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7360 desc = "Config Page Can't Commit";
7361 break;
7364 if (!desc)
7365 return;
7367 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7368 ioc->name, ioc_status, desc, extend_desc));
7372 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7373 * @ioc: Pointer to MPT_ADAPTER structure
7374 * @ioc_status: U32 IOCStatus word from IOC
7375 * @mf: Pointer to MPT request frame
7377 * Refer to lsi/mpi.h.
7379 static void
7380 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7382 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
7383 char *desc = NULL;
7385 switch (status) {
7387 /****************************************************************************/
7388 /* Common IOCStatus values for all replies */
7389 /****************************************************************************/
7391 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
7392 desc = "Invalid Function";
7393 break;
7395 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
7396 desc = "Busy";
7397 break;
7399 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
7400 desc = "Invalid SGL";
7401 break;
7403 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
7404 desc = "Internal Error";
7405 break;
7407 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
7408 desc = "Reserved";
7409 break;
7411 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
7412 desc = "Insufficient Resources";
7413 break;
7415 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
7416 desc = "Invalid Field";
7417 break;
7419 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
7420 desc = "Invalid State";
7421 break;
7423 /****************************************************************************/
7424 /* Config IOCStatus values */
7425 /****************************************************************************/
7427 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7428 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7429 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7430 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7431 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7432 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7433 mpt_iocstatus_info_config(ioc, status, mf);
7434 break;
7436 /****************************************************************************/
7437 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
7438 /* */
7439 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7440 /* */
7441 /****************************************************************************/
7443 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
7444 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
7445 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
7446 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
7447 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
7448 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
7449 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
7450 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
7451 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
7452 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
7453 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
7454 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
7455 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
7456 break;
7458 /****************************************************************************/
7459 /* SCSI Target values */
7460 /****************************************************************************/
7462 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
7463 desc = "Target: Priority IO";
7464 break;
7466 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
7467 desc = "Target: Invalid Port";
7468 break;
7470 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
7471 desc = "Target Invalid IO Index:";
7472 break;
7474 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
7475 desc = "Target: Aborted";
7476 break;
7478 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
7479 desc = "Target: No Conn Retryable";
7480 break;
7482 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
7483 desc = "Target: No Connection";
7484 break;
7486 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
7487 desc = "Target: Transfer Count Mismatch";
7488 break;
7490 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
7491 desc = "Target: STS Data not Sent";
7492 break;
7494 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
7495 desc = "Target: Data Offset Error";
7496 break;
7498 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
7499 desc = "Target: Too Much Write Data";
7500 break;
7502 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
7503 desc = "Target: IU Too Short";
7504 break;
7506 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
7507 desc = "Target: ACK NAK Timeout";
7508 break;
7510 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
7511 desc = "Target: Nak Received";
7512 break;
7514 /****************************************************************************/
7515 /* Fibre Channel Direct Access values */
7516 /****************************************************************************/
7518 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
7519 desc = "FC: Aborted";
7520 break;
7522 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
7523 desc = "FC: RX ID Invalid";
7524 break;
7526 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
7527 desc = "FC: DID Invalid";
7528 break;
7530 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
7531 desc = "FC: Node Logged Out";
7532 break;
7534 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
7535 desc = "FC: Exchange Canceled";
7536 break;
7538 /****************************************************************************/
7539 /* LAN values */
7540 /****************************************************************************/
7542 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
7543 desc = "LAN: Device not Found";
7544 break;
7546 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
7547 desc = "LAN: Device Failure";
7548 break;
7550 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
7551 desc = "LAN: Transmit Error";
7552 break;
7554 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
7555 desc = "LAN: Transmit Aborted";
7556 break;
7558 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
7559 desc = "LAN: Receive Error";
7560 break;
7562 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
7563 desc = "LAN: Receive Aborted";
7564 break;
7566 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
7567 desc = "LAN: Partial Packet";
7568 break;
7570 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
7571 desc = "LAN: Canceled";
7572 break;
7574 /****************************************************************************/
7575 /* Serial Attached SCSI values */
7576 /****************************************************************************/
7578 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
7579 desc = "SAS: SMP Request Failed";
7580 break;
7582 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
7583 desc = "SAS: SMP Data Overrun";
7584 break;
7586 default:
7587 desc = "Others";
7588 break;
7591 if (!desc)
7592 return;
7594 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
7595 ioc->name, status, desc));
7598 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7599 EXPORT_SYMBOL(mpt_attach);
7600 EXPORT_SYMBOL(mpt_detach);
7601 #ifdef CONFIG_PM
7602 EXPORT_SYMBOL(mpt_resume);
7603 EXPORT_SYMBOL(mpt_suspend);
7604 #endif
7605 EXPORT_SYMBOL(ioc_list);
7606 EXPORT_SYMBOL(mpt_register);
7607 EXPORT_SYMBOL(mpt_deregister);
7608 EXPORT_SYMBOL(mpt_event_register);
7609 EXPORT_SYMBOL(mpt_event_deregister);
7610 EXPORT_SYMBOL(mpt_reset_register);
7611 EXPORT_SYMBOL(mpt_reset_deregister);
7612 EXPORT_SYMBOL(mpt_device_driver_register);
7613 EXPORT_SYMBOL(mpt_device_driver_deregister);
7614 EXPORT_SYMBOL(mpt_get_msg_frame);
7615 EXPORT_SYMBOL(mpt_put_msg_frame);
7616 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
7617 EXPORT_SYMBOL(mpt_free_msg_frame);
7618 EXPORT_SYMBOL(mpt_add_sge);
7619 EXPORT_SYMBOL(mpt_send_handshake_request);
7620 EXPORT_SYMBOL(mpt_verify_adapter);
7621 EXPORT_SYMBOL(mpt_GetIocState);
7622 EXPORT_SYMBOL(mpt_print_ioc_summary);
7623 EXPORT_SYMBOL(mpt_HardResetHandler);
7624 EXPORT_SYMBOL(mpt_config);
7625 EXPORT_SYMBOL(mpt_findImVolumes);
7626 EXPORT_SYMBOL(mpt_alloc_fw_memory);
7627 EXPORT_SYMBOL(mpt_free_fw_memory);
7628 EXPORT_SYMBOL(mptbase_sas_persist_operation);
7629 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
7631 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7633 * fusion_init - Fusion MPT base driver initialization routine.
7635 * Returns 0 for success, non-zero for failure.
7637 static int __init
7638 fusion_init(void)
7640 u8 cb_idx;
7642 show_mptmod_ver(my_NAME, my_VERSION);
7643 printk(KERN_INFO COPYRIGHT "\n");
7645 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
7646 MptCallbacks[cb_idx] = NULL;
7647 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
7648 MptEvHandlers[cb_idx] = NULL;
7649 MptResetHandlers[cb_idx] = NULL;
7652 /* Register ourselves (mptbase) in order to facilitate
7653 * EventNotification handling.
7655 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
7657 /* Register for hard reset handling callbacks.
7659 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
7661 #ifdef CONFIG_PROC_FS
7662 (void) procmpt_create();
7663 #endif
7664 return 0;
7667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7669 * fusion_exit - Perform driver unload cleanup.
7671 * This routine frees all resources associated with each MPT adapter
7672 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
7674 static void __exit
7675 fusion_exit(void)
7678 mpt_reset_deregister(mpt_base_index);
7680 #ifdef CONFIG_PROC_FS
7681 procmpt_destroy();
7682 #endif
7685 module_init(fusion_init);
7686 module_exit(fusion_exit);