/*
* linux/drivers/message/fusion/mptbase.c
- * High performance SCSI + LAN / Fibre Channel device drivers.
* This is the Fusion MPT base driver which supports multiple
* (SCSI + LAN) specialized protocol drivers.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * There are lots of people not mentioned below that deserve credit
- * and thanks but won't get it here - sorry in advance that you
- * got overlooked.
- *
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A special thanks to Noah Romer (LSI Logic) for tons of work
- * and tough debugging on the LAN driver, especially early on;-)
- * And to Roger Hickerson (LSI Logic) for tirelessly supporting
- * this driver project.
- *
- * A special thanks to Pamela Delaney (LSI Logic) for tons of work
- * and countless enhancements while adding support for the 1030
- * chip family. Pam has been instrumental in the development of
- * of the 2.xx.xx series fusion drivers, and her contributions are
- * far too numerous to hope to list in one place.
- *
- * All manner of help from Stephen Shirron (LSI Logic):
- * low-level FC analysis, debug + various fixes in FCxx firmware,
- * initial port to alpha platform, various driver code optimizations,
- * being a faithful sounding board on all sorts of issues & ideas,
- * etc.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * Special thanks goes to the I2O LAN driver people at the
- * University of Helsinki, who, unbeknownst to them, provided
- * the inspiration and initial structure for this driver.
- *
- * A really huge debt of gratitude is owed to Eddie C. Dost
- * for gobs of hard work fixing and optimizing LAN code.
- * THANK YOU!
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
/*
* cmd line parameters
*/
+static int mpt_msi_enable;
+module_param(mpt_msi_enable, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
#ifdef MFCNT
static int mfcounter = 0;
#define PRINT_MF_COUNT 20000
struct proc_dir_entry *mpt_proc_root_dir;
-DmpServices_t *DmpService;
-
-void *mpt_v_ASCQ_TablePtr;
-const char **mpt_ScsiOpcodesPtr;
-int mpt_ASCQ_TableSz;
-
-
#define WHOINIT_UNKNOWN 0xAA
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private data...
*/
- /* Adapter lookup table */
- MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS];
-static MPT_ADAPTER_TRACKER MptAdapters;
+ /* Adapter link list */
+LIST_HEAD(ioc_list);
/* Callback lookup table */
static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
/* Protocol driver class lookup table */
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
-static int FusionInitCalled = 0;
static int mpt_base_index = -1;
static int last_drv_idx = -1;
-static int isense_idx = -1;
static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
*/
static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
-
+static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
+ u32 *req, int replyBytes, u16 *u16reply, int maxwait,
+ int sleepFlag);
static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
-static void mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
-static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
+static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+static void mpt_adapter_disable(MPT_ADAPTER *ioc);
static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
-//static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
-static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
+static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int GetLanConfigPages(MPT_ADAPTER *ioc);
-static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
static int GetIoUnitPage2(MPT_ADAPTER *ioc);
+int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
static void mpt_timer_expired(unsigned long data);
static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
+static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
#ifdef CONFIG_PROC_FS
-static int procmpt_create(void);
-static int procmpt_destroy(void);
static int procmpt_summary_read(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
static int procmpt_version_read(char *buf, char **start, off_t offset,
//int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
+static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
-static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
/* module entry point */
-static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit mptbase_remove(struct pci_dev *);
-static void mptbase_shutdown(struct device * );
static int __init fusion_init (void);
static void __exit fusion_exit (void);
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define CHIPREG_READ32(addr) readl_relaxed(addr)
+#define CHIPREG_READ32_dmasync(addr) readl(addr)
+#define CHIPREG_WRITE32(addr,val) writel(val, addr)
+#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
+#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
+
+static void
+pci_disable_io_access(struct pci_dev *pdev)
+{
+ u16 command_reg;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+ command_reg &= ~1;
+ pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
+static void
+pci_enable_io_access(struct pci_dev *pdev)
+{
+ u16 command_reg;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+ command_reg |= 1;
+ pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
/*
- * more Private data...
+ * Process turbo (context) reply...
*/
-#ifdef CONFIG_PROC_FS
-struct _mpt_proc_list {
- const char *name;
- int (*f)(char *, char **, off_t, int, int *, void *);
-} mpt_proc_list[] = {
- { "summary", procmpt_summary_read},
- { "version", procmpt_version_read},
-};
-#define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0]))
-
-struct _mpt_ioc_proc_list {
- const char *name;
- int (*f)(char *, char **, off_t, int, int *, void *);
-} mpt_ioc_proc_list[] = {
- { "info", procmpt_iocinfo_read},
- { "summary", procmpt_summary_read},
-};
-#define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0]))
+static void
+mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+ MPT_FRAME_HDR *mf = NULL;
+ MPT_FRAME_HDR *mr = NULL;
+ int req_idx = 0;
+ int cb_idx;
+
+ dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+ ioc->name, pa));
+
+ switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+ case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
+ req_idx = pa & 0x0000FFFF;
+ cb_idx = (pa & 0x00FF0000) >> 16;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+ break;
+ case MPI_CONTEXT_REPLY_TYPE_LAN:
+ cb_idx = mpt_lan_index;
+ /*
+ * Blind set of mf to NULL here was fatal
+ * after lan_reply says "freeme"
+ * Fix sort of combined with an optimization here;
+ * added explicit check for case where lan_reply
+ * was just returning 1 and doing nothing else.
+ * For this case skip the callback, but set up
+ * proper mf value first here:-)
+ */
+ if ((pa & 0x58000000) == 0x58000000) {
+ req_idx = pa & 0x0000FFFF;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+ mpt_free_msg_frame(ioc, mf);
+ mb();
+ return;
+ break;
+ }
+ mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+ break;
+ case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
+ cb_idx = mpt_stm_index;
+ mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+ break;
+ default:
+ cb_idx = 0;
+ BUG();
+ }
-#endif
+ /* Check for (valid) IO callback! */
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+ MptCallbacks[cb_idx] == NULL) {
+ printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+ __FUNCTION__, ioc->name, cb_idx);
+ goto out;
+ }
-/****************************************************************************
- * Supported hardware
- */
+ if (MptCallbacks[cb_idx](ioc, mf, mr))
+ mpt_free_msg_frame(ioc, mf);
+ out:
+ mb();
+}
-static struct pci_device_id mptbase_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
- PCI_ANY_ID, PCI_ANY_ID },
- {0} /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
+static void
+mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+ MPT_FRAME_HDR *mf;
+ MPT_FRAME_HDR *mr;
+ int req_idx;
+ int cb_idx;
+ int freeme;
-#define CHIPREG_READ32(addr) readl(addr)
-#define CHIPREG_WRITE32(addr,val) writel(val, addr)
-#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
-#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
+ u32 reply_dma_low;
+ u16 ioc_stat;
+
+ /* non-TURBO reply! Hmmm, something may be up...
+ * Newest turbo reply mechanism; get address
+ * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
+ */
+
+ /* Map DMA address of reply header to cpu address.
+ * pa is 32 bits - but the dma address may be 32 or 64 bits
+ * get offset based only only the low addresses
+ */
+
+ reply_dma_low = (pa <<= 1);
+ mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
+ (reply_dma_low - ioc->reply_frames_low_dma));
+
+ req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
+ cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+
+ dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+ ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
+ DBG_DUMP_REPLY_FRAME(mr)
+
+ /* Check/log IOC log info
+ */
+ ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+ if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+ u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+ if (ioc->bus_type == FC)
+ mpt_fc_log_info(ioc, log_info);
+ else if (ioc->bus_type == SPI)
+ mpt_spi_log_info(ioc, log_info);
+ else if (ioc->bus_type == SAS)
+ mpt_sas_log_info(ioc, log_info);
+ }
+ if (ioc_stat & MPI_IOCSTATUS_MASK) {
+ if (ioc->bus_type == SPI &&
+ cb_idx != mpt_stm_index &&
+ cb_idx != mpt_lan_index)
+ mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
+ }
+
+
+ /* Check for (valid) IO callback! */
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+ MptCallbacks[cb_idx] == NULL) {
+ printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+ __FUNCTION__, ioc->name, cb_idx);
+ freeme = 0;
+ goto out;
+ }
+
+ freeme = MptCallbacks[cb_idx](ioc, mf, mr);
+
+ out:
+ /* Flush (non-TURBO) reply with a WRITE! */
+ CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+
+ if (freeme)
+ mpt_free_msg_frame(ioc, mf);
+ mb();
+}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* (also referred to as a IO Controller or IOC).
* This routine must clear the interrupt from the adapter and does
* so by reading the reply FIFO. Multiple replies may be processed
- * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
- * which is currently set to 32 in mptbase.h.
+ * per single call to this routine.
*
* This routine handles register-level access of the adapter but
* dispatches (calls) a protocol-specific callback routine to handle
static irqreturn_t
mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
{
- MPT_ADAPTER *ioc;
- MPT_FRAME_HDR *mf;
- MPT_FRAME_HDR *mr;
- u32 pa;
- int req_idx;
- int cb_idx;
- int type;
- int freeme;
-
- ioc = bus_id;
-
-#ifdef MPT_DEBUG_IRQ
- /*
- * Verify ioc pointer is ok
- */
- {
- MPT_ADAPTER *iocCmp;
- iocCmp = mpt_adapter_find_first();
- while ((ioc != iocCmp) && iocCmp)
- iocCmp = mpt_adapter_find_next(iocCmp);
-
- if (!iocCmp) {
- printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n");
- return IRQ_NONE;
- }
- }
-#endif
+ MPT_ADAPTER *ioc = bus_id;
+ u32 pa;
/*
* Drain the reply FIFO!
- *
- * NOTES: I've seen up to 10 replies processed in this loop, so far...
- * Update: I've seen up to 9182 replies processed in this loop! ??
- * Update: Limit ourselves to processing max of N replies
- * (bottom of loop).
*/
while (1) {
-
- if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
+ pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+ if (pa == 0xFFFFFFFF)
return IRQ_HANDLED;
-
- cb_idx = 0;
- freeme = 0;
-
- /*
- * Check for non-TURBO reply!
- */
- if (pa & MPI_ADDRESS_REPLY_A_BIT) {
- u32 reply_dma_low;
- u16 ioc_stat;
-
- /* non-TURBO reply! Hmmm, something may be up...
- * Newest turbo reply mechanism; get address
- * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
- */
-
- /* Map DMA address of reply header to cpu address.
- * pa is 32 bits - but the dma address may be 32 or 64 bits
- * get offset based only only the low addresses
- */
- reply_dma_low = (pa = (pa << 1));
- mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
- (reply_dma_low - ioc->reply_frames_low_dma));
-
- req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
- cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-
- dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
- ioc->name, mr));
- DBG_DUMP_REPLY_FRAME(mr)
-
- /* NEW! 20010301 -sralston
- * Check/log IOC log info
- */
- ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
- if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
- u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
- if ((int)ioc->chip_type <= (int)FC929)
- mpt_fc_log_info(ioc, log_info);
- else
- mpt_sp_log_info(ioc, log_info);
- }
- } else {
- /*
- * Process turbo (context) reply...
- */
- dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
- type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
- if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
- cb_idx = mpt_stm_index;
- mf = NULL;
- mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
- } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
- cb_idx = mpt_lan_index;
- /*
- * BUG FIX! 20001218 -sralston
- * Blind set of mf to NULL here was fatal
- * after lan_reply says "freeme"
- * Fix sort of combined with an optimization here;
- * added explicit check for case where lan_reply
- * was just returning 1 and doing nothing else.
- * For this case skip the callback, but set up
- * proper mf value first here:-)
- */
- if ((pa & 0x58000000) == 0x58000000) {
- req_idx = pa & 0x0000FFFF;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
- freeme = 1;
- /*
- * IMPORTANT! Invalidate the callback!
- */
- cb_idx = 0;
- } else {
- mf = NULL;
- }
- mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
- } else {
- req_idx = pa & 0x0000FFFF;
- cb_idx = (pa & 0x00FF0000) >> 16;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
- mr = NULL;
- }
- pa = 0; /* No reply flush! */
- }
-
-#ifdef MPT_DEBUG_IRQ
- if ((int)ioc->chip_type > (int)FC929) {
- /* Verify mf, mr are reasonable.
- */
- if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
- || (mf < ioc->req_frames)) ) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
- || (mr < ioc->reply_frames)) ) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- }
-#endif
-
- /* Check for (valid) IO callback! */
- if (cb_idx) {
- /* Do the callback! */
- freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
- }
-
- if (pa) {
- /* Flush (non-TURBO) reply with a WRITE! */
- CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
- }
-
- if (freeme) {
- unsigned long flags;
-
- /* Put Request back on FreeQ! */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
-#ifdef MFCNT
- ioc->mfcnt--;
-#endif
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
- }
-
- mb();
- } /* drain reply FIFO */
+ else if (pa & MPI_ADDRESS_REPLY_A_BIT)
+ mpt_reply(ioc, pa);
+ else
+ mpt_turbo_reply(ioc, pa);
+ }
return IRQ_HANDLED;
}
* @mf: Pointer to original MPT request frame
* @reply: Pointer to MPT reply frame (NULL if TurboReply)
*
- * Returns 1 indicating original alloc'd request frame ptr
+ * Returns 1 indicating original alloc'd request frame ptr
* should be freed, or 0 if it shouldn't.
*/
static int
int freereq = 1;
u8 func;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
-
- if ((mf == NULL) ||
- (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
- printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
- ioc->name, (void *)mf);
- return 1;
- }
-
- if (reply == NULL) {
- dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
- ioc->name));
- return 1;
- }
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
+#if defined(MPT_DEBUG_MSG_FRAME)
if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
DBG_DUMP_REQUEST_FRAME_HDR(mf)
}
+#endif
func = reply->u.hdr.Function;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
ioc->name, func));
if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
if (results != evHandlers) {
/* CHECKME! Any special handling needed here? */
- dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+ devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
ioc->name, evHandlers, results));
}
* Hmmm... It seems that EventNotificationReply is an exception
* to the rule of one reply per request.
*/
- if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
freereq = 0;
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+ ioc->name, pEvReply));
+ } else {
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+ ioc->name, pEvReply));
+ }
#ifdef CONFIG_PROC_FS
// LogEvent(ioc, pEvReply);
} else if (func == MPI_FUNCTION_EVENT_ACK) {
dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
ioc->name));
- } else if (func == MPI_FUNCTION_CONFIG ||
- func == MPI_FUNCTION_TOOLBOX) {
+ } else if (func == MPI_FUNCTION_CONFIG) {
CONFIGPARMS *pCfg;
unsigned long flags;
del_timer(&pCfg->timer);
spin_lock_irqsave(&ioc->FreeQlock, flags);
- Q_DEL_ITEM(&pCfg->linkage);
+ list_del(&pCfg->linkage);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
/*
pCfg->status = status;
if (status == MPI_IOCSTATUS_SUCCESS) {
- pCfg->hdr->PageVersion = pReply->Header.PageVersion;
- pCfg->hdr->PageLength = pReply->Header.PageLength;
- pCfg->hdr->PageNumber = pReply->Header.PageNumber;
- pCfg->hdr->PageType = pReply->Header.PageType;
+ if ((pReply->Header.PageType &
+ MPI_CONFIG_PAGETYPE_MASK) ==
+ MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pCfg->cfghdr.ehdr->ExtPageLength =
+ le16_to_cpu(pReply->ExtPageLength);
+ pCfg->cfghdr.ehdr->ExtPageType =
+ pReply->ExtPageType;
+ }
+ pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+
+ /* If this is a regular header, save PageLength. */
+ /* LMP Do this better so not using a reserved field! */
+ pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+ pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+ pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
}
}
pCfg->wait_done = 1;
wake_up(&mpt_waitq);
}
+ } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+ /* we should be always getting a reply frame */
+ memcpy(ioc->persist_reply_frame, reply,
+ min(MPT_DEFAULT_FRAME_SIZE,
+ 4*reply->u.reply.MsgLength));
+ del_timer(&ioc->persist_timer);
+ ioc->persist_wait_done = 1;
+ wake_up(&mpt_waitq);
} else {
printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
ioc->name, func);
last_drv_idx = -1;
-#ifndef MODULE
- /*
- * Handle possibility of the mptscsih_detect() routine getting
- * called *before* fusion_init!
- */
- if (!FusionInitCalled) {
- dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
- /*
- * NOTE! We'll get recursion here, as fusion_init()
- * calls mpt_register()!
- */
- fusion_init();
- FusionInitCalled++;
- }
-#endif
-
/*
* Search for empty callback slot in this order: {N,...,7,6,5,...,1}
* (slot/handle 0 is reserved!)
MptEvHandlers[cb_idx] = NULL;
last_drv_idx++;
- if (isense_idx != -1 && isense_idx <= cb_idx)
- isense_idx++;
}
}
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
{
MPT_ADAPTER *ioc;
- int error=0;
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
- error= -EINVAL;
- return error;
+ return -EINVAL;
}
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
/* call per pci device probe entry point */
- for(ioc = mpt_adapter_find_first(); ioc != NULL;
- ioc = mpt_adapter_find_next(ioc)) {
+ list_for_each_entry(ioc, &ioc_list, list) {
if(dd_cbfunc->probe) {
- error = dd_cbfunc->probe(ioc->pcidev,
+ dd_cbfunc->probe(ioc->pcidev,
ioc->pcidev->driver->id_table);
- if(error != 0)
- return error;
}
}
- return error;
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
void
mpt_device_driver_deregister(int cb_idx)
{
+ struct mpt_pci_driver *dd_cbfunc;
+ MPT_ADAPTER *ioc;
+
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
return;
+ dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
+
+ list_for_each_entry(ioc, &ioc_list, list) {
+ if (dd_cbfunc->remove)
+ dd_cbfunc->remove(ioc->pcidev);
+ }
+
MptDeviceDriverHandlers[cb_idx] = NULL;
}
* mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
* allocated per MPT adapter.
* @handle: Handle of registered MPT protocol driver
- * @iocid: IOC unique identifier (integer)
+ * @ioc: Pointer to MPT adapter structure
*
* Returns pointer to a MPT request frame or %NULL if none are available
* or IOC is not active.
*/
MPT_FRAME_HDR*
-mpt_get_msg_frame(int handle, int iocid)
+mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
{
MPT_FRAME_HDR *mf;
- MPT_ADAPTER *iocp;
unsigned long flags;
+ u16 req_idx; /* Request index */
/* validate handle and ioc identifier */
- iocp = mpt_adapters[iocid];
#ifdef MFCNT
- if (!iocp->active)
+ if (!ioc->active)
printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
#endif
/* If interrupts are not attached, do not return a request frame */
- if (!iocp->active)
+ if (!ioc->active)
return NULL;
- spin_lock_irqsave(&iocp->FreeQlock, flags);
- if (! Q_IS_EMPTY(&iocp->FreeQ)) {
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+ if (!list_empty(&ioc->FreeQ)) {
int req_offset;
- mf = iocp->FreeQ.head;
- Q_DEL_ITEM(&mf->u.frame.linkage);
+ mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
+ u.frame.linkage.list);
+ list_del(&mf->u.frame.linkage.list);
+ mf->u.frame.linkage.arg1 = 0;
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
- req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+ req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
- mf->u.frame.hwhdr.msgctxu.fld.req_idx =
- cpu_to_le16(req_offset / iocp->req_sz);
+ req_idx = req_offset / ioc->req_sz;
+ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+ ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
#ifdef MFCNT
- iocp->mfcnt++;
+ ioc->mfcnt++;
#endif
}
else
mf = NULL;
- spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
#ifdef MFCNT
if (mf == NULL)
- printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
+ printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
mfcounter++;
if (mfcounter == PRINT_MF_COUNT)
- printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
+ printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
#endif
dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
- iocp->name, handle, iocid, mf));
+ ioc->name, handle, ioc->id, mf));
return mf;
}
* mpt_put_msg_frame - Send a protocol specific MPT request frame
* to a IOC.
* @handle: Handle of registered MPT protocol driver
- * @iocid: IOC unique identifier (integer)
+ * @ioc: Pointer to MPT adapter structure
* @mf: Pointer to MPT request frame
*
* This routine posts a MPT request frame to the request post FIFO of a
* specific MPT adapter.
*/
void
-mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
{
- MPT_ADAPTER *iocp;
-
- iocp = mpt_adapters[iocid];
- if (iocp != NULL) {
- u32 mf_dma_addr;
- int req_offset;
+ u32 mf_dma_addr;
+ int req_offset;
+ u16 req_idx; /* Request index */
- /* ensure values are reset properly! */
- mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
- req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
- /* u16! */
- mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
- mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+ /* ensure values are reset properly! */
+ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
+ req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
+ /* u16! */
+ req_idx = req_offset / ioc->req_sz;
+ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
+ mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
#ifdef MPT_DEBUG_MSG_FRAME
- {
- u32 *m = mf->u.frame.hwhdr.__hdr;
- int ii, n;
-
- printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
- iocp->name, m);
- n = iocp->req_sz/4 - 1;
- while (m[n] == 0)
- n--;
- for (ii=0; ii<=n; ii++) {
- if (ii && ((ii%8)==0))
- printk("\n" KERN_INFO " ");
- printk(" %08x", le32_to_cpu(m[ii]));
- }
- printk("\n");
+ {
+ u32 *m = mf->u.frame.hwhdr.__hdr;
+ int ii, n;
+
+ printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
+ ioc->name, m);
+ n = ioc->req_sz/4 - 1;
+ while (m[n] == 0)
+ n--;
+ for (ii=0; ii<=n; ii++) {
+ if (ii && ((ii%8)==0))
+ printk("\n" KERN_INFO " ");
+ printk(" %08x", le32_to_cpu(m[ii]));
}
-#endif
-
- mf_dma_addr = iocp->req_frames_low_dma + req_offset;
- CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
- } else {
- printk (KERN_ERR
- "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);
+ printk("\n");
}
+#endif
+ mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
+ dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
+ CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mpt_free_msg_frame - Place MPT request frame back on FreeQ.
* @handle: Handle of registered MPT protocol driver
- * @iocid: IOC unique identifier (integer)
+ * @ioc: Pointer to MPT adapter structure
* @mf: Pointer to MPT request frame
*
* This routine places a MPT request frame back on the MPT adapter's
* FreeQ.
*/
void
-mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
{
- MPT_ADAPTER *iocp;
unsigned long flags;
- iocp = mpt_adapters[iocid];
- if (iocp != NULL) {
- /* Put Request back on FreeQ! */
- spin_lock_irqsave(&iocp->FreeQlock, flags);
- Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+ /* Put Request back on FreeQ! */
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+ mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
+ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
#ifdef MFCNT
- iocp->mfcnt--;
+ ioc->mfcnt--;
#endif
- spin_unlock_irqrestore(&iocp->FreeQlock, flags);
- }
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
}
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_add_chain - Place a chain SGE at address pAddr.
- * @pAddr: virtual address for SGE
- * @next: nextChainOffset value (u32's)
- * @length: length of next SGL segment
- * @dma_addr: Physical address
- *
- * This routine places a MPT request frame back on the MPT adapter's
- * FreeQ.
- */
-void
-mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
-{
- if (sizeof(dma_addr_t) == sizeof(u64)) {
- SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
- u32 tmp = dma_addr & 0xFFFFFFFF;
-
- pChain->Length = cpu_to_le16(length);
- pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
-
- pChain->NextChainOffset = next;
-
- pChain->Address.Low = cpu_to_le32(tmp);
- tmp = (u32) ((u64)dma_addr >> 32);
- pChain->Address.High = cpu_to_le32(tmp);
- } else {
- SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
- pChain->Length = cpu_to_le16(length);
- pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
- pChain->NextChainOffset = next;
- pChain->Address = cpu_to_le32(dma_addr);
- }
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mpt_send_handshake_request - Send MPT request via doorbell
* handshake method.
* @handle: Handle of registered MPT protocol driver
- * @iocid: IOC unique identifier (integer)
+ * @ioc: Pointer to MPT adapter structure
* @reqBytes: Size of the request in bytes
* @req: Pointer to MPT request frame
* @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
* Returns 0 for success, non-zero for failure.
*/
int
-mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag)
+mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
{
- MPT_ADAPTER *iocp;
int r = 0;
+ u8 *req_as_bytes;
+ int ii;
- iocp = mpt_adapters[iocid];
- if (iocp != NULL) {
- u8 *req_as_bytes;
- int ii;
+ /* State is known to be good upon entering
+ * this function so issue the bus reset
+ * request.
+ */
- /* State is known to be good upon entering
- * this function so issue the bus reset
- * request.
- */
+ /*
+ * Emulate what mpt_put_msg_frame() does /wrt to sanity
+ * setting cb_idx/req_idx. But ONLY if this request
+ * is in proper (pre-alloc'd) request buffer range...
+ */
+ ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+ if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
+ MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
+ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
+ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+ }
- /*
- * Emulate what mpt_put_msg_frame() does /wrt to sanity
- * setting cb_idx/req_idx. But ONLY if this request
- * is in proper (pre-alloc'd) request buffer range...
- */
- ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
- if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
- MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
- mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
- mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
- }
+ /* Make sure there are no doorbells */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
- /* Make sure there are no doorbells */
- CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+ CHIPREG_WRITE32(&ioc->chip->Doorbell,
+ ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
+ ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
- CHIPREG_WRITE32(&iocp->chip->Doorbell,
- ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
- ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+ /* Wait for IOC doorbell int */
+ if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
+ return ii;
+ }
- /* Wait for IOC doorbell int */
- if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {
- return ii;
- }
+ /* Read doorbell and check for active bit */
+ if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+ return -5;
- /* Read doorbell and check for active bit */
- if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
- return -5;
+ dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
+ ioc->name, ii));
- dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
- iocp->name, ii));
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
- CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ return -2;
+ }
- if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
- return -2;
- }
+ /* Send request via doorbell handshake */
+ req_as_bytes = (u8 *) req;
+ for (ii = 0; ii < reqBytes/4; ii++) {
+ u32 word;
- /* Send request via doorbell handshake */
- req_as_bytes = (u8 *) req;
- for (ii = 0; ii < reqBytes/4; ii++) {
- u32 word;
-
- word = ((req_as_bytes[(ii*4) + 0] << 0) |
- (req_as_bytes[(ii*4) + 1] << 8) |
- (req_as_bytes[(ii*4) + 2] << 16) |
- (req_as_bytes[(ii*4) + 3] << 24));
- CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
- if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
- r = -3;
- break;
- }
+ word = ((req_as_bytes[(ii*4) + 0] << 0) |
+ (req_as_bytes[(ii*4) + 1] << 8) |
+ (req_as_bytes[(ii*4) + 2] << 16) |
+ (req_as_bytes[(ii*4) + 3] << 24));
+ CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ r = -3;
+ break;
}
+ }
- if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
- r = 0;
- else
- r = -4;
+ if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
+ r = 0;
+ else
+ r = -4;
- /* Make sure there are no doorbells */
- CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
- }
+ /* Make sure there are no doorbells */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mpt_adapter_find_first - Find first MPT adapter pointer.
+ * mpt_host_page_access_control - provides mechanism for the host
+ * driver to control the IOC's Host Page Buffer access.
+ * @ioc: Pointer to MPT adapter structure
+ * @access_control_value: define bits below
*
- * Returns first MPT adapter pointer or %NULL if no MPT adapters
- * are present.
+ * Access Control Value - bits[15:12]
+ * 0h Reserved
+ * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
+ * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
+ * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
+ *
+ * Returns 0 for success, non-zero for failure.
*/
-MPT_ADAPTER *
-mpt_adapter_find_first(void)
+
+static int
+mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
{
- MPT_ADAPTER *this;
+ int r = 0;
- if (! Q_IS_EMPTY(&MptAdapters))
- this = MptAdapters.head;
- else
- this = NULL;
+ /* return if in use */
+ if (CHIPREG_READ32(&ioc->chip->Doorbell)
+ & MPI_DOORBELL_ACTIVE)
+ return -1;
+
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+ CHIPREG_WRITE32(&ioc->chip->Doorbell,
+ ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
+ <<MPI_DOORBELL_FUNCTION_SHIFT) |
+ (access_control_value<<12)));
- return this;
+ /* Wait for IOC to clear Doorbell Status bit */
+ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ return -2;
+ }else
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mpt_adapter_find_next - Find next MPT adapter pointer.
- * @prev: Pointer to previous MPT adapter
+ * mpt_host_page_alloc - allocate system memory for the fw
+ * If we already allocated memory in past, then resend the same pointer.
+ * ioc@: Pointer to pointer to IOC adapter
+ * ioc_init@: Pointer to ioc init config page
*
- * Returns next MPT adapter pointer or %NULL if there are no more.
+ * Returns 0 for success, non-zero for failure.
*/
-MPT_ADAPTER *
-mpt_adapter_find_next(MPT_ADAPTER *prev)
+static int
+mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
{
- MPT_ADAPTER *next;
+ char *psge;
+ int flags_length;
+ u32 host_page_buffer_sz=0;
+
+ if(!ioc->HostPageBuffer) {
+
+ host_page_buffer_sz =
+ le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
+
+ if(!host_page_buffer_sz)
+ return 0; /* fw doesn't need any host buffers */
+
+ /* spin till we get enough memory */
+ while(host_page_buffer_sz > 0) {
+
+ if((ioc->HostPageBuffer = pci_alloc_consistent(
+ ioc->pcidev,
+ host_page_buffer_sz,
+ &ioc->HostPageBuffer_dma)) != NULL) {
+
+ dinitprintk((MYIOC_s_INFO_FMT
+ "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
+ ioc->name,
+ ioc->HostPageBuffer,
+ ioc->HostPageBuffer_dma,
+ host_page_buffer_sz));
+ ioc->alloc_total += host_page_buffer_sz;
+ ioc->HostPageBuffer_sz = host_page_buffer_sz;
+ break;
+ }
- if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
- next = prev->forw;
- else
- next = NULL;
+ host_page_buffer_sz -= (4*1024);
+ }
+ }
- return next;
-}
+ if(!ioc->HostPageBuffer) {
+ printk(MYIOC_s_ERR_FMT
+ "Failed to alloc memory for host_page_buffer!\n",
+ ioc->name);
+ return -999;
+ }
+
+ psge = (char *)&ioc_init->HostPageBufferSGE;
+ flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+ MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+ MPI_SGE_FLAGS_HOST_TO_IOC |
+ MPI_SGE_FLAGS_END_OF_BUFFER;
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+ }
+ flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
+ flags_length |= ioc->HostPageBuffer_sz;
+ mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+ ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
+return 0;
+}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
int
mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
{
- MPT_ADAPTER *p;
+ MPT_ADAPTER *ioc;
+
+ list_for_each_entry(ioc,&ioc_list,list) {
+ if (ioc->id == iocid) {
+ *iocpp =ioc;
+ return iocid;
+ }
+ }
*iocpp = NULL;
- if (iocid >= MPT_MAX_ADAPTERS)
- return -1;
+ return -1;
+}
- p = mpt_adapters[iocid];
- if (p == NULL)
- return -1;
+int
+mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
+{
+ int loop_count = 30 * 4; /* Wait 30 seconds */
+ int status = -1; /* -1 means failed to get board READY */
+
+ do {
+ spin_lock(&ioc->initializing_hba_lock);
+ if (ioc->initializing_hba_lock_flag == 0) {
+ ioc->initializing_hba_lock_flag=1;
+ spin_unlock(&ioc->initializing_hba_lock);
+ status = 0;
+ break;
+ }
+ spin_unlock(&ioc->initializing_hba_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ } while (--loop_count);
+
+ return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
+ * @ioc: Pointer to MPT adapter structure
+ * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
+ *
+ * This routine performs all the steps necessary to bring the IOC
+ * to a OPERATIONAL state.
+ *
+ * Special Note: This function was added with spin lock's so as to allow
+ * the dv(domain validation) work thread to succeed on the other channel
+ * that maybe occuring at the same time when this function is called.
+ * Without this lock, the dv would fail when message frames were
+ * requested during hba bringup on the alternate ioc.
+ */
+static int
+mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
+{
+ int r;
+
+ if(ioc->alt_ioc) {
+ if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
+ return r;
+ }
+
+ r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+ CAN_SLEEP);
+
+ if(ioc->alt_ioc) {
+ spin_lock(&ioc->alt_ioc->initializing_hba_lock);
+ ioc->alt_ioc->initializing_hba_lock_flag=0;
+ spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
+ }
- *iocpp = p;
- return iocid;
+return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_probe - Install a PCI intelligent MPT adapter.
+ * mpt_attach - Install a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
* This routine performs all the steps necessary to bring the IOC of
*
* TODO: Add support for polled controllers
*/
-static int __devinit
-mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int
+mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
- u8 *mem;
+ u8 __iomem *mem;
unsigned long mem_phys;
unsigned long port;
u32 msize;
u32 psize;
int ii;
int r = -ENODEV;
- u64 mask = 0xffffffffffffffffULL;
u8 revision;
u8 pcixcmd;
+ static int mpt_ids = 0;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *dent, *ent;
+#endif
if (pci_enable_device(pdev))
return r;
-
- if (!pci_set_dma_mask(pdev, mask)) {
+
+ dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
+
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
- } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
+ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
return r;
}
- if (!pci_set_consistent_dma_mask(pdev, mask))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
dprintk((KERN_INFO MYNAM
": Using 64 bit consistent mask\n"));
else
dprintk((KERN_INFO MYNAM
": Not using 64 bit consistent mask\n"));
- ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+ ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
}
- memset(ioc, 0, sizeof(MPT_ADAPTER));
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
ioc->pcidev = pdev;
-
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
+ spin_lock_init(&ioc->fc_rescan_work_lock);
+ spin_lock_init(&ioc->fc_rport_lock);
+ spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
*/
/* Initilize SCSI Config Data structure
*/
- memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
+ memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
/* Initialize the running configQ head.
*/
- Q_INIT(&ioc->configQ, Q_ITEM);
+ INIT_LIST_HEAD(&ioc->configQ);
+
+ /* Initialize the fc rport list head.
+ */
+ INIT_LIST_HEAD(&ioc->fc_rports);
/* Find lookup slot. */
- for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
- if (mpt_adapters[ii] == NULL) {
- ioc->id = ii; /* Assign adapter unique id (lookup) */
- break;
- }
- }
- if (ii == MPT_MAX_ADAPTERS) {
- printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);
- kfree(ioc);
- return -ENFILE;
- }
+ INIT_LIST_HEAD(&ioc->list);
+ ioc->id = mpt_ids++;
mem_phys = msize = 0;
port = psize = 0;
for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
- if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
+ if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
/* Get I/O space! */
- port = pdev->PCI_BASEADDR_START(ii);
- psize = PCI_BASEADDR_SIZE(pdev,ii);
+ port = pci_resource_start(pdev, ii);
+ psize = pci_resource_len(pdev,ii);
} else {
/* Get memmap */
- mem_phys = pdev->PCI_BASEADDR_START(ii);
- msize = PCI_BASEADDR_SIZE(pdev,ii);
+ mem_phys = pci_resource_start(pdev, ii);
+ msize = pci_resource_len(pdev,ii);
break;
}
}
return -EINVAL;
}
- dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
- dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
+ dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
+ dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
mem = NULL;
/* Get logical ptr for PciMem0 space */
return -EINVAL;
}
ioc->memmap = mem;
- dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+ dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
- dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
+ dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
&ioc->facts, &ioc->pfacts[0]));
ioc->mem_phys = mem_phys;
- ioc->chip = (SYSIF_REGS*)mem;
+ ioc->chip = (SYSIF_REGS __iomem *)mem;
- /* Save Port IO values incase we need to do downloadboot */
+ /* Save Port IO values in case we need to do downloadboot */
{
u8 *pmem = (u8*)port;
ioc->pio_mem_phys = port;
- ioc->pio_chip = (SYSIF_REGS*)pmem;
+ ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
}
- ioc->chip_type = FCUNK;
- if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
- ioc->chip_type = FC929;
+ if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
+ ioc->prod_name = "LSIFC909";
+ ioc->bus_type = FC;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
ioc->prod_name = "LSIFC929";
+ ioc->bus_type = FC;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
- ioc->chip_type = FC919;
ioc->prod_name = "LSIFC919";
+ ioc->bus_type = FC;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
- ioc->chip_type = FC929X;
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+ ioc->bus_type = FC;
if (revision < XL_929) {
ioc->prod_name = "LSIFC929X";
/* 929X Chip Fix. Set Split transactions level
}
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
- ioc->chip_type = FC919X;
ioc->prod_name = "LSIFC919X";
+ ioc->bus_type = FC;
/* 919X Chip Fix. Set Split transactions level
* for PCIX. Set MOST bits to zero.
*/
pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
+ ioc->prod_name = "LSIFC939X";
+ ioc->bus_type = FC;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
+ ioc->prod_name = "LSIFC949X";
+ ioc->bus_type = FC;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+ ioc->prod_name = "LSIFC949E";
+ ioc->bus_type = FC;
+ }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
- ioc->chip_type = C1030;
ioc->prod_name = "LSI53C1030";
+ ioc->bus_type = SPI;
/* 1030 Chip Fix. Disable Split transactions
* for PCIX. Set MOST bits to zero if Rev < C0( = 8).
*/
}
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
- ioc->chip_type = C1035;
ioc->prod_name = "LSI53C1035";
+ ioc->bus_type = SPI;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
+ ioc->prod_name = "LSISAS1064";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
+ ioc->prod_name = "LSISAS1066";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
+ ioc->prod_name = "LSISAS1068";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
+ ioc->prod_name = "LSISAS1064E";
+ ioc->bus_type = SAS;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
+ ioc->prod_name = "LSISAS1066E";
+ ioc->bus_type = SAS;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
+ ioc->prod_name = "LSISAS1068E";
+ ioc->bus_type = SAS;
+ }
+
+ if (ioc->errata_flag_1064)
+ pci_disable_io_access(pdev);
sprintf(ioc->name, "ioc%d", ioc->id);
- Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
spin_lock_init(&ioc->FreeQlock);
/* Disable all! */
ioc->active = 0;
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
- /* tack onto tail of our MPT adapter list */
- Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
-
/* Set lookup ptr. */
- mpt_adapters[ioc->id] = ioc;
+ list_add_tail(&ioc->list, &ioc_list);
ioc->pci_irq = -1;
if (pdev->irq) {
+ if (mpt_msi_enable && !pci_enable_msi(pdev))
+ printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
+
r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
if (r < 0) {
printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
ioc->name, __irq_itoa(pdev->irq));
#endif
- Q_DEL_ITEM(ioc);
- mpt_adapters[ioc->id] = NULL;
+ list_del(&ioc->list);
iounmap(mem);
kfree(ioc);
return -EBUSY;
#endif
}
- /* NEW! 20010220 -sralston
- * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
+ /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
*/
- if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
- || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
- mpt_detect_bound_ports(ioc, pdev);
+ mpt_detect_bound_ports(ioc, pdev);
- if ((r = mpt_do_ioc_recovery(ioc,
- MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
+ if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
printk(KERN_WARNING MYNAM
": WARNING - %s did not initialize properly! (%d)\n",
ioc->name, r);
- Q_DEL_ITEM(ioc);
- mpt_adapters[ioc->id] = NULL;
+ list_del(&ioc->list);
free_irq(ioc->pci_irq, ioc);
+ if (mpt_msi_enable)
+ pci_disable_msi(pdev);
+ if (ioc->alt_ioc)
+ ioc->alt_ioc->alt_ioc = NULL;
iounmap(mem);
kfree(ioc);
pci_set_drvdata(pdev, NULL);
}
}
+#ifdef CONFIG_PROC_FS
+ /*
+ * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
+ */
+ dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
+ if (dent) {
+ ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
+ if (ent) {
+ ent->read_proc = procmpt_iocinfo_read;
+ ent->data = ioc;
+ }
+ ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
+ if (ent) {
+ ent->read_proc = procmpt_summary_read;
+ ent->data = ioc;
+ }
+ }
+#endif
+
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_remove - Remove a PCI intelligent MPT adapter.
+ * mpt_detach - Remove a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
*/
-static void __devexit
-mptbase_remove(struct pci_dev *pdev)
+void
+mpt_detach(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ char pname[32];
int ii;
+ sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
+ remove_proc_entry(pname, NULL);
+ sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
+ remove_proc_entry(pname, NULL);
+ sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+ remove_proc_entry(pname, NULL);
+
/* call per device driver remove entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
ioc->active = 0;
- mpt_sync_irq(pdev->irq);
+ synchronize_irq(pdev->irq);
/* Clear any lingering interrupt */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
CHIPREG_READ32(&ioc->chip->IntStatus);
- Q_DEL_ITEM(ioc);
mpt_adapter_dispose(ioc);
pci_set_drvdata(pdev, NULL);
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * mptbase_shutdown -
- *
- */
-static void
-mptbase_shutdown(struct device * dev)
-{
- int ii;
-
- /* call per device driver shutdown entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->shutdown) {
- MptDeviceDriverHandlers[ii]->shutdown(dev);
- }
- }
-
-}
-
-
/**************************************************************************
* Power Management
*/
#ifdef CONFIG_PM
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_suspend - Fusion MPT base driver suspend routine.
+ * mpt_suspend - Fusion MPT base driver suspend routine.
*
*
*/
-static int
-mptbase_suspend(struct pci_dev *pdev, u32 state)
+int
+mpt_suspend(struct pci_dev *pdev, pm_message_t state)
{
u32 device_state;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- int ii;
- switch(state)
- {
- case 1: /* S1 */
- device_state=1; /* D1 */;
- break;
- case 3: /* S3 */
- case 4: /* S4 */
- device_state=3; /* D3 */;
- break;
- default:
- return -EAGAIN /*FIXME*/;
- break;
- }
+ device_state=pci_choose_state(pdev, state);
printk(MYIOC_s_INFO_FMT
"pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
- /* call per device driver suspend entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->suspend) {
- MptDeviceDriverHandlers[ii]->suspend(pdev, state);
- }
- }
-
- pci_save_state(pdev, ioc->PciState);
+ pci_save_state(pdev);
/* put ioc into READY_STATE */
if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_resume - Fusion MPT base driver resume routine.
+ * mpt_resume - Fusion MPT base driver resume routine.
*
*
*/
-static int
-mptbase_resume(struct pci_dev *pdev)
+int
+mpt_resume(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
ioc->name, pdev, pci_name(pdev), device_state);
pci_set_power_state(pdev, 0);
- pci_restore_state(pdev, ioc->PciState);
+ pci_restore_state(pdev);
pci_enable_device(pdev);
/* enable interrupts */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
/* F/W not running */
"pci-resume: success\n", ioc->name);
}
- /* call per device driver resume entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->resume) {
- MptDeviceDriverHandlers[ii]->resume(pdev);
- }
- }
-
return 0;
}
#endif
int hard_reset_done = 0;
int alt_ioc_ready = 0;
int hard;
- int r;
+ int rc=0;
int ii;
int handlers;
int ret = 0;
/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
* and 1 if a hard reset was performed.
*/
if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
- if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
+ if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
alt_ioc_ready = 1;
else
printk(KERN_WARNING MYNAM
- ": alt-%s: (%d) Not ready WARNING!\n",
- ioc->alt_ioc->name, r);
+ ": alt-%s: Not ready WARNING!\n",
+ ioc->alt_ioc->name);
+ }
+
+ for (ii=0; ii<5; ii++) {
+ /* Get IOC facts! Allow 5 retries */
+ if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
+ break;
}
- /* Get IOC facts! Allow 1 retry */
- if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
- r = GetIocFacts(ioc, sleepFlag, reason);
- if (r) {
+ if (ii == 5) {
+ dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
ret = -2;
} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
MptDisplayIocCapabilities(ioc);
}
if (alt_ioc_ready) {
- if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+ if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+ dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
/* Retry - alt IOC was initialized once
*/
- r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
+ rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
}
- if (r) {
+ if (rc) {
+ dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
alt_ioc_ready = 0;
reset_alt_ioc_active = 0;
} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
* init as upper addresses are needed for init.
* If fails, continue with alt-ioc processing
*/
- if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
+ if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
ret = -3;
/* May need to check/upload firmware & data here!
* If fails, continue with alt-ioc processing
*/
- if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
+ if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
ret = -4;
// NEW!
- if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
+ if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
- ioc->alt_ioc->name, r);
+ ioc->alt_ioc->name, rc);
alt_ioc_ready = 0;
reset_alt_ioc_active = 0;
}
if (alt_ioc_ready) {
- if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
+ if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
alt_ioc_ready = 0;
reset_alt_ioc_active = 0;
printk(KERN_WARNING MYNAM
": alt-%s: (%d) init failure WARNING!\n",
- ioc->alt_ioc->name, r);
+ ioc->alt_ioc->name, rc);
}
}
/* Controller is not operational, cannot do upload
*/
if (ret == 0) {
- r = mpt_do_upload(ioc, sleepFlag);
- if (r != 0)
- printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
- }
-
- /* Handle the alt IOC too */
- if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
- ddlprintk((MYIOC_s_INFO_FMT
- "Alt-ioc firmware upload required!\n",
- ioc->name));
- r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
- if (r != 0)
+ rc = mpt_do_upload(ioc, sleepFlag);
+ if (rc == 0) {
+ if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+ /*
+ * Maintain only one pointer to FW memory
+ * so there will not be two attempt to
+ * downloadboot onboard dual function
+ * chips (mpt_adapter_disable,
+ * mpt_diag_reset)
+ */
+ ioc->cached_fw = NULL;
+ ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
+ ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+ }
+ } else {
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+ ret = -5;
+ }
}
}
}
if (ret == 0) {
/* Enable! (reply interrupt) */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
}
if (reset_alt_ioc_active && ioc->alt_ioc) {
/* (re)Enable alt-IOC! (reply interrupt) */
- dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
+ dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
- /* NEW! 20010120 -sralston
- * Enable MPT base driver management of EventNotification
+ /* Enable MPT base driver management of EventNotification
* and EventAck handling.
*/
if ((ret == 0) && (!ioc->facts.EventState))
if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
(void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 2)! 20010905 -sralston
- * Add additional "reason" check before call to GetLanConfigPages
+ /* Add additional "reason" check before call to GetLanConfigPages
* (combined with GetIoUnitPage2 call). This prevents a somewhat
* recursive scenario; GetLanConfigPages times out, timer expired
* routine calls HardResetHandler, which calls into here again,
* and we try GetLanConfigPages again...
*/
if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
- if ((int)ioc->chip_type <= (int)FC929) {
+ if (ioc->bus_type == SAS) {
+
+ /* clear persistency table */
+ if(ioc->facts.IOCExceptions &
+ MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+ ret = mptbase_sas_persist_operation(ioc,
+ MPI_SAS_OP_CLEAR_NOT_PRESENT);
+ if(ret != 0)
+ return -1;
+ }
+
+ /* Find IM volumes
+ */
+ mpt_findImVolumes(ioc);
+
+ } else if (ioc->bus_type == FC) {
/*
* Pre-fetch FC port WWN and stuff...
* (FCPortPage0_t stuff)
*/
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) GetFcPortPage0(ioc, ii);
+ (void) mptbase_GetFcPortPage0(ioc, ii);
}
if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
/* Find IM volumes
*/
- if (ioc->facts.MsgVersion >= 0x0102)
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
mpt_findImVolumes(ioc);
/* Check, and possibly reset, the coalescing value
* MptResetHandlers[] registered yet.
*/
if (hard_reset_done) {
- r = handlers = 0;
+ rc = handlers = 0;
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
if ((ret == 0) && MptResetHandlers[ii]) {
dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+ rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
handlers++;
}
if (alt_ioc_ready && MptResetHandlers[ii]) {
- dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+ drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+ rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
handlers++;
}
}
static void
mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
{
- MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
- unsigned int match_lo, match_hi;
-
- match_lo = pdev->devfn-1;
- match_hi = pdev->devfn+1;
- dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
- ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
+ struct pci_dev *peer=NULL;
+ unsigned int slot = PCI_SLOT(pdev->devfn);
+ unsigned int func = PCI_FUNC(pdev->devfn);
+ MPT_ADAPTER *ioc_srch;
+
+ dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
+ " searching for devfn match on %x or %x\n",
+ ioc->name, pci_name(pdev), pdev->bus->number,
+ pdev->devfn, func-1, func+1));
+
+ peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
+ if (!peer) {
+ peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
+ if (!peer)
+ return;
+ }
- while (ioc_srch != NULL) {
+ list_for_each_entry(ioc_srch, &ioc_list, list) {
struct pci_dev *_pcidev = ioc_srch->pcidev;
-
- if ((_pcidev->device == pdev->device) &&
- (_pcidev->bus->number == pdev->bus->number) &&
- (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+ if (_pcidev == peer) {
/* Paranoia checks */
if (ioc->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
- ioc->name, ioc->alt_ioc->name);
+ ioc->name, ioc->alt_ioc->name);
break;
} else if (ioc_srch->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
- ioc_srch->name, ioc_srch->alt_ioc->name);
+ ioc_srch->name, ioc_srch->alt_ioc->name);
break;
}
dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
- ioc->name, ioc_srch->name));
+ ioc->name, ioc_srch->name));
ioc_srch->alt_ioc = ioc;
ioc->alt_ioc = ioc_srch;
- break;
}
- ioc_srch = mpt_adapter_find_next(ioc_srch);
}
+ pci_dev_put(peer);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_adapter_disable - Disable misbehaving MPT adapter.
* @this: Pointer to MPT adapter structure
- * @free: Free up alloc'd reply, request, etc.
*/
static void
-mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
+mpt_adapter_disable(MPT_ADAPTER *ioc)
{
- if (this != NULL) {
- int sz=0;
- u32 state;
- int ret;
-
- /* Disable the FW */
- state = mpt_GetIocState(this, 1);
- if (state == MPI_IOC_STATE_OPERATIONAL) {
- SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
- }
-
- if (this->cached_fw != NULL) {
- ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
+ int sz;
+ int ret;
- if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
- printk(KERN_WARNING MYNAM
- ": firmware downloadboot failure (%d)!\n", ret);
- }
+ if (ioc->cached_fw != NULL) {
+ ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
+ if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
+ printk(KERN_WARNING MYNAM
+ ": firmware downloadboot failure (%d)!\n", ret);
}
+ }
- /* Disable adapter interrupts! */
- CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
- this->active = 0;
- /* Clear any lingering interrupt */
- CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
- if (freeup && this->fifo_pool != NULL) {
- pci_free_consistent(this->pcidev,
- this->fifo_pool_sz,
- this->fifo_pool, this->fifo_pool_dma);
- this->reply_frames = NULL;
- this->reply_alloc = NULL;
- this->req_frames = NULL;
- this->req_alloc = NULL;
- this->chain_alloc = NULL;
- this->fifo_pool = NULL;
- this->alloc_total -= this->fifo_pool_sz;
- }
- if (freeup && this->sense_buf_pool != NULL) {
- sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
- pci_free_consistent(this->pcidev, sz,
- this->sense_buf_pool, this->sense_buf_pool_dma);
- this->sense_buf_pool = NULL;
- this->alloc_total -= sz;
- }
+ /* Disable adapter interrupts! */
+ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+ ioc->active = 0;
+ /* Clear any lingering interrupt */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
- if (freeup && this->events != NULL){
- sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
- kfree(this->events);
- this->events = NULL;
- this->alloc_total -= sz;
- }
+ if (ioc->alloc != NULL) {
+ sz = ioc->alloc_sz;
+ dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
+ ioc->name, ioc->alloc, ioc->alloc_sz));
+ pci_free_consistent(ioc->pcidev, sz,
+ ioc->alloc, ioc->alloc_dma);
+ ioc->reply_frames = NULL;
+ ioc->req_frames = NULL;
+ ioc->alloc = NULL;
+ ioc->alloc_total -= sz;
+ }
- if (freeup && this->cached_fw != NULL) {
- int ii = 0;
+ if (ioc->sense_buf_pool != NULL) {
+ sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+ pci_free_consistent(ioc->pcidev, sz,
+ ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+ ioc->sense_buf_pool = NULL;
+ ioc->alloc_total -= sz;
+ }
- while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) {
- sz = this->cached_fw[ii]->size;
- pci_free_consistent(this->pcidev, sz,
- this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma);
- this->cached_fw[ii]->fw = NULL;
- this->alloc_total -= sz;
+ if (ioc->events != NULL){
+ sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+ kfree(ioc->events);
+ ioc->events = NULL;
+ ioc->alloc_total -= sz;
+ }
- kfree(this->cached_fw[ii]);
- this->cached_fw[ii] = NULL;
- this->alloc_total -= sizeof(fw_image_t);
+ if (ioc->cached_fw != NULL) {
+ sz = ioc->facts.FWImageSize;
+ pci_free_consistent(ioc->pcidev, sz,
+ ioc->cached_fw, ioc->cached_fw_dma);
+ ioc->cached_fw = NULL;
+ ioc->alloc_total -= sz;
+ }
- ii++;
- }
+ kfree(ioc->spi_data.nvram);
+ kfree(ioc->raid_data.pIocPg3);
+ ioc->spi_data.nvram = NULL;
+ ioc->raid_data.pIocPg3 = NULL;
- kfree(this->cached_fw);
- this->cached_fw = NULL;
- sz = this->num_fw_frags * sizeof(void *);
- this->alloc_total -= sz;
- }
+ if (ioc->spi_data.pIocPg4 != NULL) {
+ sz = ioc->spi_data.IocPg4Sz;
+ pci_free_consistent(ioc->pcidev, sz,
+ ioc->spi_data.pIocPg4,
+ ioc->spi_data.IocPg4_dma);
+ ioc->spi_data.pIocPg4 = NULL;
+ ioc->alloc_total -= sz;
+ }
- if (freeup && this->spi_data.nvram != NULL) {
- kfree(this->spi_data.nvram);
- this->spi_data.nvram = NULL;
- }
+ if (ioc->ReqToChain != NULL) {
+ kfree(ioc->ReqToChain);
+ kfree(ioc->RequestNB);
+ ioc->ReqToChain = NULL;
+ }
- if (freeup && this->spi_data.pIocPg3 != NULL) {
- kfree(this->spi_data.pIocPg3);
- this->spi_data.pIocPg3 = NULL;
- }
+ kfree(ioc->ChainToChain);
+ ioc->ChainToChain = NULL;
- if (freeup && this->spi_data.pIocPg4 != NULL) {
- sz = this->spi_data.IocPg4Sz;
- pci_free_consistent(this->pcidev, sz,
- this->spi_data.pIocPg4,
- this->spi_data.IocPg4_dma);
- this->spi_data.pIocPg4 = NULL;
- this->alloc_total -= sz;
+ if (ioc->HostPageBuffer != NULL) {
+ if((ret = mpt_host_page_access_control(ioc,
+ MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
+ printk(KERN_ERR MYNAM
+ ": %s: host page buffers free failed (%d)!\n",
+ __FUNCTION__, ret);
}
+ dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
+ ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+ pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+ ioc->HostPageBuffer,
+ ioc->HostPageBuffer_dma);
+ ioc->HostPageBuffer = NULL;
+ ioc->HostPageBuffer_sz = 0;
+ ioc->alloc_total -= ioc->HostPageBuffer_sz;
}
}
/*
* mpt_adapter_dispose - Free all resources associated with a MPT
* adapter.
- * @this: Pointer to MPT adapter structure
+ * @ioc: Pointer to MPT adapter structure
*
* This routine unregisters h/w resources and frees all alloc'd memory
* associated with a MPT adapter structure.
*/
static void
-mpt_adapter_dispose(MPT_ADAPTER *this)
+mpt_adapter_dispose(MPT_ADAPTER *ioc)
{
- if (this != NULL) {
- int sz_first, sz_last;
+ int sz_first, sz_last;
- sz_first = this->alloc_total;
+ if (ioc == NULL)
+ return;
- if (this->alt_ioc != NULL) {
- this->alt_ioc->alt_ioc = NULL;
- this->alt_ioc = NULL;
- }
+ sz_first = ioc->alloc_total;
- mpt_adapter_disable(this, 1);
+ mpt_adapter_disable(ioc);
- if (this->pci_irq != -1) {
- free_irq(this->pci_irq, this);
- this->pci_irq = -1;
- }
+ if (ioc->pci_irq != -1) {
+ free_irq(ioc->pci_irq, ioc);
+ if (mpt_msi_enable)
+ pci_disable_msi(ioc->pcidev);
+ ioc->pci_irq = -1;
+ }
- if (this->memmap != NULL)
- iounmap((u8 *) this->memmap);
+ if (ioc->memmap != NULL) {
+ iounmap(ioc->memmap);
+ ioc->memmap = NULL;
+ }
#if defined(CONFIG_MTRR) && 0
- if (this->mtrr_reg > 0) {
- mtrr_del(this->mtrr_reg, 0, 0);
- dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
- }
+ if (ioc->mtrr_reg > 0) {
+ mtrr_del(ioc->mtrr_reg, 0, 0);
+ dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+ }
#endif
- /* Zap the adapter lookup ptr! */
- mpt_adapters[this->id] = NULL;
+ /* Zap the adapter lookup ptr! */
+ list_del(&ioc->list);
- sz_last = this->alloc_total;
- dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
- this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
- kfree(this);
- }
+ sz_last = ioc->alloc_total;
+ dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+ ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+
+ if (ioc->alt_ioc)
+ ioc->alt_ioc->alt_ioc = NULL;
+
+ kfree(ioc);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
}
/* Is it already READY? */
- if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
- if ((int)ioc->chip_type <= (int)FC929)
- return 0;
- else {
- /* Workaround from broken 1030 FW.
- * Force a diagnostic reset if fails.
- */
- if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
- return 0;
- else
- statefault = 4;
- }
- }
+ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
+ return 0;
/*
* Check to see if IOC is in FAULT state.
* Hmmm... Did it get left operational?
*/
if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
- dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+ dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
ioc->name));
/* Check WhoInit.
* Else, fall through to KickStart case
*/
whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
- dprintk((KERN_WARNING MYNAM
- ": whoinit 0x%x\n statefault %d force %d\n",
+ dinitprintk((KERN_INFO MYNAM
+ ": whoinit 0x%x statefault %d force %d\n",
whoinit, statefault, force));
if (whoinit == MPI_WHOINIT_PCI_PEER)
return -4;
* Loop here waiting for IOC to come READY.
*/
ii = 0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
+ cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
ii++; cntdn--;
if (!cntdn) {
printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
- ioc->name, (ii+5)/HZ);
+ ioc->name, (int)((ii+5)/HZ));
return -ETIME;
}
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible(1);
} else {
mdelay (1); /* 1 msec delay */
}
int r;
int req_sz;
int reply_sz;
- u32 status;
+ int sz;
+ u32 status, vv;
+ u8 shiftFactor=1;
/* IOC *must* NOT be in RESET state! */
if (ioc->last_state == MPI_IOC_STATE_RESET) {
get_facts.Function = MPI_FUNCTION_IOC_FACTS;
/* Assert: All other get_facts fields are zero! */
- dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
+ dinitprintk((MYIOC_s_INFO_FMT
+ "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
+ ioc->name, req_sz, reply_sz));
/* No non-zero fields in the get_facts request are greater than
* 1 byte in size, so we can just fire it off as is.
facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
- status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
+ status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
/* CHECKME! IOCStatus, IOCLogInfo */
facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
le32_to_cpu(facts->CurrentSenseBufferHighAddr);
facts->CurReplyFrameSize =
le16_to_cpu(facts->CurReplyFrameSize);
+ facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
/*
* Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
}
+ sz = facts->FWImageSize;
+ if ( sz & 0x01 )
+ sz += 1;
+ if ( sz & 0x02 )
+ sz += 2;
+ facts->FWImageSize = sz;
+
if (!facts->RequestFrameSize) {
/* Something is wrong! */
printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
return -55;
}
+ r = sz = facts->BlockSize;
+ vv = ((63 / (sz * 4)) + 1) & 0x03;
+ ioc->NB_for_64_byte_frame = vv;
+ while ( sz )
+ {
+ shiftFactor++;
+ sz = sz >> 1;
+ }
+ ioc->NBShiftFactor = shiftFactor;
+ dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+ ioc->name, vv, shiftFactor, r));
+
if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
/*
* Set values for this IOC's request & reply frame sizes,
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
- dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
+ dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
ioc->name, ioc->reply_sz, ioc->reply_depth));
- dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
+ dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
ioc->name, ioc->req_sz, ioc->req_depth));
/* Get port facts! */
return r;
}
} else {
- printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
- ioc->name);
+ printk(MYIOC_s_ERR_FMT
+ "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
+ ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
+ RequestFrameSize)/sizeof(u32)));
return -66;
}
get_pfacts.PortNumber = portnum;
/* Assert: All other get_pfacts fields are zero! */
- dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
+ dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
ioc->name, portnum));
/* No non-zero fields in the get_pfacts request are greater than
memset(&init_reply, 0, sizeof(init_reply));
ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
-/* ioc_init.ChainOffset = 0; */
ioc_init.Function = MPI_FUNCTION_IOC_INIT;
-/* ioc_init.Flags = 0; */
/* If we are in a recovery mode and we uploaded the FW image,
* then this pointer is not NULL. Skip the upload a second time.
* Set this flag if cached_fw set for either IOC.
*/
- ioc->upload_fw = 0;
- ioc_init.Flags = 0;
- if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
- if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
- ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
- else
- ioc->upload_fw = 1;
- }
- ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
- ioc->name, ioc_init.Flags, ioc->upload_fw));
+ if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
+ ioc->upload_fw = 1;
+ else
+ ioc->upload_fw = 0;
+ ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+ ioc->name, ioc->upload_fw, ioc->facts.Flags));
- if ((int)ioc->chip_type <= (int)FC929) {
+ if(ioc->bus_type == SAS)
+ ioc_init.MaxDevices = ioc->facts.MaxDevices;
+ else if(ioc->bus_type == FC)
ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
- } else {
+ else
ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
- }
ioc_init.MaxBuses = MPT_MAX_BUS;
-
-/* ioc_init.MsgFlags = 0; */
-/* ioc_init.MsgContext = cpu_to_le32(0x00000000); */
+ dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+ ioc->name, ioc->facts.MsgVersion));
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+ // set MsgVersion and HeaderVersion host driver was built with
+ ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
+ ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
+
+ if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
+ ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
+ } else if(mpt_host_page_alloc(ioc, &ioc_init))
+ return -99;
+ }
ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
-
- ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
if (sizeof(dma_addr_t) == sizeof(u64)) {
/* Save the upper 32-bits of the request
* (reply) and sense buffers.
*/
- ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
+ ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
} else {
/* Force 32-bit addressing */
ioc_init.HostMfaHighAddr = cpu_to_le32(0);
ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
}
-
+
ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
+ ioc->facts.MaxDevices = ioc_init.MaxDevices;
+ ioc->facts.MaxBuses = ioc_init.MaxBuses;
- dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
+ dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
ioc->name, &ioc_init));
r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
- if (r != 0)
+ if (r != 0) {
+ printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
return r;
+ }
/* No need to byte swap the multibyte fields in the reply
* since we don't even look at it's contents.
*/
- if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
+ dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
+ ioc->name, &ioc_init));
+
+ if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
+ printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
return r;
+ }
/* YIKES! SUPER IMPORTANT!!!
* Poll IocState until _OPERATIONAL while IOC is doing
state = mpt_GetIocState(ioc, 1);
while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible(1);
} else {
mdelay(1);
}
if (!cntdn) {
printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
- ioc->name, (count+5)/HZ);
+ ioc->name, (int)((count+5)/HZ));
return -9;
}
state = mpt_GetIocState(ioc, 1);
count++;
}
- dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+ dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
ioc->name, count));
return r;
{
PortEnable_t port_enable;
MPIDefaultReply_t reply_buf;
- int ii;
+ int rc;
int req_sz;
int reply_sz;
/* port_enable.MsgFlags = 0; */
/* port_enable.MsgContext = 0; */
- dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
+ dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
ioc->name, portnum, &port_enable));
/* RAID FW may take a long time to enable
*/
- if ((int)ioc->chip_type <= (int)FC929) {
- ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
- reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
+ if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+ > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
+ (ioc->bus_type == SAS)) {
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+ (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+ 300 /*seconds*/, sleepFlag);
} else {
- ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
- reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+ (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+ 30 /*seconds*/, sleepFlag);
}
-
- if (ii != 0)
- return ii;
-
- /* We do not even look at the reply, so we need not
- * swap the multi-byte fields.
- */
-
- return 0;
+ return rc;
}
/*
- * Inputs: size - total FW bytes
- * Outputs: frags - number of fragments needed
- * Return NULL if failed.
+ * ioc: Pointer to MPT_ADAPTER structure
+ * size - total FW bytes
*/
-void *
-mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
+void
+mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
{
- fw_image_t **cached_fw;
- u8 *mem;
- dma_addr_t fw_dma;
- int alloc_total = 0;
- int bytes_left, bytes, num_frags;
- int sz, ii;
-
- /* cached_fw
- */
- sz = ioc->num_fw_frags * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL)
- return NULL;
-
- memset(mem, 0, sz);
- cached_fw = (fw_image_t **)mem;
- alloc_total += sz;
-
- /* malloc fragment memory
- * fw_image_t struct and dma for fw data
- */
- bytes_left = size;
- ii = 0;
- num_frags = 0;
- bytes = bytes_left;
- while((bytes_left) && (num_frags < ioc->num_fw_frags)) {
- if (cached_fw[ii] == NULL) {
- mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC);
- if (mem == NULL)
- break;
-
- memset(mem, 0, sizeof(fw_image_t));
- cached_fw[ii] = (fw_image_t *)mem;
- alloc_total += sizeof(fw_image_t);
- }
-
- mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma);
- if (mem == NULL) {
- if (bytes > 0x10000)
- bytes = 0x10000;
- else if (bytes > 0x8000)
- bytes = 0x8000;
- else if (bytes > 0x4000)
- bytes = 0x4000;
- else if (bytes > 0x2000)
- bytes = 0x2000;
- else if (bytes > 0x1000)
- bytes = 0x1000;
- else
- break;
-
- continue;
- }
-
- cached_fw[ii]->fw = mem;
- cached_fw[ii]->fw_dma = fw_dma;
- cached_fw[ii]->size = bytes;
- memset(mem, 0, bytes);
- alloc_total += bytes;
-
- bytes_left -= bytes;
-
- num_frags++;
- ii++;
- }
-
- if (bytes_left ) {
- /* Major Failure.
- */
- mpt_free_fw_memory(ioc, cached_fw);
- return NULL;
+ if (ioc->cached_fw)
+ return; /* use already allocated memory */
+ if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+ ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
+ ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
+ } else {
+ if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
+ ioc->alloc_total += size;
}
-
- *frags = num_frags;
- *alloc_sz = alloc_total;
-
- return (void *) cached_fw;
}
-
/*
* If alt_img is NULL, delete from ioc structure.
* Else, delete a secondary image in same format.
*/
void
-mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img)
+mpt_free_fw_memory(MPT_ADAPTER *ioc)
{
- fw_image_t **cached_fw;
- int ii;
int sz;
- int alloc_freed = 0;
-
- if (alt_img != NULL)
- cached_fw = alt_img;
- else
- cached_fw = ioc->cached_fw;
-
- if (cached_fw == NULL)
- return;
-
- ii = 0;
- while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) {
- sz = cached_fw[ii]->size;
- if (sz > 0) {
- pci_free_consistent(ioc->pcidev, sz,
- cached_fw[ii]->fw, cached_fw[ii]->fw_dma);
- }
- cached_fw[ii]->fw = NULL;
- alloc_freed += sz;
-
- kfree(cached_fw[ii]);
- cached_fw[ii] = NULL;
- alloc_freed += sizeof(fw_image_t);
-
- ii++;
- }
-
- kfree(cached_fw);
- cached_fw = NULL;
- sz = ioc->num_fw_frags * sizeof(void *);
- alloc_freed += sz;
- if (alt_img == NULL)
- ioc->alloc_total -= alloc_freed;
+ sz = ioc->facts.FWImageSize;
+ dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+ pci_free_consistent(ioc->pcidev, sz,
+ ioc->cached_fw, ioc->cached_fw_dma);
+ ioc->cached_fw = NULL;
return;
}
FWUploadReply_t *preply;
FWUploadTCSGE_t *ptcsge;
int sgeoffset;
+ u32 flagsLength;
int ii, sz, reply_sz;
- int cmdStatus, freeMem = 0;
- int num_frags, alloc_sz;
+ int cmdStatus;
- /* If the image size is 0 or if the pointer is
- * not NULL (error), we are done.
+ /* If the image size is 0, we are done.
*/
- if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
+ if ((sz = ioc->facts.FWImageSize) == 0)
return 0;
- ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
- ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
+ mpt_alloc_fw_memory(ioc, sz);
- ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
- ioc->facts.FWImageSize, &num_frags, &alloc_sz);
+ dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
if (ioc->cached_fw == NULL) {
/* Major Failure.
*/
- mpt_free_fw_memory(ioc, NULL);
- ioc->cached_fw = NULL;
-
return -ENOMEM;
}
- ioc->alloc_total += alloc_sz;
-
- ddlprintk((KERN_INFO MYNAM ": FW Image @ %p, sz=%d bytes\n",
- (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize));
prequest = (FWUpload_t *)&request;
preply = (FWUploadReply_t *)&reply;
prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
prequest->Function = MPI_FUNCTION_FW_UPLOAD;
- prequest->MsgContext = 0; /* anything */
ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
- ptcsge->Reserved = 0;
- ptcsge->ContextSize = 0;
ptcsge->DetailsLength = 12;
ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
- ptcsge->Reserved1 = 0;
- ptcsge->ImageOffset = 0;
ptcsge->ImageSize = cpu_to_le32(sz);
sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
- for (ii = 0; ii < (num_frags-1); ii++) {
- mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT |
- MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST |
- (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma);
-
- sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
- }
-
- mpt_add_sge(&request[sgeoffset],
- MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
- ioc->cached_fw[ii]->fw_dma);
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
+ mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-
- dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n",
- ioc->name, prequest, sgeoffset));
+ dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
+ prequest, sgeoffset));
+ DBG_DUMP_FW_REQUEST_FRAME(prequest)
ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
+ dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
+
cmdStatus = -EFAULT;
if (ii == 0) {
/* Handshake transfer was complete and successful.
cmdStatus = 0;
}
}
- ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+ dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
ioc->name, cmdStatus));
- /* Check to see if we have a copy of this image in
- * host memory already.
- */
- if (cmdStatus == 0) {
- ioc->upload_fw = 0;
- if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
- freeMem = 1;
- }
- /* We already have a copy of this image or
- * we had some type of an error - either the handshake
- * failed (i != 0) or the command did not complete successfully.
- */
- if (cmdStatus || freeMem) {
+ if (cmdStatus) {
- ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
- ioc->name, cmdStatus ? "incomplete" : "duplicate"));
- mpt_free_fw_memory(ioc, NULL);
- ioc->cached_fw = NULL;
+ ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
+ ioc->name));
+ mpt_free_fw_memory(ioc);
}
return cmdStatus;
* <0 for fw upload failure.
*/
static int
-mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
{
- MpiFwHeader_t *FwHdr;
- MpiExtImageHeader_t *ExtHdr;
- fw_image_t **pCached=NULL;
- int fw_sz;
+ MpiExtImageHeader_t *pExtImage;
+ u32 fwSize;
u32 diag0val;
-#ifdef MPT_DEBUG
- u32 diag1val = 0;
-#endif
- int count = 0;
- u32 *ptru32;
+ int count;
+ u32 *ptrFw;
u32 diagRwData;
u32 nextImage;
- u32 ext_offset;
u32 load_addr;
- int max_idx, fw_idx, ext_idx;
- int left_u32s;
-
- ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n",
- ioc->name));
-#ifdef MPT_DEBUG
- diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
- if (ioc->alt_ioc)
- diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
- ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
- ioc->name, diag0val, diag1val));
-#endif
+ u32 ioc_state=0;
- ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
- ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
- if (ioc->alt_ioc)
- ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
- ioc->name, ioc->alt_ioc->cached_fw));
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
+ ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
- /* Get dma_addr and data transfer size.
- */
- if ((fw_sz = ioc->facts.FWImageSize) == 0)
- return -1;
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
- /* Get the DMA from ioc or ioc->alt_ioc */
- if (ioc->cached_fw != NULL)
- pCached = (fw_image_t **)ioc->cached_fw;
- else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL))
- pCached = (fw_image_t **)ioc->alt_ioc->cached_fw;
- else
- return -2;
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
- ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
- ioc->name, pCached));
+ /* wait 1 msec */
+ if (sleepFlag == CAN_SLEEP) {
+ msleep_interruptible(1);
+ } else {
+ mdelay (1);
+ }
- /* Write magic sequence to WriteSequence register
- * until enter diagnostic mode
- */
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
- while ((diag0val & MPI_DIAG_DRWE) == 0) {
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
- /* wait 100 msec */
+ for (count = 0; count < 30; count ++) {
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+ if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+ ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
+ ioc->name, count));
+ break;
+ }
+ /* wait .1 sec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(100 * HZ / 1000);
+ msleep_interruptible (100);
} else {
mdelay (100);
}
-
- count++;
- if (count > 20) {
- printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
- ioc->name, diag0val);
- return -EFAULT;
-
- }
-
- diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
- if (ioc->alt_ioc)
- diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
- ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
- ioc->name, diag0val, diag1val));
-#endif
- ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
- ioc->name, diag0val));
}
- /* Set the DiagRwEn and Disable ARM bits */
- diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM);
- CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-
-#ifdef MPT_DEBUG
- if (ioc->alt_ioc)
- diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+ if ( count == 30 ) {
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
+ "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
+ ioc->name, diag0val));
+ return -3;
+ }
- ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
- ioc->name, diag0val, diag1val));
-#endif
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
- /* max_idx = 1 + maximum valid buffer index
- */
- max_idx = 0;
- while (pCached[max_idx])
- max_idx++;
+ /* Set the DiagRwEn and Disable ARM bits */
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
- fw_idx = 0;
- FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw;
- ptru32 = (u32 *) FwHdr;
- count = (FwHdr->ImageSize + 3)/4;
- nextImage = FwHdr->NextImageHeaderOffset;
+ fwSize = (pFwHeader->ImageSize + 3)/4;
+ ptrFw = (u32 *) pFwHeader;
/* Write the LoadStartAddress to the DiagRw Address Register
* using Programmed IO
*/
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
+ if (ioc->errata_flag_1064)
+ pci_enable_io_access(ioc->pcidev);
+
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
- ioc->name, FwHdr->LoadStartAddress));
-
- ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
- ioc->name, count, ptru32));
- left_u32s = pCached[fw_idx]->size/4;
- while (count--) {
- if (left_u32s == 0) {
- fw_idx++;
- if (fw_idx >= max_idx) {
- /* FIXME
- ERROR CASE
- */
- ;
- }
- ptru32 = (u32 *) pCached[fw_idx]->fw;
- left_u32s = pCached[fw_idx]->size / 4;
- }
- left_u32s--;
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
- ptru32++;
+ ioc->name, pFwHeader->LoadStartAddress));
+
+ ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
+ ioc->name, fwSize*4, ptrFw));
+ while (fwSize--) {
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
}
- /* left_u32s, fw_idx and ptru32 are all valid
- */
+ nextImage = pFwHeader->NextImageHeaderOffset;
while (nextImage) {
- ext_idx = 0;
- ext_offset = nextImage;
- while (ext_offset > pCached[ext_idx]->size) {
- ext_idx++;
- if (ext_idx >= max_idx) {
- /* FIXME
- ERROR CASE
- */
- ;
- }
- ext_offset -= pCached[ext_idx]->size;
- }
- ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset);
- left_u32s = pCached[ext_idx]->size - ext_offset;
-
- if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) {
- ExtHdr = (MpiExtImageHeader_t *) ptru32;
- count = (ExtHdr->ImageSize + 3 )/4;
- nextImage = ExtHdr->NextImageHeaderOffset;
- load_addr = ExtHdr->LoadStartAddress;
- } else {
- u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw;
-
- switch (left_u32s) {
- case 5:
- count = *(ptru32 + 2);
- nextImage = *(ptru32 + 3);
- load_addr = *(ptru32 + 4);
- break;
- case 4:
- count = *(ptru32 + 2);
- nextImage = *(ptru32 + 3);
- load_addr = *ptmp;
- break;
- case 3:
- count = *(ptru32 + 2);
- nextImage = *ptmp;
- load_addr = *(ptmp + 1);
- break;
- case 2:
- count = *ptmp;
- nextImage = *(ptmp + 1);
- load_addr = *(ptmp + 2);
- break;
-
- case 1:
- count = *(ptmp + 1);
- nextImage = *(ptmp + 2);
- load_addr = *(ptmp + 3);
- break;
+ pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
- default:
- count = 0;
- nextImage = 0;
- load_addr = 0;
- /* FIXME
- ERROR CASE
- */
- ;
+ load_addr = pExtImage->LoadStartAddress;
- }
- count = (count +3)/4;
- }
+ fwSize = (pExtImage->ImageSize + 3) >> 2;
+ ptrFw = (u32 *)pExtImage;
- ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
- ioc->name, count, ptru32));
+ ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+ ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
- while (count--) {
- if (left_u32s == 0) {
- fw_idx++;
- if (fw_idx >= max_idx) {
- /* FIXME
- ERROR CASE
- */
- ;
- }
- ptru32 = (u32 *) pCached[fw_idx]->fw;
- left_u32s = pCached[fw_idx]->size / 4;
- }
- left_u32s--;
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
- ptru32++;
+ while (fwSize--) {
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
}
+ nextImage = pExtImage->NextImageHeaderOffset;
}
/* Write the IopResetVectorRegAddr */
- ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
+ ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
/* Write the IopResetVectorValue */
- ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
+ ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
/* Clear the internal flash bad bit - autoincrementing register,
* so must do two writes.
*/
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
- diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
- diagRwData |= 0x4000000;
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+ if (ioc->bus_type == SPI) {
+ /*
+ * 1030 and 1035 H/W errata, workaround to access
+ * the ClearFlashBadSignatureBit
+ */
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+ diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+ diagRwData |= 0x40000000;
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+
+ } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
+ MPI_DIAG_CLEAR_FLASH_BAD_SIG);
+
+ /* wait 1 msec */
+ if (sleepFlag == CAN_SLEEP) {
+ msleep_interruptible (1);
+ } else {
+ mdelay (1);
+ }
+ }
+
+ if (ioc->errata_flag_1064)
+ pci_disable_io_access(ioc->pcidev);
- /* clear the RW enable and DISARM bits */
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
- diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG);
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
+ "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
+ ioc->name, diag0val));
+ diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+ ioc->name, diag0val));
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
/* Write 0xFF to reset the sequencer */
CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
- return 0;
+ if (ioc->bus_type == SAS) {
+ ioc_state = mpt_GetIocState(ioc, 0);
+ if ( (GetIocFacts(ioc, sleepFlag,
+ MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
+ ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
+ ioc->name, ioc_state));
+ return -EFAULT;
+ }
+ }
+
+ for (count=0; count<HZ*20; count++) {
+ if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
+ ioc->name, count, ioc_state));
+ if (ioc->bus_type == SAS) {
+ return 0;
+ }
+ if ((SendIocInit(ioc, sleepFlag)) != 0) {
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+ ioc->name));
+ return -EFAULT;
+ }
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+ ioc->name));
+ return 0;
+ }
+ if (sleepFlag == CAN_SLEEP) {
+ msleep_interruptible (10);
+ } else {
+ mdelay (10);
+ }
+ }
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
+ ioc->name, ioc_state));
+ return -EFAULT;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
* 0 else
*
* Returns:
- * 1 - hard reset, READY
- * 0 - no reset due to History bit, READY
- * -1 - no reset due to History bit but not READY
+ * 1 - hard reset, READY
+ * 0 - no reset due to History bit, READY
+ * -1 - no reset due to History bit but not READY
* OR reset but failed to come READY
* -2 - no reset, could not enter DIAG mode
* -3 - reset but bad FW bit
KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
{
int hard_reset_done = 0;
- u32 ioc_state;
- int cntdn, cnt = 0;
+ u32 ioc_state=0;
+ int cnt,cntdn;
- dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
- if ((int)ioc->chip_type > (int)FC929) {
+ dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+ if (ioc->bus_type == SPI) {
/* Always issue a Msg Unit Reset first. This will clear some
* SCSI bus hang conditions.
*/
SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
+ msleep_interruptible (1000);
} else {
mdelay (1000);
}
if (hard_reset_done < 0)
return hard_reset_done;
- dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
+ dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
ioc->name));
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20; /* 20 seconds */
+ cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
for (cnt=0; cnt<cntdn; cnt++) {
- if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
- dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
- ioc->name, cnt));
+ ioc_state = mpt_GetIocState(ioc, 1);
+ if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
+ dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
+ ioc->name, cnt));
return hard_reset_done;
}
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible (10);
} else {
mdelay (10);
}
}
- printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
- ioc->name);
+ printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
+ ioc->name, ioc_state);
return -1;
}
/* wait 100 msec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(100 * HZ / 1000);
+ msleep_interruptible (100);
} else {
mdelay (100);
}
dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
ioc->name, diag0val, diag1val));
#endif
- /* Write the PreventIocBoot bit */
- if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
- diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
- CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
- }
-
/*
* Disable the ARM (Bug fix)
*
*/
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
- mdelay (1);
+ mdelay(1);
/*
* Now hit the reset bit in the Diagnostic register
/* FIXME? Examine results here? */
}
- if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
+ if (ioc->cached_fw) {
/* If the DownloadBoot operation fails, the
* IOC will be left unusable. This is a fatal error
* case. _diag_reset will return < 0
*/
for (count = 0; count < 30; count ++) {
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
- if (ioc->alt_ioc)
- diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
- dprintk((MYIOC_s_INFO_FMT
- "DbG2b: diag0=%08x, diag1=%08x\n",
- ioc->name, diag0val, diag1val));
-#endif
if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
break;
}
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
+ msleep_interruptible (1000);
} else {
mdelay (1000);
}
}
- if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+ if ((count = mpt_downloadboot(ioc,
+ (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", count);
}
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
+ msleep_interruptible (1000);
} else {
mdelay (1000);
}
/* Write magic sequence to WriteSequence register
* Loop until in diagnostic mode
*/
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
/* wait 100 msec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(100 * HZ / 1000);
+ msleep_interruptible (100);
} else {
mdelay (100);
}
u32 state;
int cntdn, count;
- dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+ drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
ioc->name, reset_type));
CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
count *= 10;
printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
- ioc->name, (count+5)/HZ);
+ ioc->name, (int)((count+5)/HZ));
return -ETIME;
}
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible(1);
} else {
mdelay (1); /* 1 msec delay */
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * PrimeIocFifos - Initialize IOC request and reply FIFOs.
- * @ioc: Pointer to MPT_ADAPTER structure
- *
- * This routine allocates memory for the MPT reply and request frame
- * pools (if necessary), and primes the IOC reply FIFO with
- * reply frames.
- *
- * Returns 0 for success, non-zero for failure.
+ * initChainBuffers - Allocate memory for and initialize
+ * chain buffers, chain buffer control arrays and spinlock.
+ * @hd: Pointer to MPT_SCSI_HOST structure
+ * @init: If set, initialize the spin lock.
*/
static int
-PrimeIocFifos(MPT_ADAPTER *ioc)
+initChainBuffers(MPT_ADAPTER *ioc)
{
- MPT_FRAME_HDR *mf;
- unsigned long b;
- unsigned long flags;
- dma_addr_t aligned_mem_dma;
- u8 *aligned_mem;
- int i, sz;
- int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
- int scale, num_sge, num_chain;
+ u8 *mem;
+ int sz, ii, num_chain;
+ int scale, num_sge, numSGE;
+
+ /* ReqToChain size must equal the req_depth
+ * index = req_idx
+ */
+ if (ioc->ReqToChain == NULL) {
+ sz = ioc->req_depth * sizeof(int);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ return -1;
- /* request buffer size, rounding UP to nearest 4-kB boundary */
- request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
- request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+ ioc->ReqToChain = (int *) mem;
+ dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
+ ioc->name, mem, sz));
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ return -1;
- /* reply buffer size */
- reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+ ioc->RequestNB = (int *) mem;
+ dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
+ ioc->name, mem, sz));
+ }
+ for (ii = 0; ii < ioc->req_depth; ii++) {
+ ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
+ }
- /* chain buffer size, copied from from mptscsih_initChainBuffers()
+ /* ChainToChain size must equal the total number
+ * of chain buffers to be allocated.
+ * index = chain_idx
*
* Calculate the number of chain buffers needed(plus 1) per I/O
* then multiply the the maximum number of simultaneous cmds
* num_sge = num sge in request frame + last chain buffer
* scale = num sge per chain buffer if no chain element
*/
-
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
if (sizeof(dma_addr_t) == sizeof(u64))
num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
else
- num_sge = 1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+ num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+ } else {
+ numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+ }
+ dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
+ ioc->name, num_sge, numSGE));
+
+ if ( numSGE > MPT_SCSI_SG_DEPTH )
+ numSGE = MPT_SCSI_SG_DEPTH;
+
+ num_chain = 1;
+ while (numSGE - num_sge > 0) {
+ num_chain++;
+ num_sge += (scale - 1);
+ }
+ num_chain++;
+
+ dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
+ ioc->name, numSGE, num_sge, num_chain));
+
+ if (ioc->bus_type == SPI)
+ num_chain *= MPT_SCSI_CAN_QUEUE;
+ else
+ num_chain *= MPT_FC_CAN_QUEUE;
+
+ ioc->num_chain = num_chain;
+
+ sz = num_chain * sizeof(int);
+ if (ioc->ChainToChain == NULL) {
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ return -1;
+
+ ioc->ChainToChain = (int *) mem;
+ dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
+ ioc->name, mem, sz));
+ } else {
+ mem = (u8 *) ioc->ChainToChain;
+ }
+ memset(mem, 0xFF, sz);
+ return num_chain;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * PrimeIocFifos - Initialize IOC request and reply FIFOs.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ *
+ * This routine allocates memory for the MPT reply and request frame
+ * pools (if necessary), and primes the IOC reply FIFO with
+ * reply frames.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+PrimeIocFifos(MPT_ADAPTER *ioc)
+{
+ MPT_FRAME_HDR *mf;
+ unsigned long flags;
+ dma_addr_t alloc_dma;
+ u8 *mem;
+ int i, reply_sz, sz, total_size, num_chain;
- num_chain = 1;
- while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
- num_chain++;
- num_sge += (scale - 1);
- }
- num_chain++;
+ /* Prime reply FIFO... */
- if ((int)ioc->chip_type > (int) FC929)
- num_chain *= MPT_SCSI_CAN_QUEUE;
- else
- num_chain *= MPT_FC_CAN_QUEUE;
+ if (ioc->reply_frames == NULL) {
+ if ( (num_chain = initChainBuffers(ioc)) < 0)
+ return -1;
- chain_buffer_sz = num_chain * ioc->req_sz;
+ total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
+ dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
+ ioc->name, ioc->reply_sz, ioc->reply_depth));
+ dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
+ ioc->name, reply_sz, reply_sz));
+
+ sz = (ioc->req_sz * ioc->req_depth);
+ dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+ ioc->name, ioc->req_sz, ioc->req_depth));
+ dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
+ ioc->name, sz, sz));
+ total_size += sz;
+
+ sz = num_chain * ioc->req_sz; /* chain buffer pool size */
+ dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
+ ioc->name, ioc->req_sz, num_chain));
+ dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
+ ioc->name, sz, sz, num_chain));
+
+ total_size += sz;
+ mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
+ if (mem == NULL) {
+ printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
+ ioc->name);
+ goto out_fail;
+ }
- if(ioc->fifo_pool == NULL) {
+ dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
+ ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
- ioc->fifo_pool_sz = request_buffer_sz +
- reply_buffer_sz + chain_buffer_sz;
+ memset(mem, 0, total_size);
+ ioc->alloc_total += total_size;
+ ioc->alloc = mem;
+ ioc->alloc_dma = alloc_dma;
+ ioc->alloc_sz = total_size;
+ ioc->reply_frames = (MPT_FRAME_HDR *) mem;
+ ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
- ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
- ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
+ dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
- if( ioc->fifo_pool == NULL)
- goto out_fail;
+ alloc_dma += reply_sz;
+ mem += reply_sz;
- ioc->alloc_total += ioc->fifo_pool_sz;
- memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
-
- /* reply fifo pointers */
- ioc->reply_alloc = ioc->fifo_pool;
- ioc->reply_alloc_dma = ioc->fifo_pool_dma;
- /* request fifo pointers */
- ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
- ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
- /* chain buffer pointers */
- ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
- ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
- ioc->chain_alloc_sz = chain_buffer_sz;
-
- /* Prime reply FIFO... */
- dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%p], sz=%d bytes\n",
- ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
-
- b = (unsigned long) ioc->reply_alloc;
- b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
- aligned_mem = (u8 *) b;
- ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
- ioc->reply_frames_dma =
- (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
-
- ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
-
/* Request FIFO - WE manage this! */
- dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%p], sz=%d bytes\n",
- ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
- b = (unsigned long) ioc->req_alloc;
- b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
- aligned_mem = (u8 *) b;
- ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
- ioc->req_frames_dma =
- (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
+ ioc->req_frames = (MPT_FRAME_HDR *) mem;
+ ioc->req_frames_dma = alloc_dma;
- ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
+ dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
+ ioc->name, mem, (void *)(ulong)alloc_dma));
+
+ ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
#if defined(CONFIG_MTRR) && 0
/*
* (at least as much as we can; "size and base must be
* multiples of 4 kiB"
*/
- ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
- ioc->fifo_pool_sz,
+ ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
+ sz,
MTRR_TYPE_WRCOMB, 1);
dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
- ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
+ ioc->name, ioc->req_frames_dma, sz));
#endif
- } /* ioc->fifo_pool == NULL */
-
- /* Post Reply frames to FIFO
- */
- aligned_mem_dma = ioc->reply_frames_dma;
- dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
- ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
+ for (i = 0; i < ioc->req_depth; i++) {
+ alloc_dma += ioc->req_sz;
+ mem += ioc->req_sz;
+ }
- for (i = 0; i < ioc->reply_depth; i++) {
- /* Write each address to the IOC! */
- CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
- aligned_mem_dma += ioc->reply_sz;
- }
+ ioc->ChainBuffer = mem;
+ ioc->ChainBufferDMA = alloc_dma;
+ dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
+ ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
- /* Initialize Request frames linked list
- */
- aligned_mem_dma = ioc->req_frames_dma;
- aligned_mem = (u8 *) ioc->req_frames;
- dprintk((KERN_INFO MYNAM ": %s.req_frames @ %p[%p]\n",
- ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
+ /* Initialize the free chain Q.
+ */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
- for (i = 0; i < ioc->req_depth; i++) {
- mf = (MPT_FRAME_HDR *) aligned_mem;
+ INIT_LIST_HEAD(&ioc->FreeChainQ);
- /* Queue REQUESTs *internally*! */
- Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
- aligned_mem += ioc->req_sz;
- }
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ /* Post the chain buffers to the FreeChainQ.
+ */
+ mem = (u8 *)ioc->ChainBuffer;
+ for (i=0; i < num_chain; i++) {
+ mf = (MPT_FRAME_HDR *) mem;
+ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
+ mem += ioc->req_sz;
+ }
+
+ /* Initialize Request frames linked list
+ */
+ alloc_dma = ioc->req_frames_dma;
+ mem = (u8 *) ioc->req_frames;
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+ INIT_LIST_HEAD(&ioc->FreeQ);
+ for (i = 0; i < ioc->req_depth; i++) {
+ mf = (MPT_FRAME_HDR *) mem;
+
+ /* Queue REQUESTs *internally*! */
+ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+
+ mem += ioc->req_sz;
+ }
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
- if (ioc->sense_buf_pool == NULL) {
sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
ioc->sense_buf_pool =
- pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
- if (ioc->sense_buf_pool == NULL)
+ pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+ if (ioc->sense_buf_pool == NULL) {
+ printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
+ ioc->name);
goto out_fail;
+ }
ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
ioc->alloc_total += sz;
+ dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
+ ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
+
+ }
+
+ /* Post Reply frames to FIFO
+ */
+ alloc_dma = ioc->alloc_dma;
+ dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
+ for (i = 0; i < ioc->reply_depth; i++) {
+ /* Write each address to the IOC! */
+ CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
+ alloc_dma += ioc->reply_sz;
}
return 0;
out_fail:
- if (ioc->fifo_pool != NULL) {
+ if (ioc->alloc != NULL) {
+ sz = ioc->alloc_sz;
pci_free_consistent(ioc->pcidev,
- ioc->fifo_pool_sz,
- ioc->fifo_pool, ioc->fifo_pool_dma);
+ sz,
+ ioc->alloc, ioc->alloc_dma);
ioc->reply_frames = NULL;
- ioc->reply_alloc = NULL;
ioc->req_frames = NULL;
- ioc->req_alloc = NULL;
- ioc->chain_alloc = NULL;
- ioc->fifo_pool = NULL;
- ioc->alloc_total -= ioc->fifo_pool_sz;
-#if defined(CONFIG_MTRR) && 0
- if (ioc->mtrr_reg > 0) {
- mtrr_del(ioc->mtrr_reg, 0, 0);
- dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
- ioc->name));
- }
-#endif
+ ioc->alloc_total -= sz;
}
if (ioc->sense_buf_pool != NULL) {
sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
*
* Returns 0 for success, non-zero for failure.
*/
-int
+static int
mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
- int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+ int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
{
MPIDefaultReply_t *mptReply;
int failcnt = 0;
if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
failcnt++;
- dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
- ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+ dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
+ ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
/* Read doorbell and check for active bit */
if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
failcnt++;
}
- dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
+ dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
DBG_DUMP_REQUEST_FRAME_HDR(req)
dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
failcnt++;
+ dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
+ ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
+
/*
* Copy out the cached reply...
*/
{
int cntdn;
int count = 0;
- u32 intstat;
+ u32 intstat=0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+ cntdn = 1000 * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible (1);
count++;
}
} else {
}
if (cntdn) {
- dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
+ dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
ioc->name, count));
return count;
}
- printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
- ioc->name, (count+5)/HZ);
+ printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
+ ioc->name, count, intstat);
return -1;
}
{
int cntdn;
int count = 0;
- u32 intstat;
+ u32 intstat=0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+ cntdn = 1000 * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
break;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ msleep_interruptible(1);
count++;
}
} else {
}
if (cntdn) {
- dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
- ioc->name, count));
+ dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
+ ioc->name, count, howlong));
return count;
}
- printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
- ioc->name, (count+5)/HZ);
+ printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
+ ioc->name, count, intstat);
return -1;
}
}
}
- dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
- ioc->name, le32_to_cpu(*(u32 *)hs_reply),
+ dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
+ ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
/*
}
#endif
- dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
+ dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
DBG_DUMP_REPLY_FRAME(mptReply)
- dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
- ioc->name, u16cnt/2));
+ dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
+ ioc->name, t, u16cnt/2));
return u16cnt/2;
}
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
hdr.PageLength = 0;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * GetFcPortPage0 - Fetch FCPort config Page0.
+ * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
* @ioc: Pointer to MPT_ADAPTER structure
* @portnum: IOC Port number
*
* -EAGAIN if no msg frames currently available
* -EFAULT for non-successful reply or no reply (timeout)
*/
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
int data_sz;
int copy_sz;
int rc;
+ int count = 400;
+
/* Get FCPort Page 0 header */
hdr.PageVersion = 0;
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
rc = -ENOMEM;
ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
if (ppage0_alloc) {
+
+ try_again:
memset((u8 *)ppage0_alloc, 0, data_sz);
cfg.physAddr = page0_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+ /*
+ * if still doing discovery,
+ * hang loose a while until finished
+ */
+ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+ if (count-- > 0) {
+ msleep_interruptible(100);
+ goto try_again;
+ }
+ printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+ " complete.\n",
+ ioc->name);
+ }
}
pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
return rc;
}
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sas_address: 64bit SAS Address for operation.
+ * @target_id: specified target for operation
+ * @bus: specified bus for operation
+ * @persist_opcode: see below
+ *
+ * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+ * devices not currently present.
+ * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+ *
+ * NOTE: Don't use not this function during interrupt time.
+ *
+ * Returns: 0 for success, non-zero error
+ */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int
+mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
+{
+ SasIoUnitControlRequest_t *sasIoUnitCntrReq;
+ SasIoUnitControlReply_t *sasIoUnitCntrReply;
+ MPT_FRAME_HDR *mf = NULL;
+ MPIHeader_t *mpi_hdr;
+
+
+ /* insure garbage is not sent to fw */
+ switch(persist_opcode) {
+
+ case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+ case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+
+ /* Get a MF for this command.
+ */
+ if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+ printk("%s: no msg frames!\n",__FUNCTION__);
+ return -1;
+ }
+
+ mpi_hdr = (MPIHeader_t *) mf;
+ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+ sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+ sasIoUnitCntrReq->Operation = persist_opcode;
+
+ init_timer(&ioc->persist_timer);
+ ioc->persist_timer.data = (unsigned long) ioc;
+ ioc->persist_timer.function = mpt_timer_expired;
+ ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
+ ioc->persist_wait_done=0;
+ add_timer(&ioc->persist_timer);
+ mpt_put_msg_frame(mpt_base_index, ioc, mf);
+ wait_event(mpt_waitq, ioc->persist_wait_done);
+
+ sasIoUnitCntrReply =
+ (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+ if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
+ printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+ __FUNCTION__,
+ sasIoUnitCntrReply->IOCStatus,
+ sasIoUnitCntrReply->IOCLogInfo);
+ return -1;
+ }
+
+ printk("%s: success\n",__FUNCTION__);
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static void
+mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+ MpiEventDataRaid_t * pRaidEventData)
+{
+ int volume;
+ int reason;
+ int disk;
+ int status;
+ int flags;
+ int state;
+
+ volume = pRaidEventData->VolumeID;
+ reason = pRaidEventData->ReasonCode;
+ disk = pRaidEventData->PhysDiskNum;
+ status = le32_to_cpu(pRaidEventData->SettingsStatus);
+ flags = (status >> 0) & 0xff;
+ state = (status >> 8) & 0xff;
+
+ if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+ return;
+ }
+
+ if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
+ reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
+ (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
+ printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
+ ioc->name, disk);
+ } else {
+ printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
+ ioc->name, volume);
+ }
+
+ switch(reason) {
+ case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+ printk(MYIOC_s_INFO_FMT " volume has been created\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+
+ printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
+ ioc->name,
+ state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
+ ? "optimal"
+ : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
+ ? "degraded"
+ : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
+ ? "failed"
+ : "state unknown",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
+ ? ", enabled" : "",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
+ ? ", quiesced" : "",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
+ ? ", resync in progress" : "" );
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
+ ioc->name, disk);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
+ ioc->name,
+ state == MPI_PHYSDISK0_STATUS_ONLINE
+ ? "online"
+ : state == MPI_PHYSDISK0_STATUS_MISSING
+ ? "missing"
+ : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
+ ? "not compatible"
+ : state == MPI_PHYSDISK0_STATUS_FAILED
+ ? "failed"
+ : state == MPI_PHYSDISK0_STATUS_INITIALIZING
+ ? "initializing"
+ : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
+ ? "offline requested"
+ : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
+ ? "failed requested"
+ : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
+ ? "offline"
+ : "state unknown",
+ flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
+ ? ", out of sync" : "",
+ flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
+ ? ", quiesced" : "" );
+ break;
+
+ case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
+ printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
+ ioc->name, disk);
+ break;
+
+ case MPI_EVENT_RAID_RC_SMART_DATA:
+ printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
+ ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
+ break;
+
+ case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
+ printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
+ ioc->name, disk);
+ break;
+ }
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* GetIoUnitPage2 - Retrieve BIOS version and boot order information.
hdr.PageLength = 0;
hdr.PageNumber = 2;
hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
header.PageLength = 0;
header.PageNumber = 0;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
ioc->spi_data.minSyncFactor = MPT_ASYNC;
ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
rc = 1;
+ ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
/* Save the Port Page 0 data
*/
pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
- if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
+ if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-
+ ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+ ioc->name, pPP0->Capabilities));
+ }
ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
if (data) {
ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
ioc->spi_data.minSyncFactor = (u8) (data >> 8);
+ ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
ioc->spi_data.maxSyncOffset = 0;
ioc->spi_data.minSyncFactor = MPT_ASYNC;
if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
- if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+ if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
ioc->spi_data.minSyncFactor = MPT_ULTRA;
+ ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
+ }
}
}
if (pbuf) {
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
MpiDeviceInfo_t *pdevice = NULL;
+ /*
+ * Save "Set to Avoid SCSI Bus Resets" flag
+ */
+ ioc->spi_data.bus_reset =
+ (le32_to_cpu(pPP2->PortFlags) &
+ MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
+ 0 : 1 ;
+
/* Save the Port Page 2 data
* (reformat into a 32bit quantity)
*/
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
header.PageVersion = 0;
header.PageLength = 0;
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
if (mpt_config(ioc, &cfg) != 0)
goto done_and_free;
- if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
+ if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
mem = kmalloc(iocpage2sz, GFP_ATOMIC);
if (mem) {
- ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
+ ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
} else {
goto done_and_free;
}
/* At least 1 RAID Volume
*/
pIocRv = pIoc2->RaidVolume;
- ioc->spi_data.isRaid = 0;
+ ioc->raid_data.isRaid = 0;
for (jj = 0; jj < nVols; jj++, pIocRv++) {
vid = pIocRv->VolumeID;
vbus = pIocRv->VolumeBus;
/* find the match
*/
if (vbus == 0) {
- ioc->spi_data.isRaid |= (1 << vid);
+ ioc->raid_data.isRaid |= (1 << vid);
} else {
/* Error! Always bus 0
*/
/* Free the old page
*/
- if (ioc->spi_data.pIocPg3) {
- kfree(ioc->spi_data.pIocPg3);
- ioc->spi_data.pIocPg3 = NULL;
- }
+ kfree(ioc->raid_data.pIocPg3);
+ ioc->raid_data.pIocPg3 = NULL;
/* There is at least one physical disk.
* Read and save IOC Page 3
header.PageLength = 0;
header.PageNumber = 3;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
mem = kmalloc(iocpage3sz, GFP_ATOMIC);
if (mem) {
memcpy(mem, (u8 *)pIoc3, iocpage3sz);
- ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+ ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
}
}
header.PageLength = 0;
header.PageNumber = 4;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
{
EventNotification_t *evnp;
- evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
+ evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
if (evnp == NULL) {
- dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+ devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
ioc->name));
return 0;
}
memset(evnp, 0, sizeof(*evnp));
- dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+ devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
evnp->ChainOffset = 0;
evnp->MsgFlags = 0;
evnp->Switch = EvSwitch;
- mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
+ mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
return 0;
}
static int
SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
{
- EventAck_t *pAck;
-
- if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
- printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
- ioc->name);
- return -1;
- }
- memset(pAck, 0, sizeof(*pAck));
-
- dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
-
- pAck->Function = MPI_FUNCTION_EVENT_ACK;
- pAck->ChainOffset = 0;
- pAck->MsgFlags = 0;
- pAck->Event = evnp->Event;
- pAck->EventContext = evnp->EventContext;
-
- mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
-
- return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_config - Generic function to issue config message
- * @ioc - Pointer to an adapter structure
- * @cfg - Pointer to a configuration structure. Struct contains
- * action, page address, direction, physical address
- * and pointer to a configuration page header
- * Page header is updated.
- *
- * Returns 0 for success
- * -EPERM if not allowed due to ISR context
- * -EAGAIN if no msg frames currently available
- * -EFAULT for non-successful reply or no reply (timeout)
- */
-int
-mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
-{
- Config_t *pReq;
- MPT_FRAME_HDR *mf;
- unsigned long flags;
- int ii, rc;
- int flagsLength;
- int in_isr;
-
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 1)! 20010905 -sralston
- * Prevent calling wait_event() (below), if caller happens
- * to be in ISR context, because that is fatal!
- */
- in_isr = in_interrupt();
- if (in_isr) {
- dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
- ioc->name));
- return -EPERM;
- }
-
- /* Get and Populate a free Frame
- */
- if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
- dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
- ioc->name));
- return -EAGAIN;
- }
- pReq = (Config_t *)mf;
- pReq->Action = pCfg->action;
- pReq->Reserved = 0;
- pReq->ChainOffset = 0;
- pReq->Function = MPI_FUNCTION_CONFIG;
- pReq->ExtPageLength = 0;
- pReq->ExtPageType = 0;
- pReq->MsgFlags = 0;
- for (ii=0; ii < 8; ii++)
- pReq->Reserved2[ii] = 0;
-
- pReq->Header.PageVersion = pCfg->hdr->PageVersion;
- pReq->Header.PageLength = pCfg->hdr->PageLength;
- pReq->Header.PageNumber = pCfg->hdr->PageNumber;
- pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
- pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
-
- /* Add a SGE to the config request.
- */
- if (pCfg->dir)
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
- else
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
-
- flagsLength |= pCfg->hdr->PageLength * 4;
-
- mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
-
- dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
- ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
-
- /* Append pCfg pointer to end of mf
- */
- *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
-
- /* Initalize the timer
- */
- init_timer(&pCfg->timer);
- pCfg->timer.data = (unsigned long) ioc;
- pCfg->timer.function = mpt_timer_expired;
- pCfg->wait_done = 0;
-
- /* Set the timer; ensure 10 second minimum */
- if (pCfg->timeout < 10)
- pCfg->timer.expires = jiffies + HZ*10;
- else
- pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
-
- /* Add to end of Q, set timer and then issue this command */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ EventAck_t *pAck;
- add_timer(&pCfg->timer);
- mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
- wait_event(mpt_waitq, pCfg->wait_done);
+ if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+ printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
+ "request frame for Event=%x EventContext=%x EventData=%x!\n",
+ ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
+ le32_to_cpu(evnp->Data[0]));
+ return -1;
+ }
+ memset(pAck, 0, sizeof(*pAck));
- /* mf has been freed - do not access */
+ dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
- rc = pCfg->status;
+ pAck->Function = MPI_FUNCTION_EVENT_ACK;
+ pAck->ChainOffset = 0;
+ pAck->MsgFlags = 0;
+ pAck->Event = evnp->Event;
+ pAck->EventContext = evnp->EventContext;
- return rc;
+ mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
+
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mpt_toolbox - Generic function to issue toolbox message
+ * mpt_config - Generic function to issue config message
* @ioc - Pointer to an adapter structure
- * @cfg - Pointer to a toolbox structure. Struct contains
+ * @cfg - Pointer to a configuration structure. Struct contains
* action, page address, direction, physical address
* and pointer to a configuration page header
* Page header is updated.
* -EFAULT for non-successful reply or no reply (timeout)
*/
int
-mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
+mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
{
- ToolboxIstwiReadWriteRequest_t *pReq;
+ Config_t *pReq;
+ ConfigExtendedPageHeader_t *pExtHdr = NULL;
MPT_FRAME_HDR *mf;
unsigned long flags;
- int rc;
+ int ii, rc;
int flagsLength;
int in_isr;
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 1)! 20010905 -sralston
- * Prevent calling wait_event() (below), if caller happens
+ /* Prevent calling wait_event() (below), if caller happens
* to be in ISR context, because that is fatal!
*/
in_isr = in_interrupt();
if (in_isr) {
- dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
+ dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
ioc->name));
return -EPERM;
}
/* Get and Populate a free Frame
*/
- if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
- dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
+ if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+ dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
ioc->name));
return -EAGAIN;
}
- pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
- pReq->Tool = pCfg->action;
+ pReq = (Config_t *)mf;
+ pReq->Action = pCfg->action;
pReq->Reserved = 0;
pReq->ChainOffset = 0;
- pReq->Function = MPI_FUNCTION_TOOLBOX;
- pReq->Reserved1 = 0;
- pReq->Reserved2 = 0;
+ pReq->Function = MPI_FUNCTION_CONFIG;
+
+ /* Assume page type is not extended and clear "reserved" fields. */
+ pReq->ExtPageLength = 0;
+ pReq->ExtPageType = 0;
pReq->MsgFlags = 0;
- pReq->Flags = pCfg->dir;
- pReq->BusNum = 0;
- pReq->Reserved3 = 0;
- pReq->NumAddressBytes = 0x01;
- pReq->Reserved4 = 0;
- pReq->DataLength = 0x04;
- pReq->DeviceAddr = 0xB0;
- pReq->Addr1 = 0;
- pReq->Addr2 = 0;
- pReq->Addr3 = 0;
- pReq->Reserved5 = 0;
+
+ for (ii=0; ii < 8; ii++)
+ pReq->Reserved2[ii] = 0;
+
+ pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
+ pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
+ pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
+ pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
+ pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
+ pReq->ExtPageType = pExtHdr->ExtPageType;
+ pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+
+ /* Page Length must be treated as a reserved field for the extended header. */
+ pReq->Header.PageLength = 0;
+ }
+
+ pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
/* Add a SGE to the config request.
*/
+ if (pCfg->dir)
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+ else
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ flagsLength |= pExtHdr->ExtPageLength * 4;
- mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
+ }
+ else {
+ flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
+
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+ }
- dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
- ioc->name, pReq->Tool));
+ mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
/* Append pCfg pointer to end of mf
*/
/* Add to end of Q, set timer and then issue this command */
spin_lock_irqsave(&ioc->FreeQlock, flags);
- Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
+ list_add_tail(&pCfg->linkage, &ioc->configQ);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
add_timer(&pCfg->timer);
- mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
+ mpt_put_msg_frame(mpt_base_index, ioc, mf);
wait_event(mpt_waitq, pCfg->wait_done);
/* mf has been freed - do not access */
* the FIFO's are primed.
*/
spin_lock_irqsave(&ioc->FreeQlock, flags);
- if (! Q_IS_EMPTY(&ioc->configQ)){
- pCfg = (CONFIGPARMS *)ioc->configQ.head;
- do {
- del_timer(&pCfg->timer);
- pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
- } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
- }
+ list_for_each_entry(pCfg, &ioc->configQ, linkage)
+ del_timer(&pCfg->timer);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
} else {
* Flush the Q, and wake up all suspended threads.
*/
spin_lock_irqsave(&ioc->FreeQlock, flags);
- if (! Q_IS_EMPTY(&ioc->configQ)){
- pCfg = (CONFIGPARMS *)ioc->configQ.head;
- do {
- pNext = (CONFIGPARMS *) pCfg->linkage.forw;
-
- Q_DEL_ITEM(&pCfg->linkage);
-
- pCfg->status = MPT_CONFIG_ERROR;
- pCfg->wait_done = 1;
- wake_up(&mpt_waitq);
+ list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
+ list_del(&pCfg->linkage);
- pCfg = pNext;
- } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
+ pCfg->status = MPT_CONFIG_ERROR;
+ pCfg->wait_done = 1;
+ wake_up(&mpt_waitq);
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
}
static int
procmpt_create(void)
{
- MPT_ADAPTER *ioc;
struct proc_dir_entry *ent;
- int ii;
- /*
- * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
- * (single level) to multi level (e.g. "driver/message/fusion")
- * something here needs to change. -sralston
- */
mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
if (mpt_proc_root_dir == NULL)
return -ENOTDIR;
- for (ii=0; ii < MPT_PROC_ENTRIES; ii++) {
- ent = create_proc_entry(mpt_proc_list[ii].name,
- S_IFREG|S_IRUGO, mpt_proc_root_dir);
- if (!ent) {
- printk(KERN_WARNING MYNAM
- ": WARNING - Could not create /proc/mpt/%s entry\n",
- mpt_proc_list[ii].name);
- continue;
- }
- ent->read_proc = mpt_proc_list[ii].f;
- ent->data = NULL;
- }
+ ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
+ if (ent)
+ ent->read_proc = procmpt_summary_read;
- ioc = mpt_adapter_find_first();
- while (ioc != NULL) {
- struct proc_dir_entry *dent;
- /*
- * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
- */
- if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
- /*
- * And populate it with mpt_ioc_proc_list[] entries.
- */
- for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
- ent = create_proc_entry(mpt_ioc_proc_list[ii].name,
- S_IFREG|S_IRUGO, dent);
- if (!ent) {
- printk(KERN_WARNING MYNAM
- ": WARNING - Could not create /proc/mpt/%s/%s entry!\n",
- ioc->name,
- mpt_ioc_proc_list[ii].name);
- continue;
- }
- ent->read_proc = mpt_ioc_proc_list[ii].f;
- ent->data = ioc;
- }
- } else {
- printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n",
- ioc->name, mpt_ioc_proc_list[ii].name);
- }
- ioc = mpt_adapter_find_next(ioc);
- }
+ ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
+ if (ent)
+ ent->read_proc = procmpt_version_read;
return 0;
}
*
* Returns 0 for success, non-zero for failure.
*/
-static int
+static void
procmpt_destroy(void)
{
- MPT_ADAPTER *ioc;
- int ii;
-
- if (!mpt_proc_root_dir)
- return 0;
-
- /*
- * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
- * (single level) to multi level (e.g. "driver/message/fusion")
- * something here needs to change. -sralston
- */
-
- ioc = mpt_adapter_find_first();
- while (ioc != NULL) {
- char pname[32];
- int namelen;
-
- namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
-
- /*
- * Tear down each "/proc/mpt/iocN" subdirectory.
- */
- for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
- (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name);
- remove_proc_entry(pname, NULL);
- }
- remove_proc_entry(ioc->name, mpt_proc_root_dir);
- ioc = mpt_adapter_find_next(ioc);
- }
-
- for (ii=0; ii < MPT_PROC_ENTRIES; ii++)
- remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir);
-
- if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) {
- remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
- mpt_proc_root_dir = NULL;
- return 0;
- }
-
- return -1;
+ remove_proc_entry("version", mpt_proc_root_dir);
+ remove_proc_entry("summary", mpt_proc_root_dir);
+ remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
char *out = buf;
int len;
- if (data == NULL)
- ioc = mpt_adapter_find_first();
- else
- ioc = data;
-
- while (ioc) {
- int more = 0;
+ if (data) {
+ int more = 0;
+ ioc = data;
mpt_print_ioc_summary(ioc, out, &more, 0, 1);
out += more;
- if ((out-buf) >= request) {
- break;
- }
+ } else {
+ list_for_each_entry(ioc, &ioc_list, list) {
+ int more = 0;
- if (data == NULL)
- ioc = mpt_adapter_find_next(ioc);
- else
- ioc = NULL; /* force exit for iocN */
+ mpt_print_ioc_summary(ioc, out, &more, 0, 1);
+
+ out += more;
+ if ((out-buf) >= request)
+ break;
+ }
}
+
len = out - buf;
MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
{
int ii;
- int scsi, lan, ctl, targ, dmp;
+ int scsi, fc, sas, lan, ctl, targ, dmp;
char *drvname;
int len;
len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
len += sprintf(buf+len, " Fusion MPT base driver\n");
- scsi = lan = ctl = targ = dmp = 0;
+ scsi = fc = sas = lan = ctl = targ = dmp = 0;
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
drvname = NULL;
if (MptCallbacks[ii]) {
switch (MptDriverClass[ii]) {
- case MPTSCSIH_DRIVER:
- if (!scsi++) drvname = "SCSI host";
+ case MPTSPI_DRIVER:
+ if (!scsi++) drvname = "SPI host";
+ break;
+ case MPTFC_DRIVER:
+ if (!fc++) drvname = "FC host";
+ break;
+ case MPTSAS_DRIVER:
+ if (!sas++) drvname = "SAS host";
break;
case MPTLAN_DRIVER:
if (!lan++) drvname = "LAN";
case MPTCTL_DRIVER:
if (!ctl++) drvname = "ioctl";
break;
- case MPTDMP_DRIVER:
- if (!dmp++) drvname = "DMP";
- break;
}
if (drvname)
len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
- /*
- * Handle isense special case, because it
- * doesn't do a formal mpt_register call.
- */
- if (isense_idx == ii)
- len += sprintf(buf+len, " Fusion MPT isense driver\n");
}
}
len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
- (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
+ (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
/*
* Rounding UP to nearest 4-kB boundary here...
*/
4*ioc->facts.RequestFrameSize,
ioc->facts.GlobalCredits);
- len += sprintf(buf+len, " ReplyFrames @ 0x%p (Dma @ 0x%p)\n",
- (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
+ len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
+ (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
sz = (ioc->reply_sz * ioc->reply_depth) + 128;
len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
p+1,
ioc->facts.NumberOfPorts);
- if ((int)ioc->chip_type <= (int)FC929) {
+ if (ioc->bus_type == FC) {
if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *
-EventDescriptionStr(u8 event, u32 evData0)
+static void
+EventDescriptionStr(u8 event, u32 evData0, char *evStr)
{
char *ds;
ds = "Events(OFF) Change";
break;
case MPI_EVENT_INTEGRATED_RAID:
- ds = "Integrated Raid";
+ {
+ u8 ReasonCode = (u8)(evData0 >> 16);
+ switch (ReasonCode) {
+ case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+ ds = "Integrated Raid: Volume Created";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_DELETED :
+ ds = "Integrated Raid: Volume Deleted";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
+ ds = "Integrated Raid: Volume Settings Changed";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
+ ds = "Integrated Raid: Volume Status Changed";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
+ ds = "Integrated Raid: Volume Physdisk Changed";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
+ ds = "Integrated Raid: Physdisk Created";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
+ ds = "Integrated Raid: Physdisk Deleted";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
+ ds = "Integrated Raid: Physdisk Settings Changed";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
+ ds = "Integrated Raid: Physdisk Status Changed";
+ break;
+ case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
+ ds = "Integrated Raid: Domain Validation Needed";
+ break;
+ case MPI_EVENT_RAID_RC_SMART_DATA :
+ ds = "Integrated Raid; Smart Data";
+ break;
+ case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
+ ds = "Integrated Raid: Replace Action Started";
+ break;
+ default:
+ ds = "Integrated Raid";
+ break;
+ }
+ break;
+ }
+ case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
+ ds = "SCSI Device Status Change";
break;
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ {
+ u8 ReasonCode = (u8)(evData0 >> 16);
+ switch (ReasonCode) {
+ case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+ ds = "SAS Device Status Change: Added";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+ ds = "SAS Device Status Change: Deleted";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+ ds = "SAS Device Status Change: SMART Data";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+ ds = "SAS Device Status Change: No Persistancy Added";
+ break;
+ default:
+ ds = "SAS Device Status Change: Unknown";
+ break;
+ }
+ break;
+ }
+ case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
+ ds = "Bus Timer Expired";
+ break;
+ case MPI_EVENT_QUEUE_FULL:
+ ds = "Queue Full";
+ break;
+ case MPI_EVENT_SAS_SES:
+ ds = "SAS SES Event";
+ break;
+ case MPI_EVENT_PERSISTENT_TABLE_FULL:
+ ds = "Persistent Table Full";
+ break;
+ case MPI_EVENT_SAS_PHY_LINK_STATUS:
+ ds = "SAS PHY Link Status";
+ break;
+ case MPI_EVENT_SAS_DISCOVERY_ERROR:
+ ds = "SAS Discovery Error";
+ break;
+
/*
* MPT base "custom" events may be added here...
*/
ds = "Unknown";
break;
}
- return ds;
+ strcpy(evStr,ds);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int ii;
int r = 0;
int handlers = 0;
- char *evStr;
+ char evStr[100];
u8 event;
/*
evData0 = le32_to_cpu(pEventReply->Data[0]);
}
- evStr = EventDescriptionStr(event, evData0);
- dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+ EventDescriptionStr(event, evData0, evStr);
+ devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
ioc->name,
evStr,
event));
* Do general / base driver event processing
*/
switch(event) {
- case MPI_EVENT_NONE: /* 00 */
- case MPI_EVENT_LOG_DATA: /* 01 */
- case MPI_EVENT_STATE_CHANGE: /* 02 */
- case MPI_EVENT_UNIT_ATTENTION: /* 03 */
- case MPI_EVENT_IOC_BUS_RESET: /* 04 */
- case MPI_EVENT_EXT_BUS_RESET: /* 05 */
- case MPI_EVENT_RESCAN: /* 06 */
- case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
- case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
- case MPI_EVENT_LOGOUT: /* 09 */
- case MPI_EVENT_INTEGRATED_RAID: /* 0B */
- case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */
- default:
- break;
case MPI_EVENT_EVENT_CHANGE: /* 0A */
if (evDataLen) {
u8 evState = evData0 & 0xFF;
}
}
break;
+ case MPI_EVENT_INTEGRATED_RAID:
+ mptbase_raid_process_event_data(ioc,
+ (MpiEventDataRaid_t *)pEventReply->Data);
+ break;
+ default:
+ break;
}
/*
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
int idx;
- idx = ioc->eventContext % ioc->eventLogSize;
+ idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
ioc->events[idx].event = event;
ioc->events[idx].eventContext = ioc->eventContext;
*/
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
if (MptEvHandlers[ii]) {
- dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+ devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
ioc->name, ii));
r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
handlers++;
* If needed, send (a single) EventAck.
*/
if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+ devtprintk((MYIOC_s_WARN_FMT
+ "EventAck required\n",ioc->name));
if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
- printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
- ioc->name, ii);
+ devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+ ioc->name, ii));
}
}
"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
};
u8 subcl = (log_info >> 24) & 0x7;
-// u32 SubCl = log_info & 0x27000000;
- printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
+ printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
ioc->name, log_info, subcl_str[subcl]);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
+ * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
* @ioc: Pointer to MPT_ADAPTER structure
* @mr: Pointer to MPT reply frame
* @log_info: U32 LogInfo word from the IOC
* Refer to lsi/sp_log.h.
*/
static void
-mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
+mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
{
u32 info = log_info & 0x00FF0000;
char *desc = "unknown";
case 0x00080000:
desc = "Outbound DMA Overrun";
break;
+
+ case 0x00090000:
+ desc = "Task Management";
+ break;
+
+ case 0x000A0000:
+ desc = "Device Problem";
+ break;
+
+ case 0x000B0000:
+ desc = "Invalid Phase Change";
+ break;
+
+ case 0x000C0000:
+ desc = "Untagged Table Size";
+ break;
+
}
printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
}
+/* strings for sas loginfo */
+ static char *originator_str[] = {
+ "IOP", /* 00h */
+ "PL", /* 01h */
+ "IR" /* 02h */
+ };
+ static char *iop_code_str[] = {
+ NULL, /* 00h */
+ "Invalid SAS Address", /* 01h */
+ NULL, /* 02h */
+ "Invalid Page", /* 03h */
+ NULL, /* 04h */
+ "Task Terminated" /* 05h */
+ };
+ static char *pl_code_str[] = {
+ NULL, /* 00h */
+ "Open Failure", /* 01h */
+ "Invalid Scatter Gather List", /* 02h */
+ "Wrong Relative Offset or Frame Length", /* 03h */
+ "Frame Transfer Error", /* 04h */
+ "Transmit Frame Connected Low", /* 05h */
+ "SATA Non-NCQ RW Error Bit Set", /* 06h */
+ "SATA Read Log Receive Data Error", /* 07h */
+ "SATA NCQ Fail All Commands After Error", /* 08h */
+ "SATA Error in Receive Set Device Bit FIS", /* 09h */
+ "Receive Frame Invalid Message", /* 0Ah */
+ "Receive Context Message Valid Error", /* 0Bh */
+ "Receive Frame Current Frame Error", /* 0Ch */
+ "SATA Link Down", /* 0Dh */
+ "Discovery SATA Init W IOS", /* 0Eh */
+ "Config Invalid Page", /* 0Fh */
+ "Discovery SATA Init Timeout", /* 10h */
+ "Reset", /* 11h */
+ "Abort", /* 12h */
+ "IO Not Yet Executed", /* 13h */
+ "IO Executed", /* 14h */
+ NULL, /* 15h */
+ NULL, /* 16h */
+ NULL, /* 17h */
+ NULL, /* 18h */
+ NULL, /* 19h */
+ NULL, /* 1Ah */
+ NULL, /* 1Bh */
+ NULL, /* 1Ch */
+ NULL, /* 1Dh */
+ NULL, /* 1Eh */
+ NULL, /* 1Fh */
+ "Enclosure Management" /* 20h */
+ };
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
- * OpCode strings from the (optional) isense module.
- * @ascqTable: Pointer to ASCQ_Table_t structure
- * @ascqtbl_sz: Number of entries in ASCQ_Table
- * @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
+/*
+ * mpt_sas_log_info - Log information returned from SAS IOC.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @log_info: U32 LogInfo reply word from the IOC
*
- * Specialized driver registration routine for the isense driver.
+ * Refer to lsi/mpi_log_sas.h.
*/
-int
-mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
+static void
+mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
{
- int r = 0;
+union loginfo_type {
+ u32 loginfo;
+ struct {
+ u32 subcode:16;
+ u32 code:8;
+ u32 originator:4;
+ u32 bus_type:4;
+ }dw;
+};
+ union loginfo_type sas_loginfo;
+ char *code_desc = NULL;
- if (ascqTable && ascqtbl_sz && opsTable) {
- mpt_v_ASCQ_TablePtr = ascqTable;
- mpt_ASCQ_TableSz = ascqtbl_sz;
- mpt_ScsiOpcodesPtr = opsTable;
- printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
- isense_idx = last_drv_idx;
- r = 1;
+ sas_loginfo.loginfo = log_info;
+ if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
+ (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
+ return;
+ if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
+ (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
+ code_desc = iop_code_str[sas_loginfo.dw.code];
+ }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
+ (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
+ code_desc = pl_code_str[sas_loginfo.dw.code];
}
- return r;
+
+ if (code_desc != NULL)
+ printk(MYIOC_s_INFO_FMT
+ "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+ " SubCode(0x%04x)\n",
+ ioc->name,
+ log_info,
+ originator_str[sas_loginfo.dw.originator],
+ code_desc,
+ sas_loginfo.dw.subcode);
+ else
+ printk(MYIOC_s_INFO_FMT
+ "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+ " SubCode(0x%04x)\n",
+ ioc->name,
+ log_info,
+ originator_str[sas_loginfo.dw.originator],
+ sas_loginfo.dw.code,
+ sas_loginfo.dw.subcode);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
- * OpCode strings from the isense driver.
+/*
+ * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @ioc_status: U32 IOCStatus word from IOC
+ * @mf: Pointer to MPT request frame
*
- * Specialized driver deregistration routine for the isense driver.
+ * Refer to lsi/mpi.h.
*/
-void
-mpt_deregister_ascqops_strings(void)
+static void
+mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
{
- mpt_v_ASCQ_TablePtr = NULL;
- mpt_ASCQ_TableSz = 0;
- mpt_ScsiOpcodesPtr = NULL;
- printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
- isense_idx = -1;
+ u32 status = ioc_status & MPI_IOCSTATUS_MASK;
+ char *desc = "";
+
+ switch (status) {
+ case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
+ desc = "Invalid Function";
+ break;
+
+ case MPI_IOCSTATUS_BUSY: /* 0x0002 */
+ desc = "Busy";
+ break;
+
+ case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
+ desc = "Invalid SGL";
+ break;
+
+ case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
+ desc = "Internal Error";
+ break;
+
+ case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
+ desc = "Reserved";
+ break;
+
+ case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
+ desc = "Insufficient Resources";
+ break;
+
+ case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
+ desc = "Invalid Field";
+ break;
+
+ case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
+ desc = "Invalid State";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
+ case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
+ case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
+ case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
+ case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
+ case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
+ /* No message for Config IOCStatus values */
+ break;
+
+ case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
+ /* No message for recovered error
+ desc = "SCSI Recovered Error";
+ */
+ break;
+
+ case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+ desc = "SCSI Invalid Bus";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+ desc = "SCSI Invalid TargetID";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+ {
+ SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
+ U8 cdb = pScsiReq->CDB[0];
+ if (cdb != 0x12) { /* Inquiry is issued for device scanning */
+ desc = "SCSI Device Not There";
+ }
+ break;
+ }
+
+ case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+ desc = "SCSI Data Overrun";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
+ /* This error is checked in scsi_io_done(). Skip.
+ desc = "SCSI Data Underrun";
+ */
+ break;
+
+ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+ desc = "SCSI I/O Data Error";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+ desc = "SCSI Protocol Error";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+ desc = "SCSI Task Terminated";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+ desc = "SCSI Residual Mismatch";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+ desc = "SCSI Task Management Failed";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+ desc = "SCSI IOC Terminated";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
+ desc = "SCSI Ext Terminated";
+ break;
+
+ default:
+ desc = "Others";
+ break;
+ }
+ if (desc != "")
+ printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-EXPORT_SYMBOL(mpt_adapters);
+EXPORT_SYMBOL(mpt_attach);
+EXPORT_SYMBOL(mpt_detach);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mpt_resume);
+EXPORT_SYMBOL(mpt_suspend);
+#endif
+EXPORT_SYMBOL(ioc_list);
EXPORT_SYMBOL(mpt_proc_root_dir);
-EXPORT_SYMBOL(DmpService);
EXPORT_SYMBOL(mpt_register);
EXPORT_SYMBOL(mpt_deregister);
EXPORT_SYMBOL(mpt_event_register);
EXPORT_SYMBOL(mpt_put_msg_frame);
EXPORT_SYMBOL(mpt_free_msg_frame);
EXPORT_SYMBOL(mpt_add_sge);
-EXPORT_SYMBOL(mpt_add_chain);
EXPORT_SYMBOL(mpt_send_handshake_request);
-EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
-EXPORT_SYMBOL(mpt_adapter_find_first);
-EXPORT_SYMBOL(mpt_adapter_find_next);
EXPORT_SYMBOL(mpt_verify_adapter);
EXPORT_SYMBOL(mpt_GetIocState);
EXPORT_SYMBOL(mpt_print_ioc_summary);
EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config);
-EXPORT_SYMBOL(mpt_toolbox);
EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
+EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
-EXPORT_SYMBOL(mpt_register_ascqops_strings);
-EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
-EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
-EXPORT_SYMBOL(mpt_ASCQ_TableSz);
-EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
-
-
-static struct pci_driver mptbase_driver = {
- .name = "mptbase",
- .id_table = mptbase_pci_table,
- .probe = mptbase_probe,
- .remove = __devexit_p(mptbase_remove),
- .driver = {
- .shutdown = mptbase_shutdown,
- },
-#ifdef CONFIG_PM
- .suspend = mptbase_suspend,
- .resume = mptbase_resume,
-#endif
-};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
fusion_init(void)
{
int i;
- int r;
-
- if (FusionInitCalled++) {
- dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
- return 0;
- }
show_mptmod_ver(my_NAME, my_VERSION);
printk(KERN_INFO COPYRIGHT "\n");
- Q_INIT(&MptAdapters, MPT_ADAPTER); /* set to empty */
for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
MptCallbacks[i] = NULL;
MptDriverClass[i] = MPTUNKNOWN_DRIVER;
MptResetHandlers[i] = NULL;
}
- DmpService = NULL;
-
- /* NEW! 20010120 -sralston
- * Register ourselves (mptbase) in order to facilitate
+ /* Register ourselves (mptbase) in order to facilitate
* EventNotification handling.
*/
mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
/* FIXME! */
}
- r = pci_module_init(&mptbase_driver);
- if(r)
- return(r);
-
#ifdef CONFIG_PROC_FS
(void) procmpt_create();
#endif
-
- return r;
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
fusion_exit(void)
{
- dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+ dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+
+ mpt_reset_deregister(mpt_base_index);
- /* Whups? 20010120 -sralston
- * Moved this *above* removal of all MptAdapters!
- */
#ifdef CONFIG_PROC_FS
- (void) procmpt_destroy();
+ procmpt_destroy();
#endif
- pci_unregister_driver(&mptbase_driver);
- mpt_reset_deregister(mpt_base_index);
}
-
module_init(fusion_init);
module_exit(fusion_exit);