of: MSI: Simplify irqdomain lookup
[linux/fpc-iii.git] / drivers / message / fusion / mptbase.c
blob5dcc0313c38a677d5f1960483dd64bb47f779891
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/seq_file.h>
54 #include <linux/slab.h>
55 #include <linux/types.h>
56 #include <linux/pci.h>
57 #include <linux/kdev_t.h>
58 #include <linux/blkdev.h>
59 #include <linux/delay.h>
60 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
61 #include <linux/dma-mapping.h>
62 #include <linux/kthread.h>
63 #include <scsi/scsi_host.h>
65 #include "mptbase.h"
66 #include "lsi/mpi_log_fc.h"
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT base driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
71 #define MYNAM "mptbase"
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
76 MODULE_VERSION(my_VERSION);
79 * cmd line parameters
82 static int mpt_msi_enable_spi;
83 module_param(mpt_msi_enable_spi, int, 0);
84 MODULE_PARM_DESC(mpt_msi_enable_spi,
85 " Enable MSI Support for SPI controllers (default=0)");
87 static int mpt_msi_enable_fc;
88 module_param(mpt_msi_enable_fc, int, 0);
89 MODULE_PARM_DESC(mpt_msi_enable_fc,
90 " Enable MSI Support for FC controllers (default=0)");
92 static int mpt_msi_enable_sas;
93 module_param(mpt_msi_enable_sas, int, 0);
94 MODULE_PARM_DESC(mpt_msi_enable_sas,
95 " Enable MSI Support for SAS controllers (default=0)");
97 static int mpt_channel_mapping;
98 module_param(mpt_channel_mapping, int, 0);
99 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
101 static int mpt_debug_level;
102 static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
103 module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
104 &mpt_debug_level, 0600);
105 MODULE_PARM_DESC(mpt_debug_level,
106 " debug level - refer to mptdebug.h - (default=0)");
108 int mpt_fwfault_debug;
109 EXPORT_SYMBOL(mpt_fwfault_debug);
110 module_param(mpt_fwfault_debug, int, 0600);
111 MODULE_PARM_DESC(mpt_fwfault_debug,
112 "Enable detection of Firmware fault and halt Firmware on fault - (default=0)");
114 static char MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS]
115 [MPT_MAX_CALLBACKNAME_LEN+1];
117 #ifdef MFCNT
118 static int mfcounter = 0;
119 #define PRINT_MF_COUNT 20000
120 #endif
122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
124 * Public data...
127 #define WHOINIT_UNKNOWN 0xAA
129 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
131 * Private data...
133 /* Adapter link list */
134 LIST_HEAD(ioc_list);
135 /* Callback lookup table */
136 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
137 /* Protocol driver class lookup table */
138 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
139 /* Event handler lookup table */
140 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
141 /* Reset handler lookup table */
142 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
143 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
145 #ifdef CONFIG_PROC_FS
146 static struct proc_dir_entry *mpt_proc_root_dir;
147 #endif
150 * Driver Callback Index's
152 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
153 static u8 last_drv_idx;
155 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
157 * Forward protos...
159 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
160 static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
161 MPT_FRAME_HDR *reply);
162 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
163 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
164 int sleepFlag);
165 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
166 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
167 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
168 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
170 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
171 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
172 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
173 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
174 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
175 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
176 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
177 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
178 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
179 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
180 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
181 static int PrimeIocFifos(MPT_ADAPTER *ioc);
182 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
183 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
184 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
185 static int GetLanConfigPages(MPT_ADAPTER *ioc);
186 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
187 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
188 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
189 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
190 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
191 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
192 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
193 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch,
194 int sleepFlag);
195 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
196 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
197 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
199 #ifdef CONFIG_PROC_FS
200 static const struct file_operations mpt_summary_proc_fops;
201 static const struct file_operations mpt_version_proc_fops;
202 static const struct file_operations mpt_iocinfo_proc_fops;
203 #endif
204 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
206 static int ProcessEventNotification(MPT_ADAPTER *ioc,
207 EventNotificationReply_t *evReply, int *evHandlers);
208 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
209 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
210 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
211 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info , u8 cb_idx);
212 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
213 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
215 /* module entry point */
216 static int __init fusion_init (void);
217 static void __exit fusion_exit (void);
219 #define CHIPREG_READ32(addr) readl_relaxed(addr)
220 #define CHIPREG_READ32_dmasync(addr) readl(addr)
221 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
222 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
223 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
225 static void
226 pci_disable_io_access(struct pci_dev *pdev)
228 u16 command_reg;
230 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
231 command_reg &= ~1;
232 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
235 static void
236 pci_enable_io_access(struct pci_dev *pdev)
238 u16 command_reg;
240 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
241 command_reg |= 1;
242 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
245 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
247 int ret = param_set_int(val, kp);
248 MPT_ADAPTER *ioc;
250 if (ret)
251 return ret;
253 list_for_each_entry(ioc, &ioc_list, list)
254 ioc->debug_level = mpt_debug_level;
255 return 0;
259 * mpt_get_cb_idx - obtain cb_idx for registered driver
260 * @dclass: class driver enum
262 * Returns cb_idx, or zero means it wasn't found
264 static u8
265 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
267 u8 cb_idx;
269 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
270 if (MptDriverClass[cb_idx] == dclass)
271 return cb_idx;
272 return 0;
276 * mpt_is_discovery_complete - determine if discovery has completed
277 * @ioc: per adatper instance
279 * Returns 1 when discovery completed, else zero.
281 static int
282 mpt_is_discovery_complete(MPT_ADAPTER *ioc)
284 ConfigExtendedPageHeader_t hdr;
285 CONFIGPARMS cfg;
286 SasIOUnitPage0_t *buffer;
287 dma_addr_t dma_handle;
288 int rc = 0;
290 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
291 memset(&cfg, 0, sizeof(CONFIGPARMS));
292 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
293 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
294 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
295 cfg.cfghdr.ehdr = &hdr;
296 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
298 if ((mpt_config(ioc, &cfg)))
299 goto out;
300 if (!hdr.ExtPageLength)
301 goto out;
303 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
304 &dma_handle);
305 if (!buffer)
306 goto out;
308 cfg.physAddr = dma_handle;
309 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
311 if ((mpt_config(ioc, &cfg)))
312 goto out_free_consistent;
314 if (!(buffer->PhyData[0].PortFlags &
315 MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS))
316 rc = 1;
318 out_free_consistent:
319 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
320 buffer, dma_handle);
321 out:
322 return rc;
327 * mpt_remove_dead_ioc_func - kthread context to remove dead ioc
328 * @arg: input argument, used to derive ioc
330 * Return 0 if controller is removed from pci subsystem.
331 * Return -1 for other case.
333 static int mpt_remove_dead_ioc_func(void *arg)
335 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
336 struct pci_dev *pdev;
338 if ((ioc == NULL))
339 return -1;
341 pdev = ioc->pcidev;
342 if ((pdev == NULL))
343 return -1;
345 pci_stop_and_remove_bus_device_locked(pdev);
346 return 0;
352 * mpt_fault_reset_work - work performed on workq after ioc fault
353 * @work: input argument, used to derive ioc
356 static void
357 mpt_fault_reset_work(struct work_struct *work)
359 MPT_ADAPTER *ioc =
360 container_of(work, MPT_ADAPTER, fault_reset_work.work);
361 u32 ioc_raw_state;
362 int rc;
363 unsigned long flags;
364 MPT_SCSI_HOST *hd;
365 struct task_struct *p;
367 if (ioc->ioc_reset_in_progress || !ioc->active)
368 goto out;
371 ioc_raw_state = mpt_GetIocState(ioc, 0);
372 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) {
373 printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n",
374 ioc->name, __func__);
377 * Call mptscsih_flush_pending_cmds callback so that we
378 * flush all pending commands back to OS.
379 * This call is required to aovid deadlock at block layer.
380 * Dead IOC will fail to do diag reset,and this call is safe
381 * since dead ioc will never return any command back from HW.
383 hd = shost_priv(ioc->sh);
384 ioc->schedule_dead_ioc_flush_running_cmds(hd);
386 /*Remove the Dead Host */
387 p = kthread_run(mpt_remove_dead_ioc_func, ioc,
388 "mpt_dead_ioc_%d", ioc->id);
389 if (IS_ERR(p)) {
390 printk(MYIOC_s_ERR_FMT
391 "%s: Running mpt_dead_ioc thread failed !\n",
392 ioc->name, __func__);
393 } else {
394 printk(MYIOC_s_WARN_FMT
395 "%s: Running mpt_dead_ioc thread success !\n",
396 ioc->name, __func__);
398 return; /* don't rearm timer */
401 if ((ioc_raw_state & MPI_IOC_STATE_MASK)
402 == MPI_IOC_STATE_FAULT) {
403 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
404 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
405 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
406 ioc->name, __func__);
407 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
408 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
409 __func__, (rc == 0) ? "success" : "failed");
410 ioc_raw_state = mpt_GetIocState(ioc, 0);
411 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
412 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
413 "reset (%04xh)\n", ioc->name, ioc_raw_state &
414 MPI_DOORBELL_DATA_MASK);
415 } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) {
416 if ((mpt_is_discovery_complete(ioc))) {
417 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing "
418 "discovery_quiesce_io flag\n", ioc->name));
419 ioc->sas_discovery_quiesce_io = 0;
423 out:
425 * Take turns polling alternate controller
427 if (ioc->alt_ioc)
428 ioc = ioc->alt_ioc;
430 /* rearm the timer */
431 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
432 if (ioc->reset_work_q)
433 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
434 msecs_to_jiffies(MPT_POLLING_INTERVAL));
435 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
440 * Process turbo (context) reply...
442 static void
443 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
445 MPT_FRAME_HDR *mf = NULL;
446 MPT_FRAME_HDR *mr = NULL;
447 u16 req_idx = 0;
448 u8 cb_idx;
450 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
451 ioc->name, pa));
453 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
454 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
455 req_idx = pa & 0x0000FFFF;
456 cb_idx = (pa & 0x00FF0000) >> 16;
457 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
458 break;
459 case MPI_CONTEXT_REPLY_TYPE_LAN:
460 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
462 * Blind set of mf to NULL here was fatal
463 * after lan_reply says "freeme"
464 * Fix sort of combined with an optimization here;
465 * added explicit check for case where lan_reply
466 * was just returning 1 and doing nothing else.
467 * For this case skip the callback, but set up
468 * proper mf value first here:-)
470 if ((pa & 0x58000000) == 0x58000000) {
471 req_idx = pa & 0x0000FFFF;
472 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
473 mpt_free_msg_frame(ioc, mf);
474 mb();
475 return;
476 break;
478 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
479 break;
480 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
481 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
482 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
483 break;
484 default:
485 cb_idx = 0;
486 BUG();
489 /* Check for (valid) IO callback! */
490 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
491 MptCallbacks[cb_idx] == NULL) {
492 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
493 __func__, ioc->name, cb_idx);
494 goto out;
497 if (MptCallbacks[cb_idx](ioc, mf, mr))
498 mpt_free_msg_frame(ioc, mf);
499 out:
500 mb();
503 static void
504 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
506 MPT_FRAME_HDR *mf;
507 MPT_FRAME_HDR *mr;
508 u16 req_idx;
509 u8 cb_idx;
510 int freeme;
512 u32 reply_dma_low;
513 u16 ioc_stat;
515 /* non-TURBO reply! Hmmm, something may be up...
516 * Newest turbo reply mechanism; get address
517 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
520 /* Map DMA address of reply header to cpu address.
521 * pa is 32 bits - but the dma address may be 32 or 64 bits
522 * get offset based only only the low addresses
525 reply_dma_low = (pa <<= 1);
526 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
527 (reply_dma_low - ioc->reply_frames_low_dma));
529 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
530 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
531 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
533 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
534 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
535 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
537 /* Check/log IOC log info
539 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
540 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
541 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
542 if (ioc->bus_type == FC)
543 mpt_fc_log_info(ioc, log_info);
544 else if (ioc->bus_type == SPI)
545 mpt_spi_log_info(ioc, log_info);
546 else if (ioc->bus_type == SAS)
547 mpt_sas_log_info(ioc, log_info, cb_idx);
550 if (ioc_stat & MPI_IOCSTATUS_MASK)
551 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
553 /* Check for (valid) IO callback! */
554 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
555 MptCallbacks[cb_idx] == NULL) {
556 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
557 __func__, ioc->name, cb_idx);
558 freeme = 0;
559 goto out;
562 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
564 out:
565 /* Flush (non-TURBO) reply with a WRITE! */
566 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
568 if (freeme)
569 mpt_free_msg_frame(ioc, mf);
570 mb();
573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
575 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
576 * @irq: irq number (not used)
577 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
579 * This routine is registered via the request_irq() kernel API call,
580 * and handles all interrupts generated from a specific MPT adapter
581 * (also referred to as a IO Controller or IOC).
582 * This routine must clear the interrupt from the adapter and does
583 * so by reading the reply FIFO. Multiple replies may be processed
584 * per single call to this routine.
586 * This routine handles register-level access of the adapter but
587 * dispatches (calls) a protocol-specific callback routine to handle
588 * the protocol-specific details of the MPT request completion.
590 static irqreturn_t
591 mpt_interrupt(int irq, void *bus_id)
593 MPT_ADAPTER *ioc = bus_id;
594 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
596 if (pa == 0xFFFFFFFF)
597 return IRQ_NONE;
600 * Drain the reply FIFO!
602 do {
603 if (pa & MPI_ADDRESS_REPLY_A_BIT)
604 mpt_reply(ioc, pa);
605 else
606 mpt_turbo_reply(ioc, pa);
607 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
608 } while (pa != 0xFFFFFFFF);
610 return IRQ_HANDLED;
613 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
615 * mptbase_reply - MPT base driver's callback routine
616 * @ioc: Pointer to MPT_ADAPTER structure
617 * @req: Pointer to original MPT request frame
618 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
620 * MPT base driver's callback routine; all base driver
621 * "internal" request/reply processing is routed here.
622 * Currently used for EventNotification and EventAck handling.
624 * Returns 1 indicating original alloc'd request frame ptr
625 * should be freed, or 0 if it shouldn't.
627 static int
628 mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
630 EventNotificationReply_t *pEventReply;
631 u8 event;
632 int evHandlers;
633 int freereq = 1;
635 switch (reply->u.hdr.Function) {
636 case MPI_FUNCTION_EVENT_NOTIFICATION:
637 pEventReply = (EventNotificationReply_t *)reply;
638 evHandlers = 0;
639 ProcessEventNotification(ioc, pEventReply, &evHandlers);
640 event = le32_to_cpu(pEventReply->Event) & 0xFF;
641 if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
642 freereq = 0;
643 if (event != MPI_EVENT_EVENT_CHANGE)
644 break;
645 case MPI_FUNCTION_CONFIG:
646 case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
647 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
648 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
649 memcpy(ioc->mptbase_cmds.reply, reply,
650 min(MPT_DEFAULT_FRAME_SIZE,
651 4 * reply->u.reply.MsgLength));
652 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
653 ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
654 complete(&ioc->mptbase_cmds.done);
655 } else
656 freereq = 0;
657 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF)
658 freereq = 1;
659 break;
660 case MPI_FUNCTION_EVENT_ACK:
661 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
662 "EventAck reply received\n", ioc->name));
663 break;
664 default:
665 printk(MYIOC_s_ERR_FMT
666 "Unexpected msg function (=%02Xh) reply received!\n",
667 ioc->name, reply->u.hdr.Function);
668 break;
672 * Conditionally tell caller to free the original
673 * EventNotification/EventAck/unexpected request frame!
675 return freereq;
678 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
680 * mpt_register - Register protocol-specific main callback handler.
681 * @cbfunc: callback function pointer
682 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
683 * @func_name: call function's name
685 * This routine is called by a protocol-specific driver (SCSI host,
686 * LAN, SCSI target) to register its reply callback routine. Each
687 * protocol-specific driver must do this before it will be able to
688 * use any IOC resources, such as obtaining request frames.
690 * NOTES: The SCSI protocol driver currently calls this routine thrice
691 * in order to register separate callbacks; one for "normal" SCSI IO;
692 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
694 * Returns u8 valued "handle" in the range (and S.O.D. order)
695 * {N,...,7,6,5,...,1} if successful.
696 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
697 * considered an error by the caller.
700 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name)
702 u8 cb_idx;
703 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
706 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
707 * (slot/handle 0 is reserved!)
709 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
710 if (MptCallbacks[cb_idx] == NULL) {
711 MptCallbacks[cb_idx] = cbfunc;
712 MptDriverClass[cb_idx] = dclass;
713 MptEvHandlers[cb_idx] = NULL;
714 last_drv_idx = cb_idx;
715 strlcpy(MptCallbacksName[cb_idx], func_name,
716 MPT_MAX_CALLBACKNAME_LEN+1);
717 break;
721 return last_drv_idx;
724 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
726 * mpt_deregister - Deregister a protocol drivers resources.
727 * @cb_idx: previously registered callback handle
729 * Each protocol-specific driver should call this routine when its
730 * module is unloaded.
732 void
733 mpt_deregister(u8 cb_idx)
735 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
736 MptCallbacks[cb_idx] = NULL;
737 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
738 MptEvHandlers[cb_idx] = NULL;
740 last_drv_idx++;
744 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
746 * mpt_event_register - Register protocol-specific event callback handler.
747 * @cb_idx: previously registered (via mpt_register) callback handle
748 * @ev_cbfunc: callback function
750 * This routine can be called by one or more protocol-specific drivers
751 * if/when they choose to be notified of MPT events.
753 * Returns 0 for success.
756 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
758 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
759 return -1;
761 MptEvHandlers[cb_idx] = ev_cbfunc;
762 return 0;
765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
767 * mpt_event_deregister - Deregister protocol-specific event callback handler
768 * @cb_idx: previously registered callback handle
770 * Each protocol-specific driver should call this routine
771 * when it does not (or can no longer) handle events,
772 * or when its module is unloaded.
774 void
775 mpt_event_deregister(u8 cb_idx)
777 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
778 return;
780 MptEvHandlers[cb_idx] = NULL;
783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
785 * mpt_reset_register - Register protocol-specific IOC reset handler.
786 * @cb_idx: previously registered (via mpt_register) callback handle
787 * @reset_func: reset function
789 * This routine can be called by one or more protocol-specific drivers
790 * if/when they choose to be notified of IOC resets.
792 * Returns 0 for success.
795 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
797 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
798 return -1;
800 MptResetHandlers[cb_idx] = reset_func;
801 return 0;
804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
806 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
807 * @cb_idx: previously registered callback handle
809 * Each protocol-specific driver should call this routine
810 * when it does not (or can no longer) handle IOC reset handling,
811 * or when its module is unloaded.
813 void
814 mpt_reset_deregister(u8 cb_idx)
816 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
817 return;
819 MptResetHandlers[cb_idx] = NULL;
822 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
824 * mpt_device_driver_register - Register device driver hooks
825 * @dd_cbfunc: driver callbacks struct
826 * @cb_idx: MPT protocol driver index
829 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
831 MPT_ADAPTER *ioc;
832 const struct pci_device_id *id;
834 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
835 return -EINVAL;
837 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
839 /* call per pci device probe entry point */
840 list_for_each_entry(ioc, &ioc_list, list) {
841 id = ioc->pcidev->driver ?
842 ioc->pcidev->driver->id_table : NULL;
843 if (dd_cbfunc->probe)
844 dd_cbfunc->probe(ioc->pcidev, id);
847 return 0;
850 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
852 * mpt_device_driver_deregister - DeRegister device driver hooks
853 * @cb_idx: MPT protocol driver index
855 void
856 mpt_device_driver_deregister(u8 cb_idx)
858 struct mpt_pci_driver *dd_cbfunc;
859 MPT_ADAPTER *ioc;
861 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
862 return;
864 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
866 list_for_each_entry(ioc, &ioc_list, list) {
867 if (dd_cbfunc->remove)
868 dd_cbfunc->remove(ioc->pcidev);
871 MptDeviceDriverHandlers[cb_idx] = NULL;
875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
877 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
878 * @cb_idx: Handle of registered MPT protocol driver
879 * @ioc: Pointer to MPT adapter structure
881 * Obtain an MPT request frame from the pool (of 1024) that are
882 * allocated per MPT adapter.
884 * Returns pointer to a MPT request frame or %NULL if none are available
885 * or IOC is not active.
887 MPT_FRAME_HDR*
888 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
890 MPT_FRAME_HDR *mf;
891 unsigned long flags;
892 u16 req_idx; /* Request index */
894 /* validate handle and ioc identifier */
896 #ifdef MFCNT
897 if (!ioc->active)
898 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
899 "returning NULL!\n", ioc->name);
900 #endif
902 /* If interrupts are not attached, do not return a request frame */
903 if (!ioc->active)
904 return NULL;
906 spin_lock_irqsave(&ioc->FreeQlock, flags);
907 if (!list_empty(&ioc->FreeQ)) {
908 int req_offset;
910 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
911 u.frame.linkage.list);
912 list_del(&mf->u.frame.linkage.list);
913 mf->u.frame.linkage.arg1 = 0;
914 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
915 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
916 /* u16! */
917 req_idx = req_offset / ioc->req_sz;
918 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
919 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
920 /* Default, will be changed if necessary in SG generation */
921 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
922 #ifdef MFCNT
923 ioc->mfcnt++;
924 #endif
926 else
927 mf = NULL;
928 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
930 #ifdef MFCNT
931 if (mf == NULL)
932 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
933 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
934 ioc->req_depth);
935 mfcounter++;
936 if (mfcounter == PRINT_MF_COUNT)
937 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
938 ioc->mfcnt, ioc->req_depth);
939 #endif
941 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
942 ioc->name, cb_idx, ioc->id, mf));
943 return mf;
946 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
948 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
949 * @cb_idx: Handle of registered MPT protocol driver
950 * @ioc: Pointer to MPT adapter structure
951 * @mf: Pointer to MPT request frame
953 * This routine posts an MPT request frame to the request post FIFO of a
954 * specific MPT adapter.
956 void
957 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
959 u32 mf_dma_addr;
960 int req_offset;
961 u16 req_idx; /* Request index */
963 /* ensure values are reset properly! */
964 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
965 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
966 /* u16! */
967 req_idx = req_offset / ioc->req_sz;
968 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
969 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
971 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
973 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
974 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
975 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
976 ioc->RequestNB[req_idx]));
977 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
981 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
982 * @cb_idx: Handle of registered MPT protocol driver
983 * @ioc: Pointer to MPT adapter structure
984 * @mf: Pointer to MPT request frame
986 * Send a protocol-specific MPT request frame to an IOC using
987 * hi-priority request queue.
989 * This routine posts an MPT request frame to the request post FIFO of a
990 * specific MPT adapter.
992 void
993 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
995 u32 mf_dma_addr;
996 int req_offset;
997 u16 req_idx; /* Request index */
999 /* ensure values are reset properly! */
1000 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1001 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
1002 req_idx = req_offset / ioc->req_sz;
1003 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
1004 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
1006 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
1008 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
1009 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
1010 ioc->name, mf_dma_addr, req_idx));
1011 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
1014 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1016 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
1017 * @ioc: Pointer to MPT adapter structure
1018 * @mf: Pointer to MPT request frame
1020 * This routine places a MPT request frame back on the MPT adapter's
1021 * FreeQ.
1023 void
1024 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
1026 unsigned long flags;
1028 /* Put Request back on FreeQ! */
1029 spin_lock_irqsave(&ioc->FreeQlock, flags);
1030 if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf)
1031 goto out;
1032 /* signature to know if this mf is freed */
1033 mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf);
1034 list_add(&mf->u.frame.linkage.list, &ioc->FreeQ);
1035 #ifdef MFCNT
1036 ioc->mfcnt--;
1037 #endif
1038 out:
1039 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1042 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1044 * mpt_add_sge - Place a simple 32 bit SGE at address pAddr.
1045 * @pAddr: virtual address for SGE
1046 * @flagslength: SGE flags and data transfer length
1047 * @dma_addr: Physical address
1049 * This routine places a MPT request frame back on the MPT adapter's
1050 * FreeQ.
1052 static void
1053 mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1055 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1056 pSge->FlagsLength = cpu_to_le32(flagslength);
1057 pSge->Address = cpu_to_le32(dma_addr);
1061 * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr.
1062 * @pAddr: virtual address for SGE
1063 * @flagslength: SGE flags and data transfer length
1064 * @dma_addr: Physical address
1066 * This routine places a MPT request frame back on the MPT adapter's
1067 * FreeQ.
1069 static void
1070 mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1072 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1073 pSge->Address.Low = cpu_to_le32
1074 (lower_32_bits(dma_addr));
1075 pSge->Address.High = cpu_to_le32
1076 (upper_32_bits(dma_addr));
1077 pSge->FlagsLength = cpu_to_le32
1078 ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1082 * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround).
1083 * @pAddr: virtual address for SGE
1084 * @flagslength: SGE flags and data transfer length
1085 * @dma_addr: Physical address
1087 * This routine places a MPT request frame back on the MPT adapter's
1088 * FreeQ.
1090 static void
1091 mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1093 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1094 u32 tmp;
1096 pSge->Address.Low = cpu_to_le32
1097 (lower_32_bits(dma_addr));
1098 tmp = (u32)(upper_32_bits(dma_addr));
1101 * 1078 errata workaround for the 36GB limitation
1103 if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) {
1104 flagslength |=
1105 MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS);
1106 tmp |= (1<<31);
1107 if (mpt_debug_level & MPT_DEBUG_36GB_MEM)
1108 printk(KERN_DEBUG "1078 P0M2 addressing for "
1109 "addr = 0x%llx len = %d\n",
1110 (unsigned long long)dma_addr,
1111 MPI_SGE_LENGTH(flagslength));
1114 pSge->Address.High = cpu_to_le32(tmp);
1115 pSge->FlagsLength = cpu_to_le32(
1116 (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1119 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1121 * mpt_add_chain - Place a 32 bit chain SGE at address pAddr.
1122 * @pAddr: virtual address for SGE
1123 * @next: nextChainOffset value (u32's)
1124 * @length: length of next SGL segment
1125 * @dma_addr: Physical address
1128 static void
1129 mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1131 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
1132 pChain->Length = cpu_to_le16(length);
1133 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
1134 pChain->NextChainOffset = next;
1135 pChain->Address = cpu_to_le32(dma_addr);
1138 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1140 * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
1141 * @pAddr: virtual address for SGE
1142 * @next: nextChainOffset value (u32's)
1143 * @length: length of next SGL segment
1144 * @dma_addr: Physical address
1147 static void
1148 mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1150 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1151 u32 tmp = dma_addr & 0xFFFFFFFF;
1153 pChain->Length = cpu_to_le16(length);
1154 pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
1155 MPI_SGE_FLAGS_64_BIT_ADDRESSING);
1157 pChain->NextChainOffset = next;
1159 pChain->Address.Low = cpu_to_le32(tmp);
1160 tmp = (u32)(upper_32_bits(dma_addr));
1161 pChain->Address.High = cpu_to_le32(tmp);
1164 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1166 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1167 * @cb_idx: Handle of registered MPT protocol driver
1168 * @ioc: Pointer to MPT adapter structure
1169 * @reqBytes: Size of the request in bytes
1170 * @req: Pointer to MPT request frame
1171 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1173 * This routine is used exclusively to send MptScsiTaskMgmt
1174 * requests since they are required to be sent via doorbell handshake.
1176 * NOTE: It is the callers responsibility to byte-swap fields in the
1177 * request which are greater than 1 byte in size.
1179 * Returns 0 for success, non-zero for failure.
1182 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1184 int r = 0;
1185 u8 *req_as_bytes;
1186 int ii;
1188 /* State is known to be good upon entering
1189 * this function so issue the bus reset
1190 * request.
1194 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1195 * setting cb_idx/req_idx. But ONLY if this request
1196 * is in proper (pre-alloc'd) request buffer range...
1198 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1199 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1200 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1201 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1202 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1205 /* Make sure there are no doorbells */
1206 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1208 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1209 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1210 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1212 /* Wait for IOC doorbell int */
1213 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1214 return ii;
1217 /* Read doorbell and check for active bit */
1218 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1219 return -5;
1221 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1222 ioc->name, ii));
1224 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1226 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1227 return -2;
1230 /* Send request via doorbell handshake */
1231 req_as_bytes = (u8 *) req;
1232 for (ii = 0; ii < reqBytes/4; ii++) {
1233 u32 word;
1235 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1236 (req_as_bytes[(ii*4) + 1] << 8) |
1237 (req_as_bytes[(ii*4) + 2] << 16) |
1238 (req_as_bytes[(ii*4) + 3] << 24));
1239 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1240 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1241 r = -3;
1242 break;
1246 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1247 r = 0;
1248 else
1249 r = -4;
1251 /* Make sure there are no doorbells */
1252 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1254 return r;
1257 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1259 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1260 * @ioc: Pointer to MPT adapter structure
1261 * @access_control_value: define bits below
1262 * @sleepFlag: Specifies whether the process can sleep
1264 * Provides mechanism for the host driver to control the IOC's
1265 * Host Page Buffer access.
1267 * Access Control Value - bits[15:12]
1268 * 0h Reserved
1269 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1270 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1271 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1273 * Returns 0 for success, non-zero for failure.
1276 static int
1277 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1279 int r = 0;
1281 /* return if in use */
1282 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1283 & MPI_DOORBELL_ACTIVE)
1284 return -1;
1286 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1288 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1289 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1290 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1291 (access_control_value<<12)));
1293 /* Wait for IOC to clear Doorbell Status bit */
1294 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1295 return -2;
1296 }else
1297 return 0;
1300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1302 * mpt_host_page_alloc - allocate system memory for the fw
1303 * @ioc: Pointer to pointer to IOC adapter
1304 * @ioc_init: Pointer to ioc init config page
1306 * If we already allocated memory in past, then resend the same pointer.
1307 * Returns 0 for success, non-zero for failure.
1309 static int
1310 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1312 char *psge;
1313 int flags_length;
1314 u32 host_page_buffer_sz=0;
1316 if(!ioc->HostPageBuffer) {
1318 host_page_buffer_sz =
1319 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1321 if(!host_page_buffer_sz)
1322 return 0; /* fw doesn't need any host buffers */
1324 /* spin till we get enough memory */
1325 while(host_page_buffer_sz > 0) {
1327 if((ioc->HostPageBuffer = pci_alloc_consistent(
1328 ioc->pcidev,
1329 host_page_buffer_sz,
1330 &ioc->HostPageBuffer_dma)) != NULL) {
1332 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1333 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1334 ioc->name, ioc->HostPageBuffer,
1335 (u32)ioc->HostPageBuffer_dma,
1336 host_page_buffer_sz));
1337 ioc->alloc_total += host_page_buffer_sz;
1338 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1339 break;
1342 host_page_buffer_sz -= (4*1024);
1346 if(!ioc->HostPageBuffer) {
1347 printk(MYIOC_s_ERR_FMT
1348 "Failed to alloc memory for host_page_buffer!\n",
1349 ioc->name);
1350 return -999;
1353 psge = (char *)&ioc_init->HostPageBufferSGE;
1354 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1355 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1356 MPI_SGE_FLAGS_HOST_TO_IOC |
1357 MPI_SGE_FLAGS_END_OF_BUFFER;
1358 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1359 flags_length |= ioc->HostPageBuffer_sz;
1360 ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1361 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1363 return 0;
1366 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1368 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1369 * @iocid: IOC unique identifier (integer)
1370 * @iocpp: Pointer to pointer to IOC adapter
1372 * Given a unique IOC identifier, set pointer to the associated MPT
1373 * adapter structure.
1375 * Returns iocid and sets iocpp if iocid is found.
1376 * Returns -1 if iocid is not found.
1379 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1381 MPT_ADAPTER *ioc;
1383 list_for_each_entry(ioc,&ioc_list,list) {
1384 if (ioc->id == iocid) {
1385 *iocpp =ioc;
1386 return iocid;
1390 *iocpp = NULL;
1391 return -1;
1395 * mpt_get_product_name - returns product string
1396 * @vendor: pci vendor id
1397 * @device: pci device id
1398 * @revision: pci revision id
1400 * Returns product string displayed when driver loads,
1401 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1404 static const char*
1405 mpt_get_product_name(u16 vendor, u16 device, u8 revision)
1407 char *product_str = NULL;
1409 if (vendor == PCI_VENDOR_ID_BROCADE) {
1410 switch (device)
1412 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1413 switch (revision)
1415 case 0x00:
1416 product_str = "BRE040 A0";
1417 break;
1418 case 0x01:
1419 product_str = "BRE040 A1";
1420 break;
1421 default:
1422 product_str = "BRE040";
1423 break;
1425 break;
1427 goto out;
1430 switch (device)
1432 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1433 product_str = "LSIFC909 B1";
1434 break;
1435 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1436 product_str = "LSIFC919 B0";
1437 break;
1438 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1439 product_str = "LSIFC929 B0";
1440 break;
1441 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1442 if (revision < 0x80)
1443 product_str = "LSIFC919X A0";
1444 else
1445 product_str = "LSIFC919XL A1";
1446 break;
1447 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1448 if (revision < 0x80)
1449 product_str = "LSIFC929X A0";
1450 else
1451 product_str = "LSIFC929XL A1";
1452 break;
1453 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1454 product_str = "LSIFC939X A1";
1455 break;
1456 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1457 product_str = "LSIFC949X A1";
1458 break;
1459 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1460 switch (revision)
1462 case 0x00:
1463 product_str = "LSIFC949E A0";
1464 break;
1465 case 0x01:
1466 product_str = "LSIFC949E A1";
1467 break;
1468 default:
1469 product_str = "LSIFC949E";
1470 break;
1472 break;
1473 case MPI_MANUFACTPAGE_DEVID_53C1030:
1474 switch (revision)
1476 case 0x00:
1477 product_str = "LSI53C1030 A0";
1478 break;
1479 case 0x01:
1480 product_str = "LSI53C1030 B0";
1481 break;
1482 case 0x03:
1483 product_str = "LSI53C1030 B1";
1484 break;
1485 case 0x07:
1486 product_str = "LSI53C1030 B2";
1487 break;
1488 case 0x08:
1489 product_str = "LSI53C1030 C0";
1490 break;
1491 case 0x80:
1492 product_str = "LSI53C1030T A0";
1493 break;
1494 case 0x83:
1495 product_str = "LSI53C1030T A2";
1496 break;
1497 case 0x87:
1498 product_str = "LSI53C1030T A3";
1499 break;
1500 case 0xc1:
1501 product_str = "LSI53C1020A A1";
1502 break;
1503 default:
1504 product_str = "LSI53C1030";
1505 break;
1507 break;
1508 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1509 switch (revision)
1511 case 0x03:
1512 product_str = "LSI53C1035 A2";
1513 break;
1514 case 0x04:
1515 product_str = "LSI53C1035 B0";
1516 break;
1517 default:
1518 product_str = "LSI53C1035";
1519 break;
1521 break;
1522 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1523 switch (revision)
1525 case 0x00:
1526 product_str = "LSISAS1064 A1";
1527 break;
1528 case 0x01:
1529 product_str = "LSISAS1064 A2";
1530 break;
1531 case 0x02:
1532 product_str = "LSISAS1064 A3";
1533 break;
1534 case 0x03:
1535 product_str = "LSISAS1064 A4";
1536 break;
1537 default:
1538 product_str = "LSISAS1064";
1539 break;
1541 break;
1542 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1543 switch (revision)
1545 case 0x00:
1546 product_str = "LSISAS1064E A0";
1547 break;
1548 case 0x01:
1549 product_str = "LSISAS1064E B0";
1550 break;
1551 case 0x02:
1552 product_str = "LSISAS1064E B1";
1553 break;
1554 case 0x04:
1555 product_str = "LSISAS1064E B2";
1556 break;
1557 case 0x08:
1558 product_str = "LSISAS1064E B3";
1559 break;
1560 default:
1561 product_str = "LSISAS1064E";
1562 break;
1564 break;
1565 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1566 switch (revision)
1568 case 0x00:
1569 product_str = "LSISAS1068 A0";
1570 break;
1571 case 0x01:
1572 product_str = "LSISAS1068 B0";
1573 break;
1574 case 0x02:
1575 product_str = "LSISAS1068 B1";
1576 break;
1577 default:
1578 product_str = "LSISAS1068";
1579 break;
1581 break;
1582 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1583 switch (revision)
1585 case 0x00:
1586 product_str = "LSISAS1068E A0";
1587 break;
1588 case 0x01:
1589 product_str = "LSISAS1068E B0";
1590 break;
1591 case 0x02:
1592 product_str = "LSISAS1068E B1";
1593 break;
1594 case 0x04:
1595 product_str = "LSISAS1068E B2";
1596 break;
1597 case 0x08:
1598 product_str = "LSISAS1068E B3";
1599 break;
1600 default:
1601 product_str = "LSISAS1068E";
1602 break;
1604 break;
1605 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1606 switch (revision)
1608 case 0x00:
1609 product_str = "LSISAS1078 A0";
1610 break;
1611 case 0x01:
1612 product_str = "LSISAS1078 B0";
1613 break;
1614 case 0x02:
1615 product_str = "LSISAS1078 C0";
1616 break;
1617 case 0x03:
1618 product_str = "LSISAS1078 C1";
1619 break;
1620 case 0x04:
1621 product_str = "LSISAS1078 C2";
1622 break;
1623 default:
1624 product_str = "LSISAS1078";
1625 break;
1627 break;
1630 out:
1631 return product_str;
1635 * mpt_mapresources - map in memory mapped io
1636 * @ioc: Pointer to pointer to IOC adapter
1639 static int
1640 mpt_mapresources(MPT_ADAPTER *ioc)
1642 u8 __iomem *mem;
1643 int ii;
1644 resource_size_t mem_phys;
1645 unsigned long port;
1646 u32 msize;
1647 u32 psize;
1648 int r = -ENODEV;
1649 struct pci_dev *pdev;
1651 pdev = ioc->pcidev;
1652 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1653 if (pci_enable_device_mem(pdev)) {
1654 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1655 "failed\n", ioc->name);
1656 return r;
1658 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1659 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1660 "MEM failed\n", ioc->name);
1661 goto out_pci_disable_device;
1664 if (sizeof(dma_addr_t) > 4) {
1665 const uint64_t required_mask = dma_get_required_mask
1666 (&pdev->dev);
1667 if (required_mask > DMA_BIT_MASK(32)
1668 && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1669 && !pci_set_consistent_dma_mask(pdev,
1670 DMA_BIT_MASK(64))) {
1671 ioc->dma_mask = DMA_BIT_MASK(64);
1672 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1673 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1674 ioc->name));
1675 } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1676 && !pci_set_consistent_dma_mask(pdev,
1677 DMA_BIT_MASK(32))) {
1678 ioc->dma_mask = DMA_BIT_MASK(32);
1679 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1680 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1681 ioc->name));
1682 } else {
1683 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1684 ioc->name, pci_name(pdev));
1685 goto out_pci_release_region;
1687 } else {
1688 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1689 && !pci_set_consistent_dma_mask(pdev,
1690 DMA_BIT_MASK(32))) {
1691 ioc->dma_mask = DMA_BIT_MASK(32);
1692 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1693 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1694 ioc->name));
1695 } else {
1696 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1697 ioc->name, pci_name(pdev));
1698 goto out_pci_release_region;
1702 mem_phys = msize = 0;
1703 port = psize = 0;
1704 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1705 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1706 if (psize)
1707 continue;
1708 /* Get I/O space! */
1709 port = pci_resource_start(pdev, ii);
1710 psize = pci_resource_len(pdev, ii);
1711 } else {
1712 if (msize)
1713 continue;
1714 /* Get memmap */
1715 mem_phys = pci_resource_start(pdev, ii);
1716 msize = pci_resource_len(pdev, ii);
1719 ioc->mem_size = msize;
1721 mem = NULL;
1722 /* Get logical ptr for PciMem0 space */
1723 /*mem = ioremap(mem_phys, msize);*/
1724 mem = ioremap(mem_phys, msize);
1725 if (mem == NULL) {
1726 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1727 " memory!\n", ioc->name);
1728 r = -EINVAL;
1729 goto out_pci_release_region;
1731 ioc->memmap = mem;
1732 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
1733 ioc->name, mem, (unsigned long long)mem_phys));
1735 ioc->mem_phys = mem_phys;
1736 ioc->chip = (SYSIF_REGS __iomem *)mem;
1738 /* Save Port IO values in case we need to do downloadboot */
1739 ioc->pio_mem_phys = port;
1740 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1742 return 0;
1744 out_pci_release_region:
1745 pci_release_selected_regions(pdev, ioc->bars);
1746 out_pci_disable_device:
1747 pci_disable_device(pdev);
1748 return r;
1751 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1753 * mpt_attach - Install a PCI intelligent MPT adapter.
1754 * @pdev: Pointer to pci_dev structure
1755 * @id: PCI device ID information
1757 * This routine performs all the steps necessary to bring the IOC of
1758 * a MPT adapter to a OPERATIONAL state. This includes registering
1759 * memory regions, registering the interrupt, and allocating request
1760 * and reply memory pools.
1762 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1763 * MPT adapter.
1765 * Returns 0 for success, non-zero for failure.
1767 * TODO: Add support for polled controllers
1770 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1772 MPT_ADAPTER *ioc;
1773 u8 cb_idx;
1774 int r = -ENODEV;
1775 u8 pcixcmd;
1776 static int mpt_ids = 0;
1777 #ifdef CONFIG_PROC_FS
1778 struct proc_dir_entry *dent;
1779 #endif
1781 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1782 if (ioc == NULL) {
1783 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1784 return -ENOMEM;
1787 ioc->id = mpt_ids++;
1788 sprintf(ioc->name, "ioc%d", ioc->id);
1789 dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1792 * set initial debug level
1793 * (refer to mptdebug.h)
1796 ioc->debug_level = mpt_debug_level;
1797 if (mpt_debug_level)
1798 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1800 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1802 ioc->pcidev = pdev;
1803 if (mpt_mapresources(ioc)) {
1804 kfree(ioc);
1805 return r;
1809 * Setting up proper handlers for scatter gather handling
1811 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
1812 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
1813 ioc->add_sge = &mpt_add_sge_64bit_1078;
1814 else
1815 ioc->add_sge = &mpt_add_sge_64bit;
1816 ioc->add_chain = &mpt_add_chain_64bit;
1817 ioc->sg_addr_size = 8;
1818 } else {
1819 ioc->add_sge = &mpt_add_sge;
1820 ioc->add_chain = &mpt_add_chain;
1821 ioc->sg_addr_size = 4;
1823 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
1825 ioc->alloc_total = sizeof(MPT_ADAPTER);
1826 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1827 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1830 spin_lock_init(&ioc->taskmgmt_lock);
1831 mutex_init(&ioc->internal_cmds.mutex);
1832 init_completion(&ioc->internal_cmds.done);
1833 mutex_init(&ioc->mptbase_cmds.mutex);
1834 init_completion(&ioc->mptbase_cmds.done);
1835 mutex_init(&ioc->taskmgmt_cmds.mutex);
1836 init_completion(&ioc->taskmgmt_cmds.done);
1838 /* Initialize the event logging.
1840 ioc->eventTypes = 0; /* None */
1841 ioc->eventContext = 0;
1842 ioc->eventLogSize = 0;
1843 ioc->events = NULL;
1845 #ifdef MFCNT
1846 ioc->mfcnt = 0;
1847 #endif
1849 ioc->sh = NULL;
1850 ioc->cached_fw = NULL;
1852 /* Initialize SCSI Config Data structure
1854 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1856 /* Initialize the fc rport list head.
1858 INIT_LIST_HEAD(&ioc->fc_rports);
1860 /* Find lookup slot. */
1861 INIT_LIST_HEAD(&ioc->list);
1864 /* Initialize workqueue */
1865 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1867 snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
1868 "mpt_poll_%d", ioc->id);
1869 ioc->reset_work_q =
1870 create_singlethread_workqueue(ioc->reset_work_q_name);
1871 if (!ioc->reset_work_q) {
1872 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1873 ioc->name);
1874 pci_release_selected_regions(pdev, ioc->bars);
1875 kfree(ioc);
1876 return -ENOMEM;
1879 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1880 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1882 ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device,
1883 pdev->revision);
1885 switch (pdev->device)
1887 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1888 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1889 ioc->errata_flag_1064 = 1;
1890 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1891 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1892 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1893 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1894 ioc->bus_type = FC;
1895 break;
1897 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1898 if (pdev->revision < XL_929) {
1899 /* 929X Chip Fix. Set Split transactions level
1900 * for PCIX. Set MOST bits to zero.
1902 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1903 pcixcmd &= 0x8F;
1904 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1905 } else {
1906 /* 929XL Chip Fix. Set MMRBC to 0x08.
1908 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1909 pcixcmd |= 0x08;
1910 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1912 ioc->bus_type = FC;
1913 break;
1915 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1916 /* 919X Chip Fix. Set Split transactions level
1917 * for PCIX. Set MOST bits to zero.
1919 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1920 pcixcmd &= 0x8F;
1921 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1922 ioc->bus_type = FC;
1923 break;
1925 case MPI_MANUFACTPAGE_DEVID_53C1030:
1926 /* 1030 Chip Fix. Disable Split transactions
1927 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1929 if (pdev->revision < C0_1030) {
1930 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1931 pcixcmd &= 0x8F;
1932 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1935 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1936 ioc->bus_type = SPI;
1937 break;
1939 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1940 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1941 ioc->errata_flag_1064 = 1;
1942 ioc->bus_type = SAS;
1943 break;
1945 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1946 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1947 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1948 ioc->bus_type = SAS;
1949 break;
1953 switch (ioc->bus_type) {
1955 case SAS:
1956 ioc->msi_enable = mpt_msi_enable_sas;
1957 break;
1959 case SPI:
1960 ioc->msi_enable = mpt_msi_enable_spi;
1961 break;
1963 case FC:
1964 ioc->msi_enable = mpt_msi_enable_fc;
1965 break;
1967 default:
1968 ioc->msi_enable = 0;
1969 break;
1972 ioc->fw_events_off = 1;
1974 if (ioc->errata_flag_1064)
1975 pci_disable_io_access(pdev);
1977 spin_lock_init(&ioc->FreeQlock);
1979 /* Disable all! */
1980 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1981 ioc->active = 0;
1982 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1984 /* Set IOC ptr in the pcidev's driver data. */
1985 pci_set_drvdata(ioc->pcidev, ioc);
1987 /* Set lookup ptr. */
1988 list_add_tail(&ioc->list, &ioc_list);
1990 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1992 mpt_detect_bound_ports(ioc, pdev);
1994 INIT_LIST_HEAD(&ioc->fw_event_list);
1995 spin_lock_init(&ioc->fw_event_lock);
1996 snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
1997 ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
1999 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2000 CAN_SLEEP)) != 0){
2001 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
2002 ioc->name, r);
2004 list_del(&ioc->list);
2005 if (ioc->alt_ioc)
2006 ioc->alt_ioc->alt_ioc = NULL;
2007 iounmap(ioc->memmap);
2008 if (r != -5)
2009 pci_release_selected_regions(pdev, ioc->bars);
2011 destroy_workqueue(ioc->reset_work_q);
2012 ioc->reset_work_q = NULL;
2014 kfree(ioc);
2015 pci_set_drvdata(pdev, NULL);
2016 return r;
2019 /* call per device driver probe entry point */
2020 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2021 if(MptDeviceDriverHandlers[cb_idx] &&
2022 MptDeviceDriverHandlers[cb_idx]->probe) {
2023 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
2027 #ifdef CONFIG_PROC_FS
2029 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
2031 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
2032 if (dent) {
2033 proc_create_data("info", S_IRUGO, dent, &mpt_iocinfo_proc_fops, ioc);
2034 proc_create_data("summary", S_IRUGO, dent, &mpt_summary_proc_fops, ioc);
2036 #endif
2038 if (!ioc->alt_ioc)
2039 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
2040 msecs_to_jiffies(MPT_POLLING_INTERVAL));
2042 return 0;
2045 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2047 * mpt_detach - Remove a PCI intelligent MPT adapter.
2048 * @pdev: Pointer to pci_dev structure
2051 void
2052 mpt_detach(struct pci_dev *pdev)
2054 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2055 char pname[32];
2056 u8 cb_idx;
2057 unsigned long flags;
2058 struct workqueue_struct *wq;
2061 * Stop polling ioc for fault condition
2063 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2064 wq = ioc->reset_work_q;
2065 ioc->reset_work_q = NULL;
2066 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2067 cancel_delayed_work(&ioc->fault_reset_work);
2068 destroy_workqueue(wq);
2070 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2071 wq = ioc->fw_event_q;
2072 ioc->fw_event_q = NULL;
2073 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2074 destroy_workqueue(wq);
2076 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
2077 remove_proc_entry(pname, NULL);
2078 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
2079 remove_proc_entry(pname, NULL);
2080 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2081 remove_proc_entry(pname, NULL);
2083 /* call per device driver remove entry point */
2084 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2085 if(MptDeviceDriverHandlers[cb_idx] &&
2086 MptDeviceDriverHandlers[cb_idx]->remove) {
2087 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
2091 /* Disable interrupts! */
2092 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2094 ioc->active = 0;
2095 synchronize_irq(pdev->irq);
2097 /* Clear any lingering interrupt */
2098 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2100 CHIPREG_READ32(&ioc->chip->IntStatus);
2102 mpt_adapter_dispose(ioc);
2106 /**************************************************************************
2107 * Power Management
2109 #ifdef CONFIG_PM
2110 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2112 * mpt_suspend - Fusion MPT base driver suspend routine.
2113 * @pdev: Pointer to pci_dev structure
2114 * @state: new state to enter
2117 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
2119 u32 device_state;
2120 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2122 device_state = pci_choose_state(pdev, state);
2123 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
2124 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2125 device_state);
2127 /* put ioc into READY_STATE */
2128 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
2129 printk(MYIOC_s_ERR_FMT
2130 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
2133 /* disable interrupts */
2134 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2135 ioc->active = 0;
2137 /* Clear any lingering interrupt */
2138 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2140 free_irq(ioc->pci_irq, ioc);
2141 if (ioc->msi_enable)
2142 pci_disable_msi(ioc->pcidev);
2143 ioc->pci_irq = -1;
2144 pci_save_state(pdev);
2145 pci_disable_device(pdev);
2146 pci_release_selected_regions(pdev, ioc->bars);
2147 pci_set_power_state(pdev, device_state);
2148 return 0;
2151 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2153 * mpt_resume - Fusion MPT base driver resume routine.
2154 * @pdev: Pointer to pci_dev structure
2157 mpt_resume(struct pci_dev *pdev)
2159 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2160 u32 device_state = pdev->current_state;
2161 int recovery_state;
2162 int err;
2164 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
2165 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2166 device_state);
2168 pci_set_power_state(pdev, PCI_D0);
2169 pci_enable_wake(pdev, PCI_D0, 0);
2170 pci_restore_state(pdev);
2171 ioc->pcidev = pdev;
2172 err = mpt_mapresources(ioc);
2173 if (err)
2174 return err;
2176 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
2177 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
2178 ioc->add_sge = &mpt_add_sge_64bit_1078;
2179 else
2180 ioc->add_sge = &mpt_add_sge_64bit;
2181 ioc->add_chain = &mpt_add_chain_64bit;
2182 ioc->sg_addr_size = 8;
2183 } else {
2185 ioc->add_sge = &mpt_add_sge;
2186 ioc->add_chain = &mpt_add_chain;
2187 ioc->sg_addr_size = 4;
2189 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
2191 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
2192 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
2193 CHIPREG_READ32(&ioc->chip->Doorbell));
2196 * Errata workaround for SAS pci express:
2197 * Upon returning to the D0 state, the contents of the doorbell will be
2198 * stale data, and this will incorrectly signal to the host driver that
2199 * the firmware is ready to process mpt commands. The workaround is
2200 * to issue a diagnostic reset.
2202 if (ioc->bus_type == SAS && (pdev->device ==
2203 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2204 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2205 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2206 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2207 ioc->name);
2208 goto out;
2212 /* bring ioc to operational state */
2213 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2214 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2215 CAN_SLEEP);
2216 if (recovery_state != 0)
2217 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2218 "error:[%x]\n", ioc->name, recovery_state);
2219 else
2220 printk(MYIOC_s_INFO_FMT
2221 "pci-resume: success\n", ioc->name);
2222 out:
2223 return 0;
2226 #endif
2228 static int
2229 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2231 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2232 ioc->bus_type != SPI) ||
2233 (MptDriverClass[index] == MPTFC_DRIVER &&
2234 ioc->bus_type != FC) ||
2235 (MptDriverClass[index] == MPTSAS_DRIVER &&
2236 ioc->bus_type != SAS))
2237 /* make sure we only call the relevant reset handler
2238 * for the bus */
2239 return 0;
2240 return (MptResetHandlers[index])(ioc, reset_phase);
2243 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2245 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2246 * @ioc: Pointer to MPT adapter structure
2247 * @reason: Event word / reason
2248 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2250 * This routine performs all the steps necessary to bring the IOC
2251 * to a OPERATIONAL state.
2253 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2254 * MPT adapter.
2256 * Returns:
2257 * 0 for success
2258 * -1 if failed to get board READY
2259 * -2 if READY but IOCFacts Failed
2260 * -3 if READY but PrimeIOCFifos Failed
2261 * -4 if READY but IOCInit Failed
2262 * -5 if failed to enable_device and/or request_selected_regions
2263 * -6 if failed to upload firmware
2265 static int
2266 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2268 int hard_reset_done = 0;
2269 int alt_ioc_ready = 0;
2270 int hard;
2271 int rc=0;
2272 int ii;
2273 int ret = 0;
2274 int reset_alt_ioc_active = 0;
2275 int irq_allocated = 0;
2276 u8 *a;
2278 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2279 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2281 /* Disable reply interrupts (also blocks FreeQ) */
2282 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2283 ioc->active = 0;
2285 if (ioc->alt_ioc) {
2286 if (ioc->alt_ioc->active ||
2287 reason == MPT_HOSTEVENT_IOC_RECOVER) {
2288 reset_alt_ioc_active = 1;
2289 /* Disable alt-IOC's reply interrupts
2290 * (and FreeQ) for a bit
2292 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2293 0xFFFFFFFF);
2294 ioc->alt_ioc->active = 0;
2298 hard = 1;
2299 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2300 hard = 0;
2302 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2303 if (hard_reset_done == -4) {
2304 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2305 ioc->name);
2307 if (reset_alt_ioc_active && ioc->alt_ioc) {
2308 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2309 dprintk(ioc, printk(MYIOC_s_INFO_FMT
2310 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2311 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2312 ioc->alt_ioc->active = 1;
2315 } else {
2316 printk(MYIOC_s_WARN_FMT
2317 "NOT READY WARNING!\n", ioc->name);
2319 ret = -1;
2320 goto out;
2323 /* hard_reset_done = 0 if a soft reset was performed
2324 * and 1 if a hard reset was performed.
2326 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2327 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2328 alt_ioc_ready = 1;
2329 else
2330 printk(MYIOC_s_WARN_FMT
2331 ": alt-ioc Not ready WARNING!\n",
2332 ioc->alt_ioc->name);
2335 for (ii=0; ii<5; ii++) {
2336 /* Get IOC facts! Allow 5 retries */
2337 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2338 break;
2342 if (ii == 5) {
2343 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2344 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2345 ret = -2;
2346 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2347 MptDisplayIocCapabilities(ioc);
2350 if (alt_ioc_ready) {
2351 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2352 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2353 "Initial Alt IocFacts failed rc=%x\n",
2354 ioc->name, rc));
2355 /* Retry - alt IOC was initialized once
2357 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2359 if (rc) {
2360 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2361 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2362 alt_ioc_ready = 0;
2363 reset_alt_ioc_active = 0;
2364 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2365 MptDisplayIocCapabilities(ioc->alt_ioc);
2369 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2370 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2371 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2372 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2373 IORESOURCE_IO);
2374 if (pci_enable_device(ioc->pcidev))
2375 return -5;
2376 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2377 "mpt"))
2378 return -5;
2382 * Device is reset now. It must have de-asserted the interrupt line
2383 * (if it was asserted) and it should be safe to register for the
2384 * interrupt now.
2386 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2387 ioc->pci_irq = -1;
2388 if (ioc->pcidev->irq) {
2389 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2390 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2391 ioc->name);
2392 else
2393 ioc->msi_enable = 0;
2394 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2395 IRQF_SHARED, ioc->name, ioc);
2396 if (rc < 0) {
2397 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2398 "interrupt %d!\n",
2399 ioc->name, ioc->pcidev->irq);
2400 if (ioc->msi_enable)
2401 pci_disable_msi(ioc->pcidev);
2402 ret = -EBUSY;
2403 goto out;
2405 irq_allocated = 1;
2406 ioc->pci_irq = ioc->pcidev->irq;
2407 pci_set_master(ioc->pcidev); /* ?? */
2408 pci_set_drvdata(ioc->pcidev, ioc);
2409 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2410 "installed at interrupt %d\n", ioc->name,
2411 ioc->pcidev->irq));
2415 /* Prime reply & request queues!
2416 * (mucho alloc's) Must be done prior to
2417 * init as upper addresses are needed for init.
2418 * If fails, continue with alt-ioc processing
2420 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
2421 ioc->name));
2422 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2423 ret = -3;
2425 /* May need to check/upload firmware & data here!
2426 * If fails, continue with alt-ioc processing
2428 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
2429 ioc->name));
2430 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2431 ret = -4;
2432 // NEW!
2433 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2434 printk(MYIOC_s_WARN_FMT
2435 ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
2436 ioc->alt_ioc->name, rc);
2437 alt_ioc_ready = 0;
2438 reset_alt_ioc_active = 0;
2441 if (alt_ioc_ready) {
2442 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2443 alt_ioc_ready = 0;
2444 reset_alt_ioc_active = 0;
2445 printk(MYIOC_s_WARN_FMT
2446 ": alt-ioc: (%d) init failure WARNING!\n",
2447 ioc->alt_ioc->name, rc);
2451 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2452 if (ioc->upload_fw) {
2453 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2454 "firmware upload required!\n", ioc->name));
2456 /* Controller is not operational, cannot do upload
2458 if (ret == 0) {
2459 rc = mpt_do_upload(ioc, sleepFlag);
2460 if (rc == 0) {
2461 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2463 * Maintain only one pointer to FW memory
2464 * so there will not be two attempt to
2465 * downloadboot onboard dual function
2466 * chips (mpt_adapter_disable,
2467 * mpt_diag_reset)
2469 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2470 "mpt_upload: alt_%s has cached_fw=%p \n",
2471 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2472 ioc->cached_fw = NULL;
2474 } else {
2475 printk(MYIOC_s_WARN_FMT
2476 "firmware upload failure!\n", ioc->name);
2477 ret = -6;
2483 /* Enable MPT base driver management of EventNotification
2484 * and EventAck handling.
2486 if ((ret == 0) && (!ioc->facts.EventState)) {
2487 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2488 "SendEventNotification\n",
2489 ioc->name));
2490 ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */
2493 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2494 rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
2496 if (ret == 0) {
2497 /* Enable! (reply interrupt) */
2498 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2499 ioc->active = 1;
2501 if (rc == 0) { /* alt ioc */
2502 if (reset_alt_ioc_active && ioc->alt_ioc) {
2503 /* (re)Enable alt-IOC! (reply interrupt) */
2504 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc"
2505 "reply irq re-enabled\n",
2506 ioc->alt_ioc->name));
2507 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2508 MPI_HIM_DIM);
2509 ioc->alt_ioc->active = 1;
2514 /* Add additional "reason" check before call to GetLanConfigPages
2515 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2516 * recursive scenario; GetLanConfigPages times out, timer expired
2517 * routine calls HardResetHandler, which calls into here again,
2518 * and we try GetLanConfigPages again...
2520 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2523 * Initialize link list for inactive raid volumes.
2525 mutex_init(&ioc->raid_data.inactive_list_mutex);
2526 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2528 switch (ioc->bus_type) {
2530 case SAS:
2531 /* clear persistency table */
2532 if(ioc->facts.IOCExceptions &
2533 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2534 ret = mptbase_sas_persist_operation(ioc,
2535 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2536 if(ret != 0)
2537 goto out;
2540 /* Find IM volumes
2542 mpt_findImVolumes(ioc);
2544 /* Check, and possibly reset, the coalescing value
2546 mpt_read_ioc_pg_1(ioc);
2548 break;
2550 case FC:
2551 if ((ioc->pfacts[0].ProtocolFlags &
2552 MPI_PORTFACTS_PROTOCOL_LAN) &&
2553 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2555 * Pre-fetch the ports LAN MAC address!
2556 * (LANPage1_t stuff)
2558 (void) GetLanConfigPages(ioc);
2559 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2560 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2561 "LanAddr = %02X:%02X:%02X"
2562 ":%02X:%02X:%02X\n",
2563 ioc->name, a[5], a[4],
2564 a[3], a[2], a[1], a[0]));
2566 break;
2568 case SPI:
2569 /* Get NVRAM and adapter maximums from SPP 0 and 2
2571 mpt_GetScsiPortSettings(ioc, 0);
2573 /* Get version and length of SDP 1
2575 mpt_readScsiDevicePageHeaders(ioc, 0);
2577 /* Find IM volumes
2579 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2580 mpt_findImVolumes(ioc);
2582 /* Check, and possibly reset, the coalescing value
2584 mpt_read_ioc_pg_1(ioc);
2586 mpt_read_ioc_pg_4(ioc);
2588 break;
2591 GetIoUnitPage2(ioc);
2592 mpt_get_manufacturing_pg_0(ioc);
2595 out:
2596 if ((ret != 0) && irq_allocated) {
2597 free_irq(ioc->pci_irq, ioc);
2598 if (ioc->msi_enable)
2599 pci_disable_msi(ioc->pcidev);
2601 return ret;
2604 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2606 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2607 * @ioc: Pointer to MPT adapter structure
2608 * @pdev: Pointer to (struct pci_dev) structure
2610 * Search for PCI bus/dev_function which matches
2611 * PCI bus/dev_function (+/-1) for newly discovered 929,
2612 * 929X, 1030 or 1035.
2614 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2615 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2617 static void
2618 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2620 struct pci_dev *peer=NULL;
2621 unsigned int slot = PCI_SLOT(pdev->devfn);
2622 unsigned int func = PCI_FUNC(pdev->devfn);
2623 MPT_ADAPTER *ioc_srch;
2625 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2626 " searching for devfn match on %x or %x\n",
2627 ioc->name, pci_name(pdev), pdev->bus->number,
2628 pdev->devfn, func-1, func+1));
2630 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2631 if (!peer) {
2632 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2633 if (!peer)
2634 return;
2637 list_for_each_entry(ioc_srch, &ioc_list, list) {
2638 struct pci_dev *_pcidev = ioc_srch->pcidev;
2639 if (_pcidev == peer) {
2640 /* Paranoia checks */
2641 if (ioc->alt_ioc != NULL) {
2642 printk(MYIOC_s_WARN_FMT
2643 "Oops, already bound (%s <==> %s)!\n",
2644 ioc->name, ioc->name, ioc->alt_ioc->name);
2645 break;
2646 } else if (ioc_srch->alt_ioc != NULL) {
2647 printk(MYIOC_s_WARN_FMT
2648 "Oops, already bound (%s <==> %s)!\n",
2649 ioc_srch->name, ioc_srch->name,
2650 ioc_srch->alt_ioc->name);
2651 break;
2653 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2654 "FOUND! binding %s <==> %s\n",
2655 ioc->name, ioc->name, ioc_srch->name));
2656 ioc_srch->alt_ioc = ioc;
2657 ioc->alt_ioc = ioc_srch;
2660 pci_dev_put(peer);
2663 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2665 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2666 * @ioc: Pointer to MPT adapter structure
2668 static void
2669 mpt_adapter_disable(MPT_ADAPTER *ioc)
2671 int sz;
2672 int ret;
2674 if (ioc->cached_fw != NULL) {
2675 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2676 "%s: Pushing FW onto adapter\n", __func__, ioc->name));
2677 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2678 ioc->cached_fw, CAN_SLEEP)) < 0) {
2679 printk(MYIOC_s_WARN_FMT
2680 ": firmware downloadboot failure (%d)!\n",
2681 ioc->name, ret);
2686 * Put the controller into ready state (if its not already)
2688 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
2689 if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
2690 CAN_SLEEP)) {
2691 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
2692 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit "
2693 "reset failed to put ioc in ready state!\n",
2694 ioc->name, __func__);
2695 } else
2696 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset "
2697 "failed!\n", ioc->name, __func__);
2701 /* Disable adapter interrupts! */
2702 synchronize_irq(ioc->pcidev->irq);
2703 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2704 ioc->active = 0;
2706 /* Clear any lingering interrupt */
2707 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2708 CHIPREG_READ32(&ioc->chip->IntStatus);
2710 if (ioc->alloc != NULL) {
2711 sz = ioc->alloc_sz;
2712 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2713 ioc->name, ioc->alloc, ioc->alloc_sz));
2714 pci_free_consistent(ioc->pcidev, sz,
2715 ioc->alloc, ioc->alloc_dma);
2716 ioc->reply_frames = NULL;
2717 ioc->req_frames = NULL;
2718 ioc->alloc = NULL;
2719 ioc->alloc_total -= sz;
2722 if (ioc->sense_buf_pool != NULL) {
2723 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2724 pci_free_consistent(ioc->pcidev, sz,
2725 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2726 ioc->sense_buf_pool = NULL;
2727 ioc->alloc_total -= sz;
2730 if (ioc->events != NULL){
2731 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2732 kfree(ioc->events);
2733 ioc->events = NULL;
2734 ioc->alloc_total -= sz;
2737 mpt_free_fw_memory(ioc);
2739 kfree(ioc->spi_data.nvram);
2740 mpt_inactive_raid_list_free(ioc);
2741 kfree(ioc->raid_data.pIocPg2);
2742 kfree(ioc->raid_data.pIocPg3);
2743 ioc->spi_data.nvram = NULL;
2744 ioc->raid_data.pIocPg3 = NULL;
2746 if (ioc->spi_data.pIocPg4 != NULL) {
2747 sz = ioc->spi_data.IocPg4Sz;
2748 pci_free_consistent(ioc->pcidev, sz,
2749 ioc->spi_data.pIocPg4,
2750 ioc->spi_data.IocPg4_dma);
2751 ioc->spi_data.pIocPg4 = NULL;
2752 ioc->alloc_total -= sz;
2755 if (ioc->ReqToChain != NULL) {
2756 kfree(ioc->ReqToChain);
2757 kfree(ioc->RequestNB);
2758 ioc->ReqToChain = NULL;
2761 kfree(ioc->ChainToChain);
2762 ioc->ChainToChain = NULL;
2764 if (ioc->HostPageBuffer != NULL) {
2765 if((ret = mpt_host_page_access_control(ioc,
2766 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2767 printk(MYIOC_s_ERR_FMT
2768 ": %s: host page buffers free failed (%d)!\n",
2769 ioc->name, __func__, ret);
2771 dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2772 "HostPageBuffer free @ %p, sz=%d bytes\n",
2773 ioc->name, ioc->HostPageBuffer,
2774 ioc->HostPageBuffer_sz));
2775 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2776 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2777 ioc->HostPageBuffer = NULL;
2778 ioc->HostPageBuffer_sz = 0;
2779 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2782 pci_set_drvdata(ioc->pcidev, NULL);
2784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2786 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2787 * @ioc: Pointer to MPT adapter structure
2789 * This routine unregisters h/w resources and frees all alloc'd memory
2790 * associated with a MPT adapter structure.
2792 static void
2793 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2795 int sz_first, sz_last;
2797 if (ioc == NULL)
2798 return;
2800 sz_first = ioc->alloc_total;
2802 mpt_adapter_disable(ioc);
2804 if (ioc->pci_irq != -1) {
2805 free_irq(ioc->pci_irq, ioc);
2806 if (ioc->msi_enable)
2807 pci_disable_msi(ioc->pcidev);
2808 ioc->pci_irq = -1;
2811 if (ioc->memmap != NULL) {
2812 iounmap(ioc->memmap);
2813 ioc->memmap = NULL;
2816 pci_disable_device(ioc->pcidev);
2817 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2819 /* Zap the adapter lookup ptr! */
2820 list_del(&ioc->list);
2822 sz_last = ioc->alloc_total;
2823 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2824 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2826 if (ioc->alt_ioc)
2827 ioc->alt_ioc->alt_ioc = NULL;
2829 kfree(ioc);
2832 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2834 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2835 * @ioc: Pointer to MPT adapter structure
2837 static void
2838 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2840 int i = 0;
2842 printk(KERN_INFO "%s: ", ioc->name);
2843 if (ioc->prod_name)
2844 printk("%s: ", ioc->prod_name);
2845 printk("Capabilities={");
2847 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2848 printk("Initiator");
2849 i++;
2852 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2853 printk("%sTarget", i ? "," : "");
2854 i++;
2857 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2858 printk("%sLAN", i ? "," : "");
2859 i++;
2862 #if 0
2864 * This would probably evoke more questions than it's worth
2866 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2867 printk("%sLogBusAddr", i ? "," : "");
2868 i++;
2870 #endif
2872 printk("}\n");
2875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2877 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2878 * @ioc: Pointer to MPT_ADAPTER structure
2879 * @force: Force hard KickStart of IOC
2880 * @sleepFlag: Specifies whether the process can sleep
2882 * Returns:
2883 * 1 - DIAG reset and READY
2884 * 0 - READY initially OR soft reset and READY
2885 * -1 - Any failure on KickStart
2886 * -2 - Msg Unit Reset Failed
2887 * -3 - IO Unit Reset Failed
2888 * -4 - IOC owned by a PEER
2890 static int
2891 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2893 u32 ioc_state;
2894 int statefault = 0;
2895 int cntdn;
2896 int hard_reset_done = 0;
2897 int r;
2898 int ii;
2899 int whoinit;
2901 /* Get current [raw] IOC state */
2902 ioc_state = mpt_GetIocState(ioc, 0);
2903 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2906 * Check to see if IOC got left/stuck in doorbell handshake
2907 * grip of death. If so, hard reset the IOC.
2909 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2910 statefault = 1;
2911 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2912 ioc->name);
2915 /* Is it already READY? */
2916 if (!statefault &&
2917 ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) {
2918 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2919 "IOC is in READY state\n", ioc->name));
2920 return 0;
2924 * Check to see if IOC is in FAULT state.
2926 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2927 statefault = 2;
2928 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2929 ioc->name);
2930 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2931 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2935 * Hmmm... Did it get left operational?
2937 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2938 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2939 ioc->name));
2941 /* Check WhoInit.
2942 * If PCI Peer, exit.
2943 * Else, if no fault conditions are present, issue a MessageUnitReset
2944 * Else, fall through to KickStart case
2946 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2947 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2948 "whoinit 0x%x statefault %d force %d\n",
2949 ioc->name, whoinit, statefault, force));
2950 if (whoinit == MPI_WHOINIT_PCI_PEER)
2951 return -4;
2952 else {
2953 if ((statefault == 0 ) && (force == 0)) {
2954 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2955 return 0;
2957 statefault = 3;
2961 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2962 if (hard_reset_done < 0)
2963 return -1;
2966 * Loop here waiting for IOC to come READY.
2968 ii = 0;
2969 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2971 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2972 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2974 * BIOS or previous driver load left IOC in OP state.
2975 * Reset messaging FIFOs.
2977 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2978 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2979 return -2;
2981 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2983 * Something is wrong. Try to get IOC back
2984 * to a known state.
2986 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2987 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2988 return -3;
2992 ii++; cntdn--;
2993 if (!cntdn) {
2994 printk(MYIOC_s_ERR_FMT
2995 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
2996 ioc->name, ioc_state, (int)((ii+5)/HZ));
2997 return -ETIME;
3000 if (sleepFlag == CAN_SLEEP) {
3001 msleep(1);
3002 } else {
3003 mdelay (1); /* 1 msec delay */
3008 if (statefault < 3) {
3009 printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name,
3010 statefault == 1 ? "stuck handshake" : "IOC FAULT");
3013 return hard_reset_done;
3016 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3018 * mpt_GetIocState - Get the current state of a MPT adapter.
3019 * @ioc: Pointer to MPT_ADAPTER structure
3020 * @cooked: Request raw or cooked IOC state
3022 * Returns all IOC Doorbell register bits if cooked==0, else just the
3023 * Doorbell bits in MPI_IOC_STATE_MASK.
3026 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
3028 u32 s, sc;
3030 /* Get! */
3031 s = CHIPREG_READ32(&ioc->chip->Doorbell);
3032 sc = s & MPI_IOC_STATE_MASK;
3034 /* Save! */
3035 ioc->last_state = sc;
3037 return cooked ? sc : s;
3040 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3042 * GetIocFacts - Send IOCFacts request to MPT adapter.
3043 * @ioc: Pointer to MPT_ADAPTER structure
3044 * @sleepFlag: Specifies whether the process can sleep
3045 * @reason: If recovery, only update facts.
3047 * Returns 0 for success, non-zero for failure.
3049 static int
3050 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
3052 IOCFacts_t get_facts;
3053 IOCFactsReply_t *facts;
3054 int r;
3055 int req_sz;
3056 int reply_sz;
3057 int sz;
3058 u32 status, vv;
3059 u8 shiftFactor=1;
3061 /* IOC *must* NOT be in RESET state! */
3062 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3063 printk(KERN_ERR MYNAM
3064 ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
3065 ioc->name, ioc->last_state);
3066 return -44;
3069 facts = &ioc->facts;
3071 /* Destination (reply area)... */
3072 reply_sz = sizeof(*facts);
3073 memset(facts, 0, reply_sz);
3075 /* Request area (get_facts on the stack right now!) */
3076 req_sz = sizeof(get_facts);
3077 memset(&get_facts, 0, req_sz);
3079 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
3080 /* Assert: All other get_facts fields are zero! */
3082 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3083 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
3084 ioc->name, req_sz, reply_sz));
3086 /* No non-zero fields in the get_facts request are greater than
3087 * 1 byte in size, so we can just fire it off as is.
3089 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
3090 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
3091 if (r != 0)
3092 return r;
3095 * Now byte swap (GRRR) the necessary fields before any further
3096 * inspection of reply contents.
3098 * But need to do some sanity checks on MsgLength (byte) field
3099 * to make sure we don't zero IOC's req_sz!
3101 /* Did we get a valid reply? */
3102 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
3103 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3105 * If not been here, done that, save off first WhoInit value
3107 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
3108 ioc->FirstWhoInit = facts->WhoInit;
3111 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
3112 facts->MsgContext = le32_to_cpu(facts->MsgContext);
3113 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
3114 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
3115 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
3116 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
3117 /* CHECKME! IOCStatus, IOCLogInfo */
3119 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
3120 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
3123 * FC f/w version changed between 1.1 and 1.2
3124 * Old: u16{Major(4),Minor(4),SubMinor(8)}
3125 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
3127 if (facts->MsgVersion < MPI_VERSION_01_02) {
3129 * Handle old FC f/w style, convert to new...
3131 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
3132 facts->FWVersion.Word =
3133 ((oldv<<12) & 0xFF000000) |
3134 ((oldv<<8) & 0x000FFF00);
3135 } else
3136 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
3138 facts->ProductID = le16_to_cpu(facts->ProductID);
3140 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
3141 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
3142 ioc->ir_firmware = 1;
3144 facts->CurrentHostMfaHighAddr =
3145 le32_to_cpu(facts->CurrentHostMfaHighAddr);
3146 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
3147 facts->CurrentSenseBufferHighAddr =
3148 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
3149 facts->CurReplyFrameSize =
3150 le16_to_cpu(facts->CurReplyFrameSize);
3151 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
3154 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
3155 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
3156 * to 14 in MPI-1.01.0x.
3158 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
3159 facts->MsgVersion > MPI_VERSION_01_00) {
3160 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
3163 facts->FWImageSize = ALIGN(facts->FWImageSize, 4);
3165 if (!facts->RequestFrameSize) {
3166 /* Something is wrong! */
3167 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
3168 ioc->name);
3169 return -55;
3172 r = sz = facts->BlockSize;
3173 vv = ((63 / (sz * 4)) + 1) & 0x03;
3174 ioc->NB_for_64_byte_frame = vv;
3175 while ( sz )
3177 shiftFactor++;
3178 sz = sz >> 1;
3180 ioc->NBShiftFactor = shiftFactor;
3181 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3182 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
3183 ioc->name, vv, shiftFactor, r));
3185 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3187 * Set values for this IOC's request & reply frame sizes,
3188 * and request & reply queue depths...
3190 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
3191 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
3192 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
3193 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
3195 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
3196 ioc->name, ioc->reply_sz, ioc->reply_depth));
3197 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
3198 ioc->name, ioc->req_sz, ioc->req_depth));
3200 /* Get port facts! */
3201 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
3202 return r;
3204 } else {
3205 printk(MYIOC_s_ERR_FMT
3206 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
3207 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
3208 RequestFrameSize)/sizeof(u32)));
3209 return -66;
3212 return 0;
3215 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3217 * GetPortFacts - Send PortFacts request to MPT adapter.
3218 * @ioc: Pointer to MPT_ADAPTER structure
3219 * @portnum: Port number
3220 * @sleepFlag: Specifies whether the process can sleep
3222 * Returns 0 for success, non-zero for failure.
3224 static int
3225 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3227 PortFacts_t get_pfacts;
3228 PortFactsReply_t *pfacts;
3229 int ii;
3230 int req_sz;
3231 int reply_sz;
3232 int max_id;
3234 /* IOC *must* NOT be in RESET state! */
3235 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3236 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3237 ioc->name, ioc->last_state );
3238 return -4;
3241 pfacts = &ioc->pfacts[portnum];
3243 /* Destination (reply area)... */
3244 reply_sz = sizeof(*pfacts);
3245 memset(pfacts, 0, reply_sz);
3247 /* Request area (get_pfacts on the stack right now!) */
3248 req_sz = sizeof(get_pfacts);
3249 memset(&get_pfacts, 0, req_sz);
3251 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3252 get_pfacts.PortNumber = portnum;
3253 /* Assert: All other get_pfacts fields are zero! */
3255 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3256 ioc->name, portnum));
3258 /* No non-zero fields in the get_pfacts request are greater than
3259 * 1 byte in size, so we can just fire it off as is.
3261 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3262 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3263 if (ii != 0)
3264 return ii;
3266 /* Did we get a valid reply? */
3268 /* Now byte swap the necessary fields in the response. */
3269 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3270 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3271 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3272 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3273 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3274 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3275 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3276 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3277 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3279 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3280 pfacts->MaxDevices;
3281 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3282 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3285 * Place all the devices on channels
3287 * (for debuging)
3289 if (mpt_channel_mapping) {
3290 ioc->devices_per_bus = 1;
3291 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3294 return 0;
3297 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3299 * SendIocInit - Send IOCInit request to MPT adapter.
3300 * @ioc: Pointer to MPT_ADAPTER structure
3301 * @sleepFlag: Specifies whether the process can sleep
3303 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3305 * Returns 0 for success, non-zero for failure.
3307 static int
3308 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3310 IOCInit_t ioc_init;
3311 MPIDefaultReply_t init_reply;
3312 u32 state;
3313 int r;
3314 int count;
3315 int cntdn;
3317 memset(&ioc_init, 0, sizeof(ioc_init));
3318 memset(&init_reply, 0, sizeof(init_reply));
3320 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3321 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3323 /* If we are in a recovery mode and we uploaded the FW image,
3324 * then this pointer is not NULL. Skip the upload a second time.
3325 * Set this flag if cached_fw set for either IOC.
3327 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3328 ioc->upload_fw = 1;
3329 else
3330 ioc->upload_fw = 0;
3331 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3332 ioc->name, ioc->upload_fw, ioc->facts.Flags));
3334 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3335 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3337 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3338 ioc->name, ioc->facts.MsgVersion));
3339 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3340 // set MsgVersion and HeaderVersion host driver was built with
3341 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3342 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3344 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3345 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3346 } else if(mpt_host_page_alloc(ioc, &ioc_init))
3347 return -99;
3349 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3351 if (ioc->sg_addr_size == sizeof(u64)) {
3352 /* Save the upper 32-bits of the request
3353 * (reply) and sense buffers.
3355 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3356 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3357 } else {
3358 /* Force 32-bit addressing */
3359 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3360 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3363 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3364 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3365 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3366 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3368 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3369 ioc->name, &ioc_init));
3371 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3372 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3373 if (r != 0) {
3374 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3375 return r;
3378 /* No need to byte swap the multibyte fields in the reply
3379 * since we don't even look at its contents.
3382 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3383 ioc->name, &ioc_init));
3385 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3386 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3387 return r;
3390 /* YIKES! SUPER IMPORTANT!!!
3391 * Poll IocState until _OPERATIONAL while IOC is doing
3392 * LoopInit and TargetDiscovery!
3394 count = 0;
3395 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3396 state = mpt_GetIocState(ioc, 1);
3397 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3398 if (sleepFlag == CAN_SLEEP) {
3399 msleep(1);
3400 } else {
3401 mdelay(1);
3404 if (!cntdn) {
3405 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3406 ioc->name, (int)((count+5)/HZ));
3407 return -9;
3410 state = mpt_GetIocState(ioc, 1);
3411 count++;
3413 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3414 ioc->name, count));
3416 ioc->aen_event_read_flag=0;
3417 return r;
3420 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3422 * SendPortEnable - Send PortEnable request to MPT adapter port.
3423 * @ioc: Pointer to MPT_ADAPTER structure
3424 * @portnum: Port number to enable
3425 * @sleepFlag: Specifies whether the process can sleep
3427 * Send PortEnable to bring IOC to OPERATIONAL state.
3429 * Returns 0 for success, non-zero for failure.
3431 static int
3432 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3434 PortEnable_t port_enable;
3435 MPIDefaultReply_t reply_buf;
3436 int rc;
3437 int req_sz;
3438 int reply_sz;
3440 /* Destination... */
3441 reply_sz = sizeof(MPIDefaultReply_t);
3442 memset(&reply_buf, 0, reply_sz);
3444 req_sz = sizeof(PortEnable_t);
3445 memset(&port_enable, 0, req_sz);
3447 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3448 port_enable.PortNumber = portnum;
3449 /* port_enable.ChainOffset = 0; */
3450 /* port_enable.MsgFlags = 0; */
3451 /* port_enable.MsgContext = 0; */
3453 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3454 ioc->name, portnum, &port_enable));
3456 /* RAID FW may take a long time to enable
3458 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3459 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3460 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3461 300 /*seconds*/, sleepFlag);
3462 } else {
3463 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3464 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3465 30 /*seconds*/, sleepFlag);
3467 return rc;
3471 * mpt_alloc_fw_memory - allocate firmware memory
3472 * @ioc: Pointer to MPT_ADAPTER structure
3473 * @size: total FW bytes
3475 * If memory has already been allocated, the same (cached) value
3476 * is returned.
3478 * Return 0 if successful, or non-zero for failure
3481 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3483 int rc;
3485 if (ioc->cached_fw) {
3486 rc = 0; /* use already allocated memory */
3487 goto out;
3489 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3490 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3491 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3492 rc = 0;
3493 goto out;
3495 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3496 if (!ioc->cached_fw) {
3497 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3498 ioc->name);
3499 rc = -1;
3500 } else {
3501 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3502 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3503 ioc->alloc_total += size;
3504 rc = 0;
3506 out:
3507 return rc;
3511 * mpt_free_fw_memory - free firmware memory
3512 * @ioc: Pointer to MPT_ADAPTER structure
3514 * If alt_img is NULL, delete from ioc structure.
3515 * Else, delete a secondary image in same format.
3517 void
3518 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3520 int sz;
3522 if (!ioc->cached_fw)
3523 return;
3525 sz = ioc->facts.FWImageSize;
3526 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3527 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3528 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3529 ioc->alloc_total -= sz;
3530 ioc->cached_fw = NULL;
3533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3535 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3536 * @ioc: Pointer to MPT_ADAPTER structure
3537 * @sleepFlag: Specifies whether the process can sleep
3539 * Returns 0 for success, >0 for handshake failure
3540 * <0 for fw upload failure.
3542 * Remark: If bound IOC and a successful FWUpload was performed
3543 * on the bound IOC, the second image is discarded
3544 * and memory is free'd. Both channels must upload to prevent
3545 * IOC from running in degraded mode.
3547 static int
3548 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3550 u8 reply[sizeof(FWUploadReply_t)];
3551 FWUpload_t *prequest;
3552 FWUploadReply_t *preply;
3553 FWUploadTCSGE_t *ptcsge;
3554 u32 flagsLength;
3555 int ii, sz, reply_sz;
3556 int cmdStatus;
3557 int request_size;
3558 /* If the image size is 0, we are done.
3560 if ((sz = ioc->facts.FWImageSize) == 0)
3561 return 0;
3563 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3564 return -ENOMEM;
3566 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3567 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3569 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3570 kzalloc(ioc->req_sz, GFP_KERNEL);
3571 if (!prequest) {
3572 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3573 "while allocating memory \n", ioc->name));
3574 mpt_free_fw_memory(ioc);
3575 return -ENOMEM;
3578 preply = (FWUploadReply_t *)&reply;
3580 reply_sz = sizeof(reply);
3581 memset(preply, 0, reply_sz);
3583 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3584 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3586 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3587 ptcsge->DetailsLength = 12;
3588 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3589 ptcsge->ImageSize = cpu_to_le32(sz);
3590 ptcsge++;
3592 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3593 ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3594 request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
3595 ioc->SGE_size;
3596 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
3597 " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
3598 ioc->facts.FWImageSize, request_size));
3599 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3601 ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
3602 reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag);
3604 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
3605 "rc=%x \n", ioc->name, ii));
3607 cmdStatus = -EFAULT;
3608 if (ii == 0) {
3609 /* Handshake transfer was complete and successful.
3610 * Check the Reply Frame.
3612 int status;
3613 status = le16_to_cpu(preply->IOCStatus) &
3614 MPI_IOCSTATUS_MASK;
3615 if (status == MPI_IOCSTATUS_SUCCESS &&
3616 ioc->facts.FWImageSize ==
3617 le32_to_cpu(preply->ActualImageSize))
3618 cmdStatus = 0;
3620 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3621 ioc->name, cmdStatus));
3624 if (cmdStatus) {
3625 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
3626 "freeing image \n", ioc->name));
3627 mpt_free_fw_memory(ioc);
3629 kfree(prequest);
3631 return cmdStatus;
3634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3636 * mpt_downloadboot - DownloadBoot code
3637 * @ioc: Pointer to MPT_ADAPTER structure
3638 * @pFwHeader: Pointer to firmware header info
3639 * @sleepFlag: Specifies whether the process can sleep
3641 * FwDownloadBoot requires Programmed IO access.
3643 * Returns 0 for success
3644 * -1 FW Image size is 0
3645 * -2 No valid cached_fw Pointer
3646 * <0 for fw upload failure.
3648 static int
3649 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3651 MpiExtImageHeader_t *pExtImage;
3652 u32 fwSize;
3653 u32 diag0val;
3654 int count;
3655 u32 *ptrFw;
3656 u32 diagRwData;
3657 u32 nextImage;
3658 u32 load_addr;
3659 u32 ioc_state=0;
3661 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3662 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3664 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3665 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3666 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3667 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3668 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3669 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3671 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3673 /* wait 1 msec */
3674 if (sleepFlag == CAN_SLEEP) {
3675 msleep(1);
3676 } else {
3677 mdelay (1);
3680 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3681 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3683 for (count = 0; count < 30; count ++) {
3684 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3685 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3686 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3687 ioc->name, count));
3688 break;
3690 /* wait .1 sec */
3691 if (sleepFlag == CAN_SLEEP) {
3692 msleep (100);
3693 } else {
3694 mdelay (100);
3698 if ( count == 30 ) {
3699 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3700 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3701 ioc->name, diag0val));
3702 return -3;
3705 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3706 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3707 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3708 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3709 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3710 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3712 /* Set the DiagRwEn and Disable ARM bits */
3713 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3715 fwSize = (pFwHeader->ImageSize + 3)/4;
3716 ptrFw = (u32 *) pFwHeader;
3718 /* Write the LoadStartAddress to the DiagRw Address Register
3719 * using Programmed IO
3721 if (ioc->errata_flag_1064)
3722 pci_enable_io_access(ioc->pcidev);
3724 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3725 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3726 ioc->name, pFwHeader->LoadStartAddress));
3728 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3729 ioc->name, fwSize*4, ptrFw));
3730 while (fwSize--) {
3731 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3734 nextImage = pFwHeader->NextImageHeaderOffset;
3735 while (nextImage) {
3736 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3738 load_addr = pExtImage->LoadStartAddress;
3740 fwSize = (pExtImage->ImageSize + 3) >> 2;
3741 ptrFw = (u32 *)pExtImage;
3743 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3744 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3745 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3747 while (fwSize--) {
3748 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3750 nextImage = pExtImage->NextImageHeaderOffset;
3753 /* Write the IopResetVectorRegAddr */
3754 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3755 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3757 /* Write the IopResetVectorValue */
3758 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3759 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3761 /* Clear the internal flash bad bit - autoincrementing register,
3762 * so must do two writes.
3764 if (ioc->bus_type == SPI) {
3766 * 1030 and 1035 H/W errata, workaround to access
3767 * the ClearFlashBadSignatureBit
3769 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3770 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3771 diagRwData |= 0x40000000;
3772 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3773 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3775 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3776 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3777 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3778 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3780 /* wait 1 msec */
3781 if (sleepFlag == CAN_SLEEP) {
3782 msleep (1);
3783 } else {
3784 mdelay (1);
3788 if (ioc->errata_flag_1064)
3789 pci_disable_io_access(ioc->pcidev);
3791 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3792 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3793 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3794 ioc->name, diag0val));
3795 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3796 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3797 ioc->name, diag0val));
3798 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3800 /* Write 0xFF to reset the sequencer */
3801 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3803 if (ioc->bus_type == SAS) {
3804 ioc_state = mpt_GetIocState(ioc, 0);
3805 if ( (GetIocFacts(ioc, sleepFlag,
3806 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3807 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3808 ioc->name, ioc_state));
3809 return -EFAULT;
3813 for (count=0; count<HZ*20; count++) {
3814 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3815 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3816 "downloadboot successful! (count=%d) IocState=%x\n",
3817 ioc->name, count, ioc_state));
3818 if (ioc->bus_type == SAS) {
3819 return 0;
3821 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3822 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3823 "downloadboot: SendIocInit failed\n",
3824 ioc->name));
3825 return -EFAULT;
3827 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3828 "downloadboot: SendIocInit successful\n",
3829 ioc->name));
3830 return 0;
3832 if (sleepFlag == CAN_SLEEP) {
3833 msleep (10);
3834 } else {
3835 mdelay (10);
3838 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3839 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3840 return -EFAULT;
3843 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3845 * KickStart - Perform hard reset of MPT adapter.
3846 * @ioc: Pointer to MPT_ADAPTER structure
3847 * @force: Force hard reset
3848 * @sleepFlag: Specifies whether the process can sleep
3850 * This routine places MPT adapter in diagnostic mode via the
3851 * WriteSequence register, and then performs a hard reset of adapter
3852 * via the Diagnostic register.
3854 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3855 * or NO_SLEEP (interrupt thread, use mdelay)
3856 * force - 1 if doorbell active, board fault state
3857 * board operational, IOC_RECOVERY or
3858 * IOC_BRINGUP and there is an alt_ioc.
3859 * 0 else
3861 * Returns:
3862 * 1 - hard reset, READY
3863 * 0 - no reset due to History bit, READY
3864 * -1 - no reset due to History bit but not READY
3865 * OR reset but failed to come READY
3866 * -2 - no reset, could not enter DIAG mode
3867 * -3 - reset but bad FW bit
3869 static int
3870 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3872 int hard_reset_done = 0;
3873 u32 ioc_state=0;
3874 int cnt,cntdn;
3876 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3877 if (ioc->bus_type == SPI) {
3878 /* Always issue a Msg Unit Reset first. This will clear some
3879 * SCSI bus hang conditions.
3881 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3883 if (sleepFlag == CAN_SLEEP) {
3884 msleep (1000);
3885 } else {
3886 mdelay (1000);
3890 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3891 if (hard_reset_done < 0)
3892 return hard_reset_done;
3894 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3895 ioc->name));
3897 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3898 for (cnt=0; cnt<cntdn; cnt++) {
3899 ioc_state = mpt_GetIocState(ioc, 1);
3900 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3901 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3902 ioc->name, cnt));
3903 return hard_reset_done;
3905 if (sleepFlag == CAN_SLEEP) {
3906 msleep (10);
3907 } else {
3908 mdelay (10);
3912 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3913 ioc->name, mpt_GetIocState(ioc, 0)));
3914 return -1;
3917 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3919 * mpt_diag_reset - Perform hard reset of the adapter.
3920 * @ioc: Pointer to MPT_ADAPTER structure
3921 * @ignore: Set if to honor and clear to ignore
3922 * the reset history bit
3923 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3924 * else set to NO_SLEEP (use mdelay instead)
3926 * This routine places the adapter in diagnostic mode via the
3927 * WriteSequence register and then performs a hard reset of adapter
3928 * via the Diagnostic register. Adapter should be in ready state
3929 * upon successful completion.
3931 * Returns: 1 hard reset successful
3932 * 0 no reset performed because reset history bit set
3933 * -2 enabling diagnostic mode failed
3934 * -3 diagnostic reset failed
3936 static int
3937 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3939 u32 diag0val;
3940 u32 doorbell;
3941 int hard_reset_done = 0;
3942 int count = 0;
3943 u32 diag1val = 0;
3944 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3945 u8 cb_idx;
3947 /* Clear any existing interrupts */
3948 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3950 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3952 if (!ignore)
3953 return 0;
3955 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3956 "address=%p\n", ioc->name, __func__,
3957 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3958 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3959 if (sleepFlag == CAN_SLEEP)
3960 msleep(1);
3961 else
3962 mdelay(1);
3965 * Call each currently registered protocol IOC reset handler
3966 * with pre-reset indication.
3967 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3968 * MptResetHandlers[] registered yet.
3970 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3971 if (MptResetHandlers[cb_idx])
3972 (*(MptResetHandlers[cb_idx]))(ioc,
3973 MPT_IOC_PRE_RESET);
3976 for (count = 0; count < 60; count ++) {
3977 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3978 doorbell &= MPI_IOC_STATE_MASK;
3980 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3981 "looking for READY STATE: doorbell=%x"
3982 " count=%d\n",
3983 ioc->name, doorbell, count));
3985 if (doorbell == MPI_IOC_STATE_READY) {
3986 return 1;
3989 /* wait 1 sec */
3990 if (sleepFlag == CAN_SLEEP)
3991 msleep(1000);
3992 else
3993 mdelay(1000);
3995 return -1;
3998 /* Use "Diagnostic reset" method! (only thing available!) */
3999 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4001 if (ioc->debug_level & MPT_DEBUG) {
4002 if (ioc->alt_ioc)
4003 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4004 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
4005 ioc->name, diag0val, diag1val));
4008 /* Do the reset if we are told to ignore the reset history
4009 * or if the reset history is 0
4011 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
4012 while ((diag0val & MPI_DIAG_DRWE) == 0) {
4013 /* Write magic sequence to WriteSequence register
4014 * Loop until in diagnostic mode
4016 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4017 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4018 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4019 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4020 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4021 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4023 /* wait 100 msec */
4024 if (sleepFlag == CAN_SLEEP) {
4025 msleep (100);
4026 } else {
4027 mdelay (100);
4030 count++;
4031 if (count > 20) {
4032 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4033 ioc->name, diag0val);
4034 return -2;
4038 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4040 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
4041 ioc->name, diag0val));
4044 if (ioc->debug_level & MPT_DEBUG) {
4045 if (ioc->alt_ioc)
4046 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4047 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
4048 ioc->name, diag0val, diag1val));
4051 * Disable the ARM (Bug fix)
4054 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
4055 mdelay(1);
4058 * Now hit the reset bit in the Diagnostic register
4059 * (THE BIG HAMMER!) (Clears DRWE bit).
4061 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
4062 hard_reset_done = 1;
4063 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
4064 ioc->name));
4067 * Call each currently registered protocol IOC reset handler
4068 * with pre-reset indication.
4069 * NOTE: If we're doing _IOC_BRINGUP, there can be no
4070 * MptResetHandlers[] registered yet.
4072 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
4073 if (MptResetHandlers[cb_idx]) {
4074 mpt_signal_reset(cb_idx,
4075 ioc, MPT_IOC_PRE_RESET);
4076 if (ioc->alt_ioc) {
4077 mpt_signal_reset(cb_idx,
4078 ioc->alt_ioc, MPT_IOC_PRE_RESET);
4083 if (ioc->cached_fw)
4084 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
4085 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
4086 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
4087 else
4088 cached_fw = NULL;
4089 if (cached_fw) {
4090 /* If the DownloadBoot operation fails, the
4091 * IOC will be left unusable. This is a fatal error
4092 * case. _diag_reset will return < 0
4094 for (count = 0; count < 30; count ++) {
4095 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4096 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
4097 break;
4100 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
4101 ioc->name, diag0val, count));
4102 /* wait 1 sec */
4103 if (sleepFlag == CAN_SLEEP) {
4104 msleep (1000);
4105 } else {
4106 mdelay (1000);
4109 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
4110 printk(MYIOC_s_WARN_FMT
4111 "firmware downloadboot failure (%d)!\n", ioc->name, count);
4114 } else {
4115 /* Wait for FW to reload and for board
4116 * to go to the READY state.
4117 * Maximum wait is 60 seconds.
4118 * If fail, no error will check again
4119 * with calling program.
4121 for (count = 0; count < 60; count ++) {
4122 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
4123 doorbell &= MPI_IOC_STATE_MASK;
4125 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4126 "looking for READY STATE: doorbell=%x"
4127 " count=%d\n", ioc->name, doorbell, count));
4129 if (doorbell == MPI_IOC_STATE_READY) {
4130 break;
4133 /* wait 1 sec */
4134 if (sleepFlag == CAN_SLEEP) {
4135 msleep (1000);
4136 } else {
4137 mdelay (1000);
4141 if (doorbell != MPI_IOC_STATE_READY)
4142 printk(MYIOC_s_ERR_FMT "Failed to come READY "
4143 "after reset! IocState=%x", ioc->name,
4144 doorbell);
4148 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4149 if (ioc->debug_level & MPT_DEBUG) {
4150 if (ioc->alt_ioc)
4151 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4152 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
4153 ioc->name, diag0val, diag1val));
4156 /* Clear RESET_HISTORY bit! Place board in the
4157 * diagnostic mode to update the diag register.
4159 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4160 count = 0;
4161 while ((diag0val & MPI_DIAG_DRWE) == 0) {
4162 /* Write magic sequence to WriteSequence register
4163 * Loop until in diagnostic mode
4165 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4166 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4167 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4168 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4169 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4170 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4172 /* wait 100 msec */
4173 if (sleepFlag == CAN_SLEEP) {
4174 msleep (100);
4175 } else {
4176 mdelay (100);
4179 count++;
4180 if (count > 20) {
4181 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4182 ioc->name, diag0val);
4183 break;
4185 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4187 diag0val &= ~MPI_DIAG_RESET_HISTORY;
4188 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
4189 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4190 if (diag0val & MPI_DIAG_RESET_HISTORY) {
4191 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
4192 ioc->name);
4195 /* Disable Diagnostic Mode
4197 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
4199 /* Check FW reload status flags.
4201 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4202 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
4203 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
4204 ioc->name, diag0val);
4205 return -3;
4208 if (ioc->debug_level & MPT_DEBUG) {
4209 if (ioc->alt_ioc)
4210 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4211 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
4212 ioc->name, diag0val, diag1val));
4216 * Reset flag that says we've enabled event notification
4218 ioc->facts.EventState = 0;
4220 if (ioc->alt_ioc)
4221 ioc->alt_ioc->facts.EventState = 0;
4223 return hard_reset_done;
4226 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4228 * SendIocReset - Send IOCReset request to MPT adapter.
4229 * @ioc: Pointer to MPT_ADAPTER structure
4230 * @reset_type: reset type, expected values are
4231 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
4232 * @sleepFlag: Specifies whether the process can sleep
4234 * Send IOCReset request to the MPT adapter.
4236 * Returns 0 for success, non-zero for failure.
4238 static int
4239 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4241 int r;
4242 u32 state;
4243 int cntdn, count;
4245 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4246 ioc->name, reset_type));
4247 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4248 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4249 return r;
4251 /* FW ACK'd request, wait for READY state
4253 count = 0;
4254 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
4256 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4257 cntdn--;
4258 count++;
4259 if (!cntdn) {
4260 if (sleepFlag != CAN_SLEEP)
4261 count *= 10;
4263 printk(MYIOC_s_ERR_FMT
4264 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
4265 ioc->name, state, (int)((count+5)/HZ));
4266 return -ETIME;
4269 if (sleepFlag == CAN_SLEEP) {
4270 msleep(1);
4271 } else {
4272 mdelay (1); /* 1 msec delay */
4276 /* TODO!
4277 * Cleanup all event stuff for this IOC; re-issue EventNotification
4278 * request if needed.
4280 if (ioc->facts.Function)
4281 ioc->facts.EventState = 0;
4283 return 0;
4286 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4288 * initChainBuffers - Allocate memory for and initialize chain buffers
4289 * @ioc: Pointer to MPT_ADAPTER structure
4291 * Allocates memory for and initializes chain buffers,
4292 * chain buffer control arrays and spinlock.
4294 static int
4295 initChainBuffers(MPT_ADAPTER *ioc)
4297 u8 *mem;
4298 int sz, ii, num_chain;
4299 int scale, num_sge, numSGE;
4301 /* ReqToChain size must equal the req_depth
4302 * index = req_idx
4304 if (ioc->ReqToChain == NULL) {
4305 sz = ioc->req_depth * sizeof(int);
4306 mem = kmalloc(sz, GFP_ATOMIC);
4307 if (mem == NULL)
4308 return -1;
4310 ioc->ReqToChain = (int *) mem;
4311 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
4312 ioc->name, mem, sz));
4313 mem = kmalloc(sz, GFP_ATOMIC);
4314 if (mem == NULL)
4315 return -1;
4317 ioc->RequestNB = (int *) mem;
4318 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
4319 ioc->name, mem, sz));
4321 for (ii = 0; ii < ioc->req_depth; ii++) {
4322 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4325 /* ChainToChain size must equal the total number
4326 * of chain buffers to be allocated.
4327 * index = chain_idx
4329 * Calculate the number of chain buffers needed(plus 1) per I/O
4330 * then multiply the maximum number of simultaneous cmds
4332 * num_sge = num sge in request frame + last chain buffer
4333 * scale = num sge per chain buffer if no chain element
4335 scale = ioc->req_sz / ioc->SGE_size;
4336 if (ioc->sg_addr_size == sizeof(u64))
4337 num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size;
4338 else
4339 num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size;
4341 if (ioc->sg_addr_size == sizeof(u64)) {
4342 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4343 (ioc->req_sz - 60) / ioc->SGE_size;
4344 } else {
4345 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) +
4346 scale + (ioc->req_sz - 64) / ioc->SGE_size;
4348 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4349 ioc->name, num_sge, numSGE));
4351 if (ioc->bus_type == FC) {
4352 if (numSGE > MPT_SCSI_FC_SG_DEPTH)
4353 numSGE = MPT_SCSI_FC_SG_DEPTH;
4354 } else {
4355 if (numSGE > MPT_SCSI_SG_DEPTH)
4356 numSGE = MPT_SCSI_SG_DEPTH;
4359 num_chain = 1;
4360 while (numSGE - num_sge > 0) {
4361 num_chain++;
4362 num_sge += (scale - 1);
4364 num_chain++;
4366 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4367 ioc->name, numSGE, num_sge, num_chain));
4369 if (ioc->bus_type == SPI)
4370 num_chain *= MPT_SCSI_CAN_QUEUE;
4371 else if (ioc->bus_type == SAS)
4372 num_chain *= MPT_SAS_CAN_QUEUE;
4373 else
4374 num_chain *= MPT_FC_CAN_QUEUE;
4376 ioc->num_chain = num_chain;
4378 sz = num_chain * sizeof(int);
4379 if (ioc->ChainToChain == NULL) {
4380 mem = kmalloc(sz, GFP_ATOMIC);
4381 if (mem == NULL)
4382 return -1;
4384 ioc->ChainToChain = (int *) mem;
4385 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4386 ioc->name, mem, sz));
4387 } else {
4388 mem = (u8 *) ioc->ChainToChain;
4390 memset(mem, 0xFF, sz);
4391 return num_chain;
4394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4396 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4397 * @ioc: Pointer to MPT_ADAPTER structure
4399 * This routine allocates memory for the MPT reply and request frame
4400 * pools (if necessary), and primes the IOC reply FIFO with
4401 * reply frames.
4403 * Returns 0 for success, non-zero for failure.
4405 static int
4406 PrimeIocFifos(MPT_ADAPTER *ioc)
4408 MPT_FRAME_HDR *mf;
4409 unsigned long flags;
4410 dma_addr_t alloc_dma;
4411 u8 *mem;
4412 int i, reply_sz, sz, total_size, num_chain;
4413 u64 dma_mask;
4415 dma_mask = 0;
4417 /* Prime reply FIFO... */
4419 if (ioc->reply_frames == NULL) {
4420 if ( (num_chain = initChainBuffers(ioc)) < 0)
4421 return -1;
4423 * 1078 errata workaround for the 36GB limitation
4425 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
4426 ioc->dma_mask > DMA_BIT_MASK(35)) {
4427 if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32))
4428 && !pci_set_consistent_dma_mask(ioc->pcidev,
4429 DMA_BIT_MASK(32))) {
4430 dma_mask = DMA_BIT_MASK(35);
4431 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4432 "setting 35 bit addressing for "
4433 "Request/Reply/Chain and Sense Buffers\n",
4434 ioc->name));
4435 } else {
4436 /*Reseting DMA mask to 64 bit*/
4437 pci_set_dma_mask(ioc->pcidev,
4438 DMA_BIT_MASK(64));
4439 pci_set_consistent_dma_mask(ioc->pcidev,
4440 DMA_BIT_MASK(64));
4442 printk(MYIOC_s_ERR_FMT
4443 "failed setting 35 bit addressing for "
4444 "Request/Reply/Chain and Sense Buffers\n",
4445 ioc->name);
4446 return -1;
4450 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4451 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4452 ioc->name, ioc->reply_sz, ioc->reply_depth));
4453 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4454 ioc->name, reply_sz, reply_sz));
4456 sz = (ioc->req_sz * ioc->req_depth);
4457 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4458 ioc->name, ioc->req_sz, ioc->req_depth));
4459 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4460 ioc->name, sz, sz));
4461 total_size += sz;
4463 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4464 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4465 ioc->name, ioc->req_sz, num_chain));
4466 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4467 ioc->name, sz, sz, num_chain));
4469 total_size += sz;
4470 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4471 if (mem == NULL) {
4472 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4473 ioc->name);
4474 goto out_fail;
4477 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4478 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4480 memset(mem, 0, total_size);
4481 ioc->alloc_total += total_size;
4482 ioc->alloc = mem;
4483 ioc->alloc_dma = alloc_dma;
4484 ioc->alloc_sz = total_size;
4485 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4486 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4488 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4489 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4491 alloc_dma += reply_sz;
4492 mem += reply_sz;
4494 /* Request FIFO - WE manage this! */
4496 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4497 ioc->req_frames_dma = alloc_dma;
4499 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4500 ioc->name, mem, (void *)(ulong)alloc_dma));
4502 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4504 for (i = 0; i < ioc->req_depth; i++) {
4505 alloc_dma += ioc->req_sz;
4506 mem += ioc->req_sz;
4509 ioc->ChainBuffer = mem;
4510 ioc->ChainBufferDMA = alloc_dma;
4512 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4513 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4515 /* Initialize the free chain Q.
4518 INIT_LIST_HEAD(&ioc->FreeChainQ);
4520 /* Post the chain buffers to the FreeChainQ.
4522 mem = (u8 *)ioc->ChainBuffer;
4523 for (i=0; i < num_chain; i++) {
4524 mf = (MPT_FRAME_HDR *) mem;
4525 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4526 mem += ioc->req_sz;
4529 /* Initialize Request frames linked list
4531 alloc_dma = ioc->req_frames_dma;
4532 mem = (u8 *) ioc->req_frames;
4534 spin_lock_irqsave(&ioc->FreeQlock, flags);
4535 INIT_LIST_HEAD(&ioc->FreeQ);
4536 for (i = 0; i < ioc->req_depth; i++) {
4537 mf = (MPT_FRAME_HDR *) mem;
4539 /* Queue REQUESTs *internally*! */
4540 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4542 mem += ioc->req_sz;
4544 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4546 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4547 ioc->sense_buf_pool =
4548 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4549 if (ioc->sense_buf_pool == NULL) {
4550 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4551 ioc->name);
4552 goto out_fail;
4555 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4556 ioc->alloc_total += sz;
4557 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4558 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4562 /* Post Reply frames to FIFO
4564 alloc_dma = ioc->alloc_dma;
4565 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4566 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4568 for (i = 0; i < ioc->reply_depth; i++) {
4569 /* Write each address to the IOC! */
4570 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4571 alloc_dma += ioc->reply_sz;
4574 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4575 ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
4576 ioc->dma_mask))
4577 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4578 "restoring 64 bit addressing\n", ioc->name));
4580 return 0;
4582 out_fail:
4584 if (ioc->alloc != NULL) {
4585 sz = ioc->alloc_sz;
4586 pci_free_consistent(ioc->pcidev,
4588 ioc->alloc, ioc->alloc_dma);
4589 ioc->reply_frames = NULL;
4590 ioc->req_frames = NULL;
4591 ioc->alloc_total -= sz;
4593 if (ioc->sense_buf_pool != NULL) {
4594 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4595 pci_free_consistent(ioc->pcidev,
4597 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4598 ioc->sense_buf_pool = NULL;
4601 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4602 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev,
4603 DMA_BIT_MASK(64)))
4604 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4605 "restoring 64 bit addressing\n", ioc->name));
4607 return -1;
4610 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4612 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4613 * from IOC via doorbell handshake method.
4614 * @ioc: Pointer to MPT_ADAPTER structure
4615 * @reqBytes: Size of the request in bytes
4616 * @req: Pointer to MPT request frame
4617 * @replyBytes: Expected size of the reply in bytes
4618 * @u16reply: Pointer to area where reply should be written
4619 * @maxwait: Max wait time for a reply (in seconds)
4620 * @sleepFlag: Specifies whether the process can sleep
4622 * NOTES: It is the callers responsibility to byte-swap fields in the
4623 * request which are greater than 1 byte in size. It is also the
4624 * callers responsibility to byte-swap response fields which are
4625 * greater than 1 byte in size.
4627 * Returns 0 for success, non-zero for failure.
4629 static int
4630 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4631 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4633 MPIDefaultReply_t *mptReply;
4634 int failcnt = 0;
4635 int t;
4638 * Get ready to cache a handshake reply
4640 ioc->hs_reply_idx = 0;
4641 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4642 mptReply->MsgLength = 0;
4645 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4646 * then tell IOC that we want to handshake a request of N words.
4647 * (WRITE u32val to Doorbell reg).
4649 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4650 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4651 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4652 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4655 * Wait for IOC's doorbell handshake int
4657 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4658 failcnt++;
4660 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4661 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4663 /* Read doorbell and check for active bit */
4664 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4665 return -1;
4668 * Clear doorbell int (WRITE 0 to IntStatus reg),
4669 * then wait for IOC to ACKnowledge that it's ready for
4670 * our handshake request.
4672 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4673 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4674 failcnt++;
4676 if (!failcnt) {
4677 int ii;
4678 u8 *req_as_bytes = (u8 *) req;
4681 * Stuff request words via doorbell handshake,
4682 * with ACK from IOC for each.
4684 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4685 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4686 (req_as_bytes[(ii*4) + 1] << 8) |
4687 (req_as_bytes[(ii*4) + 2] << 16) |
4688 (req_as_bytes[(ii*4) + 3] << 24));
4690 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4691 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4692 failcnt++;
4695 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4696 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4698 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4699 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4702 * Wait for completion of doorbell handshake reply from the IOC
4704 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4705 failcnt++;
4707 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4708 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4711 * Copy out the cached reply...
4713 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4714 u16reply[ii] = ioc->hs_reply[ii];
4715 } else {
4716 return -99;
4719 return -failcnt;
4722 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4724 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4725 * @ioc: Pointer to MPT_ADAPTER structure
4726 * @howlong: How long to wait (in seconds)
4727 * @sleepFlag: Specifies whether the process can sleep
4729 * This routine waits (up to ~2 seconds max) for IOC doorbell
4730 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4731 * bit in its IntStatus register being clear.
4733 * Returns a negative value on failure, else wait loop count.
4735 static int
4736 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4738 int cntdn;
4739 int count = 0;
4740 u32 intstat=0;
4742 cntdn = 1000 * howlong;
4744 if (sleepFlag == CAN_SLEEP) {
4745 while (--cntdn) {
4746 msleep (1);
4747 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4748 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4749 break;
4750 count++;
4752 } else {
4753 while (--cntdn) {
4754 udelay (1000);
4755 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4756 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4757 break;
4758 count++;
4762 if (cntdn) {
4763 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4764 ioc->name, count));
4765 return count;
4768 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4769 ioc->name, count, intstat);
4770 return -1;
4773 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4775 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4776 * @ioc: Pointer to MPT_ADAPTER structure
4777 * @howlong: How long to wait (in seconds)
4778 * @sleepFlag: Specifies whether the process can sleep
4780 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4781 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4783 * Returns a negative value on failure, else wait loop count.
4785 static int
4786 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4788 int cntdn;
4789 int count = 0;
4790 u32 intstat=0;
4792 cntdn = 1000 * howlong;
4793 if (sleepFlag == CAN_SLEEP) {
4794 while (--cntdn) {
4795 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4796 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4797 break;
4798 msleep(1);
4799 count++;
4801 } else {
4802 while (--cntdn) {
4803 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4804 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4805 break;
4806 udelay (1000);
4807 count++;
4811 if (cntdn) {
4812 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4813 ioc->name, count, howlong));
4814 return count;
4817 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4818 ioc->name, count, intstat);
4819 return -1;
4822 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4824 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4825 * @ioc: Pointer to MPT_ADAPTER structure
4826 * @howlong: How long to wait (in seconds)
4827 * @sleepFlag: Specifies whether the process can sleep
4829 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4830 * Reply is cached to IOC private area large enough to hold a maximum
4831 * of 128 bytes of reply data.
4833 * Returns a negative value on failure, else size of reply in WORDS.
4835 static int
4836 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4838 int u16cnt = 0;
4839 int failcnt = 0;
4840 int t;
4841 u16 *hs_reply = ioc->hs_reply;
4842 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4843 u16 hword;
4845 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4848 * Get first two u16's so we can look at IOC's intended reply MsgLength
4850 u16cnt=0;
4851 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4852 failcnt++;
4853 } else {
4854 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4855 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4856 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4857 failcnt++;
4858 else {
4859 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4860 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4864 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4865 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4866 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4869 * If no error (and IOC said MsgLength is > 0), piece together
4870 * reply 16 bits at a time.
4872 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4873 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4874 failcnt++;
4875 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4876 /* don't overflow our IOC hs_reply[] buffer! */
4877 if (u16cnt < ARRAY_SIZE(ioc->hs_reply))
4878 hs_reply[u16cnt] = hword;
4879 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4882 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4883 failcnt++;
4884 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4886 if (failcnt) {
4887 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4888 ioc->name);
4889 return -failcnt;
4891 #if 0
4892 else if (u16cnt != (2 * mptReply->MsgLength)) {
4893 return -101;
4895 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4896 return -102;
4898 #endif
4900 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4901 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4903 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4904 ioc->name, t, u16cnt/2));
4905 return u16cnt/2;
4908 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4910 * GetLanConfigPages - Fetch LANConfig pages.
4911 * @ioc: Pointer to MPT_ADAPTER structure
4913 * Return: 0 for success
4914 * -ENOMEM if no memory available
4915 * -EPERM if not allowed due to ISR context
4916 * -EAGAIN if no msg frames currently available
4917 * -EFAULT for non-successful reply or no reply (timeout)
4919 static int
4920 GetLanConfigPages(MPT_ADAPTER *ioc)
4922 ConfigPageHeader_t hdr;
4923 CONFIGPARMS cfg;
4924 LANPage0_t *ppage0_alloc;
4925 dma_addr_t page0_dma;
4926 LANPage1_t *ppage1_alloc;
4927 dma_addr_t page1_dma;
4928 int rc = 0;
4929 int data_sz;
4930 int copy_sz;
4932 /* Get LAN Page 0 header */
4933 hdr.PageVersion = 0;
4934 hdr.PageLength = 0;
4935 hdr.PageNumber = 0;
4936 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4937 cfg.cfghdr.hdr = &hdr;
4938 cfg.physAddr = -1;
4939 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4940 cfg.dir = 0;
4941 cfg.pageAddr = 0;
4942 cfg.timeout = 0;
4944 if ((rc = mpt_config(ioc, &cfg)) != 0)
4945 return rc;
4947 if (hdr.PageLength > 0) {
4948 data_sz = hdr.PageLength * 4;
4949 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4950 rc = -ENOMEM;
4951 if (ppage0_alloc) {
4952 memset((u8 *)ppage0_alloc, 0, data_sz);
4953 cfg.physAddr = page0_dma;
4954 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4956 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4957 /* save the data */
4958 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4959 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4963 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4965 /* FIXME!
4966 * Normalize endianness of structure data,
4967 * by byte-swapping all > 1 byte fields!
4972 if (rc)
4973 return rc;
4976 /* Get LAN Page 1 header */
4977 hdr.PageVersion = 0;
4978 hdr.PageLength = 0;
4979 hdr.PageNumber = 1;
4980 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4981 cfg.cfghdr.hdr = &hdr;
4982 cfg.physAddr = -1;
4983 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4984 cfg.dir = 0;
4985 cfg.pageAddr = 0;
4987 if ((rc = mpt_config(ioc, &cfg)) != 0)
4988 return rc;
4990 if (hdr.PageLength == 0)
4991 return 0;
4993 data_sz = hdr.PageLength * 4;
4994 rc = -ENOMEM;
4995 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4996 if (ppage1_alloc) {
4997 memset((u8 *)ppage1_alloc, 0, data_sz);
4998 cfg.physAddr = page1_dma;
4999 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5001 if ((rc = mpt_config(ioc, &cfg)) == 0) {
5002 /* save the data */
5003 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
5004 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
5007 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
5009 /* FIXME!
5010 * Normalize endianness of structure data,
5011 * by byte-swapping all > 1 byte fields!
5016 return rc;
5019 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5021 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
5022 * @ioc: Pointer to MPT_ADAPTER structure
5023 * @persist_opcode: see below
5025 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
5026 * devices not currently present.
5027 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
5029 * NOTE: Don't use not this function during interrupt time.
5031 * Returns 0 for success, non-zero error
5034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5036 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
5038 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
5039 SasIoUnitControlReply_t *sasIoUnitCntrReply;
5040 MPT_FRAME_HDR *mf = NULL;
5041 MPIHeader_t *mpi_hdr;
5042 int ret = 0;
5043 unsigned long timeleft;
5045 mutex_lock(&ioc->mptbase_cmds.mutex);
5047 /* init the internal cmd struct */
5048 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
5049 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
5051 /* insure garbage is not sent to fw */
5052 switch(persist_opcode) {
5054 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
5055 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
5056 break;
5058 default:
5059 ret = -1;
5060 goto out;
5063 printk(KERN_DEBUG "%s: persist_opcode=%x\n",
5064 __func__, persist_opcode);
5066 /* Get a MF for this command.
5068 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5069 printk(KERN_DEBUG "%s: no msg frames!\n", __func__);
5070 ret = -1;
5071 goto out;
5074 mpi_hdr = (MPIHeader_t *) mf;
5075 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
5076 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
5077 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
5078 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
5079 sasIoUnitCntrReq->Operation = persist_opcode;
5081 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5082 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ);
5083 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
5084 ret = -ETIME;
5085 printk(KERN_DEBUG "%s: failed\n", __func__);
5086 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
5087 goto out;
5088 if (!timeleft) {
5089 printk(MYIOC_s_WARN_FMT
5090 "Issuing Reset from %s!!, doorbell=0x%08x\n",
5091 ioc->name, __func__, mpt_GetIocState(ioc, 0));
5092 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
5093 mpt_free_msg_frame(ioc, mf);
5095 goto out;
5098 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
5099 ret = -1;
5100 goto out;
5103 sasIoUnitCntrReply =
5104 (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply;
5105 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
5106 printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
5107 __func__, sasIoUnitCntrReply->IOCStatus,
5108 sasIoUnitCntrReply->IOCLogInfo);
5109 printk(KERN_DEBUG "%s: failed\n", __func__);
5110 ret = -1;
5111 } else
5112 printk(KERN_DEBUG "%s: success\n", __func__);
5113 out:
5115 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
5116 mutex_unlock(&ioc->mptbase_cmds.mutex);
5117 return ret;
5120 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5122 static void
5123 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
5124 MpiEventDataRaid_t * pRaidEventData)
5126 int volume;
5127 int reason;
5128 int disk;
5129 int status;
5130 int flags;
5131 int state;
5133 volume = pRaidEventData->VolumeID;
5134 reason = pRaidEventData->ReasonCode;
5135 disk = pRaidEventData->PhysDiskNum;
5136 status = le32_to_cpu(pRaidEventData->SettingsStatus);
5137 flags = (status >> 0) & 0xff;
5138 state = (status >> 8) & 0xff;
5140 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
5141 return;
5144 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
5145 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
5146 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
5147 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
5148 ioc->name, disk, volume);
5149 } else {
5150 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
5151 ioc->name, volume);
5154 switch(reason) {
5155 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
5156 printk(MYIOC_s_INFO_FMT " volume has been created\n",
5157 ioc->name);
5158 break;
5160 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
5162 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
5163 ioc->name);
5164 break;
5166 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
5167 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
5168 ioc->name);
5169 break;
5171 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
5172 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
5173 ioc->name,
5174 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
5175 ? "optimal"
5176 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
5177 ? "degraded"
5178 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
5179 ? "failed"
5180 : "state unknown",
5181 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
5182 ? ", enabled" : "",
5183 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
5184 ? ", quiesced" : "",
5185 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
5186 ? ", resync in progress" : "" );
5187 break;
5189 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
5190 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
5191 ioc->name, disk);
5192 break;
5194 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
5195 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
5196 ioc->name);
5197 break;
5199 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
5200 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
5201 ioc->name);
5202 break;
5204 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
5205 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
5206 ioc->name);
5207 break;
5209 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
5210 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
5211 ioc->name,
5212 state == MPI_PHYSDISK0_STATUS_ONLINE
5213 ? "online"
5214 : state == MPI_PHYSDISK0_STATUS_MISSING
5215 ? "missing"
5216 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
5217 ? "not compatible"
5218 : state == MPI_PHYSDISK0_STATUS_FAILED
5219 ? "failed"
5220 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
5221 ? "initializing"
5222 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
5223 ? "offline requested"
5224 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
5225 ? "failed requested"
5226 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
5227 ? "offline"
5228 : "state unknown",
5229 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
5230 ? ", out of sync" : "",
5231 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
5232 ? ", quiesced" : "" );
5233 break;
5235 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
5236 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
5237 ioc->name, disk);
5238 break;
5240 case MPI_EVENT_RAID_RC_SMART_DATA:
5241 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
5242 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
5243 break;
5245 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
5246 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
5247 ioc->name, disk);
5248 break;
5252 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5254 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
5255 * @ioc: Pointer to MPT_ADAPTER structure
5257 * Returns: 0 for success
5258 * -ENOMEM if no memory available
5259 * -EPERM if not allowed due to ISR context
5260 * -EAGAIN if no msg frames currently available
5261 * -EFAULT for non-successful reply or no reply (timeout)
5263 static int
5264 GetIoUnitPage2(MPT_ADAPTER *ioc)
5266 ConfigPageHeader_t hdr;
5267 CONFIGPARMS cfg;
5268 IOUnitPage2_t *ppage_alloc;
5269 dma_addr_t page_dma;
5270 int data_sz;
5271 int rc;
5273 /* Get the page header */
5274 hdr.PageVersion = 0;
5275 hdr.PageLength = 0;
5276 hdr.PageNumber = 2;
5277 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
5278 cfg.cfghdr.hdr = &hdr;
5279 cfg.physAddr = -1;
5280 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5281 cfg.dir = 0;
5282 cfg.pageAddr = 0;
5283 cfg.timeout = 0;
5285 if ((rc = mpt_config(ioc, &cfg)) != 0)
5286 return rc;
5288 if (hdr.PageLength == 0)
5289 return 0;
5291 /* Read the config page */
5292 data_sz = hdr.PageLength * 4;
5293 rc = -ENOMEM;
5294 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
5295 if (ppage_alloc) {
5296 memset((u8 *)ppage_alloc, 0, data_sz);
5297 cfg.physAddr = page_dma;
5298 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5300 /* If Good, save data */
5301 if ((rc = mpt_config(ioc, &cfg)) == 0)
5302 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
5304 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
5307 return rc;
5310 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5312 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5313 * @ioc: Pointer to a Adapter Strucutre
5314 * @portnum: IOC port number
5316 * Return: -EFAULT if read of config page header fails
5317 * or if no nvram
5318 * If read of SCSI Port Page 0 fails,
5319 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5320 * Adapter settings: async, narrow
5321 * Return 1
5322 * If read of SCSI Port Page 2 fails,
5323 * Adapter settings valid
5324 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5325 * Return 1
5326 * Else
5327 * Both valid
5328 * Return 0
5329 * CHECK - what type of locking mechanisms should be used????
5331 static int
5332 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
5334 u8 *pbuf;
5335 dma_addr_t buf_dma;
5336 CONFIGPARMS cfg;
5337 ConfigPageHeader_t header;
5338 int ii;
5339 int data, rc = 0;
5341 /* Allocate memory
5343 if (!ioc->spi_data.nvram) {
5344 int sz;
5345 u8 *mem;
5346 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5347 mem = kmalloc(sz, GFP_ATOMIC);
5348 if (mem == NULL)
5349 return -EFAULT;
5351 ioc->spi_data.nvram = (int *) mem;
5353 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5354 ioc->name, ioc->spi_data.nvram, sz));
5357 /* Invalidate NVRAM information
5359 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5360 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5363 /* Read SPP0 header, allocate memory, then read page.
5365 header.PageVersion = 0;
5366 header.PageLength = 0;
5367 header.PageNumber = 0;
5368 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5369 cfg.cfghdr.hdr = &header;
5370 cfg.physAddr = -1;
5371 cfg.pageAddr = portnum;
5372 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5373 cfg.dir = 0;
5374 cfg.timeout = 0; /* use default */
5375 if (mpt_config(ioc, &cfg) != 0)
5376 return -EFAULT;
5378 if (header.PageLength > 0) {
5379 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5380 if (pbuf) {
5381 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5382 cfg.physAddr = buf_dma;
5383 if (mpt_config(ioc, &cfg) != 0) {
5384 ioc->spi_data.maxBusWidth = MPT_NARROW;
5385 ioc->spi_data.maxSyncOffset = 0;
5386 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5387 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5388 rc = 1;
5389 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5390 "Unable to read PortPage0 minSyncFactor=%x\n",
5391 ioc->name, ioc->spi_data.minSyncFactor));
5392 } else {
5393 /* Save the Port Page 0 data
5395 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
5396 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5397 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5399 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5400 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5401 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5402 "noQas due to Capabilities=%x\n",
5403 ioc->name, pPP0->Capabilities));
5405 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5406 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5407 if (data) {
5408 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5409 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5410 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5411 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5412 "PortPage0 minSyncFactor=%x\n",
5413 ioc->name, ioc->spi_data.minSyncFactor));
5414 } else {
5415 ioc->spi_data.maxSyncOffset = 0;
5416 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5419 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5421 /* Update the minSyncFactor based on bus type.
5423 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5424 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
5426 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5427 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5428 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5429 "HVD or SE detected, minSyncFactor=%x\n",
5430 ioc->name, ioc->spi_data.minSyncFactor));
5434 if (pbuf) {
5435 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5440 /* SCSI Port Page 2 - Read the header then the page.
5442 header.PageVersion = 0;
5443 header.PageLength = 0;
5444 header.PageNumber = 2;
5445 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5446 cfg.cfghdr.hdr = &header;
5447 cfg.physAddr = -1;
5448 cfg.pageAddr = portnum;
5449 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5450 cfg.dir = 0;
5451 if (mpt_config(ioc, &cfg) != 0)
5452 return -EFAULT;
5454 if (header.PageLength > 0) {
5455 /* Allocate memory and read SCSI Port Page 2
5457 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5458 if (pbuf) {
5459 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5460 cfg.physAddr = buf_dma;
5461 if (mpt_config(ioc, &cfg) != 0) {
5462 /* Nvram data is left with INVALID mark
5464 rc = 1;
5465 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5467 /* This is an ATTO adapter, read Page2 accordingly
5469 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5470 ATTODeviceInfo_t *pdevice = NULL;
5471 u16 ATTOFlags;
5473 /* Save the Port Page 2 data
5474 * (reformat into a 32bit quantity)
5476 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5477 pdevice = &pPP2->DeviceSettings[ii];
5478 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5479 data = 0;
5481 /* Translate ATTO device flags to LSI format
5483 if (ATTOFlags & ATTOFLAG_DISC)
5484 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5485 if (ATTOFlags & ATTOFLAG_ID_ENB)
5486 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5487 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5488 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5489 if (ATTOFlags & ATTOFLAG_TAGGED)
5490 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5491 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5492 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5494 data = (data << 16) | (pdevice->Period << 8) | 10;
5495 ioc->spi_data.nvram[ii] = data;
5497 } else {
5498 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5499 MpiDeviceInfo_t *pdevice = NULL;
5502 * Save "Set to Avoid SCSI Bus Resets" flag
5504 ioc->spi_data.bus_reset =
5505 (le32_to_cpu(pPP2->PortFlags) &
5506 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5507 0 : 1 ;
5509 /* Save the Port Page 2 data
5510 * (reformat into a 32bit quantity)
5512 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5513 ioc->spi_data.PortFlags = data;
5514 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5515 pdevice = &pPP2->DeviceSettings[ii];
5516 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5517 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5518 ioc->spi_data.nvram[ii] = data;
5522 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5526 /* Update Adapter limits with those from NVRAM
5527 * Comment: Don't need to do this. Target performance
5528 * parameters will never exceed the adapters limits.
5531 return rc;
5534 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5536 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5537 * @ioc: Pointer to a Adapter Strucutre
5538 * @portnum: IOC port number
5540 * Return: -EFAULT if read of config page header fails
5541 * or 0 if success.
5543 static int
5544 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5546 CONFIGPARMS cfg;
5547 ConfigPageHeader_t header;
5549 /* Read the SCSI Device Page 1 header
5551 header.PageVersion = 0;
5552 header.PageLength = 0;
5553 header.PageNumber = 1;
5554 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5555 cfg.cfghdr.hdr = &header;
5556 cfg.physAddr = -1;
5557 cfg.pageAddr = portnum;
5558 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5559 cfg.dir = 0;
5560 cfg.timeout = 0;
5561 if (mpt_config(ioc, &cfg) != 0)
5562 return -EFAULT;
5564 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5565 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5567 header.PageVersion = 0;
5568 header.PageLength = 0;
5569 header.PageNumber = 0;
5570 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5571 if (mpt_config(ioc, &cfg) != 0)
5572 return -EFAULT;
5574 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5575 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5577 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5578 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5580 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5581 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5582 return 0;
5586 * mpt_inactive_raid_list_free - This clears this link list.
5587 * @ioc : pointer to per adapter structure
5589 static void
5590 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5592 struct inactive_raid_component_info *component_info, *pNext;
5594 if (list_empty(&ioc->raid_data.inactive_list))
5595 return;
5597 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5598 list_for_each_entry_safe(component_info, pNext,
5599 &ioc->raid_data.inactive_list, list) {
5600 list_del(&component_info->list);
5601 kfree(component_info);
5603 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5607 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5609 * @ioc : pointer to per adapter structure
5610 * @channel : volume channel
5611 * @id : volume target id
5613 static void
5614 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5616 CONFIGPARMS cfg;
5617 ConfigPageHeader_t hdr;
5618 dma_addr_t dma_handle;
5619 pRaidVolumePage0_t buffer = NULL;
5620 int i;
5621 RaidPhysDiskPage0_t phys_disk;
5622 struct inactive_raid_component_info *component_info;
5623 int handle_inactive_volumes;
5625 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5626 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5627 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5628 cfg.pageAddr = (channel << 8) + id;
5629 cfg.cfghdr.hdr = &hdr;
5630 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5632 if (mpt_config(ioc, &cfg) != 0)
5633 goto out;
5635 if (!hdr.PageLength)
5636 goto out;
5638 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5639 &dma_handle);
5641 if (!buffer)
5642 goto out;
5644 cfg.physAddr = dma_handle;
5645 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5647 if (mpt_config(ioc, &cfg) != 0)
5648 goto out;
5650 if (!buffer->NumPhysDisks)
5651 goto out;
5653 handle_inactive_volumes =
5654 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5655 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5656 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5657 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5659 if (!handle_inactive_volumes)
5660 goto out;
5662 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5663 for (i = 0; i < buffer->NumPhysDisks; i++) {
5664 if(mpt_raid_phys_disk_pg0(ioc,
5665 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5666 continue;
5668 if ((component_info = kmalloc(sizeof (*component_info),
5669 GFP_KERNEL)) == NULL)
5670 continue;
5672 component_info->volumeID = id;
5673 component_info->volumeBus = channel;
5674 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5675 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5676 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5677 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5679 list_add_tail(&component_info->list,
5680 &ioc->raid_data.inactive_list);
5682 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5684 out:
5685 if (buffer)
5686 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5687 dma_handle);
5691 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5692 * @ioc: Pointer to a Adapter Structure
5693 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5694 * @phys_disk: requested payload data returned
5696 * Return:
5697 * 0 on success
5698 * -EFAULT if read of config page header fails or data pointer not NULL
5699 * -ENOMEM if pci_alloc failed
5702 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
5703 RaidPhysDiskPage0_t *phys_disk)
5705 CONFIGPARMS cfg;
5706 ConfigPageHeader_t hdr;
5707 dma_addr_t dma_handle;
5708 pRaidPhysDiskPage0_t buffer = NULL;
5709 int rc;
5711 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5712 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5713 memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t));
5715 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION;
5716 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5717 cfg.cfghdr.hdr = &hdr;
5718 cfg.physAddr = -1;
5719 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5721 if (mpt_config(ioc, &cfg) != 0) {
5722 rc = -EFAULT;
5723 goto out;
5726 if (!hdr.PageLength) {
5727 rc = -EFAULT;
5728 goto out;
5731 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5732 &dma_handle);
5734 if (!buffer) {
5735 rc = -ENOMEM;
5736 goto out;
5739 cfg.physAddr = dma_handle;
5740 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5741 cfg.pageAddr = phys_disk_num;
5743 if (mpt_config(ioc, &cfg) != 0) {
5744 rc = -EFAULT;
5745 goto out;
5748 rc = 0;
5749 memcpy(phys_disk, buffer, sizeof(*buffer));
5750 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5752 out:
5754 if (buffer)
5755 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5756 dma_handle);
5758 return rc;
5762 * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
5763 * @ioc: Pointer to a Adapter Structure
5764 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5766 * Return:
5767 * returns number paths
5770 mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
5772 CONFIGPARMS cfg;
5773 ConfigPageHeader_t hdr;
5774 dma_addr_t dma_handle;
5775 pRaidPhysDiskPage1_t buffer = NULL;
5776 int rc;
5778 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5779 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5781 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5782 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5783 hdr.PageNumber = 1;
5784 cfg.cfghdr.hdr = &hdr;
5785 cfg.physAddr = -1;
5786 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5788 if (mpt_config(ioc, &cfg) != 0) {
5789 rc = 0;
5790 goto out;
5793 if (!hdr.PageLength) {
5794 rc = 0;
5795 goto out;
5798 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5799 &dma_handle);
5801 if (!buffer) {
5802 rc = 0;
5803 goto out;
5806 cfg.physAddr = dma_handle;
5807 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5808 cfg.pageAddr = phys_disk_num;
5810 if (mpt_config(ioc, &cfg) != 0) {
5811 rc = 0;
5812 goto out;
5815 rc = buffer->NumPhysDiskPaths;
5816 out:
5818 if (buffer)
5819 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5820 dma_handle);
5822 return rc;
5824 EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
5827 * mpt_raid_phys_disk_pg1 - returns phys disk page 1
5828 * @ioc: Pointer to a Adapter Structure
5829 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5830 * @phys_disk: requested payload data returned
5832 * Return:
5833 * 0 on success
5834 * -EFAULT if read of config page header fails or data pointer not NULL
5835 * -ENOMEM if pci_alloc failed
5838 mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
5839 RaidPhysDiskPage1_t *phys_disk)
5841 CONFIGPARMS cfg;
5842 ConfigPageHeader_t hdr;
5843 dma_addr_t dma_handle;
5844 pRaidPhysDiskPage1_t buffer = NULL;
5845 int rc;
5846 int i;
5847 __le64 sas_address;
5849 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5850 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5851 rc = 0;
5853 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5854 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5855 hdr.PageNumber = 1;
5856 cfg.cfghdr.hdr = &hdr;
5857 cfg.physAddr = -1;
5858 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5860 if (mpt_config(ioc, &cfg) != 0) {
5861 rc = -EFAULT;
5862 goto out;
5865 if (!hdr.PageLength) {
5866 rc = -EFAULT;
5867 goto out;
5870 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5871 &dma_handle);
5873 if (!buffer) {
5874 rc = -ENOMEM;
5875 goto out;
5878 cfg.physAddr = dma_handle;
5879 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5880 cfg.pageAddr = phys_disk_num;
5882 if (mpt_config(ioc, &cfg) != 0) {
5883 rc = -EFAULT;
5884 goto out;
5887 phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
5888 phys_disk->PhysDiskNum = phys_disk_num;
5889 for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
5890 phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
5891 phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
5892 phys_disk->Path[i].OwnerIdentifier =
5893 buffer->Path[i].OwnerIdentifier;
5894 phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
5895 memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
5896 sas_address = le64_to_cpu(sas_address);
5897 memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
5898 memcpy(&sas_address,
5899 &buffer->Path[i].OwnerWWID, sizeof(__le64));
5900 sas_address = le64_to_cpu(sas_address);
5901 memcpy(&phys_disk->Path[i].OwnerWWID,
5902 &sas_address, sizeof(__le64));
5905 out:
5907 if (buffer)
5908 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5909 dma_handle);
5911 return rc;
5913 EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
5917 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5918 * @ioc: Pointer to a Adapter Strucutre
5920 * Return:
5921 * 0 on success
5922 * -EFAULT if read of config page header fails or data pointer not NULL
5923 * -ENOMEM if pci_alloc failed
5926 mpt_findImVolumes(MPT_ADAPTER *ioc)
5928 IOCPage2_t *pIoc2;
5929 u8 *mem;
5930 dma_addr_t ioc2_dma;
5931 CONFIGPARMS cfg;
5932 ConfigPageHeader_t header;
5933 int rc = 0;
5934 int iocpage2sz;
5935 int i;
5937 if (!ioc->ir_firmware)
5938 return 0;
5940 /* Free the old page
5942 kfree(ioc->raid_data.pIocPg2);
5943 ioc->raid_data.pIocPg2 = NULL;
5944 mpt_inactive_raid_list_free(ioc);
5946 /* Read IOCP2 header then the page.
5948 header.PageVersion = 0;
5949 header.PageLength = 0;
5950 header.PageNumber = 2;
5951 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5952 cfg.cfghdr.hdr = &header;
5953 cfg.physAddr = -1;
5954 cfg.pageAddr = 0;
5955 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5956 cfg.dir = 0;
5957 cfg.timeout = 0;
5958 if (mpt_config(ioc, &cfg) != 0)
5959 return -EFAULT;
5961 if (header.PageLength == 0)
5962 return -EFAULT;
5964 iocpage2sz = header.PageLength * 4;
5965 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5966 if (!pIoc2)
5967 return -ENOMEM;
5969 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5970 cfg.physAddr = ioc2_dma;
5971 if (mpt_config(ioc, &cfg) != 0)
5972 goto out;
5974 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5975 if (!mem) {
5976 rc = -ENOMEM;
5977 goto out;
5980 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5981 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5983 mpt_read_ioc_pg_3(ioc);
5985 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5986 mpt_inactive_raid_volumes(ioc,
5987 pIoc2->RaidVolume[i].VolumeBus,
5988 pIoc2->RaidVolume[i].VolumeID);
5990 out:
5991 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5993 return rc;
5996 static int
5997 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5999 IOCPage3_t *pIoc3;
6000 u8 *mem;
6001 CONFIGPARMS cfg;
6002 ConfigPageHeader_t header;
6003 dma_addr_t ioc3_dma;
6004 int iocpage3sz = 0;
6006 /* Free the old page
6008 kfree(ioc->raid_data.pIocPg3);
6009 ioc->raid_data.pIocPg3 = NULL;
6011 /* There is at least one physical disk.
6012 * Read and save IOC Page 3
6014 header.PageVersion = 0;
6015 header.PageLength = 0;
6016 header.PageNumber = 3;
6017 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6018 cfg.cfghdr.hdr = &header;
6019 cfg.physAddr = -1;
6020 cfg.pageAddr = 0;
6021 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6022 cfg.dir = 0;
6023 cfg.timeout = 0;
6024 if (mpt_config(ioc, &cfg) != 0)
6025 return 0;
6027 if (header.PageLength == 0)
6028 return 0;
6030 /* Read Header good, alloc memory
6032 iocpage3sz = header.PageLength * 4;
6033 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
6034 if (!pIoc3)
6035 return 0;
6037 /* Read the Page and save the data
6038 * into malloc'd memory.
6040 cfg.physAddr = ioc3_dma;
6041 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6042 if (mpt_config(ioc, &cfg) == 0) {
6043 mem = kmalloc(iocpage3sz, GFP_KERNEL);
6044 if (mem) {
6045 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
6046 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
6050 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
6052 return 0;
6055 static void
6056 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
6058 IOCPage4_t *pIoc4;
6059 CONFIGPARMS cfg;
6060 ConfigPageHeader_t header;
6061 dma_addr_t ioc4_dma;
6062 int iocpage4sz;
6064 /* Read and save IOC Page 4
6066 header.PageVersion = 0;
6067 header.PageLength = 0;
6068 header.PageNumber = 4;
6069 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6070 cfg.cfghdr.hdr = &header;
6071 cfg.physAddr = -1;
6072 cfg.pageAddr = 0;
6073 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6074 cfg.dir = 0;
6075 cfg.timeout = 0;
6076 if (mpt_config(ioc, &cfg) != 0)
6077 return;
6079 if (header.PageLength == 0)
6080 return;
6082 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
6083 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
6084 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
6085 if (!pIoc4)
6086 return;
6087 ioc->alloc_total += iocpage4sz;
6088 } else {
6089 ioc4_dma = ioc->spi_data.IocPg4_dma;
6090 iocpage4sz = ioc->spi_data.IocPg4Sz;
6093 /* Read the Page into dma memory.
6095 cfg.physAddr = ioc4_dma;
6096 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6097 if (mpt_config(ioc, &cfg) == 0) {
6098 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
6099 ioc->spi_data.IocPg4_dma = ioc4_dma;
6100 ioc->spi_data.IocPg4Sz = iocpage4sz;
6101 } else {
6102 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
6103 ioc->spi_data.pIocPg4 = NULL;
6104 ioc->alloc_total -= iocpage4sz;
6108 static void
6109 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
6111 IOCPage1_t *pIoc1;
6112 CONFIGPARMS cfg;
6113 ConfigPageHeader_t header;
6114 dma_addr_t ioc1_dma;
6115 int iocpage1sz = 0;
6116 u32 tmp;
6118 /* Check the Coalescing Timeout in IOC Page 1
6120 header.PageVersion = 0;
6121 header.PageLength = 0;
6122 header.PageNumber = 1;
6123 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6124 cfg.cfghdr.hdr = &header;
6125 cfg.physAddr = -1;
6126 cfg.pageAddr = 0;
6127 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6128 cfg.dir = 0;
6129 cfg.timeout = 0;
6130 if (mpt_config(ioc, &cfg) != 0)
6131 return;
6133 if (header.PageLength == 0)
6134 return;
6136 /* Read Header good, alloc memory
6138 iocpage1sz = header.PageLength * 4;
6139 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
6140 if (!pIoc1)
6141 return;
6143 /* Read the Page and check coalescing timeout
6145 cfg.physAddr = ioc1_dma;
6146 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6147 if (mpt_config(ioc, &cfg) == 0) {
6149 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
6150 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
6151 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
6153 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
6154 ioc->name, tmp));
6156 if (tmp > MPT_COALESCING_TIMEOUT) {
6157 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
6159 /* Write NVRAM and current
6161 cfg.dir = 1;
6162 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6163 if (mpt_config(ioc, &cfg) == 0) {
6164 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
6165 ioc->name, MPT_COALESCING_TIMEOUT));
6167 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
6168 if (mpt_config(ioc, &cfg) == 0) {
6169 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6170 "Reset NVRAM Coalescing Timeout to = %d\n",
6171 ioc->name, MPT_COALESCING_TIMEOUT));
6172 } else {
6173 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6174 "Reset NVRAM Coalescing Timeout Failed\n",
6175 ioc->name));
6178 } else {
6179 dprintk(ioc, printk(MYIOC_s_WARN_FMT
6180 "Reset of Current Coalescing Timeout Failed!\n",
6181 ioc->name));
6185 } else {
6186 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
6190 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
6192 return;
6195 static void
6196 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
6198 CONFIGPARMS cfg;
6199 ConfigPageHeader_t hdr;
6200 dma_addr_t buf_dma;
6201 ManufacturingPage0_t *pbuf = NULL;
6203 memset(&cfg, 0 , sizeof(CONFIGPARMS));
6204 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
6206 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
6207 cfg.cfghdr.hdr = &hdr;
6208 cfg.physAddr = -1;
6209 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6210 cfg.timeout = 10;
6212 if (mpt_config(ioc, &cfg) != 0)
6213 goto out;
6215 if (!cfg.cfghdr.hdr->PageLength)
6216 goto out;
6218 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6219 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
6220 if (!pbuf)
6221 goto out;
6223 cfg.physAddr = buf_dma;
6225 if (mpt_config(ioc, &cfg) != 0)
6226 goto out;
6228 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
6229 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
6230 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
6232 out:
6234 if (pbuf)
6235 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
6238 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6240 * SendEventNotification - Send EventNotification (on or off) request to adapter
6241 * @ioc: Pointer to MPT_ADAPTER structure
6242 * @EvSwitch: Event switch flags
6243 * @sleepFlag: Specifies whether the process can sleep
6245 static int
6246 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag)
6248 EventNotification_t evn;
6249 MPIDefaultReply_t reply_buf;
6251 memset(&evn, 0, sizeof(EventNotification_t));
6252 memset(&reply_buf, 0, sizeof(MPIDefaultReply_t));
6254 evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION;
6255 evn.Switch = EvSwitch;
6256 evn.MsgContext = cpu_to_le32(mpt_base_index << 16);
6258 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6259 "Sending EventNotification (%d) request %p\n",
6260 ioc->name, EvSwitch, &evn));
6262 return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t),
6263 (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30,
6264 sleepFlag);
6267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6269 * SendEventAck - Send EventAck request to MPT adapter.
6270 * @ioc: Pointer to MPT_ADAPTER structure
6271 * @evnp: Pointer to original EventNotification request
6273 static int
6274 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
6276 EventAck_t *pAck;
6278 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6279 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
6280 ioc->name, __func__));
6281 return -1;
6284 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
6286 pAck->Function = MPI_FUNCTION_EVENT_ACK;
6287 pAck->ChainOffset = 0;
6288 pAck->Reserved[0] = pAck->Reserved[1] = 0;
6289 pAck->MsgFlags = 0;
6290 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
6291 pAck->Event = evnp->Event;
6292 pAck->EventContext = evnp->EventContext;
6294 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
6296 return 0;
6299 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6301 * mpt_config - Generic function to issue config message
6302 * @ioc: Pointer to an adapter structure
6303 * @pCfg: Pointer to a configuration structure. Struct contains
6304 * action, page address, direction, physical address
6305 * and pointer to a configuration page header
6306 * Page header is updated.
6308 * Returns 0 for success
6309 * -EPERM if not allowed due to ISR context
6310 * -EAGAIN if no msg frames currently available
6311 * -EFAULT for non-successful reply or no reply (timeout)
6314 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
6316 Config_t *pReq;
6317 ConfigReply_t *pReply;
6318 ConfigExtendedPageHeader_t *pExtHdr = NULL;
6319 MPT_FRAME_HDR *mf;
6320 int ii;
6321 int flagsLength;
6322 long timeout;
6323 int ret;
6324 u8 page_type = 0, extend_page;
6325 unsigned long timeleft;
6326 unsigned long flags;
6327 int in_isr;
6328 u8 issue_hard_reset = 0;
6329 u8 retry_count = 0;
6331 /* Prevent calling wait_event() (below), if caller happens
6332 * to be in ISR context, because that is fatal!
6334 in_isr = in_interrupt();
6335 if (in_isr) {
6336 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
6337 ioc->name));
6338 return -EPERM;
6341 /* don't send a config page during diag reset */
6342 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6343 if (ioc->ioc_reset_in_progress) {
6344 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6345 "%s: busy with host reset\n", ioc->name, __func__));
6346 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6347 return -EBUSY;
6349 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6351 /* don't send if no chance of success */
6352 if (!ioc->active ||
6353 mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) {
6354 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6355 "%s: ioc not operational, %d, %xh\n",
6356 ioc->name, __func__, ioc->active,
6357 mpt_GetIocState(ioc, 0)));
6358 return -EFAULT;
6361 retry_config:
6362 mutex_lock(&ioc->mptbase_cmds.mutex);
6363 /* init the internal cmd struct */
6364 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
6365 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
6367 /* Get and Populate a free Frame
6369 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6370 dcprintk(ioc, printk(MYIOC_s_WARN_FMT
6371 "mpt_config: no msg frames!\n", ioc->name));
6372 ret = -EAGAIN;
6373 goto out;
6376 pReq = (Config_t *)mf;
6377 pReq->Action = pCfg->action;
6378 pReq->Reserved = 0;
6379 pReq->ChainOffset = 0;
6380 pReq->Function = MPI_FUNCTION_CONFIG;
6382 /* Assume page type is not extended and clear "reserved" fields. */
6383 pReq->ExtPageLength = 0;
6384 pReq->ExtPageType = 0;
6385 pReq->MsgFlags = 0;
6387 for (ii=0; ii < 8; ii++)
6388 pReq->Reserved2[ii] = 0;
6390 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
6391 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
6392 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
6393 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
6395 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
6396 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
6397 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
6398 pReq->ExtPageType = pExtHdr->ExtPageType;
6399 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
6401 /* Page Length must be treated as a reserved field for the
6402 * extended header.
6404 pReq->Header.PageLength = 0;
6407 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
6409 /* Add a SGE to the config request.
6411 if (pCfg->dir)
6412 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
6413 else
6414 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
6416 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
6417 MPI_CONFIG_PAGETYPE_EXTENDED) {
6418 flagsLength |= pExtHdr->ExtPageLength * 4;
6419 page_type = pReq->ExtPageType;
6420 extend_page = 1;
6421 } else {
6422 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
6423 page_type = pReq->Header.PageType;
6424 extend_page = 0;
6427 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6428 "Sending Config request type 0x%x, page 0x%x and action %d\n",
6429 ioc->name, page_type, pReq->Header.PageNumber, pReq->Action));
6431 ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
6432 timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout;
6433 mpt_put_msg_frame(mpt_base_index, ioc, mf);
6434 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done,
6435 timeout);
6436 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
6437 ret = -ETIME;
6438 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6439 "Failed Sending Config request type 0x%x, page 0x%x,"
6440 " action %d, status %xh, time left %ld\n\n",
6441 ioc->name, page_type, pReq->Header.PageNumber,
6442 pReq->Action, ioc->mptbase_cmds.status, timeleft));
6443 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
6444 goto out;
6445 if (!timeleft) {
6446 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6447 if (ioc->ioc_reset_in_progress) {
6448 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
6449 flags);
6450 printk(MYIOC_s_INFO_FMT "%s: host reset in"
6451 " progress mpt_config timed out.!!\n",
6452 __func__, ioc->name);
6453 mutex_unlock(&ioc->mptbase_cmds.mutex);
6454 return -EFAULT;
6456 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6457 issue_hard_reset = 1;
6459 goto out;
6462 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
6463 ret = -1;
6464 goto out;
6466 pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply;
6467 ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
6468 if (ret == MPI_IOCSTATUS_SUCCESS) {
6469 if (extend_page) {
6470 pCfg->cfghdr.ehdr->ExtPageLength =
6471 le16_to_cpu(pReply->ExtPageLength);
6472 pCfg->cfghdr.ehdr->ExtPageType =
6473 pReply->ExtPageType;
6475 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
6476 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
6477 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
6478 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
6482 if (retry_count)
6483 printk(MYIOC_s_INFO_FMT "Retry completed "
6484 "ret=0x%x timeleft=%ld\n",
6485 ioc->name, ret, timeleft);
6487 dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
6488 ret, le32_to_cpu(pReply->IOCLogInfo)));
6490 out:
6492 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
6493 mutex_unlock(&ioc->mptbase_cmds.mutex);
6494 if (issue_hard_reset) {
6495 issue_hard_reset = 0;
6496 printk(MYIOC_s_WARN_FMT
6497 "Issuing Reset from %s!!, doorbell=0x%08x\n",
6498 ioc->name, __func__, mpt_GetIocState(ioc, 0));
6499 if (retry_count == 0) {
6500 if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0)
6501 retry_count++;
6502 } else
6503 mpt_HardResetHandler(ioc, CAN_SLEEP);
6505 mpt_free_msg_frame(ioc, mf);
6506 /* attempt one retry for a timed out command */
6507 if (retry_count < 2) {
6508 printk(MYIOC_s_INFO_FMT
6509 "Attempting Retry Config request"
6510 " type 0x%x, page 0x%x,"
6511 " action %d\n", ioc->name, page_type,
6512 pCfg->cfghdr.hdr->PageNumber, pCfg->action);
6513 retry_count++;
6514 goto retry_config;
6517 return ret;
6521 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6523 * mpt_ioc_reset - Base cleanup for hard reset
6524 * @ioc: Pointer to the adapter structure
6525 * @reset_phase: Indicates pre- or post-reset functionality
6527 * Remark: Frees resources with internally generated commands.
6529 static int
6530 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
6532 switch (reset_phase) {
6533 case MPT_IOC_SETUP_RESET:
6534 ioc->taskmgmt_quiesce_io = 1;
6535 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6536 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
6537 break;
6538 case MPT_IOC_PRE_RESET:
6539 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6540 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
6541 break;
6542 case MPT_IOC_POST_RESET:
6543 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6544 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
6545 /* wake up mptbase_cmds */
6546 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
6547 ioc->mptbase_cmds.status |=
6548 MPT_MGMT_STATUS_DID_IOCRESET;
6549 complete(&ioc->mptbase_cmds.done);
6551 /* wake up taskmgmt_cmds */
6552 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
6553 ioc->taskmgmt_cmds.status |=
6554 MPT_MGMT_STATUS_DID_IOCRESET;
6555 complete(&ioc->taskmgmt_cmds.done);
6557 break;
6558 default:
6559 break;
6562 return 1; /* currently means nothing really */
6566 #ifdef CONFIG_PROC_FS /* { */
6567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6569 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6573 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6575 * Returns 0 for success, non-zero for failure.
6577 static int
6578 procmpt_create(void)
6580 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6581 if (mpt_proc_root_dir == NULL)
6582 return -ENOTDIR;
6584 proc_create("summary", S_IRUGO, mpt_proc_root_dir, &mpt_summary_proc_fops);
6585 proc_create("version", S_IRUGO, mpt_proc_root_dir, &mpt_version_proc_fops);
6586 return 0;
6589 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6591 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6593 * Returns 0 for success, non-zero for failure.
6595 static void
6596 procmpt_destroy(void)
6598 remove_proc_entry("version", mpt_proc_root_dir);
6599 remove_proc_entry("summary", mpt_proc_root_dir);
6600 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6603 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6605 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6607 static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan);
6609 static int mpt_summary_proc_show(struct seq_file *m, void *v)
6611 MPT_ADAPTER *ioc = m->private;
6613 if (ioc) {
6614 seq_mpt_print_ioc_summary(ioc, m, 1);
6615 } else {
6616 list_for_each_entry(ioc, &ioc_list, list) {
6617 seq_mpt_print_ioc_summary(ioc, m, 1);
6621 return 0;
6624 static int mpt_summary_proc_open(struct inode *inode, struct file *file)
6626 return single_open(file, mpt_summary_proc_show, PDE_DATA(inode));
6629 static const struct file_operations mpt_summary_proc_fops = {
6630 .owner = THIS_MODULE,
6631 .open = mpt_summary_proc_open,
6632 .read = seq_read,
6633 .llseek = seq_lseek,
6634 .release = single_release,
6637 static int mpt_version_proc_show(struct seq_file *m, void *v)
6639 u8 cb_idx;
6640 int scsi, fc, sas, lan, ctl, targ, dmp;
6641 char *drvname;
6643 seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6644 seq_printf(m, " Fusion MPT base driver\n");
6646 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6647 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6648 drvname = NULL;
6649 if (MptCallbacks[cb_idx]) {
6650 switch (MptDriverClass[cb_idx]) {
6651 case MPTSPI_DRIVER:
6652 if (!scsi++) drvname = "SPI host";
6653 break;
6654 case MPTFC_DRIVER:
6655 if (!fc++) drvname = "FC host";
6656 break;
6657 case MPTSAS_DRIVER:
6658 if (!sas++) drvname = "SAS host";
6659 break;
6660 case MPTLAN_DRIVER:
6661 if (!lan++) drvname = "LAN";
6662 break;
6663 case MPTSTM_DRIVER:
6664 if (!targ++) drvname = "SCSI target";
6665 break;
6666 case MPTCTL_DRIVER:
6667 if (!ctl++) drvname = "ioctl";
6668 break;
6671 if (drvname)
6672 seq_printf(m, " Fusion MPT %s driver\n", drvname);
6676 return 0;
6679 static int mpt_version_proc_open(struct inode *inode, struct file *file)
6681 return single_open(file, mpt_version_proc_show, NULL);
6684 static const struct file_operations mpt_version_proc_fops = {
6685 .owner = THIS_MODULE,
6686 .open = mpt_version_proc_open,
6687 .read = seq_read,
6688 .llseek = seq_lseek,
6689 .release = single_release,
6692 static int mpt_iocinfo_proc_show(struct seq_file *m, void *v)
6694 MPT_ADAPTER *ioc = m->private;
6695 char expVer[32];
6696 int sz;
6697 int p;
6699 mpt_get_fw_exp_ver(expVer, ioc);
6701 seq_printf(m, "%s:", ioc->name);
6702 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6703 seq_printf(m, " (f/w download boot flag set)");
6704 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6705 // seq_printf(m, " CONFIG_CHECKSUM_FAIL!");
6707 seq_printf(m, "\n ProductID = 0x%04x (%s)\n",
6708 ioc->facts.ProductID,
6709 ioc->prod_name);
6710 seq_printf(m, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6711 if (ioc->facts.FWImageSize)
6712 seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize);
6713 seq_printf(m, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6714 seq_printf(m, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6715 seq_printf(m, " EventState = 0x%02x\n", ioc->facts.EventState);
6717 seq_printf(m, " CurrentHostMfaHighAddr = 0x%08x\n",
6718 ioc->facts.CurrentHostMfaHighAddr);
6719 seq_printf(m, " CurrentSenseBufferHighAddr = 0x%08x\n",
6720 ioc->facts.CurrentSenseBufferHighAddr);
6722 seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6723 seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6725 seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6726 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6728 * Rounding UP to nearest 4-kB boundary here...
6730 sz = (ioc->req_sz * ioc->req_depth) + 128;
6731 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6732 seq_printf(m, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6733 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6734 seq_printf(m, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6735 4*ioc->facts.RequestFrameSize,
6736 ioc->facts.GlobalCredits);
6738 seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n",
6739 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6740 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6741 seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6742 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6743 seq_printf(m, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6744 ioc->facts.CurReplyFrameSize,
6745 ioc->facts.ReplyQueueDepth);
6747 seq_printf(m, " MaxDevices = %d\n",
6748 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6749 seq_printf(m, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6751 /* per-port info */
6752 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6753 seq_printf(m, " PortNumber = %d (of %d)\n",
6754 p+1,
6755 ioc->facts.NumberOfPorts);
6756 if (ioc->bus_type == FC) {
6757 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6758 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6759 seq_printf(m, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6760 a[5], a[4], a[3], a[2], a[1], a[0]);
6762 seq_printf(m, " WWN = %08X%08X:%08X%08X\n",
6763 ioc->fc_port_page0[p].WWNN.High,
6764 ioc->fc_port_page0[p].WWNN.Low,
6765 ioc->fc_port_page0[p].WWPN.High,
6766 ioc->fc_port_page0[p].WWPN.Low);
6770 return 0;
6773 static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)
6775 return single_open(file, mpt_iocinfo_proc_show, PDE_DATA(inode));
6778 static const struct file_operations mpt_iocinfo_proc_fops = {
6779 .owner = THIS_MODULE,
6780 .open = mpt_iocinfo_proc_open,
6781 .read = seq_read,
6782 .llseek = seq_lseek,
6783 .release = single_release,
6785 #endif /* CONFIG_PROC_FS } */
6787 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6788 static void
6789 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6791 buf[0] ='\0';
6792 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6793 sprintf(buf, " (Exp %02d%02d)",
6794 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6795 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6797 /* insider hack! */
6798 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6799 strcat(buf, " [MDBG]");
6803 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6805 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6806 * @ioc: Pointer to MPT_ADAPTER structure
6807 * @buffer: Pointer to buffer where IOC summary info should be written
6808 * @size: Pointer to number of bytes we wrote (set by this routine)
6809 * @len: Offset at which to start writing in buffer
6810 * @showlan: Display LAN stuff?
6812 * This routine writes (english readable) ASCII text, which represents
6813 * a summary of IOC information, to a buffer.
6815 void
6816 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6818 char expVer[32];
6819 int y;
6821 mpt_get_fw_exp_ver(expVer, ioc);
6824 * Shorter summary of attached ioc's...
6826 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6827 ioc->name,
6828 ioc->prod_name,
6829 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6830 ioc->facts.FWVersion.Word,
6831 expVer,
6832 ioc->facts.NumberOfPorts,
6833 ioc->req_depth);
6835 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6836 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6837 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6838 a[5], a[4], a[3], a[2], a[1], a[0]);
6841 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6843 if (!ioc->active)
6844 y += sprintf(buffer+len+y, " (disabled)");
6846 y += sprintf(buffer+len+y, "\n");
6848 *size = y;
6851 static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan)
6853 char expVer[32];
6855 mpt_get_fw_exp_ver(expVer, ioc);
6858 * Shorter summary of attached ioc's...
6860 seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6861 ioc->name,
6862 ioc->prod_name,
6863 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6864 ioc->facts.FWVersion.Word,
6865 expVer,
6866 ioc->facts.NumberOfPorts,
6867 ioc->req_depth);
6869 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6870 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6871 seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6872 a[5], a[4], a[3], a[2], a[1], a[0]);
6875 seq_printf(m, ", IRQ=%d", ioc->pci_irq);
6877 if (!ioc->active)
6878 seq_printf(m, " (disabled)");
6880 seq_putc(m, '\n');
6884 * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management
6885 * @ioc: Pointer to MPT_ADAPTER structure
6887 * Returns 0 for SUCCESS or -1 if FAILED.
6889 * If -1 is return, then it was not possible to set the flags
6892 mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6894 unsigned long flags;
6895 int retval;
6897 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6898 if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
6899 (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
6900 retval = -1;
6901 goto out;
6903 retval = 0;
6904 ioc->taskmgmt_in_progress = 1;
6905 ioc->taskmgmt_quiesce_io = 1;
6906 if (ioc->alt_ioc) {
6907 ioc->alt_ioc->taskmgmt_in_progress = 1;
6908 ioc->alt_ioc->taskmgmt_quiesce_io = 1;
6910 out:
6911 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6912 return retval;
6914 EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
6917 * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management
6918 * @ioc: Pointer to MPT_ADAPTER structure
6921 void
6922 mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6924 unsigned long flags;
6926 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6927 ioc->taskmgmt_in_progress = 0;
6928 ioc->taskmgmt_quiesce_io = 0;
6929 if (ioc->alt_ioc) {
6930 ioc->alt_ioc->taskmgmt_in_progress = 0;
6931 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
6933 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6935 EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
6939 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6940 * the kernel
6941 * @ioc: Pointer to MPT_ADAPTER structure
6944 void
6945 mpt_halt_firmware(MPT_ADAPTER *ioc)
6947 u32 ioc_raw_state;
6949 ioc_raw_state = mpt_GetIocState(ioc, 0);
6951 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6952 printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6953 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6954 panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6955 ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6956 } else {
6957 CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6958 panic("%s: Firmware is halted due to command timeout\n",
6959 ioc->name);
6962 EXPORT_SYMBOL(mpt_halt_firmware);
6965 * mpt_SoftResetHandler - Issues a less expensive reset
6966 * @ioc: Pointer to MPT_ADAPTER structure
6967 * @sleepFlag: Indicates if sleep or schedule must be called.
6969 * Returns 0 for SUCCESS or -1 if FAILED.
6971 * Message Unit Reset - instructs the IOC to reset the Reply Post and
6972 * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
6973 * All posted buffers are freed, and event notification is turned off.
6974 * IOC doesn't reply to any outstanding request. This will transfer IOC
6975 * to READY state.
6977 static int
6978 mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6980 int rc;
6981 int ii;
6982 u8 cb_idx;
6983 unsigned long flags;
6984 u32 ioc_state;
6985 unsigned long time_count;
6987 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n",
6988 ioc->name));
6990 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
6992 if (mpt_fwfault_debug)
6993 mpt_halt_firmware(ioc);
6995 if (ioc_state == MPI_IOC_STATE_FAULT ||
6996 ioc_state == MPI_IOC_STATE_RESET) {
6997 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6998 "skipping, either in FAULT or RESET state!\n", ioc->name));
6999 return -1;
7002 if (ioc->bus_type == FC) {
7003 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7004 "skipping, because the bus type is FC!\n", ioc->name));
7005 return -1;
7008 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7009 if (ioc->ioc_reset_in_progress) {
7010 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7011 return -1;
7013 ioc->ioc_reset_in_progress = 1;
7014 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7016 rc = -1;
7018 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7019 if (MptResetHandlers[cb_idx])
7020 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
7023 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7024 if (ioc->taskmgmt_in_progress) {
7025 ioc->ioc_reset_in_progress = 0;
7026 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7027 return -1;
7029 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7030 /* Disable reply interrupts (also blocks FreeQ) */
7031 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
7032 ioc->active = 0;
7033 time_count = jiffies;
7035 rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
7037 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7038 if (MptResetHandlers[cb_idx])
7039 mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
7042 if (rc)
7043 goto out;
7045 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
7046 if (ioc_state != MPI_IOC_STATE_READY)
7047 goto out;
7049 for (ii = 0; ii < 5; ii++) {
7050 /* Get IOC facts! Allow 5 retries */
7051 rc = GetIocFacts(ioc, sleepFlag,
7052 MPT_HOSTEVENT_IOC_RECOVER);
7053 if (rc == 0)
7054 break;
7055 if (sleepFlag == CAN_SLEEP)
7056 msleep(100);
7057 else
7058 mdelay(100);
7060 if (ii == 5)
7061 goto out;
7063 rc = PrimeIocFifos(ioc);
7064 if (rc != 0)
7065 goto out;
7067 rc = SendIocInit(ioc, sleepFlag);
7068 if (rc != 0)
7069 goto out;
7071 rc = SendEventNotification(ioc, 1, sleepFlag);
7072 if (rc != 0)
7073 goto out;
7075 if (ioc->hard_resets < -1)
7076 ioc->hard_resets++;
7079 * At this point, we know soft reset succeeded.
7082 ioc->active = 1;
7083 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
7085 out:
7086 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7087 ioc->ioc_reset_in_progress = 0;
7088 ioc->taskmgmt_quiesce_io = 0;
7089 ioc->taskmgmt_in_progress = 0;
7090 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7092 if (ioc->active) { /* otherwise, hard reset coming */
7093 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7094 if (MptResetHandlers[cb_idx])
7095 mpt_signal_reset(cb_idx, ioc,
7096 MPT_IOC_POST_RESET);
7100 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7101 "SoftResetHandler: completed (%d seconds): %s\n",
7102 ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
7103 ((rc == 0) ? "SUCCESS" : "FAILED")));
7105 return rc;
7109 * mpt_Soft_Hard_ResetHandler - Try less expensive reset
7110 * @ioc: Pointer to MPT_ADAPTER structure
7111 * @sleepFlag: Indicates if sleep or schedule must be called.
7113 * Returns 0 for SUCCESS or -1 if FAILED.
7114 * Try for softreset first, only if it fails go for expensive
7115 * HardReset.
7118 mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) {
7119 int ret = -1;
7121 ret = mpt_SoftResetHandler(ioc, sleepFlag);
7122 if (ret == 0)
7123 return ret;
7124 ret = mpt_HardResetHandler(ioc, sleepFlag);
7125 return ret;
7127 EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler);
7129 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7131 * Reset Handling
7133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7135 * mpt_HardResetHandler - Generic reset handler
7136 * @ioc: Pointer to MPT_ADAPTER structure
7137 * @sleepFlag: Indicates if sleep or schedule must be called.
7139 * Issues SCSI Task Management call based on input arg values.
7140 * If TaskMgmt fails, returns associated SCSI request.
7142 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
7143 * or a non-interrupt thread. In the former, must not call schedule().
7145 * Note: A return of -1 is a FATAL error case, as it means a
7146 * FW reload/initialization failed.
7148 * Returns 0 for SUCCESS or -1 if FAILED.
7151 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7153 int rc;
7154 u8 cb_idx;
7155 unsigned long flags;
7156 unsigned long time_count;
7158 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
7159 #ifdef MFCNT
7160 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
7161 printk("MF count 0x%x !\n", ioc->mfcnt);
7162 #endif
7163 if (mpt_fwfault_debug)
7164 mpt_halt_firmware(ioc);
7166 /* Reset the adapter. Prevent more than 1 call to
7167 * mpt_do_ioc_recovery at any instant in time.
7169 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7170 if (ioc->ioc_reset_in_progress) {
7171 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7172 ioc->wait_on_reset_completion = 1;
7173 do {
7174 ssleep(1);
7175 } while (ioc->ioc_reset_in_progress == 1);
7176 ioc->wait_on_reset_completion = 0;
7177 return ioc->reset_status;
7179 if (ioc->wait_on_reset_completion) {
7180 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7181 rc = 0;
7182 time_count = jiffies;
7183 goto exit;
7185 ioc->ioc_reset_in_progress = 1;
7186 if (ioc->alt_ioc)
7187 ioc->alt_ioc->ioc_reset_in_progress = 1;
7188 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7191 /* The SCSI driver needs to adjust timeouts on all current
7192 * commands prior to the diagnostic reset being issued.
7193 * Prevents timeouts occurring during a diagnostic reset...very bad.
7194 * For all other protocol drivers, this is a no-op.
7196 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7197 if (MptResetHandlers[cb_idx]) {
7198 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
7199 if (ioc->alt_ioc)
7200 mpt_signal_reset(cb_idx, ioc->alt_ioc,
7201 MPT_IOC_SETUP_RESET);
7205 time_count = jiffies;
7206 rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
7207 if (rc != 0) {
7208 printk(KERN_WARNING MYNAM
7209 ": WARNING - (%d) Cannot recover %s, doorbell=0x%08x\n",
7210 rc, ioc->name, mpt_GetIocState(ioc, 0));
7211 } else {
7212 if (ioc->hard_resets < -1)
7213 ioc->hard_resets++;
7216 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7217 ioc->ioc_reset_in_progress = 0;
7218 ioc->taskmgmt_quiesce_io = 0;
7219 ioc->taskmgmt_in_progress = 0;
7220 ioc->reset_status = rc;
7221 if (ioc->alt_ioc) {
7222 ioc->alt_ioc->ioc_reset_in_progress = 0;
7223 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
7224 ioc->alt_ioc->taskmgmt_in_progress = 0;
7226 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7228 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7229 if (MptResetHandlers[cb_idx]) {
7230 mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
7231 if (ioc->alt_ioc)
7232 mpt_signal_reset(cb_idx,
7233 ioc->alt_ioc, MPT_IOC_POST_RESET);
7236 exit:
7237 dtmprintk(ioc,
7238 printk(MYIOC_s_DEBUG_FMT
7239 "HardResetHandler: completed (%d seconds): %s\n", ioc->name,
7240 jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ?
7241 "SUCCESS" : "FAILED")));
7243 return rc;
7246 #ifdef CONFIG_FUSION_LOGGING
7247 static void
7248 mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
7250 char *ds = NULL;
7251 u32 evData0;
7252 int ii;
7253 u8 event;
7254 char *evStr = ioc->evStr;
7256 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7257 evData0 = le32_to_cpu(pEventReply->Data[0]);
7259 switch(event) {
7260 case MPI_EVENT_NONE:
7261 ds = "None";
7262 break;
7263 case MPI_EVENT_LOG_DATA:
7264 ds = "Log Data";
7265 break;
7266 case MPI_EVENT_STATE_CHANGE:
7267 ds = "State Change";
7268 break;
7269 case MPI_EVENT_UNIT_ATTENTION:
7270 ds = "Unit Attention";
7271 break;
7272 case MPI_EVENT_IOC_BUS_RESET:
7273 ds = "IOC Bus Reset";
7274 break;
7275 case MPI_EVENT_EXT_BUS_RESET:
7276 ds = "External Bus Reset";
7277 break;
7278 case MPI_EVENT_RESCAN:
7279 ds = "Bus Rescan Event";
7280 break;
7281 case MPI_EVENT_LINK_STATUS_CHANGE:
7282 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
7283 ds = "Link Status(FAILURE) Change";
7284 else
7285 ds = "Link Status(ACTIVE) Change";
7286 break;
7287 case MPI_EVENT_LOOP_STATE_CHANGE:
7288 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
7289 ds = "Loop State(LIP) Change";
7290 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
7291 ds = "Loop State(LPE) Change";
7292 else
7293 ds = "Loop State(LPB) Change";
7294 break;
7295 case MPI_EVENT_LOGOUT:
7296 ds = "Logout";
7297 break;
7298 case MPI_EVENT_EVENT_CHANGE:
7299 if (evData0)
7300 ds = "Events ON";
7301 else
7302 ds = "Events OFF";
7303 break;
7304 case MPI_EVENT_INTEGRATED_RAID:
7306 u8 ReasonCode = (u8)(evData0 >> 16);
7307 switch (ReasonCode) {
7308 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
7309 ds = "Integrated Raid: Volume Created";
7310 break;
7311 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
7312 ds = "Integrated Raid: Volume Deleted";
7313 break;
7314 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
7315 ds = "Integrated Raid: Volume Settings Changed";
7316 break;
7317 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
7318 ds = "Integrated Raid: Volume Status Changed";
7319 break;
7320 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
7321 ds = "Integrated Raid: Volume Physdisk Changed";
7322 break;
7323 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
7324 ds = "Integrated Raid: Physdisk Created";
7325 break;
7326 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
7327 ds = "Integrated Raid: Physdisk Deleted";
7328 break;
7329 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
7330 ds = "Integrated Raid: Physdisk Settings Changed";
7331 break;
7332 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
7333 ds = "Integrated Raid: Physdisk Status Changed";
7334 break;
7335 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
7336 ds = "Integrated Raid: Domain Validation Needed";
7337 break;
7338 case MPI_EVENT_RAID_RC_SMART_DATA :
7339 ds = "Integrated Raid; Smart Data";
7340 break;
7341 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
7342 ds = "Integrated Raid: Replace Action Started";
7343 break;
7344 default:
7345 ds = "Integrated Raid";
7346 break;
7348 break;
7350 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
7351 ds = "SCSI Device Status Change";
7352 break;
7353 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
7355 u8 id = (u8)(evData0);
7356 u8 channel = (u8)(evData0 >> 8);
7357 u8 ReasonCode = (u8)(evData0 >> 16);
7358 switch (ReasonCode) {
7359 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
7360 snprintf(evStr, EVENT_DESCR_STR_SZ,
7361 "SAS Device Status Change: Added: "
7362 "id=%d channel=%d", id, channel);
7363 break;
7364 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
7365 snprintf(evStr, EVENT_DESCR_STR_SZ,
7366 "SAS Device Status Change: Deleted: "
7367 "id=%d channel=%d", id, channel);
7368 break;
7369 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7370 snprintf(evStr, EVENT_DESCR_STR_SZ,
7371 "SAS Device Status Change: SMART Data: "
7372 "id=%d channel=%d", id, channel);
7373 break;
7374 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
7375 snprintf(evStr, EVENT_DESCR_STR_SZ,
7376 "SAS Device Status Change: No Persistancy: "
7377 "id=%d channel=%d", id, channel);
7378 break;
7379 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7380 snprintf(evStr, EVENT_DESCR_STR_SZ,
7381 "SAS Device Status Change: Unsupported Device "
7382 "Discovered : id=%d channel=%d", id, channel);
7383 break;
7384 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7385 snprintf(evStr, EVENT_DESCR_STR_SZ,
7386 "SAS Device Status Change: Internal Device "
7387 "Reset : id=%d channel=%d", id, channel);
7388 break;
7389 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7390 snprintf(evStr, EVENT_DESCR_STR_SZ,
7391 "SAS Device Status Change: Internal Task "
7392 "Abort : id=%d channel=%d", id, channel);
7393 break;
7394 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7395 snprintf(evStr, EVENT_DESCR_STR_SZ,
7396 "SAS Device Status Change: Internal Abort "
7397 "Task Set : id=%d channel=%d", id, channel);
7398 break;
7399 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7400 snprintf(evStr, EVENT_DESCR_STR_SZ,
7401 "SAS Device Status Change: Internal Clear "
7402 "Task Set : id=%d channel=%d", id, channel);
7403 break;
7404 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7405 snprintf(evStr, EVENT_DESCR_STR_SZ,
7406 "SAS Device Status Change: Internal Query "
7407 "Task : id=%d channel=%d", id, channel);
7408 break;
7409 default:
7410 snprintf(evStr, EVENT_DESCR_STR_SZ,
7411 "SAS Device Status Change: Unknown: "
7412 "id=%d channel=%d", id, channel);
7413 break;
7415 break;
7417 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
7418 ds = "Bus Timer Expired";
7419 break;
7420 case MPI_EVENT_QUEUE_FULL:
7422 u16 curr_depth = (u16)(evData0 >> 16);
7423 u8 channel = (u8)(evData0 >> 8);
7424 u8 id = (u8)(evData0);
7426 snprintf(evStr, EVENT_DESCR_STR_SZ,
7427 "Queue Full: channel=%d id=%d depth=%d",
7428 channel, id, curr_depth);
7429 break;
7431 case MPI_EVENT_SAS_SES:
7432 ds = "SAS SES Event";
7433 break;
7434 case MPI_EVENT_PERSISTENT_TABLE_FULL:
7435 ds = "Persistent Table Full";
7436 break;
7437 case MPI_EVENT_SAS_PHY_LINK_STATUS:
7439 u8 LinkRates = (u8)(evData0 >> 8);
7440 u8 PhyNumber = (u8)(evData0);
7441 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
7442 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
7443 switch (LinkRates) {
7444 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
7445 snprintf(evStr, EVENT_DESCR_STR_SZ,
7446 "SAS PHY Link Status: Phy=%d:"
7447 " Rate Unknown",PhyNumber);
7448 break;
7449 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
7450 snprintf(evStr, EVENT_DESCR_STR_SZ,
7451 "SAS PHY Link Status: Phy=%d:"
7452 " Phy Disabled",PhyNumber);
7453 break;
7454 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
7455 snprintf(evStr, EVENT_DESCR_STR_SZ,
7456 "SAS PHY Link Status: Phy=%d:"
7457 " Failed Speed Nego",PhyNumber);
7458 break;
7459 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
7460 snprintf(evStr, EVENT_DESCR_STR_SZ,
7461 "SAS PHY Link Status: Phy=%d:"
7462 " Sata OOB Completed",PhyNumber);
7463 break;
7464 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
7465 snprintf(evStr, EVENT_DESCR_STR_SZ,
7466 "SAS PHY Link Status: Phy=%d:"
7467 " Rate 1.5 Gbps",PhyNumber);
7468 break;
7469 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
7470 snprintf(evStr, EVENT_DESCR_STR_SZ,
7471 "SAS PHY Link Status: Phy=%d:"
7472 " Rate 3.0 Gbps", PhyNumber);
7473 break;
7474 case MPI_EVENT_SAS_PLS_LR_RATE_6_0:
7475 snprintf(evStr, EVENT_DESCR_STR_SZ,
7476 "SAS PHY Link Status: Phy=%d:"
7477 " Rate 6.0 Gbps", PhyNumber);
7478 break;
7479 default:
7480 snprintf(evStr, EVENT_DESCR_STR_SZ,
7481 "SAS PHY Link Status: Phy=%d", PhyNumber);
7482 break;
7484 break;
7486 case MPI_EVENT_SAS_DISCOVERY_ERROR:
7487 ds = "SAS Discovery Error";
7488 break;
7489 case MPI_EVENT_IR_RESYNC_UPDATE:
7491 u8 resync_complete = (u8)(evData0 >> 16);
7492 snprintf(evStr, EVENT_DESCR_STR_SZ,
7493 "IR Resync Update: Complete = %d:",resync_complete);
7494 break;
7496 case MPI_EVENT_IR2:
7498 u8 id = (u8)(evData0);
7499 u8 channel = (u8)(evData0 >> 8);
7500 u8 phys_num = (u8)(evData0 >> 24);
7501 u8 ReasonCode = (u8)(evData0 >> 16);
7503 switch (ReasonCode) {
7504 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
7505 snprintf(evStr, EVENT_DESCR_STR_SZ,
7506 "IR2: LD State Changed: "
7507 "id=%d channel=%d phys_num=%d",
7508 id, channel, phys_num);
7509 break;
7510 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
7511 snprintf(evStr, EVENT_DESCR_STR_SZ,
7512 "IR2: PD State Changed "
7513 "id=%d channel=%d phys_num=%d",
7514 id, channel, phys_num);
7515 break;
7516 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
7517 snprintf(evStr, EVENT_DESCR_STR_SZ,
7518 "IR2: Bad Block Table Full: "
7519 "id=%d channel=%d phys_num=%d",
7520 id, channel, phys_num);
7521 break;
7522 case MPI_EVENT_IR2_RC_PD_INSERTED:
7523 snprintf(evStr, EVENT_DESCR_STR_SZ,
7524 "IR2: PD Inserted: "
7525 "id=%d channel=%d phys_num=%d",
7526 id, channel, phys_num);
7527 break;
7528 case MPI_EVENT_IR2_RC_PD_REMOVED:
7529 snprintf(evStr, EVENT_DESCR_STR_SZ,
7530 "IR2: PD Removed: "
7531 "id=%d channel=%d phys_num=%d",
7532 id, channel, phys_num);
7533 break;
7534 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
7535 snprintf(evStr, EVENT_DESCR_STR_SZ,
7536 "IR2: Foreign CFG Detected: "
7537 "id=%d channel=%d phys_num=%d",
7538 id, channel, phys_num);
7539 break;
7540 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
7541 snprintf(evStr, EVENT_DESCR_STR_SZ,
7542 "IR2: Rebuild Medium Error: "
7543 "id=%d channel=%d phys_num=%d",
7544 id, channel, phys_num);
7545 break;
7546 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
7547 snprintf(evStr, EVENT_DESCR_STR_SZ,
7548 "IR2: Dual Port Added: "
7549 "id=%d channel=%d phys_num=%d",
7550 id, channel, phys_num);
7551 break;
7552 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
7553 snprintf(evStr, EVENT_DESCR_STR_SZ,
7554 "IR2: Dual Port Removed: "
7555 "id=%d channel=%d phys_num=%d",
7556 id, channel, phys_num);
7557 break;
7558 default:
7559 ds = "IR2";
7560 break;
7562 break;
7564 case MPI_EVENT_SAS_DISCOVERY:
7566 if (evData0)
7567 ds = "SAS Discovery: Start";
7568 else
7569 ds = "SAS Discovery: Stop";
7570 break;
7572 case MPI_EVENT_LOG_ENTRY_ADDED:
7573 ds = "SAS Log Entry Added";
7574 break;
7576 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
7578 u8 phy_num = (u8)(evData0);
7579 u8 port_num = (u8)(evData0 >> 8);
7580 u8 port_width = (u8)(evData0 >> 16);
7581 u8 primative = (u8)(evData0 >> 24);
7582 snprintf(evStr, EVENT_DESCR_STR_SZ,
7583 "SAS Broadcase Primative: phy=%d port=%d "
7584 "width=%d primative=0x%02x",
7585 phy_num, port_num, port_width, primative);
7586 break;
7589 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
7591 u8 reason = (u8)(evData0);
7593 switch (reason) {
7594 case MPI_EVENT_SAS_INIT_RC_ADDED:
7595 ds = "SAS Initiator Status Change: Added";
7596 break;
7597 case MPI_EVENT_SAS_INIT_RC_REMOVED:
7598 ds = "SAS Initiator Status Change: Deleted";
7599 break;
7600 default:
7601 ds = "SAS Initiator Status Change";
7602 break;
7604 break;
7607 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
7609 u8 max_init = (u8)(evData0);
7610 u8 current_init = (u8)(evData0 >> 8);
7612 snprintf(evStr, EVENT_DESCR_STR_SZ,
7613 "SAS Initiator Device Table Overflow: max initiators=%02d "
7614 "current initators=%02d",
7615 max_init, current_init);
7616 break;
7618 case MPI_EVENT_SAS_SMP_ERROR:
7620 u8 status = (u8)(evData0);
7621 u8 port_num = (u8)(evData0 >> 8);
7622 u8 result = (u8)(evData0 >> 16);
7624 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
7625 snprintf(evStr, EVENT_DESCR_STR_SZ,
7626 "SAS SMP Error: port=%d result=0x%02x",
7627 port_num, result);
7628 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
7629 snprintf(evStr, EVENT_DESCR_STR_SZ,
7630 "SAS SMP Error: port=%d : CRC Error",
7631 port_num);
7632 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
7633 snprintf(evStr, EVENT_DESCR_STR_SZ,
7634 "SAS SMP Error: port=%d : Timeout",
7635 port_num);
7636 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
7637 snprintf(evStr, EVENT_DESCR_STR_SZ,
7638 "SAS SMP Error: port=%d : No Destination",
7639 port_num);
7640 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
7641 snprintf(evStr, EVENT_DESCR_STR_SZ,
7642 "SAS SMP Error: port=%d : Bad Destination",
7643 port_num);
7644 else
7645 snprintf(evStr, EVENT_DESCR_STR_SZ,
7646 "SAS SMP Error: port=%d : status=0x%02x",
7647 port_num, status);
7648 break;
7651 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
7653 u8 reason = (u8)(evData0);
7655 switch (reason) {
7656 case MPI_EVENT_SAS_EXP_RC_ADDED:
7657 ds = "Expander Status Change: Added";
7658 break;
7659 case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
7660 ds = "Expander Status Change: Deleted";
7661 break;
7662 default:
7663 ds = "Expander Status Change";
7664 break;
7666 break;
7670 * MPT base "custom" events may be added here...
7672 default:
7673 ds = "Unknown";
7674 break;
7676 if (ds)
7677 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
7680 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7681 "MPT event:(%02Xh) : %s\n",
7682 ioc->name, event, evStr));
7684 devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
7685 ": Event data:\n"));
7686 for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
7687 devtverboseprintk(ioc, printk(" %08x",
7688 le32_to_cpu(pEventReply->Data[ii])));
7689 devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
7691 #endif
7692 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7694 * ProcessEventNotification - Route EventNotificationReply to all event handlers
7695 * @ioc: Pointer to MPT_ADAPTER structure
7696 * @pEventReply: Pointer to EventNotification reply frame
7697 * @evHandlers: Pointer to integer, number of event handlers
7699 * Routes a received EventNotificationReply to all currently registered
7700 * event handlers.
7701 * Returns sum of event handlers return values.
7703 static int
7704 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
7706 u16 evDataLen;
7707 u32 evData0 = 0;
7708 int ii;
7709 u8 cb_idx;
7710 int r = 0;
7711 int handlers = 0;
7712 u8 event;
7715 * Do platform normalization of values
7717 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7718 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
7719 if (evDataLen) {
7720 evData0 = le32_to_cpu(pEventReply->Data[0]);
7723 #ifdef CONFIG_FUSION_LOGGING
7724 if (evDataLen)
7725 mpt_display_event_info(ioc, pEventReply);
7726 #endif
7729 * Do general / base driver event processing
7731 switch(event) {
7732 case MPI_EVENT_EVENT_CHANGE: /* 0A */
7733 if (evDataLen) {
7734 u8 evState = evData0 & 0xFF;
7736 /* CHECKME! What if evState unexpectedly says OFF (0)? */
7738 /* Update EventState field in cached IocFacts */
7739 if (ioc->facts.Function) {
7740 ioc->facts.EventState = evState;
7743 break;
7744 case MPI_EVENT_INTEGRATED_RAID:
7745 mptbase_raid_process_event_data(ioc,
7746 (MpiEventDataRaid_t *)pEventReply->Data);
7747 break;
7748 default:
7749 break;
7753 * Should this event be logged? Events are written sequentially.
7754 * When buffer is full, start again at the top.
7756 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
7757 int idx;
7759 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
7761 ioc->events[idx].event = event;
7762 ioc->events[idx].eventContext = ioc->eventContext;
7764 for (ii = 0; ii < 2; ii++) {
7765 if (ii < evDataLen)
7766 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
7767 else
7768 ioc->events[idx].data[ii] = 0;
7771 ioc->eventContext++;
7776 * Call each currently registered protocol event handler.
7778 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7779 if (MptEvHandlers[cb_idx]) {
7780 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7781 "Routing Event to event handler #%d\n",
7782 ioc->name, cb_idx));
7783 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
7784 handlers++;
7787 /* FIXME? Examine results here? */
7790 * If needed, send (a single) EventAck.
7792 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
7793 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7794 "EventAck required\n",ioc->name));
7795 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
7796 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
7797 ioc->name, ii));
7801 *evHandlers = handlers;
7802 return r;
7805 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7807 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
7808 * @ioc: Pointer to MPT_ADAPTER structure
7809 * @log_info: U32 LogInfo reply word from the IOC
7811 * Refer to lsi/mpi_log_fc.h.
7813 static void
7814 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
7816 char *desc = "unknown";
7818 switch (log_info & 0xFF000000) {
7819 case MPI_IOCLOGINFO_FC_INIT_BASE:
7820 desc = "FCP Initiator";
7821 break;
7822 case MPI_IOCLOGINFO_FC_TARGET_BASE:
7823 desc = "FCP Target";
7824 break;
7825 case MPI_IOCLOGINFO_FC_LAN_BASE:
7826 desc = "LAN";
7827 break;
7828 case MPI_IOCLOGINFO_FC_MSG_BASE:
7829 desc = "MPI Message Layer";
7830 break;
7831 case MPI_IOCLOGINFO_FC_LINK_BASE:
7832 desc = "FC Link";
7833 break;
7834 case MPI_IOCLOGINFO_FC_CTX_BASE:
7835 desc = "Context Manager";
7836 break;
7837 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
7838 desc = "Invalid Field Offset";
7839 break;
7840 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
7841 desc = "State Change Info";
7842 break;
7845 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
7846 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
7849 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7851 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7852 * @ioc: Pointer to MPT_ADAPTER structure
7853 * @log_info: U32 LogInfo word from the IOC
7855 * Refer to lsi/sp_log.h.
7857 static void
7858 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7860 u32 info = log_info & 0x00FF0000;
7861 char *desc = "unknown";
7863 switch (info) {
7864 case 0x00010000:
7865 desc = "bug! MID not found";
7866 break;
7868 case 0x00020000:
7869 desc = "Parity Error";
7870 break;
7872 case 0x00030000:
7873 desc = "ASYNC Outbound Overrun";
7874 break;
7876 case 0x00040000:
7877 desc = "SYNC Offset Error";
7878 break;
7880 case 0x00050000:
7881 desc = "BM Change";
7882 break;
7884 case 0x00060000:
7885 desc = "Msg In Overflow";
7886 break;
7888 case 0x00070000:
7889 desc = "DMA Error";
7890 break;
7892 case 0x00080000:
7893 desc = "Outbound DMA Overrun";
7894 break;
7896 case 0x00090000:
7897 desc = "Task Management";
7898 break;
7900 case 0x000A0000:
7901 desc = "Device Problem";
7902 break;
7904 case 0x000B0000:
7905 desc = "Invalid Phase Change";
7906 break;
7908 case 0x000C0000:
7909 desc = "Untagged Table Size";
7910 break;
7914 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7917 /* strings for sas loginfo */
7918 static char *originator_str[] = {
7919 "IOP", /* 00h */
7920 "PL", /* 01h */
7921 "IR" /* 02h */
7923 static char *iop_code_str[] = {
7924 NULL, /* 00h */
7925 "Invalid SAS Address", /* 01h */
7926 NULL, /* 02h */
7927 "Invalid Page", /* 03h */
7928 "Diag Message Error", /* 04h */
7929 "Task Terminated", /* 05h */
7930 "Enclosure Management", /* 06h */
7931 "Target Mode" /* 07h */
7933 static char *pl_code_str[] = {
7934 NULL, /* 00h */
7935 "Open Failure", /* 01h */
7936 "Invalid Scatter Gather List", /* 02h */
7937 "Wrong Relative Offset or Frame Length", /* 03h */
7938 "Frame Transfer Error", /* 04h */
7939 "Transmit Frame Connected Low", /* 05h */
7940 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7941 "SATA Read Log Receive Data Error", /* 07h */
7942 "SATA NCQ Fail All Commands After Error", /* 08h */
7943 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7944 "Receive Frame Invalid Message", /* 0Ah */
7945 "Receive Context Message Valid Error", /* 0Bh */
7946 "Receive Frame Current Frame Error", /* 0Ch */
7947 "SATA Link Down", /* 0Dh */
7948 "Discovery SATA Init W IOS", /* 0Eh */
7949 "Config Invalid Page", /* 0Fh */
7950 "Discovery SATA Init Timeout", /* 10h */
7951 "Reset", /* 11h */
7952 "Abort", /* 12h */
7953 "IO Not Yet Executed", /* 13h */
7954 "IO Executed", /* 14h */
7955 "Persistent Reservation Out Not Affiliation "
7956 "Owner", /* 15h */
7957 "Open Transmit DMA Abort", /* 16h */
7958 "IO Device Missing Delay Retry", /* 17h */
7959 "IO Cancelled Due to Receive Error", /* 18h */
7960 NULL, /* 19h */
7961 NULL, /* 1Ah */
7962 NULL, /* 1Bh */
7963 NULL, /* 1Ch */
7964 NULL, /* 1Dh */
7965 NULL, /* 1Eh */
7966 NULL, /* 1Fh */
7967 "Enclosure Management" /* 20h */
7969 static char *ir_code_str[] = {
7970 "Raid Action Error", /* 00h */
7971 NULL, /* 00h */
7972 NULL, /* 01h */
7973 NULL, /* 02h */
7974 NULL, /* 03h */
7975 NULL, /* 04h */
7976 NULL, /* 05h */
7977 NULL, /* 06h */
7978 NULL /* 07h */
7980 static char *raid_sub_code_str[] = {
7981 NULL, /* 00h */
7982 "Volume Creation Failed: Data Passed too "
7983 "Large", /* 01h */
7984 "Volume Creation Failed: Duplicate Volumes "
7985 "Attempted", /* 02h */
7986 "Volume Creation Failed: Max Number "
7987 "Supported Volumes Exceeded", /* 03h */
7988 "Volume Creation Failed: DMA Error", /* 04h */
7989 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7990 "Volume Creation Failed: Error Reading "
7991 "MFG Page 4", /* 06h */
7992 "Volume Creation Failed: Creating Internal "
7993 "Structures", /* 07h */
7994 NULL, /* 08h */
7995 NULL, /* 09h */
7996 NULL, /* 0Ah */
7997 NULL, /* 0Bh */
7998 NULL, /* 0Ch */
7999 NULL, /* 0Dh */
8000 NULL, /* 0Eh */
8001 NULL, /* 0Fh */
8002 "Activation failed: Already Active Volume", /* 10h */
8003 "Activation failed: Unsupported Volume Type", /* 11h */
8004 "Activation failed: Too Many Active Volumes", /* 12h */
8005 "Activation failed: Volume ID in Use", /* 13h */
8006 "Activation failed: Reported Failure", /* 14h */
8007 "Activation failed: Importing a Volume", /* 15h */
8008 NULL, /* 16h */
8009 NULL, /* 17h */
8010 NULL, /* 18h */
8011 NULL, /* 19h */
8012 NULL, /* 1Ah */
8013 NULL, /* 1Bh */
8014 NULL, /* 1Ch */
8015 NULL, /* 1Dh */
8016 NULL, /* 1Eh */
8017 NULL, /* 1Fh */
8018 "Phys Disk failed: Too Many Phys Disks", /* 20h */
8019 "Phys Disk failed: Data Passed too Large", /* 21h */
8020 "Phys Disk failed: DMA Error", /* 22h */
8021 "Phys Disk failed: Invalid <channel:id>", /* 23h */
8022 "Phys Disk failed: Creating Phys Disk Config "
8023 "Page", /* 24h */
8024 NULL, /* 25h */
8025 NULL, /* 26h */
8026 NULL, /* 27h */
8027 NULL, /* 28h */
8028 NULL, /* 29h */
8029 NULL, /* 2Ah */
8030 NULL, /* 2Bh */
8031 NULL, /* 2Ch */
8032 NULL, /* 2Dh */
8033 NULL, /* 2Eh */
8034 NULL, /* 2Fh */
8035 "Compatibility Error: IR Disabled", /* 30h */
8036 "Compatibility Error: Inquiry Command Failed", /* 31h */
8037 "Compatibility Error: Device not Direct Access "
8038 "Device ", /* 32h */
8039 "Compatibility Error: Removable Device Found", /* 33h */
8040 "Compatibility Error: Device SCSI Version not "
8041 "2 or Higher", /* 34h */
8042 "Compatibility Error: SATA Device, 48 BIT LBA "
8043 "not Supported", /* 35h */
8044 "Compatibility Error: Device doesn't have "
8045 "512 Byte Block Sizes", /* 36h */
8046 "Compatibility Error: Volume Type Check Failed", /* 37h */
8047 "Compatibility Error: Volume Type is "
8048 "Unsupported by FW", /* 38h */
8049 "Compatibility Error: Disk Drive too Small for "
8050 "use in Volume", /* 39h */
8051 "Compatibility Error: Phys Disk for Create "
8052 "Volume not Found", /* 3Ah */
8053 "Compatibility Error: Too Many or too Few "
8054 "Disks for Volume Type", /* 3Bh */
8055 "Compatibility Error: Disk stripe Sizes "
8056 "Must be 64KB", /* 3Ch */
8057 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
8060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8062 * mpt_sas_log_info - Log information returned from SAS IOC.
8063 * @ioc: Pointer to MPT_ADAPTER structure
8064 * @log_info: U32 LogInfo reply word from the IOC
8065 * @cb_idx: callback function's handle
8067 * Refer to lsi/mpi_log_sas.h.
8069 static void
8070 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx)
8072 union loginfo_type {
8073 u32 loginfo;
8074 struct {
8075 u32 subcode:16;
8076 u32 code:8;
8077 u32 originator:4;
8078 u32 bus_type:4;
8079 }dw;
8081 union loginfo_type sas_loginfo;
8082 char *originator_desc = NULL;
8083 char *code_desc = NULL;
8084 char *sub_code_desc = NULL;
8086 sas_loginfo.loginfo = log_info;
8087 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
8088 (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
8089 return;
8091 originator_desc = originator_str[sas_loginfo.dw.originator];
8093 switch (sas_loginfo.dw.originator) {
8095 case 0: /* IOP */
8096 if (sas_loginfo.dw.code <
8097 ARRAY_SIZE(iop_code_str))
8098 code_desc = iop_code_str[sas_loginfo.dw.code];
8099 break;
8100 case 1: /* PL */
8101 if (sas_loginfo.dw.code <
8102 ARRAY_SIZE(pl_code_str))
8103 code_desc = pl_code_str[sas_loginfo.dw.code];
8104 break;
8105 case 2: /* IR */
8106 if (sas_loginfo.dw.code >=
8107 ARRAY_SIZE(ir_code_str))
8108 break;
8109 code_desc = ir_code_str[sas_loginfo.dw.code];
8110 if (sas_loginfo.dw.subcode >=
8111 ARRAY_SIZE(raid_sub_code_str))
8112 break;
8113 if (sas_loginfo.dw.code == 0)
8114 sub_code_desc =
8115 raid_sub_code_str[sas_loginfo.dw.subcode];
8116 break;
8117 default:
8118 return;
8121 if (sub_code_desc != NULL)
8122 printk(MYIOC_s_INFO_FMT
8123 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
8124 " SubCode={%s} cb_idx %s\n",
8125 ioc->name, log_info, originator_desc, code_desc,
8126 sub_code_desc, MptCallbacksName[cb_idx]);
8127 else if (code_desc != NULL)
8128 printk(MYIOC_s_INFO_FMT
8129 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
8130 " SubCode(0x%04x) cb_idx %s\n",
8131 ioc->name, log_info, originator_desc, code_desc,
8132 sas_loginfo.dw.subcode, MptCallbacksName[cb_idx]);
8133 else
8134 printk(MYIOC_s_INFO_FMT
8135 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
8136 " SubCode(0x%04x) cb_idx %s\n",
8137 ioc->name, log_info, originator_desc,
8138 sas_loginfo.dw.code, sas_loginfo.dw.subcode,
8139 MptCallbacksName[cb_idx]);
8142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8144 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
8145 * @ioc: Pointer to MPT_ADAPTER structure
8146 * @ioc_status: U32 IOCStatus word from IOC
8147 * @mf: Pointer to MPT request frame
8149 * Refer to lsi/mpi.h.
8151 static void
8152 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8154 Config_t *pReq = (Config_t *)mf;
8155 char extend_desc[EVENT_DESCR_STR_SZ];
8156 char *desc = NULL;
8157 u32 form;
8158 u8 page_type;
8160 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
8161 page_type = pReq->ExtPageType;
8162 else
8163 page_type = pReq->Header.PageType;
8166 * ignore invalid page messages for GET_NEXT_HANDLE
8168 form = le32_to_cpu(pReq->PageAddress);
8169 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
8170 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
8171 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
8172 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
8173 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
8174 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
8175 return;
8177 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
8178 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
8179 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
8180 return;
8183 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
8184 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
8185 page_type, pReq->Header.PageNumber, pReq->Action, form);
8187 switch (ioc_status) {
8189 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8190 desc = "Config Page Invalid Action";
8191 break;
8193 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
8194 desc = "Config Page Invalid Type";
8195 break;
8197 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
8198 desc = "Config Page Invalid Page";
8199 break;
8201 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
8202 desc = "Config Page Invalid Data";
8203 break;
8205 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
8206 desc = "Config Page No Defaults";
8207 break;
8209 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
8210 desc = "Config Page Can't Commit";
8211 break;
8214 if (!desc)
8215 return;
8217 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
8218 ioc->name, ioc_status, desc, extend_desc));
8222 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
8223 * @ioc: Pointer to MPT_ADAPTER structure
8224 * @ioc_status: U32 IOCStatus word from IOC
8225 * @mf: Pointer to MPT request frame
8227 * Refer to lsi/mpi.h.
8229 static void
8230 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8232 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
8233 char *desc = NULL;
8235 switch (status) {
8237 /****************************************************************************/
8238 /* Common IOCStatus values for all replies */
8239 /****************************************************************************/
8241 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
8242 desc = "Invalid Function";
8243 break;
8245 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
8246 desc = "Busy";
8247 break;
8249 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
8250 desc = "Invalid SGL";
8251 break;
8253 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
8254 desc = "Internal Error";
8255 break;
8257 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
8258 desc = "Reserved";
8259 break;
8261 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
8262 desc = "Insufficient Resources";
8263 break;
8265 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
8266 desc = "Invalid Field";
8267 break;
8269 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
8270 desc = "Invalid State";
8271 break;
8273 /****************************************************************************/
8274 /* Config IOCStatus values */
8275 /****************************************************************************/
8277 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8278 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
8279 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
8280 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
8281 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
8282 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
8283 mpt_iocstatus_info_config(ioc, status, mf);
8284 break;
8286 /****************************************************************************/
8287 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
8288 /* */
8289 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
8290 /* */
8291 /****************************************************************************/
8293 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
8294 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
8295 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
8296 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
8297 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
8298 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
8299 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
8300 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
8301 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
8302 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
8303 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
8304 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
8305 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
8306 break;
8308 /****************************************************************************/
8309 /* SCSI Target values */
8310 /****************************************************************************/
8312 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
8313 desc = "Target: Priority IO";
8314 break;
8316 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
8317 desc = "Target: Invalid Port";
8318 break;
8320 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
8321 desc = "Target Invalid IO Index:";
8322 break;
8324 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
8325 desc = "Target: Aborted";
8326 break;
8328 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
8329 desc = "Target: No Conn Retryable";
8330 break;
8332 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
8333 desc = "Target: No Connection";
8334 break;
8336 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
8337 desc = "Target: Transfer Count Mismatch";
8338 break;
8340 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
8341 desc = "Target: STS Data not Sent";
8342 break;
8344 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
8345 desc = "Target: Data Offset Error";
8346 break;
8348 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
8349 desc = "Target: Too Much Write Data";
8350 break;
8352 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
8353 desc = "Target: IU Too Short";
8354 break;
8356 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
8357 desc = "Target: ACK NAK Timeout";
8358 break;
8360 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
8361 desc = "Target: Nak Received";
8362 break;
8364 /****************************************************************************/
8365 /* Fibre Channel Direct Access values */
8366 /****************************************************************************/
8368 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
8369 desc = "FC: Aborted";
8370 break;
8372 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
8373 desc = "FC: RX ID Invalid";
8374 break;
8376 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
8377 desc = "FC: DID Invalid";
8378 break;
8380 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
8381 desc = "FC: Node Logged Out";
8382 break;
8384 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
8385 desc = "FC: Exchange Canceled";
8386 break;
8388 /****************************************************************************/
8389 /* LAN values */
8390 /****************************************************************************/
8392 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
8393 desc = "LAN: Device not Found";
8394 break;
8396 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
8397 desc = "LAN: Device Failure";
8398 break;
8400 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
8401 desc = "LAN: Transmit Error";
8402 break;
8404 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
8405 desc = "LAN: Transmit Aborted";
8406 break;
8408 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
8409 desc = "LAN: Receive Error";
8410 break;
8412 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
8413 desc = "LAN: Receive Aborted";
8414 break;
8416 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
8417 desc = "LAN: Partial Packet";
8418 break;
8420 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
8421 desc = "LAN: Canceled";
8422 break;
8424 /****************************************************************************/
8425 /* Serial Attached SCSI values */
8426 /****************************************************************************/
8428 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
8429 desc = "SAS: SMP Request Failed";
8430 break;
8432 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
8433 desc = "SAS: SMP Data Overrun";
8434 break;
8436 default:
8437 desc = "Others";
8438 break;
8441 if (!desc)
8442 return;
8444 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
8445 ioc->name, status, desc));
8448 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8449 EXPORT_SYMBOL(mpt_attach);
8450 EXPORT_SYMBOL(mpt_detach);
8451 #ifdef CONFIG_PM
8452 EXPORT_SYMBOL(mpt_resume);
8453 EXPORT_SYMBOL(mpt_suspend);
8454 #endif
8455 EXPORT_SYMBOL(ioc_list);
8456 EXPORT_SYMBOL(mpt_register);
8457 EXPORT_SYMBOL(mpt_deregister);
8458 EXPORT_SYMBOL(mpt_event_register);
8459 EXPORT_SYMBOL(mpt_event_deregister);
8460 EXPORT_SYMBOL(mpt_reset_register);
8461 EXPORT_SYMBOL(mpt_reset_deregister);
8462 EXPORT_SYMBOL(mpt_device_driver_register);
8463 EXPORT_SYMBOL(mpt_device_driver_deregister);
8464 EXPORT_SYMBOL(mpt_get_msg_frame);
8465 EXPORT_SYMBOL(mpt_put_msg_frame);
8466 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
8467 EXPORT_SYMBOL(mpt_free_msg_frame);
8468 EXPORT_SYMBOL(mpt_send_handshake_request);
8469 EXPORT_SYMBOL(mpt_verify_adapter);
8470 EXPORT_SYMBOL(mpt_GetIocState);
8471 EXPORT_SYMBOL(mpt_print_ioc_summary);
8472 EXPORT_SYMBOL(mpt_HardResetHandler);
8473 EXPORT_SYMBOL(mpt_config);
8474 EXPORT_SYMBOL(mpt_findImVolumes);
8475 EXPORT_SYMBOL(mpt_alloc_fw_memory);
8476 EXPORT_SYMBOL(mpt_free_fw_memory);
8477 EXPORT_SYMBOL(mptbase_sas_persist_operation);
8478 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
8480 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8482 * fusion_init - Fusion MPT base driver initialization routine.
8484 * Returns 0 for success, non-zero for failure.
8486 static int __init
8487 fusion_init(void)
8489 u8 cb_idx;
8491 show_mptmod_ver(my_NAME, my_VERSION);
8492 printk(KERN_INFO COPYRIGHT "\n");
8494 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
8495 MptCallbacks[cb_idx] = NULL;
8496 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
8497 MptEvHandlers[cb_idx] = NULL;
8498 MptResetHandlers[cb_idx] = NULL;
8501 /* Register ourselves (mptbase) in order to facilitate
8502 * EventNotification handling.
8504 mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER,
8505 "mptbase_reply");
8507 /* Register for hard reset handling callbacks.
8509 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
8511 #ifdef CONFIG_PROC_FS
8512 (void) procmpt_create();
8513 #endif
8514 return 0;
8517 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8519 * fusion_exit - Perform driver unload cleanup.
8521 * This routine frees all resources associated with each MPT adapter
8522 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
8524 static void __exit
8525 fusion_exit(void)
8528 mpt_reset_deregister(mpt_base_index);
8530 #ifdef CONFIG_PROC_FS
8531 procmpt_destroy();
8532 #endif
8535 module_init(fusion_init);
8536 module_exit(fusion_exit);