GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / message / fusion / mptbase.c
blob956887dd9dc5f53e0f88d9c89752cdf1232bf74e
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 <asm/io.h>
63 #ifdef CONFIG_MTRR
64 #include <asm/mtrr.h>
65 #endif
67 #include "mptbase.h"
68 #include "lsi/mpi_log_fc.h"
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT base driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptbase"
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 MODULE_VERSION(my_VERSION);
81 * cmd line parameters
84 static int mpt_msi_enable_spi;
85 module_param(mpt_msi_enable_spi, int, 0);
86 MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI \
87 controllers (default=0)");
89 static int mpt_msi_enable_fc;
90 module_param(mpt_msi_enable_fc, int, 0);
91 MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \
92 controllers (default=0)");
94 static int mpt_msi_enable_sas;
95 module_param(mpt_msi_enable_sas, int, 0);
96 MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \
97 controllers (default=0)");
100 static int mpt_channel_mapping;
101 module_param(mpt_channel_mapping, int, 0);
102 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
104 static int mpt_debug_level;
105 static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
106 module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
107 &mpt_debug_level, 0600);
108 MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \
109 - (default=0)");
111 int mpt_fwfault_debug;
112 EXPORT_SYMBOL(mpt_fwfault_debug);
113 module_param(mpt_fwfault_debug, int, 0600);
114 MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault"
115 " and halt Firmware on fault - (default=0)");
118 static char MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS][50];
120 #ifdef MFCNT
121 static int mfcounter = 0;
122 #define PRINT_MF_COUNT 20000
123 #endif
125 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
127 * Public data...
130 #define WHOINIT_UNKNOWN 0xAA
132 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
134 * Private data...
136 /* Adapter link list */
137 LIST_HEAD(ioc_list);
138 /* Callback lookup table */
139 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
140 /* Protocol driver class lookup table */
141 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
142 /* Event handler lookup table */
143 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
144 /* Reset handler lookup table */
145 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
146 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
148 #ifdef CONFIG_PROC_FS
149 static struct proc_dir_entry *mpt_proc_root_dir;
150 #endif
153 * Driver Callback Index's
155 static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
156 static u8 last_drv_idx;
158 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
160 * Forward protos...
162 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
163 static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
164 MPT_FRAME_HDR *reply);
165 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
166 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
167 int sleepFlag);
168 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
169 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
170 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
171 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
173 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
174 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
175 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
176 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
177 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
178 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
179 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
180 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
181 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
182 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
183 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
184 static int PrimeIocFifos(MPT_ADAPTER *ioc);
185 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
186 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
187 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
188 static int GetLanConfigPages(MPT_ADAPTER *ioc);
189 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
190 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
191 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
192 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
193 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
194 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
195 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
196 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch,
197 int sleepFlag);
198 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
199 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
200 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
202 #ifdef CONFIG_PROC_FS
203 static const struct file_operations mpt_summary_proc_fops;
204 static const struct file_operations mpt_version_proc_fops;
205 static const struct file_operations mpt_iocinfo_proc_fops;
206 #endif
207 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
209 static int ProcessEventNotification(MPT_ADAPTER *ioc,
210 EventNotificationReply_t *evReply, int *evHandlers);
211 static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
212 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
213 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
214 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info , u8 cb_idx);
215 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
216 static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
218 /* module entry point */
219 static int __init fusion_init (void);
220 static void __exit fusion_exit (void);
222 #define CHIPREG_READ32(addr) readl_relaxed(addr)
223 #define CHIPREG_READ32_dmasync(addr) readl(addr)
224 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
225 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
226 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
228 static void
229 pci_disable_io_access(struct pci_dev *pdev)
231 u16 command_reg;
233 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
234 command_reg &= ~1;
235 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
238 static void
239 pci_enable_io_access(struct pci_dev *pdev)
241 u16 command_reg;
243 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
244 command_reg |= 1;
245 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
248 static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
250 int ret = param_set_int(val, kp);
251 MPT_ADAPTER *ioc;
253 if (ret)
254 return ret;
256 list_for_each_entry(ioc, &ioc_list, list)
257 ioc->debug_level = mpt_debug_level;
258 return 0;
262 * mpt_get_cb_idx - obtain cb_idx for registered driver
263 * @dclass: class driver enum
265 * Returns cb_idx, or zero means it wasn't found
267 static u8
268 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
270 u8 cb_idx;
272 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
273 if (MptDriverClass[cb_idx] == dclass)
274 return cb_idx;
275 return 0;
279 * mpt_is_discovery_complete - determine if discovery has completed
280 * @ioc: per adatper instance
282 * Returns 1 when discovery completed, else zero.
284 static int
285 mpt_is_discovery_complete(MPT_ADAPTER *ioc)
287 ConfigExtendedPageHeader_t hdr;
288 CONFIGPARMS cfg;
289 SasIOUnitPage0_t *buffer;
290 dma_addr_t dma_handle;
291 int rc = 0;
293 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
294 memset(&cfg, 0, sizeof(CONFIGPARMS));
295 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
296 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
297 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
298 cfg.cfghdr.ehdr = &hdr;
299 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
301 if ((mpt_config(ioc, &cfg)))
302 goto out;
303 if (!hdr.ExtPageLength)
304 goto out;
306 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
307 &dma_handle);
308 if (!buffer)
309 goto out;
311 cfg.physAddr = dma_handle;
312 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
314 if ((mpt_config(ioc, &cfg)))
315 goto out_free_consistent;
317 if (!(buffer->PhyData[0].PortFlags &
318 MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS))
319 rc = 1;
321 out_free_consistent:
322 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
323 buffer, dma_handle);
324 out:
325 return rc;
329 * mpt_fault_reset_work - work performed on workq after ioc fault
330 * @work: input argument, used to derive ioc
333 static void
334 mpt_fault_reset_work(struct work_struct *work)
336 MPT_ADAPTER *ioc =
337 container_of(work, MPT_ADAPTER, fault_reset_work.work);
338 u32 ioc_raw_state;
339 int rc;
340 unsigned long flags;
342 if (ioc->ioc_reset_in_progress || !ioc->active)
343 goto out;
345 ioc_raw_state = mpt_GetIocState(ioc, 0);
346 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
347 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
348 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
349 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
350 ioc->name, __func__);
351 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
352 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
353 __func__, (rc == 0) ? "success" : "failed");
354 ioc_raw_state = mpt_GetIocState(ioc, 0);
355 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
356 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
357 "reset (%04xh)\n", ioc->name, ioc_raw_state &
358 MPI_DOORBELL_DATA_MASK);
359 } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) {
360 if ((mpt_is_discovery_complete(ioc))) {
361 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing "
362 "discovery_quiesce_io flag\n", ioc->name));
363 ioc->sas_discovery_quiesce_io = 0;
367 out:
369 * Take turns polling alternate controller
371 if (ioc->alt_ioc)
372 ioc = ioc->alt_ioc;
374 /* rearm the timer */
375 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
376 if (ioc->reset_work_q)
377 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
378 msecs_to_jiffies(MPT_POLLING_INTERVAL));
379 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
384 * Process turbo (context) reply...
386 static void
387 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
389 MPT_FRAME_HDR *mf = NULL;
390 MPT_FRAME_HDR *mr = NULL;
391 u16 req_idx = 0;
392 u8 cb_idx;
394 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
395 ioc->name, pa));
397 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
398 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
399 req_idx = pa & 0x0000FFFF;
400 cb_idx = (pa & 0x00FF0000) >> 16;
401 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
402 break;
403 case MPI_CONTEXT_REPLY_TYPE_LAN:
404 cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
406 * Blind set of mf to NULL here was fatal
407 * after lan_reply says "freeme"
408 * Fix sort of combined with an optimization here;
409 * added explicit check for case where lan_reply
410 * was just returning 1 and doing nothing else.
411 * For this case skip the callback, but set up
412 * proper mf value first here:-)
414 if ((pa & 0x58000000) == 0x58000000) {
415 req_idx = pa & 0x0000FFFF;
416 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
417 mpt_free_msg_frame(ioc, mf);
418 mb();
419 return;
420 break;
422 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
423 break;
424 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
425 cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
426 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
427 break;
428 default:
429 cb_idx = 0;
430 BUG();
433 /* Check for (valid) IO callback! */
434 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
435 MptCallbacks[cb_idx] == NULL) {
436 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
437 __func__, ioc->name, cb_idx);
438 goto out;
441 if (MptCallbacks[cb_idx](ioc, mf, mr))
442 mpt_free_msg_frame(ioc, mf);
443 out:
444 mb();
447 static void
448 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
450 MPT_FRAME_HDR *mf;
451 MPT_FRAME_HDR *mr;
452 u16 req_idx;
453 u8 cb_idx;
454 int freeme;
456 u32 reply_dma_low;
457 u16 ioc_stat;
459 /* non-TURBO reply! Hmmm, something may be up...
460 * Newest turbo reply mechanism; get address
461 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
464 /* Map DMA address of reply header to cpu address.
465 * pa is 32 bits - but the dma address may be 32 or 64 bits
466 * get offset based only only the low addresses
469 reply_dma_low = (pa <<= 1);
470 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
471 (reply_dma_low - ioc->reply_frames_low_dma));
473 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
474 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
475 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
477 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
478 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
479 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
481 /* Check/log IOC log info
483 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
484 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
485 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
486 if (ioc->bus_type == FC)
487 mpt_fc_log_info(ioc, log_info);
488 else if (ioc->bus_type == SPI)
489 mpt_spi_log_info(ioc, log_info);
490 else if (ioc->bus_type == SAS)
491 mpt_sas_log_info(ioc, log_info, cb_idx);
494 if (ioc_stat & MPI_IOCSTATUS_MASK)
495 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
497 /* Check for (valid) IO callback! */
498 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
499 MptCallbacks[cb_idx] == NULL) {
500 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
501 __func__, ioc->name, cb_idx);
502 freeme = 0;
503 goto out;
506 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
508 out:
509 /* Flush (non-TURBO) reply with a WRITE! */
510 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
512 if (freeme)
513 mpt_free_msg_frame(ioc, mf);
514 mb();
517 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
519 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
520 * @irq: irq number (not used)
521 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
523 * This routine is registered via the request_irq() kernel API call,
524 * and handles all interrupts generated from a specific MPT adapter
525 * (also referred to as a IO Controller or IOC).
526 * This routine must clear the interrupt from the adapter and does
527 * so by reading the reply FIFO. Multiple replies may be processed
528 * per single call to this routine.
530 * This routine handles register-level access of the adapter but
531 * dispatches (calls) a protocol-specific callback routine to handle
532 * the protocol-specific details of the MPT request completion.
534 static irqreturn_t
535 mpt_interrupt(int irq, void *bus_id)
537 MPT_ADAPTER *ioc = bus_id;
538 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
540 if (pa == 0xFFFFFFFF)
541 return IRQ_NONE;
544 * Drain the reply FIFO!
546 do {
547 if (pa & MPI_ADDRESS_REPLY_A_BIT)
548 mpt_reply(ioc, pa);
549 else
550 mpt_turbo_reply(ioc, pa);
551 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
552 } while (pa != 0xFFFFFFFF);
554 return IRQ_HANDLED;
557 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
559 * mptbase_reply - MPT base driver's callback routine
560 * @ioc: Pointer to MPT_ADAPTER structure
561 * @req: Pointer to original MPT request frame
562 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
564 * MPT base driver's callback routine; all base driver
565 * "internal" request/reply processing is routed here.
566 * Currently used for EventNotification and EventAck handling.
568 * Returns 1 indicating original alloc'd request frame ptr
569 * should be freed, or 0 if it shouldn't.
571 static int
572 mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
574 EventNotificationReply_t *pEventReply;
575 u8 event;
576 int evHandlers;
577 int freereq = 1;
579 switch (reply->u.hdr.Function) {
580 case MPI_FUNCTION_EVENT_NOTIFICATION:
581 pEventReply = (EventNotificationReply_t *)reply;
582 evHandlers = 0;
583 ProcessEventNotification(ioc, pEventReply, &evHandlers);
584 event = le32_to_cpu(pEventReply->Event) & 0xFF;
585 if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
586 freereq = 0;
587 if (event != MPI_EVENT_EVENT_CHANGE)
588 break;
589 case MPI_FUNCTION_CONFIG:
590 case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
591 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
592 if (reply) {
593 ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
594 memcpy(ioc->mptbase_cmds.reply, reply,
595 min(MPT_DEFAULT_FRAME_SIZE,
596 4 * reply->u.reply.MsgLength));
598 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
599 ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
600 complete(&ioc->mptbase_cmds.done);
601 } else
602 freereq = 0;
603 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF)
604 freereq = 1;
605 break;
606 case MPI_FUNCTION_EVENT_ACK:
607 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
608 "EventAck reply received\n", ioc->name));
609 break;
610 default:
611 printk(MYIOC_s_ERR_FMT
612 "Unexpected msg function (=%02Xh) reply received!\n",
613 ioc->name, reply->u.hdr.Function);
614 break;
618 * Conditionally tell caller to free the original
619 * EventNotification/EventAck/unexpected request frame!
621 return freereq;
624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
626 * mpt_register - Register protocol-specific main callback handler.
627 * @cbfunc: callback function pointer
628 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
629 * @func_name: call function's name
631 * This routine is called by a protocol-specific driver (SCSI host,
632 * LAN, SCSI target) to register its reply callback routine. Each
633 * protocol-specific driver must do this before it will be able to
634 * use any IOC resources, such as obtaining request frames.
636 * NOTES: The SCSI protocol driver currently calls this routine thrice
637 * in order to register separate callbacks; one for "normal" SCSI IO;
638 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
640 * Returns u8 valued "handle" in the range (and S.O.D. order)
641 * {N,...,7,6,5,...,1} if successful.
642 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
643 * considered an error by the caller.
646 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name)
648 u8 cb_idx;
649 last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
652 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
653 * (slot/handle 0 is reserved!)
655 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
656 if (MptCallbacks[cb_idx] == NULL) {
657 MptCallbacks[cb_idx] = cbfunc;
658 MptDriverClass[cb_idx] = dclass;
659 MptEvHandlers[cb_idx] = NULL;
660 last_drv_idx = cb_idx;
661 memcpy(MptCallbacksName[cb_idx], func_name,
662 strlen(func_name) > 50 ? 50 : strlen(func_name));
663 break;
667 return last_drv_idx;
670 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
672 * mpt_deregister - Deregister a protocol drivers resources.
673 * @cb_idx: previously registered callback handle
675 * Each protocol-specific driver should call this routine when its
676 * module is unloaded.
678 void
679 mpt_deregister(u8 cb_idx)
681 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
682 MptCallbacks[cb_idx] = NULL;
683 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
684 MptEvHandlers[cb_idx] = NULL;
686 last_drv_idx++;
690 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
692 * mpt_event_register - Register protocol-specific event callback handler.
693 * @cb_idx: previously registered (via mpt_register) callback handle
694 * @ev_cbfunc: callback function
696 * This routine can be called by one or more protocol-specific drivers
697 * if/when they choose to be notified of MPT events.
699 * Returns 0 for success.
702 mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
704 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
705 return -1;
707 MptEvHandlers[cb_idx] = ev_cbfunc;
708 return 0;
711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
713 * mpt_event_deregister - Deregister protocol-specific event callback handler
714 * @cb_idx: previously registered callback handle
716 * Each protocol-specific driver should call this routine
717 * when it does not (or can no longer) handle events,
718 * or when its module is unloaded.
720 void
721 mpt_event_deregister(u8 cb_idx)
723 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
724 return;
726 MptEvHandlers[cb_idx] = NULL;
729 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
731 * mpt_reset_register - Register protocol-specific IOC reset handler.
732 * @cb_idx: previously registered (via mpt_register) callback handle
733 * @reset_func: reset function
735 * This routine can be called by one or more protocol-specific drivers
736 * if/when they choose to be notified of IOC resets.
738 * Returns 0 for success.
741 mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
743 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
744 return -1;
746 MptResetHandlers[cb_idx] = reset_func;
747 return 0;
750 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
752 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
753 * @cb_idx: previously registered callback handle
755 * Each protocol-specific driver should call this routine
756 * when it does not (or can no longer) handle IOC reset handling,
757 * or when its module is unloaded.
759 void
760 mpt_reset_deregister(u8 cb_idx)
762 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
763 return;
765 MptResetHandlers[cb_idx] = NULL;
768 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
770 * mpt_device_driver_register - Register device driver hooks
771 * @dd_cbfunc: driver callbacks struct
772 * @cb_idx: MPT protocol driver index
775 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
777 MPT_ADAPTER *ioc;
778 const struct pci_device_id *id;
780 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
781 return -EINVAL;
783 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
785 /* call per pci device probe entry point */
786 list_for_each_entry(ioc, &ioc_list, list) {
787 id = ioc->pcidev->driver ?
788 ioc->pcidev->driver->id_table : NULL;
789 if (dd_cbfunc->probe)
790 dd_cbfunc->probe(ioc->pcidev, id);
793 return 0;
796 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
798 * mpt_device_driver_deregister - DeRegister device driver hooks
799 * @cb_idx: MPT protocol driver index
801 void
802 mpt_device_driver_deregister(u8 cb_idx)
804 struct mpt_pci_driver *dd_cbfunc;
805 MPT_ADAPTER *ioc;
807 if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
808 return;
810 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
812 list_for_each_entry(ioc, &ioc_list, list) {
813 if (dd_cbfunc->remove)
814 dd_cbfunc->remove(ioc->pcidev);
817 MptDeviceDriverHandlers[cb_idx] = NULL;
821 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
823 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
824 * @cb_idx: Handle of registered MPT protocol driver
825 * @ioc: Pointer to MPT adapter structure
827 * Obtain an MPT request frame from the pool (of 1024) that are
828 * allocated per MPT adapter.
830 * Returns pointer to a MPT request frame or %NULL if none are available
831 * or IOC is not active.
833 MPT_FRAME_HDR*
834 mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
836 MPT_FRAME_HDR *mf;
837 unsigned long flags;
838 u16 req_idx; /* Request index */
840 /* validate handle and ioc identifier */
842 #ifdef MFCNT
843 if (!ioc->active)
844 printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
845 "returning NULL!\n", ioc->name);
846 #endif
848 /* If interrupts are not attached, do not return a request frame */
849 if (!ioc->active)
850 return NULL;
852 spin_lock_irqsave(&ioc->FreeQlock, flags);
853 if (!list_empty(&ioc->FreeQ)) {
854 int req_offset;
856 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
857 u.frame.linkage.list);
858 list_del(&mf->u.frame.linkage.list);
859 mf->u.frame.linkage.arg1 = 0;
860 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
861 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
862 /* u16! */
863 req_idx = req_offset / ioc->req_sz;
864 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
865 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
866 /* Default, will be changed if necessary in SG generation */
867 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
868 #ifdef MFCNT
869 ioc->mfcnt++;
870 #endif
872 else
873 mf = NULL;
874 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
876 #ifdef MFCNT
877 if (mf == NULL)
878 printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
879 "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
880 ioc->req_depth);
881 mfcounter++;
882 if (mfcounter == PRINT_MF_COUNT)
883 printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
884 ioc->mfcnt, ioc->req_depth);
885 #endif
887 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
888 ioc->name, cb_idx, ioc->id, mf));
889 return mf;
892 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
894 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
895 * @cb_idx: Handle of registered MPT protocol driver
896 * @ioc: Pointer to MPT adapter structure
897 * @mf: Pointer to MPT request frame
899 * This routine posts an MPT request frame to the request post FIFO of a
900 * specific MPT adapter.
902 void
903 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
905 u32 mf_dma_addr;
906 int req_offset;
907 u16 req_idx; /* Request index */
909 /* ensure values are reset properly! */
910 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
911 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
912 /* u16! */
913 req_idx = req_offset / ioc->req_sz;
914 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
915 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
917 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
919 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
920 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
921 "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
922 ioc->RequestNB[req_idx]));
923 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
927 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
928 * @cb_idx: Handle of registered MPT protocol driver
929 * @ioc: Pointer to MPT adapter structure
930 * @mf: Pointer to MPT request frame
932 * Send a protocol-specific MPT request frame to an IOC using
933 * hi-priority request queue.
935 * This routine posts an MPT request frame to the request post FIFO of a
936 * specific MPT adapter.
938 void
939 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
941 u32 mf_dma_addr;
942 int req_offset;
943 u16 req_idx; /* Request index */
945 /* ensure values are reset properly! */
946 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
947 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
948 req_idx = req_offset / ioc->req_sz;
949 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
950 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
952 DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
954 mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
955 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
956 ioc->name, mf_dma_addr, req_idx));
957 CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
960 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
962 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
963 * @ioc: Pointer to MPT adapter structure
964 * @mf: Pointer to MPT request frame
966 * This routine places a MPT request frame back on the MPT adapter's
967 * FreeQ.
969 void
970 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
972 unsigned long flags;
974 /* Put Request back on FreeQ! */
975 spin_lock_irqsave(&ioc->FreeQlock, flags);
976 if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf)
977 goto out;
978 /* signature to know if this mf is freed */
979 mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf);
980 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
981 #ifdef MFCNT
982 ioc->mfcnt--;
983 #endif
984 out:
985 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
988 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
990 * mpt_add_sge - Place a simple 32 bit SGE at address pAddr.
991 * @pAddr: virtual address for SGE
992 * @flagslength: SGE flags and data transfer length
993 * @dma_addr: Physical address
995 * This routine places a MPT request frame back on the MPT adapter's
996 * FreeQ.
998 static void
999 mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1001 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1002 pSge->FlagsLength = cpu_to_le32(flagslength);
1003 pSge->Address = cpu_to_le32(dma_addr);
1007 * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr.
1008 * @pAddr: virtual address for SGE
1009 * @flagslength: SGE flags and data transfer length
1010 * @dma_addr: Physical address
1012 * This routine places a MPT request frame back on the MPT adapter's
1013 * FreeQ.
1015 static void
1016 mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1018 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1019 pSge->Address.Low = cpu_to_le32
1020 (lower_32_bits(dma_addr));
1021 pSge->Address.High = cpu_to_le32
1022 (upper_32_bits(dma_addr));
1023 pSge->FlagsLength = cpu_to_le32
1024 ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1027 static void
1028 mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
1030 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
1031 u32 tmp;
1033 pSge->Address.Low = cpu_to_le32
1034 (lower_32_bits(dma_addr));
1035 tmp = (u32)(upper_32_bits(dma_addr));
1037 if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) {
1038 flagslength |=
1039 MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS);
1040 tmp |= (1<<31);
1041 if (mpt_debug_level & MPT_DEBUG_36GB_MEM)
1042 printk(KERN_DEBUG "1078 P0M2 addressing for "
1043 "addr = 0x%llx len = %d\n",
1044 (unsigned long long)dma_addr,
1045 MPI_SGE_LENGTH(flagslength));
1048 pSge->Address.High = cpu_to_le32(tmp);
1049 pSge->FlagsLength = cpu_to_le32(
1050 (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
1053 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1055 * mpt_add_chain - Place a 32 bit chain SGE at address pAddr.
1056 * @pAddr: virtual address for SGE
1057 * @next: nextChainOffset value (u32's)
1058 * @length: length of next SGL segment
1059 * @dma_addr: Physical address
1062 static void
1063 mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1065 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
1066 pChain->Length = cpu_to_le16(length);
1067 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
1068 pChain->NextChainOffset = next;
1069 pChain->Address = cpu_to_le32(dma_addr);
1072 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1074 * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
1075 * @pAddr: virtual address for SGE
1076 * @next: nextChainOffset value (u32's)
1077 * @length: length of next SGL segment
1078 * @dma_addr: Physical address
1081 static void
1082 mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1084 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1085 u32 tmp = dma_addr & 0xFFFFFFFF;
1087 pChain->Length = cpu_to_le16(length);
1088 pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
1089 MPI_SGE_FLAGS_64_BIT_ADDRESSING);
1091 pChain->NextChainOffset = next;
1093 pChain->Address.Low = cpu_to_le32(tmp);
1094 tmp = (u32)(upper_32_bits(dma_addr));
1095 pChain->Address.High = cpu_to_le32(tmp);
1098 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1100 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1101 * @cb_idx: Handle of registered MPT protocol driver
1102 * @ioc: Pointer to MPT adapter structure
1103 * @reqBytes: Size of the request in bytes
1104 * @req: Pointer to MPT request frame
1105 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1107 * This routine is used exclusively to send MptScsiTaskMgmt
1108 * requests since they are required to be sent via doorbell handshake.
1110 * NOTE: It is the callers responsibility to byte-swap fields in the
1111 * request which are greater than 1 byte in size.
1113 * Returns 0 for success, non-zero for failure.
1116 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1118 int r = 0;
1119 u8 *req_as_bytes;
1120 int ii;
1122 /* State is known to be good upon entering
1123 * this function so issue the bus reset
1124 * request.
1128 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1129 * setting cb_idx/req_idx. But ONLY if this request
1130 * is in proper (pre-alloc'd) request buffer range...
1132 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1133 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1134 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1135 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1136 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1139 /* Make sure there are no doorbells */
1140 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1142 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1143 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1144 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1146 /* Wait for IOC doorbell int */
1147 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1148 return ii;
1151 /* Read doorbell and check for active bit */
1152 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1153 return -5;
1155 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1156 ioc->name, ii));
1158 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1160 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1161 return -2;
1164 /* Send request via doorbell handshake */
1165 req_as_bytes = (u8 *) req;
1166 for (ii = 0; ii < reqBytes/4; ii++) {
1167 u32 word;
1169 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1170 (req_as_bytes[(ii*4) + 1] << 8) |
1171 (req_as_bytes[(ii*4) + 2] << 16) |
1172 (req_as_bytes[(ii*4) + 3] << 24));
1173 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1174 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1175 r = -3;
1176 break;
1180 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1181 r = 0;
1182 else
1183 r = -4;
1185 /* Make sure there are no doorbells */
1186 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1188 return r;
1191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1193 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1194 * @ioc: Pointer to MPT adapter structure
1195 * @access_control_value: define bits below
1196 * @sleepFlag: Specifies whether the process can sleep
1198 * Provides mechanism for the host driver to control the IOC's
1199 * Host Page Buffer access.
1201 * Access Control Value - bits[15:12]
1202 * 0h Reserved
1203 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1204 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1205 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1207 * Returns 0 for success, non-zero for failure.
1210 static int
1211 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1213 int r = 0;
1215 /* return if in use */
1216 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1217 & MPI_DOORBELL_ACTIVE)
1218 return -1;
1220 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1222 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1223 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1224 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1225 (access_control_value<<12)));
1227 /* Wait for IOC to clear Doorbell Status bit */
1228 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1229 return -2;
1230 }else
1231 return 0;
1234 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1236 * mpt_host_page_alloc - allocate system memory for the fw
1237 * @ioc: Pointer to pointer to IOC adapter
1238 * @ioc_init: Pointer to ioc init config page
1240 * If we already allocated memory in past, then resend the same pointer.
1241 * Returns 0 for success, non-zero for failure.
1243 static int
1244 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1246 char *psge;
1247 int flags_length;
1248 u32 host_page_buffer_sz=0;
1250 if(!ioc->HostPageBuffer) {
1252 host_page_buffer_sz =
1253 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1255 if(!host_page_buffer_sz)
1256 return 0; /* fw doesn't need any host buffers */
1258 /* spin till we get enough memory */
1259 while(host_page_buffer_sz > 0) {
1261 if((ioc->HostPageBuffer = pci_alloc_consistent(
1262 ioc->pcidev,
1263 host_page_buffer_sz,
1264 &ioc->HostPageBuffer_dma)) != NULL) {
1266 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1267 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1268 ioc->name, ioc->HostPageBuffer,
1269 (u32)ioc->HostPageBuffer_dma,
1270 host_page_buffer_sz));
1271 ioc->alloc_total += host_page_buffer_sz;
1272 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1273 break;
1276 host_page_buffer_sz -= (4*1024);
1280 if(!ioc->HostPageBuffer) {
1281 printk(MYIOC_s_ERR_FMT
1282 "Failed to alloc memory for host_page_buffer!\n",
1283 ioc->name);
1284 return -999;
1287 psge = (char *)&ioc_init->HostPageBufferSGE;
1288 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1289 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1290 MPI_SGE_FLAGS_HOST_TO_IOC |
1291 MPI_SGE_FLAGS_END_OF_BUFFER;
1292 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1293 flags_length |= ioc->HostPageBuffer_sz;
1294 ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1295 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1297 return 0;
1300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1302 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1303 * @iocid: IOC unique identifier (integer)
1304 * @iocpp: Pointer to pointer to IOC adapter
1306 * Given a unique IOC identifier, set pointer to the associated MPT
1307 * adapter structure.
1309 * Returns iocid and sets iocpp if iocid is found.
1310 * Returns -1 if iocid is not found.
1313 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1315 MPT_ADAPTER *ioc;
1317 list_for_each_entry(ioc,&ioc_list,list) {
1318 if (ioc->id == iocid) {
1319 *iocpp =ioc;
1320 return iocid;
1324 *iocpp = NULL;
1325 return -1;
1329 * mpt_get_product_name - returns product string
1330 * @vendor: pci vendor id
1331 * @device: pci device id
1332 * @revision: pci revision id
1333 * @prod_name: string returned
1335 * Returns product string displayed when driver loads,
1336 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1339 static void
1340 mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1342 char *product_str = NULL;
1344 if (vendor == PCI_VENDOR_ID_BROCADE) {
1345 switch (device)
1347 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1348 switch (revision)
1350 case 0x00:
1351 product_str = "BRE040 A0";
1352 break;
1353 case 0x01:
1354 product_str = "BRE040 A1";
1355 break;
1356 default:
1357 product_str = "BRE040";
1358 break;
1360 break;
1362 goto out;
1365 switch (device)
1367 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1368 product_str = "LSIFC909 B1";
1369 break;
1370 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1371 product_str = "LSIFC919 B0";
1372 break;
1373 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1374 product_str = "LSIFC929 B0";
1375 break;
1376 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1377 if (revision < 0x80)
1378 product_str = "LSIFC919X A0";
1379 else
1380 product_str = "LSIFC919XL A1";
1381 break;
1382 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1383 if (revision < 0x80)
1384 product_str = "LSIFC929X A0";
1385 else
1386 product_str = "LSIFC929XL A1";
1387 break;
1388 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1389 product_str = "LSIFC939X A1";
1390 break;
1391 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1392 product_str = "LSIFC949X A1";
1393 break;
1394 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1395 switch (revision)
1397 case 0x00:
1398 product_str = "LSIFC949E A0";
1399 break;
1400 case 0x01:
1401 product_str = "LSIFC949E A1";
1402 break;
1403 default:
1404 product_str = "LSIFC949E";
1405 break;
1407 break;
1408 case MPI_MANUFACTPAGE_DEVID_53C1030:
1409 switch (revision)
1411 case 0x00:
1412 product_str = "LSI53C1030 A0";
1413 break;
1414 case 0x01:
1415 product_str = "LSI53C1030 B0";
1416 break;
1417 case 0x03:
1418 product_str = "LSI53C1030 B1";
1419 break;
1420 case 0x07:
1421 product_str = "LSI53C1030 B2";
1422 break;
1423 case 0x08:
1424 product_str = "LSI53C1030 C0";
1425 break;
1426 case 0x80:
1427 product_str = "LSI53C1030T A0";
1428 break;
1429 case 0x83:
1430 product_str = "LSI53C1030T A2";
1431 break;
1432 case 0x87:
1433 product_str = "LSI53C1030T A3";
1434 break;
1435 case 0xc1:
1436 product_str = "LSI53C1020A A1";
1437 break;
1438 default:
1439 product_str = "LSI53C1030";
1440 break;
1442 break;
1443 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1444 switch (revision)
1446 case 0x03:
1447 product_str = "LSI53C1035 A2";
1448 break;
1449 case 0x04:
1450 product_str = "LSI53C1035 B0";
1451 break;
1452 default:
1453 product_str = "LSI53C1035";
1454 break;
1456 break;
1457 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1458 switch (revision)
1460 case 0x00:
1461 product_str = "LSISAS1064 A1";
1462 break;
1463 case 0x01:
1464 product_str = "LSISAS1064 A2";
1465 break;
1466 case 0x02:
1467 product_str = "LSISAS1064 A3";
1468 break;
1469 case 0x03:
1470 product_str = "LSISAS1064 A4";
1471 break;
1472 default:
1473 product_str = "LSISAS1064";
1474 break;
1476 break;
1477 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1478 switch (revision)
1480 case 0x00:
1481 product_str = "LSISAS1064E A0";
1482 break;
1483 case 0x01:
1484 product_str = "LSISAS1064E B0";
1485 break;
1486 case 0x02:
1487 product_str = "LSISAS1064E B1";
1488 break;
1489 case 0x04:
1490 product_str = "LSISAS1064E B2";
1491 break;
1492 case 0x08:
1493 product_str = "LSISAS1064E B3";
1494 break;
1495 default:
1496 product_str = "LSISAS1064E";
1497 break;
1499 break;
1500 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1501 switch (revision)
1503 case 0x00:
1504 product_str = "LSISAS1068 A0";
1505 break;
1506 case 0x01:
1507 product_str = "LSISAS1068 B0";
1508 break;
1509 case 0x02:
1510 product_str = "LSISAS1068 B1";
1511 break;
1512 default:
1513 product_str = "LSISAS1068";
1514 break;
1516 break;
1517 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1518 switch (revision)
1520 case 0x00:
1521 product_str = "LSISAS1068E A0";
1522 break;
1523 case 0x01:
1524 product_str = "LSISAS1068E B0";
1525 break;
1526 case 0x02:
1527 product_str = "LSISAS1068E B1";
1528 break;
1529 case 0x04:
1530 product_str = "LSISAS1068E B2";
1531 break;
1532 case 0x08:
1533 product_str = "LSISAS1068E B3";
1534 break;
1535 default:
1536 product_str = "LSISAS1068E";
1537 break;
1539 break;
1540 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1541 switch (revision)
1543 case 0x00:
1544 product_str = "LSISAS1078 A0";
1545 break;
1546 case 0x01:
1547 product_str = "LSISAS1078 B0";
1548 break;
1549 case 0x02:
1550 product_str = "LSISAS1078 C0";
1551 break;
1552 case 0x03:
1553 product_str = "LSISAS1078 C1";
1554 break;
1555 case 0x04:
1556 product_str = "LSISAS1078 C2";
1557 break;
1558 default:
1559 product_str = "LSISAS1078";
1560 break;
1562 break;
1565 out:
1566 if (product_str)
1567 sprintf(prod_name, "%s", product_str);
1571 * mpt_mapresources - map in memory mapped io
1572 * @ioc: Pointer to pointer to IOC adapter
1575 static int
1576 mpt_mapresources(MPT_ADAPTER *ioc)
1578 u8 __iomem *mem;
1579 int ii;
1580 resource_size_t mem_phys;
1581 unsigned long port;
1582 u32 msize;
1583 u32 psize;
1584 u8 revision;
1585 int r = -ENODEV;
1586 struct pci_dev *pdev;
1588 pdev = ioc->pcidev;
1589 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1590 if (pci_enable_device_mem(pdev)) {
1591 printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1592 "failed\n", ioc->name);
1593 return r;
1595 if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1596 printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1597 "MEM failed\n", ioc->name);
1598 return r;
1601 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1603 if (sizeof(dma_addr_t) > 4) {
1604 const uint64_t required_mask = dma_get_required_mask
1605 (&pdev->dev);
1606 if (required_mask > DMA_BIT_MASK(32)
1607 && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1608 && !pci_set_consistent_dma_mask(pdev,
1609 DMA_BIT_MASK(64))) {
1610 ioc->dma_mask = DMA_BIT_MASK(64);
1611 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1612 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1613 ioc->name));
1614 } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1615 && !pci_set_consistent_dma_mask(pdev,
1616 DMA_BIT_MASK(32))) {
1617 ioc->dma_mask = DMA_BIT_MASK(32);
1618 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1619 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1620 ioc->name));
1621 } else {
1622 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1623 ioc->name, pci_name(pdev));
1624 pci_release_selected_regions(pdev, ioc->bars);
1625 return r;
1627 } else {
1628 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1629 && !pci_set_consistent_dma_mask(pdev,
1630 DMA_BIT_MASK(32))) {
1631 ioc->dma_mask = DMA_BIT_MASK(32);
1632 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1633 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1634 ioc->name));
1635 } else {
1636 printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1637 ioc->name, pci_name(pdev));
1638 pci_release_selected_regions(pdev, ioc->bars);
1639 return r;
1643 mem_phys = msize = 0;
1644 port = psize = 0;
1645 for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1646 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1647 if (psize)
1648 continue;
1649 /* Get I/O space! */
1650 port = pci_resource_start(pdev, ii);
1651 psize = pci_resource_len(pdev, ii);
1652 } else {
1653 if (msize)
1654 continue;
1655 /* Get memmap */
1656 mem_phys = pci_resource_start(pdev, ii);
1657 msize = pci_resource_len(pdev, ii);
1660 ioc->mem_size = msize;
1662 mem = NULL;
1663 /* Get logical ptr for PciMem0 space */
1664 /*mem = ioremap(mem_phys, msize);*/
1665 mem = ioremap(mem_phys, msize);
1666 if (mem == NULL) {
1667 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1668 " memory!\n", ioc->name);
1669 pci_release_selected_regions(pdev, ioc->bars);
1670 return -EINVAL;
1672 ioc->memmap = mem;
1673 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
1674 ioc->name, mem, (unsigned long long)mem_phys));
1676 ioc->mem_phys = mem_phys;
1677 ioc->chip = (SYSIF_REGS __iomem *)mem;
1679 /* Save Port IO values in case we need to do downloadboot */
1680 ioc->pio_mem_phys = port;
1681 ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1683 return 0;
1686 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1688 * mpt_attach - Install a PCI intelligent MPT adapter.
1689 * @pdev: Pointer to pci_dev structure
1690 * @id: PCI device ID information
1692 * This routine performs all the steps necessary to bring the IOC of
1693 * a MPT adapter to a OPERATIONAL state. This includes registering
1694 * memory regions, registering the interrupt, and allocating request
1695 * and reply memory pools.
1697 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1698 * MPT adapter.
1700 * Returns 0 for success, non-zero for failure.
1702 * TODO: Add support for polled controllers
1705 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1707 MPT_ADAPTER *ioc;
1708 u8 cb_idx;
1709 int r = -ENODEV;
1710 u8 revision;
1711 u8 pcixcmd;
1712 static int mpt_ids = 0;
1713 #ifdef CONFIG_PROC_FS
1714 struct proc_dir_entry *dent;
1715 #endif
1717 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1718 if (ioc == NULL) {
1719 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1720 return -ENOMEM;
1723 ioc->id = mpt_ids++;
1724 sprintf(ioc->name, "ioc%d", ioc->id);
1725 dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1728 * set initial debug level
1729 * (refer to mptdebug.h)
1732 ioc->debug_level = mpt_debug_level;
1733 if (mpt_debug_level)
1734 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1736 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1738 ioc->pcidev = pdev;
1739 if (mpt_mapresources(ioc)) {
1740 kfree(ioc);
1741 return r;
1745 * Setting up proper handlers for scatter gather handling
1747 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
1748 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
1749 ioc->add_sge = &mpt_add_sge_64bit_1078;
1750 else
1751 ioc->add_sge = &mpt_add_sge_64bit;
1752 ioc->add_chain = &mpt_add_chain_64bit;
1753 ioc->sg_addr_size = 8;
1754 } else {
1755 ioc->add_sge = &mpt_add_sge;
1756 ioc->add_chain = &mpt_add_chain;
1757 ioc->sg_addr_size = 4;
1759 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
1761 ioc->alloc_total = sizeof(MPT_ADAPTER);
1762 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1763 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1766 spin_lock_init(&ioc->taskmgmt_lock);
1767 mutex_init(&ioc->internal_cmds.mutex);
1768 init_completion(&ioc->internal_cmds.done);
1769 mutex_init(&ioc->mptbase_cmds.mutex);
1770 init_completion(&ioc->mptbase_cmds.done);
1771 mutex_init(&ioc->taskmgmt_cmds.mutex);
1772 init_completion(&ioc->taskmgmt_cmds.done);
1774 /* Initialize the event logging.
1776 ioc->eventTypes = 0; /* None */
1777 ioc->eventContext = 0;
1778 ioc->eventLogSize = 0;
1779 ioc->events = NULL;
1781 #ifdef MFCNT
1782 ioc->mfcnt = 0;
1783 #endif
1785 ioc->sh = NULL;
1786 ioc->cached_fw = NULL;
1788 /* Initialize SCSI Config Data structure
1790 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1792 /* Initialize the fc rport list head.
1794 INIT_LIST_HEAD(&ioc->fc_rports);
1796 /* Find lookup slot. */
1797 INIT_LIST_HEAD(&ioc->list);
1800 /* Initialize workqueue */
1801 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1803 snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
1804 "mpt_poll_%d", ioc->id);
1805 ioc->reset_work_q =
1806 create_singlethread_workqueue(ioc->reset_work_q_name);
1807 if (!ioc->reset_work_q) {
1808 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1809 ioc->name);
1810 pci_release_selected_regions(pdev, ioc->bars);
1811 kfree(ioc);
1812 return -ENOMEM;
1815 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1816 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1818 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1819 mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1821 switch (pdev->device)
1823 case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1824 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1825 ioc->errata_flag_1064 = 1;
1826 case MPI_MANUFACTPAGE_DEVICEID_FC909:
1827 case MPI_MANUFACTPAGE_DEVICEID_FC929:
1828 case MPI_MANUFACTPAGE_DEVICEID_FC919:
1829 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1830 ioc->bus_type = FC;
1831 break;
1833 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1834 if (revision < XL_929) {
1835 /* 929X Chip Fix. Set Split transactions level
1836 * for PCIX. Set MOST bits to zero.
1838 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1839 pcixcmd &= 0x8F;
1840 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1841 } else {
1842 /* 929XL Chip Fix. Set MMRBC to 0x08.
1844 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1845 pcixcmd |= 0x08;
1846 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1848 ioc->bus_type = FC;
1849 break;
1851 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1852 /* 919X Chip Fix. Set Split transactions level
1853 * for PCIX. Set MOST bits to zero.
1855 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1856 pcixcmd &= 0x8F;
1857 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1858 ioc->bus_type = FC;
1859 break;
1861 case MPI_MANUFACTPAGE_DEVID_53C1030:
1862 /* 1030 Chip Fix. Disable Split transactions
1863 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1865 if (revision < C0_1030) {
1866 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1867 pcixcmd &= 0x8F;
1868 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1871 case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1872 ioc->bus_type = SPI;
1873 break;
1875 case MPI_MANUFACTPAGE_DEVID_SAS1064:
1876 case MPI_MANUFACTPAGE_DEVID_SAS1068:
1877 ioc->errata_flag_1064 = 1;
1878 ioc->bus_type = SAS;
1879 break;
1881 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1882 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1883 case MPI_MANUFACTPAGE_DEVID_SAS1078:
1884 ioc->bus_type = SAS;
1885 break;
1889 switch (ioc->bus_type) {
1891 case SAS:
1892 ioc->msi_enable = mpt_msi_enable_sas;
1893 break;
1895 case SPI:
1896 ioc->msi_enable = mpt_msi_enable_spi;
1897 break;
1899 case FC:
1900 ioc->msi_enable = mpt_msi_enable_fc;
1901 break;
1903 default:
1904 ioc->msi_enable = 0;
1905 break;
1908 ioc->fw_events_off = 1;
1910 if (ioc->errata_flag_1064)
1911 pci_disable_io_access(pdev);
1913 spin_lock_init(&ioc->FreeQlock);
1915 /* Disable all! */
1916 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1917 ioc->active = 0;
1918 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1920 /* Set IOC ptr in the pcidev's driver data. */
1921 pci_set_drvdata(ioc->pcidev, ioc);
1923 /* Set lookup ptr. */
1924 list_add_tail(&ioc->list, &ioc_list);
1926 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1928 mpt_detect_bound_ports(ioc, pdev);
1930 INIT_LIST_HEAD(&ioc->fw_event_list);
1931 spin_lock_init(&ioc->fw_event_lock);
1932 snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
1933 ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
1935 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1936 CAN_SLEEP)) != 0){
1937 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1938 ioc->name, r);
1940 list_del(&ioc->list);
1941 if (ioc->alt_ioc)
1942 ioc->alt_ioc->alt_ioc = NULL;
1943 iounmap(ioc->memmap);
1944 if (r != -5)
1945 pci_release_selected_regions(pdev, ioc->bars);
1947 destroy_workqueue(ioc->reset_work_q);
1948 ioc->reset_work_q = NULL;
1950 kfree(ioc);
1951 pci_set_drvdata(pdev, NULL);
1952 return r;
1955 /* call per device driver probe entry point */
1956 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1957 if(MptDeviceDriverHandlers[cb_idx] &&
1958 MptDeviceDriverHandlers[cb_idx]->probe) {
1959 MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1963 #ifdef CONFIG_PROC_FS
1965 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1967 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1968 if (dent) {
1969 proc_create_data("info", S_IRUGO, dent, &mpt_iocinfo_proc_fops, ioc);
1970 proc_create_data("summary", S_IRUGO, dent, &mpt_summary_proc_fops, ioc);
1972 #endif
1974 if (!ioc->alt_ioc)
1975 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1976 msecs_to_jiffies(MPT_POLLING_INTERVAL));
1978 return 0;
1981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1983 * mpt_detach - Remove a PCI intelligent MPT adapter.
1984 * @pdev: Pointer to pci_dev structure
1987 void
1988 mpt_detach(struct pci_dev *pdev)
1990 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1991 char pname[32];
1992 u8 cb_idx;
1993 unsigned long flags;
1994 struct workqueue_struct *wq;
1997 * Stop polling ioc for fault condition
1999 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2000 wq = ioc->reset_work_q;
2001 ioc->reset_work_q = NULL;
2002 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2003 cancel_delayed_work(&ioc->fault_reset_work);
2004 destroy_workqueue(wq);
2006 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2007 wq = ioc->fw_event_q;
2008 ioc->fw_event_q = NULL;
2009 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2010 destroy_workqueue(wq);
2012 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
2013 remove_proc_entry(pname, NULL);
2014 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
2015 remove_proc_entry(pname, NULL);
2016 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2017 remove_proc_entry(pname, NULL);
2019 /* call per device driver remove entry point */
2020 for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2021 if(MptDeviceDriverHandlers[cb_idx] &&
2022 MptDeviceDriverHandlers[cb_idx]->remove) {
2023 MptDeviceDriverHandlers[cb_idx]->remove(pdev);
2027 /* Disable interrupts! */
2028 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2030 ioc->active = 0;
2031 synchronize_irq(pdev->irq);
2033 /* Clear any lingering interrupt */
2034 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2036 CHIPREG_READ32(&ioc->chip->IntStatus);
2038 mpt_adapter_dispose(ioc);
2042 /**************************************************************************
2043 * Power Management
2045 #ifdef CONFIG_PM
2046 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2048 * mpt_suspend - Fusion MPT base driver suspend routine.
2049 * @pdev: Pointer to pci_dev structure
2050 * @state: new state to enter
2053 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
2055 u32 device_state;
2056 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2058 device_state = pci_choose_state(pdev, state);
2059 printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
2060 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2061 device_state);
2063 /* put ioc into READY_STATE */
2064 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
2065 printk(MYIOC_s_ERR_FMT
2066 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
2069 /* disable interrupts */
2070 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2071 ioc->active = 0;
2073 /* Clear any lingering interrupt */
2074 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2076 free_irq(ioc->pci_irq, ioc);
2077 if (ioc->msi_enable)
2078 pci_disable_msi(ioc->pcidev);
2079 ioc->pci_irq = -1;
2080 pci_save_state(pdev);
2081 pci_disable_device(pdev);
2082 pci_release_selected_regions(pdev, ioc->bars);
2083 pci_set_power_state(pdev, device_state);
2084 return 0;
2087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2089 * mpt_resume - Fusion MPT base driver resume routine.
2090 * @pdev: Pointer to pci_dev structure
2093 mpt_resume(struct pci_dev *pdev)
2095 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2096 u32 device_state = pdev->current_state;
2097 int recovery_state;
2098 int err;
2100 printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
2101 "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2102 device_state);
2104 pci_set_power_state(pdev, PCI_D0);
2105 pci_enable_wake(pdev, PCI_D0, 0);
2106 pci_restore_state(pdev);
2107 ioc->pcidev = pdev;
2108 err = mpt_mapresources(ioc);
2109 if (err)
2110 return err;
2112 if (ioc->dma_mask == DMA_BIT_MASK(64)) {
2113 if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
2114 ioc->add_sge = &mpt_add_sge_64bit_1078;
2115 else
2116 ioc->add_sge = &mpt_add_sge_64bit;
2117 ioc->add_chain = &mpt_add_chain_64bit;
2118 ioc->sg_addr_size = 8;
2119 } else {
2121 ioc->add_sge = &mpt_add_sge;
2122 ioc->add_chain = &mpt_add_chain;
2123 ioc->sg_addr_size = 4;
2125 ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
2127 printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
2128 ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
2129 CHIPREG_READ32(&ioc->chip->Doorbell));
2131 if (ioc->bus_type == SAS && (pdev->device ==
2132 MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2133 MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2134 if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2135 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2136 ioc->name);
2137 goto out;
2141 /* bring ioc to operational state */
2142 printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2143 recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2144 CAN_SLEEP);
2145 if (recovery_state != 0)
2146 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2147 "error:[%x]\n", ioc->name, recovery_state);
2148 else
2149 printk(MYIOC_s_INFO_FMT
2150 "pci-resume: success\n", ioc->name);
2151 out:
2152 return 0;
2155 #endif
2157 static int
2158 mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2160 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2161 ioc->bus_type != SPI) ||
2162 (MptDriverClass[index] == MPTFC_DRIVER &&
2163 ioc->bus_type != FC) ||
2164 (MptDriverClass[index] == MPTSAS_DRIVER &&
2165 ioc->bus_type != SAS))
2166 /* make sure we only call the relevant reset handler
2167 * for the bus */
2168 return 0;
2169 return (MptResetHandlers[index])(ioc, reset_phase);
2172 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2174 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2175 * @ioc: Pointer to MPT adapter structure
2176 * @reason: Event word / reason
2177 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2179 * This routine performs all the steps necessary to bring the IOC
2180 * to a OPERATIONAL state.
2182 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2183 * MPT adapter.
2185 * Returns:
2186 * 0 for success
2187 * -1 if failed to get board READY
2188 * -2 if READY but IOCFacts Failed
2189 * -3 if READY but PrimeIOCFifos Failed
2190 * -4 if READY but IOCInit Failed
2191 * -5 if failed to enable_device and/or request_selected_regions
2192 * -6 if failed to upload firmware
2194 static int
2195 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2197 int hard_reset_done = 0;
2198 int alt_ioc_ready = 0;
2199 int hard;
2200 int rc=0;
2201 int ii;
2202 int ret = 0;
2203 int reset_alt_ioc_active = 0;
2204 int irq_allocated = 0;
2205 u8 *a;
2207 printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2208 reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2210 /* Disable reply interrupts (also blocks FreeQ) */
2211 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2212 ioc->active = 0;
2214 if (ioc->alt_ioc) {
2215 if (ioc->alt_ioc->active ||
2216 reason == MPT_HOSTEVENT_IOC_RECOVER) {
2217 reset_alt_ioc_active = 1;
2218 /* Disable alt-IOC's reply interrupts
2219 * (and FreeQ) for a bit
2221 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2222 0xFFFFFFFF);
2223 ioc->alt_ioc->active = 0;
2227 hard = 1;
2228 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2229 hard = 0;
2231 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2232 if (hard_reset_done == -4) {
2233 printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2234 ioc->name);
2236 if (reset_alt_ioc_active && ioc->alt_ioc) {
2237 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2238 dprintk(ioc, printk(MYIOC_s_INFO_FMT
2239 "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2240 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2241 ioc->alt_ioc->active = 1;
2244 } else {
2245 printk(MYIOC_s_WARN_FMT
2246 "NOT READY WARNING!\n", ioc->name);
2248 ret = -1;
2249 goto out;
2252 /* hard_reset_done = 0 if a soft reset was performed
2253 * and 1 if a hard reset was performed.
2255 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2256 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2257 alt_ioc_ready = 1;
2258 else
2259 printk(MYIOC_s_WARN_FMT
2260 ": alt-ioc Not ready WARNING!\n",
2261 ioc->alt_ioc->name);
2264 for (ii=0; ii<5; ii++) {
2265 /* Get IOC facts! Allow 5 retries */
2266 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2267 break;
2271 if (ii == 5) {
2272 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2273 "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2274 ret = -2;
2275 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2276 MptDisplayIocCapabilities(ioc);
2279 if (alt_ioc_ready) {
2280 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2281 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2282 "Initial Alt IocFacts failed rc=%x\n",
2283 ioc->name, rc));
2284 /* Retry - alt IOC was initialized once
2286 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2288 if (rc) {
2289 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2290 "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2291 alt_ioc_ready = 0;
2292 reset_alt_ioc_active = 0;
2293 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2294 MptDisplayIocCapabilities(ioc->alt_ioc);
2298 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2299 (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2300 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2301 ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2302 IORESOURCE_IO);
2303 if (pci_enable_device(ioc->pcidev))
2304 return -5;
2305 if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2306 "mpt"))
2307 return -5;
2311 * Device is reset now. It must have de-asserted the interrupt line
2312 * (if it was asserted) and it should be safe to register for the
2313 * interrupt now.
2315 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2316 ioc->pci_irq = -1;
2317 if (ioc->pcidev->irq) {
2318 if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2319 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2320 ioc->name);
2321 else
2322 ioc->msi_enable = 0;
2323 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2324 IRQF_SHARED, ioc->name, ioc);
2325 if (rc < 0) {
2326 printk(MYIOC_s_ERR_FMT "Unable to allocate "
2327 "interrupt %d!\n",
2328 ioc->name, ioc->pcidev->irq);
2329 if (ioc->msi_enable)
2330 pci_disable_msi(ioc->pcidev);
2331 ret = -EBUSY;
2332 goto out;
2334 irq_allocated = 1;
2335 ioc->pci_irq = ioc->pcidev->irq;
2336 pci_set_master(ioc->pcidev); /* ?? */
2337 pci_set_drvdata(ioc->pcidev, ioc);
2338 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2339 "installed at interrupt %d\n", ioc->name,
2340 ioc->pcidev->irq));
2344 /* Prime reply & request queues!
2345 * (mucho alloc's) Must be done prior to
2346 * init as upper addresses are needed for init.
2347 * If fails, continue with alt-ioc processing
2349 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
2350 ioc->name));
2351 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2352 ret = -3;
2354 /* May need to check/upload firmware & data here!
2355 * If fails, continue with alt-ioc processing
2357 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
2358 ioc->name));
2359 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2360 ret = -4;
2361 // NEW!
2362 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2363 printk(MYIOC_s_WARN_FMT
2364 ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
2365 ioc->alt_ioc->name, rc);
2366 alt_ioc_ready = 0;
2367 reset_alt_ioc_active = 0;
2370 if (alt_ioc_ready) {
2371 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2372 alt_ioc_ready = 0;
2373 reset_alt_ioc_active = 0;
2374 printk(MYIOC_s_WARN_FMT
2375 ": alt-ioc: (%d) init failure WARNING!\n",
2376 ioc->alt_ioc->name, rc);
2380 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2381 if (ioc->upload_fw) {
2382 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2383 "firmware upload required!\n", ioc->name));
2385 /* Controller is not operational, cannot do upload
2387 if (ret == 0) {
2388 rc = mpt_do_upload(ioc, sleepFlag);
2389 if (rc == 0) {
2390 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2392 * Maintain only one pointer to FW memory
2393 * so there will not be two attempt to
2394 * downloadboot onboard dual function
2395 * chips (mpt_adapter_disable,
2396 * mpt_diag_reset)
2398 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2399 "mpt_upload: alt_%s has cached_fw=%p \n",
2400 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2401 ioc->cached_fw = NULL;
2403 } else {
2404 printk(MYIOC_s_WARN_FMT
2405 "firmware upload failure!\n", ioc->name);
2406 ret = -6;
2412 /* Enable MPT base driver management of EventNotification
2413 * and EventAck handling.
2415 if ((ret == 0) && (!ioc->facts.EventState)) {
2416 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2417 "SendEventNotification\n",
2418 ioc->name));
2419 ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */
2422 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2423 rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
2425 if (ret == 0) {
2426 /* Enable! (reply interrupt) */
2427 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2428 ioc->active = 1;
2430 if (rc == 0) { /* alt ioc */
2431 if (reset_alt_ioc_active && ioc->alt_ioc) {
2432 /* (re)Enable alt-IOC! (reply interrupt) */
2433 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc"
2434 "reply irq re-enabled\n",
2435 ioc->alt_ioc->name));
2436 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2437 MPI_HIM_DIM);
2438 ioc->alt_ioc->active = 1;
2443 /* Add additional "reason" check before call to GetLanConfigPages
2444 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2445 * recursive scenario; GetLanConfigPages times out, timer expired
2446 * routine calls HardResetHandler, which calls into here again,
2447 * and we try GetLanConfigPages again...
2449 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2452 * Initialize link list for inactive raid volumes.
2454 mutex_init(&ioc->raid_data.inactive_list_mutex);
2455 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2457 switch (ioc->bus_type) {
2459 case SAS:
2460 /* clear persistency table */
2461 if(ioc->facts.IOCExceptions &
2462 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2463 ret = mptbase_sas_persist_operation(ioc,
2464 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2465 if(ret != 0)
2466 goto out;
2469 /* Find IM volumes
2471 mpt_findImVolumes(ioc);
2473 /* Check, and possibly reset, the coalescing value
2475 mpt_read_ioc_pg_1(ioc);
2477 break;
2479 case FC:
2480 if ((ioc->pfacts[0].ProtocolFlags &
2481 MPI_PORTFACTS_PROTOCOL_LAN) &&
2482 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2484 * Pre-fetch the ports LAN MAC address!
2485 * (LANPage1_t stuff)
2487 (void) GetLanConfigPages(ioc);
2488 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2489 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2490 "LanAddr = %02X:%02X:%02X"
2491 ":%02X:%02X:%02X\n",
2492 ioc->name, a[5], a[4],
2493 a[3], a[2], a[1], a[0]));
2495 break;
2497 case SPI:
2498 /* Get NVRAM and adapter maximums from SPP 0 and 2
2500 mpt_GetScsiPortSettings(ioc, 0);
2502 /* Get version and length of SDP 1
2504 mpt_readScsiDevicePageHeaders(ioc, 0);
2506 /* Find IM volumes
2508 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2509 mpt_findImVolumes(ioc);
2511 /* Check, and possibly reset, the coalescing value
2513 mpt_read_ioc_pg_1(ioc);
2515 mpt_read_ioc_pg_4(ioc);
2517 break;
2520 GetIoUnitPage2(ioc);
2521 mpt_get_manufacturing_pg_0(ioc);
2524 out:
2525 if ((ret != 0) && irq_allocated) {
2526 free_irq(ioc->pci_irq, ioc);
2527 if (ioc->msi_enable)
2528 pci_disable_msi(ioc->pcidev);
2530 return ret;
2533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2535 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2536 * @ioc: Pointer to MPT adapter structure
2537 * @pdev: Pointer to (struct pci_dev) structure
2539 * Search for PCI bus/dev_function which matches
2540 * PCI bus/dev_function (+/-1) for newly discovered 929,
2541 * 929X, 1030 or 1035.
2543 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2544 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2546 static void
2547 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2549 struct pci_dev *peer=NULL;
2550 unsigned int slot = PCI_SLOT(pdev->devfn);
2551 unsigned int func = PCI_FUNC(pdev->devfn);
2552 MPT_ADAPTER *ioc_srch;
2554 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2555 " searching for devfn match on %x or %x\n",
2556 ioc->name, pci_name(pdev), pdev->bus->number,
2557 pdev->devfn, func-1, func+1));
2559 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2560 if (!peer) {
2561 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2562 if (!peer)
2563 return;
2566 list_for_each_entry(ioc_srch, &ioc_list, list) {
2567 struct pci_dev *_pcidev = ioc_srch->pcidev;
2568 if (_pcidev == peer) {
2569 /* Paranoia checks */
2570 if (ioc->alt_ioc != NULL) {
2571 printk(MYIOC_s_WARN_FMT
2572 "Oops, already bound (%s <==> %s)!\n",
2573 ioc->name, ioc->name, ioc->alt_ioc->name);
2574 break;
2575 } else if (ioc_srch->alt_ioc != NULL) {
2576 printk(MYIOC_s_WARN_FMT
2577 "Oops, already bound (%s <==> %s)!\n",
2578 ioc_srch->name, ioc_srch->name,
2579 ioc_srch->alt_ioc->name);
2580 break;
2582 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2583 "FOUND! binding %s <==> %s\n",
2584 ioc->name, ioc->name, ioc_srch->name));
2585 ioc_srch->alt_ioc = ioc;
2586 ioc->alt_ioc = ioc_srch;
2589 pci_dev_put(peer);
2592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2594 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2595 * @ioc: Pointer to MPT adapter structure
2597 static void
2598 mpt_adapter_disable(MPT_ADAPTER *ioc)
2600 int sz;
2601 int ret;
2603 if (ioc->cached_fw != NULL) {
2604 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2605 "%s: Pushing FW onto adapter\n", __func__, ioc->name));
2606 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2607 ioc->cached_fw, CAN_SLEEP)) < 0) {
2608 printk(MYIOC_s_WARN_FMT
2609 ": firmware downloadboot failure (%d)!\n",
2610 ioc->name, ret);
2615 * Put the controller into ready state (if its not already)
2617 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
2618 if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
2619 CAN_SLEEP)) {
2620 if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
2621 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit "
2622 "reset failed to put ioc in ready state!\n",
2623 ioc->name, __func__);
2624 } else
2625 printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset "
2626 "failed!\n", ioc->name, __func__);
2630 /* Disable adapter interrupts! */
2631 synchronize_irq(ioc->pcidev->irq);
2632 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2633 ioc->active = 0;
2635 /* Clear any lingering interrupt */
2636 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2637 CHIPREG_READ32(&ioc->chip->IntStatus);
2639 if (ioc->alloc != NULL) {
2640 sz = ioc->alloc_sz;
2641 dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n",
2642 ioc->name, ioc->alloc, ioc->alloc_sz));
2643 pci_free_consistent(ioc->pcidev, sz,
2644 ioc->alloc, ioc->alloc_dma);
2645 ioc->reply_frames = NULL;
2646 ioc->req_frames = NULL;
2647 ioc->alloc = NULL;
2648 ioc->alloc_total -= sz;
2651 if (ioc->sense_buf_pool != NULL) {
2652 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2653 pci_free_consistent(ioc->pcidev, sz,
2654 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2655 ioc->sense_buf_pool = NULL;
2656 ioc->alloc_total -= sz;
2659 if (ioc->events != NULL){
2660 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2661 kfree(ioc->events);
2662 ioc->events = NULL;
2663 ioc->alloc_total -= sz;
2666 mpt_free_fw_memory(ioc);
2668 kfree(ioc->spi_data.nvram);
2669 mpt_inactive_raid_list_free(ioc);
2670 kfree(ioc->raid_data.pIocPg2);
2671 kfree(ioc->raid_data.pIocPg3);
2672 ioc->spi_data.nvram = NULL;
2673 ioc->raid_data.pIocPg3 = NULL;
2675 if (ioc->spi_data.pIocPg4 != NULL) {
2676 sz = ioc->spi_data.IocPg4Sz;
2677 pci_free_consistent(ioc->pcidev, sz,
2678 ioc->spi_data.pIocPg4,
2679 ioc->spi_data.IocPg4_dma);
2680 ioc->spi_data.pIocPg4 = NULL;
2681 ioc->alloc_total -= sz;
2684 if (ioc->ReqToChain != NULL) {
2685 kfree(ioc->ReqToChain);
2686 kfree(ioc->RequestNB);
2687 ioc->ReqToChain = NULL;
2690 kfree(ioc->ChainToChain);
2691 ioc->ChainToChain = NULL;
2693 if (ioc->HostPageBuffer != NULL) {
2694 if((ret = mpt_host_page_access_control(ioc,
2695 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2696 printk(MYIOC_s_ERR_FMT
2697 ": %s: host page buffers free failed (%d)!\n",
2698 ioc->name, __func__, ret);
2700 dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2701 "HostPageBuffer free @ %p, sz=%d bytes\n",
2702 ioc->name, ioc->HostPageBuffer,
2703 ioc->HostPageBuffer_sz));
2704 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2705 ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2706 ioc->HostPageBuffer = NULL;
2707 ioc->HostPageBuffer_sz = 0;
2708 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2711 pci_set_drvdata(ioc->pcidev, NULL);
2713 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2715 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2716 * @ioc: Pointer to MPT adapter structure
2718 * This routine unregisters h/w resources and frees all alloc'd memory
2719 * associated with a MPT adapter structure.
2721 static void
2722 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2724 int sz_first, sz_last;
2726 if (ioc == NULL)
2727 return;
2729 sz_first = ioc->alloc_total;
2731 mpt_adapter_disable(ioc);
2733 if (ioc->pci_irq != -1) {
2734 free_irq(ioc->pci_irq, ioc);
2735 if (ioc->msi_enable)
2736 pci_disable_msi(ioc->pcidev);
2737 ioc->pci_irq = -1;
2740 if (ioc->memmap != NULL) {
2741 iounmap(ioc->memmap);
2742 ioc->memmap = NULL;
2745 pci_disable_device(ioc->pcidev);
2746 pci_release_selected_regions(ioc->pcidev, ioc->bars);
2749 /* Zap the adapter lookup ptr! */
2750 list_del(&ioc->list);
2752 sz_last = ioc->alloc_total;
2753 dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2754 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2756 if (ioc->alt_ioc)
2757 ioc->alt_ioc->alt_ioc = NULL;
2759 kfree(ioc);
2762 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2764 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2765 * @ioc: Pointer to MPT adapter structure
2767 static void
2768 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2770 int i = 0;
2772 printk(KERN_INFO "%s: ", ioc->name);
2773 if (ioc->prod_name)
2774 printk("%s: ", ioc->prod_name);
2775 printk("Capabilities={");
2777 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2778 printk("Initiator");
2779 i++;
2782 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2783 printk("%sTarget", i ? "," : "");
2784 i++;
2787 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2788 printk("%sLAN", i ? "," : "");
2789 i++;
2793 printk("}\n");
2796 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2798 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2799 * @ioc: Pointer to MPT_ADAPTER structure
2800 * @force: Force hard KickStart of IOC
2801 * @sleepFlag: Specifies whether the process can sleep
2803 * Returns:
2804 * 1 - DIAG reset and READY
2805 * 0 - READY initially OR soft reset and READY
2806 * -1 - Any failure on KickStart
2807 * -2 - Msg Unit Reset Failed
2808 * -3 - IO Unit Reset Failed
2809 * -4 - IOC owned by a PEER
2811 static int
2812 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2814 u32 ioc_state;
2815 int statefault = 0;
2816 int cntdn;
2817 int hard_reset_done = 0;
2818 int r;
2819 int ii;
2820 int whoinit;
2822 /* Get current [raw] IOC state */
2823 ioc_state = mpt_GetIocState(ioc, 0);
2824 dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2827 * Check to see if IOC got left/stuck in doorbell handshake
2828 * grip of death. If so, hard reset the IOC.
2830 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2831 statefault = 1;
2832 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2833 ioc->name);
2836 /* Is it already READY? */
2837 if (!statefault &&
2838 ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) {
2839 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2840 "IOC is in READY state\n", ioc->name));
2841 return 0;
2845 * Check to see if IOC is in FAULT state.
2847 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2848 statefault = 2;
2849 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2850 ioc->name);
2851 printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
2852 ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2856 * Hmmm... Did it get left operational?
2858 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2859 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2860 ioc->name));
2862 /* Check WhoInit.
2863 * If PCI Peer, exit.
2864 * Else, if no fault conditions are present, issue a MessageUnitReset
2865 * Else, fall through to KickStart case
2867 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2868 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2869 "whoinit 0x%x statefault %d force %d\n",
2870 ioc->name, whoinit, statefault, force));
2871 if (whoinit == MPI_WHOINIT_PCI_PEER)
2872 return -4;
2873 else {
2874 if ((statefault == 0 ) && (force == 0)) {
2875 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2876 return 0;
2878 statefault = 3;
2882 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2883 if (hard_reset_done < 0)
2884 return -1;
2887 * Loop here waiting for IOC to come READY.
2889 ii = 0;
2890 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2892 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2893 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2895 * BIOS or previous driver load left IOC in OP state.
2896 * Reset messaging FIFOs.
2898 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2899 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2900 return -2;
2902 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2904 * Something is wrong. Try to get IOC back
2905 * to a known state.
2907 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2908 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2909 return -3;
2913 ii++; cntdn--;
2914 if (!cntdn) {
2915 printk(MYIOC_s_ERR_FMT
2916 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
2917 ioc->name, ioc_state, (int)((ii+5)/HZ));
2918 return -ETIME;
2921 if (sleepFlag == CAN_SLEEP) {
2922 msleep(1);
2923 } else {
2924 mdelay (1); /* 1 msec delay */
2929 if (statefault < 3) {
2930 printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name,
2931 statefault == 1 ? "stuck handshake" : "IOC FAULT");
2934 return hard_reset_done;
2937 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2939 * mpt_GetIocState - Get the current state of a MPT adapter.
2940 * @ioc: Pointer to MPT_ADAPTER structure
2941 * @cooked: Request raw or cooked IOC state
2943 * Returns all IOC Doorbell register bits if cooked==0, else just the
2944 * Doorbell bits in MPI_IOC_STATE_MASK.
2947 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2949 u32 s, sc;
2951 /* Get! */
2952 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2953 sc = s & MPI_IOC_STATE_MASK;
2955 /* Save! */
2956 ioc->last_state = sc;
2958 return cooked ? sc : s;
2961 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2963 * GetIocFacts - Send IOCFacts request to MPT adapter.
2964 * @ioc: Pointer to MPT_ADAPTER structure
2965 * @sleepFlag: Specifies whether the process can sleep
2966 * @reason: If recovery, only update facts.
2968 * Returns 0 for success, non-zero for failure.
2970 static int
2971 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2973 IOCFacts_t get_facts;
2974 IOCFactsReply_t *facts;
2975 int r;
2976 int req_sz;
2977 int reply_sz;
2978 int sz;
2979 u32 status, vv;
2980 u8 shiftFactor=1;
2982 /* IOC *must* NOT be in RESET state! */
2983 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2984 printk(KERN_ERR MYNAM
2985 ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2986 ioc->name, ioc->last_state);
2987 return -44;
2990 facts = &ioc->facts;
2992 /* Destination (reply area)... */
2993 reply_sz = sizeof(*facts);
2994 memset(facts, 0, reply_sz);
2996 /* Request area (get_facts on the stack right now!) */
2997 req_sz = sizeof(get_facts);
2998 memset(&get_facts, 0, req_sz);
3000 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
3001 /* Assert: All other get_facts fields are zero! */
3003 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3004 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
3005 ioc->name, req_sz, reply_sz));
3007 /* No non-zero fields in the get_facts request are greater than
3008 * 1 byte in size, so we can just fire it off as is.
3010 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
3011 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
3012 if (r != 0)
3013 return r;
3016 * Now byte swap (GRRR) the necessary fields before any further
3017 * inspection of reply contents.
3019 * But need to do some sanity checks on MsgLength (byte) field
3020 * to make sure we don't zero IOC's req_sz!
3022 /* Did we get a valid reply? */
3023 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
3024 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3026 * If not been here, done that, save off first WhoInit value
3028 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
3029 ioc->FirstWhoInit = facts->WhoInit;
3032 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
3033 facts->MsgContext = le32_to_cpu(facts->MsgContext);
3034 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
3035 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
3036 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
3037 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
3038 /* CHECKME! IOCStatus, IOCLogInfo */
3040 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
3041 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
3044 * FC f/w version changed between 1.1 and 1.2
3045 * Old: u16{Major(4),Minor(4),SubMinor(8)}
3046 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
3048 if (facts->MsgVersion < MPI_VERSION_01_02) {
3050 * Handle old FC f/w style, convert to new...
3052 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
3053 facts->FWVersion.Word =
3054 ((oldv<<12) & 0xFF000000) |
3055 ((oldv<<8) & 0x000FFF00);
3056 } else
3057 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
3059 facts->ProductID = le16_to_cpu(facts->ProductID);
3061 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
3062 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
3063 ioc->ir_firmware = 1;
3065 facts->CurrentHostMfaHighAddr =
3066 le32_to_cpu(facts->CurrentHostMfaHighAddr);
3067 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
3068 facts->CurrentSenseBufferHighAddr =
3069 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
3070 facts->CurReplyFrameSize =
3071 le16_to_cpu(facts->CurReplyFrameSize);
3072 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
3075 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
3076 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
3077 * to 14 in MPI-1.01.0x.
3079 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
3080 facts->MsgVersion > MPI_VERSION_01_00) {
3081 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
3084 sz = facts->FWImageSize;
3085 if ( sz & 0x01 )
3086 sz += 1;
3087 if ( sz & 0x02 )
3088 sz += 2;
3089 facts->FWImageSize = sz;
3091 if (!facts->RequestFrameSize) {
3092 /* Something is wrong! */
3093 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
3094 ioc->name);
3095 return -55;
3098 r = sz = facts->BlockSize;
3099 vv = ((63 / (sz * 4)) + 1) & 0x03;
3100 ioc->NB_for_64_byte_frame = vv;
3101 while ( sz )
3103 shiftFactor++;
3104 sz = sz >> 1;
3106 ioc->NBShiftFactor = shiftFactor;
3107 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3108 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
3109 ioc->name, vv, shiftFactor, r));
3111 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3113 * Set values for this IOC's request & reply frame sizes,
3114 * and request & reply queue depths...
3116 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
3117 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
3118 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
3119 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
3121 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
3122 ioc->name, ioc->reply_sz, ioc->reply_depth));
3123 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n",
3124 ioc->name, ioc->req_sz, ioc->req_depth));
3126 /* Get port facts! */
3127 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
3128 return r;
3130 } else {
3131 printk(MYIOC_s_ERR_FMT
3132 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
3133 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
3134 RequestFrameSize)/sizeof(u32)));
3135 return -66;
3138 return 0;
3141 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3143 * GetPortFacts - Send PortFacts request to MPT adapter.
3144 * @ioc: Pointer to MPT_ADAPTER structure
3145 * @portnum: Port number
3146 * @sleepFlag: Specifies whether the process can sleep
3148 * Returns 0 for success, non-zero for failure.
3150 static int
3151 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3153 PortFacts_t get_pfacts;
3154 PortFactsReply_t *pfacts;
3155 int ii;
3156 int req_sz;
3157 int reply_sz;
3158 int max_id;
3160 /* IOC *must* NOT be in RESET state! */
3161 if (ioc->last_state == MPI_IOC_STATE_RESET) {
3162 printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3163 ioc->name, ioc->last_state );
3164 return -4;
3167 pfacts = &ioc->pfacts[portnum];
3169 /* Destination (reply area)... */
3170 reply_sz = sizeof(*pfacts);
3171 memset(pfacts, 0, reply_sz);
3173 /* Request area (get_pfacts on the stack right now!) */
3174 req_sz = sizeof(get_pfacts);
3175 memset(&get_pfacts, 0, req_sz);
3177 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3178 get_pfacts.PortNumber = portnum;
3179 /* Assert: All other get_pfacts fields are zero! */
3181 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3182 ioc->name, portnum));
3184 /* No non-zero fields in the get_pfacts request are greater than
3185 * 1 byte in size, so we can just fire it off as is.
3187 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3188 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3189 if (ii != 0)
3190 return ii;
3192 /* Did we get a valid reply? */
3194 /* Now byte swap the necessary fields in the response. */
3195 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3196 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3197 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3198 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3199 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3200 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3201 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3202 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3203 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3205 max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3206 pfacts->MaxDevices;
3207 ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3208 ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3211 * Place all the devices on channels
3213 * (for debuging)
3215 if (mpt_channel_mapping) {
3216 ioc->devices_per_bus = 1;
3217 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3220 return 0;
3223 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3225 * SendIocInit - Send IOCInit request to MPT adapter.
3226 * @ioc: Pointer to MPT_ADAPTER structure
3227 * @sleepFlag: Specifies whether the process can sleep
3229 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3231 * Returns 0 for success, non-zero for failure.
3233 static int
3234 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3236 IOCInit_t ioc_init;
3237 MPIDefaultReply_t init_reply;
3238 u32 state;
3239 int r;
3240 int count;
3241 int cntdn;
3243 memset(&ioc_init, 0, sizeof(ioc_init));
3244 memset(&init_reply, 0, sizeof(init_reply));
3246 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3247 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3249 /* If we are in a recovery mode and we uploaded the FW image,
3250 * then this pointer is not NULL. Skip the upload a second time.
3251 * Set this flag if cached_fw set for either IOC.
3253 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3254 ioc->upload_fw = 1;
3255 else
3256 ioc->upload_fw = 0;
3257 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3258 ioc->name, ioc->upload_fw, ioc->facts.Flags));
3260 ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3261 ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3263 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3264 ioc->name, ioc->facts.MsgVersion));
3265 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3266 // set MsgVersion and HeaderVersion host driver was built with
3267 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3268 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3270 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3271 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3272 } else if(mpt_host_page_alloc(ioc, &ioc_init))
3273 return -99;
3275 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
3277 if (ioc->sg_addr_size == sizeof(u64)) {
3278 /* Save the upper 32-bits of the request
3279 * (reply) and sense buffers.
3281 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3282 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3283 } else {
3284 /* Force 32-bit addressing */
3285 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3286 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3289 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3290 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3291 ioc->facts.MaxDevices = ioc_init.MaxDevices;
3292 ioc->facts.MaxBuses = ioc_init.MaxBuses;
3294 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3295 ioc->name, &ioc_init));
3297 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3298 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3299 if (r != 0) {
3300 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3301 return r;
3304 /* No need to byte swap the multibyte fields in the reply
3305 * since we don't even look at its contents.
3308 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3309 ioc->name, &ioc_init));
3311 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3312 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3313 return r;
3316 /* YIKES! SUPER IMPORTANT!!!
3317 * Poll IocState until _OPERATIONAL while IOC is doing
3318 * LoopInit and TargetDiscovery!
3320 count = 0;
3321 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
3322 state = mpt_GetIocState(ioc, 1);
3323 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3324 if (sleepFlag == CAN_SLEEP) {
3325 msleep(1);
3326 } else {
3327 mdelay(1);
3330 if (!cntdn) {
3331 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3332 ioc->name, (int)((count+5)/HZ));
3333 return -9;
3336 state = mpt_GetIocState(ioc, 1);
3337 count++;
3339 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3340 ioc->name, count));
3342 ioc->aen_event_read_flag=0;
3343 return r;
3346 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3348 * SendPortEnable - Send PortEnable request to MPT adapter port.
3349 * @ioc: Pointer to MPT_ADAPTER structure
3350 * @portnum: Port number to enable
3351 * @sleepFlag: Specifies whether the process can sleep
3353 * Send PortEnable to bring IOC to OPERATIONAL state.
3355 * Returns 0 for success, non-zero for failure.
3357 static int
3358 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3360 PortEnable_t port_enable;
3361 MPIDefaultReply_t reply_buf;
3362 int rc;
3363 int req_sz;
3364 int reply_sz;
3366 /* Destination... */
3367 reply_sz = sizeof(MPIDefaultReply_t);
3368 memset(&reply_buf, 0, reply_sz);
3370 req_sz = sizeof(PortEnable_t);
3371 memset(&port_enable, 0, req_sz);
3373 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3374 port_enable.PortNumber = portnum;
3375 /* port_enable.ChainOffset = 0; */
3376 /* port_enable.MsgFlags = 0; */
3377 /* port_enable.MsgContext = 0; */
3379 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3380 ioc->name, portnum, &port_enable));
3382 /* RAID FW may take a long time to enable
3384 if (ioc->ir_firmware || ioc->bus_type == SAS) {
3385 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3386 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3387 300 /*seconds*/, sleepFlag);
3388 } else {
3389 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3390 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3391 30 /*seconds*/, sleepFlag);
3393 return rc;
3397 * mpt_alloc_fw_memory - allocate firmware memory
3398 * @ioc: Pointer to MPT_ADAPTER structure
3399 * @size: total FW bytes
3401 * If memory has already been allocated, the same (cached) value
3402 * is returned.
3404 * Return 0 if successfull, or non-zero for failure
3407 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3409 int rc;
3411 if (ioc->cached_fw) {
3412 rc = 0; /* use already allocated memory */
3413 goto out;
3415 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3416 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3417 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3418 rc = 0;
3419 goto out;
3421 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3422 if (!ioc->cached_fw) {
3423 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3424 ioc->name);
3425 rc = -1;
3426 } else {
3427 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3428 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3429 ioc->alloc_total += size;
3430 rc = 0;
3432 out:
3433 return rc;
3437 * mpt_free_fw_memory - free firmware memory
3438 * @ioc: Pointer to MPT_ADAPTER structure
3440 * If alt_img is NULL, delete from ioc structure.
3441 * Else, delete a secondary image in same format.
3443 void
3444 mpt_free_fw_memory(MPT_ADAPTER *ioc)
3446 int sz;
3448 if (!ioc->cached_fw)
3449 return;
3451 sz = ioc->facts.FWImageSize;
3452 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3453 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3454 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3455 ioc->alloc_total -= sz;
3456 ioc->cached_fw = NULL;
3459 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3461 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3462 * @ioc: Pointer to MPT_ADAPTER structure
3463 * @sleepFlag: Specifies whether the process can sleep
3465 * Returns 0 for success, >0 for handshake failure
3466 * <0 for fw upload failure.
3468 * Remark: If bound IOC and a successful FWUpload was performed
3469 * on the bound IOC, the second image is discarded
3470 * and memory is free'd. Both channels must upload to prevent
3471 * IOC from running in degraded mode.
3473 static int
3474 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3476 u8 reply[sizeof(FWUploadReply_t)];
3477 FWUpload_t *prequest;
3478 FWUploadReply_t *preply;
3479 FWUploadTCSGE_t *ptcsge;
3480 u32 flagsLength;
3481 int ii, sz, reply_sz;
3482 int cmdStatus;
3483 int request_size;
3484 /* If the image size is 0, we are done.
3486 if ((sz = ioc->facts.FWImageSize) == 0)
3487 return 0;
3489 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3490 return -ENOMEM;
3492 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3493 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3495 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3496 kzalloc(ioc->req_sz, GFP_KERNEL);
3497 if (!prequest) {
3498 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3499 "while allocating memory \n", ioc->name));
3500 mpt_free_fw_memory(ioc);
3501 return -ENOMEM;
3504 preply = (FWUploadReply_t *)&reply;
3506 reply_sz = sizeof(reply);
3507 memset(preply, 0, reply_sz);
3509 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3510 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3512 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3513 ptcsge->DetailsLength = 12;
3514 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3515 ptcsge->ImageSize = cpu_to_le32(sz);
3516 ptcsge++;
3518 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3519 ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3520 request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
3521 ioc->SGE_size;
3522 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
3523 " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
3524 ioc->facts.FWImageSize, request_size));
3525 DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3527 ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
3528 reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag);
3530 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
3531 "rc=%x \n", ioc->name, ii));
3533 cmdStatus = -EFAULT;
3534 if (ii == 0) {
3535 /* Handshake transfer was complete and successful.
3536 * Check the Reply Frame.
3538 int status;
3539 status = le16_to_cpu(preply->IOCStatus) &
3540 MPI_IOCSTATUS_MASK;
3541 if (status == MPI_IOCSTATUS_SUCCESS &&
3542 ioc->facts.FWImageSize ==
3543 le32_to_cpu(preply->ActualImageSize))
3544 cmdStatus = 0;
3546 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3547 ioc->name, cmdStatus));
3550 if (cmdStatus) {
3551 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
3552 "freeing image \n", ioc->name));
3553 mpt_free_fw_memory(ioc);
3555 kfree(prequest);
3557 return cmdStatus;
3560 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3562 * mpt_downloadboot - DownloadBoot code
3563 * @ioc: Pointer to MPT_ADAPTER structure
3564 * @pFwHeader: Pointer to firmware header info
3565 * @sleepFlag: Specifies whether the process can sleep
3567 * FwDownloadBoot requires Programmed IO access.
3569 * Returns 0 for success
3570 * -1 FW Image size is 0
3571 * -2 No valid cached_fw Pointer
3572 * <0 for fw upload failure.
3574 static int
3575 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3577 MpiExtImageHeader_t *pExtImage;
3578 u32 fwSize;
3579 u32 diag0val;
3580 int count;
3581 u32 *ptrFw;
3582 u32 diagRwData;
3583 u32 nextImage;
3584 u32 load_addr;
3585 u32 ioc_state=0;
3587 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3588 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3590 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3591 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3592 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3593 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3594 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3595 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3597 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3599 /* wait 1 msec */
3600 if (sleepFlag == CAN_SLEEP) {
3601 msleep(1);
3602 } else {
3603 mdelay (1);
3606 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3607 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3609 for (count = 0; count < 30; count ++) {
3610 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3611 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3612 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3613 ioc->name, count));
3614 break;
3616 /* wait .1 sec */
3617 if (sleepFlag == CAN_SLEEP) {
3618 msleep (100);
3619 } else {
3620 mdelay (100);
3624 if ( count == 30 ) {
3625 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3626 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3627 ioc->name, diag0val));
3628 return -3;
3631 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3632 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3633 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3634 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3635 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3636 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3638 /* Set the DiagRwEn and Disable ARM bits */
3639 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3641 fwSize = (pFwHeader->ImageSize + 3)/4;
3642 ptrFw = (u32 *) pFwHeader;
3644 /* Write the LoadStartAddress to the DiagRw Address Register
3645 * using Programmed IO
3647 if (ioc->errata_flag_1064)
3648 pci_enable_io_access(ioc->pcidev);
3650 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3651 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3652 ioc->name, pFwHeader->LoadStartAddress));
3654 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3655 ioc->name, fwSize*4, ptrFw));
3656 while (fwSize--) {
3657 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3660 nextImage = pFwHeader->NextImageHeaderOffset;
3661 while (nextImage) {
3662 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3664 load_addr = pExtImage->LoadStartAddress;
3666 fwSize = (pExtImage->ImageSize + 3) >> 2;
3667 ptrFw = (u32 *)pExtImage;
3669 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3670 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3671 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3673 while (fwSize--) {
3674 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3676 nextImage = pExtImage->NextImageHeaderOffset;
3679 /* Write the IopResetVectorRegAddr */
3680 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3681 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3683 /* Write the IopResetVectorValue */
3684 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3685 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3687 /* Clear the internal flash bad bit - autoincrementing register,
3688 * so must do two writes.
3690 if (ioc->bus_type == SPI) {
3691 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3692 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3693 diagRwData |= 0x40000000;
3694 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3695 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3697 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3698 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3699 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3700 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3702 /* wait 1 msec */
3703 if (sleepFlag == CAN_SLEEP) {
3704 msleep (1);
3705 } else {
3706 mdelay (1);
3710 if (ioc->errata_flag_1064)
3711 pci_disable_io_access(ioc->pcidev);
3713 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3714 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3715 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3716 ioc->name, diag0val));
3717 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3718 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3719 ioc->name, diag0val));
3720 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3722 /* Write 0xFF to reset the sequencer */
3723 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3725 if (ioc->bus_type == SAS) {
3726 ioc_state = mpt_GetIocState(ioc, 0);
3727 if ( (GetIocFacts(ioc, sleepFlag,
3728 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3729 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3730 ioc->name, ioc_state));
3731 return -EFAULT;
3735 for (count=0; count<HZ*20; count++) {
3736 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3737 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3738 "downloadboot successful! (count=%d) IocState=%x\n",
3739 ioc->name, count, ioc_state));
3740 if (ioc->bus_type == SAS) {
3741 return 0;
3743 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3744 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3745 "downloadboot: SendIocInit failed\n",
3746 ioc->name));
3747 return -EFAULT;
3749 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3750 "downloadboot: SendIocInit successful\n",
3751 ioc->name));
3752 return 0;
3754 if (sleepFlag == CAN_SLEEP) {
3755 msleep (10);
3756 } else {
3757 mdelay (10);
3760 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3761 "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3762 return -EFAULT;
3765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3767 * KickStart - Perform hard reset of MPT adapter.
3768 * @ioc: Pointer to MPT_ADAPTER structure
3769 * @force: Force hard reset
3770 * @sleepFlag: Specifies whether the process can sleep
3772 * This routine places MPT adapter in diagnostic mode via the
3773 * WriteSequence register, and then performs a hard reset of adapter
3774 * via the Diagnostic register.
3776 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3777 * or NO_SLEEP (interrupt thread, use mdelay)
3778 * force - 1 if doorbell active, board fault state
3779 * board operational, IOC_RECOVERY or
3780 * IOC_BRINGUP and there is an alt_ioc.
3781 * 0 else
3783 * Returns:
3784 * 1 - hard reset, READY
3785 * 0 - no reset due to History bit, READY
3786 * -1 - no reset due to History bit but not READY
3787 * OR reset but failed to come READY
3788 * -2 - no reset, could not enter DIAG mode
3789 * -3 - reset but bad FW bit
3791 static int
3792 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3794 int hard_reset_done = 0;
3795 u32 ioc_state=0;
3796 int cnt,cntdn;
3798 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3799 if (ioc->bus_type == SPI) {
3800 /* Always issue a Msg Unit Reset first. This will clear some
3801 * SCSI bus hang conditions.
3803 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3805 if (sleepFlag == CAN_SLEEP) {
3806 msleep (1000);
3807 } else {
3808 mdelay (1000);
3812 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3813 if (hard_reset_done < 0)
3814 return hard_reset_done;
3816 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3817 ioc->name));
3819 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3820 for (cnt=0; cnt<cntdn; cnt++) {
3821 ioc_state = mpt_GetIocState(ioc, 1);
3822 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3823 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3824 ioc->name, cnt));
3825 return hard_reset_done;
3827 if (sleepFlag == CAN_SLEEP) {
3828 msleep (10);
3829 } else {
3830 mdelay (10);
3834 dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3835 ioc->name, mpt_GetIocState(ioc, 0)));
3836 return -1;
3839 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3841 * mpt_diag_reset - Perform hard reset of the adapter.
3842 * @ioc: Pointer to MPT_ADAPTER structure
3843 * @ignore: Set if to honor and clear to ignore
3844 * the reset history bit
3845 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3846 * else set to NO_SLEEP (use mdelay instead)
3848 * This routine places the adapter in diagnostic mode via the
3849 * WriteSequence register and then performs a hard reset of adapter
3850 * via the Diagnostic register. Adapter should be in ready state
3851 * upon successful completion.
3853 * Returns: 1 hard reset successful
3854 * 0 no reset performed because reset history bit set
3855 * -2 enabling diagnostic mode failed
3856 * -3 diagnostic reset failed
3858 static int
3859 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3861 u32 diag0val;
3862 u32 doorbell;
3863 int hard_reset_done = 0;
3864 int count = 0;
3865 u32 diag1val = 0;
3866 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3867 u8 cb_idx;
3869 /* Clear any existing interrupts */
3870 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3872 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3874 if (!ignore)
3875 return 0;
3877 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3878 "address=%p\n", ioc->name, __func__,
3879 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3880 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3881 if (sleepFlag == CAN_SLEEP)
3882 msleep(1);
3883 else
3884 mdelay(1);
3887 * Call each currently registered protocol IOC reset handler
3888 * with pre-reset indication.
3889 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3890 * MptResetHandlers[] registered yet.
3892 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3893 if (MptResetHandlers[cb_idx])
3894 (*(MptResetHandlers[cb_idx]))(ioc,
3895 MPT_IOC_PRE_RESET);
3898 for (count = 0; count < 60; count ++) {
3899 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3900 doorbell &= MPI_IOC_STATE_MASK;
3902 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3903 "looking for READY STATE: doorbell=%x"
3904 " count=%d\n",
3905 ioc->name, doorbell, count));
3907 if (doorbell == MPI_IOC_STATE_READY) {
3908 return 1;
3911 /* wait 1 sec */
3912 if (sleepFlag == CAN_SLEEP)
3913 msleep(1000);
3914 else
3915 mdelay(1000);
3917 return -1;
3920 /* Use "Diagnostic reset" method! (only thing available!) */
3921 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3923 if (ioc->debug_level & MPT_DEBUG) {
3924 if (ioc->alt_ioc)
3925 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3926 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3927 ioc->name, diag0val, diag1val));
3930 /* Do the reset if we are told to ignore the reset history
3931 * or if the reset history is 0
3933 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3934 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3935 /* Write magic sequence to WriteSequence register
3936 * Loop until in diagnostic mode
3938 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3939 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3940 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3941 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3942 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3943 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3945 /* wait 100 msec */
3946 if (sleepFlag == CAN_SLEEP) {
3947 msleep (100);
3948 } else {
3949 mdelay (100);
3952 count++;
3953 if (count > 20) {
3954 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3955 ioc->name, diag0val);
3956 return -2;
3960 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3962 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3963 ioc->name, diag0val));
3966 if (ioc->debug_level & MPT_DEBUG) {
3967 if (ioc->alt_ioc)
3968 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3969 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3970 ioc->name, diag0val, diag1val));
3973 * Disable the ARM (Bug fix)
3976 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3977 mdelay(1);
3980 * Now hit the reset bit in the Diagnostic register
3981 * (THE BIG HAMMER!) (Clears DRWE bit).
3983 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3984 hard_reset_done = 1;
3985 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3986 ioc->name));
3989 * Call each currently registered protocol IOC reset handler
3990 * with pre-reset indication.
3991 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3992 * MptResetHandlers[] registered yet.
3994 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3995 if (MptResetHandlers[cb_idx]) {
3996 mpt_signal_reset(cb_idx,
3997 ioc, MPT_IOC_PRE_RESET);
3998 if (ioc->alt_ioc) {
3999 mpt_signal_reset(cb_idx,
4000 ioc->alt_ioc, MPT_IOC_PRE_RESET);
4005 if (ioc->cached_fw)
4006 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
4007 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
4008 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
4009 else
4010 cached_fw = NULL;
4011 if (cached_fw) {
4012 /* If the DownloadBoot operation fails, the
4013 * IOC will be left unusable. This is a fatal error
4014 * case. _diag_reset will return < 0
4016 for (count = 0; count < 30; count ++) {
4017 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4018 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
4019 break;
4022 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
4023 ioc->name, diag0val, count));
4024 /* wait 1 sec */
4025 if (sleepFlag == CAN_SLEEP) {
4026 msleep (1000);
4027 } else {
4028 mdelay (1000);
4031 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
4032 printk(MYIOC_s_WARN_FMT
4033 "firmware downloadboot failure (%d)!\n", ioc->name, count);
4036 } else {
4037 /* Wait for FW to reload and for board
4038 * to go to the READY state.
4039 * Maximum wait is 60 seconds.
4040 * If fail, no error will check again
4041 * with calling program.
4043 for (count = 0; count < 60; count ++) {
4044 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
4045 doorbell &= MPI_IOC_STATE_MASK;
4047 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4048 "looking for READY STATE: doorbell=%x"
4049 " count=%d\n", ioc->name, doorbell, count));
4051 if (doorbell == MPI_IOC_STATE_READY) {
4052 break;
4055 /* wait 1 sec */
4056 if (sleepFlag == CAN_SLEEP) {
4057 msleep (1000);
4058 } else {
4059 mdelay (1000);
4063 if (doorbell != MPI_IOC_STATE_READY)
4064 printk(MYIOC_s_ERR_FMT "Failed to come READY "
4065 "after reset! IocState=%x", ioc->name,
4066 doorbell);
4070 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4071 if (ioc->debug_level & MPT_DEBUG) {
4072 if (ioc->alt_ioc)
4073 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4074 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
4075 ioc->name, diag0val, diag1val));
4078 /* Clear RESET_HISTORY bit! Place board in the
4079 * diagnostic mode to update the diag register.
4081 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4082 count = 0;
4083 while ((diag0val & MPI_DIAG_DRWE) == 0) {
4084 /* Write magic sequence to WriteSequence register
4085 * Loop until in diagnostic mode
4087 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4088 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4089 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4090 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4091 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4092 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4094 /* wait 100 msec */
4095 if (sleepFlag == CAN_SLEEP) {
4096 msleep (100);
4097 } else {
4098 mdelay (100);
4101 count++;
4102 if (count > 20) {
4103 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4104 ioc->name, diag0val);
4105 break;
4107 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4109 diag0val &= ~MPI_DIAG_RESET_HISTORY;
4110 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
4111 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4112 if (diag0val & MPI_DIAG_RESET_HISTORY) {
4113 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
4114 ioc->name);
4117 /* Disable Diagnostic Mode
4119 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
4121 /* Check FW reload status flags.
4123 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4124 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
4125 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
4126 ioc->name, diag0val);
4127 return -3;
4130 if (ioc->debug_level & MPT_DEBUG) {
4131 if (ioc->alt_ioc)
4132 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4133 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
4134 ioc->name, diag0val, diag1val));
4138 * Reset flag that says we've enabled event notification
4140 ioc->facts.EventState = 0;
4142 if (ioc->alt_ioc)
4143 ioc->alt_ioc->facts.EventState = 0;
4145 return hard_reset_done;
4148 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4150 * SendIocReset - Send IOCReset request to MPT adapter.
4151 * @ioc: Pointer to MPT_ADAPTER structure
4152 * @reset_type: reset type, expected values are
4153 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
4154 * @sleepFlag: Specifies whether the process can sleep
4156 * Send IOCReset request to the MPT adapter.
4158 * Returns 0 for success, non-zero for failure.
4160 static int
4161 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4163 int r;
4164 u32 state;
4165 int cntdn, count;
4167 drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4168 ioc->name, reset_type));
4169 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4170 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4171 return r;
4173 /* FW ACK'd request, wait for READY state
4175 count = 0;
4176 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
4178 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4179 cntdn--;
4180 count++;
4181 if (!cntdn) {
4182 if (sleepFlag != CAN_SLEEP)
4183 count *= 10;
4185 printk(MYIOC_s_ERR_FMT
4186 "Wait IOC_READY state (0x%x) timeout(%d)!\n",
4187 ioc->name, state, (int)((count+5)/HZ));
4188 return -ETIME;
4191 if (sleepFlag == CAN_SLEEP) {
4192 msleep(1);
4193 } else {
4194 mdelay (1); /* 1 msec delay */
4198 /* TODO!
4199 * Cleanup all event stuff for this IOC; re-issue EventNotification
4200 * request if needed.
4202 if (ioc->facts.Function)
4203 ioc->facts.EventState = 0;
4205 return 0;
4208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4210 * initChainBuffers - Allocate memory for and initialize chain buffers
4211 * @ioc: Pointer to MPT_ADAPTER structure
4213 * Allocates memory for and initializes chain buffers,
4214 * chain buffer control arrays and spinlock.
4216 static int
4217 initChainBuffers(MPT_ADAPTER *ioc)
4219 u8 *mem;
4220 int sz, ii, num_chain;
4221 int scale, num_sge, numSGE;
4223 /* ReqToChain size must equal the req_depth
4224 * index = req_idx
4226 if (ioc->ReqToChain == NULL) {
4227 sz = ioc->req_depth * sizeof(int);
4228 mem = kmalloc(sz, GFP_ATOMIC);
4229 if (mem == NULL)
4230 return -1;
4232 ioc->ReqToChain = (int *) mem;
4233 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
4234 ioc->name, mem, sz));
4235 mem = kmalloc(sz, GFP_ATOMIC);
4236 if (mem == NULL)
4237 return -1;
4239 ioc->RequestNB = (int *) mem;
4240 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
4241 ioc->name, mem, sz));
4243 for (ii = 0; ii < ioc->req_depth; ii++) {
4244 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4247 /* ChainToChain size must equal the total number
4248 * of chain buffers to be allocated.
4249 * index = chain_idx
4251 * Calculate the number of chain buffers needed(plus 1) per I/O
4252 * then multiply the maximum number of simultaneous cmds
4254 * num_sge = num sge in request frame + last chain buffer
4255 * scale = num sge per chain buffer if no chain element
4257 scale = ioc->req_sz / ioc->SGE_size;
4258 if (ioc->sg_addr_size == sizeof(u64))
4259 num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size;
4260 else
4261 num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size;
4263 if (ioc->sg_addr_size == sizeof(u64)) {
4264 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4265 (ioc->req_sz - 60) / ioc->SGE_size;
4266 } else {
4267 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) +
4268 scale + (ioc->req_sz - 64) / ioc->SGE_size;
4270 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4271 ioc->name, num_sge, numSGE));
4273 if (ioc->bus_type == FC) {
4274 if (numSGE > MPT_SCSI_FC_SG_DEPTH)
4275 numSGE = MPT_SCSI_FC_SG_DEPTH;
4276 } else {
4277 if (numSGE > MPT_SCSI_SG_DEPTH)
4278 numSGE = MPT_SCSI_SG_DEPTH;
4281 num_chain = 1;
4282 while (numSGE - num_sge > 0) {
4283 num_chain++;
4284 num_sge += (scale - 1);
4286 num_chain++;
4288 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4289 ioc->name, numSGE, num_sge, num_chain));
4291 if (ioc->bus_type == SPI)
4292 num_chain *= MPT_SCSI_CAN_QUEUE;
4293 else if (ioc->bus_type == SAS)
4294 num_chain *= MPT_SAS_CAN_QUEUE;
4295 else
4296 num_chain *= MPT_FC_CAN_QUEUE;
4298 ioc->num_chain = num_chain;
4300 sz = num_chain * sizeof(int);
4301 if (ioc->ChainToChain == NULL) {
4302 mem = kmalloc(sz, GFP_ATOMIC);
4303 if (mem == NULL)
4304 return -1;
4306 ioc->ChainToChain = (int *) mem;
4307 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4308 ioc->name, mem, sz));
4309 } else {
4310 mem = (u8 *) ioc->ChainToChain;
4312 memset(mem, 0xFF, sz);
4313 return num_chain;
4316 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4318 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4319 * @ioc: Pointer to MPT_ADAPTER structure
4321 * This routine allocates memory for the MPT reply and request frame
4322 * pools (if necessary), and primes the IOC reply FIFO with
4323 * reply frames.
4325 * Returns 0 for success, non-zero for failure.
4327 static int
4328 PrimeIocFifos(MPT_ADAPTER *ioc)
4330 MPT_FRAME_HDR *mf;
4331 unsigned long flags;
4332 dma_addr_t alloc_dma;
4333 u8 *mem;
4334 int i, reply_sz, sz, total_size, num_chain;
4335 u64 dma_mask;
4337 dma_mask = 0;
4339 /* Prime reply FIFO... */
4341 if (ioc->reply_frames == NULL) {
4342 if ( (num_chain = initChainBuffers(ioc)) < 0)
4343 return -1;
4344 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
4345 ioc->dma_mask > DMA_BIT_MASK(35)) {
4346 if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32))
4347 && !pci_set_consistent_dma_mask(ioc->pcidev,
4348 DMA_BIT_MASK(32))) {
4349 dma_mask = DMA_BIT_MASK(35);
4350 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4351 "setting 35 bit addressing for "
4352 "Request/Reply/Chain and Sense Buffers\n",
4353 ioc->name));
4354 } else {
4355 /*Reseting DMA mask to 64 bit*/
4356 pci_set_dma_mask(ioc->pcidev,
4357 DMA_BIT_MASK(64));
4358 pci_set_consistent_dma_mask(ioc->pcidev,
4359 DMA_BIT_MASK(64));
4361 printk(MYIOC_s_ERR_FMT
4362 "failed setting 35 bit addressing for "
4363 "Request/Reply/Chain and Sense Buffers\n",
4364 ioc->name);
4365 return -1;
4369 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4370 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4371 ioc->name, ioc->reply_sz, ioc->reply_depth));
4372 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4373 ioc->name, reply_sz, reply_sz));
4375 sz = (ioc->req_sz * ioc->req_depth);
4376 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4377 ioc->name, ioc->req_sz, ioc->req_depth));
4378 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4379 ioc->name, sz, sz));
4380 total_size += sz;
4382 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4383 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4384 ioc->name, ioc->req_sz, num_chain));
4385 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4386 ioc->name, sz, sz, num_chain));
4388 total_size += sz;
4389 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4390 if (mem == NULL) {
4391 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4392 ioc->name);
4393 goto out_fail;
4396 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4397 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4399 memset(mem, 0, total_size);
4400 ioc->alloc_total += total_size;
4401 ioc->alloc = mem;
4402 ioc->alloc_dma = alloc_dma;
4403 ioc->alloc_sz = total_size;
4404 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4405 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4407 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4408 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4410 alloc_dma += reply_sz;
4411 mem += reply_sz;
4413 /* Request FIFO - WE manage this! */
4415 ioc->req_frames = (MPT_FRAME_HDR *) mem;
4416 ioc->req_frames_dma = alloc_dma;
4418 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4419 ioc->name, mem, (void *)(ulong)alloc_dma));
4421 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4424 for (i = 0; i < ioc->req_depth; i++) {
4425 alloc_dma += ioc->req_sz;
4426 mem += ioc->req_sz;
4429 ioc->ChainBuffer = mem;
4430 ioc->ChainBufferDMA = alloc_dma;
4432 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4433 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4435 /* Initialize the free chain Q.
4438 INIT_LIST_HEAD(&ioc->FreeChainQ);
4440 /* Post the chain buffers to the FreeChainQ.
4442 mem = (u8 *)ioc->ChainBuffer;
4443 for (i=0; i < num_chain; i++) {
4444 mf = (MPT_FRAME_HDR *) mem;
4445 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4446 mem += ioc->req_sz;
4449 /* Initialize Request frames linked list
4451 alloc_dma = ioc->req_frames_dma;
4452 mem = (u8 *) ioc->req_frames;
4454 spin_lock_irqsave(&ioc->FreeQlock, flags);
4455 INIT_LIST_HEAD(&ioc->FreeQ);
4456 for (i = 0; i < ioc->req_depth; i++) {
4457 mf = (MPT_FRAME_HDR *) mem;
4459 /* Queue REQUESTs *internally*! */
4460 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4462 mem += ioc->req_sz;
4464 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4466 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4467 ioc->sense_buf_pool =
4468 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4469 if (ioc->sense_buf_pool == NULL) {
4470 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4471 ioc->name);
4472 goto out_fail;
4475 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4476 ioc->alloc_total += sz;
4477 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4478 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4482 /* Post Reply frames to FIFO
4484 alloc_dma = ioc->alloc_dma;
4485 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4486 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4488 for (i = 0; i < ioc->reply_depth; i++) {
4489 /* Write each address to the IOC! */
4490 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4491 alloc_dma += ioc->reply_sz;
4494 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4495 ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
4496 ioc->dma_mask))
4497 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4498 "restoring 64 bit addressing\n", ioc->name));
4500 return 0;
4502 out_fail:
4504 if (ioc->alloc != NULL) {
4505 sz = ioc->alloc_sz;
4506 pci_free_consistent(ioc->pcidev,
4508 ioc->alloc, ioc->alloc_dma);
4509 ioc->reply_frames = NULL;
4510 ioc->req_frames = NULL;
4511 ioc->alloc_total -= sz;
4513 if (ioc->sense_buf_pool != NULL) {
4514 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4515 pci_free_consistent(ioc->pcidev,
4517 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4518 ioc->sense_buf_pool = NULL;
4521 if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4522 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev,
4523 DMA_BIT_MASK(64)))
4524 d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4525 "restoring 64 bit addressing\n", ioc->name));
4527 return -1;
4530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4532 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4533 * from IOC via doorbell handshake method.
4534 * @ioc: Pointer to MPT_ADAPTER structure
4535 * @reqBytes: Size of the request in bytes
4536 * @req: Pointer to MPT request frame
4537 * @replyBytes: Expected size of the reply in bytes
4538 * @u16reply: Pointer to area where reply should be written
4539 * @maxwait: Max wait time for a reply (in seconds)
4540 * @sleepFlag: Specifies whether the process can sleep
4542 * NOTES: It is the callers responsibility to byte-swap fields in the
4543 * request which are greater than 1 byte in size. It is also the
4544 * callers responsibility to byte-swap response fields which are
4545 * greater than 1 byte in size.
4547 * Returns 0 for success, non-zero for failure.
4549 static int
4550 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4551 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4553 MPIDefaultReply_t *mptReply;
4554 int failcnt = 0;
4555 int t;
4558 * Get ready to cache a handshake reply
4560 ioc->hs_reply_idx = 0;
4561 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4562 mptReply->MsgLength = 0;
4565 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4566 * then tell IOC that we want to handshake a request of N words.
4567 * (WRITE u32val to Doorbell reg).
4569 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4570 CHIPREG_WRITE32(&ioc->chip->Doorbell,
4571 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4572 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4575 * Wait for IOC's doorbell handshake int
4577 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4578 failcnt++;
4580 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4581 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4583 /* Read doorbell and check for active bit */
4584 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4585 return -1;
4588 * Clear doorbell int (WRITE 0 to IntStatus reg),
4589 * then wait for IOC to ACKnowledge that it's ready for
4590 * our handshake request.
4592 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4593 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4594 failcnt++;
4596 if (!failcnt) {
4597 int ii;
4598 u8 *req_as_bytes = (u8 *) req;
4601 * Stuff request words via doorbell handshake,
4602 * with ACK from IOC for each.
4604 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4605 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
4606 (req_as_bytes[(ii*4) + 1] << 8) |
4607 (req_as_bytes[(ii*4) + 2] << 16) |
4608 (req_as_bytes[(ii*4) + 3] << 24));
4610 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4611 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4612 failcnt++;
4615 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4616 DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4618 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4619 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4622 * Wait for completion of doorbell handshake reply from the IOC
4624 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4625 failcnt++;
4627 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4628 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4631 * Copy out the cached reply...
4633 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4634 u16reply[ii] = ioc->hs_reply[ii];
4635 } else {
4636 return -99;
4639 return -failcnt;
4642 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4644 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4645 * @ioc: Pointer to MPT_ADAPTER structure
4646 * @howlong: How long to wait (in seconds)
4647 * @sleepFlag: Specifies whether the process can sleep
4649 * This routine waits (up to ~2 seconds max) for IOC doorbell
4650 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4651 * bit in its IntStatus register being clear.
4653 * Returns a negative value on failure, else wait loop count.
4655 static int
4656 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4658 int cntdn;
4659 int count = 0;
4660 u32 intstat=0;
4662 cntdn = 1000 * howlong;
4664 if (sleepFlag == CAN_SLEEP) {
4665 while (--cntdn) {
4666 msleep (1);
4667 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4668 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4669 break;
4670 count++;
4672 } else {
4673 while (--cntdn) {
4674 udelay (1000);
4675 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4676 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4677 break;
4678 count++;
4682 if (cntdn) {
4683 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4684 ioc->name, count));
4685 return count;
4688 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4689 ioc->name, count, intstat);
4690 return -1;
4693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4695 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4696 * @ioc: Pointer to MPT_ADAPTER structure
4697 * @howlong: How long to wait (in seconds)
4698 * @sleepFlag: Specifies whether the process can sleep
4700 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4701 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4703 * Returns a negative value on failure, else wait loop count.
4705 static int
4706 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4708 int cntdn;
4709 int count = 0;
4710 u32 intstat=0;
4712 cntdn = 1000 * howlong;
4713 if (sleepFlag == CAN_SLEEP) {
4714 while (--cntdn) {
4715 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4716 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4717 break;
4718 msleep(1);
4719 count++;
4721 } else {
4722 while (--cntdn) {
4723 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4724 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4725 break;
4726 udelay (1000);
4727 count++;
4731 if (cntdn) {
4732 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4733 ioc->name, count, howlong));
4734 return count;
4737 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4738 ioc->name, count, intstat);
4739 return -1;
4742 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4744 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4745 * @ioc: Pointer to MPT_ADAPTER structure
4746 * @howlong: How long to wait (in seconds)
4747 * @sleepFlag: Specifies whether the process can sleep
4749 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4750 * Reply is cached to IOC private area large enough to hold a maximum
4751 * of 128 bytes of reply data.
4753 * Returns a negative value on failure, else size of reply in WORDS.
4755 static int
4756 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4758 int u16cnt = 0;
4759 int failcnt = 0;
4760 int t;
4761 u16 *hs_reply = ioc->hs_reply;
4762 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4763 u16 hword;
4765 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4768 * Get first two u16's so we can look at IOC's intended reply MsgLength
4770 u16cnt=0;
4771 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4772 failcnt++;
4773 } else {
4774 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4775 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4776 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4777 failcnt++;
4778 else {
4779 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4780 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4784 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4785 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4786 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4789 * If no error (and IOC said MsgLength is > 0), piece together
4790 * reply 16 bits at a time.
4792 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4793 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4794 failcnt++;
4795 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4796 /* don't overflow our IOC hs_reply[] buffer! */
4797 if (u16cnt < ARRAY_SIZE(ioc->hs_reply))
4798 hs_reply[u16cnt] = hword;
4799 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4802 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4803 failcnt++;
4804 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4806 if (failcnt) {
4807 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4808 ioc->name);
4809 return -failcnt;
4812 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4813 DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4815 dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4816 ioc->name, t, u16cnt/2));
4817 return u16cnt/2;
4820 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4822 * GetLanConfigPages - Fetch LANConfig pages.
4823 * @ioc: Pointer to MPT_ADAPTER structure
4825 * Return: 0 for success
4826 * -ENOMEM if no memory available
4827 * -EPERM if not allowed due to ISR context
4828 * -EAGAIN if no msg frames currently available
4829 * -EFAULT for non-successful reply or no reply (timeout)
4831 static int
4832 GetLanConfigPages(MPT_ADAPTER *ioc)
4834 ConfigPageHeader_t hdr;
4835 CONFIGPARMS cfg;
4836 LANPage0_t *ppage0_alloc;
4837 dma_addr_t page0_dma;
4838 LANPage1_t *ppage1_alloc;
4839 dma_addr_t page1_dma;
4840 int rc = 0;
4841 int data_sz;
4842 int copy_sz;
4844 /* Get LAN Page 0 header */
4845 hdr.PageVersion = 0;
4846 hdr.PageLength = 0;
4847 hdr.PageNumber = 0;
4848 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4849 cfg.cfghdr.hdr = &hdr;
4850 cfg.physAddr = -1;
4851 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4852 cfg.dir = 0;
4853 cfg.pageAddr = 0;
4854 cfg.timeout = 0;
4856 if ((rc = mpt_config(ioc, &cfg)) != 0)
4857 return rc;
4859 if (hdr.PageLength > 0) {
4860 data_sz = hdr.PageLength * 4;
4861 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4862 rc = -ENOMEM;
4863 if (ppage0_alloc) {
4864 memset((u8 *)ppage0_alloc, 0, data_sz);
4865 cfg.physAddr = page0_dma;
4866 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4868 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4869 /* save the data */
4870 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4871 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4875 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4880 if (rc)
4881 return rc;
4884 /* Get LAN Page 1 header */
4885 hdr.PageVersion = 0;
4886 hdr.PageLength = 0;
4887 hdr.PageNumber = 1;
4888 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4889 cfg.cfghdr.hdr = &hdr;
4890 cfg.physAddr = -1;
4891 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4892 cfg.dir = 0;
4893 cfg.pageAddr = 0;
4895 if ((rc = mpt_config(ioc, &cfg)) != 0)
4896 return rc;
4898 if (hdr.PageLength == 0)
4899 return 0;
4901 data_sz = hdr.PageLength * 4;
4902 rc = -ENOMEM;
4903 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4904 if (ppage1_alloc) {
4905 memset((u8 *)ppage1_alloc, 0, data_sz);
4906 cfg.physAddr = page1_dma;
4907 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4909 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4910 /* save the data */
4911 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4912 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4915 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4920 return rc;
4923 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4925 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4926 * @ioc: Pointer to MPT_ADAPTER structure
4927 * @persist_opcode: see below
4929 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4930 * devices not currently present.
4931 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4933 * NOTE: Don't use not this function during interrupt time.
4935 * Returns 0 for success, non-zero error
4938 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4940 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4942 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4943 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4944 MPT_FRAME_HDR *mf = NULL;
4945 MPIHeader_t *mpi_hdr;
4946 int ret = 0;
4947 unsigned long timeleft;
4949 mutex_lock(&ioc->mptbase_cmds.mutex);
4951 /* init the internal cmd struct */
4952 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
4953 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
4955 /* insure garbage is not sent to fw */
4956 switch(persist_opcode) {
4958 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4959 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4960 break;
4962 default:
4963 ret = -1;
4964 goto out;
4967 printk(KERN_DEBUG "%s: persist_opcode=%x\n",
4968 __func__, persist_opcode);
4970 /* Get a MF for this command.
4972 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4973 printk(KERN_DEBUG "%s: no msg frames!\n", __func__);
4974 ret = -1;
4975 goto out;
4978 mpi_hdr = (MPIHeader_t *) mf;
4979 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4980 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4981 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4982 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4983 sasIoUnitCntrReq->Operation = persist_opcode;
4985 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4986 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ);
4987 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4988 ret = -ETIME;
4989 printk(KERN_DEBUG "%s: failed\n", __func__);
4990 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4991 goto out;
4992 if (!timeleft) {
4993 printk(MYIOC_s_WARN_FMT
4994 "Issuing Reset from %s!!, doorbell=0x%08x\n",
4995 ioc->name, __func__, mpt_GetIocState(ioc, 0));
4996 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
4997 mpt_free_msg_frame(ioc, mf);
4999 goto out;
5002 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
5003 ret = -1;
5004 goto out;
5007 sasIoUnitCntrReply =
5008 (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply;
5009 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
5010 printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
5011 __func__, sasIoUnitCntrReply->IOCStatus,
5012 sasIoUnitCntrReply->IOCLogInfo);
5013 printk(KERN_DEBUG "%s: failed\n", __func__);
5014 ret = -1;
5015 } else
5016 printk(KERN_DEBUG "%s: success\n", __func__);
5017 out:
5019 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
5020 mutex_unlock(&ioc->mptbase_cmds.mutex);
5021 return ret;
5024 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5026 static void
5027 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
5028 MpiEventDataRaid_t * pRaidEventData)
5030 int volume;
5031 int reason;
5032 int disk;
5033 int status;
5034 int flags;
5035 int state;
5037 volume = pRaidEventData->VolumeID;
5038 reason = pRaidEventData->ReasonCode;
5039 disk = pRaidEventData->PhysDiskNum;
5040 status = le32_to_cpu(pRaidEventData->SettingsStatus);
5041 flags = (status >> 0) & 0xff;
5042 state = (status >> 8) & 0xff;
5044 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
5045 return;
5048 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
5049 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
5050 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
5051 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
5052 ioc->name, disk, volume);
5053 } else {
5054 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
5055 ioc->name, volume);
5058 switch(reason) {
5059 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
5060 printk(MYIOC_s_INFO_FMT " volume has been created\n",
5061 ioc->name);
5062 break;
5064 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
5066 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
5067 ioc->name);
5068 break;
5070 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
5071 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
5072 ioc->name);
5073 break;
5075 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
5076 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
5077 ioc->name,
5078 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
5079 ? "optimal"
5080 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
5081 ? "degraded"
5082 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
5083 ? "failed"
5084 : "state unknown",
5085 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
5086 ? ", enabled" : "",
5087 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
5088 ? ", quiesced" : "",
5089 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
5090 ? ", resync in progress" : "" );
5091 break;
5093 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
5094 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
5095 ioc->name, disk);
5096 break;
5098 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
5099 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
5100 ioc->name);
5101 break;
5103 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
5104 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
5105 ioc->name);
5106 break;
5108 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
5109 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
5110 ioc->name);
5111 break;
5113 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
5114 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
5115 ioc->name,
5116 state == MPI_PHYSDISK0_STATUS_ONLINE
5117 ? "online"
5118 : state == MPI_PHYSDISK0_STATUS_MISSING
5119 ? "missing"
5120 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
5121 ? "not compatible"
5122 : state == MPI_PHYSDISK0_STATUS_FAILED
5123 ? "failed"
5124 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
5125 ? "initializing"
5126 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
5127 ? "offline requested"
5128 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
5129 ? "failed requested"
5130 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
5131 ? "offline"
5132 : "state unknown",
5133 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
5134 ? ", out of sync" : "",
5135 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
5136 ? ", quiesced" : "" );
5137 break;
5139 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
5140 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
5141 ioc->name, disk);
5142 break;
5144 case MPI_EVENT_RAID_RC_SMART_DATA:
5145 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
5146 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
5147 break;
5149 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
5150 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
5151 ioc->name, disk);
5152 break;
5156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5158 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
5159 * @ioc: Pointer to MPT_ADAPTER structure
5161 * Returns: 0 for success
5162 * -ENOMEM if no memory available
5163 * -EPERM if not allowed due to ISR context
5164 * -EAGAIN if no msg frames currently available
5165 * -EFAULT for non-successful reply or no reply (timeout)
5167 static int
5168 GetIoUnitPage2(MPT_ADAPTER *ioc)
5170 ConfigPageHeader_t hdr;
5171 CONFIGPARMS cfg;
5172 IOUnitPage2_t *ppage_alloc;
5173 dma_addr_t page_dma;
5174 int data_sz;
5175 int rc;
5177 /* Get the page header */
5178 hdr.PageVersion = 0;
5179 hdr.PageLength = 0;
5180 hdr.PageNumber = 2;
5181 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
5182 cfg.cfghdr.hdr = &hdr;
5183 cfg.physAddr = -1;
5184 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5185 cfg.dir = 0;
5186 cfg.pageAddr = 0;
5187 cfg.timeout = 0;
5189 if ((rc = mpt_config(ioc, &cfg)) != 0)
5190 return rc;
5192 if (hdr.PageLength == 0)
5193 return 0;
5195 /* Read the config page */
5196 data_sz = hdr.PageLength * 4;
5197 rc = -ENOMEM;
5198 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
5199 if (ppage_alloc) {
5200 memset((u8 *)ppage_alloc, 0, data_sz);
5201 cfg.physAddr = page_dma;
5202 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5204 /* If Good, save data */
5205 if ((rc = mpt_config(ioc, &cfg)) == 0)
5206 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
5208 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
5211 return rc;
5214 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5216 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5217 * @ioc: Pointer to a Adapter Strucutre
5218 * @portnum: IOC port number
5220 * Return: -EFAULT if read of config page header fails
5221 * or if no nvram
5222 * If read of SCSI Port Page 0 fails,
5223 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5224 * Adapter settings: async, narrow
5225 * Return 1
5226 * If read of SCSI Port Page 2 fails,
5227 * Adapter settings valid
5228 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5229 * Return 1
5230 * Else
5231 * Both valid
5232 * Return 0
5233 * CHECK - what type of locking mechanisms should be used????
5235 static int
5236 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
5238 u8 *pbuf;
5239 dma_addr_t buf_dma;
5240 CONFIGPARMS cfg;
5241 ConfigPageHeader_t header;
5242 int ii;
5243 int data, rc = 0;
5245 /* Allocate memory
5247 if (!ioc->spi_data.nvram) {
5248 int sz;
5249 u8 *mem;
5250 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5251 mem = kmalloc(sz, GFP_ATOMIC);
5252 if (mem == NULL)
5253 return -EFAULT;
5255 ioc->spi_data.nvram = (int *) mem;
5257 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5258 ioc->name, ioc->spi_data.nvram, sz));
5261 /* Invalidate NVRAM information
5263 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5264 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5267 /* Read SPP0 header, allocate memory, then read page.
5269 header.PageVersion = 0;
5270 header.PageLength = 0;
5271 header.PageNumber = 0;
5272 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5273 cfg.cfghdr.hdr = &header;
5274 cfg.physAddr = -1;
5275 cfg.pageAddr = portnum;
5276 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5277 cfg.dir = 0;
5278 cfg.timeout = 0; /* use default */
5279 if (mpt_config(ioc, &cfg) != 0)
5280 return -EFAULT;
5282 if (header.PageLength > 0) {
5283 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5284 if (pbuf) {
5285 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5286 cfg.physAddr = buf_dma;
5287 if (mpt_config(ioc, &cfg) != 0) {
5288 ioc->spi_data.maxBusWidth = MPT_NARROW;
5289 ioc->spi_data.maxSyncOffset = 0;
5290 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5291 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5292 rc = 1;
5293 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5294 "Unable to read PortPage0 minSyncFactor=%x\n",
5295 ioc->name, ioc->spi_data.minSyncFactor));
5296 } else {
5297 /* Save the Port Page 0 data
5299 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
5300 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5301 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5303 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5304 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5305 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5306 "noQas due to Capabilities=%x\n",
5307 ioc->name, pPP0->Capabilities));
5309 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5310 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5311 if (data) {
5312 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5313 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5314 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5315 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5316 "PortPage0 minSyncFactor=%x\n",
5317 ioc->name, ioc->spi_data.minSyncFactor));
5318 } else {
5319 ioc->spi_data.maxSyncOffset = 0;
5320 ioc->spi_data.minSyncFactor = MPT_ASYNC;
5323 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5325 /* Update the minSyncFactor based on bus type.
5327 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5328 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
5330 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5331 ioc->spi_data.minSyncFactor = MPT_ULTRA;
5332 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5333 "HVD or SE detected, minSyncFactor=%x\n",
5334 ioc->name, ioc->spi_data.minSyncFactor));
5338 if (pbuf) {
5339 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5344 /* SCSI Port Page 2 - Read the header then the page.
5346 header.PageVersion = 0;
5347 header.PageLength = 0;
5348 header.PageNumber = 2;
5349 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5350 cfg.cfghdr.hdr = &header;
5351 cfg.physAddr = -1;
5352 cfg.pageAddr = portnum;
5353 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5354 cfg.dir = 0;
5355 if (mpt_config(ioc, &cfg) != 0)
5356 return -EFAULT;
5358 if (header.PageLength > 0) {
5359 /* Allocate memory and read SCSI Port Page 2
5361 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5362 if (pbuf) {
5363 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5364 cfg.physAddr = buf_dma;
5365 if (mpt_config(ioc, &cfg) != 0) {
5366 /* Nvram data is left with INVALID mark
5368 rc = 1;
5369 } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5371 /* This is an ATTO adapter, read Page2 accordingly
5373 ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf;
5374 ATTODeviceInfo_t *pdevice = NULL;
5375 u16 ATTOFlags;
5377 /* Save the Port Page 2 data
5378 * (reformat into a 32bit quantity)
5380 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5381 pdevice = &pPP2->DeviceSettings[ii];
5382 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5383 data = 0;
5385 /* Translate ATTO device flags to LSI format
5387 if (ATTOFlags & ATTOFLAG_DISC)
5388 data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5389 if (ATTOFlags & ATTOFLAG_ID_ENB)
5390 data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5391 if (ATTOFlags & ATTOFLAG_LUN_ENB)
5392 data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5393 if (ATTOFlags & ATTOFLAG_TAGGED)
5394 data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5395 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5396 data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5398 data = (data << 16) | (pdevice->Period << 8) | 10;
5399 ioc->spi_data.nvram[ii] = data;
5401 } else {
5402 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
5403 MpiDeviceInfo_t *pdevice = NULL;
5406 * Save "Set to Avoid SCSI Bus Resets" flag
5408 ioc->spi_data.bus_reset =
5409 (le32_to_cpu(pPP2->PortFlags) &
5410 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5411 0 : 1 ;
5413 /* Save the Port Page 2 data
5414 * (reformat into a 32bit quantity)
5416 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5417 ioc->spi_data.PortFlags = data;
5418 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5419 pdevice = &pPP2->DeviceSettings[ii];
5420 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5421 (pdevice->SyncFactor << 8) | pdevice->Timeout;
5422 ioc->spi_data.nvram[ii] = data;
5426 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5430 /* Update Adapter limits with those from NVRAM
5431 * Comment: Don't need to do this. Target performance
5432 * parameters will never exceed the adapters limits.
5435 return rc;
5438 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5440 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5441 * @ioc: Pointer to a Adapter Strucutre
5442 * @portnum: IOC port number
5444 * Return: -EFAULT if read of config page header fails
5445 * or 0 if success.
5447 static int
5448 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5450 CONFIGPARMS cfg;
5451 ConfigPageHeader_t header;
5453 /* Read the SCSI Device Page 1 header
5455 header.PageVersion = 0;
5456 header.PageLength = 0;
5457 header.PageNumber = 1;
5458 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5459 cfg.cfghdr.hdr = &header;
5460 cfg.physAddr = -1;
5461 cfg.pageAddr = portnum;
5462 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5463 cfg.dir = 0;
5464 cfg.timeout = 0;
5465 if (mpt_config(ioc, &cfg) != 0)
5466 return -EFAULT;
5468 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5469 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5471 header.PageVersion = 0;
5472 header.PageLength = 0;
5473 header.PageNumber = 0;
5474 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5475 if (mpt_config(ioc, &cfg) != 0)
5476 return -EFAULT;
5478 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5479 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5481 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5482 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5484 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5485 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5486 return 0;
5490 * mpt_inactive_raid_list_free - This clears this link list.
5491 * @ioc : pointer to per adapter structure
5493 static void
5494 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5496 struct inactive_raid_component_info *component_info, *pNext;
5498 if (list_empty(&ioc->raid_data.inactive_list))
5499 return;
5501 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5502 list_for_each_entry_safe(component_info, pNext,
5503 &ioc->raid_data.inactive_list, list) {
5504 list_del(&component_info->list);
5505 kfree(component_info);
5507 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5511 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5513 * @ioc : pointer to per adapter structure
5514 * @channel : volume channel
5515 * @id : volume target id
5517 static void
5518 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5520 CONFIGPARMS cfg;
5521 ConfigPageHeader_t hdr;
5522 dma_addr_t dma_handle;
5523 pRaidVolumePage0_t buffer = NULL;
5524 int i;
5525 RaidPhysDiskPage0_t phys_disk;
5526 struct inactive_raid_component_info *component_info;
5527 int handle_inactive_volumes;
5529 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5530 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5531 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5532 cfg.pageAddr = (channel << 8) + id;
5533 cfg.cfghdr.hdr = &hdr;
5534 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5536 if (mpt_config(ioc, &cfg) != 0)
5537 goto out;
5539 if (!hdr.PageLength)
5540 goto out;
5542 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5543 &dma_handle);
5545 if (!buffer)
5546 goto out;
5548 cfg.physAddr = dma_handle;
5549 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5551 if (mpt_config(ioc, &cfg) != 0)
5552 goto out;
5554 if (!buffer->NumPhysDisks)
5555 goto out;
5557 handle_inactive_volumes =
5558 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5559 (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5560 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5561 buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5563 if (!handle_inactive_volumes)
5564 goto out;
5566 mutex_lock(&ioc->raid_data.inactive_list_mutex);
5567 for (i = 0; i < buffer->NumPhysDisks; i++) {
5568 if(mpt_raid_phys_disk_pg0(ioc,
5569 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5570 continue;
5572 if ((component_info = kmalloc(sizeof (*component_info),
5573 GFP_KERNEL)) == NULL)
5574 continue;
5576 component_info->volumeID = id;
5577 component_info->volumeBus = channel;
5578 component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5579 component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5580 component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5581 component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5583 list_add_tail(&component_info->list,
5584 &ioc->raid_data.inactive_list);
5586 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5588 out:
5589 if (buffer)
5590 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5591 dma_handle);
5595 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5596 * @ioc: Pointer to a Adapter Structure
5597 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5598 * @phys_disk: requested payload data returned
5600 * Return:
5601 * 0 on success
5602 * -EFAULT if read of config page header fails or data pointer not NULL
5603 * -ENOMEM if pci_alloc failed
5606 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
5607 RaidPhysDiskPage0_t *phys_disk)
5609 CONFIGPARMS cfg;
5610 ConfigPageHeader_t hdr;
5611 dma_addr_t dma_handle;
5612 pRaidPhysDiskPage0_t buffer = NULL;
5613 int rc;
5615 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5616 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5617 memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t));
5619 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION;
5620 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5621 cfg.cfghdr.hdr = &hdr;
5622 cfg.physAddr = -1;
5623 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5625 if (mpt_config(ioc, &cfg) != 0) {
5626 rc = -EFAULT;
5627 goto out;
5630 if (!hdr.PageLength) {
5631 rc = -EFAULT;
5632 goto out;
5635 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5636 &dma_handle);
5638 if (!buffer) {
5639 rc = -ENOMEM;
5640 goto out;
5643 cfg.physAddr = dma_handle;
5644 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5645 cfg.pageAddr = phys_disk_num;
5647 if (mpt_config(ioc, &cfg) != 0) {
5648 rc = -EFAULT;
5649 goto out;
5652 rc = 0;
5653 memcpy(phys_disk, buffer, sizeof(*buffer));
5654 phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5656 out:
5658 if (buffer)
5659 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5660 dma_handle);
5662 return rc;
5666 * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
5667 * @ioc: Pointer to a Adapter Structure
5668 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5670 * Return:
5671 * returns number paths
5674 mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
5676 CONFIGPARMS cfg;
5677 ConfigPageHeader_t hdr;
5678 dma_addr_t dma_handle;
5679 pRaidPhysDiskPage1_t buffer = NULL;
5680 int rc;
5682 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5683 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5685 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5686 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5687 hdr.PageNumber = 1;
5688 cfg.cfghdr.hdr = &hdr;
5689 cfg.physAddr = -1;
5690 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5692 if (mpt_config(ioc, &cfg) != 0) {
5693 rc = 0;
5694 goto out;
5697 if (!hdr.PageLength) {
5698 rc = 0;
5699 goto out;
5702 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5703 &dma_handle);
5705 if (!buffer) {
5706 rc = 0;
5707 goto out;
5710 cfg.physAddr = dma_handle;
5711 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5712 cfg.pageAddr = phys_disk_num;
5714 if (mpt_config(ioc, &cfg) != 0) {
5715 rc = 0;
5716 goto out;
5719 rc = buffer->NumPhysDiskPaths;
5720 out:
5722 if (buffer)
5723 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5724 dma_handle);
5726 return rc;
5728 EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
5731 * mpt_raid_phys_disk_pg1 - returns phys disk page 1
5732 * @ioc: Pointer to a Adapter Structure
5733 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5734 * @phys_disk: requested payload data returned
5736 * Return:
5737 * 0 on success
5738 * -EFAULT if read of config page header fails or data pointer not NULL
5739 * -ENOMEM if pci_alloc failed
5742 mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
5743 RaidPhysDiskPage1_t *phys_disk)
5745 CONFIGPARMS cfg;
5746 ConfigPageHeader_t hdr;
5747 dma_addr_t dma_handle;
5748 pRaidPhysDiskPage1_t buffer = NULL;
5749 int rc;
5750 int i;
5751 __le64 sas_address;
5753 memset(&cfg, 0 , sizeof(CONFIGPARMS));
5754 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5755 rc = 0;
5757 hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
5758 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5759 hdr.PageNumber = 1;
5760 cfg.cfghdr.hdr = &hdr;
5761 cfg.physAddr = -1;
5762 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5764 if (mpt_config(ioc, &cfg) != 0) {
5765 rc = -EFAULT;
5766 goto out;
5769 if (!hdr.PageLength) {
5770 rc = -EFAULT;
5771 goto out;
5774 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5775 &dma_handle);
5777 if (!buffer) {
5778 rc = -ENOMEM;
5779 goto out;
5782 cfg.physAddr = dma_handle;
5783 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5784 cfg.pageAddr = phys_disk_num;
5786 if (mpt_config(ioc, &cfg) != 0) {
5787 rc = -EFAULT;
5788 goto out;
5791 phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
5792 phys_disk->PhysDiskNum = phys_disk_num;
5793 for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
5794 phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
5795 phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
5796 phys_disk->Path[i].OwnerIdentifier =
5797 buffer->Path[i].OwnerIdentifier;
5798 phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
5799 memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
5800 sas_address = le64_to_cpu(sas_address);
5801 memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
5802 memcpy(&sas_address,
5803 &buffer->Path[i].OwnerWWID, sizeof(__le64));
5804 sas_address = le64_to_cpu(sas_address);
5805 memcpy(&phys_disk->Path[i].OwnerWWID,
5806 &sas_address, sizeof(__le64));
5809 out:
5811 if (buffer)
5812 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5813 dma_handle);
5815 return rc;
5817 EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
5821 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5822 * @ioc: Pointer to a Adapter Strucutre
5824 * Return:
5825 * 0 on success
5826 * -EFAULT if read of config page header fails or data pointer not NULL
5827 * -ENOMEM if pci_alloc failed
5830 mpt_findImVolumes(MPT_ADAPTER *ioc)
5832 IOCPage2_t *pIoc2;
5833 u8 *mem;
5834 dma_addr_t ioc2_dma;
5835 CONFIGPARMS cfg;
5836 ConfigPageHeader_t header;
5837 int rc = 0;
5838 int iocpage2sz;
5839 int i;
5841 if (!ioc->ir_firmware)
5842 return 0;
5844 /* Free the old page
5846 kfree(ioc->raid_data.pIocPg2);
5847 ioc->raid_data.pIocPg2 = NULL;
5848 mpt_inactive_raid_list_free(ioc);
5850 /* Read IOCP2 header then the page.
5852 header.PageVersion = 0;
5853 header.PageLength = 0;
5854 header.PageNumber = 2;
5855 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5856 cfg.cfghdr.hdr = &header;
5857 cfg.physAddr = -1;
5858 cfg.pageAddr = 0;
5859 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5860 cfg.dir = 0;
5861 cfg.timeout = 0;
5862 if (mpt_config(ioc, &cfg) != 0)
5863 return -EFAULT;
5865 if (header.PageLength == 0)
5866 return -EFAULT;
5868 iocpage2sz = header.PageLength * 4;
5869 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5870 if (!pIoc2)
5871 return -ENOMEM;
5873 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5874 cfg.physAddr = ioc2_dma;
5875 if (mpt_config(ioc, &cfg) != 0)
5876 goto out;
5878 mem = kmalloc(iocpage2sz, GFP_KERNEL);
5879 if (!mem)
5880 goto out;
5882 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5883 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5885 mpt_read_ioc_pg_3(ioc);
5887 for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5888 mpt_inactive_raid_volumes(ioc,
5889 pIoc2->RaidVolume[i].VolumeBus,
5890 pIoc2->RaidVolume[i].VolumeID);
5892 out:
5893 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5895 return rc;
5898 static int
5899 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5901 IOCPage3_t *pIoc3;
5902 u8 *mem;
5903 CONFIGPARMS cfg;
5904 ConfigPageHeader_t header;
5905 dma_addr_t ioc3_dma;
5906 int iocpage3sz = 0;
5908 /* Free the old page
5910 kfree(ioc->raid_data.pIocPg3);
5911 ioc->raid_data.pIocPg3 = NULL;
5913 /* There is at least one physical disk.
5914 * Read and save IOC Page 3
5916 header.PageVersion = 0;
5917 header.PageLength = 0;
5918 header.PageNumber = 3;
5919 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5920 cfg.cfghdr.hdr = &header;
5921 cfg.physAddr = -1;
5922 cfg.pageAddr = 0;
5923 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5924 cfg.dir = 0;
5925 cfg.timeout = 0;
5926 if (mpt_config(ioc, &cfg) != 0)
5927 return 0;
5929 if (header.PageLength == 0)
5930 return 0;
5932 /* Read Header good, alloc memory
5934 iocpage3sz = header.PageLength * 4;
5935 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5936 if (!pIoc3)
5937 return 0;
5939 /* Read the Page and save the data
5940 * into malloc'd memory.
5942 cfg.physAddr = ioc3_dma;
5943 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5944 if (mpt_config(ioc, &cfg) == 0) {
5945 mem = kmalloc(iocpage3sz, GFP_KERNEL);
5946 if (mem) {
5947 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5948 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5952 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5954 return 0;
5957 static void
5958 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5960 IOCPage4_t *pIoc4;
5961 CONFIGPARMS cfg;
5962 ConfigPageHeader_t header;
5963 dma_addr_t ioc4_dma;
5964 int iocpage4sz;
5966 /* Read and save IOC Page 4
5968 header.PageVersion = 0;
5969 header.PageLength = 0;
5970 header.PageNumber = 4;
5971 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5972 cfg.cfghdr.hdr = &header;
5973 cfg.physAddr = -1;
5974 cfg.pageAddr = 0;
5975 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5976 cfg.dir = 0;
5977 cfg.timeout = 0;
5978 if (mpt_config(ioc, &cfg) != 0)
5979 return;
5981 if (header.PageLength == 0)
5982 return;
5984 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5985 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5986 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5987 if (!pIoc4)
5988 return;
5989 ioc->alloc_total += iocpage4sz;
5990 } else {
5991 ioc4_dma = ioc->spi_data.IocPg4_dma;
5992 iocpage4sz = ioc->spi_data.IocPg4Sz;
5995 /* Read the Page into dma memory.
5997 cfg.physAddr = ioc4_dma;
5998 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5999 if (mpt_config(ioc, &cfg) == 0) {
6000 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
6001 ioc->spi_data.IocPg4_dma = ioc4_dma;
6002 ioc->spi_data.IocPg4Sz = iocpage4sz;
6003 } else {
6004 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
6005 ioc->spi_data.pIocPg4 = NULL;
6006 ioc->alloc_total -= iocpage4sz;
6010 static void
6011 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
6013 IOCPage1_t *pIoc1;
6014 CONFIGPARMS cfg;
6015 ConfigPageHeader_t header;
6016 dma_addr_t ioc1_dma;
6017 int iocpage1sz = 0;
6018 u32 tmp;
6020 /* Check the Coalescing Timeout in IOC Page 1
6022 header.PageVersion = 0;
6023 header.PageLength = 0;
6024 header.PageNumber = 1;
6025 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
6026 cfg.cfghdr.hdr = &header;
6027 cfg.physAddr = -1;
6028 cfg.pageAddr = 0;
6029 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6030 cfg.dir = 0;
6031 cfg.timeout = 0;
6032 if (mpt_config(ioc, &cfg) != 0)
6033 return;
6035 if (header.PageLength == 0)
6036 return;
6038 /* Read Header good, alloc memory
6040 iocpage1sz = header.PageLength * 4;
6041 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
6042 if (!pIoc1)
6043 return;
6045 /* Read the Page and check coalescing timeout
6047 cfg.physAddr = ioc1_dma;
6048 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6049 if (mpt_config(ioc, &cfg) == 0) {
6051 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
6052 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
6053 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
6055 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
6056 ioc->name, tmp));
6058 if (tmp > MPT_COALESCING_TIMEOUT) {
6059 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
6061 /* Write NVRAM and current
6063 cfg.dir = 1;
6064 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6065 if (mpt_config(ioc, &cfg) == 0) {
6066 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
6067 ioc->name, MPT_COALESCING_TIMEOUT));
6069 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
6070 if (mpt_config(ioc, &cfg) == 0) {
6071 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6072 "Reset NVRAM Coalescing Timeout to = %d\n",
6073 ioc->name, MPT_COALESCING_TIMEOUT));
6074 } else {
6075 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6076 "Reset NVRAM Coalescing Timeout Failed\n",
6077 ioc->name));
6080 } else {
6081 dprintk(ioc, printk(MYIOC_s_WARN_FMT
6082 "Reset of Current Coalescing Timeout Failed!\n",
6083 ioc->name));
6087 } else {
6088 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
6092 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
6094 return;
6097 static void
6098 mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
6100 CONFIGPARMS cfg;
6101 ConfigPageHeader_t hdr;
6102 dma_addr_t buf_dma;
6103 ManufacturingPage0_t *pbuf = NULL;
6105 memset(&cfg, 0 , sizeof(CONFIGPARMS));
6106 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
6108 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
6109 cfg.cfghdr.hdr = &hdr;
6110 cfg.physAddr = -1;
6111 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
6112 cfg.timeout = 10;
6114 if (mpt_config(ioc, &cfg) != 0)
6115 goto out;
6117 if (!cfg.cfghdr.hdr->PageLength)
6118 goto out;
6120 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6121 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
6122 if (!pbuf)
6123 goto out;
6125 cfg.physAddr = buf_dma;
6127 if (mpt_config(ioc, &cfg) != 0)
6128 goto out;
6130 memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
6131 memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
6132 memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
6134 out:
6136 if (pbuf)
6137 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
6140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6142 * SendEventNotification - Send EventNotification (on or off) request to adapter
6143 * @ioc: Pointer to MPT_ADAPTER structure
6144 * @EvSwitch: Event switch flags
6145 * @sleepFlag: Specifies whether the process can sleep
6147 static int
6148 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag)
6150 EventNotification_t evn;
6151 MPIDefaultReply_t reply_buf;
6153 memset(&evn, 0, sizeof(EventNotification_t));
6154 memset(&reply_buf, 0, sizeof(MPIDefaultReply_t));
6156 evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION;
6157 evn.Switch = EvSwitch;
6158 evn.MsgContext = cpu_to_le32(mpt_base_index << 16);
6160 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6161 "Sending EventNotification (%d) request %p\n",
6162 ioc->name, EvSwitch, &evn));
6164 return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t),
6165 (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30,
6166 sleepFlag);
6169 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6171 * SendEventAck - Send EventAck request to MPT adapter.
6172 * @ioc: Pointer to MPT_ADAPTER structure
6173 * @evnp: Pointer to original EventNotification request
6175 static int
6176 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
6178 EventAck_t *pAck;
6180 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6181 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
6182 ioc->name, __func__));
6183 return -1;
6186 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
6188 pAck->Function = MPI_FUNCTION_EVENT_ACK;
6189 pAck->ChainOffset = 0;
6190 pAck->Reserved[0] = pAck->Reserved[1] = 0;
6191 pAck->MsgFlags = 0;
6192 pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
6193 pAck->Event = evnp->Event;
6194 pAck->EventContext = evnp->EventContext;
6196 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
6198 return 0;
6201 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6203 * mpt_config - Generic function to issue config message
6204 * @ioc: Pointer to an adapter structure
6205 * @pCfg: Pointer to a configuration structure. Struct contains
6206 * action, page address, direction, physical address
6207 * and pointer to a configuration page header
6208 * Page header is updated.
6210 * Returns 0 for success
6211 * -EPERM if not allowed due to ISR context
6212 * -EAGAIN if no msg frames currently available
6213 * -EFAULT for non-successful reply or no reply (timeout)
6216 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
6218 Config_t *pReq;
6219 ConfigReply_t *pReply;
6220 ConfigExtendedPageHeader_t *pExtHdr = NULL;
6221 MPT_FRAME_HDR *mf;
6222 int ii;
6223 int flagsLength;
6224 long timeout;
6225 int ret;
6226 u8 page_type = 0, extend_page;
6227 unsigned long timeleft;
6228 unsigned long flags;
6229 int in_isr;
6230 u8 issue_hard_reset = 0;
6231 u8 retry_count = 0;
6233 /* Prevent calling wait_event() (below), if caller happens
6234 * to be in ISR context, because that is fatal!
6236 in_isr = in_interrupt();
6237 if (in_isr) {
6238 dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
6239 ioc->name));
6240 return -EPERM;
6243 /* don't send a config page during diag reset */
6244 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6245 if (ioc->ioc_reset_in_progress) {
6246 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6247 "%s: busy with host reset\n", ioc->name, __func__));
6248 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6249 return -EBUSY;
6251 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6253 /* don't send if no chance of success */
6254 if (!ioc->active ||
6255 mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) {
6256 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6257 "%s: ioc not operational, %d, %xh\n",
6258 ioc->name, __func__, ioc->active,
6259 mpt_GetIocState(ioc, 0)));
6260 return -EFAULT;
6263 retry_config:
6264 mutex_lock(&ioc->mptbase_cmds.mutex);
6265 /* init the internal cmd struct */
6266 memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
6267 INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
6269 /* Get and Populate a free Frame
6271 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
6272 dcprintk(ioc, printk(MYIOC_s_WARN_FMT
6273 "mpt_config: no msg frames!\n", ioc->name));
6274 ret = -EAGAIN;
6275 goto out;
6278 pReq = (Config_t *)mf;
6279 pReq->Action = pCfg->action;
6280 pReq->Reserved = 0;
6281 pReq->ChainOffset = 0;
6282 pReq->Function = MPI_FUNCTION_CONFIG;
6284 /* Assume page type is not extended and clear "reserved" fields. */
6285 pReq->ExtPageLength = 0;
6286 pReq->ExtPageType = 0;
6287 pReq->MsgFlags = 0;
6289 for (ii=0; ii < 8; ii++)
6290 pReq->Reserved2[ii] = 0;
6292 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
6293 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
6294 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
6295 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
6297 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
6298 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
6299 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
6300 pReq->ExtPageType = pExtHdr->ExtPageType;
6301 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
6303 /* Page Length must be treated as a reserved field for the
6304 * extended header.
6306 pReq->Header.PageLength = 0;
6309 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
6311 /* Add a SGE to the config request.
6313 if (pCfg->dir)
6314 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
6315 else
6316 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
6318 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
6319 MPI_CONFIG_PAGETYPE_EXTENDED) {
6320 flagsLength |= pExtHdr->ExtPageLength * 4;
6321 page_type = pReq->ExtPageType;
6322 extend_page = 1;
6323 } else {
6324 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
6325 page_type = pReq->Header.PageType;
6326 extend_page = 0;
6329 dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6330 "Sending Config request type 0x%x, page 0x%x and action %d\n",
6331 ioc->name, page_type, pReq->Header.PageNumber, pReq->Action));
6333 ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
6334 timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout;
6335 mpt_put_msg_frame(mpt_base_index, ioc, mf);
6336 timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done,
6337 timeout);
6338 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
6339 ret = -ETIME;
6340 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6341 "Failed Sending Config request type 0x%x, page 0x%x,"
6342 " action %d, status %xh, time left %ld\n\n",
6343 ioc->name, page_type, pReq->Header.PageNumber,
6344 pReq->Action, ioc->mptbase_cmds.status, timeleft));
6345 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
6346 goto out;
6347 if (!timeleft)
6348 issue_hard_reset = 1;
6349 goto out;
6352 if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
6353 ret = -1;
6354 goto out;
6356 pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply;
6357 ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
6358 if (ret == MPI_IOCSTATUS_SUCCESS) {
6359 if (extend_page) {
6360 pCfg->cfghdr.ehdr->ExtPageLength =
6361 le16_to_cpu(pReply->ExtPageLength);
6362 pCfg->cfghdr.ehdr->ExtPageType =
6363 pReply->ExtPageType;
6365 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
6366 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
6367 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
6368 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
6372 if (retry_count)
6373 printk(MYIOC_s_INFO_FMT "Retry completed "
6374 "ret=0x%x timeleft=%ld\n",
6375 ioc->name, ret, timeleft);
6377 dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
6378 ret, le32_to_cpu(pReply->IOCLogInfo)));
6380 out:
6382 CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
6383 mutex_unlock(&ioc->mptbase_cmds.mutex);
6384 if (issue_hard_reset) {
6385 issue_hard_reset = 0;
6386 printk(MYIOC_s_WARN_FMT
6387 "Issuing Reset from %s!!, doorbell=0x%08x\n",
6388 ioc->name, __func__, mpt_GetIocState(ioc, 0));
6389 if (retry_count == 0) {
6390 if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0)
6391 retry_count++;
6392 } else
6393 mpt_HardResetHandler(ioc, CAN_SLEEP);
6395 mpt_free_msg_frame(ioc, mf);
6396 /* attempt one retry for a timed out command */
6397 if (retry_count < 2) {
6398 printk(MYIOC_s_INFO_FMT
6399 "Attempting Retry Config request"
6400 " type 0x%x, page 0x%x,"
6401 " action %d\n", ioc->name, page_type,
6402 pCfg->cfghdr.hdr->PageNumber, pCfg->action);
6403 retry_count++;
6404 goto retry_config;
6407 return ret;
6411 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6413 * mpt_ioc_reset - Base cleanup for hard reset
6414 * @ioc: Pointer to the adapter structure
6415 * @reset_phase: Indicates pre- or post-reset functionality
6417 * Remark: Frees resources with internally generated commands.
6419 static int
6420 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
6422 switch (reset_phase) {
6423 case MPT_IOC_SETUP_RESET:
6424 ioc->taskmgmt_quiesce_io = 1;
6425 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6426 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
6427 break;
6428 case MPT_IOC_PRE_RESET:
6429 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6430 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
6431 break;
6432 case MPT_IOC_POST_RESET:
6433 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6434 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
6435 /* wake up mptbase_cmds */
6436 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
6437 ioc->mptbase_cmds.status |=
6438 MPT_MGMT_STATUS_DID_IOCRESET;
6439 complete(&ioc->mptbase_cmds.done);
6441 /* wake up taskmgmt_cmds */
6442 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
6443 ioc->taskmgmt_cmds.status |=
6444 MPT_MGMT_STATUS_DID_IOCRESET;
6445 complete(&ioc->taskmgmt_cmds.done);
6447 break;
6448 default:
6449 break;
6452 return 1; /* currently means nothing really */
6456 #ifdef CONFIG_PROC_FS /* { */
6457 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6459 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6461 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6463 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6465 * Returns 0 for success, non-zero for failure.
6467 static int
6468 procmpt_create(void)
6470 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6471 if (mpt_proc_root_dir == NULL)
6472 return -ENOTDIR;
6474 proc_create("summary", S_IRUGO, mpt_proc_root_dir, &mpt_summary_proc_fops);
6475 proc_create("version", S_IRUGO, mpt_proc_root_dir, &mpt_version_proc_fops);
6476 return 0;
6479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6481 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6483 * Returns 0 for success, non-zero for failure.
6485 static void
6486 procmpt_destroy(void)
6488 remove_proc_entry("version", mpt_proc_root_dir);
6489 remove_proc_entry("summary", mpt_proc_root_dir);
6490 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6495 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6497 static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan);
6499 static int mpt_summary_proc_show(struct seq_file *m, void *v)
6501 MPT_ADAPTER *ioc = m->private;
6503 if (ioc) {
6504 seq_mpt_print_ioc_summary(ioc, m, 1);
6505 } else {
6506 list_for_each_entry(ioc, &ioc_list, list) {
6507 seq_mpt_print_ioc_summary(ioc, m, 1);
6511 return 0;
6514 static int mpt_summary_proc_open(struct inode *inode, struct file *file)
6516 return single_open(file, mpt_summary_proc_show, PDE(inode)->data);
6519 static const struct file_operations mpt_summary_proc_fops = {
6520 .owner = THIS_MODULE,
6521 .open = mpt_summary_proc_open,
6522 .read = seq_read,
6523 .llseek = seq_lseek,
6524 .release = single_release,
6527 static int mpt_version_proc_show(struct seq_file *m, void *v)
6529 u8 cb_idx;
6530 int scsi, fc, sas, lan, ctl, targ, dmp;
6531 char *drvname;
6533 seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6534 seq_printf(m, " Fusion MPT base driver\n");
6536 scsi = fc = sas = lan = ctl = targ = dmp = 0;
6537 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6538 drvname = NULL;
6539 if (MptCallbacks[cb_idx]) {
6540 switch (MptDriverClass[cb_idx]) {
6541 case MPTSPI_DRIVER:
6542 if (!scsi++) drvname = "SPI host";
6543 break;
6544 case MPTFC_DRIVER:
6545 if (!fc++) drvname = "FC host";
6546 break;
6547 case MPTSAS_DRIVER:
6548 if (!sas++) drvname = "SAS host";
6549 break;
6550 case MPTLAN_DRIVER:
6551 if (!lan++) drvname = "LAN";
6552 break;
6553 case MPTSTM_DRIVER:
6554 if (!targ++) drvname = "SCSI target";
6555 break;
6556 case MPTCTL_DRIVER:
6557 if (!ctl++) drvname = "ioctl";
6558 break;
6561 if (drvname)
6562 seq_printf(m, " Fusion MPT %s driver\n", drvname);
6566 return 0;
6569 static int mpt_version_proc_open(struct inode *inode, struct file *file)
6571 return single_open(file, mpt_version_proc_show, NULL);
6574 static const struct file_operations mpt_version_proc_fops = {
6575 .owner = THIS_MODULE,
6576 .open = mpt_version_proc_open,
6577 .read = seq_read,
6578 .llseek = seq_lseek,
6579 .release = single_release,
6582 static int mpt_iocinfo_proc_show(struct seq_file *m, void *v)
6584 MPT_ADAPTER *ioc = m->private;
6585 char expVer[32];
6586 int sz;
6587 int p;
6589 mpt_get_fw_exp_ver(expVer, ioc);
6591 seq_printf(m, "%s:", ioc->name);
6592 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6593 seq_printf(m, " (f/w download boot flag set)");
6594 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6595 // seq_printf(m, " CONFIG_CHECKSUM_FAIL!");
6597 seq_printf(m, "\n ProductID = 0x%04x (%s)\n",
6598 ioc->facts.ProductID,
6599 ioc->prod_name);
6600 seq_printf(m, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6601 if (ioc->facts.FWImageSize)
6602 seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize);
6603 seq_printf(m, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6604 seq_printf(m, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6605 seq_printf(m, " EventState = 0x%02x\n", ioc->facts.EventState);
6607 seq_printf(m, " CurrentHostMfaHighAddr = 0x%08x\n",
6608 ioc->facts.CurrentHostMfaHighAddr);
6609 seq_printf(m, " CurrentSenseBufferHighAddr = 0x%08x\n",
6610 ioc->facts.CurrentSenseBufferHighAddr);
6612 seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6613 seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6615 seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6616 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6618 * Rounding UP to nearest 4-kB boundary here...
6620 sz = (ioc->req_sz * ioc->req_depth) + 128;
6621 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6622 seq_printf(m, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6623 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6624 seq_printf(m, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6625 4*ioc->facts.RequestFrameSize,
6626 ioc->facts.GlobalCredits);
6628 seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n",
6629 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6630 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6631 seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6632 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6633 seq_printf(m, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6634 ioc->facts.CurReplyFrameSize,
6635 ioc->facts.ReplyQueueDepth);
6637 seq_printf(m, " MaxDevices = %d\n",
6638 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6639 seq_printf(m, " MaxBuses = %d\n", ioc->facts.MaxBuses);
6641 /* per-port info */
6642 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6643 seq_printf(m, " PortNumber = %d (of %d)\n",
6644 p+1,
6645 ioc->facts.NumberOfPorts);
6646 if (ioc->bus_type == FC) {
6647 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6648 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6649 seq_printf(m, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6650 a[5], a[4], a[3], a[2], a[1], a[0]);
6652 seq_printf(m, " WWN = %08X%08X:%08X%08X\n",
6653 ioc->fc_port_page0[p].WWNN.High,
6654 ioc->fc_port_page0[p].WWNN.Low,
6655 ioc->fc_port_page0[p].WWPN.High,
6656 ioc->fc_port_page0[p].WWPN.Low);
6660 return 0;
6663 static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)
6665 return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data);
6668 static const struct file_operations mpt_iocinfo_proc_fops = {
6669 .owner = THIS_MODULE,
6670 .open = mpt_iocinfo_proc_open,
6671 .read = seq_read,
6672 .llseek = seq_lseek,
6673 .release = single_release,
6675 #endif /* CONFIG_PROC_FS } */
6677 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6678 static void
6679 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6681 buf[0] ='\0';
6682 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6683 sprintf(buf, " (Exp %02d%02d)",
6684 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
6685 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
6687 /* insider hack! */
6688 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6689 strcat(buf, " [MDBG]");
6693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6695 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6696 * @ioc: Pointer to MPT_ADAPTER structure
6697 * @buffer: Pointer to buffer where IOC summary info should be written
6698 * @size: Pointer to number of bytes we wrote (set by this routine)
6699 * @len: Offset at which to start writing in buffer
6700 * @showlan: Display LAN stuff?
6702 * This routine writes (english readable) ASCII text, which represents
6703 * a summary of IOC information, to a buffer.
6705 void
6706 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6708 char expVer[32];
6709 int y;
6711 mpt_get_fw_exp_ver(expVer, ioc);
6714 * Shorter summary of attached ioc's...
6716 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6717 ioc->name,
6718 ioc->prod_name,
6719 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6720 ioc->facts.FWVersion.Word,
6721 expVer,
6722 ioc->facts.NumberOfPorts,
6723 ioc->req_depth);
6725 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6726 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6727 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6728 a[5], a[4], a[3], a[2], a[1], a[0]);
6731 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6733 if (!ioc->active)
6734 y += sprintf(buffer+len+y, " (disabled)");
6736 y += sprintf(buffer+len+y, "\n");
6738 *size = y;
6741 static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan)
6743 char expVer[32];
6745 mpt_get_fw_exp_ver(expVer, ioc);
6748 * Shorter summary of attached ioc's...
6750 seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6751 ioc->name,
6752 ioc->prod_name,
6753 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
6754 ioc->facts.FWVersion.Word,
6755 expVer,
6756 ioc->facts.NumberOfPorts,
6757 ioc->req_depth);
6759 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6760 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6761 seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6762 a[5], a[4], a[3], a[2], a[1], a[0]);
6765 seq_printf(m, ", IRQ=%d", ioc->pci_irq);
6767 if (!ioc->active)
6768 seq_printf(m, " (disabled)");
6770 seq_putc(m, '\n');
6774 * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management
6775 * @ioc: Pointer to MPT_ADAPTER structure
6777 * Returns 0 for SUCCESS or -1 if FAILED.
6779 * If -1 is return, then it was not possible to set the flags
6782 mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6784 unsigned long flags;
6785 int retval;
6787 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6788 if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
6789 (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
6790 retval = -1;
6791 goto out;
6793 retval = 0;
6794 ioc->taskmgmt_in_progress = 1;
6795 ioc->taskmgmt_quiesce_io = 1;
6796 if (ioc->alt_ioc) {
6797 ioc->alt_ioc->taskmgmt_in_progress = 1;
6798 ioc->alt_ioc->taskmgmt_quiesce_io = 1;
6800 out:
6801 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6802 return retval;
6804 EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
6807 * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management
6808 * @ioc: Pointer to MPT_ADAPTER structure
6811 void
6812 mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6814 unsigned long flags;
6816 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6817 ioc->taskmgmt_in_progress = 0;
6818 ioc->taskmgmt_quiesce_io = 0;
6819 if (ioc->alt_ioc) {
6820 ioc->alt_ioc->taskmgmt_in_progress = 0;
6821 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
6823 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6825 EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
6829 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6830 * the kernel
6831 * @ioc: Pointer to MPT_ADAPTER structure
6834 void
6835 mpt_halt_firmware(MPT_ADAPTER *ioc)
6837 u32 ioc_raw_state;
6839 ioc_raw_state = mpt_GetIocState(ioc, 0);
6841 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6842 printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6843 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6844 panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6845 ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6846 } else {
6847 CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6848 panic("%s: Firmware is halted due to command timeout\n",
6849 ioc->name);
6852 EXPORT_SYMBOL(mpt_halt_firmware);
6855 * mpt_SoftResetHandler - Issues a less expensive reset
6856 * @ioc: Pointer to MPT_ADAPTER structure
6857 * @sleepFlag: Indicates if sleep or schedule must be called.
6859 * Returns 0 for SUCCESS or -1 if FAILED.
6861 * Message Unit Reset - instructs the IOC to reset the Reply Post and
6862 * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
6863 * All posted buffers are freed, and event notification is turned off.
6864 * IOC doesnt reply to any outstanding request. This will transfer IOC
6865 * to READY state.
6868 mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6870 int rc;
6871 int ii;
6872 u8 cb_idx;
6873 unsigned long flags;
6874 u32 ioc_state;
6875 unsigned long time_count;
6877 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n",
6878 ioc->name));
6880 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
6882 if (mpt_fwfault_debug)
6883 mpt_halt_firmware(ioc);
6885 if (ioc_state == MPI_IOC_STATE_FAULT ||
6886 ioc_state == MPI_IOC_STATE_RESET) {
6887 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6888 "skipping, either in FAULT or RESET state!\n", ioc->name));
6889 return -1;
6892 if (ioc->bus_type == FC) {
6893 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6894 "skipping, because the bus type is FC!\n", ioc->name));
6895 return -1;
6898 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6899 if (ioc->ioc_reset_in_progress) {
6900 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6901 return -1;
6903 ioc->ioc_reset_in_progress = 1;
6904 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6906 rc = -1;
6908 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6909 if (MptResetHandlers[cb_idx])
6910 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6913 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6914 if (ioc->taskmgmt_in_progress) {
6915 ioc->ioc_reset_in_progress = 0;
6916 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6917 return -1;
6919 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6920 /* Disable reply interrupts (also blocks FreeQ) */
6921 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
6922 ioc->active = 0;
6923 time_count = jiffies;
6925 rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
6927 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6928 if (MptResetHandlers[cb_idx])
6929 mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
6932 if (rc)
6933 goto out;
6935 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
6936 if (ioc_state != MPI_IOC_STATE_READY)
6937 goto out;
6939 for (ii = 0; ii < 5; ii++) {
6940 /* Get IOC facts! Allow 5 retries */
6941 rc = GetIocFacts(ioc, sleepFlag,
6942 MPT_HOSTEVENT_IOC_RECOVER);
6943 if (rc == 0)
6944 break;
6945 if (sleepFlag == CAN_SLEEP)
6946 msleep(100);
6947 else
6948 mdelay(100);
6950 if (ii == 5)
6951 goto out;
6953 rc = PrimeIocFifos(ioc);
6954 if (rc != 0)
6955 goto out;
6957 rc = SendIocInit(ioc, sleepFlag);
6958 if (rc != 0)
6959 goto out;
6961 rc = SendEventNotification(ioc, 1, sleepFlag);
6962 if (rc != 0)
6963 goto out;
6965 if (ioc->hard_resets < -1)
6966 ioc->hard_resets++;
6969 * At this point, we know soft reset succeeded.
6972 ioc->active = 1;
6973 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
6975 out:
6976 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6977 ioc->ioc_reset_in_progress = 0;
6978 ioc->taskmgmt_quiesce_io = 0;
6979 ioc->taskmgmt_in_progress = 0;
6980 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6982 if (ioc->active) { /* otherwise, hard reset coming */
6983 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6984 if (MptResetHandlers[cb_idx])
6985 mpt_signal_reset(cb_idx, ioc,
6986 MPT_IOC_POST_RESET);
6990 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6991 "SoftResetHandler: completed (%d seconds): %s\n",
6992 ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
6993 ((rc == 0) ? "SUCCESS" : "FAILED")));
6995 return rc;
6999 * mpt_Soft_Hard_ResetHandler - Try less expensive reset
7000 * @ioc: Pointer to MPT_ADAPTER structure
7001 * @sleepFlag: Indicates if sleep or schedule must be called.
7003 * Returns 0 for SUCCESS or -1 if FAILED.
7004 * Try for softreset first, only if it fails go for expensive
7005 * HardReset.
7008 mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) {
7009 int ret = -1;
7011 ret = mpt_SoftResetHandler(ioc, sleepFlag);
7012 if (ret == 0)
7013 return ret;
7014 ret = mpt_HardResetHandler(ioc, sleepFlag);
7015 return ret;
7017 EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler);
7019 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7021 * Reset Handling
7023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7025 * mpt_HardResetHandler - Generic reset handler
7026 * @ioc: Pointer to MPT_ADAPTER structure
7027 * @sleepFlag: Indicates if sleep or schedule must be called.
7029 * Issues SCSI Task Management call based on input arg values.
7030 * If TaskMgmt fails, returns associated SCSI request.
7032 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
7033 * or a non-interrupt thread. In the former, must not call schedule().
7035 * Note: A return of -1 is a FATAL error case, as it means a
7036 * FW reload/initialization failed.
7038 * Returns 0 for SUCCESS or -1 if FAILED.
7041 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7043 int rc;
7044 u8 cb_idx;
7045 unsigned long flags;
7046 unsigned long time_count;
7048 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
7049 #ifdef MFCNT
7050 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
7051 printk("MF count 0x%x !\n", ioc->mfcnt);
7052 #endif
7053 if (mpt_fwfault_debug)
7054 mpt_halt_firmware(ioc);
7056 /* Reset the adapter. Prevent more than 1 call to
7057 * mpt_do_ioc_recovery at any instant in time.
7059 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7060 if (ioc->ioc_reset_in_progress) {
7061 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7062 return 0;
7064 ioc->ioc_reset_in_progress = 1;
7065 if (ioc->alt_ioc)
7066 ioc->alt_ioc->ioc_reset_in_progress = 1;
7067 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7070 /* The SCSI driver needs to adjust timeouts on all current
7071 * commands prior to the diagnostic reset being issued.
7072 * Prevents timeouts occurring during a diagnostic reset...very bad.
7073 * For all other protocol drivers, this is a no-op.
7075 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7076 if (MptResetHandlers[cb_idx]) {
7077 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
7078 if (ioc->alt_ioc)
7079 mpt_signal_reset(cb_idx, ioc->alt_ioc,
7080 MPT_IOC_SETUP_RESET);
7084 time_count = jiffies;
7085 rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
7086 if (rc != 0) {
7087 printk(KERN_WARNING MYNAM
7088 ": WARNING - (%d) Cannot recover %s, doorbell=0x%08x\n",
7089 rc, ioc->name, mpt_GetIocState(ioc, 0));
7090 } else {
7091 if (ioc->hard_resets < -1)
7092 ioc->hard_resets++;
7095 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7096 ioc->ioc_reset_in_progress = 0;
7097 ioc->taskmgmt_quiesce_io = 0;
7098 ioc->taskmgmt_in_progress = 0;
7099 if (ioc->alt_ioc) {
7100 ioc->alt_ioc->ioc_reset_in_progress = 0;
7101 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
7102 ioc->alt_ioc->taskmgmt_in_progress = 0;
7104 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7106 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7107 if (MptResetHandlers[cb_idx]) {
7108 mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
7109 if (ioc->alt_ioc)
7110 mpt_signal_reset(cb_idx,
7111 ioc->alt_ioc, MPT_IOC_POST_RESET);
7115 dtmprintk(ioc,
7116 printk(MYIOC_s_DEBUG_FMT
7117 "HardResetHandler: completed (%d seconds): %s\n", ioc->name,
7118 jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ?
7119 "SUCCESS" : "FAILED")));
7121 return rc;
7124 #ifdef CONFIG_FUSION_LOGGING
7125 static void
7126 mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
7128 char *ds = NULL;
7129 u32 evData0;
7130 int ii;
7131 u8 event;
7132 char *evStr = ioc->evStr;
7134 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7135 evData0 = le32_to_cpu(pEventReply->Data[0]);
7137 switch(event) {
7138 case MPI_EVENT_NONE:
7139 ds = "None";
7140 break;
7141 case MPI_EVENT_LOG_DATA:
7142 ds = "Log Data";
7143 break;
7144 case MPI_EVENT_STATE_CHANGE:
7145 ds = "State Change";
7146 break;
7147 case MPI_EVENT_UNIT_ATTENTION:
7148 ds = "Unit Attention";
7149 break;
7150 case MPI_EVENT_IOC_BUS_RESET:
7151 ds = "IOC Bus Reset";
7152 break;
7153 case MPI_EVENT_EXT_BUS_RESET:
7154 ds = "External Bus Reset";
7155 break;
7156 case MPI_EVENT_RESCAN:
7157 ds = "Bus Rescan Event";
7158 break;
7159 case MPI_EVENT_LINK_STATUS_CHANGE:
7160 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
7161 ds = "Link Status(FAILURE) Change";
7162 else
7163 ds = "Link Status(ACTIVE) Change";
7164 break;
7165 case MPI_EVENT_LOOP_STATE_CHANGE:
7166 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
7167 ds = "Loop State(LIP) Change";
7168 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
7169 ds = "Loop State(LPE) Change";
7170 else
7171 ds = "Loop State(LPB) Change";
7172 break;
7173 case MPI_EVENT_LOGOUT:
7174 ds = "Logout";
7175 break;
7176 case MPI_EVENT_EVENT_CHANGE:
7177 if (evData0)
7178 ds = "Events ON";
7179 else
7180 ds = "Events OFF";
7181 break;
7182 case MPI_EVENT_INTEGRATED_RAID:
7184 u8 ReasonCode = (u8)(evData0 >> 16);
7185 switch (ReasonCode) {
7186 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
7187 ds = "Integrated Raid: Volume Created";
7188 break;
7189 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
7190 ds = "Integrated Raid: Volume Deleted";
7191 break;
7192 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
7193 ds = "Integrated Raid: Volume Settings Changed";
7194 break;
7195 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
7196 ds = "Integrated Raid: Volume Status Changed";
7197 break;
7198 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
7199 ds = "Integrated Raid: Volume Physdisk Changed";
7200 break;
7201 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
7202 ds = "Integrated Raid: Physdisk Created";
7203 break;
7204 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
7205 ds = "Integrated Raid: Physdisk Deleted";
7206 break;
7207 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
7208 ds = "Integrated Raid: Physdisk Settings Changed";
7209 break;
7210 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
7211 ds = "Integrated Raid: Physdisk Status Changed";
7212 break;
7213 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
7214 ds = "Integrated Raid: Domain Validation Needed";
7215 break;
7216 case MPI_EVENT_RAID_RC_SMART_DATA :
7217 ds = "Integrated Raid; Smart Data";
7218 break;
7219 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
7220 ds = "Integrated Raid: Replace Action Started";
7221 break;
7222 default:
7223 ds = "Integrated Raid";
7224 break;
7226 break;
7228 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
7229 ds = "SCSI Device Status Change";
7230 break;
7231 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
7233 u8 id = (u8)(evData0);
7234 u8 channel = (u8)(evData0 >> 8);
7235 u8 ReasonCode = (u8)(evData0 >> 16);
7236 switch (ReasonCode) {
7237 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
7238 snprintf(evStr, EVENT_DESCR_STR_SZ,
7239 "SAS Device Status Change: Added: "
7240 "id=%d channel=%d", id, channel);
7241 break;
7242 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
7243 snprintf(evStr, EVENT_DESCR_STR_SZ,
7244 "SAS Device Status Change: Deleted: "
7245 "id=%d channel=%d", id, channel);
7246 break;
7247 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7248 snprintf(evStr, EVENT_DESCR_STR_SZ,
7249 "SAS Device Status Change: SMART Data: "
7250 "id=%d channel=%d", id, channel);
7251 break;
7252 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
7253 snprintf(evStr, EVENT_DESCR_STR_SZ,
7254 "SAS Device Status Change: No Persistancy: "
7255 "id=%d channel=%d", id, channel);
7256 break;
7257 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7258 snprintf(evStr, EVENT_DESCR_STR_SZ,
7259 "SAS Device Status Change: Unsupported Device "
7260 "Discovered : id=%d channel=%d", id, channel);
7261 break;
7262 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7263 snprintf(evStr, EVENT_DESCR_STR_SZ,
7264 "SAS Device Status Change: Internal Device "
7265 "Reset : id=%d channel=%d", id, channel);
7266 break;
7267 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7268 snprintf(evStr, EVENT_DESCR_STR_SZ,
7269 "SAS Device Status Change: Internal Task "
7270 "Abort : id=%d channel=%d", id, channel);
7271 break;
7272 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7273 snprintf(evStr, EVENT_DESCR_STR_SZ,
7274 "SAS Device Status Change: Internal Abort "
7275 "Task Set : id=%d channel=%d", id, channel);
7276 break;
7277 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7278 snprintf(evStr, EVENT_DESCR_STR_SZ,
7279 "SAS Device Status Change: Internal Clear "
7280 "Task Set : id=%d channel=%d", id, channel);
7281 break;
7282 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7283 snprintf(evStr, EVENT_DESCR_STR_SZ,
7284 "SAS Device Status Change: Internal Query "
7285 "Task : id=%d channel=%d", id, channel);
7286 break;
7287 default:
7288 snprintf(evStr, EVENT_DESCR_STR_SZ,
7289 "SAS Device Status Change: Unknown: "
7290 "id=%d channel=%d", id, channel);
7291 break;
7293 break;
7295 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
7296 ds = "Bus Timer Expired";
7297 break;
7298 case MPI_EVENT_QUEUE_FULL:
7300 u16 curr_depth = (u16)(evData0 >> 16);
7301 u8 channel = (u8)(evData0 >> 8);
7302 u8 id = (u8)(evData0);
7304 snprintf(evStr, EVENT_DESCR_STR_SZ,
7305 "Queue Full: channel=%d id=%d depth=%d",
7306 channel, id, curr_depth);
7307 break;
7309 case MPI_EVENT_SAS_SES:
7310 ds = "SAS SES Event";
7311 break;
7312 case MPI_EVENT_PERSISTENT_TABLE_FULL:
7313 ds = "Persistent Table Full";
7314 break;
7315 case MPI_EVENT_SAS_PHY_LINK_STATUS:
7317 u8 LinkRates = (u8)(evData0 >> 8);
7318 u8 PhyNumber = (u8)(evData0);
7319 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
7320 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
7321 switch (LinkRates) {
7322 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
7323 snprintf(evStr, EVENT_DESCR_STR_SZ,
7324 "SAS PHY Link Status: Phy=%d:"
7325 " Rate Unknown",PhyNumber);
7326 break;
7327 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
7328 snprintf(evStr, EVENT_DESCR_STR_SZ,
7329 "SAS PHY Link Status: Phy=%d:"
7330 " Phy Disabled",PhyNumber);
7331 break;
7332 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
7333 snprintf(evStr, EVENT_DESCR_STR_SZ,
7334 "SAS PHY Link Status: Phy=%d:"
7335 " Failed Speed Nego",PhyNumber);
7336 break;
7337 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
7338 snprintf(evStr, EVENT_DESCR_STR_SZ,
7339 "SAS PHY Link Status: Phy=%d:"
7340 " Sata OOB Completed",PhyNumber);
7341 break;
7342 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
7343 snprintf(evStr, EVENT_DESCR_STR_SZ,
7344 "SAS PHY Link Status: Phy=%d:"
7345 " Rate 1.5 Gbps",PhyNumber);
7346 break;
7347 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
7348 snprintf(evStr, EVENT_DESCR_STR_SZ,
7349 "SAS PHY Link Status: Phy=%d:"
7350 " Rate 3.0 Gpbs",PhyNumber);
7351 break;
7352 default:
7353 snprintf(evStr, EVENT_DESCR_STR_SZ,
7354 "SAS PHY Link Status: Phy=%d", PhyNumber);
7355 break;
7357 break;
7359 case MPI_EVENT_SAS_DISCOVERY_ERROR:
7360 ds = "SAS Discovery Error";
7361 break;
7362 case MPI_EVENT_IR_RESYNC_UPDATE:
7364 u8 resync_complete = (u8)(evData0 >> 16);
7365 snprintf(evStr, EVENT_DESCR_STR_SZ,
7366 "IR Resync Update: Complete = %d:",resync_complete);
7367 break;
7369 case MPI_EVENT_IR2:
7371 u8 id = (u8)(evData0);
7372 u8 channel = (u8)(evData0 >> 8);
7373 u8 phys_num = (u8)(evData0 >> 24);
7374 u8 ReasonCode = (u8)(evData0 >> 16);
7376 switch (ReasonCode) {
7377 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
7378 snprintf(evStr, EVENT_DESCR_STR_SZ,
7379 "IR2: LD State Changed: "
7380 "id=%d channel=%d phys_num=%d",
7381 id, channel, phys_num);
7382 break;
7383 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
7384 snprintf(evStr, EVENT_DESCR_STR_SZ,
7385 "IR2: PD State Changed "
7386 "id=%d channel=%d phys_num=%d",
7387 id, channel, phys_num);
7388 break;
7389 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
7390 snprintf(evStr, EVENT_DESCR_STR_SZ,
7391 "IR2: Bad Block Table Full: "
7392 "id=%d channel=%d phys_num=%d",
7393 id, channel, phys_num);
7394 break;
7395 case MPI_EVENT_IR2_RC_PD_INSERTED:
7396 snprintf(evStr, EVENT_DESCR_STR_SZ,
7397 "IR2: PD Inserted: "
7398 "id=%d channel=%d phys_num=%d",
7399 id, channel, phys_num);
7400 break;
7401 case MPI_EVENT_IR2_RC_PD_REMOVED:
7402 snprintf(evStr, EVENT_DESCR_STR_SZ,
7403 "IR2: PD Removed: "
7404 "id=%d channel=%d phys_num=%d",
7405 id, channel, phys_num);
7406 break;
7407 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
7408 snprintf(evStr, EVENT_DESCR_STR_SZ,
7409 "IR2: Foreign CFG Detected: "
7410 "id=%d channel=%d phys_num=%d",
7411 id, channel, phys_num);
7412 break;
7413 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
7414 snprintf(evStr, EVENT_DESCR_STR_SZ,
7415 "IR2: Rebuild Medium Error: "
7416 "id=%d channel=%d phys_num=%d",
7417 id, channel, phys_num);
7418 break;
7419 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
7420 snprintf(evStr, EVENT_DESCR_STR_SZ,
7421 "IR2: Dual Port Added: "
7422 "id=%d channel=%d phys_num=%d",
7423 id, channel, phys_num);
7424 break;
7425 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
7426 snprintf(evStr, EVENT_DESCR_STR_SZ,
7427 "IR2: Dual Port Removed: "
7428 "id=%d channel=%d phys_num=%d",
7429 id, channel, phys_num);
7430 break;
7431 default:
7432 ds = "IR2";
7433 break;
7435 break;
7437 case MPI_EVENT_SAS_DISCOVERY:
7439 if (evData0)
7440 ds = "SAS Discovery: Start";
7441 else
7442 ds = "SAS Discovery: Stop";
7443 break;
7445 case MPI_EVENT_LOG_ENTRY_ADDED:
7446 ds = "SAS Log Entry Added";
7447 break;
7449 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
7451 u8 phy_num = (u8)(evData0);
7452 u8 port_num = (u8)(evData0 >> 8);
7453 u8 port_width = (u8)(evData0 >> 16);
7454 u8 primative = (u8)(evData0 >> 24);
7455 snprintf(evStr, EVENT_DESCR_STR_SZ,
7456 "SAS Broadcase Primative: phy=%d port=%d "
7457 "width=%d primative=0x%02x",
7458 phy_num, port_num, port_width, primative);
7459 break;
7462 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
7464 u8 reason = (u8)(evData0);
7466 switch (reason) {
7467 case MPI_EVENT_SAS_INIT_RC_ADDED:
7468 ds = "SAS Initiator Status Change: Added";
7469 break;
7470 case MPI_EVENT_SAS_INIT_RC_REMOVED:
7471 ds = "SAS Initiator Status Change: Deleted";
7472 break;
7473 default:
7474 ds = "SAS Initiator Status Change";
7475 break;
7477 break;
7480 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
7482 u8 max_init = (u8)(evData0);
7483 u8 current_init = (u8)(evData0 >> 8);
7485 snprintf(evStr, EVENT_DESCR_STR_SZ,
7486 "SAS Initiator Device Table Overflow: max initiators=%02d "
7487 "current initators=%02d",
7488 max_init, current_init);
7489 break;
7491 case MPI_EVENT_SAS_SMP_ERROR:
7493 u8 status = (u8)(evData0);
7494 u8 port_num = (u8)(evData0 >> 8);
7495 u8 result = (u8)(evData0 >> 16);
7497 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
7498 snprintf(evStr, EVENT_DESCR_STR_SZ,
7499 "SAS SMP Error: port=%d result=0x%02x",
7500 port_num, result);
7501 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
7502 snprintf(evStr, EVENT_DESCR_STR_SZ,
7503 "SAS SMP Error: port=%d : CRC Error",
7504 port_num);
7505 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
7506 snprintf(evStr, EVENT_DESCR_STR_SZ,
7507 "SAS SMP Error: port=%d : Timeout",
7508 port_num);
7509 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
7510 snprintf(evStr, EVENT_DESCR_STR_SZ,
7511 "SAS SMP Error: port=%d : No Destination",
7512 port_num);
7513 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
7514 snprintf(evStr, EVENT_DESCR_STR_SZ,
7515 "SAS SMP Error: port=%d : Bad Destination",
7516 port_num);
7517 else
7518 snprintf(evStr, EVENT_DESCR_STR_SZ,
7519 "SAS SMP Error: port=%d : status=0x%02x",
7520 port_num, status);
7521 break;
7524 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
7526 u8 reason = (u8)(evData0);
7528 switch (reason) {
7529 case MPI_EVENT_SAS_EXP_RC_ADDED:
7530 ds = "Expander Status Change: Added";
7531 break;
7532 case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
7533 ds = "Expander Status Change: Deleted";
7534 break;
7535 default:
7536 ds = "Expander Status Change";
7537 break;
7539 break;
7543 * MPT base "custom" events may be added here...
7545 default:
7546 ds = "Unknown";
7547 break;
7549 if (ds)
7550 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
7553 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7554 "MPT event:(%02Xh) : %s\n",
7555 ioc->name, event, evStr));
7557 devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
7558 ": Event data:\n"));
7559 for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
7560 devtverboseprintk(ioc, printk(" %08x",
7561 le32_to_cpu(pEventReply->Data[ii])));
7562 devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
7564 #endif
7565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7567 * ProcessEventNotification - Route EventNotificationReply to all event handlers
7568 * @ioc: Pointer to MPT_ADAPTER structure
7569 * @pEventReply: Pointer to EventNotification reply frame
7570 * @evHandlers: Pointer to integer, number of event handlers
7572 * Routes a received EventNotificationReply to all currently registered
7573 * event handlers.
7574 * Returns sum of event handlers return values.
7576 static int
7577 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
7579 u16 evDataLen;
7580 u32 evData0 = 0;
7581 int ii;
7582 u8 cb_idx;
7583 int r = 0;
7584 int handlers = 0;
7585 u8 event;
7588 * Do platform normalization of values
7590 event = le32_to_cpu(pEventReply->Event) & 0xFF;
7591 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
7592 if (evDataLen) {
7593 evData0 = le32_to_cpu(pEventReply->Data[0]);
7596 #ifdef CONFIG_FUSION_LOGGING
7597 if (evDataLen)
7598 mpt_display_event_info(ioc, pEventReply);
7599 #endif
7602 * Do general / base driver event processing
7604 switch(event) {
7605 case MPI_EVENT_EVENT_CHANGE: /* 0A */
7606 if (evDataLen) {
7607 u8 evState = evData0 & 0xFF;
7609 /* CHECKME! What if evState unexpectedly says OFF (0)? */
7611 /* Update EventState field in cached IocFacts */
7612 if (ioc->facts.Function) {
7613 ioc->facts.EventState = evState;
7616 break;
7617 case MPI_EVENT_INTEGRATED_RAID:
7618 mptbase_raid_process_event_data(ioc,
7619 (MpiEventDataRaid_t *)pEventReply->Data);
7620 break;
7621 default:
7622 break;
7626 * Should this event be logged? Events are written sequentially.
7627 * When buffer is full, start again at the top.
7629 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
7630 int idx;
7632 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
7634 ioc->events[idx].event = event;
7635 ioc->events[idx].eventContext = ioc->eventContext;
7637 for (ii = 0; ii < 2; ii++) {
7638 if (ii < evDataLen)
7639 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
7640 else
7641 ioc->events[idx].data[ii] = 0;
7644 ioc->eventContext++;
7649 * Call each currently registered protocol event handler.
7651 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7652 if (MptEvHandlers[cb_idx]) {
7653 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7654 "Routing Event to event handler #%d\n",
7655 ioc->name, cb_idx));
7656 r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
7657 handlers++;
7662 * If needed, send (a single) EventAck.
7664 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
7665 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7666 "EventAck required\n",ioc->name));
7667 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
7668 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
7669 ioc->name, ii));
7673 *evHandlers = handlers;
7674 return r;
7677 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7679 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
7680 * @ioc: Pointer to MPT_ADAPTER structure
7681 * @log_info: U32 LogInfo reply word from the IOC
7683 * Refer to lsi/mpi_log_fc.h.
7685 static void
7686 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
7688 char *desc = "unknown";
7690 switch (log_info & 0xFF000000) {
7691 case MPI_IOCLOGINFO_FC_INIT_BASE:
7692 desc = "FCP Initiator";
7693 break;
7694 case MPI_IOCLOGINFO_FC_TARGET_BASE:
7695 desc = "FCP Target";
7696 break;
7697 case MPI_IOCLOGINFO_FC_LAN_BASE:
7698 desc = "LAN";
7699 break;
7700 case MPI_IOCLOGINFO_FC_MSG_BASE:
7701 desc = "MPI Message Layer";
7702 break;
7703 case MPI_IOCLOGINFO_FC_LINK_BASE:
7704 desc = "FC Link";
7705 break;
7706 case MPI_IOCLOGINFO_FC_CTX_BASE:
7707 desc = "Context Manager";
7708 break;
7709 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
7710 desc = "Invalid Field Offset";
7711 break;
7712 case MPI_IOCLOGINFO_FC_STATE_CHANGE:
7713 desc = "State Change Info";
7714 break;
7717 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
7718 ioc->name, log_info, desc, (log_info & 0xFFFFFF));
7721 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7723 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7724 * @ioc: Pointer to MPT_ADAPTER structure
7725 * @log_info: U32 LogInfo word from the IOC
7727 * Refer to lsi/sp_log.h.
7729 static void
7730 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7732 u32 info = log_info & 0x00FF0000;
7733 char *desc = "unknown";
7735 switch (info) {
7736 case 0x00010000:
7737 desc = "bug! MID not found";
7738 break;
7740 case 0x00020000:
7741 desc = "Parity Error";
7742 break;
7744 case 0x00030000:
7745 desc = "ASYNC Outbound Overrun";
7746 break;
7748 case 0x00040000:
7749 desc = "SYNC Offset Error";
7750 break;
7752 case 0x00050000:
7753 desc = "BM Change";
7754 break;
7756 case 0x00060000:
7757 desc = "Msg In Overflow";
7758 break;
7760 case 0x00070000:
7761 desc = "DMA Error";
7762 break;
7764 case 0x00080000:
7765 desc = "Outbound DMA Overrun";
7766 break;
7768 case 0x00090000:
7769 desc = "Task Management";
7770 break;
7772 case 0x000A0000:
7773 desc = "Device Problem";
7774 break;
7776 case 0x000B0000:
7777 desc = "Invalid Phase Change";
7778 break;
7780 case 0x000C0000:
7781 desc = "Untagged Table Size";
7782 break;
7786 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7789 /* strings for sas loginfo */
7790 static char *originator_str[] = {
7791 "IOP", /* 00h */
7792 "PL", /* 01h */
7793 "IR" /* 02h */
7795 static char *iop_code_str[] = {
7796 NULL, /* 00h */
7797 "Invalid SAS Address", /* 01h */
7798 NULL, /* 02h */
7799 "Invalid Page", /* 03h */
7800 "Diag Message Error", /* 04h */
7801 "Task Terminated", /* 05h */
7802 "Enclosure Management", /* 06h */
7803 "Target Mode" /* 07h */
7805 static char *pl_code_str[] = {
7806 NULL, /* 00h */
7807 "Open Failure", /* 01h */
7808 "Invalid Scatter Gather List", /* 02h */
7809 "Wrong Relative Offset or Frame Length", /* 03h */
7810 "Frame Transfer Error", /* 04h */
7811 "Transmit Frame Connected Low", /* 05h */
7812 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7813 "SATA Read Log Receive Data Error", /* 07h */
7814 "SATA NCQ Fail All Commands After Error", /* 08h */
7815 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7816 "Receive Frame Invalid Message", /* 0Ah */
7817 "Receive Context Message Valid Error", /* 0Bh */
7818 "Receive Frame Current Frame Error", /* 0Ch */
7819 "SATA Link Down", /* 0Dh */
7820 "Discovery SATA Init W IOS", /* 0Eh */
7821 "Config Invalid Page", /* 0Fh */
7822 "Discovery SATA Init Timeout", /* 10h */
7823 "Reset", /* 11h */
7824 "Abort", /* 12h */
7825 "IO Not Yet Executed", /* 13h */
7826 "IO Executed", /* 14h */
7827 "Persistent Reservation Out Not Affiliation "
7828 "Owner", /* 15h */
7829 "Open Transmit DMA Abort", /* 16h */
7830 "IO Device Missing Delay Retry", /* 17h */
7831 "IO Cancelled Due to Recieve Error", /* 18h */
7832 NULL, /* 19h */
7833 NULL, /* 1Ah */
7834 NULL, /* 1Bh */
7835 NULL, /* 1Ch */
7836 NULL, /* 1Dh */
7837 NULL, /* 1Eh */
7838 NULL, /* 1Fh */
7839 "Enclosure Management" /* 20h */
7841 static char *ir_code_str[] = {
7842 "Raid Action Error", /* 00h */
7843 NULL, /* 00h */
7844 NULL, /* 01h */
7845 NULL, /* 02h */
7846 NULL, /* 03h */
7847 NULL, /* 04h */
7848 NULL, /* 05h */
7849 NULL, /* 06h */
7850 NULL /* 07h */
7852 static char *raid_sub_code_str[] = {
7853 NULL, /* 00h */
7854 "Volume Creation Failed: Data Passed too "
7855 "Large", /* 01h */
7856 "Volume Creation Failed: Duplicate Volumes "
7857 "Attempted", /* 02h */
7858 "Volume Creation Failed: Max Number "
7859 "Supported Volumes Exceeded", /* 03h */
7860 "Volume Creation Failed: DMA Error", /* 04h */
7861 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7862 "Volume Creation Failed: Error Reading "
7863 "MFG Page 4", /* 06h */
7864 "Volume Creation Failed: Creating Internal "
7865 "Structures", /* 07h */
7866 NULL, /* 08h */
7867 NULL, /* 09h */
7868 NULL, /* 0Ah */
7869 NULL, /* 0Bh */
7870 NULL, /* 0Ch */
7871 NULL, /* 0Dh */
7872 NULL, /* 0Eh */
7873 NULL, /* 0Fh */
7874 "Activation failed: Already Active Volume", /* 10h */
7875 "Activation failed: Unsupported Volume Type", /* 11h */
7876 "Activation failed: Too Many Active Volumes", /* 12h */
7877 "Activation failed: Volume ID in Use", /* 13h */
7878 "Activation failed: Reported Failure", /* 14h */
7879 "Activation failed: Importing a Volume", /* 15h */
7880 NULL, /* 16h */
7881 NULL, /* 17h */
7882 NULL, /* 18h */
7883 NULL, /* 19h */
7884 NULL, /* 1Ah */
7885 NULL, /* 1Bh */
7886 NULL, /* 1Ch */
7887 NULL, /* 1Dh */
7888 NULL, /* 1Eh */
7889 NULL, /* 1Fh */
7890 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7891 "Phys Disk failed: Data Passed too Large", /* 21h */
7892 "Phys Disk failed: DMA Error", /* 22h */
7893 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7894 "Phys Disk failed: Creating Phys Disk Config "
7895 "Page", /* 24h */
7896 NULL, /* 25h */
7897 NULL, /* 26h */
7898 NULL, /* 27h */
7899 NULL, /* 28h */
7900 NULL, /* 29h */
7901 NULL, /* 2Ah */
7902 NULL, /* 2Bh */
7903 NULL, /* 2Ch */
7904 NULL, /* 2Dh */
7905 NULL, /* 2Eh */
7906 NULL, /* 2Fh */
7907 "Compatibility Error: IR Disabled", /* 30h */
7908 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7909 "Compatibility Error: Device not Direct Access "
7910 "Device ", /* 32h */
7911 "Compatibility Error: Removable Device Found", /* 33h */
7912 "Compatibility Error: Device SCSI Version not "
7913 "2 or Higher", /* 34h */
7914 "Compatibility Error: SATA Device, 48 BIT LBA "
7915 "not Supported", /* 35h */
7916 "Compatibility Error: Device doesn't have "
7917 "512 Byte Block Sizes", /* 36h */
7918 "Compatibility Error: Volume Type Check Failed", /* 37h */
7919 "Compatibility Error: Volume Type is "
7920 "Unsupported by FW", /* 38h */
7921 "Compatibility Error: Disk Drive too Small for "
7922 "use in Volume", /* 39h */
7923 "Compatibility Error: Phys Disk for Create "
7924 "Volume not Found", /* 3Ah */
7925 "Compatibility Error: Too Many or too Few "
7926 "Disks for Volume Type", /* 3Bh */
7927 "Compatibility Error: Disk stripe Sizes "
7928 "Must be 64KB", /* 3Ch */
7929 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7932 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7934 * mpt_sas_log_info - Log information returned from SAS IOC.
7935 * @ioc: Pointer to MPT_ADAPTER structure
7936 * @log_info: U32 LogInfo reply word from the IOC
7937 * @cb_idx: callback function's handle
7939 * Refer to lsi/mpi_log_sas.h.
7941 static void
7942 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx)
7944 union loginfo_type {
7945 u32 loginfo;
7946 struct {
7947 u32 subcode:16;
7948 u32 code:8;
7949 u32 originator:4;
7950 u32 bus_type:4;
7951 }dw;
7953 union loginfo_type sas_loginfo;
7954 char *originator_desc = NULL;
7955 char *code_desc = NULL;
7956 char *sub_code_desc = NULL;
7958 sas_loginfo.loginfo = log_info;
7959 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7960 (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
7961 return;
7963 originator_desc = originator_str[sas_loginfo.dw.originator];
7965 switch (sas_loginfo.dw.originator) {
7967 case 0: /* IOP */
7968 if (sas_loginfo.dw.code <
7969 ARRAY_SIZE(iop_code_str))
7970 code_desc = iop_code_str[sas_loginfo.dw.code];
7971 break;
7972 case 1: /* PL */
7973 if (sas_loginfo.dw.code <
7974 ARRAY_SIZE(pl_code_str))
7975 code_desc = pl_code_str[sas_loginfo.dw.code];
7976 break;
7977 case 2: /* IR */
7978 if (sas_loginfo.dw.code >=
7979 ARRAY_SIZE(ir_code_str))
7980 break;
7981 code_desc = ir_code_str[sas_loginfo.dw.code];
7982 if (sas_loginfo.dw.subcode >=
7983 ARRAY_SIZE(raid_sub_code_str))
7984 break;
7985 if (sas_loginfo.dw.code == 0)
7986 sub_code_desc =
7987 raid_sub_code_str[sas_loginfo.dw.subcode];
7988 break;
7989 default:
7990 return;
7993 if (sub_code_desc != NULL)
7994 printk(MYIOC_s_INFO_FMT
7995 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7996 " SubCode={%s} cb_idx %s\n",
7997 ioc->name, log_info, originator_desc, code_desc,
7998 sub_code_desc, MptCallbacksName[cb_idx]);
7999 else if (code_desc != NULL)
8000 printk(MYIOC_s_INFO_FMT
8001 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
8002 " SubCode(0x%04x) cb_idx %s\n",
8003 ioc->name, log_info, originator_desc, code_desc,
8004 sas_loginfo.dw.subcode, MptCallbacksName[cb_idx]);
8005 else
8006 printk(MYIOC_s_INFO_FMT
8007 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
8008 " SubCode(0x%04x) cb_idx %s\n",
8009 ioc->name, log_info, originator_desc,
8010 sas_loginfo.dw.code, sas_loginfo.dw.subcode,
8011 MptCallbacksName[cb_idx]);
8014 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8016 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
8017 * @ioc: Pointer to MPT_ADAPTER structure
8018 * @ioc_status: U32 IOCStatus word from IOC
8019 * @mf: Pointer to MPT request frame
8021 * Refer to lsi/mpi.h.
8023 static void
8024 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8026 Config_t *pReq = (Config_t *)mf;
8027 char extend_desc[EVENT_DESCR_STR_SZ];
8028 char *desc = NULL;
8029 u32 form;
8030 u8 page_type;
8032 if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
8033 page_type = pReq->ExtPageType;
8034 else
8035 page_type = pReq->Header.PageType;
8038 * ignore invalid page messages for GET_NEXT_HANDLE
8040 form = le32_to_cpu(pReq->PageAddress);
8041 if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
8042 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
8043 page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
8044 page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
8045 if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
8046 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
8047 return;
8049 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
8050 if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
8051 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
8052 return;
8055 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
8056 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
8057 page_type, pReq->Header.PageNumber, pReq->Action, form);
8059 switch (ioc_status) {
8061 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8062 desc = "Config Page Invalid Action";
8063 break;
8065 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
8066 desc = "Config Page Invalid Type";
8067 break;
8069 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
8070 desc = "Config Page Invalid Page";
8071 break;
8073 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
8074 desc = "Config Page Invalid Data";
8075 break;
8077 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
8078 desc = "Config Page No Defaults";
8079 break;
8081 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
8082 desc = "Config Page Can't Commit";
8083 break;
8086 if (!desc)
8087 return;
8089 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
8090 ioc->name, ioc_status, desc, extend_desc));
8094 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
8095 * @ioc: Pointer to MPT_ADAPTER structure
8096 * @ioc_status: U32 IOCStatus word from IOC
8097 * @mf: Pointer to MPT request frame
8099 * Refer to lsi/mpi.h.
8101 static void
8102 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8104 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
8105 char *desc = NULL;
8107 switch (status) {
8109 /****************************************************************************/
8110 /* Common IOCStatus values for all replies */
8111 /****************************************************************************/
8113 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
8114 desc = "Invalid Function";
8115 break;
8117 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
8118 desc = "Busy";
8119 break;
8121 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
8122 desc = "Invalid SGL";
8123 break;
8125 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
8126 desc = "Internal Error";
8127 break;
8129 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
8130 desc = "Reserved";
8131 break;
8133 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
8134 desc = "Insufficient Resources";
8135 break;
8137 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
8138 desc = "Invalid Field";
8139 break;
8141 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
8142 desc = "Invalid State";
8143 break;
8145 /****************************************************************************/
8146 /* Config IOCStatus values */
8147 /****************************************************************************/
8149 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8150 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
8151 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
8152 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
8153 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
8154 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
8155 mpt_iocstatus_info_config(ioc, status, mf);
8156 break;
8158 /****************************************************************************/
8159 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
8160 /* */
8161 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
8162 /* */
8163 /****************************************************************************/
8165 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
8166 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
8167 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
8168 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
8169 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
8170 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
8171 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
8172 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
8173 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
8174 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
8175 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
8176 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
8177 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
8178 break;
8180 /****************************************************************************/
8181 /* SCSI Target values */
8182 /****************************************************************************/
8184 case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
8185 desc = "Target: Priority IO";
8186 break;
8188 case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
8189 desc = "Target: Invalid Port";
8190 break;
8192 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
8193 desc = "Target Invalid IO Index:";
8194 break;
8196 case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
8197 desc = "Target: Aborted";
8198 break;
8200 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
8201 desc = "Target: No Conn Retryable";
8202 break;
8204 case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
8205 desc = "Target: No Connection";
8206 break;
8208 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
8209 desc = "Target: Transfer Count Mismatch";
8210 break;
8212 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
8213 desc = "Target: STS Data not Sent";
8214 break;
8216 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
8217 desc = "Target: Data Offset Error";
8218 break;
8220 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
8221 desc = "Target: Too Much Write Data";
8222 break;
8224 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
8225 desc = "Target: IU Too Short";
8226 break;
8228 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
8229 desc = "Target: ACK NAK Timeout";
8230 break;
8232 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
8233 desc = "Target: Nak Received";
8234 break;
8236 /****************************************************************************/
8237 /* Fibre Channel Direct Access values */
8238 /****************************************************************************/
8240 case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
8241 desc = "FC: Aborted";
8242 break;
8244 case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
8245 desc = "FC: RX ID Invalid";
8246 break;
8248 case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
8249 desc = "FC: DID Invalid";
8250 break;
8252 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
8253 desc = "FC: Node Logged Out";
8254 break;
8256 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
8257 desc = "FC: Exchange Canceled";
8258 break;
8260 /****************************************************************************/
8261 /* LAN values */
8262 /****************************************************************************/
8264 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
8265 desc = "LAN: Device not Found";
8266 break;
8268 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
8269 desc = "LAN: Device Failure";
8270 break;
8272 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
8273 desc = "LAN: Transmit Error";
8274 break;
8276 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
8277 desc = "LAN: Transmit Aborted";
8278 break;
8280 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
8281 desc = "LAN: Receive Error";
8282 break;
8284 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
8285 desc = "LAN: Receive Aborted";
8286 break;
8288 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
8289 desc = "LAN: Partial Packet";
8290 break;
8292 case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
8293 desc = "LAN: Canceled";
8294 break;
8296 /****************************************************************************/
8297 /* Serial Attached SCSI values */
8298 /****************************************************************************/
8300 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
8301 desc = "SAS: SMP Request Failed";
8302 break;
8304 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
8305 desc = "SAS: SMP Data Overrun";
8306 break;
8308 default:
8309 desc = "Others";
8310 break;
8313 if (!desc)
8314 return;
8316 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
8317 ioc->name, status, desc));
8320 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8321 EXPORT_SYMBOL(mpt_attach);
8322 EXPORT_SYMBOL(mpt_detach);
8323 #ifdef CONFIG_PM
8324 EXPORT_SYMBOL(mpt_resume);
8325 EXPORT_SYMBOL(mpt_suspend);
8326 #endif
8327 EXPORT_SYMBOL(ioc_list);
8328 EXPORT_SYMBOL(mpt_register);
8329 EXPORT_SYMBOL(mpt_deregister);
8330 EXPORT_SYMBOL(mpt_event_register);
8331 EXPORT_SYMBOL(mpt_event_deregister);
8332 EXPORT_SYMBOL(mpt_reset_register);
8333 EXPORT_SYMBOL(mpt_reset_deregister);
8334 EXPORT_SYMBOL(mpt_device_driver_register);
8335 EXPORT_SYMBOL(mpt_device_driver_deregister);
8336 EXPORT_SYMBOL(mpt_get_msg_frame);
8337 EXPORT_SYMBOL(mpt_put_msg_frame);
8338 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
8339 EXPORT_SYMBOL(mpt_free_msg_frame);
8340 EXPORT_SYMBOL(mpt_send_handshake_request);
8341 EXPORT_SYMBOL(mpt_verify_adapter);
8342 EXPORT_SYMBOL(mpt_GetIocState);
8343 EXPORT_SYMBOL(mpt_print_ioc_summary);
8344 EXPORT_SYMBOL(mpt_HardResetHandler);
8345 EXPORT_SYMBOL(mpt_config);
8346 EXPORT_SYMBOL(mpt_findImVolumes);
8347 EXPORT_SYMBOL(mpt_alloc_fw_memory);
8348 EXPORT_SYMBOL(mpt_free_fw_memory);
8349 EXPORT_SYMBOL(mptbase_sas_persist_operation);
8350 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
8352 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8354 * fusion_init - Fusion MPT base driver initialization routine.
8356 * Returns 0 for success, non-zero for failure.
8358 static int __init
8359 fusion_init(void)
8361 u8 cb_idx;
8363 show_mptmod_ver(my_NAME, my_VERSION);
8364 printk(KERN_INFO COPYRIGHT "\n");
8366 for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
8367 MptCallbacks[cb_idx] = NULL;
8368 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
8369 MptEvHandlers[cb_idx] = NULL;
8370 MptResetHandlers[cb_idx] = NULL;
8373 /* Register ourselves (mptbase) in order to facilitate
8374 * EventNotification handling.
8376 mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER,
8377 "mptbase_reply");
8379 /* Register for hard reset handling callbacks.
8381 mpt_reset_register(mpt_base_index, mpt_ioc_reset);
8383 #ifdef CONFIG_PROC_FS
8384 (void) procmpt_create();
8385 #endif
8386 return 0;
8389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8391 * fusion_exit - Perform driver unload cleanup.
8393 * This routine frees all resources associated with each MPT adapter
8394 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
8396 static void __exit
8397 fusion_exit(void)
8400 mpt_reset_deregister(mpt_base_index);
8402 #ifdef CONFIG_PROC_FS
8403 procmpt_destroy();
8404 #endif
8407 module_init(fusion_init);
8408 module_exit(fusion_exit);