Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6/mini2440.git] / drivers / message / fusion / mptbase.c
blob5d0ba4f5924ca5bf34547dabcab8cda8cbf2ff4a
1 /*
2 * linux/drivers/message/fusion/mptbase.c
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
5 * For use with LSI PCI chip/adapter(s)
6 * running LSI Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2008 LSI Corporation
9 * (mailto:DL-MPTFusionLinux@lsi.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 NO WARRANTY
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
49 #include <linux/kernel.h>
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/types.h>
55 #include <linux/pci.h>
56 #include <linux/kdev_t.h>
57 #include <linux/blkdev.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
60 #include <linux/dma-mapping.h>
61 #include <asm/io.h>
62 #ifdef CONFIG_MTRR
63 #include <asm/mtrr.h>
64 #endif
66 #include "mptbase.h"
67 #include "lsi/mpi_log_fc.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT base driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptbase"
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION);
80 * cmd line parameters
83 static int mpt_msi_enable_spi;
84 module_param(mpt_msi_enable_spi, int, 0);
85 MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI \
86 controllers (default=0)");
88 static int mpt_msi_enable_fc;
89 module_param(mpt_msi_enable_fc, int, 0);
90 MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \
91 controllers (default=0)");
93 static int mpt_msi_enable_sas;
94 module_param(mpt_msi_enable_sas, int, 0);
95 MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \
96 controllers (default=0)");
99 static int mpt_channel_mapping;
100 module_param(mpt_channel_mapping, int, 0);
101 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
103 static int mpt_debug_level;
104 static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
105 module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
106 &mpt_debug_level, 0600);
107 MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \
108 - (default=0)");
110 int mpt_fwfault_debug;
111 EXPORT_SYMBOL(mpt_fwfault_debug);
112 module_param_call(mpt_fwfault_debug, param_set_int, param_get_int,
113 &mpt_fwfault_debug, 0600);
114 MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault"
115 " and halt Firmware on fault - (default=0)");
119 #ifdef MFCNT
120 static int mfcounter = 0;
121 #define PRINT_MF_COUNT 20000
122 #endif
124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
126 * Public data...
129 static struct proc_dir_entry *mpt_proc_root_dir;
131 #define WHOINIT_UNKNOWN 0xAA
133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
135 * Private data...
137 /* Adapter link list */
138 LIST_HEAD(ioc_list);
139 /* Callback lookup table */
140 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
141 /* Protocol driver class lookup table */
142 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
143 /* Event handler lookup table */
144 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
145 /* Reset handler lookup table */
146 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
147 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
151 * Driver Callback Index's
153 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
154 static u8 last_drv_idx;
156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
158 * Forward protos...
160 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
161 static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
162 MPT_FRAME_HDR *reply);
163 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
164 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
165 int sleepFlag);
166 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
167 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
168 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
169 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
171 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
172 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
173 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
174 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
175 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
176 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
177 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
178 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
179 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
180 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
181 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
182 static int PrimeIocFifos(MPT_ADAPTER *ioc);
183 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
184 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
185 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
186 static int GetLanConfigPages(MPT_ADAPTER *ioc);
187 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
188 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
189 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
190 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
191 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
192 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
193 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
194 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch,
195 int sleepFlag);
196 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
197 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
198 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
200 #ifdef CONFIG_PROC_FS
201 static int procmpt_summary_read(char *buf, char **start, off_t offset,
202 int request, int *eof, void *data);
203 static int procmpt_version_read(char *buf, char **start, off_t offset,
204 int request, int *eof, void *data);
205 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
206 int request, int *eof, void *data);
207 #endif
208 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
210 static int ProcessEventNotification(MPT_ADAPTER *ioc,
211 EventNotificationReply_t *evReply, int *evHandlers);
212 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
213 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
214 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
215 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
216 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
217 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
219 /* module entry point */
220 static int __init fusion_init (void);
221 static void __exit fusion_exit (void);
223 #define CHIPREG_READ32(addr) readl_relaxed(addr)
224 #define CHIPREG_READ32_dmasync(addr) readl(addr)
225 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
226 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
227 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
229 static void
230 pci_disable_io_access(struct pci_dev *pdev)
232 u16 command_reg;
234 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
235 command_reg &= ~1;
236 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
239 static void
240 pci_enable_io_access(struct pci_dev *pdev)
242 u16 command_reg;
244 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
245 command_reg |= 1;
246 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
249 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
251 int ret = param_set_int(val, kp);
252 MPT_ADAPTER *ioc;
254 if (ret)
255 return ret;
257 list_for_each_entry(ioc, &ioc_list, list)
258 ioc->debug_level = mpt_debug_level;
259 return 0;
263 * mpt_get_cb_idx - obtain cb_idx for registered driver
264 * @dclass: class driver enum
266 * Returns cb_idx, or zero means it wasn't found
268 static u8
269 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
271 u8 cb_idx;
273 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
274 if (MptDriverClass[cb_idx] == dclass)
275 return cb_idx;
276 return 0;
280 * mpt_is_discovery_complete - determine if discovery has completed
281 * @ioc: per adatper instance
283 * Returns 1 when discovery completed, else zero.
285 static int
286 mpt_is_discovery_complete(MPT_ADAPTER *ioc)
288 ConfigExtendedPageHeader_t hdr;
289 CONFIGPARMS cfg;
290 SasIOUnitPage0_t *buffer;
291 dma_addr_t dma_handle;
292 int rc = 0;
294 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
295 memset(&cfg, 0, sizeof(CONFIGPARMS));
296 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
297 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
298 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
299 cfg.cfghdr.ehdr = &hdr;
300 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
302 if ((mpt_config(ioc, &cfg)))
303 goto out;
304 if (!hdr.ExtPageLength)
305 goto out;
307 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
308 &dma_handle);
309 if (!buffer)
310 goto out;
312 cfg.physAddr = dma_handle;
313 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
315 if ((mpt_config(ioc, &cfg)))
316 goto out_free_consistent;
318 if (!(buffer->PhyData[0].PortFlags &
319 MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS))
320 rc = 1;
322 out_free_consistent:
323 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
324 buffer, dma_handle);
325 out:
326 return rc;
330 * mpt_fault_reset_work - work performed on workq after ioc fault
331 * @work: input argument, used to derive ioc
334 static void
335 mpt_fault_reset_work(struct work_struct *work)
337 MPT_ADAPTER *ioc =
338 container_of(work, MPT_ADAPTER, fault_reset_work.work);
339 u32 ioc_raw_state;
340 int rc;
341 unsigned long flags;
343 if (ioc->ioc_reset_in_progress || !ioc->active)
344 goto out;
346 ioc_raw_state = mpt_GetIocState(ioc, 0);
347 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
348 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
349 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
350 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
351 ioc->name, __func__);
352 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
353 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
354 __func__, (rc == 0) ? "success" : "failed");
355 ioc_raw_state = mpt_GetIocState(ioc, 0);
356 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
357 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
358 "reset (%04xh)\n", ioc->name, ioc_raw_state &
359 MPI_DOORBELL_DATA_MASK);
360 } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) {
361 if ((mpt_is_discovery_complete(ioc))) {
362 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing "
363 "discovery_quiesce_io flag\n", ioc->name));
364 ioc->sas_discovery_quiesce_io = 0;
368 out:
370 * Take turns polling alternate controller
372 if (ioc->alt_ioc)
373 ioc = ioc->alt_ioc;
375 /* rearm the timer */
376 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
377 if (ioc->reset_work_q)
378 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
379 msecs_to_jiffies(MPT_POLLING_INTERVAL));
380 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
385 * Process turbo (context) reply...
387 static void
388 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
390 MPT_FRAME_HDR *mf = NULL;
391 MPT_FRAME_HDR *mr = NULL;
392 u16 req_idx = 0;
393 u8 cb_idx;
395 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
396 ioc->name, pa));
398 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
399 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
400 req_idx = pa & 0x0000FFFF;
401 cb_idx = (pa & 0x00FF0000) >> 16;
402 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
403 break;
404 case MPI_CONTEXT_REPLY_TYPE_LAN:
405 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
407 * Blind set of mf to NULL here was fatal
408 * after lan_reply says "freeme"
409 * Fix sort of combined with an optimization here;
410 * added explicit check for case where lan_reply
411 * was just returning 1 and doing nothing else.
412 * For this case skip the callback, but set up
413 * proper mf value first here:-)
415 if ((pa & 0x58000000) == 0x58000000) {
416 req_idx = pa & 0x0000FFFF;
417 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
418 mpt_free_msg_frame(ioc, mf);
419 mb();
420 return;
421 break;
423 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
424 break;
425 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
426 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
427 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
428 break;
429 default:
430 cb_idx = 0;
431 BUG();
434 /* Check for (valid) IO callback! */
435 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
436 MptCallbacks[cb_idx] == NULL) {
437 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
438 __func__, ioc->name, cb_idx);
439 goto out;
442 if (MptCallbacks[cb_idx](ioc, mf, mr))
443 mpt_free_msg_frame(ioc, mf);
444 out:
445 mb();
448 static void
449 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
451 MPT_FRAME_HDR *mf;
452 MPT_FRAME_HDR *mr;
453 u16 req_idx;
454 u8 cb_idx;
455 int freeme;
457 u32 reply_dma_low;
458 u16 ioc_stat;
460 /* non-TURBO reply! Hmmm, something may be up...
461 * Newest turbo reply mechanism; get address
462 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
465 /* Map DMA address of reply header to cpu address.
466 * pa is 32 bits - but the dma address may be 32 or 64 bits
467 * get offset based only only the low addresses
470 reply_dma_low = (pa <<= 1);
471 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
472 (reply_dma_low - ioc->reply_frames_low_dma));
474 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
475 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
476 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
478 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
479 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
480 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
482 /* Check/log IOC log info
484 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
485 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
486 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
487 if (ioc->bus_type == FC)
488 mpt_fc_log_info(ioc, log_info);
489 else if (ioc->bus_type == SPI)
490 mpt_spi_log_info(ioc, log_info);
491 else if (ioc->bus_type == SAS)
492 mpt_sas_log_info(ioc, log_info);
495 if (ioc_stat & MPI_IOCSTATUS_MASK)
496 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
498 /* Check for (valid) IO callback! */
499 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
500 MptCallbacks[cb_idx] == NULL) {
501 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
502 __func__, ioc->name, cb_idx);
503 freeme = 0;
504 goto out;
507 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
509 out:
510 /* Flush (non-TURBO) reply with a WRITE! */
511 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
513 if (freeme)
514 mpt_free_msg_frame(ioc, mf);
515 mb();
518 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
520 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
521 * @irq: irq number (not used)
522 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
524 * This routine is registered via the request_irq() kernel API call,
525 * and handles all interrupts generated from a specific MPT adapter
526 * (also referred to as a IO Controller or IOC).
527 * This routine must clear the interrupt from the adapter and does
528 * so by reading the reply FIFO. Multiple replies may be processed
529 * per single call to this routine.
531 * This routine handles register-level access of the adapter but
532 * dispatches (calls) a protocol-specific callback routine to handle
533 * the protocol-specific details of the MPT request completion.
535 static irqreturn_t
536 mpt_interrupt(int irq, void *bus_id)
538 MPT_ADAPTER *ioc = bus_id;
539 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
541 if (pa == 0xFFFFFFFF)
542 return IRQ_NONE;
545 * Drain the reply FIFO!
547 do {
548 if (pa & MPI_ADDRESS_REPLY_A_BIT)
549 mpt_reply(ioc, pa);
550 else
551 mpt_turbo_reply(ioc, pa);
552 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
553 } while (pa != 0xFFFFFFFF);
555 return IRQ_HANDLED;
558 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
560 * mptbase_reply - MPT base driver's callback routine
561 * @ioc: Pointer to MPT_ADAPTER structure
562 * @req: Pointer to original MPT request frame
563 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
565 * MPT base driver's callback routine; all base driver
566 * "internal" request/reply processing is routed here.
567 * Currently used for EventNotification and EventAck handling.
569 * Returns 1 indicating original alloc'd request frame ptr
570 * should be freed, or 0 if it shouldn't.
572 static int
573 mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
575 EventNotificationReply_t *pEventReply;
576 u8 event;
577 int evHandlers;
578 int freereq = 1;
580 switch (reply->u.hdr.Function) {
581 case MPI_FUNCTION_EVENT_NOTIFICATION:
582 pEventReply = (EventNotificationReply_t *)reply;
583 evHandlers = 0;
584 ProcessEventNotification(ioc, pEventReply, &evHandlers);
585 event = le32_to_cpu(pEventReply->Event) & 0xFF;
586 if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
587 freereq = 0;
588 if (event != MPI_EVENT_EVENT_CHANGE)
589 break;
590 case MPI_FUNCTION_CONFIG:
591 case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
592 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
593 if (reply) {
594 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
595 memcpy(ioc->mptbase_cmds.reply, reply,
596 min(MPT_DEFAULT_FRAME_SIZE,
597 4 * reply->u.reply.MsgLength));
599 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
600 ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
601 complete(&ioc->mptbase_cmds.done);
602 } else
603 freereq = 0;
604 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF)
605 freereq = 1;
606 break;
607 case MPI_FUNCTION_EVENT_ACK:
608 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
609 "EventAck reply received\n", ioc->name));
610 break;
611 default:
612 printk(MYIOC_s_ERR_FMT
613 "Unexpected msg function (=%02Xh) reply received!\n",
614 ioc->name, reply->u.hdr.Function);
615 break;
619 * Conditionally tell caller to free the original
620 * EventNotification/EventAck/unexpected request frame!
622 return freereq;
625 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
627 * mpt_register - Register protocol-specific main callback handler.
628 * @cbfunc: callback function pointer
629 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
631 * This routine is called by a protocol-specific driver (SCSI host,
632 * LAN, SCSI target) to register its reply callback routine. Each
633 * protocol-specific driver must do this before it will be able to
634 * use any IOC resources, such as obtaining request frames.
636 * NOTES: The SCSI protocol driver currently calls this routine thrice
637 * in order to register separate callbacks; one for "normal" SCSI IO;
638 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
640 * Returns u8 valued "handle" in the range (and S.O.D. order)
641 * {N,...,7,6,5,...,1} if successful.
642 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
643 * considered an error by the caller.
646 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
648 u8 cb_idx;
649 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
652 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
653 * (slot/handle 0 is reserved!)
655 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
656 if (MptCallbacks[cb_idx] == NULL) {
657 MptCallbacks[cb_idx] = cbfunc;
658 MptDriverClass[cb_idx] = dclass;
659 MptEvHandlers[cb_idx] = NULL;
660 last_drv_idx = cb_idx;
661 break;
665 return last_drv_idx;
668 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
670 * mpt_deregister - Deregister a protocol drivers resources.
671 * @cb_idx: previously registered callback handle
673 * Each protocol-specific driver should call this routine when its
674 * module is unloaded.
676 void
677 mpt_deregister(u8 cb_idx)
679 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
680 MptCallbacks[cb_idx] = NULL;
681 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
682 MptEvHandlers[cb_idx] = NULL;
684 last_drv_idx++;
688 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
690 * mpt_event_register - Register protocol-specific event callback handler.
691 * @cb_idx: previously registered (via mpt_register) callback handle
692 * @ev_cbfunc: callback function
694 * This routine can be called by one or more protocol-specific drivers
695 * if/when they choose to be notified of MPT events.
697 * Returns 0 for success.
700 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
702 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
703 return -1;
705 MptEvHandlers[cb_idx] = ev_cbfunc;
706 return 0;
709 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
711 * mpt_event_deregister - Deregister protocol-specific event callback handler
712 * @cb_idx: previously registered callback handle
714 * Each protocol-specific driver should call this routine
715 * when it does not (or can no longer) handle events,
716 * or when its module is unloaded.
718 void
719 mpt_event_deregister(u8 cb_idx)
721 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
722 return;
724 MptEvHandlers[cb_idx] = NULL;
727 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
729 * mpt_reset_register - Register protocol-specific IOC reset handler.
730 * @cb_idx: previously registered (via mpt_register) callback handle
731 * @reset_func: reset function
733 * This routine can be called by one or more protocol-specific drivers
734 * if/when they choose to be notified of IOC resets.
736 * Returns 0 for success.
739 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
741 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
742 return -1;
744 MptResetHandlers[cb_idx] = reset_func;
745 return 0;
748 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
750 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
751 * @cb_idx: previously registered callback handle
753 * Each protocol-specific driver should call this routine
754 * when it does not (or can no longer) handle IOC reset handling,
755 * or when its module is unloaded.
757 void
758 mpt_reset_deregister(u8 cb_idx)
760 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
761 return;
763 MptResetHandlers[cb_idx] = NULL;
766 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
768 * mpt_device_driver_register - Register device driver hooks
769 * @dd_cbfunc: driver callbacks struct
770 * @cb_idx: MPT protocol driver index
773 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
775 MPT_ADAPTER *ioc;
776 const struct pci_device_id *id;
778 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
779 return -EINVAL;
781 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
783 /* call per pci device probe entry point */
784 list_for_each_entry(ioc, &ioc_list, list) {
785 id = ioc->pcidev->driver ?
786 ioc->pcidev->driver->id_table : NULL;
787 if (dd_cbfunc->probe)
788 dd_cbfunc->probe(ioc->pcidev, id);
791 return 0;
794 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
796 * mpt_device_driver_deregister - DeRegister device driver hooks
797 * @cb_idx: MPT protocol driver index
799 void
800 mpt_device_driver_deregister(u8 cb_idx)
802 struct mpt_pci_driver *dd_cbfunc;
803 MPT_ADAPTER *ioc;
805 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
806 return;
808 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
810 list_for_each_entry(ioc, &ioc_list, list) {
811 if (dd_cbfunc->remove)
812 dd_cbfunc->remove(ioc->pcidev);
815 MptDeviceDriverHandlers[cb_idx] = NULL;
819 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
821 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
822 * @cb_idx: Handle of registered MPT protocol driver
823 * @ioc: Pointer to MPT adapter structure
825 * Obtain an MPT request frame from the pool (of 1024) that are
826 * allocated per MPT adapter.
828 * Returns pointer to a MPT request frame or %NULL if none are available
829 * or IOC is not active.
831 MPT_FRAME_HDR*
832 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
834 MPT_FRAME_HDR *mf;
835 unsigned long flags;
836 u16 req_idx; /* Request index */
838 /* validate handle and ioc identifier */
840 #ifdef MFCNT
841 if (!ioc->active)
842 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
843 "returning NULL!\n", ioc->name);
844 #endif
846 /* If interrupts are not attached, do not return a request frame */
847 if (!ioc->active)
848 return NULL;
850 spin_lock_irqsave(&ioc->FreeQlock, flags);
851 if (!list_empty(&ioc->FreeQ)) {
852 int req_offset;
854 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
855 u.frame.linkage.list);
856 list_del(&mf->u.frame.linkage.list);
857 mf->u.frame.linkage.arg1 = 0;
858 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
859 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
860 /* u16! */
861 req_idx = req_offset / ioc->req_sz;
862 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
863 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
864 /* Default, will be changed if necessary in SG generation */
865 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
866 #ifdef MFCNT
867 ioc->mfcnt++;
868 #endif
870 else
871 mf = NULL;
872 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
874 #ifdef MFCNT
875 if (mf == NULL)
876 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
877 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
878 ioc->req_depth);
879 mfcounter++;
880 if (mfcounter == PRINT_MF_COUNT)
881 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
882 ioc->mfcnt, ioc->req_depth);
883 #endif
885 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
886 ioc->name, cb_idx, ioc->id, mf));
887 return mf;
890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
892 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
893 * @cb_idx: Handle of registered MPT protocol driver
894 * @ioc: Pointer to MPT adapter structure
895 * @mf: Pointer to MPT request frame
897 * This routine posts an MPT request frame to the request post FIFO of a
898 * specific MPT adapter.
900 void
901 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
903 u32 mf_dma_addr;
904 int req_offset;
905 u16 req_idx; /* Request index */
907 /* ensure values are reset properly! */
908 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
909 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
910 /* u16! */
911 req_idx = req_offset / ioc->req_sz;
912 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
913 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
915 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
917 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
918 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
919 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
920 ioc->RequestNB[req_idx]));
921 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
925 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
926 * @cb_idx: Handle of registered MPT protocol driver
927 * @ioc: Pointer to MPT adapter structure
928 * @mf: Pointer to MPT request frame
930 * Send a protocol-specific MPT request frame to an IOC using
931 * hi-priority request queue.
933 * This routine posts an MPT request frame to the request post FIFO of a
934 * specific MPT adapter.
936 void
937 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
939 u32 mf_dma_addr;
940 int req_offset;
941 u16 req_idx; /* Request index */
943 /* ensure values are reset properly! */
944 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
945 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
946 req_idx = req_offset / ioc->req_sz;
947 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
948 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
950 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
952 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
953 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
954 ioc->name, mf_dma_addr, req_idx));
955 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
960 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
961 * @ioc: Pointer to MPT adapter structure
962 * @mf: Pointer to MPT request frame
964 * This routine places a MPT request frame back on the MPT adapter's
965 * FreeQ.
967 void
968 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
970 unsigned long flags;
972 /* Put Request back on FreeQ! */
973 spin_lock_irqsave(&ioc->FreeQlock, flags);
974 if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf)
975 goto out;
976 /* signature to know if this mf is freed */
977 mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf);
978 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
979 #ifdef MFCNT
980 ioc->mfcnt--;
981 #endif
982 out:
983 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
986 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
988 * mpt_add_sge - Place a simple 32 bit SGE at address pAddr.
989 * @pAddr: virtual address for SGE
990 * @flagslength: SGE flags and data transfer length
991 * @dma_addr: Physical address
993 * This routine places a MPT request frame back on the MPT adapter's
994 * FreeQ.
996 static void
997 mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
999 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1000 pSge->FlagsLength = cpu_to_le32(flagslength);
1001 pSge->Address = cpu_to_le32(dma_addr);
1005 * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr.
1006 * @pAddr: virtual address for SGE
1007 * @flagslength: SGE flags and data transfer length
1008 * @dma_addr: Physical address
1010 * This routine places a MPT request frame back on the MPT adapter's
1011 * FreeQ.
1013 static void
1014 mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1016 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1017 pSge->Address.Low = cpu_to_le32
1018 (lower_32_bits((unsigned long)(dma_addr)));
1019 pSge->Address.High = cpu_to_le32
1020 (upper_32_bits((unsigned long)dma_addr));
1021 pSge->FlagsLength = cpu_to_le32
1022 ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1026 * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround).
1027 * @pAddr: virtual address for SGE
1028 * @flagslength: SGE flags and data transfer length
1029 * @dma_addr: Physical address
1031 * This routine places a MPT request frame back on the MPT adapter's
1032 * FreeQ.
1034 static void
1035 mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1037 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1038 u32 tmp;
1040 pSge->Address.Low = cpu_to_le32
1041 (lower_32_bits((unsigned long)(dma_addr)));
1042 tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
1045 * 1078 errata workaround for the 36GB limitation
1047 if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) {
1048 flagslength |=
1049 MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS);
1050 tmp |= (1<<31);
1051 if (mpt_debug_level & MPT_DEBUG_36GB_MEM)
1052 printk(KERN_DEBUG "1078 P0M2 addressing for "
1053 "addr = 0x%llx len = %d\n",
1054 (unsigned long long)dma_addr,
1055 MPI_SGE_LENGTH(flagslength));
1058 pSge->Address.High = cpu_to_le32(tmp);
1059 pSge->FlagsLength = cpu_to_le32(
1060 (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1065 * mpt_add_chain - Place a 32 bit chain SGE at address pAddr.
1066 * @pAddr: virtual address for SGE
1067 * @next: nextChainOffset value (u32's)
1068 * @length: length of next SGL segment
1069 * @dma_addr: Physical address
1072 static void
1073 mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1075 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
1076 pChain->Length = cpu_to_le16(length);
1077 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
1078 pChain->NextChainOffset = next;
1079 pChain->Address = cpu_to_le32(dma_addr);
1082 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1084 * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
1085 * @pAddr: virtual address for SGE
1086 * @next: nextChainOffset value (u32's)
1087 * @length: length of next SGL segment
1088 * @dma_addr: Physical address
1091 static void
1092 mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1094 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1095 u32 tmp = dma_addr & 0xFFFFFFFF;
1097 pChain->Length = cpu_to_le16(length);
1098 pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
1099 MPI_SGE_FLAGS_64_BIT_ADDRESSING);
1101 pChain->NextChainOffset = next;
1103 pChain->Address.Low = cpu_to_le32(tmp);
1104 tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
1105 pChain->Address.High = cpu_to_le32(tmp);
1108 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1110 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1111 * @cb_idx: Handle of registered MPT protocol driver
1112 * @ioc: Pointer to MPT adapter structure
1113 * @reqBytes: Size of the request in bytes
1114 * @req: Pointer to MPT request frame
1115 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1117 * This routine is used exclusively to send MptScsiTaskMgmt
1118 * requests since they are required to be sent via doorbell handshake.
1120 * NOTE: It is the callers responsibility to byte-swap fields in the
1121 * request which are greater than 1 byte in size.
1123 * Returns 0 for success, non-zero for failure.
1126 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1128 int r = 0;
1129 u8 *req_as_bytes;
1130 int ii;
1132 /* State is known to be good upon entering
1133 * this function so issue the bus reset
1134 * request.
1138 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1139 * setting cb_idx/req_idx. But ONLY if this request
1140 * is in proper (pre-alloc'd) request buffer range...
1142 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1143 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1144 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1145 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1146 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1149 /* Make sure there are no doorbells */
1150 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1152 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1153 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1154 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1156 /* Wait for IOC doorbell int */
1157 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1158 return ii;
1161 /* Read doorbell and check for active bit */
1162 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1163 return -5;
1165 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1166 ioc->name, ii));
1168 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1170 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1171 return -2;
1174 /* Send request via doorbell handshake */
1175 req_as_bytes = (u8 *) req;
1176 for (ii = 0; ii < reqBytes/4; ii++) {
1177 u32 word;
1179 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1180 (req_as_bytes[(ii*4) + 1] << 8) |
1181 (req_as_bytes[(ii*4) + 2] << 16) |
1182 (req_as_bytes[(ii*4) + 3] << 24));
1183 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1184 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1185 r = -3;
1186 break;
1190 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1191 r = 0;
1192 else
1193 r = -4;
1195 /* Make sure there are no doorbells */
1196 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1198 return r;
1201 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1203 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1204 * @ioc: Pointer to MPT adapter structure
1205 * @access_control_value: define bits below
1206 * @sleepFlag: Specifies whether the process can sleep
1208 * Provides mechanism for the host driver to control the IOC's
1209 * Host Page Buffer access.
1211 * Access Control Value - bits[15:12]
1212 * 0h Reserved
1213 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1214 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1215 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1217 * Returns 0 for success, non-zero for failure.
1220 static int
1221 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1223 int r = 0;
1225 /* return if in use */
1226 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1227 & MPI_DOORBELL_ACTIVE)
1228 return -1;
1230 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1232 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1233 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1234 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1235 (access_control_value<<12)));
1237 /* Wait for IOC to clear Doorbell Status bit */
1238 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1239 return -2;
1240 }else
1241 return 0;
1244 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1246 * mpt_host_page_alloc - allocate system memory for the fw
1247 * @ioc: Pointer to pointer to IOC adapter
1248 * @ioc_init: Pointer to ioc init config page
1250 * If we already allocated memory in past, then resend the same pointer.
1251 * Returns 0 for success, non-zero for failure.
1253 static int
1254 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1256 char *psge;
1257 int flags_length;
1258 u32 host_page_buffer_sz=0;
1260 if(!ioc->HostPageBuffer) {
1262 host_page_buffer_sz =
1263 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1265 if(!host_page_buffer_sz)
1266 return 0; /* fw doesn't need any host buffers */
1268 /* spin till we get enough memory */
1269 while(host_page_buffer_sz > 0) {
1271 if((ioc->HostPageBuffer = pci_alloc_consistent(
1272 ioc->pcidev,
1273 host_page_buffer_sz,
1274 &ioc->HostPageBuffer_dma)) != NULL) {
1276 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1277 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1278 ioc->name, ioc->HostPageBuffer,
1279 (u32)ioc->HostPageBuffer_dma,
1280 host_page_buffer_sz));
1281 ioc->alloc_total += host_page_buffer_sz;
1282 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1283 break;
1286 host_page_buffer_sz -= (4*1024);
1290 if(!ioc->HostPageBuffer) {
1291 printk(MYIOC_s_ERR_FMT
1292 "Failed to alloc memory for host_page_buffer!\n",
1293 ioc->name);
1294 return -999;
1297 psge = (char *)&ioc_init->HostPageBufferSGE;
1298 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1299 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1300 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1301 MPI_SGE_FLAGS_HOST_TO_IOC |
1302 MPI_SGE_FLAGS_END_OF_BUFFER;
1303 if (sizeof(dma_addr_t) == sizeof(u64)) {
1304 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1306 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1307 flags_length |= ioc->HostPageBuffer_sz;
1308 ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1309 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1311 return 0;
1314 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1316 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1317 * @iocid: IOC unique identifier (integer)
1318 * @iocpp: Pointer to pointer to IOC adapter
1320 * Given a unique IOC identifier, set pointer to the associated MPT
1321 * adapter structure.
1323 * Returns iocid and sets iocpp if iocid is found.
1324 * Returns -1 if iocid is not found.
1327 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1329 MPT_ADAPTER *ioc;
1331 list_for_each_entry(ioc,&ioc_list,list) {
1332 if (ioc->id == iocid) {
1333 *iocpp =ioc;
1334 return iocid;
1338 *iocpp = NULL;
1339 return -1;
1343 * mpt_get_product_name - returns product string
1344 * @vendor: pci vendor id
1345 * @device: pci device id
1346 * @revision: pci revision id
1347 * @prod_name: string returned
1349 * Returns product string displayed when driver loads,
1350 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1353 static void
1354 mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1356 char *product_str = NULL;
1358 if (vendor == PCI_VENDOR_ID_BROCADE) {
1359 switch (device)
1361 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1362 switch (revision)
1364 case 0x00:
1365 product_str = "BRE040 A0";
1366 break;
1367 case 0x01:
1368 product_str = "BRE040 A1";
1369 break;
1370 default:
1371 product_str = "BRE040";
1372 break;
1374 break;
1376 goto out;
1379 switch (device)
1381 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1382 product_str = "LSIFC909 B1";
1383 break;
1384 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1385 product_str = "LSIFC919 B0";
1386 break;
1387 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1388 product_str = "LSIFC929 B0";
1389 break;
1390 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1391 if (revision < 0x80)
1392 product_str = "LSIFC919X A0";
1393 else
1394 product_str = "LSIFC919XL A1";
1395 break;
1396 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1397 if (revision < 0x80)
1398 product_str = "LSIFC929X A0";
1399 else
1400 product_str = "LSIFC929XL A1";
1401 break;
1402 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1403 product_str = "LSIFC939X A1";
1404 break;
1405 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1406 product_str = "LSIFC949X A1";
1407 break;
1408 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1409 switch (revision)
1411 case 0x00:
1412 product_str = "LSIFC949E A0";
1413 break;
1414 case 0x01:
1415 product_str = "LSIFC949E A1";
1416 break;
1417 default:
1418 product_str = "LSIFC949E";
1419 break;
1421 break;
1422 case MPI_MANUFACTPAGE_DEVID_53C1030:
1423 switch (revision)
1425 case 0x00:
1426 product_str = "LSI53C1030 A0";
1427 break;
1428 case 0x01:
1429 product_str = "LSI53C1030 B0";
1430 break;
1431 case 0x03:
1432 product_str = "LSI53C1030 B1";
1433 break;
1434 case 0x07:
1435 product_str = "LSI53C1030 B2";
1436 break;
1437 case 0x08:
1438 product_str = "LSI53C1030 C0";
1439 break;
1440 case 0x80:
1441 product_str = "LSI53C1030T A0";
1442 break;
1443 case 0x83:
1444 product_str = "LSI53C1030T A2";
1445 break;
1446 case 0x87:
1447 product_str = "LSI53C1030T A3";
1448 break;
1449 case 0xc1:
1450 product_str = "LSI53C1020A A1";
1451 break;
1452 default:
1453 product_str = "LSI53C1030";
1454 break;
1456 break;
1457 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1458 switch (revision)
1460 case 0x03:
1461 product_str = "LSI53C1035 A2";
1462 break;
1463 case 0x04:
1464 product_str = "LSI53C1035 B0";
1465 break;
1466 default:
1467 product_str = "LSI53C1035";
1468 break;
1470 break;
1471 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1472 switch (revision)
1474 case 0x00:
1475 product_str = "LSISAS1064 A1";
1476 break;
1477 case 0x01:
1478 product_str = "LSISAS1064 A2";
1479 break;
1480 case 0x02:
1481 product_str = "LSISAS1064 A3";
1482 break;
1483 case 0x03:
1484 product_str = "LSISAS1064 A4";
1485 break;
1486 default:
1487 product_str = "LSISAS1064";
1488 break;
1490 break;
1491 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1492 switch (revision)
1494 case 0x00:
1495 product_str = "LSISAS1064E A0";
1496 break;
1497 case 0x01:
1498 product_str = "LSISAS1064E B0";
1499 break;
1500 case 0x02:
1501 product_str = "LSISAS1064E B1";
1502 break;
1503 case 0x04:
1504 product_str = "LSISAS1064E B2";
1505 break;
1506 case 0x08:
1507 product_str = "LSISAS1064E B3";
1508 break;
1509 default:
1510 product_str = "LSISAS1064E";
1511 break;
1513 break;
1514 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1515 switch (revision)
1517 case 0x00:
1518 product_str = "LSISAS1068 A0";
1519 break;
1520 case 0x01:
1521 product_str = "LSISAS1068 B0";
1522 break;
1523 case 0x02:
1524 product_str = "LSISAS1068 B1";
1525 break;
1526 default:
1527 product_str = "LSISAS1068";
1528 break;
1530 break;
1531 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1532 switch (revision)
1534 case 0x00:
1535 product_str = "LSISAS1068E A0";
1536 break;
1537 case 0x01:
1538 product_str = "LSISAS1068E B0";
1539 break;
1540 case 0x02:
1541 product_str = "LSISAS1068E B1";
1542 break;
1543 case 0x04:
1544 product_str = "LSISAS1068E B2";
1545 break;
1546 case 0x08:
1547 product_str = "LSISAS1068E B3";
1548 break;
1549 default:
1550 product_str = "LSISAS1068E";
1551 break;
1553 break;
1554 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1555 switch (revision)
1557 case 0x00:
1558 product_str = "LSISAS1078 A0";
1559 break;
1560 case 0x01:
1561 product_str = "LSISAS1078 B0";
1562 break;
1563 case 0x02:
1564 product_str = "LSISAS1078 C0";
1565 break;
1566 case 0x03:
1567 product_str = "LSISAS1078 C1";
1568 break;
1569 case 0x04:
1570 product_str = "LSISAS1078 C2";
1571 break;
1572 default:
1573 product_str = "LSISAS1078";
1574 break;
1576 break;
1579 out:
1580 if (product_str)
1581 sprintf(prod_name, "%s", product_str);
1585 * mpt_mapresources - map in memory mapped io
1586 * @ioc: Pointer to pointer to IOC adapter
1589 static int
1590 mpt_mapresources(MPT_ADAPTER *ioc)
1592 u8 __iomem *mem;
1593 int ii;
1594 unsigned long mem_phys;
1595 unsigned long port;
1596 u32 msize;
1597 u32 psize;
1598 u8 revision;
1599 int r = -ENODEV;
1600 struct pci_dev *pdev;
1602 pdev = ioc->pcidev;
1603 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1604 if (pci_enable_device_mem(pdev)) {
1605 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1606 "failed\n", ioc->name);
1607 return r;
1609 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1610 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1611 "MEM failed\n", ioc->name);
1612 return r;
1615 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1617 if (sizeof(dma_addr_t) > 4) {
1618 const uint64_t required_mask = dma_get_required_mask
1619 (&pdev->dev);
1620 if (required_mask > DMA_BIT_MASK(32)
1621 && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1622 && !pci_set_consistent_dma_mask(pdev,
1623 DMA_BIT_MASK(64))) {
1624 ioc->dma_mask = DMA_BIT_MASK(64);
1625 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1626 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1627 ioc->name));
1628 } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1629 && !pci_set_consistent_dma_mask(pdev,
1630 DMA_BIT_MASK(32))) {
1631 ioc->dma_mask = DMA_BIT_MASK(32);
1632 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1633 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1634 ioc->name));
1635 } else {
1636 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1637 ioc->name, pci_name(pdev));
1638 return r;
1640 } else {
1641 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1642 && !pci_set_consistent_dma_mask(pdev,
1643 DMA_BIT_MASK(32))) {
1644 ioc->dma_mask = DMA_BIT_MASK(32);
1645 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1646 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1647 ioc->name));
1648 } else {
1649 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1650 ioc->name, pci_name(pdev));
1651 return r;
1655 mem_phys = msize = 0;
1656 port = psize = 0;
1657 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1658 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1659 if (psize)
1660 continue;
1661 /* Get I/O space! */
1662 port = pci_resource_start(pdev, ii);
1663 psize = pci_resource_len(pdev, ii);
1664 } else {
1665 if (msize)
1666 continue;
1667 /* Get memmap */
1668 mem_phys = pci_resource_start(pdev, ii);
1669 msize = pci_resource_len(pdev, ii);
1672 ioc->mem_size = msize;
1674 mem = NULL;
1675 /* Get logical ptr for PciMem0 space */
1676 /*mem = ioremap(mem_phys, msize);*/
1677 mem = ioremap(mem_phys, msize);
1678 if (mem == NULL) {
1679 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1680 " memory!\n", ioc->name);
1681 return -EINVAL;
1683 ioc->memmap = mem;
1684 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
1685 ioc->name, mem, mem_phys));
1687 ioc->mem_phys = mem_phys;
1688 ioc->chip = (SYSIF_REGS __iomem *)mem;
1690 /* Save Port IO values in case we need to do downloadboot */
1691 ioc->pio_mem_phys = port;
1692 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1694 return 0;
1697 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1699 * mpt_attach - Install a PCI intelligent MPT adapter.
1700 * @pdev: Pointer to pci_dev structure
1701 * @id: PCI device ID information
1703 * This routine performs all the steps necessary to bring the IOC of
1704 * a MPT adapter to a OPERATIONAL state. This includes registering
1705 * memory regions, registering the interrupt, and allocating request
1706 * and reply memory pools.
1708 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1709 * MPT adapter.
1711 * Returns 0 for success, non-zero for failure.
1713 * TODO: Add support for polled controllers
1716 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1718 MPT_ADAPTER *ioc;
1719 u8 cb_idx;
1720 int r = -ENODEV;
1721 u8 revision;
1722 u8 pcixcmd;
1723 static int mpt_ids = 0;
1724 #ifdef CONFIG_PROC_FS
1725 struct proc_dir_entry *dent, *ent;
1726 #endif
1728 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1729 if (ioc == NULL) {
1730 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1731 return -ENOMEM;
1734 ioc->id = mpt_ids++;
1735 sprintf(ioc->name, "ioc%d", ioc->id);
1736 dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1739 * set initial debug level
1740 * (refer to mptdebug.h)
1743 ioc->debug_level = mpt_debug_level;
1744 if (mpt_debug_level)
1745 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1747 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1749 ioc->pcidev = pdev;
1750 if (mpt_mapresources(ioc)) {
1751 kfree(ioc);
1752 return r;
1756 * Setting up proper handlers for scatter gather handling
1758 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
1759 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
1760 ioc->add_sge = &mpt_add_sge_64bit_1078;
1761 else
1762 ioc->add_sge = &mpt_add_sge_64bit;
1763 ioc->add_chain = &mpt_add_chain_64bit;
1764 ioc->sg_addr_size = 8;
1765 } else {
1766 ioc->add_sge = &mpt_add_sge;
1767 ioc->add_chain = &mpt_add_chain;
1768 ioc->sg_addr_size = 4;
1770 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
1772 ioc->alloc_total = sizeof(MPT_ADAPTER);
1773 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1774 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1776 ioc->pcidev = pdev;
1778 spin_lock_init(&ioc->taskmgmt_lock);
1779 mutex_init(&ioc->internal_cmds.mutex);
1780 init_completion(&ioc->internal_cmds.done);
1781 mutex_init(&ioc->mptbase_cmds.mutex);
1782 init_completion(&ioc->mptbase_cmds.done);
1783 mutex_init(&ioc->taskmgmt_cmds.mutex);
1784 init_completion(&ioc->taskmgmt_cmds.done);
1786 /* Initialize the event logging.
1788 ioc->eventTypes = 0; /* None */
1789 ioc->eventContext = 0;
1790 ioc->eventLogSize = 0;
1791 ioc->events = NULL;
1793 #ifdef MFCNT
1794 ioc->mfcnt = 0;
1795 #endif
1797 ioc->sh = NULL;
1798 ioc->cached_fw = NULL;
1800 /* Initilize SCSI Config Data structure
1802 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1804 /* Initialize the fc rport list head.
1806 INIT_LIST_HEAD(&ioc->fc_rports);
1808 /* Find lookup slot. */
1809 INIT_LIST_HEAD(&ioc->list);
1812 /* Initialize workqueue */
1813 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1815 snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
1816 "mpt_poll_%d", ioc->id);
1817 ioc->reset_work_q =
1818 create_singlethread_workqueue(ioc->reset_work_q_name);
1819 if (!ioc->reset_work_q) {
1820 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1821 ioc->name);
1822 pci_release_selected_regions(pdev, ioc->bars);
1823 kfree(ioc);
1824 return -ENOMEM;
1827 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1828 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1830 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1831 mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1833 switch (pdev->device)
1835 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1836 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1837 ioc->errata_flag_1064 = 1;
1838 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1839 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1840 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1841 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1842 ioc->bus_type = FC;
1843 break;
1845 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1846 if (revision < XL_929) {
1847 /* 929X Chip Fix. Set Split transactions level
1848 * for PCIX. Set MOST bits to zero.
1850 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1851 pcixcmd &= 0x8F;
1852 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1853 } else {
1854 /* 929XL Chip Fix. Set MMRBC to 0x08.
1856 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1857 pcixcmd |= 0x08;
1858 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1860 ioc->bus_type = FC;
1861 break;
1863 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1864 /* 919X Chip Fix. Set Split transactions level
1865 * for PCIX. Set MOST bits to zero.
1867 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1868 pcixcmd &= 0x8F;
1869 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1870 ioc->bus_type = FC;
1871 break;
1873 case MPI_MANUFACTPAGE_DEVID_53C1030:
1874 /* 1030 Chip Fix. Disable Split transactions
1875 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1877 if (revision < C0_1030) {
1878 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1879 pcixcmd &= 0x8F;
1880 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1883 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1884 ioc->bus_type = SPI;
1885 break;
1887 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1888 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1889 ioc->errata_flag_1064 = 1;
1890 ioc->bus_type = SAS;
1891 break;
1893 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1894 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1895 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1896 ioc->bus_type = SAS;
1897 break;
1901 switch (ioc->bus_type) {
1903 case SAS:
1904 ioc->msi_enable = mpt_msi_enable_sas;
1905 break;
1907 case SPI:
1908 ioc->msi_enable = mpt_msi_enable_spi;
1909 break;
1911 case FC:
1912 ioc->msi_enable = mpt_msi_enable_fc;
1913 break;
1915 default:
1916 ioc->msi_enable = 0;
1917 break;
1919 if (ioc->errata_flag_1064)
1920 pci_disable_io_access(pdev);
1922 spin_lock_init(&ioc->FreeQlock);
1924 /* Disable all! */
1925 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1926 ioc->active = 0;
1927 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1929 /* Set IOC ptr in the pcidev's driver data. */
1930 pci_set_drvdata(ioc->pcidev, ioc);
1932 /* Set lookup ptr. */
1933 list_add_tail(&ioc->list, &ioc_list);
1935 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1937 mpt_detect_bound_ports(ioc, pdev);
1939 INIT_LIST_HEAD(&ioc->fw_event_list);
1940 spin_lock_init(&ioc->fw_event_lock);
1941 snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
1942 ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
1944 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1945 CAN_SLEEP)) != 0){
1946 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1947 ioc->name, r);
1949 list_del(&ioc->list);
1950 if (ioc->alt_ioc)
1951 ioc->alt_ioc->alt_ioc = NULL;
1952 iounmap(ioc->memmap);
1953 if (r != -5)
1954 pci_release_selected_regions(pdev, ioc->bars);
1956 destroy_workqueue(ioc->reset_work_q);
1957 ioc->reset_work_q = NULL;
1959 kfree(ioc);
1960 pci_set_drvdata(pdev, NULL);
1961 return r;
1964 /* call per device driver probe entry point */
1965 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1966 if(MptDeviceDriverHandlers[cb_idx] &&
1967 MptDeviceDriverHandlers[cb_idx]->probe) {
1968 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1972 #ifdef CONFIG_PROC_FS
1974 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1976 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1977 if (dent) {
1978 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1979 if (ent) {
1980 ent->read_proc = procmpt_iocinfo_read;
1981 ent->data = ioc;
1983 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1984 if (ent) {
1985 ent->read_proc = procmpt_summary_read;
1986 ent->data = ioc;
1989 #endif
1991 if (!ioc->alt_ioc)
1992 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1993 msecs_to_jiffies(MPT_POLLING_INTERVAL));
1995 return 0;
1998 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2000 * mpt_detach - Remove a PCI intelligent MPT adapter.
2001 * @pdev: Pointer to pci_dev structure
2004 void
2005 mpt_detach(struct pci_dev *pdev)
2007 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2008 char pname[32];
2009 u8 cb_idx;
2010 unsigned long flags;
2011 struct workqueue_struct *wq;
2014 * Stop polling ioc for fault condition
2016 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2017 wq = ioc->reset_work_q;
2018 ioc->reset_work_q = NULL;
2019 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2020 cancel_delayed_work(&ioc->fault_reset_work);
2021 destroy_workqueue(wq);
2023 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2024 wq = ioc->fw_event_q;
2025 ioc->fw_event_q = NULL;
2026 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2027 destroy_workqueue(wq);
2029 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
2030 remove_proc_entry(pname, NULL);
2031 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
2032 remove_proc_entry(pname, NULL);
2033 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2034 remove_proc_entry(pname, NULL);
2036 /* call per device driver remove entry point */
2037 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2038 if(MptDeviceDriverHandlers[cb_idx] &&
2039 MptDeviceDriverHandlers[cb_idx]->remove) {
2040 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
2044 /* Disable interrupts! */
2045 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2047 ioc->active = 0;
2048 synchronize_irq(pdev->irq);
2050 /* Clear any lingering interrupt */
2051 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2053 CHIPREG_READ32(&ioc->chip->IntStatus);
2055 mpt_adapter_dispose(ioc);
2057 pci_set_drvdata(pdev, NULL);
2060 /**************************************************************************
2061 * Power Management
2063 #ifdef CONFIG_PM
2064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2066 * mpt_suspend - Fusion MPT base driver suspend routine.
2067 * @pdev: Pointer to pci_dev structure
2068 * @state: new state to enter
2071 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
2073 u32 device_state;
2074 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2076 device_state = pci_choose_state(pdev, state);
2077 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
2078 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2079 device_state);
2081 /* put ioc into READY_STATE */
2082 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
2083 printk(MYIOC_s_ERR_FMT
2084 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
2087 /* disable interrupts */
2088 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2089 ioc->active = 0;
2091 /* Clear any lingering interrupt */
2092 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2094 free_irq(ioc->pci_irq, ioc);
2095 if (ioc->msi_enable)
2096 pci_disable_msi(ioc->pcidev);
2097 ioc->pci_irq = -1;
2098 pci_save_state(pdev);
2099 pci_disable_device(pdev);
2100 pci_release_selected_regions(pdev, ioc->bars);
2101 pci_set_power_state(pdev, device_state);
2102 return 0;
2105 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2107 * mpt_resume - Fusion MPT base driver resume routine.
2108 * @pdev: Pointer to pci_dev structure
2111 mpt_resume(struct pci_dev *pdev)
2113 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2114 u32 device_state = pdev->current_state;
2115 int recovery_state;
2116 int err;
2118 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
2119 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2120 device_state);
2122 pci_set_power_state(pdev, PCI_D0);
2123 pci_enable_wake(pdev, PCI_D0, 0);
2124 pci_restore_state(pdev);
2125 ioc->pcidev = pdev;
2126 err = mpt_mapresources(ioc);
2127 if (err)
2128 return err;
2130 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
2131 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
2132 ioc->add_sge = &mpt_add_sge_64bit_1078;
2133 else
2134 ioc->add_sge = &mpt_add_sge_64bit;
2135 ioc->add_chain = &mpt_add_chain_64bit;
2136 ioc->sg_addr_size = 8;
2137 } else {
2139 ioc->add_sge = &mpt_add_sge;
2140 ioc->add_chain = &mpt_add_chain;
2141 ioc->sg_addr_size = 4;
2143 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
2145 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
2146 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
2147 CHIPREG_READ32(&ioc->chip->Doorbell));
2150 * Errata workaround for SAS pci express:
2151 * Upon returning to the D0 state, the contents of the doorbell will be
2152 * stale data, and this will incorrectly signal to the host driver that
2153 * the firmware is ready to process mpt commands. The workaround is
2154 * to issue a diagnostic reset.
2156 if (ioc->bus_type == SAS && (pdev->device ==
2157 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2158 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2159 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2160 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2161 ioc->name);
2162 goto out;
2166 /* bring ioc to operational state */
2167 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2168 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2169 CAN_SLEEP);
2170 if (recovery_state != 0)
2171 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2172 "error:[%x]\n", ioc->name, recovery_state);
2173 else
2174 printk(MYIOC_s_INFO_FMT
2175 "pci-resume: success\n", ioc->name);
2176 out:
2177 return 0;
2180 #endif
2182 static int
2183 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2185 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2186 ioc->bus_type != SPI) ||
2187 (MptDriverClass[index] == MPTFC_DRIVER &&
2188 ioc->bus_type != FC) ||
2189 (MptDriverClass[index] == MPTSAS_DRIVER &&
2190 ioc->bus_type != SAS))
2191 /* make sure we only call the relevant reset handler
2192 * for the bus */
2193 return 0;
2194 return (MptResetHandlers[index])(ioc, reset_phase);
2197 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2199 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2200 * @ioc: Pointer to MPT adapter structure
2201 * @reason: Event word / reason
2202 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2204 * This routine performs all the steps necessary to bring the IOC
2205 * to a OPERATIONAL state.
2207 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2208 * MPT adapter.
2210 * Returns:
2211 * 0 for success
2212 * -1 if failed to get board READY
2213 * -2 if READY but IOCFacts Failed
2214 * -3 if READY but PrimeIOCFifos Failed
2215 * -4 if READY but IOCInit Failed
2216 * -5 if failed to enable_device and/or request_selected_regions
2217 * -6 if failed to upload firmware
2219 static int
2220 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2222 int hard_reset_done = 0;
2223 int alt_ioc_ready = 0;
2224 int hard;
2225 int rc=0;
2226 int ii;
2227 u8 cb_idx;
2228 int handlers;
2229 int ret = 0;
2230 int reset_alt_ioc_active = 0;
2231 int irq_allocated = 0;
2232 u8 *a;
2234 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2235 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2237 /* Disable reply interrupts (also blocks FreeQ) */
2238 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2239 ioc->active = 0;
2241 if (ioc->alt_ioc) {
2242 if (ioc->alt_ioc->active ||
2243 reason == MPT_HOSTEVENT_IOC_RECOVER) {
2244 reset_alt_ioc_active = 1;
2245 /* Disable alt-IOC's reply interrupts
2246 * (and FreeQ) for a bit
2248 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2249 0xFFFFFFFF);
2250 ioc->alt_ioc->active = 0;
2254 hard = 1;
2255 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2256 hard = 0;
2258 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2259 if (hard_reset_done == -4) {
2260 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2261 ioc->name);
2263 if (reset_alt_ioc_active && ioc->alt_ioc) {
2264 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2265 dprintk(ioc, printk(MYIOC_s_INFO_FMT
2266 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2267 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2268 ioc->alt_ioc->active = 1;
2271 } else {
2272 printk(MYIOC_s_WARN_FMT
2273 "NOT READY WARNING!\n", ioc->name);
2275 ret = -1;
2276 goto out;
2279 /* hard_reset_done = 0 if a soft reset was performed
2280 * and 1 if a hard reset was performed.
2282 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2283 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2284 alt_ioc_ready = 1;
2285 else
2286 printk(MYIOC_s_WARN_FMT
2287 ": alt-ioc Not ready WARNING!\n",
2288 ioc->alt_ioc->name);
2291 for (ii=0; ii<5; ii++) {
2292 /* Get IOC facts! Allow 5 retries */
2293 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2294 break;
2298 if (ii == 5) {
2299 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2300 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2301 ret = -2;
2302 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2303 MptDisplayIocCapabilities(ioc);
2306 if (alt_ioc_ready) {
2307 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2308 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2309 "Initial Alt IocFacts failed rc=%x\n",
2310 ioc->name, rc));
2311 /* Retry - alt IOC was initialized once
2313 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2315 if (rc) {
2316 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2317 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2318 alt_ioc_ready = 0;
2319 reset_alt_ioc_active = 0;
2320 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2321 MptDisplayIocCapabilities(ioc->alt_ioc);
2325 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2326 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2327 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2328 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2329 IORESOURCE_IO);
2330 if (pci_enable_device(ioc->pcidev))
2331 return -5;
2332 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2333 "mpt"))
2334 return -5;
2338 * Device is reset now. It must have de-asserted the interrupt line
2339 * (if it was asserted) and it should be safe to register for the
2340 * interrupt now.
2342 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2343 ioc->pci_irq = -1;
2344 if (ioc->pcidev->irq) {
2345 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2346 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2347 ioc->name);
2348 else
2349 ioc->msi_enable = 0;
2350 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2351 IRQF_SHARED, ioc->name, ioc);
2352 if (rc < 0) {
2353 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2354 "interrupt %d!\n",
2355 ioc->name, ioc->pcidev->irq);
2356 if (ioc->msi_enable)
2357 pci_disable_msi(ioc->pcidev);
2358 ret = -EBUSY;
2359 goto out;
2361 irq_allocated = 1;
2362 ioc->pci_irq = ioc->pcidev->irq;
2363 pci_set_master(ioc->pcidev); /* ?? */
2364 pci_set_drvdata(ioc->pcidev, ioc);
2365 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2366 "installed at interrupt %d\n", ioc->name,
2367 ioc->pcidev->irq));
2371 /* Prime reply & request queues!
2372 * (mucho alloc's) Must be done prior to
2373 * init as upper addresses are needed for init.
2374 * If fails, continue with alt-ioc processing
2376 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
2377 ioc->name));
2378 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2379 ret = -3;
2381 /* May need to check/upload firmware & data here!
2382 * If fails, continue with alt-ioc processing
2384 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
2385 ioc->name));
2386 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2387 ret = -4;
2388 // NEW!
2389 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2390 printk(MYIOC_s_WARN_FMT
2391 ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
2392 ioc->alt_ioc->name, rc);
2393 alt_ioc_ready = 0;
2394 reset_alt_ioc_active = 0;
2397 if (alt_ioc_ready) {
2398 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2399 alt_ioc_ready = 0;
2400 reset_alt_ioc_active = 0;
2401 printk(MYIOC_s_WARN_FMT
2402 ": alt-ioc: (%d) init failure WARNING!\n",
2403 ioc->alt_ioc->name, rc);
2407 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2408 if (ioc->upload_fw) {
2409 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2410 "firmware upload required!\n", ioc->name));
2412 /* Controller is not operational, cannot do upload
2414 if (ret == 0) {
2415 rc = mpt_do_upload(ioc, sleepFlag);
2416 if (rc == 0) {
2417 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2419 * Maintain only one pointer to FW memory
2420 * so there will not be two attempt to
2421 * downloadboot onboard dual function
2422 * chips (mpt_adapter_disable,
2423 * mpt_diag_reset)
2425 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2426 "mpt_upload: alt_%s has cached_fw=%p \n",
2427 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2428 ioc->cached_fw = NULL;
2430 } else {
2431 printk(MYIOC_s_WARN_FMT
2432 "firmware upload failure!\n", ioc->name);
2433 ret = -6;
2439 /* Enable MPT base driver management of EventNotification
2440 * and EventAck handling.
2442 if ((ret == 0) && (!ioc->facts.EventState)) {
2443 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2444 "SendEventNotification\n",
2445 ioc->name));
2446 ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */
2449 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2450 rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
2452 if (ret == 0) {
2453 /* Enable! (reply interrupt) */
2454 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2455 ioc->active = 1;
2457 if (rc == 0) { /* alt ioc */
2458 if (reset_alt_ioc_active && ioc->alt_ioc) {
2459 /* (re)Enable alt-IOC! (reply interrupt) */
2460 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc"
2461 "reply irq re-enabled\n",
2462 ioc->alt_ioc->name));
2463 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2464 MPI_HIM_DIM);
2465 ioc->alt_ioc->active = 1;
2470 /* Add additional "reason" check before call to GetLanConfigPages
2471 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2472 * recursive scenario; GetLanConfigPages times out, timer expired
2473 * routine calls HardResetHandler, which calls into here again,
2474 * and we try GetLanConfigPages again...
2476 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2479 * Initalize link list for inactive raid volumes.
2481 mutex_init(&ioc->raid_data.inactive_list_mutex);
2482 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2484 switch (ioc->bus_type) {
2486 case SAS:
2487 /* clear persistency table */
2488 if(ioc->facts.IOCExceptions &
2489 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2490 ret = mptbase_sas_persist_operation(ioc,
2491 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2492 if(ret != 0)
2493 goto out;
2496 /* Find IM volumes
2498 mpt_findImVolumes(ioc);
2500 /* Check, and possibly reset, the coalescing value
2502 mpt_read_ioc_pg_1(ioc);
2504 break;
2506 case FC:
2507 if ((ioc->pfacts[0].ProtocolFlags &
2508 MPI_PORTFACTS_PROTOCOL_LAN) &&
2509 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2511 * Pre-fetch the ports LAN MAC address!
2512 * (LANPage1_t stuff)
2514 (void) GetLanConfigPages(ioc);
2515 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2516 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2517 "LanAddr = %02X:%02X:%02X"
2518 ":%02X:%02X:%02X\n",
2519 ioc->name, a[5], a[4],
2520 a[3], a[2], a[1], a[0]));
2522 break;
2524 case SPI:
2525 /* Get NVRAM and adapter maximums from SPP 0 and 2
2527 mpt_GetScsiPortSettings(ioc, 0);
2529 /* Get version and length of SDP 1
2531 mpt_readScsiDevicePageHeaders(ioc, 0);
2533 /* Find IM volumes
2535 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2536 mpt_findImVolumes(ioc);
2538 /* Check, and possibly reset, the coalescing value
2540 mpt_read_ioc_pg_1(ioc);
2542 mpt_read_ioc_pg_4(ioc);
2544 break;
2547 GetIoUnitPage2(ioc);
2548 mpt_get_manufacturing_pg_0(ioc);
2552 * Call each currently registered protocol IOC reset handler
2553 * with post-reset indication.
2554 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2555 * MptResetHandlers[] registered yet.
2557 if (hard_reset_done) {
2558 rc = handlers = 0;
2559 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2560 if ((ret == 0) && MptResetHandlers[cb_idx]) {
2561 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2562 "Calling IOC post_reset handler #%d\n",
2563 ioc->name, cb_idx));
2564 rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2565 handlers++;
2568 if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2569 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2570 "Calling IOC post_reset handler #%d\n",
2571 ioc->alt_ioc->name, cb_idx));
2572 rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2573 handlers++;
2576 /* FIXME? Examine results here? */
2579 out:
2580 if ((ret != 0) && irq_allocated) {
2581 free_irq(ioc->pci_irq, ioc);
2582 if (ioc->msi_enable)
2583 pci_disable_msi(ioc->pcidev);
2585 return ret;
2588 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2590 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2591 * @ioc: Pointer to MPT adapter structure
2592 * @pdev: Pointer to (struct pci_dev) structure
2594 * Search for PCI bus/dev_function which matches
2595 * PCI bus/dev_function (+/-1) for newly discovered 929,
2596 * 929X, 1030 or 1035.
2598 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2599 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2601 static void
2602 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2604 struct pci_dev *peer=NULL;
2605 unsigned int slot = PCI_SLOT(pdev->devfn);
2606 unsigned int func = PCI_FUNC(pdev->devfn);
2607 MPT_ADAPTER *ioc_srch;
2609 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2610 " searching for devfn match on %x or %x\n",
2611 ioc->name, pci_name(pdev), pdev->bus->number,
2612 pdev->devfn, func-1, func+1));
2614 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2615 if (!peer) {
2616 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2617 if (!peer)
2618 return;
2621 list_for_each_entry(ioc_srch, &ioc_list, list) {
2622 struct pci_dev *_pcidev = ioc_srch->pcidev;
2623 if (_pcidev == peer) {
2624 /* Paranoia checks */
2625 if (ioc->alt_ioc != NULL) {
2626 printk(MYIOC_s_WARN_FMT
2627 "Oops, already bound (%s <==> %s)!\n",
2628 ioc->name, ioc->name, ioc->alt_ioc->name);
2629 break;
2630 } else if (ioc_srch->alt_ioc != NULL) {
2631 printk(MYIOC_s_WARN_FMT
2632 "Oops, already bound (%s <==> %s)!\n",
2633 ioc_srch->name, ioc_srch->name,
2634 ioc_srch->alt_ioc->name);
2635 break;
2637 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2638 "FOUND! binding %s <==> %s\n",
2639 ioc->name, ioc->name, ioc_srch->name));
2640 ioc_srch->alt_ioc = ioc;
2641 ioc->alt_ioc = ioc_srch;
2644 pci_dev_put(peer);
2647 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2649 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2650 * @ioc: Pointer to MPT adapter structure
2652 static void
2653 mpt_adapter_disable(MPT_ADAPTER *ioc)
2655 int sz;
2656 int ret;
2658 if (ioc->cached_fw != NULL) {
2659 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2660 "%s: Pushing FW onto adapter\n", __func__, ioc->name));
2661 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2662 ioc->cached_fw, CAN_SLEEP)) < 0) {
2663 printk(MYIOC_s_WARN_FMT
2664 ": firmware downloadboot failure (%d)!\n",
2665 ioc->name, ret);
2670 * Put the controller into ready state (if its not already)
2672 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
2673 if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
2674 CAN_SLEEP)) {
2675 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
2676 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit "
2677 "reset failed to put ioc in ready state!\n",
2678 ioc->name, __func__);
2679 } else
2680 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset "
2681 "failed!\n", ioc->name, __func__);
2685 /* Disable adapter interrupts! */
2686 synchronize_irq(ioc->pcidev->irq);
2687 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2688 ioc->active = 0;
2690 /* Clear any lingering interrupt */
2691 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2692 CHIPREG_READ32(&ioc->chip->IntStatus);
2694 if (ioc->alloc != NULL) {
2695 sz = ioc->alloc_sz;
2696 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2697 ioc->name, ioc->alloc, ioc->alloc_sz));
2698 pci_free_consistent(ioc->pcidev, sz,
2699 ioc->alloc, ioc->alloc_dma);
2700 ioc->reply_frames = NULL;
2701 ioc->req_frames = NULL;
2702 ioc->alloc = NULL;
2703 ioc->alloc_total -= sz;
2706 if (ioc->sense_buf_pool != NULL) {
2707 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2708 pci_free_consistent(ioc->pcidev, sz,
2709 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2710 ioc->sense_buf_pool = NULL;
2711 ioc->alloc_total -= sz;
2714 if (ioc->events != NULL){
2715 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2716 kfree(ioc->events);
2717 ioc->events = NULL;
2718 ioc->alloc_total -= sz;
2721 mpt_free_fw_memory(ioc);
2723 kfree(ioc->spi_data.nvram);
2724 mpt_inactive_raid_list_free(ioc);
2725 kfree(ioc->raid_data.pIocPg2);
2726 kfree(ioc->raid_data.pIocPg3);
2727 ioc->spi_data.nvram = NULL;
2728 ioc->raid_data.pIocPg3 = NULL;
2730 if (ioc->spi_data.pIocPg4 != NULL) {
2731 sz = ioc->spi_data.IocPg4Sz;
2732 pci_free_consistent(ioc->pcidev, sz,
2733 ioc->spi_data.pIocPg4,
2734 ioc->spi_data.IocPg4_dma);
2735 ioc->spi_data.pIocPg4 = NULL;
2736 ioc->alloc_total -= sz;
2739 if (ioc->ReqToChain != NULL) {
2740 kfree(ioc->ReqToChain);
2741 kfree(ioc->RequestNB);
2742 ioc->ReqToChain = NULL;
2745 kfree(ioc->ChainToChain);
2746 ioc->ChainToChain = NULL;
2748 if (ioc->HostPageBuffer != NULL) {
2749 if((ret = mpt_host_page_access_control(ioc,
2750 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2751 printk(MYIOC_s_ERR_FMT
2752 ": %s: host page buffers free failed (%d)!\n",
2753 ioc->name, __func__, ret);
2755 dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2756 "HostPageBuffer free @ %p, sz=%d bytes\n",
2757 ioc->name, ioc->HostPageBuffer,
2758 ioc->HostPageBuffer_sz));
2759 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2760 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2761 ioc->HostPageBuffer = NULL;
2762 ioc->HostPageBuffer_sz = 0;
2763 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2766 pci_set_drvdata(ioc->pcidev, NULL);
2768 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2770 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2771 * @ioc: Pointer to MPT adapter structure
2773 * This routine unregisters h/w resources and frees all alloc'd memory
2774 * associated with a MPT adapter structure.
2776 static void
2777 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2779 int sz_first, sz_last;
2781 if (ioc == NULL)
2782 return;
2784 sz_first = ioc->alloc_total;
2786 mpt_adapter_disable(ioc);
2788 if (ioc->pci_irq != -1) {
2789 free_irq(ioc->pci_irq, ioc);
2790 if (ioc->msi_enable)
2791 pci_disable_msi(ioc->pcidev);
2792 ioc->pci_irq = -1;
2795 if (ioc->memmap != NULL) {
2796 iounmap(ioc->memmap);
2797 ioc->memmap = NULL;
2800 pci_disable_device(ioc->pcidev);
2801 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2803 #if defined(CONFIG_MTRR) && 0
2804 if (ioc->mtrr_reg > 0) {
2805 mtrr_del(ioc->mtrr_reg, 0, 0);
2806 dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2808 #endif
2810 /* Zap the adapter lookup ptr! */
2811 list_del(&ioc->list);
2813 sz_last = ioc->alloc_total;
2814 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2815 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2817 if (ioc->alt_ioc)
2818 ioc->alt_ioc->alt_ioc = NULL;
2820 kfree(ioc);
2823 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2825 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2826 * @ioc: Pointer to MPT adapter structure
2828 static void
2829 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2831 int i = 0;
2833 printk(KERN_INFO "%s: ", ioc->name);
2834 if (ioc->prod_name)
2835 printk("%s: ", ioc->prod_name);
2836 printk("Capabilities={");
2838 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2839 printk("Initiator");
2840 i++;
2843 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2844 printk("%sTarget", i ? "," : "");
2845 i++;
2848 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2849 printk("%sLAN", i ? "," : "");
2850 i++;
2853 #if 0
2855 * This would probably evoke more questions than it's worth
2857 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2858 printk("%sLogBusAddr", i ? "," : "");
2859 i++;
2861 #endif
2863 printk("}\n");
2866 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2868 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2869 * @ioc: Pointer to MPT_ADAPTER structure
2870 * @force: Force hard KickStart of IOC
2871 * @sleepFlag: Specifies whether the process can sleep
2873 * Returns:
2874 * 1 - DIAG reset and READY
2875 * 0 - READY initially OR soft reset and READY
2876 * -1 - Any failure on KickStart
2877 * -2 - Msg Unit Reset Failed
2878 * -3 - IO Unit Reset Failed
2879 * -4 - IOC owned by a PEER
2881 static int
2882 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2884 u32 ioc_state;
2885 int statefault = 0;
2886 int cntdn;
2887 int hard_reset_done = 0;
2888 int r;
2889 int ii;
2890 int whoinit;
2892 /* Get current [raw] IOC state */
2893 ioc_state = mpt_GetIocState(ioc, 0);
2894 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2897 * Check to see if IOC got left/stuck in doorbell handshake
2898 * grip of death. If so, hard reset the IOC.
2900 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2901 statefault = 1;
2902 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2903 ioc->name);
2906 /* Is it already READY? */
2907 if (!statefault &&
2908 ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) {
2909 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2910 "IOC is in READY state\n", ioc->name));
2911 return 0;
2915 * Check to see if IOC is in FAULT state.
2917 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2918 statefault = 2;
2919 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2920 ioc->name);
2921 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2922 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2926 * Hmmm... Did it get left operational?
2928 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2929 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2930 ioc->name));
2932 /* Check WhoInit.
2933 * If PCI Peer, exit.
2934 * Else, if no fault conditions are present, issue a MessageUnitReset
2935 * Else, fall through to KickStart case
2937 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2938 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2939 "whoinit 0x%x statefault %d force %d\n",
2940 ioc->name, whoinit, statefault, force));
2941 if (whoinit == MPI_WHOINIT_PCI_PEER)
2942 return -4;
2943 else {
2944 if ((statefault == 0 ) && (force == 0)) {
2945 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2946 return 0;
2948 statefault = 3;
2952 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2953 if (hard_reset_done < 0)
2954 return -1;
2957 * Loop here waiting for IOC to come READY.
2959 ii = 0;
2960 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2962 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2963 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2965 * BIOS or previous driver load left IOC in OP state.
2966 * Reset messaging FIFOs.
2968 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2969 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2970 return -2;
2972 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2974 * Something is wrong. Try to get IOC back
2975 * to a known state.
2977 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2978 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2979 return -3;
2983 ii++; cntdn--;
2984 if (!cntdn) {
2985 printk(MYIOC_s_ERR_FMT
2986 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
2987 ioc->name, ioc_state, (int)((ii+5)/HZ));
2988 return -ETIME;
2991 if (sleepFlag == CAN_SLEEP) {
2992 msleep(1);
2993 } else {
2994 mdelay (1); /* 1 msec delay */
2999 if (statefault < 3) {
3000 printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name,
3001 statefault == 1 ? "stuck handshake" : "IOC FAULT");
3004 return hard_reset_done;
3007 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3009 * mpt_GetIocState - Get the current state of a MPT adapter.
3010 * @ioc: Pointer to MPT_ADAPTER structure
3011 * @cooked: Request raw or cooked IOC state
3013 * Returns all IOC Doorbell register bits if cooked==0, else just the
3014 * Doorbell bits in MPI_IOC_STATE_MASK.
3017 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
3019 u32 s, sc;
3021 /* Get! */
3022 s = CHIPREG_READ32(&ioc->chip->Doorbell);
3023 sc = s & MPI_IOC_STATE_MASK;
3025 /* Save! */
3026 ioc->last_state = sc;
3028 return cooked ? sc : s;
3031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3033 * GetIocFacts - Send IOCFacts request to MPT adapter.
3034 * @ioc: Pointer to MPT_ADAPTER structure
3035 * @sleepFlag: Specifies whether the process can sleep
3036 * @reason: If recovery, only update facts.
3038 * Returns 0 for success, non-zero for failure.
3040 static int
3041 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
3043 IOCFacts_t get_facts;
3044 IOCFactsReply_t *facts;
3045 int r;
3046 int req_sz;
3047 int reply_sz;
3048 int sz;
3049 u32 status, vv;
3050 u8 shiftFactor=1;
3052 /* IOC *must* NOT be in RESET state! */
3053 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3054 printk(KERN_ERR MYNAM
3055 ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
3056 ioc->name, ioc->last_state);
3057 return -44;
3060 facts = &ioc->facts;
3062 /* Destination (reply area)... */
3063 reply_sz = sizeof(*facts);
3064 memset(facts, 0, reply_sz);
3066 /* Request area (get_facts on the stack right now!) */
3067 req_sz = sizeof(get_facts);
3068 memset(&get_facts, 0, req_sz);
3070 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
3071 /* Assert: All other get_facts fields are zero! */
3073 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3074 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
3075 ioc->name, req_sz, reply_sz));
3077 /* No non-zero fields in the get_facts request are greater than
3078 * 1 byte in size, so we can just fire it off as is.
3080 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
3081 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
3082 if (r != 0)
3083 return r;
3086 * Now byte swap (GRRR) the necessary fields before any further
3087 * inspection of reply contents.
3089 * But need to do some sanity checks on MsgLength (byte) field
3090 * to make sure we don't zero IOC's req_sz!
3092 /* Did we get a valid reply? */
3093 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
3094 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3096 * If not been here, done that, save off first WhoInit value
3098 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
3099 ioc->FirstWhoInit = facts->WhoInit;
3102 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
3103 facts->MsgContext = le32_to_cpu(facts->MsgContext);
3104 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
3105 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
3106 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
3107 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
3108 /* CHECKME! IOCStatus, IOCLogInfo */
3110 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
3111 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
3114 * FC f/w version changed between 1.1 and 1.2
3115 * Old: u16{Major(4),Minor(4),SubMinor(8)}
3116 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
3118 if (facts->MsgVersion < MPI_VERSION_01_02) {
3120 * Handle old FC f/w style, convert to new...
3122 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
3123 facts->FWVersion.Word =
3124 ((oldv<<12) & 0xFF000000) |
3125 ((oldv<<8) & 0x000FFF00);
3126 } else
3127 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
3129 facts->ProductID = le16_to_cpu(facts->ProductID);
3131 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
3132 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
3133 ioc->ir_firmware = 1;
3135 facts->CurrentHostMfaHighAddr =
3136 le32_to_cpu(facts->CurrentHostMfaHighAddr);
3137 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
3138 facts->CurrentSenseBufferHighAddr =
3139 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
3140 facts->CurReplyFrameSize =
3141 le16_to_cpu(facts->CurReplyFrameSize);
3142 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
3145 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
3146 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
3147 * to 14 in MPI-1.01.0x.
3149 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
3150 facts->MsgVersion > MPI_VERSION_01_00) {
3151 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
3154 sz = facts->FWImageSize;
3155 if ( sz & 0x01 )
3156 sz += 1;
3157 if ( sz & 0x02 )
3158 sz += 2;
3159 facts->FWImageSize = sz;
3161 if (!facts->RequestFrameSize) {
3162 /* Something is wrong! */
3163 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
3164 ioc->name);
3165 return -55;
3168 r = sz = facts->BlockSize;
3169 vv = ((63 / (sz * 4)) + 1) & 0x03;
3170 ioc->NB_for_64_byte_frame = vv;
3171 while ( sz )
3173 shiftFactor++;
3174 sz = sz >> 1;
3176 ioc->NBShiftFactor = shiftFactor;
3177 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3178 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
3179 ioc->name, vv, shiftFactor, r));
3181 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3183 * Set values for this IOC's request & reply frame sizes,
3184 * and request & reply queue depths...
3186 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
3187 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
3188 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
3189 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
3191 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
3192 ioc->name, ioc->reply_sz, ioc->reply_depth));
3193 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
3194 ioc->name, ioc->req_sz, ioc->req_depth));
3196 /* Get port facts! */
3197 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
3198 return r;
3200 } else {
3201 printk(MYIOC_s_ERR_FMT
3202 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
3203 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
3204 RequestFrameSize)/sizeof(u32)));
3205 return -66;
3208 return 0;
3211 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3213 * GetPortFacts - Send PortFacts request to MPT adapter.
3214 * @ioc: Pointer to MPT_ADAPTER structure
3215 * @portnum: Port number
3216 * @sleepFlag: Specifies whether the process can sleep
3218 * Returns 0 for success, non-zero for failure.
3220 static int
3221 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3223 PortFacts_t get_pfacts;
3224 PortFactsReply_t *pfacts;
3225 int ii;
3226 int req_sz;
3227 int reply_sz;
3228 int max_id;
3230 /* IOC *must* NOT be in RESET state! */
3231 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3232 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3233 ioc->name, ioc->last_state );
3234 return -4;
3237 pfacts = &ioc->pfacts[portnum];
3239 /* Destination (reply area)... */
3240 reply_sz = sizeof(*pfacts);
3241 memset(pfacts, 0, reply_sz);
3243 /* Request area (get_pfacts on the stack right now!) */
3244 req_sz = sizeof(get_pfacts);
3245 memset(&get_pfacts, 0, req_sz);
3247 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3248 get_pfacts.PortNumber = portnum;
3249 /* Assert: All other get_pfacts fields are zero! */
3251 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3252 ioc->name, portnum));
3254 /* No non-zero fields in the get_pfacts request are greater than
3255 * 1 byte in size, so we can just fire it off as is.
3257 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3258 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3259 if (ii != 0)
3260 return ii;
3262 /* Did we get a valid reply? */
3264 /* Now byte swap the necessary fields in the response. */
3265 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3266 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3267 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3268 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3269 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3270 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3271 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3272 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3273 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3275 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3276 pfacts->MaxDevices;
3277 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3278 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3281 * Place all the devices on channels
3283 * (for debuging)
3285 if (mpt_channel_mapping) {
3286 ioc->devices_per_bus = 1;
3287 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3290 return 0;
3293 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3295 * SendIocInit - Send IOCInit request to MPT adapter.
3296 * @ioc: Pointer to MPT_ADAPTER structure
3297 * @sleepFlag: Specifies whether the process can sleep
3299 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3301 * Returns 0 for success, non-zero for failure.
3303 static int
3304 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3306 IOCInit_t ioc_init;
3307 MPIDefaultReply_t init_reply;
3308 u32 state;
3309 int r;
3310 int count;
3311 int cntdn;
3313 memset(&ioc_init, 0, sizeof(ioc_init));
3314 memset(&init_reply, 0, sizeof(init_reply));
3316 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3317 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3319 /* If we are in a recovery mode and we uploaded the FW image,
3320 * then this pointer is not NULL. Skip the upload a second time.
3321 * Set this flag if cached_fw set for either IOC.
3323 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3324 ioc->upload_fw = 1;
3325 else
3326 ioc->upload_fw = 0;
3327 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3328 ioc->name, ioc->upload_fw, ioc->facts.Flags));
3330 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3331 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3333 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3334 ioc->name, ioc->facts.MsgVersion));
3335 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3336 // set MsgVersion and HeaderVersion host driver was built with
3337 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3338 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3340 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3341 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3342 } else if(mpt_host_page_alloc(ioc, &ioc_init))
3343 return -99;
3345 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3347 if (ioc->sg_addr_size == sizeof(u64)) {
3348 /* Save the upper 32-bits of the request
3349 * (reply) and sense buffers.
3351 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3352 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3353 } else {
3354 /* Force 32-bit addressing */
3355 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3356 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3359 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3360 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3361 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3362 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3364 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3365 ioc->name, &ioc_init));
3367 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3368 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3369 if (r != 0) {
3370 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3371 return r;
3374 /* No need to byte swap the multibyte fields in the reply
3375 * since we don't even look at its contents.
3378 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3379 ioc->name, &ioc_init));
3381 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3382 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3383 return r;
3386 /* YIKES! SUPER IMPORTANT!!!
3387 * Poll IocState until _OPERATIONAL while IOC is doing
3388 * LoopInit and TargetDiscovery!
3390 count = 0;
3391 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3392 state = mpt_GetIocState(ioc, 1);
3393 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3394 if (sleepFlag == CAN_SLEEP) {
3395 msleep(1);
3396 } else {
3397 mdelay(1);
3400 if (!cntdn) {
3401 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3402 ioc->name, (int)((count+5)/HZ));
3403 return -9;
3406 state = mpt_GetIocState(ioc, 1);
3407 count++;
3409 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3410 ioc->name, count));
3412 ioc->aen_event_read_flag=0;
3413 return r;
3416 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3418 * SendPortEnable - Send PortEnable request to MPT adapter port.
3419 * @ioc: Pointer to MPT_ADAPTER structure
3420 * @portnum: Port number to enable
3421 * @sleepFlag: Specifies whether the process can sleep
3423 * Send PortEnable to bring IOC to OPERATIONAL state.
3425 * Returns 0 for success, non-zero for failure.
3427 static int
3428 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3430 PortEnable_t port_enable;
3431 MPIDefaultReply_t reply_buf;
3432 int rc;
3433 int req_sz;
3434 int reply_sz;
3436 /* Destination... */
3437 reply_sz = sizeof(MPIDefaultReply_t);
3438 memset(&reply_buf, 0, reply_sz);
3440 req_sz = sizeof(PortEnable_t);
3441 memset(&port_enable, 0, req_sz);
3443 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3444 port_enable.PortNumber = portnum;
3445 /* port_enable.ChainOffset = 0; */
3446 /* port_enable.MsgFlags = 0; */
3447 /* port_enable.MsgContext = 0; */
3449 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3450 ioc->name, portnum, &port_enable));
3452 /* RAID FW may take a long time to enable
3454 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3455 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3456 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3457 300 /*seconds*/, sleepFlag);
3458 } else {
3459 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3460 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3461 30 /*seconds*/, sleepFlag);
3463 return rc;
3467 * mpt_alloc_fw_memory - allocate firmware memory
3468 * @ioc: Pointer to MPT_ADAPTER structure
3469 * @size: total FW bytes
3471 * If memory has already been allocated, the same (cached) value
3472 * is returned.
3474 * Return 0 if successfull, or non-zero for failure
3477 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3479 int rc;
3481 if (ioc->cached_fw) {
3482 rc = 0; /* use already allocated memory */
3483 goto out;
3485 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3486 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3487 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3488 rc = 0;
3489 goto out;
3491 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3492 if (!ioc->cached_fw) {
3493 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3494 ioc->name);
3495 rc = -1;
3496 } else {
3497 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3498 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3499 ioc->alloc_total += size;
3500 rc = 0;
3502 out:
3503 return rc;
3507 * mpt_free_fw_memory - free firmware memory
3508 * @ioc: Pointer to MPT_ADAPTER structure
3510 * If alt_img is NULL, delete from ioc structure.
3511 * Else, delete a secondary image in same format.
3513 void
3514 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3516 int sz;
3518 if (!ioc->cached_fw)
3519 return;
3521 sz = ioc->facts.FWImageSize;
3522 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3523 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3524 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3525 ioc->alloc_total -= sz;
3526 ioc->cached_fw = NULL;
3529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3531 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3532 * @ioc: Pointer to MPT_ADAPTER structure
3533 * @sleepFlag: Specifies whether the process can sleep
3535 * Returns 0 for success, >0 for handshake failure
3536 * <0 for fw upload failure.
3538 * Remark: If bound IOC and a successful FWUpload was performed
3539 * on the bound IOC, the second image is discarded
3540 * and memory is free'd. Both channels must upload to prevent
3541 * IOC from running in degraded mode.
3543 static int
3544 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3546 u8 reply[sizeof(FWUploadReply_t)];
3547 FWUpload_t *prequest;
3548 FWUploadReply_t *preply;
3549 FWUploadTCSGE_t *ptcsge;
3550 u32 flagsLength;
3551 int ii, sz, reply_sz;
3552 int cmdStatus;
3553 int request_size;
3554 /* If the image size is 0, we are done.
3556 if ((sz = ioc->facts.FWImageSize) == 0)
3557 return 0;
3559 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3560 return -ENOMEM;
3562 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3563 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3565 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3566 kzalloc(ioc->req_sz, GFP_KERNEL);
3567 if (!prequest) {
3568 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3569 "while allocating memory \n", ioc->name));
3570 mpt_free_fw_memory(ioc);
3571 return -ENOMEM;
3574 preply = (FWUploadReply_t *)&reply;
3576 reply_sz = sizeof(reply);
3577 memset(preply, 0, reply_sz);
3579 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3580 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3582 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3583 ptcsge->DetailsLength = 12;
3584 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3585 ptcsge->ImageSize = cpu_to_le32(sz);
3586 ptcsge++;
3588 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3589 ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3590 request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
3591 ioc->SGE_size;
3592 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
3593 " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
3594 ioc->facts.FWImageSize, request_size));
3595 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3597 ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
3598 reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag);
3600 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
3601 "rc=%x \n", ioc->name, ii));
3603 cmdStatus = -EFAULT;
3604 if (ii == 0) {
3605 /* Handshake transfer was complete and successful.
3606 * Check the Reply Frame.
3608 int status;
3609 status = le16_to_cpu(preply->IOCStatus) &
3610 MPI_IOCSTATUS_MASK;
3611 if (status == MPI_IOCSTATUS_SUCCESS &&
3612 ioc->facts.FWImageSize ==
3613 le32_to_cpu(preply->ActualImageSize))
3614 cmdStatus = 0;
3616 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3617 ioc->name, cmdStatus));
3620 if (cmdStatus) {
3621 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
3622 "freeing image \n", ioc->name));
3623 mpt_free_fw_memory(ioc);
3625 kfree(prequest);
3627 return cmdStatus;
3630 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3632 * mpt_downloadboot - DownloadBoot code
3633 * @ioc: Pointer to MPT_ADAPTER structure
3634 * @pFwHeader: Pointer to firmware header info
3635 * @sleepFlag: Specifies whether the process can sleep
3637 * FwDownloadBoot requires Programmed IO access.
3639 * Returns 0 for success
3640 * -1 FW Image size is 0
3641 * -2 No valid cached_fw Pointer
3642 * <0 for fw upload failure.
3644 static int
3645 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3647 MpiExtImageHeader_t *pExtImage;
3648 u32 fwSize;
3649 u32 diag0val;
3650 int count;
3651 u32 *ptrFw;
3652 u32 diagRwData;
3653 u32 nextImage;
3654 u32 load_addr;
3655 u32 ioc_state=0;
3657 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3658 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3660 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3661 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3662 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3663 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3664 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3665 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3667 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3669 /* wait 1 msec */
3670 if (sleepFlag == CAN_SLEEP) {
3671 msleep(1);
3672 } else {
3673 mdelay (1);
3676 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3677 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3679 for (count = 0; count < 30; count ++) {
3680 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3681 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3682 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3683 ioc->name, count));
3684 break;
3686 /* wait .1 sec */
3687 if (sleepFlag == CAN_SLEEP) {
3688 msleep (100);
3689 } else {
3690 mdelay (100);
3694 if ( count == 30 ) {
3695 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3696 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3697 ioc->name, diag0val));
3698 return -3;
3701 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3702 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3703 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3704 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3705 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3706 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3708 /* Set the DiagRwEn and Disable ARM bits */
3709 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3711 fwSize = (pFwHeader->ImageSize + 3)/4;
3712 ptrFw = (u32 *) pFwHeader;
3714 /* Write the LoadStartAddress to the DiagRw Address Register
3715 * using Programmed IO
3717 if (ioc->errata_flag_1064)
3718 pci_enable_io_access(ioc->pcidev);
3720 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3721 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3722 ioc->name, pFwHeader->LoadStartAddress));
3724 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3725 ioc->name, fwSize*4, ptrFw));
3726 while (fwSize--) {
3727 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3730 nextImage = pFwHeader->NextImageHeaderOffset;
3731 while (nextImage) {
3732 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3734 load_addr = pExtImage->LoadStartAddress;
3736 fwSize = (pExtImage->ImageSize + 3) >> 2;
3737 ptrFw = (u32 *)pExtImage;
3739 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3740 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3741 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3743 while (fwSize--) {
3744 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3746 nextImage = pExtImage->NextImageHeaderOffset;
3749 /* Write the IopResetVectorRegAddr */
3750 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3751 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3753 /* Write the IopResetVectorValue */
3754 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3755 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3757 /* Clear the internal flash bad bit - autoincrementing register,
3758 * so must do two writes.
3760 if (ioc->bus_type == SPI) {
3762 * 1030 and 1035 H/W errata, workaround to access
3763 * the ClearFlashBadSignatureBit
3765 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3766 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3767 diagRwData |= 0x40000000;
3768 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3769 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3771 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3772 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3773 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3774 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3776 /* wait 1 msec */
3777 if (sleepFlag == CAN_SLEEP) {
3778 msleep (1);
3779 } else {
3780 mdelay (1);
3784 if (ioc->errata_flag_1064)
3785 pci_disable_io_access(ioc->pcidev);
3787 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3788 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3789 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3790 ioc->name, diag0val));
3791 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3792 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3793 ioc->name, diag0val));
3794 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3796 /* Write 0xFF to reset the sequencer */
3797 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3799 if (ioc->bus_type == SAS) {
3800 ioc_state = mpt_GetIocState(ioc, 0);
3801 if ( (GetIocFacts(ioc, sleepFlag,
3802 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3803 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3804 ioc->name, ioc_state));
3805 return -EFAULT;
3809 for (count=0; count<HZ*20; count++) {
3810 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3811 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3812 "downloadboot successful! (count=%d) IocState=%x\n",
3813 ioc->name, count, ioc_state));
3814 if (ioc->bus_type == SAS) {
3815 return 0;
3817 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3818 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3819 "downloadboot: SendIocInit failed\n",
3820 ioc->name));
3821 return -EFAULT;
3823 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3824 "downloadboot: SendIocInit successful\n",
3825 ioc->name));
3826 return 0;
3828 if (sleepFlag == CAN_SLEEP) {
3829 msleep (10);
3830 } else {
3831 mdelay (10);
3834 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3835 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3836 return -EFAULT;
3839 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3841 * KickStart - Perform hard reset of MPT adapter.
3842 * @ioc: Pointer to MPT_ADAPTER structure
3843 * @force: Force hard reset
3844 * @sleepFlag: Specifies whether the process can sleep
3846 * This routine places MPT adapter in diagnostic mode via the
3847 * WriteSequence register, and then performs a hard reset of adapter
3848 * via the Diagnostic register.
3850 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3851 * or NO_SLEEP (interrupt thread, use mdelay)
3852 * force - 1 if doorbell active, board fault state
3853 * board operational, IOC_RECOVERY or
3854 * IOC_BRINGUP and there is an alt_ioc.
3855 * 0 else
3857 * Returns:
3858 * 1 - hard reset, READY
3859 * 0 - no reset due to History bit, READY
3860 * -1 - no reset due to History bit but not READY
3861 * OR reset but failed to come READY
3862 * -2 - no reset, could not enter DIAG mode
3863 * -3 - reset but bad FW bit
3865 static int
3866 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3868 int hard_reset_done = 0;
3869 u32 ioc_state=0;
3870 int cnt,cntdn;
3872 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3873 if (ioc->bus_type == SPI) {
3874 /* Always issue a Msg Unit Reset first. This will clear some
3875 * SCSI bus hang conditions.
3877 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3879 if (sleepFlag == CAN_SLEEP) {
3880 msleep (1000);
3881 } else {
3882 mdelay (1000);
3886 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3887 if (hard_reset_done < 0)
3888 return hard_reset_done;
3890 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3891 ioc->name));
3893 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3894 for (cnt=0; cnt<cntdn; cnt++) {
3895 ioc_state = mpt_GetIocState(ioc, 1);
3896 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3897 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3898 ioc->name, cnt));
3899 return hard_reset_done;
3901 if (sleepFlag == CAN_SLEEP) {
3902 msleep (10);
3903 } else {
3904 mdelay (10);
3908 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3909 ioc->name, mpt_GetIocState(ioc, 0)));
3910 return -1;
3913 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3915 * mpt_diag_reset - Perform hard reset of the adapter.
3916 * @ioc: Pointer to MPT_ADAPTER structure
3917 * @ignore: Set if to honor and clear to ignore
3918 * the reset history bit
3919 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3920 * else set to NO_SLEEP (use mdelay instead)
3922 * This routine places the adapter in diagnostic mode via the
3923 * WriteSequence register and then performs a hard reset of adapter
3924 * via the Diagnostic register. Adapter should be in ready state
3925 * upon successful completion.
3927 * Returns: 1 hard reset successful
3928 * 0 no reset performed because reset history bit set
3929 * -2 enabling diagnostic mode failed
3930 * -3 diagnostic reset failed
3932 static int
3933 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3935 u32 diag0val;
3936 u32 doorbell;
3937 int hard_reset_done = 0;
3938 int count = 0;
3939 u32 diag1val = 0;
3940 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3942 /* Clear any existing interrupts */
3943 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3945 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3947 if (!ignore)
3948 return 0;
3950 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3951 "address=%p\n", ioc->name, __func__,
3952 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3953 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3954 if (sleepFlag == CAN_SLEEP)
3955 msleep(1);
3956 else
3957 mdelay(1);
3959 for (count = 0; count < 60; count ++) {
3960 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3961 doorbell &= MPI_IOC_STATE_MASK;
3963 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3964 "looking for READY STATE: doorbell=%x"
3965 " count=%d\n",
3966 ioc->name, doorbell, count));
3968 if (doorbell == MPI_IOC_STATE_READY) {
3969 return 1;
3972 /* wait 1 sec */
3973 if (sleepFlag == CAN_SLEEP)
3974 msleep(1000);
3975 else
3976 mdelay(1000);
3978 return -1;
3981 /* Use "Diagnostic reset" method! (only thing available!) */
3982 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3984 if (ioc->debug_level & MPT_DEBUG) {
3985 if (ioc->alt_ioc)
3986 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3987 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3988 ioc->name, diag0val, diag1val));
3991 /* Do the reset if we are told to ignore the reset history
3992 * or if the reset history is 0
3994 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3995 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3996 /* Write magic sequence to WriteSequence register
3997 * Loop until in diagnostic mode
3999 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4000 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4001 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4002 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4003 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4004 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4006 /* wait 100 msec */
4007 if (sleepFlag == CAN_SLEEP) {
4008 msleep (100);
4009 } else {
4010 mdelay (100);
4013 count++;
4014 if (count > 20) {
4015 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4016 ioc->name, diag0val);
4017 return -2;
4021 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4023 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
4024 ioc->name, diag0val));
4027 if (ioc->debug_level & MPT_DEBUG) {
4028 if (ioc->alt_ioc)
4029 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4030 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
4031 ioc->name, diag0val, diag1val));
4034 * Disable the ARM (Bug fix)
4037 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
4038 mdelay(1);
4041 * Now hit the reset bit in the Diagnostic register
4042 * (THE BIG HAMMER!) (Clears DRWE bit).
4044 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
4045 hard_reset_done = 1;
4046 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
4047 ioc->name));
4050 * Call each currently registered protocol IOC reset handler
4051 * with pre-reset indication.
4052 * NOTE: If we're doing _IOC_BRINGUP, there can be no
4053 * MptResetHandlers[] registered yet.
4056 u8 cb_idx;
4057 int r = 0;
4059 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
4060 if (MptResetHandlers[cb_idx]) {
4061 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4062 "Calling IOC pre_reset handler #%d\n",
4063 ioc->name, cb_idx));
4064 r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
4065 if (ioc->alt_ioc) {
4066 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4067 "Calling alt-%s pre_reset handler #%d\n",
4068 ioc->name, ioc->alt_ioc->name, cb_idx));
4069 r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
4073 /* FIXME? Examine results here? */
4076 if (ioc->cached_fw)
4077 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
4078 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
4079 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
4080 else
4081 cached_fw = NULL;
4082 if (cached_fw) {
4083 /* If the DownloadBoot operation fails, the
4084 * IOC will be left unusable. This is a fatal error
4085 * case. _diag_reset will return < 0
4087 for (count = 0; count < 30; count ++) {
4088 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4089 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
4090 break;
4093 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
4094 ioc->name, diag0val, count));
4095 /* wait 1 sec */
4096 if (sleepFlag == CAN_SLEEP) {
4097 msleep (1000);
4098 } else {
4099 mdelay (1000);
4102 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
4103 printk(MYIOC_s_WARN_FMT
4104 "firmware downloadboot failure (%d)!\n", ioc->name, count);
4107 } else {
4108 /* Wait for FW to reload and for board
4109 * to go to the READY state.
4110 * Maximum wait is 60 seconds.
4111 * If fail, no error will check again
4112 * with calling program.
4114 for (count = 0; count < 60; count ++) {
4115 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
4116 doorbell &= MPI_IOC_STATE_MASK;
4118 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4119 "looking for READY STATE: doorbell=%x"
4120 " count=%d\n", ioc->name, doorbell, count));
4122 if (doorbell == MPI_IOC_STATE_READY) {
4123 break;
4126 /* wait 1 sec */
4127 if (sleepFlag == CAN_SLEEP) {
4128 msleep (1000);
4129 } else {
4130 mdelay (1000);
4134 if (doorbell != MPI_IOC_STATE_READY)
4135 printk(MYIOC_s_ERR_FMT "Failed to come READY "
4136 "after reset! IocState=%x", ioc->name,
4137 doorbell);
4141 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4142 if (ioc->debug_level & MPT_DEBUG) {
4143 if (ioc->alt_ioc)
4144 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4145 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
4146 ioc->name, diag0val, diag1val));
4149 /* Clear RESET_HISTORY bit! Place board in the
4150 * diagnostic mode to update the diag register.
4152 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4153 count = 0;
4154 while ((diag0val & MPI_DIAG_DRWE) == 0) {
4155 /* Write magic sequence to WriteSequence register
4156 * Loop until in diagnostic mode
4158 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4159 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4160 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4161 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4162 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4163 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4165 /* wait 100 msec */
4166 if (sleepFlag == CAN_SLEEP) {
4167 msleep (100);
4168 } else {
4169 mdelay (100);
4172 count++;
4173 if (count > 20) {
4174 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4175 ioc->name, diag0val);
4176 break;
4178 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4180 diag0val &= ~MPI_DIAG_RESET_HISTORY;
4181 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
4182 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4183 if (diag0val & MPI_DIAG_RESET_HISTORY) {
4184 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
4185 ioc->name);
4188 /* Disable Diagnostic Mode
4190 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
4192 /* Check FW reload status flags.
4194 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4195 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
4196 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
4197 ioc->name, diag0val);
4198 return -3;
4201 if (ioc->debug_level & MPT_DEBUG) {
4202 if (ioc->alt_ioc)
4203 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4204 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
4205 ioc->name, diag0val, diag1val));
4209 * Reset flag that says we've enabled event notification
4211 ioc->facts.EventState = 0;
4213 if (ioc->alt_ioc)
4214 ioc->alt_ioc->facts.EventState = 0;
4216 return hard_reset_done;
4219 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4221 * SendIocReset - Send IOCReset request to MPT adapter.
4222 * @ioc: Pointer to MPT_ADAPTER structure
4223 * @reset_type: reset type, expected values are
4224 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
4225 * @sleepFlag: Specifies whether the process can sleep
4227 * Send IOCReset request to the MPT adapter.
4229 * Returns 0 for success, non-zero for failure.
4231 static int
4232 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4234 int r;
4235 u32 state;
4236 int cntdn, count;
4238 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4239 ioc->name, reset_type));
4240 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4241 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4242 return r;
4244 /* FW ACK'd request, wait for READY state
4246 count = 0;
4247 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
4249 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4250 cntdn--;
4251 count++;
4252 if (!cntdn) {
4253 if (sleepFlag != CAN_SLEEP)
4254 count *= 10;
4256 printk(MYIOC_s_ERR_FMT
4257 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
4258 ioc->name, state, (int)((count+5)/HZ));
4259 return -ETIME;
4262 if (sleepFlag == CAN_SLEEP) {
4263 msleep(1);
4264 } else {
4265 mdelay (1); /* 1 msec delay */
4269 /* TODO!
4270 * Cleanup all event stuff for this IOC; re-issue EventNotification
4271 * request if needed.
4273 if (ioc->facts.Function)
4274 ioc->facts.EventState = 0;
4276 return 0;
4279 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4281 * initChainBuffers - Allocate memory for and initialize chain buffers
4282 * @ioc: Pointer to MPT_ADAPTER structure
4284 * Allocates memory for and initializes chain buffers,
4285 * chain buffer control arrays and spinlock.
4287 static int
4288 initChainBuffers(MPT_ADAPTER *ioc)
4290 u8 *mem;
4291 int sz, ii, num_chain;
4292 int scale, num_sge, numSGE;
4294 /* ReqToChain size must equal the req_depth
4295 * index = req_idx
4297 if (ioc->ReqToChain == NULL) {
4298 sz = ioc->req_depth * sizeof(int);
4299 mem = kmalloc(sz, GFP_ATOMIC);
4300 if (mem == NULL)
4301 return -1;
4303 ioc->ReqToChain = (int *) mem;
4304 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
4305 ioc->name, mem, sz));
4306 mem = kmalloc(sz, GFP_ATOMIC);
4307 if (mem == NULL)
4308 return -1;
4310 ioc->RequestNB = (int *) mem;
4311 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
4312 ioc->name, mem, sz));
4314 for (ii = 0; ii < ioc->req_depth; ii++) {
4315 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4318 /* ChainToChain size must equal the total number
4319 * of chain buffers to be allocated.
4320 * index = chain_idx
4322 * Calculate the number of chain buffers needed(plus 1) per I/O
4323 * then multiply the maximum number of simultaneous cmds
4325 * num_sge = num sge in request frame + last chain buffer
4326 * scale = num sge per chain buffer if no chain element
4328 scale = ioc->req_sz / ioc->SGE_size;
4329 if (ioc->sg_addr_size == sizeof(u64))
4330 num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size;
4331 else
4332 num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size;
4334 if (ioc->sg_addr_size == sizeof(u64)) {
4335 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4336 (ioc->req_sz - 60) / ioc->SGE_size;
4337 } else {
4338 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) +
4339 scale + (ioc->req_sz - 64) / ioc->SGE_size;
4341 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4342 ioc->name, num_sge, numSGE));
4344 if (ioc->bus_type == FC) {
4345 if (numSGE > MPT_SCSI_FC_SG_DEPTH)
4346 numSGE = MPT_SCSI_FC_SG_DEPTH;
4347 } else {
4348 if (numSGE > MPT_SCSI_SG_DEPTH)
4349 numSGE = MPT_SCSI_SG_DEPTH;
4352 num_chain = 1;
4353 while (numSGE - num_sge > 0) {
4354 num_chain++;
4355 num_sge += (scale - 1);
4357 num_chain++;
4359 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4360 ioc->name, numSGE, num_sge, num_chain));
4362 if (ioc->bus_type == SPI)
4363 num_chain *= MPT_SCSI_CAN_QUEUE;
4364 else
4365 num_chain *= MPT_FC_CAN_QUEUE;
4367 ioc->num_chain = num_chain;
4369 sz = num_chain * sizeof(int);
4370 if (ioc->ChainToChain == NULL) {
4371 mem = kmalloc(sz, GFP_ATOMIC);
4372 if (mem == NULL)
4373 return -1;
4375 ioc->ChainToChain = (int *) mem;
4376 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4377 ioc->name, mem, sz));
4378 } else {
4379 mem = (u8 *) ioc->ChainToChain;
4381 memset(mem, 0xFF, sz);
4382 return num_chain;
4385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4387 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4388 * @ioc: Pointer to MPT_ADAPTER structure
4390 * This routine allocates memory for the MPT reply and request frame
4391 * pools (if necessary), and primes the IOC reply FIFO with
4392 * reply frames.
4394 * Returns 0 for success, non-zero for failure.
4396 static int
4397 PrimeIocFifos(MPT_ADAPTER *ioc)
4399 MPT_FRAME_HDR *mf;
4400 unsigned long flags;
4401 dma_addr_t alloc_dma;
4402 u8 *mem;
4403 int i, reply_sz, sz, total_size, num_chain;
4404 u64 dma_mask;
4406 dma_mask = 0;
4408 /* Prime reply FIFO... */
4410 if (ioc->reply_frames == NULL) {
4411 if ( (num_chain = initChainBuffers(ioc)) < 0)
4412 return -1;
4414 * 1078 errata workaround for the 36GB limitation
4416 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
4417 ioc->dma_mask > DMA_BIT_MASK(35)) {
4418 if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32))
4419 && !pci_set_consistent_dma_mask(ioc->pcidev,
4420 DMA_BIT_MASK(32))) {
4421 dma_mask = DMA_BIT_MASK(35);
4422 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4423 "setting 35 bit addressing for "
4424 "Request/Reply/Chain and Sense Buffers\n",
4425 ioc->name));
4426 } else {
4427 /*Reseting DMA mask to 64 bit*/
4428 pci_set_dma_mask(ioc->pcidev,
4429 DMA_BIT_MASK(64));
4430 pci_set_consistent_dma_mask(ioc->pcidev,
4431 DMA_BIT_MASK(64));
4433 printk(MYIOC_s_ERR_FMT
4434 "failed setting 35 bit addressing for "
4435 "Request/Reply/Chain and Sense Buffers\n",
4436 ioc->name);
4437 return -1;
4441 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4442 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4443 ioc->name, ioc->reply_sz, ioc->reply_depth));
4444 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4445 ioc->name, reply_sz, reply_sz));
4447 sz = (ioc->req_sz * ioc->req_depth);
4448 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4449 ioc->name, ioc->req_sz, ioc->req_depth));
4450 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4451 ioc->name, sz, sz));
4452 total_size += sz;
4454 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4455 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4456 ioc->name, ioc->req_sz, num_chain));
4457 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4458 ioc->name, sz, sz, num_chain));
4460 total_size += sz;
4461 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4462 if (mem == NULL) {
4463 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4464 ioc->name);
4465 goto out_fail;
4468 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4469 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4471 memset(mem, 0, total_size);
4472 ioc->alloc_total += total_size;
4473 ioc->alloc = mem;
4474 ioc->alloc_dma = alloc_dma;
4475 ioc->alloc_sz = total_size;
4476 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4477 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4479 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4480 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4482 alloc_dma += reply_sz;
4483 mem += reply_sz;
4485 /* Request FIFO - WE manage this! */
4487 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4488 ioc->req_frames_dma = alloc_dma;
4490 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4491 ioc->name, mem, (void *)(ulong)alloc_dma));
4493 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4495 #if defined(CONFIG_MTRR) && 0
4497 * Enable Write Combining MTRR for IOC's memory region.
4498 * (at least as much as we can; "size and base must be
4499 * multiples of 4 kiB"
4501 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4503 MTRR_TYPE_WRCOMB, 1);
4504 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4505 ioc->name, ioc->req_frames_dma, sz));
4506 #endif
4508 for (i = 0; i < ioc->req_depth; i++) {
4509 alloc_dma += ioc->req_sz;
4510 mem += ioc->req_sz;
4513 ioc->ChainBuffer = mem;
4514 ioc->ChainBufferDMA = alloc_dma;
4516 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4517 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4519 /* Initialize the free chain Q.
4522 INIT_LIST_HEAD(&ioc->FreeChainQ);
4524 /* Post the chain buffers to the FreeChainQ.
4526 mem = (u8 *)ioc->ChainBuffer;
4527 for (i=0; i < num_chain; i++) {
4528 mf = (MPT_FRAME_HDR *) mem;
4529 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4530 mem += ioc->req_sz;
4533 /* Initialize Request frames linked list
4535 alloc_dma = ioc->req_frames_dma;
4536 mem = (u8 *) ioc->req_frames;
4538 spin_lock_irqsave(&ioc->FreeQlock, flags);
4539 INIT_LIST_HEAD(&ioc->FreeQ);
4540 for (i = 0; i < ioc->req_depth; i++) {
4541 mf = (MPT_FRAME_HDR *) mem;
4543 /* Queue REQUESTs *internally*! */
4544 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4546 mem += ioc->req_sz;
4548 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4550 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4551 ioc->sense_buf_pool =
4552 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4553 if (ioc->sense_buf_pool == NULL) {
4554 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4555 ioc->name);
4556 goto out_fail;
4559 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4560 ioc->alloc_total += sz;
4561 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4562 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4566 /* Post Reply frames to FIFO
4568 alloc_dma = ioc->alloc_dma;
4569 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4570 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4572 for (i = 0; i < ioc->reply_depth; i++) {
4573 /* Write each address to the IOC! */
4574 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4575 alloc_dma += ioc->reply_sz;
4578 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4579 ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
4580 ioc->dma_mask))
4581 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4582 "restoring 64 bit addressing\n", ioc->name));
4584 return 0;
4586 out_fail:
4588 if (ioc->alloc != NULL) {
4589 sz = ioc->alloc_sz;
4590 pci_free_consistent(ioc->pcidev,
4592 ioc->alloc, ioc->alloc_dma);
4593 ioc->reply_frames = NULL;
4594 ioc->req_frames = NULL;
4595 ioc->alloc_total -= sz;
4597 if (ioc->sense_buf_pool != NULL) {
4598 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4599 pci_free_consistent(ioc->pcidev,
4601 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4602 ioc->sense_buf_pool = NULL;
4605 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4606 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev,
4607 DMA_BIT_MASK(64)))
4608 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4609 "restoring 64 bit addressing\n", ioc->name));
4611 return -1;
4614 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4616 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4617 * from IOC via doorbell handshake method.
4618 * @ioc: Pointer to MPT_ADAPTER structure
4619 * @reqBytes: Size of the request in bytes
4620 * @req: Pointer to MPT request frame
4621 * @replyBytes: Expected size of the reply in bytes
4622 * @u16reply: Pointer to area where reply should be written
4623 * @maxwait: Max wait time for a reply (in seconds)
4624 * @sleepFlag: Specifies whether the process can sleep
4626 * NOTES: It is the callers responsibility to byte-swap fields in the
4627 * request which are greater than 1 byte in size. It is also the
4628 * callers responsibility to byte-swap response fields which are
4629 * greater than 1 byte in size.
4631 * Returns 0 for success, non-zero for failure.
4633 static int
4634 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4635 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4637 MPIDefaultReply_t *mptReply;
4638 int failcnt = 0;
4639 int t;
4642 * Get ready to cache a handshake reply
4644 ioc->hs_reply_idx = 0;
4645 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4646 mptReply->MsgLength = 0;
4649 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4650 * then tell IOC that we want to handshake a request of N words.
4651 * (WRITE u32val to Doorbell reg).
4653 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4654 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4655 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4656 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4659 * Wait for IOC's doorbell handshake int
4661 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4662 failcnt++;
4664 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4665 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4667 /* Read doorbell and check for active bit */
4668 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4669 return -1;
4672 * Clear doorbell int (WRITE 0 to IntStatus reg),
4673 * then wait for IOC to ACKnowledge that it's ready for
4674 * our handshake request.
4676 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4677 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4678 failcnt++;
4680 if (!failcnt) {
4681 int ii;
4682 u8 *req_as_bytes = (u8 *) req;
4685 * Stuff request words via doorbell handshake,
4686 * with ACK from IOC for each.
4688 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4689 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4690 (req_as_bytes[(ii*4) + 1] << 8) |
4691 (req_as_bytes[(ii*4) + 2] << 16) |
4692 (req_as_bytes[(ii*4) + 3] << 24));
4694 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4695 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4696 failcnt++;
4699 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4700 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4702 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4703 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4706 * Wait for completion of doorbell handshake reply from the IOC
4708 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4709 failcnt++;
4711 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4712 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4715 * Copy out the cached reply...
4717 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4718 u16reply[ii] = ioc->hs_reply[ii];
4719 } else {
4720 return -99;
4723 return -failcnt;
4726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4728 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4729 * @ioc: Pointer to MPT_ADAPTER structure
4730 * @howlong: How long to wait (in seconds)
4731 * @sleepFlag: Specifies whether the process can sleep
4733 * This routine waits (up to ~2 seconds max) for IOC doorbell
4734 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4735 * bit in its IntStatus register being clear.
4737 * Returns a negative value on failure, else wait loop count.
4739 static int
4740 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4742 int cntdn;
4743 int count = 0;
4744 u32 intstat=0;
4746 cntdn = 1000 * howlong;
4748 if (sleepFlag == CAN_SLEEP) {
4749 while (--cntdn) {
4750 msleep (1);
4751 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4752 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4753 break;
4754 count++;
4756 } else {
4757 while (--cntdn) {
4758 udelay (1000);
4759 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4760 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4761 break;
4762 count++;
4766 if (cntdn) {
4767 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4768 ioc->name, count));
4769 return count;
4772 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4773 ioc->name, count, intstat);
4774 return -1;
4777 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4779 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4780 * @ioc: Pointer to MPT_ADAPTER structure
4781 * @howlong: How long to wait (in seconds)
4782 * @sleepFlag: Specifies whether the process can sleep
4784 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4785 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4787 * Returns a negative value on failure, else wait loop count.
4789 static int
4790 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4792 int cntdn;
4793 int count = 0;
4794 u32 intstat=0;
4796 cntdn = 1000 * howlong;
4797 if (sleepFlag == CAN_SLEEP) {
4798 while (--cntdn) {
4799 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4800 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4801 break;
4802 msleep(1);
4803 count++;
4805 } else {
4806 while (--cntdn) {
4807 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4808 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4809 break;
4810 udelay (1000);
4811 count++;
4815 if (cntdn) {
4816 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4817 ioc->name, count, howlong));
4818 return count;
4821 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4822 ioc->name, count, intstat);
4823 return -1;
4826 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4828 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4829 * @ioc: Pointer to MPT_ADAPTER structure
4830 * @howlong: How long to wait (in seconds)
4831 * @sleepFlag: Specifies whether the process can sleep
4833 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4834 * Reply is cached to IOC private area large enough to hold a maximum
4835 * of 128 bytes of reply data.
4837 * Returns a negative value on failure, else size of reply in WORDS.
4839 static int
4840 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4842 int u16cnt = 0;
4843 int failcnt = 0;
4844 int t;
4845 u16 *hs_reply = ioc->hs_reply;
4846 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4847 u16 hword;
4849 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4852 * Get first two u16's so we can look at IOC's intended reply MsgLength
4854 u16cnt=0;
4855 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4856 failcnt++;
4857 } else {
4858 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4859 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4860 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4861 failcnt++;
4862 else {
4863 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4864 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4868 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4869 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4870 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4873 * If no error (and IOC said MsgLength is > 0), piece together
4874 * reply 16 bits at a time.
4876 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4877 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4878 failcnt++;
4879 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4880 /* don't overflow our IOC hs_reply[] buffer! */
4881 if (u16cnt < ARRAY_SIZE(ioc->hs_reply))
4882 hs_reply[u16cnt] = hword;
4883 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4886 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4887 failcnt++;
4888 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4890 if (failcnt) {
4891 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4892 ioc->name);
4893 return -failcnt;
4895 #if 0
4896 else if (u16cnt != (2 * mptReply->MsgLength)) {
4897 return -101;
4899 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4900 return -102;
4902 #endif
4904 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4905 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4907 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4908 ioc->name, t, u16cnt/2));
4909 return u16cnt/2;
4912 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4914 * GetLanConfigPages - Fetch LANConfig pages.
4915 * @ioc: Pointer to MPT_ADAPTER structure
4917 * Return: 0 for success
4918 * -ENOMEM if no memory available
4919 * -EPERM if not allowed due to ISR context
4920 * -EAGAIN if no msg frames currently available
4921 * -EFAULT for non-successful reply or no reply (timeout)
4923 static int
4924 GetLanConfigPages(MPT_ADAPTER *ioc)
4926 ConfigPageHeader_t hdr;
4927 CONFIGPARMS cfg;
4928 LANPage0_t *ppage0_alloc;
4929 dma_addr_t page0_dma;
4930 LANPage1_t *ppage1_alloc;
4931 dma_addr_t page1_dma;
4932 int rc = 0;
4933 int data_sz;
4934 int copy_sz;
4936 /* Get LAN Page 0 header */
4937 hdr.PageVersion = 0;
4938 hdr.PageLength = 0;
4939 hdr.PageNumber = 0;
4940 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4941 cfg.cfghdr.hdr = &hdr;
4942 cfg.physAddr = -1;
4943 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4944 cfg.dir = 0;
4945 cfg.pageAddr = 0;
4946 cfg.timeout = 0;
4948 if ((rc = mpt_config(ioc, &cfg)) != 0)
4949 return rc;
4951 if (hdr.PageLength > 0) {
4952 data_sz = hdr.PageLength * 4;
4953 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4954 rc = -ENOMEM;
4955 if (ppage0_alloc) {
4956 memset((u8 *)ppage0_alloc, 0, data_sz);
4957 cfg.physAddr = page0_dma;
4958 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4960 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4961 /* save the data */
4962 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4963 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4967 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4969 /* FIXME!
4970 * Normalize endianness of structure data,
4971 * by byte-swapping all > 1 byte fields!
4976 if (rc)
4977 return rc;
4980 /* Get LAN Page 1 header */
4981 hdr.PageVersion = 0;
4982 hdr.PageLength = 0;
4983 hdr.PageNumber = 1;
4984 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4985 cfg.cfghdr.hdr = &hdr;
4986 cfg.physAddr = -1;
4987 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4988 cfg.dir = 0;
4989 cfg.pageAddr = 0;
4991 if ((rc = mpt_config(ioc, &cfg)) != 0)
4992 return rc;
4994 if (hdr.PageLength == 0)
4995 return 0;
4997 data_sz = hdr.PageLength * 4;
4998 rc = -ENOMEM;
4999 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
5000 if (ppage1_alloc) {
5001 memset((u8 *)ppage1_alloc, 0, data_sz);
5002 cfg.physAddr = page1_dma;
5003 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5005 if ((rc = mpt_config(ioc, &cfg)) == 0) {
5006 /* save the data */
5007 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
5008 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
5011 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
5013 /* FIXME!
5014 * Normalize endianness of structure data,
5015 * by byte-swapping all > 1 byte fields!
5020 return rc;
5023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5025 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
5026 * @ioc: Pointer to MPT_ADAPTER structure
5027 * @persist_opcode: see below
5029 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
5030 * devices not currently present.
5031 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
5033 * NOTE: Don't use not this function during interrupt time.
5035 * Returns 0 for success, non-zero error
5038 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5040 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
5042 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
5043 SasIoUnitControlReply_t *sasIoUnitCntrReply;
5044 MPT_FRAME_HDR *mf = NULL;
5045 MPIHeader_t *mpi_hdr;
5046 int ret = 0;
5047 unsigned long timeleft;
5049 mutex_lock(&ioc->mptbase_cmds.mutex);
5051 /* init the internal cmd struct */
5052 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
5053 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
5055 /* insure garbage is not sent to fw */
5056 switch(persist_opcode) {
5058 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
5059 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
5060 break;
5062 default:
5063 ret = -1;
5064 goto out;
5067 printk(KERN_DEBUG "%s: persist_opcode=%x\n",
5068 __func__, persist_opcode);
5070 /* Get a MF for this command.
5072 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5073 printk(KERN_DEBUG "%s: no msg frames!\n", __func__);
5074 ret = -1;
5075 goto out;
5078 mpi_hdr = (MPIHeader_t *) mf;
5079 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
5080 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
5081 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
5082 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
5083 sasIoUnitCntrReq->Operation = persist_opcode;
5085 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5086 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ);
5087 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
5088 ret = -ETIME;
5089 printk(KERN_DEBUG "%s: failed\n", __func__);
5090 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
5091 goto out;
5092 if (!timeleft) {
5093 printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",
5094 ioc->name, __func__);
5095 mpt_HardResetHandler(ioc, CAN_SLEEP);
5096 mpt_free_msg_frame(ioc, mf);
5098 goto out;
5101 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
5102 ret = -1;
5103 goto out;
5106 sasIoUnitCntrReply =
5107 (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply;
5108 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
5109 printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
5110 __func__, sasIoUnitCntrReply->IOCStatus,
5111 sasIoUnitCntrReply->IOCLogInfo);
5112 printk(KERN_DEBUG "%s: failed\n", __func__);
5113 ret = -1;
5114 } else
5115 printk(KERN_DEBUG "%s: success\n", __func__);
5116 out:
5118 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
5119 mutex_unlock(&ioc->mptbase_cmds.mutex);
5120 return ret;
5123 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5125 static void
5126 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
5127 MpiEventDataRaid_t * pRaidEventData)
5129 int volume;
5130 int reason;
5131 int disk;
5132 int status;
5133 int flags;
5134 int state;
5136 volume = pRaidEventData->VolumeID;
5137 reason = pRaidEventData->ReasonCode;
5138 disk = pRaidEventData->PhysDiskNum;
5139 status = le32_to_cpu(pRaidEventData->SettingsStatus);
5140 flags = (status >> 0) & 0xff;
5141 state = (status >> 8) & 0xff;
5143 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
5144 return;
5147 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
5148 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
5149 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
5150 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
5151 ioc->name, disk, volume);
5152 } else {
5153 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
5154 ioc->name, volume);
5157 switch(reason) {
5158 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
5159 printk(MYIOC_s_INFO_FMT " volume has been created\n",
5160 ioc->name);
5161 break;
5163 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
5165 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
5166 ioc->name);
5167 break;
5169 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
5170 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
5171 ioc->name);
5172 break;
5174 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
5175 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
5176 ioc->name,
5177 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
5178 ? "optimal"
5179 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
5180 ? "degraded"
5181 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
5182 ? "failed"
5183 : "state unknown",
5184 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
5185 ? ", enabled" : "",
5186 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
5187 ? ", quiesced" : "",
5188 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
5189 ? ", resync in progress" : "" );
5190 break;
5192 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
5193 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
5194 ioc->name, disk);
5195 break;
5197 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
5198 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
5199 ioc->name);
5200 break;
5202 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
5203 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
5204 ioc->name);
5205 break;
5207 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
5208 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
5209 ioc->name);
5210 break;
5212 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
5213 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
5214 ioc->name,
5215 state == MPI_PHYSDISK0_STATUS_ONLINE
5216 ? "online"
5217 : state == MPI_PHYSDISK0_STATUS_MISSING
5218 ? "missing"
5219 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
5220 ? "not compatible"
5221 : state == MPI_PHYSDISK0_STATUS_FAILED
5222 ? "failed"
5223 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
5224 ? "initializing"
5225 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
5226 ? "offline requested"
5227 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
5228 ? "failed requested"
5229 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
5230 ? "offline"
5231 : "state unknown",
5232 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
5233 ? ", out of sync" : "",
5234 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
5235 ? ", quiesced" : "" );
5236 break;
5238 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
5239 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
5240 ioc->name, disk);
5241 break;
5243 case MPI_EVENT_RAID_RC_SMART_DATA:
5244 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
5245 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
5246 break;
5248 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
5249 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
5250 ioc->name, disk);
5251 break;
5255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5257 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
5258 * @ioc: Pointer to MPT_ADAPTER structure
5260 * Returns: 0 for success
5261 * -ENOMEM if no memory available
5262 * -EPERM if not allowed due to ISR context
5263 * -EAGAIN if no msg frames currently available
5264 * -EFAULT for non-successful reply or no reply (timeout)
5266 static int
5267 GetIoUnitPage2(MPT_ADAPTER *ioc)
5269 ConfigPageHeader_t hdr;
5270 CONFIGPARMS cfg;
5271 IOUnitPage2_t *ppage_alloc;
5272 dma_addr_t page_dma;
5273 int data_sz;
5274 int rc;
5276 /* Get the page header */
5277 hdr.PageVersion = 0;
5278 hdr.PageLength = 0;
5279 hdr.PageNumber = 2;
5280 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
5281 cfg.cfghdr.hdr = &hdr;
5282 cfg.physAddr = -1;
5283 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5284 cfg.dir = 0;
5285 cfg.pageAddr = 0;
5286 cfg.timeout = 0;
5288 if ((rc = mpt_config(ioc, &cfg)) != 0)
5289 return rc;
5291 if (hdr.PageLength == 0)
5292 return 0;
5294 /* Read the config page */
5295 data_sz = hdr.PageLength * 4;
5296 rc = -ENOMEM;
5297 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
5298 if (ppage_alloc) {
5299 memset((u8 *)ppage_alloc, 0, data_sz);
5300 cfg.physAddr = page_dma;
5301 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5303 /* If Good, save data */
5304 if ((rc = mpt_config(ioc, &cfg)) == 0)
5305 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
5307 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
5310 return rc;
5313 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5315 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5316 * @ioc: Pointer to a Adapter Strucutre
5317 * @portnum: IOC port number
5319 * Return: -EFAULT if read of config page header fails
5320 * or if no nvram
5321 * If read of SCSI Port Page 0 fails,
5322 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5323 * Adapter settings: async, narrow
5324 * Return 1
5325 * If read of SCSI Port Page 2 fails,
5326 * Adapter settings valid
5327 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5328 * Return 1
5329 * Else
5330 * Both valid
5331 * Return 0
5332 * CHECK - what type of locking mechanisms should be used????
5334 static int
5335 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
5337 u8 *pbuf;
5338 dma_addr_t buf_dma;
5339 CONFIGPARMS cfg;
5340 ConfigPageHeader_t header;
5341 int ii;
5342 int data, rc = 0;
5344 /* Allocate memory
5346 if (!ioc->spi_data.nvram) {
5347 int sz;
5348 u8 *mem;
5349 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5350 mem = kmalloc(sz, GFP_ATOMIC);
5351 if (mem == NULL)
5352 return -EFAULT;
5354 ioc->spi_data.nvram = (int *) mem;
5356 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5357 ioc->name, ioc->spi_data.nvram, sz));
5360 /* Invalidate NVRAM information
5362 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5363 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5366 /* Read SPP0 header, allocate memory, then read page.
5368 header.PageVersion = 0;
5369 header.PageLength = 0;
5370 header.PageNumber = 0;
5371 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5372 cfg.cfghdr.hdr = &header;
5373 cfg.physAddr = -1;
5374 cfg.pageAddr = portnum;
5375 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5376 cfg.dir = 0;
5377 cfg.timeout = 0; /* use default */
5378 if (mpt_config(ioc, &cfg) != 0)
5379 return -EFAULT;
5381 if (header.PageLength > 0) {
5382 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5383 if (pbuf) {
5384 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5385 cfg.physAddr = buf_dma;
5386 if (mpt_config(ioc, &cfg) != 0) {
5387 ioc->spi_data.maxBusWidth = MPT_NARROW;
5388 ioc->spi_data.maxSyncOffset = 0;
5389 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5390 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5391 rc = 1;
5392 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5393 "Unable to read PortPage0 minSyncFactor=%x\n",
5394 ioc->name, ioc->spi_data.minSyncFactor));
5395 } else {
5396 /* Save the Port Page 0 data
5398 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
5399 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5400 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5402 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5403 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5404 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5405 "noQas due to Capabilities=%x\n",
5406 ioc->name, pPP0->Capabilities));
5408 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5409 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5410 if (data) {
5411 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5412 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5413 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5414 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5415 "PortPage0 minSyncFactor=%x\n",
5416 ioc->name, ioc->spi_data.minSyncFactor));
5417 } else {
5418 ioc->spi_data.maxSyncOffset = 0;
5419 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5422 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5424 /* Update the minSyncFactor based on bus type.
5426 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5427 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
5429 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5430 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5431 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5432 "HVD or SE detected, minSyncFactor=%x\n",
5433 ioc->name, ioc->spi_data.minSyncFactor));
5437 if (pbuf) {
5438 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5443 /* SCSI Port Page 2 - Read the header then the page.
5445 header.PageVersion = 0;
5446 header.PageLength = 0;
5447 header.PageNumber = 2;
5448 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5449 cfg.cfghdr.hdr = &header;
5450 cfg.physAddr = -1;
5451 cfg.pageAddr = portnum;
5452 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5453 cfg.dir = 0;
5454 if (mpt_config(ioc, &cfg) != 0)
5455 return -EFAULT;
5457 if (header.PageLength > 0) {
5458 /* Allocate memory and read SCSI Port Page 2
5460 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5461 if (pbuf) {
5462 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5463 cfg.physAddr = buf_dma;
5464 if (mpt_config(ioc, &cfg) != 0) {
5465 /* Nvram data is left with INVALID mark
5467 rc = 1;
5468 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5470 /* This is an ATTO adapter, read Page2 accordingly
5472 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5473 ATTODeviceInfo_t *pdevice = NULL;
5474 u16 ATTOFlags;
5476 /* Save the Port Page 2 data
5477 * (reformat into a 32bit quantity)
5479 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5480 pdevice = &pPP2->DeviceSettings[ii];
5481 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5482 data = 0;
5484 /* Translate ATTO device flags to LSI format
5486 if (ATTOFlags & ATTOFLAG_DISC)
5487 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5488 if (ATTOFlags & ATTOFLAG_ID_ENB)
5489 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5490 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5491 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5492 if (ATTOFlags & ATTOFLAG_TAGGED)
5493 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5494 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5495 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5497 data = (data << 16) | (pdevice->Period << 8) | 10;
5498 ioc->spi_data.nvram[ii] = data;
5500 } else {
5501 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5502 MpiDeviceInfo_t *pdevice = NULL;
5505 * Save "Set to Avoid SCSI Bus Resets" flag
5507 ioc->spi_data.bus_reset =
5508 (le32_to_cpu(pPP2->PortFlags) &
5509 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5510 0 : 1 ;
5512 /* Save the Port Page 2 data
5513 * (reformat into a 32bit quantity)
5515 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5516 ioc->spi_data.PortFlags = data;
5517 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5518 pdevice = &pPP2->DeviceSettings[ii];
5519 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5520 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5521 ioc->spi_data.nvram[ii] = data;
5525 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5529 /* Update Adapter limits with those from NVRAM
5530 * Comment: Don't need to do this. Target performance
5531 * parameters will never exceed the adapters limits.
5534 return rc;
5537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5539 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5540 * @ioc: Pointer to a Adapter Strucutre
5541 * @portnum: IOC port number
5543 * Return: -EFAULT if read of config page header fails
5544 * or 0 if success.
5546 static int
5547 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5549 CONFIGPARMS cfg;
5550 ConfigPageHeader_t header;
5552 /* Read the SCSI Device Page 1 header
5554 header.PageVersion = 0;
5555 header.PageLength = 0;
5556 header.PageNumber = 1;
5557 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5558 cfg.cfghdr.hdr = &header;
5559 cfg.physAddr = -1;
5560 cfg.pageAddr = portnum;
5561 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5562 cfg.dir = 0;
5563 cfg.timeout = 0;
5564 if (mpt_config(ioc, &cfg) != 0)
5565 return -EFAULT;
5567 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5568 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5570 header.PageVersion = 0;
5571 header.PageLength = 0;
5572 header.PageNumber = 0;
5573 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5574 if (mpt_config(ioc, &cfg) != 0)
5575 return -EFAULT;
5577 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5578 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5580 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5581 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5583 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5584 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5585 return 0;
5589 * mpt_inactive_raid_list_free - This clears this link list.
5590 * @ioc : pointer to per adapter structure
5592 static void
5593 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5595 struct inactive_raid_component_info *component_info, *pNext;
5597 if (list_empty(&ioc->raid_data.inactive_list))
5598 return;
5600 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5601 list_for_each_entry_safe(component_info, pNext,
5602 &ioc->raid_data.inactive_list, list) {
5603 list_del(&component_info->list);
5604 kfree(component_info);
5606 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5610 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5612 * @ioc : pointer to per adapter structure
5613 * @channel : volume channel
5614 * @id : volume target id
5616 static void
5617 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5619 CONFIGPARMS cfg;
5620 ConfigPageHeader_t hdr;
5621 dma_addr_t dma_handle;
5622 pRaidVolumePage0_t buffer = NULL;
5623 int i;
5624 RaidPhysDiskPage0_t phys_disk;
5625 struct inactive_raid_component_info *component_info;
5626 int handle_inactive_volumes;
5628 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5629 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5630 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5631 cfg.pageAddr = (channel << 8) + id;
5632 cfg.cfghdr.hdr = &hdr;
5633 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5635 if (mpt_config(ioc, &cfg) != 0)
5636 goto out;
5638 if (!hdr.PageLength)
5639 goto out;
5641 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5642 &dma_handle);
5644 if (!buffer)
5645 goto out;
5647 cfg.physAddr = dma_handle;
5648 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5650 if (mpt_config(ioc, &cfg) != 0)
5651 goto out;
5653 if (!buffer->NumPhysDisks)
5654 goto out;
5656 handle_inactive_volumes =
5657 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5658 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5659 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5660 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5662 if (!handle_inactive_volumes)
5663 goto out;
5665 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5666 for (i = 0; i < buffer->NumPhysDisks; i++) {
5667 if(mpt_raid_phys_disk_pg0(ioc,
5668 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5669 continue;
5671 if ((component_info = kmalloc(sizeof (*component_info),
5672 GFP_KERNEL)) == NULL)
5673 continue;
5675 component_info->volumeID = id;
5676 component_info->volumeBus = channel;
5677 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5678 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5679 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5680 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5682 list_add_tail(&component_info->list,
5683 &ioc->raid_data.inactive_list);
5685 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5687 out:
5688 if (buffer)
5689 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5690 dma_handle);
5694 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5695 * @ioc: Pointer to a Adapter Structure
5696 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5697 * @phys_disk: requested payload data returned
5699 * Return:
5700 * 0 on success
5701 * -EFAULT if read of config page header fails or data pointer not NULL
5702 * -ENOMEM if pci_alloc failed
5705 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
5706 RaidPhysDiskPage0_t *phys_disk)
5708 CONFIGPARMS cfg;
5709 ConfigPageHeader_t hdr;
5710 dma_addr_t dma_handle;
5711 pRaidPhysDiskPage0_t buffer = NULL;
5712 int rc;
5714 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5715 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5716 memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t));
5718 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION;
5719 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5720 cfg.cfghdr.hdr = &hdr;
5721 cfg.physAddr = -1;
5722 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5724 if (mpt_config(ioc, &cfg) != 0) {
5725 rc = -EFAULT;
5726 goto out;
5729 if (!hdr.PageLength) {
5730 rc = -EFAULT;
5731 goto out;
5734 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5735 &dma_handle);
5737 if (!buffer) {
5738 rc = -ENOMEM;
5739 goto out;
5742 cfg.physAddr = dma_handle;
5743 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5744 cfg.pageAddr = phys_disk_num;
5746 if (mpt_config(ioc, &cfg) != 0) {
5747 rc = -EFAULT;
5748 goto out;
5751 rc = 0;
5752 memcpy(phys_disk, buffer, sizeof(*buffer));
5753 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5755 out:
5757 if (buffer)
5758 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5759 dma_handle);
5761 return rc;
5765 * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
5766 * @ioc: Pointer to a Adapter Structure
5767 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5769 * Return:
5770 * returns number paths
5773 mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
5775 CONFIGPARMS cfg;
5776 ConfigPageHeader_t hdr;
5777 dma_addr_t dma_handle;
5778 pRaidPhysDiskPage1_t buffer = NULL;
5779 int rc;
5781 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5782 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5784 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5785 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5786 hdr.PageNumber = 1;
5787 cfg.cfghdr.hdr = &hdr;
5788 cfg.physAddr = -1;
5789 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5791 if (mpt_config(ioc, &cfg) != 0) {
5792 rc = 0;
5793 goto out;
5796 if (!hdr.PageLength) {
5797 rc = 0;
5798 goto out;
5801 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5802 &dma_handle);
5804 if (!buffer) {
5805 rc = 0;
5806 goto out;
5809 cfg.physAddr = dma_handle;
5810 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5811 cfg.pageAddr = phys_disk_num;
5813 if (mpt_config(ioc, &cfg) != 0) {
5814 rc = 0;
5815 goto out;
5818 rc = buffer->NumPhysDiskPaths;
5819 out:
5821 if (buffer)
5822 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5823 dma_handle);
5825 return rc;
5827 EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
5830 * mpt_raid_phys_disk_pg1 - returns phys disk page 1
5831 * @ioc: Pointer to a Adapter Structure
5832 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5833 * @phys_disk: requested payload data returned
5835 * Return:
5836 * 0 on success
5837 * -EFAULT if read of config page header fails or data pointer not NULL
5838 * -ENOMEM if pci_alloc failed
5841 mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
5842 RaidPhysDiskPage1_t *phys_disk)
5844 CONFIGPARMS cfg;
5845 ConfigPageHeader_t hdr;
5846 dma_addr_t dma_handle;
5847 pRaidPhysDiskPage1_t buffer = NULL;
5848 int rc;
5849 int i;
5850 __le64 sas_address;
5852 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5853 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5854 rc = 0;
5856 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5857 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5858 hdr.PageNumber = 1;
5859 cfg.cfghdr.hdr = &hdr;
5860 cfg.physAddr = -1;
5861 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5863 if (mpt_config(ioc, &cfg) != 0) {
5864 rc = -EFAULT;
5865 goto out;
5868 if (!hdr.PageLength) {
5869 rc = -EFAULT;
5870 goto out;
5873 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5874 &dma_handle);
5876 if (!buffer) {
5877 rc = -ENOMEM;
5878 goto out;
5881 cfg.physAddr = dma_handle;
5882 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5883 cfg.pageAddr = phys_disk_num;
5885 if (mpt_config(ioc, &cfg) != 0) {
5886 rc = -EFAULT;
5887 goto out;
5890 phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
5891 phys_disk->PhysDiskNum = phys_disk_num;
5892 for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
5893 phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
5894 phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
5895 phys_disk->Path[i].OwnerIdentifier =
5896 buffer->Path[i].OwnerIdentifier;
5897 phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
5898 memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
5899 sas_address = le64_to_cpu(sas_address);
5900 memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
5901 memcpy(&sas_address,
5902 &buffer->Path[i].OwnerWWID, sizeof(__le64));
5903 sas_address = le64_to_cpu(sas_address);
5904 memcpy(&phys_disk->Path[i].OwnerWWID,
5905 &sas_address, sizeof(__le64));
5908 out:
5910 if (buffer)
5911 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5912 dma_handle);
5914 return rc;
5916 EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
5920 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5921 * @ioc: Pointer to a Adapter Strucutre
5923 * Return:
5924 * 0 on success
5925 * -EFAULT if read of config page header fails or data pointer not NULL
5926 * -ENOMEM if pci_alloc failed
5929 mpt_findImVolumes(MPT_ADAPTER *ioc)
5931 IOCPage2_t *pIoc2;
5932 u8 *mem;
5933 dma_addr_t ioc2_dma;
5934 CONFIGPARMS cfg;
5935 ConfigPageHeader_t header;
5936 int rc = 0;
5937 int iocpage2sz;
5938 int i;
5940 if (!ioc->ir_firmware)
5941 return 0;
5943 /* Free the old page
5945 kfree(ioc->raid_data.pIocPg2);
5946 ioc->raid_data.pIocPg2 = NULL;
5947 mpt_inactive_raid_list_free(ioc);
5949 /* Read IOCP2 header then the page.
5951 header.PageVersion = 0;
5952 header.PageLength = 0;
5953 header.PageNumber = 2;
5954 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5955 cfg.cfghdr.hdr = &header;
5956 cfg.physAddr = -1;
5957 cfg.pageAddr = 0;
5958 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5959 cfg.dir = 0;
5960 cfg.timeout = 0;
5961 if (mpt_config(ioc, &cfg) != 0)
5962 return -EFAULT;
5964 if (header.PageLength == 0)
5965 return -EFAULT;
5967 iocpage2sz = header.PageLength * 4;
5968 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5969 if (!pIoc2)
5970 return -ENOMEM;
5972 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5973 cfg.physAddr = ioc2_dma;
5974 if (mpt_config(ioc, &cfg) != 0)
5975 goto out;
5977 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5978 if (!mem)
5979 goto out;
5981 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5982 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5984 mpt_read_ioc_pg_3(ioc);
5986 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5987 mpt_inactive_raid_volumes(ioc,
5988 pIoc2->RaidVolume[i].VolumeBus,
5989 pIoc2->RaidVolume[i].VolumeID);
5991 out:
5992 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5994 return rc;
5997 static int
5998 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
6000 IOCPage3_t *pIoc3;
6001 u8 *mem;
6002 CONFIGPARMS cfg;
6003 ConfigPageHeader_t header;
6004 dma_addr_t ioc3_dma;
6005 int iocpage3sz = 0;
6007 /* Free the old page
6009 kfree(ioc->raid_data.pIocPg3);
6010 ioc->raid_data.pIocPg3 = NULL;
6012 /* There is at least one physical disk.
6013 * Read and save IOC Page 3
6015 header.PageVersion = 0;
6016 header.PageLength = 0;
6017 header.PageNumber = 3;
6018 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6019 cfg.cfghdr.hdr = &header;
6020 cfg.physAddr = -1;
6021 cfg.pageAddr = 0;
6022 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6023 cfg.dir = 0;
6024 cfg.timeout = 0;
6025 if (mpt_config(ioc, &cfg) != 0)
6026 return 0;
6028 if (header.PageLength == 0)
6029 return 0;
6031 /* Read Header good, alloc memory
6033 iocpage3sz = header.PageLength * 4;
6034 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
6035 if (!pIoc3)
6036 return 0;
6038 /* Read the Page and save the data
6039 * into malloc'd memory.
6041 cfg.physAddr = ioc3_dma;
6042 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6043 if (mpt_config(ioc, &cfg) == 0) {
6044 mem = kmalloc(iocpage3sz, GFP_KERNEL);
6045 if (mem) {
6046 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
6047 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
6051 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
6053 return 0;
6056 static void
6057 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
6059 IOCPage4_t *pIoc4;
6060 CONFIGPARMS cfg;
6061 ConfigPageHeader_t header;
6062 dma_addr_t ioc4_dma;
6063 int iocpage4sz;
6065 /* Read and save IOC Page 4
6067 header.PageVersion = 0;
6068 header.PageLength = 0;
6069 header.PageNumber = 4;
6070 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6071 cfg.cfghdr.hdr = &header;
6072 cfg.physAddr = -1;
6073 cfg.pageAddr = 0;
6074 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6075 cfg.dir = 0;
6076 cfg.timeout = 0;
6077 if (mpt_config(ioc, &cfg) != 0)
6078 return;
6080 if (header.PageLength == 0)
6081 return;
6083 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
6084 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
6085 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
6086 if (!pIoc4)
6087 return;
6088 ioc->alloc_total += iocpage4sz;
6089 } else {
6090 ioc4_dma = ioc->spi_data.IocPg4_dma;
6091 iocpage4sz = ioc->spi_data.IocPg4Sz;
6094 /* Read the Page into dma memory.
6096 cfg.physAddr = ioc4_dma;
6097 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6098 if (mpt_config(ioc, &cfg) == 0) {
6099 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
6100 ioc->spi_data.IocPg4_dma = ioc4_dma;
6101 ioc->spi_data.IocPg4Sz = iocpage4sz;
6102 } else {
6103 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
6104 ioc->spi_data.pIocPg4 = NULL;
6105 ioc->alloc_total -= iocpage4sz;
6109 static void
6110 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
6112 IOCPage1_t *pIoc1;
6113 CONFIGPARMS cfg;
6114 ConfigPageHeader_t header;
6115 dma_addr_t ioc1_dma;
6116 int iocpage1sz = 0;
6117 u32 tmp;
6119 /* Check the Coalescing Timeout in IOC Page 1
6121 header.PageVersion = 0;
6122 header.PageLength = 0;
6123 header.PageNumber = 1;
6124 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6125 cfg.cfghdr.hdr = &header;
6126 cfg.physAddr = -1;
6127 cfg.pageAddr = 0;
6128 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6129 cfg.dir = 0;
6130 cfg.timeout = 0;
6131 if (mpt_config(ioc, &cfg) != 0)
6132 return;
6134 if (header.PageLength == 0)
6135 return;
6137 /* Read Header good, alloc memory
6139 iocpage1sz = header.PageLength * 4;
6140 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
6141 if (!pIoc1)
6142 return;
6144 /* Read the Page and check coalescing timeout
6146 cfg.physAddr = ioc1_dma;
6147 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6148 if (mpt_config(ioc, &cfg) == 0) {
6150 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
6151 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
6152 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
6154 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
6155 ioc->name, tmp));
6157 if (tmp > MPT_COALESCING_TIMEOUT) {
6158 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
6160 /* Write NVRAM and current
6162 cfg.dir = 1;
6163 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6164 if (mpt_config(ioc, &cfg) == 0) {
6165 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
6166 ioc->name, MPT_COALESCING_TIMEOUT));
6168 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
6169 if (mpt_config(ioc, &cfg) == 0) {
6170 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6171 "Reset NVRAM Coalescing Timeout to = %d\n",
6172 ioc->name, MPT_COALESCING_TIMEOUT));
6173 } else {
6174 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6175 "Reset NVRAM Coalescing Timeout Failed\n",
6176 ioc->name));
6179 } else {
6180 dprintk(ioc, printk(MYIOC_s_WARN_FMT
6181 "Reset of Current Coalescing Timeout Failed!\n",
6182 ioc->name));
6186 } else {
6187 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
6191 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
6193 return;
6196 static void
6197 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
6199 CONFIGPARMS cfg;
6200 ConfigPageHeader_t hdr;
6201 dma_addr_t buf_dma;
6202 ManufacturingPage0_t *pbuf = NULL;
6204 memset(&cfg, 0 , sizeof(CONFIGPARMS));
6205 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
6207 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
6208 cfg.cfghdr.hdr = &hdr;
6209 cfg.physAddr = -1;
6210 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6211 cfg.timeout = 10;
6213 if (mpt_config(ioc, &cfg) != 0)
6214 goto out;
6216 if (!cfg.cfghdr.hdr->PageLength)
6217 goto out;
6219 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6220 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
6221 if (!pbuf)
6222 goto out;
6224 cfg.physAddr = buf_dma;
6226 if (mpt_config(ioc, &cfg) != 0)
6227 goto out;
6229 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
6230 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
6231 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
6233 out:
6235 if (pbuf)
6236 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
6239 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6241 * SendEventNotification - Send EventNotification (on or off) request to adapter
6242 * @ioc: Pointer to MPT_ADAPTER structure
6243 * @EvSwitch: Event switch flags
6244 * @sleepFlag: Specifies whether the process can sleep
6246 static int
6247 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag)
6249 EventNotification_t evn;
6250 MPIDefaultReply_t reply_buf;
6252 memset(&evn, 0, sizeof(EventNotification_t));
6253 memset(&reply_buf, 0, sizeof(MPIDefaultReply_t));
6255 evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION;
6256 evn.Switch = EvSwitch;
6257 evn.MsgContext = cpu_to_le32(mpt_base_index << 16);
6259 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6260 "Sending EventNotification (%d) request %p\n",
6261 ioc->name, EvSwitch, &evn));
6263 return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t),
6264 (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30,
6265 sleepFlag);
6268 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6270 * SendEventAck - Send EventAck request to MPT adapter.
6271 * @ioc: Pointer to MPT_ADAPTER structure
6272 * @evnp: Pointer to original EventNotification request
6274 static int
6275 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
6277 EventAck_t *pAck;
6279 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6280 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
6281 ioc->name, __func__));
6282 return -1;
6285 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
6287 pAck->Function = MPI_FUNCTION_EVENT_ACK;
6288 pAck->ChainOffset = 0;
6289 pAck->Reserved[0] = pAck->Reserved[1] = 0;
6290 pAck->MsgFlags = 0;
6291 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
6292 pAck->Event = evnp->Event;
6293 pAck->EventContext = evnp->EventContext;
6295 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
6297 return 0;
6300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6302 * mpt_config - Generic function to issue config message
6303 * @ioc: Pointer to an adapter structure
6304 * @pCfg: Pointer to a configuration structure. Struct contains
6305 * action, page address, direction, physical address
6306 * and pointer to a configuration page header
6307 * Page header is updated.
6309 * Returns 0 for success
6310 * -EPERM if not allowed due to ISR context
6311 * -EAGAIN if no msg frames currently available
6312 * -EFAULT for non-successful reply or no reply (timeout)
6315 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
6317 Config_t *pReq;
6318 ConfigReply_t *pReply;
6319 ConfigExtendedPageHeader_t *pExtHdr = NULL;
6320 MPT_FRAME_HDR *mf;
6321 int ii;
6322 int flagsLength;
6323 long timeout;
6324 int ret;
6325 u8 page_type = 0, extend_page;
6326 unsigned long timeleft;
6327 unsigned long flags;
6328 int in_isr;
6329 u8 issue_hard_reset = 0;
6330 u8 retry_count = 0;
6332 /* Prevent calling wait_event() (below), if caller happens
6333 * to be in ISR context, because that is fatal!
6335 in_isr = in_interrupt();
6336 if (in_isr) {
6337 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
6338 ioc->name));
6339 return -EPERM;
6342 /* don't send a config page during diag reset */
6343 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6344 if (ioc->ioc_reset_in_progress) {
6345 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6346 "%s: busy with host reset\n", ioc->name, __func__));
6347 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6348 return -EBUSY;
6350 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6352 /* don't send if no chance of success */
6353 if (!ioc->active ||
6354 mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) {
6355 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6356 "%s: ioc not operational, %d, %xh\n",
6357 ioc->name, __func__, ioc->active,
6358 mpt_GetIocState(ioc, 0)));
6359 return -EFAULT;
6362 retry_config:
6363 mutex_lock(&ioc->mptbase_cmds.mutex);
6364 /* init the internal cmd struct */
6365 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
6366 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
6368 /* Get and Populate a free Frame
6370 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6371 dcprintk(ioc, printk(MYIOC_s_WARN_FMT
6372 "mpt_config: no msg frames!\n", ioc->name));
6373 ret = -EAGAIN;
6374 goto out;
6377 pReq = (Config_t *)mf;
6378 pReq->Action = pCfg->action;
6379 pReq->Reserved = 0;
6380 pReq->ChainOffset = 0;
6381 pReq->Function = MPI_FUNCTION_CONFIG;
6383 /* Assume page type is not extended and clear "reserved" fields. */
6384 pReq->ExtPageLength = 0;
6385 pReq->ExtPageType = 0;
6386 pReq->MsgFlags = 0;
6388 for (ii=0; ii < 8; ii++)
6389 pReq->Reserved2[ii] = 0;
6391 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
6392 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
6393 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
6394 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
6396 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
6397 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
6398 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
6399 pReq->ExtPageType = pExtHdr->ExtPageType;
6400 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
6402 /* Page Length must be treated as a reserved field for the
6403 * extended header.
6405 pReq->Header.PageLength = 0;
6408 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
6410 /* Add a SGE to the config request.
6412 if (pCfg->dir)
6413 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
6414 else
6415 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
6417 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
6418 MPI_CONFIG_PAGETYPE_EXTENDED) {
6419 flagsLength |= pExtHdr->ExtPageLength * 4;
6420 page_type = pReq->ExtPageType;
6421 extend_page = 1;
6422 } else {
6423 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
6424 page_type = pReq->Header.PageType;
6425 extend_page = 0;
6428 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6429 "Sending Config request type 0x%x, page 0x%x and action %d\n",
6430 ioc->name, page_type, pReq->Header.PageNumber, pReq->Action));
6432 ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
6433 timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout;
6434 mpt_put_msg_frame(mpt_base_index, ioc, mf);
6435 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done,
6436 timeout);
6437 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
6438 ret = -ETIME;
6439 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6440 "Failed Sending Config request type 0x%x, page 0x%x,"
6441 " action %d, status %xh, time left %ld\n\n",
6442 ioc->name, page_type, pReq->Header.PageNumber,
6443 pReq->Action, ioc->mptbase_cmds.status, timeleft));
6444 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
6445 goto out;
6446 if (!timeleft)
6447 issue_hard_reset = 1;
6448 goto out;
6451 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
6452 ret = -1;
6453 goto out;
6455 pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply;
6456 ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
6457 if (ret == MPI_IOCSTATUS_SUCCESS) {
6458 if (extend_page) {
6459 pCfg->cfghdr.ehdr->ExtPageLength =
6460 le16_to_cpu(pReply->ExtPageLength);
6461 pCfg->cfghdr.ehdr->ExtPageType =
6462 pReply->ExtPageType;
6464 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
6465 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
6466 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
6467 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
6471 if (retry_count)
6472 printk(MYIOC_s_INFO_FMT "Retry completed "
6473 "ret=0x%x timeleft=%ld\n",
6474 ioc->name, ret, timeleft);
6476 dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
6477 ret, le32_to_cpu(pReply->IOCLogInfo)));
6479 out:
6481 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
6482 mutex_unlock(&ioc->mptbase_cmds.mutex);
6483 if (issue_hard_reset) {
6484 issue_hard_reset = 0;
6485 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
6486 ioc->name, __func__);
6487 mpt_HardResetHandler(ioc, CAN_SLEEP);
6488 mpt_free_msg_frame(ioc, mf);
6489 /* attempt one retry for a timed out command */
6490 if (!retry_count) {
6491 printk(MYIOC_s_INFO_FMT
6492 "Attempting Retry Config request"
6493 " type 0x%x, page 0x%x,"
6494 " action %d\n", ioc->name, page_type,
6495 pCfg->cfghdr.hdr->PageNumber, pCfg->action);
6496 retry_count++;
6497 goto retry_config;
6500 return ret;
6504 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6506 * mpt_ioc_reset - Base cleanup for hard reset
6507 * @ioc: Pointer to the adapter structure
6508 * @reset_phase: Indicates pre- or post-reset functionality
6510 * Remark: Frees resources with internally generated commands.
6512 static int
6513 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
6515 switch (reset_phase) {
6516 case MPT_IOC_SETUP_RESET:
6517 ioc->taskmgmt_quiesce_io = 1;
6518 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6519 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
6520 break;
6521 case MPT_IOC_PRE_RESET:
6522 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6523 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
6524 break;
6525 case MPT_IOC_POST_RESET:
6526 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6527 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
6528 /* wake up mptbase_cmds */
6529 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
6530 ioc->mptbase_cmds.status |=
6531 MPT_MGMT_STATUS_DID_IOCRESET;
6532 complete(&ioc->mptbase_cmds.done);
6534 /* wake up taskmgmt_cmds */
6535 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
6536 ioc->taskmgmt_cmds.status |=
6537 MPT_MGMT_STATUS_DID_IOCRESET;
6538 complete(&ioc->taskmgmt_cmds.done);
6540 break;
6541 default:
6542 break;
6545 return 1; /* currently means nothing really */
6549 #ifdef CONFIG_PROC_FS /* { */
6550 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6552 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6554 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6556 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6558 * Returns 0 for success, non-zero for failure.
6560 static int
6561 procmpt_create(void)
6563 struct proc_dir_entry *ent;
6565 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6566 if (mpt_proc_root_dir == NULL)
6567 return -ENOTDIR;
6569 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6570 if (ent)
6571 ent->read_proc = procmpt_summary_read;
6573 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6574 if (ent)
6575 ent->read_proc = procmpt_version_read;
6577 return 0;
6580 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6582 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6584 * Returns 0 for success, non-zero for failure.
6586 static void
6587 procmpt_destroy(void)
6589 remove_proc_entry("version", mpt_proc_root_dir);
6590 remove_proc_entry("summary", mpt_proc_root_dir);
6591 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6596 * procmpt_summary_read - Handle read request of a summary file
6597 * @buf: Pointer to area to write information
6598 * @start: Pointer to start pointer
6599 * @offset: Offset to start writing
6600 * @request: Amount of read data requested
6601 * @eof: Pointer to EOF integer
6602 * @data: Pointer
6604 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6605 * Returns number of characters written to process performing the read.
6607 static int
6608 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6610 MPT_ADAPTER *ioc;
6611 char *out = buf;
6612 int len;
6614 if (data) {
6615 int more = 0;
6617 ioc = data;
6618 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6620 out += more;
6621 } else {
6622 list_for_each_entry(ioc, &ioc_list, list) {
6623 int more = 0;
6625 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6627 out += more;
6628 if ((out-buf) >= request)
6629 break;
6633 len = out - buf;
6635 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6638 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6640 * procmpt_version_read - Handle read request from /proc/mpt/version.
6641 * @buf: Pointer to area to write information
6642 * @start: Pointer to start pointer
6643 * @offset: Offset to start writing
6644 * @request: Amount of read data requested
6645 * @eof: Pointer to EOF integer
6646 * @data: Pointer
6648 * Returns number of characters written to process performing the read.
6650 static int
6651 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6653 u8 cb_idx;
6654 int scsi, fc, sas, lan, ctl, targ, dmp;
6655 char *drvname;
6656 int len;
6658 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6659 len += sprintf(buf+len, " Fusion MPT base driver\n");
6661 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6662 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6663 drvname = NULL;
6664 if (MptCallbacks[cb_idx]) {
6665 switch (MptDriverClass[cb_idx]) {
6666 case MPTSPI_DRIVER:
6667 if (!scsi++) drvname = "SPI host";
6668 break;
6669 case MPTFC_DRIVER:
6670 if (!fc++) drvname = "FC host";
6671 break;
6672 case MPTSAS_DRIVER:
6673 if (!sas++) drvname = "SAS host";
6674 break;
6675 case MPTLAN_DRIVER:
6676 if (!lan++) drvname = "LAN";
6677 break;
6678 case MPTSTM_DRIVER:
6679 if (!targ++) drvname = "SCSI target";
6680 break;
6681 case MPTCTL_DRIVER:
6682 if (!ctl++) drvname = "ioctl";
6683 break;
6686 if (drvname)
6687 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
6691 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6694 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6696 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6697 * @buf: Pointer to area to write information
6698 * @start: Pointer to start pointer
6699 * @offset: Offset to start writing
6700 * @request: Amount of read data requested
6701 * @eof: Pointer to EOF integer
6702 * @data: Pointer
6704 * Returns number of characters written to process performing the read.
6706 static int
6707 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6709 MPT_ADAPTER *ioc = data;
6710 int len;
6711 char expVer[32];
6712 int sz;
6713 int p;
6715 mpt_get_fw_exp_ver(expVer, ioc);
6717 len = sprintf(buf, "%s:", ioc->name);
6718 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6719 len += sprintf(buf+len, " (f/w download boot flag set)");
6720 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6721 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6723 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
6724 ioc->facts.ProductID,
6725 ioc->prod_name);
6726 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6727 if (ioc->facts.FWImageSize)
6728 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6729 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6730 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6731 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
6733 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
6734 ioc->facts.CurrentHostMfaHighAddr);
6735 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
6736 ioc->facts.CurrentSenseBufferHighAddr);
6738 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6739 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6741 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6742 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6744 * Rounding UP to nearest 4-kB boundary here...
6746 sz = (ioc->req_sz * ioc->req_depth) + 128;
6747 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6748 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6749 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6750 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6751 4*ioc->facts.RequestFrameSize,
6752 ioc->facts.GlobalCredits);
6754 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
6755 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6756 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6757 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6758 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6759 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6760 ioc->facts.CurReplyFrameSize,
6761 ioc->facts.ReplyQueueDepth);
6763 len += sprintf(buf+len, " MaxDevices = %d\n",
6764 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6765 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6767 /* per-port info */
6768 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6769 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
6770 p+1,
6771 ioc->facts.NumberOfPorts);
6772 if (ioc->bus_type == FC) {
6773 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6774 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6775 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6776 a[5], a[4], a[3], a[2], a[1], a[0]);
6778 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
6779 ioc->fc_port_page0[p].WWNN.High,
6780 ioc->fc_port_page0[p].WWNN.Low,
6781 ioc->fc_port_page0[p].WWPN.High,
6782 ioc->fc_port_page0[p].WWPN.Low);
6786 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6789 #endif /* CONFIG_PROC_FS } */
6791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6792 static void
6793 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6795 buf[0] ='\0';
6796 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6797 sprintf(buf, " (Exp %02d%02d)",
6798 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6799 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6801 /* insider hack! */
6802 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6803 strcat(buf, " [MDBG]");
6807 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6809 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6810 * @ioc: Pointer to MPT_ADAPTER structure
6811 * @buffer: Pointer to buffer where IOC summary info should be written
6812 * @size: Pointer to number of bytes we wrote (set by this routine)
6813 * @len: Offset at which to start writing in buffer
6814 * @showlan: Display LAN stuff?
6816 * This routine writes (english readable) ASCII text, which represents
6817 * a summary of IOC information, to a buffer.
6819 void
6820 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6822 char expVer[32];
6823 int y;
6825 mpt_get_fw_exp_ver(expVer, ioc);
6828 * Shorter summary of attached ioc's...
6830 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6831 ioc->name,
6832 ioc->prod_name,
6833 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6834 ioc->facts.FWVersion.Word,
6835 expVer,
6836 ioc->facts.NumberOfPorts,
6837 ioc->req_depth);
6839 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6840 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6841 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6842 a[5], a[4], a[3], a[2], a[1], a[0]);
6845 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6847 if (!ioc->active)
6848 y += sprintf(buffer+len+y, " (disabled)");
6850 y += sprintf(buffer+len+y, "\n");
6852 *size = y;
6855 * mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment
6856 * @ioc: Pointer to MPT_ADAPTER structure
6858 * Returns 0 for SUCCESS or -1 if FAILED.
6860 * If -1 is return, then it was not possible to set the flags
6863 mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6865 unsigned long flags;
6866 int retval;
6868 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6869 if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
6870 (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
6871 retval = -1;
6872 goto out;
6874 retval = 0;
6875 ioc->taskmgmt_in_progress = 1;
6876 ioc->taskmgmt_quiesce_io = 1;
6877 if (ioc->alt_ioc) {
6878 ioc->alt_ioc->taskmgmt_in_progress = 1;
6879 ioc->alt_ioc->taskmgmt_quiesce_io = 1;
6881 out:
6882 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6883 return retval;
6885 EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
6888 * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment
6889 * @ioc: Pointer to MPT_ADAPTER structure
6892 void
6893 mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6895 unsigned long flags;
6897 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6898 ioc->taskmgmt_in_progress = 0;
6899 ioc->taskmgmt_quiesce_io = 0;
6900 if (ioc->alt_ioc) {
6901 ioc->alt_ioc->taskmgmt_in_progress = 0;
6902 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
6904 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6906 EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
6910 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6911 * the kernel
6912 * @ioc: Pointer to MPT_ADAPTER structure
6915 void
6916 mpt_halt_firmware(MPT_ADAPTER *ioc)
6918 u32 ioc_raw_state;
6920 ioc_raw_state = mpt_GetIocState(ioc, 0);
6922 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6923 printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6924 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6925 panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6926 ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6927 } else {
6928 CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6929 panic("%s: Firmware is halted due to command timeout\n",
6930 ioc->name);
6933 EXPORT_SYMBOL(mpt_halt_firmware);
6935 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6937 * Reset Handling
6939 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6941 * mpt_HardResetHandler - Generic reset handler
6942 * @ioc: Pointer to MPT_ADAPTER structure
6943 * @sleepFlag: Indicates if sleep or schedule must be called.
6945 * Issues SCSI Task Management call based on input arg values.
6946 * If TaskMgmt fails, returns associated SCSI request.
6948 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6949 * or a non-interrupt thread. In the former, must not call schedule().
6951 * Note: A return of -1 is a FATAL error case, as it means a
6952 * FW reload/initialization failed.
6954 * Returns 0 for SUCCESS or -1 if FAILED.
6957 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6959 int rc;
6960 u8 cb_idx;
6961 unsigned long flags;
6962 unsigned long time_count;
6964 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6965 #ifdef MFCNT
6966 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6967 printk("MF count 0x%x !\n", ioc->mfcnt);
6968 #endif
6969 if (mpt_fwfault_debug)
6970 mpt_halt_firmware(ioc);
6972 /* Reset the adapter. Prevent more than 1 call to
6973 * mpt_do_ioc_recovery at any instant in time.
6975 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6976 if (ioc->ioc_reset_in_progress) {
6977 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6978 return 0;
6980 ioc->ioc_reset_in_progress = 1;
6981 if (ioc->alt_ioc)
6982 ioc->alt_ioc->ioc_reset_in_progress = 1;
6983 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6985 /* FIXME: If do_ioc_recovery fails, repeat....
6988 /* The SCSI driver needs to adjust timeouts on all current
6989 * commands prior to the diagnostic reset being issued.
6990 * Prevents timeouts occurring during a diagnostic reset...very bad.
6991 * For all other protocol drivers, this is a no-op.
6993 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6994 if (MptResetHandlers[cb_idx]) {
6995 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6996 if (ioc->alt_ioc)
6997 mpt_signal_reset(cb_idx, ioc->alt_ioc,
6998 MPT_IOC_SETUP_RESET);
7002 time_count = jiffies;
7003 rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
7004 if (rc != 0) {
7005 printk(KERN_WARNING MYNAM
7006 ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name);
7007 } else {
7008 if (ioc->hard_resets < -1)
7009 ioc->hard_resets++;
7012 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7013 ioc->ioc_reset_in_progress = 0;
7014 ioc->taskmgmt_quiesce_io = 0;
7015 ioc->taskmgmt_in_progress = 0;
7016 if (ioc->alt_ioc) {
7017 ioc->alt_ioc->ioc_reset_in_progress = 0;
7018 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
7019 ioc->alt_ioc->taskmgmt_in_progress = 0;
7021 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7023 dtmprintk(ioc,
7024 printk(MYIOC_s_DEBUG_FMT
7025 "HardResetHandler: completed (%d seconds): %s\n", ioc->name,
7026 jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ?
7027 "SUCCESS" : "FAILED")));
7029 return rc;
7032 #ifdef CONFIG_FUSION_LOGGING
7033 static void
7034 mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
7036 char *ds = NULL;
7037 u32 evData0;
7038 int ii;
7039 u8 event;
7040 char *evStr = ioc->evStr;
7042 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7043 evData0 = le32_to_cpu(pEventReply->Data[0]);
7045 switch(event) {
7046 case MPI_EVENT_NONE:
7047 ds = "None";
7048 break;
7049 case MPI_EVENT_LOG_DATA:
7050 ds = "Log Data";
7051 break;
7052 case MPI_EVENT_STATE_CHANGE:
7053 ds = "State Change";
7054 break;
7055 case MPI_EVENT_UNIT_ATTENTION:
7056 ds = "Unit Attention";
7057 break;
7058 case MPI_EVENT_IOC_BUS_RESET:
7059 ds = "IOC Bus Reset";
7060 break;
7061 case MPI_EVENT_EXT_BUS_RESET:
7062 ds = "External Bus Reset";
7063 break;
7064 case MPI_EVENT_RESCAN:
7065 ds = "Bus Rescan Event";
7066 break;
7067 case MPI_EVENT_LINK_STATUS_CHANGE:
7068 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
7069 ds = "Link Status(FAILURE) Change";
7070 else
7071 ds = "Link Status(ACTIVE) Change";
7072 break;
7073 case MPI_EVENT_LOOP_STATE_CHANGE:
7074 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
7075 ds = "Loop State(LIP) Change";
7076 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
7077 ds = "Loop State(LPE) Change";
7078 else
7079 ds = "Loop State(LPB) Change";
7080 break;
7081 case MPI_EVENT_LOGOUT:
7082 ds = "Logout";
7083 break;
7084 case MPI_EVENT_EVENT_CHANGE:
7085 if (evData0)
7086 ds = "Events ON";
7087 else
7088 ds = "Events OFF";
7089 break;
7090 case MPI_EVENT_INTEGRATED_RAID:
7092 u8 ReasonCode = (u8)(evData0 >> 16);
7093 switch (ReasonCode) {
7094 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
7095 ds = "Integrated Raid: Volume Created";
7096 break;
7097 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
7098 ds = "Integrated Raid: Volume Deleted";
7099 break;
7100 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
7101 ds = "Integrated Raid: Volume Settings Changed";
7102 break;
7103 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
7104 ds = "Integrated Raid: Volume Status Changed";
7105 break;
7106 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
7107 ds = "Integrated Raid: Volume Physdisk Changed";
7108 break;
7109 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
7110 ds = "Integrated Raid: Physdisk Created";
7111 break;
7112 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
7113 ds = "Integrated Raid: Physdisk Deleted";
7114 break;
7115 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
7116 ds = "Integrated Raid: Physdisk Settings Changed";
7117 break;
7118 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
7119 ds = "Integrated Raid: Physdisk Status Changed";
7120 break;
7121 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
7122 ds = "Integrated Raid: Domain Validation Needed";
7123 break;
7124 case MPI_EVENT_RAID_RC_SMART_DATA :
7125 ds = "Integrated Raid; Smart Data";
7126 break;
7127 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
7128 ds = "Integrated Raid: Replace Action Started";
7129 break;
7130 default:
7131 ds = "Integrated Raid";
7132 break;
7134 break;
7136 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
7137 ds = "SCSI Device Status Change";
7138 break;
7139 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
7141 u8 id = (u8)(evData0);
7142 u8 channel = (u8)(evData0 >> 8);
7143 u8 ReasonCode = (u8)(evData0 >> 16);
7144 switch (ReasonCode) {
7145 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
7146 snprintf(evStr, EVENT_DESCR_STR_SZ,
7147 "SAS Device Status Change: Added: "
7148 "id=%d channel=%d", id, channel);
7149 break;
7150 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
7151 snprintf(evStr, EVENT_DESCR_STR_SZ,
7152 "SAS Device Status Change: Deleted: "
7153 "id=%d channel=%d", id, channel);
7154 break;
7155 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7156 snprintf(evStr, EVENT_DESCR_STR_SZ,
7157 "SAS Device Status Change: SMART Data: "
7158 "id=%d channel=%d", id, channel);
7159 break;
7160 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
7161 snprintf(evStr, EVENT_DESCR_STR_SZ,
7162 "SAS Device Status Change: No Persistancy: "
7163 "id=%d channel=%d", id, channel);
7164 break;
7165 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7166 snprintf(evStr, EVENT_DESCR_STR_SZ,
7167 "SAS Device Status Change: Unsupported Device "
7168 "Discovered : id=%d channel=%d", id, channel);
7169 break;
7170 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7171 snprintf(evStr, EVENT_DESCR_STR_SZ,
7172 "SAS Device Status Change: Internal Device "
7173 "Reset : id=%d channel=%d", id, channel);
7174 break;
7175 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7176 snprintf(evStr, EVENT_DESCR_STR_SZ,
7177 "SAS Device Status Change: Internal Task "
7178 "Abort : id=%d channel=%d", id, channel);
7179 break;
7180 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7181 snprintf(evStr, EVENT_DESCR_STR_SZ,
7182 "SAS Device Status Change: Internal Abort "
7183 "Task Set : id=%d channel=%d", id, channel);
7184 break;
7185 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7186 snprintf(evStr, EVENT_DESCR_STR_SZ,
7187 "SAS Device Status Change: Internal Clear "
7188 "Task Set : id=%d channel=%d", id, channel);
7189 break;
7190 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7191 snprintf(evStr, EVENT_DESCR_STR_SZ,
7192 "SAS Device Status Change: Internal Query "
7193 "Task : id=%d channel=%d", id, channel);
7194 break;
7195 default:
7196 snprintf(evStr, EVENT_DESCR_STR_SZ,
7197 "SAS Device Status Change: Unknown: "
7198 "id=%d channel=%d", id, channel);
7199 break;
7201 break;
7203 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
7204 ds = "Bus Timer Expired";
7205 break;
7206 case MPI_EVENT_QUEUE_FULL:
7208 u16 curr_depth = (u16)(evData0 >> 16);
7209 u8 channel = (u8)(evData0 >> 8);
7210 u8 id = (u8)(evData0);
7212 snprintf(evStr, EVENT_DESCR_STR_SZ,
7213 "Queue Full: channel=%d id=%d depth=%d",
7214 channel, id, curr_depth);
7215 break;
7217 case MPI_EVENT_SAS_SES:
7218 ds = "SAS SES Event";
7219 break;
7220 case MPI_EVENT_PERSISTENT_TABLE_FULL:
7221 ds = "Persistent Table Full";
7222 break;
7223 case MPI_EVENT_SAS_PHY_LINK_STATUS:
7225 u8 LinkRates = (u8)(evData0 >> 8);
7226 u8 PhyNumber = (u8)(evData0);
7227 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
7228 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
7229 switch (LinkRates) {
7230 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
7231 snprintf(evStr, EVENT_DESCR_STR_SZ,
7232 "SAS PHY Link Status: Phy=%d:"
7233 " Rate Unknown",PhyNumber);
7234 break;
7235 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
7236 snprintf(evStr, EVENT_DESCR_STR_SZ,
7237 "SAS PHY Link Status: Phy=%d:"
7238 " Phy Disabled",PhyNumber);
7239 break;
7240 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
7241 snprintf(evStr, EVENT_DESCR_STR_SZ,
7242 "SAS PHY Link Status: Phy=%d:"
7243 " Failed Speed Nego",PhyNumber);
7244 break;
7245 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
7246 snprintf(evStr, EVENT_DESCR_STR_SZ,
7247 "SAS PHY Link Status: Phy=%d:"
7248 " Sata OOB Completed",PhyNumber);
7249 break;
7250 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
7251 snprintf(evStr, EVENT_DESCR_STR_SZ,
7252 "SAS PHY Link Status: Phy=%d:"
7253 " Rate 1.5 Gbps",PhyNumber);
7254 break;
7255 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
7256 snprintf(evStr, EVENT_DESCR_STR_SZ,
7257 "SAS PHY Link Status: Phy=%d:"
7258 " Rate 3.0 Gpbs",PhyNumber);
7259 break;
7260 default:
7261 snprintf(evStr, EVENT_DESCR_STR_SZ,
7262 "SAS PHY Link Status: Phy=%d", PhyNumber);
7263 break;
7265 break;
7267 case MPI_EVENT_SAS_DISCOVERY_ERROR:
7268 ds = "SAS Discovery Error";
7269 break;
7270 case MPI_EVENT_IR_RESYNC_UPDATE:
7272 u8 resync_complete = (u8)(evData0 >> 16);
7273 snprintf(evStr, EVENT_DESCR_STR_SZ,
7274 "IR Resync Update: Complete = %d:",resync_complete);
7275 break;
7277 case MPI_EVENT_IR2:
7279 u8 id = (u8)(evData0);
7280 u8 channel = (u8)(evData0 >> 8);
7281 u8 phys_num = (u8)(evData0 >> 24);
7282 u8 ReasonCode = (u8)(evData0 >> 16);
7284 switch (ReasonCode) {
7285 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
7286 snprintf(evStr, EVENT_DESCR_STR_SZ,
7287 "IR2: LD State Changed: "
7288 "id=%d channel=%d phys_num=%d",
7289 id, channel, phys_num);
7290 break;
7291 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
7292 snprintf(evStr, EVENT_DESCR_STR_SZ,
7293 "IR2: PD State Changed "
7294 "id=%d channel=%d phys_num=%d",
7295 id, channel, phys_num);
7296 break;
7297 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
7298 snprintf(evStr, EVENT_DESCR_STR_SZ,
7299 "IR2: Bad Block Table Full: "
7300 "id=%d channel=%d phys_num=%d",
7301 id, channel, phys_num);
7302 break;
7303 case MPI_EVENT_IR2_RC_PD_INSERTED:
7304 snprintf(evStr, EVENT_DESCR_STR_SZ,
7305 "IR2: PD Inserted: "
7306 "id=%d channel=%d phys_num=%d",
7307 id, channel, phys_num);
7308 break;
7309 case MPI_EVENT_IR2_RC_PD_REMOVED:
7310 snprintf(evStr, EVENT_DESCR_STR_SZ,
7311 "IR2: PD Removed: "
7312 "id=%d channel=%d phys_num=%d",
7313 id, channel, phys_num);
7314 break;
7315 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
7316 snprintf(evStr, EVENT_DESCR_STR_SZ,
7317 "IR2: Foreign CFG Detected: "
7318 "id=%d channel=%d phys_num=%d",
7319 id, channel, phys_num);
7320 break;
7321 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
7322 snprintf(evStr, EVENT_DESCR_STR_SZ,
7323 "IR2: Rebuild Medium Error: "
7324 "id=%d channel=%d phys_num=%d",
7325 id, channel, phys_num);
7326 break;
7327 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
7328 snprintf(evStr, EVENT_DESCR_STR_SZ,
7329 "IR2: Dual Port Added: "
7330 "id=%d channel=%d phys_num=%d",
7331 id, channel, phys_num);
7332 break;
7333 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
7334 snprintf(evStr, EVENT_DESCR_STR_SZ,
7335 "IR2: Dual Port Removed: "
7336 "id=%d channel=%d phys_num=%d",
7337 id, channel, phys_num);
7338 break;
7339 default:
7340 ds = "IR2";
7341 break;
7343 break;
7345 case MPI_EVENT_SAS_DISCOVERY:
7347 if (evData0)
7348 ds = "SAS Discovery: Start";
7349 else
7350 ds = "SAS Discovery: Stop";
7351 break;
7353 case MPI_EVENT_LOG_ENTRY_ADDED:
7354 ds = "SAS Log Entry Added";
7355 break;
7357 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
7359 u8 phy_num = (u8)(evData0);
7360 u8 port_num = (u8)(evData0 >> 8);
7361 u8 port_width = (u8)(evData0 >> 16);
7362 u8 primative = (u8)(evData0 >> 24);
7363 snprintf(evStr, EVENT_DESCR_STR_SZ,
7364 "SAS Broadcase Primative: phy=%d port=%d "
7365 "width=%d primative=0x%02x",
7366 phy_num, port_num, port_width, primative);
7367 break;
7370 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
7372 u8 reason = (u8)(evData0);
7374 switch (reason) {
7375 case MPI_EVENT_SAS_INIT_RC_ADDED:
7376 ds = "SAS Initiator Status Change: Added";
7377 break;
7378 case MPI_EVENT_SAS_INIT_RC_REMOVED:
7379 ds = "SAS Initiator Status Change: Deleted";
7380 break;
7381 default:
7382 ds = "SAS Initiator Status Change";
7383 break;
7385 break;
7388 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
7390 u8 max_init = (u8)(evData0);
7391 u8 current_init = (u8)(evData0 >> 8);
7393 snprintf(evStr, EVENT_DESCR_STR_SZ,
7394 "SAS Initiator Device Table Overflow: max initiators=%02d "
7395 "current initators=%02d",
7396 max_init, current_init);
7397 break;
7399 case MPI_EVENT_SAS_SMP_ERROR:
7401 u8 status = (u8)(evData0);
7402 u8 port_num = (u8)(evData0 >> 8);
7403 u8 result = (u8)(evData0 >> 16);
7405 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
7406 snprintf(evStr, EVENT_DESCR_STR_SZ,
7407 "SAS SMP Error: port=%d result=0x%02x",
7408 port_num, result);
7409 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
7410 snprintf(evStr, EVENT_DESCR_STR_SZ,
7411 "SAS SMP Error: port=%d : CRC Error",
7412 port_num);
7413 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
7414 snprintf(evStr, EVENT_DESCR_STR_SZ,
7415 "SAS SMP Error: port=%d : Timeout",
7416 port_num);
7417 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
7418 snprintf(evStr, EVENT_DESCR_STR_SZ,
7419 "SAS SMP Error: port=%d : No Destination",
7420 port_num);
7421 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
7422 snprintf(evStr, EVENT_DESCR_STR_SZ,
7423 "SAS SMP Error: port=%d : Bad Destination",
7424 port_num);
7425 else
7426 snprintf(evStr, EVENT_DESCR_STR_SZ,
7427 "SAS SMP Error: port=%d : status=0x%02x",
7428 port_num, status);
7429 break;
7432 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
7434 u8 reason = (u8)(evData0);
7436 switch (reason) {
7437 case MPI_EVENT_SAS_EXP_RC_ADDED:
7438 ds = "Expander Status Change: Added";
7439 break;
7440 case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
7441 ds = "Expander Status Change: Deleted";
7442 break;
7443 default:
7444 ds = "Expander Status Change";
7445 break;
7447 break;
7451 * MPT base "custom" events may be added here...
7453 default:
7454 ds = "Unknown";
7455 break;
7457 if (ds)
7458 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
7461 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7462 "MPT event:(%02Xh) : %s\n",
7463 ioc->name, event, evStr));
7465 devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
7466 ": Event data:\n"));
7467 for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
7468 devtverboseprintk(ioc, printk(" %08x",
7469 le32_to_cpu(pEventReply->Data[ii])));
7470 devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
7472 #endif
7473 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7475 * ProcessEventNotification - Route EventNotificationReply to all event handlers
7476 * @ioc: Pointer to MPT_ADAPTER structure
7477 * @pEventReply: Pointer to EventNotification reply frame
7478 * @evHandlers: Pointer to integer, number of event handlers
7480 * Routes a received EventNotificationReply to all currently registered
7481 * event handlers.
7482 * Returns sum of event handlers return values.
7484 static int
7485 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
7487 u16 evDataLen;
7488 u32 evData0 = 0;
7489 int ii;
7490 u8 cb_idx;
7491 int r = 0;
7492 int handlers = 0;
7493 u8 event;
7496 * Do platform normalization of values
7498 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7499 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
7500 if (evDataLen) {
7501 evData0 = le32_to_cpu(pEventReply->Data[0]);
7504 #ifdef CONFIG_FUSION_LOGGING
7505 if (evDataLen)
7506 mpt_display_event_info(ioc, pEventReply);
7507 #endif
7510 * Do general / base driver event processing
7512 switch(event) {
7513 case MPI_EVENT_EVENT_CHANGE: /* 0A */
7514 if (evDataLen) {
7515 u8 evState = evData0 & 0xFF;
7517 /* CHECKME! What if evState unexpectedly says OFF (0)? */
7519 /* Update EventState field in cached IocFacts */
7520 if (ioc->facts.Function) {
7521 ioc->facts.EventState = evState;
7524 break;
7525 case MPI_EVENT_INTEGRATED_RAID:
7526 mptbase_raid_process_event_data(ioc,
7527 (MpiEventDataRaid_t *)pEventReply->Data);
7528 break;
7529 default:
7530 break;
7534 * Should this event be logged? Events are written sequentially.
7535 * When buffer is full, start again at the top.
7537 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
7538 int idx;
7540 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
7542 ioc->events[idx].event = event;
7543 ioc->events[idx].eventContext = ioc->eventContext;
7545 for (ii = 0; ii < 2; ii++) {
7546 if (ii < evDataLen)
7547 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
7548 else
7549 ioc->events[idx].data[ii] = 0;
7552 ioc->eventContext++;
7557 * Call each currently registered protocol event handler.
7559 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7560 if (MptEvHandlers[cb_idx]) {
7561 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7562 "Routing Event to event handler #%d\n",
7563 ioc->name, cb_idx));
7564 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
7565 handlers++;
7568 /* FIXME? Examine results here? */
7571 * If needed, send (a single) EventAck.
7573 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
7574 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7575 "EventAck required\n",ioc->name));
7576 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
7577 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
7578 ioc->name, ii));
7582 *evHandlers = handlers;
7583 return r;
7586 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7588 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
7589 * @ioc: Pointer to MPT_ADAPTER structure
7590 * @log_info: U32 LogInfo reply word from the IOC
7592 * Refer to lsi/mpi_log_fc.h.
7594 static void
7595 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
7597 char *desc = "unknown";
7599 switch (log_info & 0xFF000000) {
7600 case MPI_IOCLOGINFO_FC_INIT_BASE:
7601 desc = "FCP Initiator";
7602 break;
7603 case MPI_IOCLOGINFO_FC_TARGET_BASE:
7604 desc = "FCP Target";
7605 break;
7606 case MPI_IOCLOGINFO_FC_LAN_BASE:
7607 desc = "LAN";
7608 break;
7609 case MPI_IOCLOGINFO_FC_MSG_BASE:
7610 desc = "MPI Message Layer";
7611 break;
7612 case MPI_IOCLOGINFO_FC_LINK_BASE:
7613 desc = "FC Link";
7614 break;
7615 case MPI_IOCLOGINFO_FC_CTX_BASE:
7616 desc = "Context Manager";
7617 break;
7618 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
7619 desc = "Invalid Field Offset";
7620 break;
7621 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
7622 desc = "State Change Info";
7623 break;
7626 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
7627 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
7630 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7632 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7633 * @ioc: Pointer to MPT_ADAPTER structure
7634 * @log_info: U32 LogInfo word from the IOC
7636 * Refer to lsi/sp_log.h.
7638 static void
7639 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7641 u32 info = log_info & 0x00FF0000;
7642 char *desc = "unknown";
7644 switch (info) {
7645 case 0x00010000:
7646 desc = "bug! MID not found";
7647 break;
7649 case 0x00020000:
7650 desc = "Parity Error";
7651 break;
7653 case 0x00030000:
7654 desc = "ASYNC Outbound Overrun";
7655 break;
7657 case 0x00040000:
7658 desc = "SYNC Offset Error";
7659 break;
7661 case 0x00050000:
7662 desc = "BM Change";
7663 break;
7665 case 0x00060000:
7666 desc = "Msg In Overflow";
7667 break;
7669 case 0x00070000:
7670 desc = "DMA Error";
7671 break;
7673 case 0x00080000:
7674 desc = "Outbound DMA Overrun";
7675 break;
7677 case 0x00090000:
7678 desc = "Task Management";
7679 break;
7681 case 0x000A0000:
7682 desc = "Device Problem";
7683 break;
7685 case 0x000B0000:
7686 desc = "Invalid Phase Change";
7687 break;
7689 case 0x000C0000:
7690 desc = "Untagged Table Size";
7691 break;
7695 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7698 /* strings for sas loginfo */
7699 static char *originator_str[] = {
7700 "IOP", /* 00h */
7701 "PL", /* 01h */
7702 "IR" /* 02h */
7704 static char *iop_code_str[] = {
7705 NULL, /* 00h */
7706 "Invalid SAS Address", /* 01h */
7707 NULL, /* 02h */
7708 "Invalid Page", /* 03h */
7709 "Diag Message Error", /* 04h */
7710 "Task Terminated", /* 05h */
7711 "Enclosure Management", /* 06h */
7712 "Target Mode" /* 07h */
7714 static char *pl_code_str[] = {
7715 NULL, /* 00h */
7716 "Open Failure", /* 01h */
7717 "Invalid Scatter Gather List", /* 02h */
7718 "Wrong Relative Offset or Frame Length", /* 03h */
7719 "Frame Transfer Error", /* 04h */
7720 "Transmit Frame Connected Low", /* 05h */
7721 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7722 "SATA Read Log Receive Data Error", /* 07h */
7723 "SATA NCQ Fail All Commands After Error", /* 08h */
7724 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7725 "Receive Frame Invalid Message", /* 0Ah */
7726 "Receive Context Message Valid Error", /* 0Bh */
7727 "Receive Frame Current Frame Error", /* 0Ch */
7728 "SATA Link Down", /* 0Dh */
7729 "Discovery SATA Init W IOS", /* 0Eh */
7730 "Config Invalid Page", /* 0Fh */
7731 "Discovery SATA Init Timeout", /* 10h */
7732 "Reset", /* 11h */
7733 "Abort", /* 12h */
7734 "IO Not Yet Executed", /* 13h */
7735 "IO Executed", /* 14h */
7736 "Persistent Reservation Out Not Affiliation "
7737 "Owner", /* 15h */
7738 "Open Transmit DMA Abort", /* 16h */
7739 "IO Device Missing Delay Retry", /* 17h */
7740 "IO Cancelled Due to Recieve Error", /* 18h */
7741 NULL, /* 19h */
7742 NULL, /* 1Ah */
7743 NULL, /* 1Bh */
7744 NULL, /* 1Ch */
7745 NULL, /* 1Dh */
7746 NULL, /* 1Eh */
7747 NULL, /* 1Fh */
7748 "Enclosure Management" /* 20h */
7750 static char *ir_code_str[] = {
7751 "Raid Action Error", /* 00h */
7752 NULL, /* 00h */
7753 NULL, /* 01h */
7754 NULL, /* 02h */
7755 NULL, /* 03h */
7756 NULL, /* 04h */
7757 NULL, /* 05h */
7758 NULL, /* 06h */
7759 NULL /* 07h */
7761 static char *raid_sub_code_str[] = {
7762 NULL, /* 00h */
7763 "Volume Creation Failed: Data Passed too "
7764 "Large", /* 01h */
7765 "Volume Creation Failed: Duplicate Volumes "
7766 "Attempted", /* 02h */
7767 "Volume Creation Failed: Max Number "
7768 "Supported Volumes Exceeded", /* 03h */
7769 "Volume Creation Failed: DMA Error", /* 04h */
7770 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7771 "Volume Creation Failed: Error Reading "
7772 "MFG Page 4", /* 06h */
7773 "Volume Creation Failed: Creating Internal "
7774 "Structures", /* 07h */
7775 NULL, /* 08h */
7776 NULL, /* 09h */
7777 NULL, /* 0Ah */
7778 NULL, /* 0Bh */
7779 NULL, /* 0Ch */
7780 NULL, /* 0Dh */
7781 NULL, /* 0Eh */
7782 NULL, /* 0Fh */
7783 "Activation failed: Already Active Volume", /* 10h */
7784 "Activation failed: Unsupported Volume Type", /* 11h */
7785 "Activation failed: Too Many Active Volumes", /* 12h */
7786 "Activation failed: Volume ID in Use", /* 13h */
7787 "Activation failed: Reported Failure", /* 14h */
7788 "Activation failed: Importing a Volume", /* 15h */
7789 NULL, /* 16h */
7790 NULL, /* 17h */
7791 NULL, /* 18h */
7792 NULL, /* 19h */
7793 NULL, /* 1Ah */
7794 NULL, /* 1Bh */
7795 NULL, /* 1Ch */
7796 NULL, /* 1Dh */
7797 NULL, /* 1Eh */
7798 NULL, /* 1Fh */
7799 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7800 "Phys Disk failed: Data Passed too Large", /* 21h */
7801 "Phys Disk failed: DMA Error", /* 22h */
7802 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7803 "Phys Disk failed: Creating Phys Disk Config "
7804 "Page", /* 24h */
7805 NULL, /* 25h */
7806 NULL, /* 26h */
7807 NULL, /* 27h */
7808 NULL, /* 28h */
7809 NULL, /* 29h */
7810 NULL, /* 2Ah */
7811 NULL, /* 2Bh */
7812 NULL, /* 2Ch */
7813 NULL, /* 2Dh */
7814 NULL, /* 2Eh */
7815 NULL, /* 2Fh */
7816 "Compatibility Error: IR Disabled", /* 30h */
7817 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7818 "Compatibility Error: Device not Direct Access "
7819 "Device ", /* 32h */
7820 "Compatibility Error: Removable Device Found", /* 33h */
7821 "Compatibility Error: Device SCSI Version not "
7822 "2 or Higher", /* 34h */
7823 "Compatibility Error: SATA Device, 48 BIT LBA "
7824 "not Supported", /* 35h */
7825 "Compatibility Error: Device doesn't have "
7826 "512 Byte Block Sizes", /* 36h */
7827 "Compatibility Error: Volume Type Check Failed", /* 37h */
7828 "Compatibility Error: Volume Type is "
7829 "Unsupported by FW", /* 38h */
7830 "Compatibility Error: Disk Drive too Small for "
7831 "use in Volume", /* 39h */
7832 "Compatibility Error: Phys Disk for Create "
7833 "Volume not Found", /* 3Ah */
7834 "Compatibility Error: Too Many or too Few "
7835 "Disks for Volume Type", /* 3Bh */
7836 "Compatibility Error: Disk stripe Sizes "
7837 "Must be 64KB", /* 3Ch */
7838 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7841 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7843 * mpt_sas_log_info - Log information returned from SAS IOC.
7844 * @ioc: Pointer to MPT_ADAPTER structure
7845 * @log_info: U32 LogInfo reply word from the IOC
7847 * Refer to lsi/mpi_log_sas.h.
7849 static void
7850 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7852 union loginfo_type {
7853 u32 loginfo;
7854 struct {
7855 u32 subcode:16;
7856 u32 code:8;
7857 u32 originator:4;
7858 u32 bus_type:4;
7859 }dw;
7861 union loginfo_type sas_loginfo;
7862 char *originator_desc = NULL;
7863 char *code_desc = NULL;
7864 char *sub_code_desc = NULL;
7866 sas_loginfo.loginfo = log_info;
7867 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7868 (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
7869 return;
7871 originator_desc = originator_str[sas_loginfo.dw.originator];
7873 switch (sas_loginfo.dw.originator) {
7875 case 0: /* IOP */
7876 if (sas_loginfo.dw.code <
7877 ARRAY_SIZE(iop_code_str))
7878 code_desc = iop_code_str[sas_loginfo.dw.code];
7879 break;
7880 case 1: /* PL */
7881 if (sas_loginfo.dw.code <
7882 ARRAY_SIZE(pl_code_str))
7883 code_desc = pl_code_str[sas_loginfo.dw.code];
7884 break;
7885 case 2: /* IR */
7886 if (sas_loginfo.dw.code >=
7887 ARRAY_SIZE(ir_code_str))
7888 break;
7889 code_desc = ir_code_str[sas_loginfo.dw.code];
7890 if (sas_loginfo.dw.subcode >=
7891 ARRAY_SIZE(raid_sub_code_str))
7892 break;
7893 if (sas_loginfo.dw.code == 0)
7894 sub_code_desc =
7895 raid_sub_code_str[sas_loginfo.dw.subcode];
7896 break;
7897 default:
7898 return;
7901 if (sub_code_desc != NULL)
7902 printk(MYIOC_s_INFO_FMT
7903 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7904 " SubCode={%s}\n",
7905 ioc->name, log_info, originator_desc, code_desc,
7906 sub_code_desc);
7907 else if (code_desc != NULL)
7908 printk(MYIOC_s_INFO_FMT
7909 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7910 " SubCode(0x%04x)\n",
7911 ioc->name, log_info, originator_desc, code_desc,
7912 sas_loginfo.dw.subcode);
7913 else
7914 printk(MYIOC_s_INFO_FMT
7915 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7916 " SubCode(0x%04x)\n",
7917 ioc->name, log_info, originator_desc,
7918 sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7923 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7924 * @ioc: Pointer to MPT_ADAPTER structure
7925 * @ioc_status: U32 IOCStatus word from IOC
7926 * @mf: Pointer to MPT request frame
7928 * Refer to lsi/mpi.h.
7930 static void
7931 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7933 Config_t *pReq = (Config_t *)mf;
7934 char extend_desc[EVENT_DESCR_STR_SZ];
7935 char *desc = NULL;
7936 u32 form;
7937 u8 page_type;
7939 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7940 page_type = pReq->ExtPageType;
7941 else
7942 page_type = pReq->Header.PageType;
7945 * ignore invalid page messages for GET_NEXT_HANDLE
7947 form = le32_to_cpu(pReq->PageAddress);
7948 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7949 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7950 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7951 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7952 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7953 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7954 return;
7956 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7957 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7958 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7959 return;
7962 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7963 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7964 page_type, pReq->Header.PageNumber, pReq->Action, form);
7966 switch (ioc_status) {
7968 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7969 desc = "Config Page Invalid Action";
7970 break;
7972 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
7973 desc = "Config Page Invalid Type";
7974 break;
7976 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
7977 desc = "Config Page Invalid Page";
7978 break;
7980 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
7981 desc = "Config Page Invalid Data";
7982 break;
7984 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
7985 desc = "Config Page No Defaults";
7986 break;
7988 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
7989 desc = "Config Page Can't Commit";
7990 break;
7993 if (!desc)
7994 return;
7996 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7997 ioc->name, ioc_status, desc, extend_desc));
8001 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
8002 * @ioc: Pointer to MPT_ADAPTER structure
8003 * @ioc_status: U32 IOCStatus word from IOC
8004 * @mf: Pointer to MPT request frame
8006 * Refer to lsi/mpi.h.
8008 static void
8009 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8011 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
8012 char *desc = NULL;
8014 switch (status) {
8016 /****************************************************************************/
8017 /* Common IOCStatus values for all replies */
8018 /****************************************************************************/
8020 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
8021 desc = "Invalid Function";
8022 break;
8024 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
8025 desc = "Busy";
8026 break;
8028 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
8029 desc = "Invalid SGL";
8030 break;
8032 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
8033 desc = "Internal Error";
8034 break;
8036 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
8037 desc = "Reserved";
8038 break;
8040 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
8041 desc = "Insufficient Resources";
8042 break;
8044 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
8045 desc = "Invalid Field";
8046 break;
8048 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
8049 desc = "Invalid State";
8050 break;
8052 /****************************************************************************/
8053 /* Config IOCStatus values */
8054 /****************************************************************************/
8056 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8057 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
8058 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
8059 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
8060 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
8061 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
8062 mpt_iocstatus_info_config(ioc, status, mf);
8063 break;
8065 /****************************************************************************/
8066 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
8067 /* */
8068 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
8069 /* */
8070 /****************************************************************************/
8072 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
8073 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
8074 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
8075 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
8076 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
8077 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
8078 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
8079 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
8080 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
8081 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
8082 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
8083 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
8084 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
8085 break;
8087 /****************************************************************************/
8088 /* SCSI Target values */
8089 /****************************************************************************/
8091 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
8092 desc = "Target: Priority IO";
8093 break;
8095 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
8096 desc = "Target: Invalid Port";
8097 break;
8099 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
8100 desc = "Target Invalid IO Index:";
8101 break;
8103 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
8104 desc = "Target: Aborted";
8105 break;
8107 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
8108 desc = "Target: No Conn Retryable";
8109 break;
8111 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
8112 desc = "Target: No Connection";
8113 break;
8115 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
8116 desc = "Target: Transfer Count Mismatch";
8117 break;
8119 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
8120 desc = "Target: STS Data not Sent";
8121 break;
8123 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
8124 desc = "Target: Data Offset Error";
8125 break;
8127 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
8128 desc = "Target: Too Much Write Data";
8129 break;
8131 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
8132 desc = "Target: IU Too Short";
8133 break;
8135 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
8136 desc = "Target: ACK NAK Timeout";
8137 break;
8139 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
8140 desc = "Target: Nak Received";
8141 break;
8143 /****************************************************************************/
8144 /* Fibre Channel Direct Access values */
8145 /****************************************************************************/
8147 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
8148 desc = "FC: Aborted";
8149 break;
8151 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
8152 desc = "FC: RX ID Invalid";
8153 break;
8155 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
8156 desc = "FC: DID Invalid";
8157 break;
8159 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
8160 desc = "FC: Node Logged Out";
8161 break;
8163 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
8164 desc = "FC: Exchange Canceled";
8165 break;
8167 /****************************************************************************/
8168 /* LAN values */
8169 /****************************************************************************/
8171 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
8172 desc = "LAN: Device not Found";
8173 break;
8175 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
8176 desc = "LAN: Device Failure";
8177 break;
8179 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
8180 desc = "LAN: Transmit Error";
8181 break;
8183 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
8184 desc = "LAN: Transmit Aborted";
8185 break;
8187 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
8188 desc = "LAN: Receive Error";
8189 break;
8191 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
8192 desc = "LAN: Receive Aborted";
8193 break;
8195 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
8196 desc = "LAN: Partial Packet";
8197 break;
8199 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
8200 desc = "LAN: Canceled";
8201 break;
8203 /****************************************************************************/
8204 /* Serial Attached SCSI values */
8205 /****************************************************************************/
8207 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
8208 desc = "SAS: SMP Request Failed";
8209 break;
8211 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
8212 desc = "SAS: SMP Data Overrun";
8213 break;
8215 default:
8216 desc = "Others";
8217 break;
8220 if (!desc)
8221 return;
8223 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
8224 ioc->name, status, desc));
8227 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8228 EXPORT_SYMBOL(mpt_attach);
8229 EXPORT_SYMBOL(mpt_detach);
8230 #ifdef CONFIG_PM
8231 EXPORT_SYMBOL(mpt_resume);
8232 EXPORT_SYMBOL(mpt_suspend);
8233 #endif
8234 EXPORT_SYMBOL(ioc_list);
8235 EXPORT_SYMBOL(mpt_register);
8236 EXPORT_SYMBOL(mpt_deregister);
8237 EXPORT_SYMBOL(mpt_event_register);
8238 EXPORT_SYMBOL(mpt_event_deregister);
8239 EXPORT_SYMBOL(mpt_reset_register);
8240 EXPORT_SYMBOL(mpt_reset_deregister);
8241 EXPORT_SYMBOL(mpt_device_driver_register);
8242 EXPORT_SYMBOL(mpt_device_driver_deregister);
8243 EXPORT_SYMBOL(mpt_get_msg_frame);
8244 EXPORT_SYMBOL(mpt_put_msg_frame);
8245 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
8246 EXPORT_SYMBOL(mpt_free_msg_frame);
8247 EXPORT_SYMBOL(mpt_send_handshake_request);
8248 EXPORT_SYMBOL(mpt_verify_adapter);
8249 EXPORT_SYMBOL(mpt_GetIocState);
8250 EXPORT_SYMBOL(mpt_print_ioc_summary);
8251 EXPORT_SYMBOL(mpt_HardResetHandler);
8252 EXPORT_SYMBOL(mpt_config);
8253 EXPORT_SYMBOL(mpt_findImVolumes);
8254 EXPORT_SYMBOL(mpt_alloc_fw_memory);
8255 EXPORT_SYMBOL(mpt_free_fw_memory);
8256 EXPORT_SYMBOL(mptbase_sas_persist_operation);
8257 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
8259 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8261 * fusion_init - Fusion MPT base driver initialization routine.
8263 * Returns 0 for success, non-zero for failure.
8265 static int __init
8266 fusion_init(void)
8268 u8 cb_idx;
8270 show_mptmod_ver(my_NAME, my_VERSION);
8271 printk(KERN_INFO COPYRIGHT "\n");
8273 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
8274 MptCallbacks[cb_idx] = NULL;
8275 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
8276 MptEvHandlers[cb_idx] = NULL;
8277 MptResetHandlers[cb_idx] = NULL;
8280 /* Register ourselves (mptbase) in order to facilitate
8281 * EventNotification handling.
8283 mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER);
8285 /* Register for hard reset handling callbacks.
8287 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
8289 #ifdef CONFIG_PROC_FS
8290 (void) procmpt_create();
8291 #endif
8292 return 0;
8295 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8297 * fusion_exit - Perform driver unload cleanup.
8299 * This routine frees all resources associated with each MPT adapter
8300 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
8302 static void __exit
8303 fusion_exit(void)
8306 mpt_reset_deregister(mpt_base_index);
8308 #ifdef CONFIG_PROC_FS
8309 procmpt_destroy();
8310 #endif
8313 module_init(fusion_init);
8314 module_exit(fusion_exit);