X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmessage%2Ffusion%2Fmptbase.c;h=6a035959ca5d43fdcf0ed68f7cb8cefcbc1c11d8;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=70a44c9d2f7414ccdc742e105ca9da0256352bae;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 70a44c9d2..6a035959c 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1,55 +1,13 @@ /* * 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 $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -88,8 +46,6 @@ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include -#include #include #include #include @@ -101,13 +57,11 @@ #include #include #include /* needed for in_interrupt() proto */ +#include #include #ifdef CONFIG_MTRR #include #endif -#ifdef __sparc__ -#include /* needed for __irq_itoa() proto */ -#endif #include "mptbase.h" @@ -119,10 +73,15 @@ MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); +MODULE_VERSION(MPT_LINUX_VERSION_COMMON); /* * 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 @@ -137,8 +96,6 @@ int mpt_stm_index = -1; struct proc_dir_entry *mpt_proc_root_dir; -DmpServices_t *DmpService; - #define WHOINIT_UNKNOWN 0xAA /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -157,7 +114,6 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; 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; @@ -169,7 +125,9 @@ 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 *ioc, struct pci_dev *pdev); static void mpt_adapter_disable(MPT_ADAPTER *ioc); @@ -177,13 +135,12 @@ 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); @@ -192,8 +149,8 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, 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); @@ -201,6 +158,8 @@ static void mpt_read_ioc_pg_4(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_summary_read(char *buf, char **start, off_t offset, @@ -216,44 +175,178 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); 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); +static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); /* 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); -/**************************************************************************** - * Supported hardware - */ - -static struct pci_device_id mptbase_pci_table[] = { - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, - PCI_ANY_ID, PCI_ANY_ID }, - { 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); - #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); +} + +/* + * Process turbo (context) reply... + */ +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(); + } + + /* 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; + } + + if (MptCallbacks[cb_idx](ioc, mf, mr)) + mpt_free_msg_frame(ioc, mf); + out: + mb(); +} + +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; + + 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(); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. @@ -266,8 +359,7 @@ MODULE_DEVICE_TABLE(pci, mptbase_pci_table); * (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 @@ -276,176 +368,22 @@ MODULE_DEVICE_TABLE(pci, mptbase_pci_table); 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; + MPT_ADAPTER *ioc = bus_id; + u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); - ioc = (MPT_ADAPTER *)bus_id; + if (pa == 0xFFFFFFFF) + return IRQ_NONE; /* * 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_dmasync(&ioc->chip->ReplyFifo)) == 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); - - dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n", - ioc->name, mr, req_idx)); - 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); - } - if (ioc_stat & MPI_IOCSTATUS_MASK) { - if ((int)ioc->chip_type <= (int)FC929) - ; - else - mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); - } - } else { - /* - * Process turbo (context) reply... - */ - dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%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 */ + do { + if (pa & MPI_ADDRESS_REPLY_A_BIT) + mpt_reply(ioc, pa); + else + mpt_turbo_reply(ioc, pa); + pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); + } while (pa != 0xFFFFFFFF); return IRQ_HANDLED; } @@ -459,7 +397,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) * @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 @@ -468,28 +406,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) 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) { @@ -500,7 +427,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) results = ProcessEventNotification(ioc, pEvReply, &evHandlers); if (results != evHandlers) { /* CHECKME! Any special handling needed here? */ - devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", ioc->name, evHandlers, results)); } @@ -508,8 +435,12 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) * 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; + } else { + devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", + ioc->name, pEvReply)); + } #ifdef CONFIG_PROC_FS // LogEvent(ioc, pEvReply); @@ -518,8 +449,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) } 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; @@ -533,7 +463,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) 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); /* @@ -551,10 +481,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) 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; } } @@ -564,6 +505,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) 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); @@ -603,22 +552,6 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) 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!) @@ -744,26 +677,22 @@ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) { MPT_ADAPTER *ioc; - int error=0; + const struct pci_device_id *id; - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) { - error= -EINVAL; - return error; - } + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + return -EINVAL; MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; /* call per pci device probe entry point */ list_for_each_entry(ioc, &ioc_list, list) { - if(dd_cbfunc->probe) { - error = dd_cbfunc->probe(ioc->pcidev, - ioc->pcidev->driver->id_table); - if(error != 0) - return error; - } + id = ioc->pcidev->driver ? + ioc->pcidev->driver->id_table : NULL; + if (dd_cbfunc->probe) + dd_cbfunc->probe(ioc->pcidev, id); } - return error; + return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -785,7 +714,7 @@ mpt_device_driver_deregister(int cb_idx) if (dd_cbfunc->remove) dd_cbfunc->remove(ioc->pcidev); } - + MptDeviceDriverHandlers[cb_idx] = NULL; } @@ -819,16 +748,18 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) return NULL; spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&ioc->FreeQ)) { + if (!list_empty(&ioc->FreeQ)) { int req_offset; - mf = ioc->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 *)ioc->req_frames; /* u16! */ - req_idx = cpu_to_le16(req_offset / ioc->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; + 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 @@ -874,8 +805,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ - req_idx = cpu_to_le16(req_offset / ioc->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; + 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 @@ -897,7 +828,7 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) } #endif - mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; + 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); } @@ -919,7 +850,8 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); + 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 ioc->mfcnt--; #endif @@ -955,41 +887,6 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) } } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * 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 @@ -1034,7 +931,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - + CHIPREG_WRITE32(&ioc->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<name, ii)); + ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { return -2; } - + /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (ii = 0; ii < reqBytes/4; ii++) { @@ -1080,10 +977,120 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - + return r; } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * 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 + * + * 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. + */ + +static int +mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) +{ + int r = 0; + + /* 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 + <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, + (u32)ioc->HostPageBuffer_dma, + host_page_buffer_sz)); + ioc->alloc_total += host_page_buffer_sz; + ioc->HostPageBuffer_sz = host_page_buffer_sz; + break; + } + + host_page_buffer_sz -= (4*1024); + } + } + + 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; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_verify_adapter - Given a unique IOC identifier, set pointer to @@ -1102,16 +1109,16 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) if (ioc->id == iocid) { *iocpp =ioc; return iocid; - } + } } - + *iocpp = NULL; return -1; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * 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 @@ -1126,18 +1133,17 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) * * 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; @@ -1147,37 +1153,37 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (pci_enable_device(pdev)) return r; - + dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n")); - - if (!pci_set_dma_mask(pdev, mask)) { + + 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->initializing_hba_lock); /* Initialize the event logging. */ @@ -1194,45 +1200,43 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* 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. */ 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 (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { + if (psize) + continue; /* Get I/O space! */ port = pci_resource_start(pdev, ii); psize = pci_resource_len(pdev,ii); } else { + if (msize) + continue; /* Get memmap */ mem_phys = pci_resource_start(pdev, ii); msize = pci_resource_len(pdev,ii); - break; } } ioc->mem_size = msize; - if (ii == DEVICE_COUNT_RESOURCE) { - printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n"); - kfree(ioc); - return -EINVAL; - } - - 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 */ /*mem = ioremap(mem_phys, msize);*/ - mem = ioremap(mem_phys, 0x100); + mem = ioremap(mem_phys, msize); if (mem == NULL) { printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n"); kfree(ioc); @@ -1245,31 +1249,30 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) &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 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_FC909) { - ioc->chip_type = FC909; ioc->prod_name = "LSIFC909"; + ioc->bus_type = FC; } - if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { - ioc->chip_type = FC929; + 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 @@ -1288,8 +1291,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } 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. */ @@ -1297,9 +1300,23 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) 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). */ @@ -1311,10 +1328,35 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } 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_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_SAS1068E) { + ioc->prod_name = "LSISAS1068E"; + ioc->bus_type = SAS; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { + ioc->prod_name = "LSISAS1078"; + ioc->bus_type = SAS; } + if (ioc->errata_flag_1064) + pci_disable_io_access(pdev); + sprintf(ioc->name, "ioc%d", ioc->id); spin_lock_init(&ioc->FreeQlock); @@ -1327,51 +1369,19 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Set lookup ptr. */ list_add_tail(&ioc->list, &ioc_list); - ioc->pci_irq = -1; - if (pdev->irq) { - r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); - - if (r < 0) { -#ifndef __sparc__ - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", - ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif - list_del(&ioc->list); - iounmap(mem); - kfree(ioc); - return -EBUSY; - } - - ioc->pci_irq = pdev->irq; - - pci_set_master(pdev); /* ?? */ - pci_set_drvdata(pdev, ioc); - -#ifndef __sparc__ - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#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_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, + CAN_SLEEP)) != 0){ printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); list_del(&ioc->list); - free_irq(ioc->pci_irq, ioc); + if (ioc->alt_ioc) + ioc->alt_ioc->alt_ioc = NULL; iounmap(mem); kfree(ioc); pci_set_drvdata(pdev, NULL); @@ -1410,13 +1420,13 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * 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]; @@ -1428,7 +1438,7 @@ mptbase_remove(struct pci_dev *pdev) 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; iiremove(pdev); } } - + /* Disable interrupts! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); @@ -1453,71 +1463,29 @@ mptbase_remove(struct pci_dev *pdev) 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; iishutdown) { - 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; iisuspend) { - 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)) { @@ -1540,38 +1508,29 @@ mptbase_suspend(struct pci_dev *pdev, u32 state) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * 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; int recovery_state; - int ii; printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", 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 */ - if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { - /* enable domain validation flags */ - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; - } - } - printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", ioc->name, @@ -1589,18 +1548,25 @@ mptbase_resume(struct pci_dev *pdev) "pci-resume: success\n", ioc->name); } - /* call per device driver resume entry point */ - for(ii=0; iiresume) { - MptDeviceDriverHandlers[ii]->resume(pdev); - } - } - return 0; } #endif +static int +mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase) +{ + if ((MptDriverClass[index] == MPTSPI_DRIVER && + ioc->bus_type != SPI) || + (MptDriverClass[index] == MPTFC_DRIVER && + ioc->bus_type != FC) || + (MptDriverClass[index] == MPTSAS_DRIVER && + ioc->bus_type != SAS)) + /* make sure we only call the relevant reset handler + * for the bus */ + return 0; + return (MptResetHandlers[index])(ioc, reset_phase); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_do_ioc_recovery - Initialize or recover MPT adapter. @@ -1632,6 +1598,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int handlers; int ret = 0; int reset_alt_ioc_active = 0; + int irq_allocated = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); @@ -1662,7 +1629,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* (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; } @@ -1690,7 +1657,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) break; } - + if (ii == 5) { dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); @@ -1698,7 +1665,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } - + if (alt_ioc_ready) { if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); @@ -1715,6 +1682,36 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } } + /* + * Device is reset now. It must have de-asserted the interrupt line + * (if it was asserted) and it should be safe to register for the + * interrupt now. + */ + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + ioc->pci_irq = -1; + if (ioc->pcidev->irq) { + if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev)) + printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", + ioc->name); + rc = request_irq(ioc->pcidev->irq, mpt_interrupt, + IRQF_SHARED, ioc->name, ioc); + if (rc < 0) { + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %d!\n", ioc->name, + ioc->pcidev->irq); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + return -EBUSY; + } + irq_allocated = 1; + ioc->pci_irq = ioc->pcidev->irq; + pci_set_master(ioc->pcidev); /* ?? */ + pci_set_drvdata(ioc->pcidev, ioc); + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); + } + } + /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. @@ -1755,28 +1752,42 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) */ if (ret == 0) { rc = mpt_do_upload(ioc, sleepFlag); - if (rc != 0) + 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) + */ + 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)); + ioc->alt_ioc->cached_fw = NULL; + } + } 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)) @@ -1785,24 +1796,29 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) 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) { - /* - * Pre-fetch FC port WWN and stuff... - * (FCPortPage0_t stuff) - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) GetFcPortPage0(ioc, ii); + 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) + goto out; } + /* Find IM volumes + */ + mpt_findImVolumes(ioc); + + } else if (ioc->bus_type == FC) { if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* @@ -1829,7 +1845,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* 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 @@ -1854,20 +1870,26 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((ret == 0) && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); - rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); + rc += mpt_signal_reset(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)); - rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); + rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } /* FIXME? Examine results here? */ } + out: + if ((ret != 0) && irq_allocated) { + free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + } return ret; } @@ -1885,37 +1907,43 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) { - unsigned int 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; - 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)); + 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; + } 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; } } + pci_dev_put(peer); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1931,7 +1959,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); - if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) { + if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", ret); } @@ -1978,15 +2006,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) ioc->alloc_total -= sz; } - if (ioc->spi_data.nvram != NULL) { - kfree(ioc->spi_data.nvram); - ioc->spi_data.nvram = NULL; - } - - if (ioc->spi_data.pIocPg3 != NULL) { - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; - } + kfree(ioc->spi_data.nvram); + kfree(ioc->raid_data.pIocPg3); + ioc->spi_data.nvram = NULL; + ioc->raid_data.pIocPg3 = NULL; if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; @@ -2003,9 +2026,24 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) ioc->ReqToChain = NULL; } - if (ioc->ChainToChain != NULL) { - kfree(ioc->ChainToChain); - ioc->ChainToChain = NULL; + kfree(ioc->ChainToChain); + ioc->ChainToChain = NULL; + + 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; } } @@ -2021,36 +2059,45 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) static void mpt_adapter_dispose(MPT_ADAPTER *ioc) { - if (ioc != NULL) { - int sz_first, sz_last; + int sz_first, sz_last; + + if (ioc == NULL) + return; - sz_first = ioc->alloc_total; + sz_first = ioc->alloc_total; - mpt_adapter_disable(ioc); + mpt_adapter_disable(ioc); - if (ioc->pci_irq != -1) { - free_irq(ioc->pci_irq, ioc); - ioc->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 (ioc->memmap != NULL) - iounmap((u8 *) ioc->memmap); + if (ioc->memmap != NULL) { + iounmap(ioc->memmap); + ioc->memmap = NULL; + } #if defined(CONFIG_MTRR) && 0 - if (ioc->mtrr_reg > 0) { - mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->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! */ - list_del(&ioc->list); + /* Zap the adapter lookup ptr! */ + list_del(&ioc->list); - 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)); - kfree(ioc); - } + 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); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2137,20 +2184,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } /* 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 { - return 0; - /* 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. @@ -2167,7 +2202,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Hmmm... Did it get left operational? */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { - dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", + dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. @@ -2176,8 +2211,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * 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; @@ -2198,7 +2233,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * 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) { @@ -2229,8 +2264,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 * HZ / 1000); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -2313,8 +2347,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT - "Sending get IocFacts request req_sz=%d reply_sz=%d\n", + 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 @@ -2347,7 +2381,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) 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); @@ -2377,6 +2411,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) 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 @@ -2394,7 +2429,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) 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", @@ -2402,7 +2437,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return -55; } - r = sz = le32_to_cpu(facts->BlockSize); + r = sz = facts->BlockSize; vv = ((63 / (sz * 4)) + 1) & 0x03; ioc->NB_for_64_byte_frame = vv; while ( sz ) @@ -2413,7 +2448,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) 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, @@ -2434,7 +2469,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return r; } } else { - printk(MYIOC_s_ERR_FMT + printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n", ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32))); @@ -2548,13 +2583,25 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) 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; - + 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 */ if (sizeof(dma_addr_t) == sizeof(u64)) { @@ -2568,17 +2615,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) 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; 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. @@ -2586,9 +2637,11 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n", ioc->name, &ioc_init)); - - if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) + + 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 @@ -2599,8 +2652,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 * HZ / 1000); + msleep(1); } else { mdelay(1); } @@ -2614,9 +2666,10 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) 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)); + ioc->aen_event_read_flag=0; return r; } @@ -2636,7 +2689,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) { PortEnable_t port_enable; MPIDefaultReply_t reply_buf; - int ii; + int rc; int req_sz; int reply_sz; @@ -2658,22 +2711,18 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* 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; } /* @@ -2688,6 +2737,8 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) 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; + ioc->alloc_total += size; + ioc->alt_ioc->alloc_total -= size; } else { if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) ) ioc->alloc_total += size; @@ -2703,7 +2754,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; - dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + 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); @@ -2747,9 +2798,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_alloc_fw_memory(ioc, sz); - dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", + 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. */ @@ -2779,14 +2830,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n", + 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_WARNING MYNAM "FW Upload completed rc=%x \n", ii)); + dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); cmdStatus = -EFAULT; if (ii == 0) { @@ -2801,10 +2852,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) cmdStatus = 0; } } - dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", + dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n", ioc->name, cmdStatus)); - + if (cmdStatus) { ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n", @@ -2830,9 +2881,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) * <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 *pFwHeader; MpiExtImageHeader_t *pExtImage; u32 fwSize; u32 diag0val; @@ -2843,19 +2893,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) u32 load_addr; u32 ioc_state=0; - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", - ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); - - if ( ioc->facts.FWImageSize == 0 ) - return -1; - - if (ioc->cached_fw == NULL) - return -2; + ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", + ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); - /* prevent a second downloadboot and memory free with alt_ioc */ - if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) - ioc->alt_ioc->cached_fw = NULL; - 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); @@ -2867,8 +2907,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 * HZ / 1000); + msleep(1); } else { mdelay (1); } @@ -2883,17 +2922,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) ioc->name, count)); break; } - /* wait 1 sec */ + /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1000 * HZ / 1000); + msleep (100); } else { - mdelay (1000); + mdelay (100); } } if ( count == 30 ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! " + "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", ioc->name, diag0val)); return -3; } @@ -2908,13 +2947,15 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Set the DiagRwEn and Disable ARM bits */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); - pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; fwSize = (pFwHeader->ImageSize + 3)/4; ptrFw = (u32 *) pFwHeader; /* Write the LoadStartAddress to the DiagRw Address Register * using Programmed IO */ + 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, pFwHeader->LoadStartAddress)); @@ -2934,8 +2975,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) fwSize = (pExtImage->ImageSize + 3) >> 2; ptrFw = (u32 *)pExtImage; - ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n", - ioc->name, fwSize*4, ptrFw, load_addr)); + 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 (fwSize--) { @@ -2955,16 +2996,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* 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 (1); + } else { + mdelay (1); + } + } + + if (ioc->errata_flag_1064) + pci_disable_io_access(ioc->pcidev); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", + 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); + 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); @@ -2972,10 +3035,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Write 0xFF to reset the sequencer */ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + 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; countname, 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)); @@ -2986,8 +3062,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) return 0; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10 * HZ / 1000); + msleep (10); } else { mdelay (10); } @@ -3016,9 +3091,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) * 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 @@ -3031,15 +3106,14 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) int cnt,cntdn; dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if ((int)ioc->chip_type > (int)FC929) { + 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(1000 * HZ / 1000); + msleep (1000); } else { mdelay (1000); } @@ -3061,8 +3135,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) return hard_reset_done; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10 * HZ / 1000); + msleep (10); } else { mdelay (10); } @@ -3095,6 +3168,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) { + MPT_ADAPTER *iocp=NULL; u32 diag0val; u32 doorbell; int hard_reset_done = 0; @@ -3103,6 +3177,37 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) u32 diag1val = 0; #endif + if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { + drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " + "address=%p\n", ioc->name, __FUNCTION__, + &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); + CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07); + if (sleepFlag == CAN_SLEEP) + msleep(1); + else + mdelay(1); + + for (count = 0; count < 60; count ++) { + doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); + doorbell &= MPI_IOC_STATE_MASK; + + drsprintk((MYIOC_s_INFO_FMT + "looking for READY STATE: doorbell=%x" + " count=%d\n", + ioc->name, doorbell, count)); + if (doorbell == MPI_IOC_STATE_READY) { + return 0; + } + + /* wait 1 sec */ + if (sleepFlag == CAN_SLEEP) + msleep(1000); + else + mdelay(1000); + } + return -1; + } + /* Clear any existing interrupts */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -3133,8 +3238,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); + msleep (100); } else { mdelay (100); } @@ -3164,7 +3268,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) * */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM); - mdelay (1); + mdelay(1); /* * Now hit the reset bit in the Diagnostic register @@ -3189,37 +3293,43 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) if (MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET); + r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET); if (ioc->alt_ioc) { dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET); } } } /* FIXME? Examine results here? */ } - if (ioc->cached_fw) { + if (ioc->cached_fw) + iocp = ioc; + else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) + iocp = ioc->alt_ioc; + if (iocp) { /* 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); + diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic); if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { break; } + dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n", + iocp->name, diag0val, count)); /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1000 * HZ / 1000); + msleep (1000); } else { mdelay (1000); } } - if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) { + if ((count = mpt_downloadboot(ioc, + (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", count); } @@ -3241,8 +3351,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1000 * HZ / 1000); + msleep (1000); } else { mdelay (1000); } @@ -3276,8 +3385,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); + msleep (100); } else { mdelay (100); } @@ -3347,7 +3455,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) u32 state; int cntdn, count; - drsprintk((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<name, numSGE, num_sge, num_chain)); - if ((int) ioc->chip_type > (int) FC929) + if (ioc->bus_type == SPI) num_chain *= MPT_SCSI_CAN_QUEUE; else num_chain *= MPT_FC_CAN_QUEUE; @@ -3552,6 +3659,9 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->reply_frames = (MPT_FRAME_HDR *) mem; ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); + dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n", + ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); + alloc_dma += reply_sz; mem += reply_sz; @@ -3560,7 +3670,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->req_frames = (MPT_FRAME_HDR *) mem; ioc->req_frames_dma = alloc_dma; - dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n", + 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); @@ -3586,20 +3696,20 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->ChainBuffer = mem; ioc->ChainBufferDMA = alloc_dma; - dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n", + dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n", ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); /* Initialize the free chain Q. */ - Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR); + INIT_LIST_HEAD(&ioc->FreeChainQ); /* Post the chain buffers to the FreeChainQ. */ mem = (u8 *)ioc->ChainBuffer; for (i=0; i < num_chain; i++) { mf = (MPT_FRAME_HDR *) mem; - Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ); mem += ioc->req_sz; } @@ -3609,12 +3719,13 @@ PrimeIocFifos(MPT_ADAPTER *ioc) mem = (u8 *) ioc->req_frames; spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); + INIT_LIST_HEAD(&ioc->FreeQ); for (i = 0; i < ioc->req_depth; i++) { mf = (MPT_FRAME_HDR *) mem; /* Queue REQUESTs *internally*! */ - Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); + mem += ioc->req_sz; } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -3688,9 +3799,9 @@ out_fail: * * 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; @@ -3765,7 +3876,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, */ 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!" : "")); @@ -3801,23 +3912,22 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; u32 intstat=0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; + cntdn = 1000 * howlong; if (sleepFlag == CAN_SLEEP) { while (--cntdn) { + msleep (1); intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 * HZ / 1000); count++; } } else { while (--cntdn) { + mdelay (1); intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - mdelay (1); count++; } } @@ -3852,14 +3962,13 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; 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 * HZ / 1000); + msleep(1); count++; } } else { @@ -3926,7 +4035,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", - ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), + ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); /* @@ -3998,7 +4107,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) 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; @@ -4042,7 +4151,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) 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; @@ -4082,87 +4191,213 @@ GetLanConfigPages(MPT_ADAPTER *ioc) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * GetFcPortPage0 - Fetch FCPort config Page0. + * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: IOC Port number + * @sas_address: 64bit SAS Address for operation. + * @target_id: specified target for operation + * @bus: specified bus for operation + * @persist_opcode: see below * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) + * 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 */ -static int -GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +int +mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) { - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - FCPortPage0_t *ppage0_alloc; - FCPortPage0_t *pp0dest; - dma_addr_t page0_dma; - int data_sz; - int copy_sz; - int rc; + 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; - /* 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.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = portnum; - cfg.timeout = 0; + 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; - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n", + ioc->name); + break; - if (hdr.PageLength == 0) - return 0; + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n", + ioc->name); + break; - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - if (ppage0_alloc) { - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: + printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n", + ioc->name); + break; - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - pp0dest = &ioc->fc_port_page0[portnum]; - copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); - memcpy(pp0dest, ppage0_alloc, copy_sz); + 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; - /* - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - pp0dest->Flags = le32_to_cpu(pp0dest->Flags); - pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); - pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); - pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); - pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); - pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); - pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); - pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); - pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); - pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); - pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); - pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); - pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); - pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); - pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); - pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + 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; - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); + case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: + printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n", + ioc->name, disk); + break; } - - return rc; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -4191,7 +4426,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc) 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; @@ -4281,7 +4516,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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; @@ -4301,6 +4536,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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 */ @@ -4310,7 +4547,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; - dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", + 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; @@ -4319,6 +4556,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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; @@ -4331,8 +4570,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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) { @@ -4347,7 +4589,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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; @@ -4370,6 +4612,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 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) */ @@ -4415,7 +4665,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) 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; @@ -4424,8 +4674,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) 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; @@ -4434,8 +4684,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) 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)); @@ -4477,7 +4727,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) 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; @@ -4499,10 +4749,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) 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; } @@ -4519,7 +4769,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* 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; @@ -4528,7 +4778,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* find the match */ if (vbus == 0) { - ioc->spi_data.isRaid |= (1 << vid); + ioc->raid_data.isRaid |= (1 << vid); } else { /* Error! Always bus 0 */ @@ -4551,7 +4801,7 @@ done_and_free: return rc; } -int +static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) { IOCPage3_t *pIoc3; @@ -4563,10 +4813,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) /* 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 @@ -4575,7 +4823,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) 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; @@ -4603,7 +4851,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) 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; } } @@ -4627,7 +4875,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) 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; @@ -4644,6 +4892,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma); if (!pIoc4) return; + ioc->alloc_total += iocpage4sz; } else { ioc4_dma = ioc->spi_data.IocPg4_dma; iocpage4sz = ioc->spi_data.IocPg4Sz; @@ -4660,6 +4909,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) } else { pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma); ioc->spi_data.pIocPg4 = NULL; + ioc->alloc_total -= iocpage4sz; } } @@ -4679,7 +4929,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) 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; @@ -4761,13 +5011,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) 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", + devtverboseprintk((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)); + devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->ChainOffset = 0; @@ -4791,17 +5041,18 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) EventAck_t *pAck; 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!\n", - ioc->name); + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", + ioc->name,__FUNCTION__)); return -1; } - memset(pAck, 0, sizeof(*pAck)); - dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name)); + devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name)); pAck->Function = MPI_FUNCTION_EVENT_ACK; pAck->ChainOffset = 0; + pAck->Reserved[0] = pAck->Reserved[1] = 0; pAck->MsgFlags = 0; + pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0; pAck->Event = evnp->Event; pAck->EventContext = evnp->EventContext; @@ -4828,15 +5079,14 @@ int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) { Config_t *pReq; + ConfigExtendedPageHeader_t *pExtHdr = NULL; MPT_FRAME_HDR *mf; unsigned long flags; int ii, rc; - u32 flagsLength; + 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(); @@ -4858,16 +5108,30 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) pReq->Reserved = 0; pReq->ChainOffset = 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; + 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->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. @@ -4877,123 +5141,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) 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); - - add_timer(&pCfg->timer); - mpt_put_msg_frame(mpt_base_index, ioc, mf); - wait_event(mpt_waitq, pCfg->wait_done); - - /* mf has been freed - do not access */ - - rc = pCfg->status; - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_toolbox - Generic function to issue toolbox message - * @ioc - Pointer to an adapter structure - * @cfg - Pointer to a toolbox 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_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) -{ - ToolboxIstwiReadWriteRequest_t *pReq; - MPT_FRAME_HDR *mf; - struct pci_dev *pdev; - unsigned long flags; - int rc; - u32 flagsLength; - int in_isr; + if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { + flagsLength |= pExtHdr->ExtPageLength * 4; - /* (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 "toobox request not allowed in ISR context!\n", - ioc->name)); - return -EPERM; + 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; - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { - dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n", - ioc->name)); - return -EAGAIN; + 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)); } - pReq = (ToolboxIstwiReadWriteRequest_t *)mf; - pReq->Tool = pCfg->action; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_TOOLBOX; - pReq->Reserved1 = 0; - pReq->Reserved2 = 0; - pReq->MsgFlags = 0; - pReq->Flags = pCfg->dir; - pReq->BusNum = 0; - pReq->Reserved3 = 0; - pReq->NumAddressBytes = 0x01; - pReq->Reserved4 = 0; - pReq->DataLength = 0x04; - pdev = (struct pci_dev *) ioc->pcidev; - if (pdev->devfn & 1) - pReq->DeviceAddr = 0xB2; - else - pReq->DeviceAddr = 0xB0; - pReq->Addr1 = 0; - pReq->Addr2 = 0; - pReq->Addr3 = 0; - pReq->Reserved5 = 0; - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4; - - mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr); - - 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 */ @@ -5014,7 +5175,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* 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); @@ -5081,13 +5242,8 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * 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 { @@ -5097,19 +5253,12 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * 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); + list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) { + list_del(&pCfg->linkage); - pCfg->status = MPT_CONFIG_ERROR; - pCfg->wait_done = 1; - wake_up(&mpt_waitq); - - 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); } @@ -5223,20 +5372,26 @@ static int 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"; @@ -5247,9 +5402,6 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo case MPTCTL_DRIVER: if (!ctl++) drvname = "ioctl"; break; - case MPTDMP_DRIVER: - if (!dmp++) drvname = "DMP"; - break; } if (drvname) @@ -5338,7 +5490,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo 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", @@ -5411,11 +5563,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh a[5], a[4], a[3], a[2], a[1], a[0]); } -#ifndef __sparc__ y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); -#else - y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq)); -#endif if (!ioc->active) y += sprintf(buffer+len+y, " (disabled)"); @@ -5474,7 +5622,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) /* The SCSI driver needs to adjust timeouts on all current * commands prior to the diagnostic reset being issued. - * Prevents timeouts occuring during a diagnostic reset...very bad. + * Prevents timeouts occurring during a diagnostic reset...very bad. * For all other protocol drivers, this is a no-op. */ { @@ -5485,11 +5633,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) if (MptResetHandlers[ii]) { dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET); + r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET); if (ioc->alt_ioc) { dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET); } } } @@ -5514,11 +5662,13 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) return rc; } +# define EVENT_DESCR_STR_SZ 100 + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static char * -EventDescriptionStr(u8 event, u32 evData0) +static void +EventDescriptionStr(u8 event, u32 evData0, char *evStr) { - char *ds; + char *ds = NULL; switch(event) { case MPI_EVENT_NONE: @@ -5555,22 +5705,226 @@ EventDescriptionStr(u8 event, u32 evData0) if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) ds = "Loop State(LIP) Change"; else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) - ds = "Loop State(LPE) Change"; /* ??? */ + ds = "Loop State(LPE) Change"; /* ??? */ else - ds = "Loop State(LPB) Change"; /* ??? */ + ds = "Loop State(LPB) Change"; /* ??? */ break; case MPI_EVENT_LOGOUT: ds = "Logout"; break; case MPI_EVENT_EVENT_CHANGE: if (evData0) - ds = "Events(ON) Change"; + ds = "Events ON"; else - ds = "Events(OFF) Change"; + ds = "Events OFF"; 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 id = (u8)(evData0); + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Added: id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Deleted: id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: SMART Data: id=%d", + id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: No Persistancy: id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Internal Device Reset : id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Internal Task Abort : id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Internal Abort Task Set : id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Internal Clear Task Set : id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Internal Query Task : id=%d", id); + break; + default: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Unknown: id=%d", id); + 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: + { + u8 LinkRates = (u8)(evData0 >> 8); + u8 PhyNumber = (u8)(evData0); + LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >> + MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT; + switch (LinkRates) { + case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Rate Unknown",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Phy Disabled",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Failed Speed Nego",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Sata OOB Completed",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_1_5: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Rate 1.5 Gbps",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_3_0: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d:" + " Rate 3.0 Gpbs",PhyNumber); + break; + default: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS PHY Link Status: Phy=%d", PhyNumber); + break; + } + break; + } + case MPI_EVENT_SAS_DISCOVERY_ERROR: + ds = "SAS Discovery Error"; + break; + case MPI_EVENT_IR_RESYNC_UPDATE: + { + u8 resync_complete = (u8)(evData0 >> 16); + snprintf(evStr, EVENT_DESCR_STR_SZ, + "IR Resync Update: Complete = %d:",resync_complete); + break; + } + case MPI_EVENT_IR2: + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: + ds = "IR2: LD State Changed"; + break; + case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: + ds = "IR2: PD State Changed"; + break; + case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: + ds = "IR2: Bad Block Table Full"; + break; + case MPI_EVENT_IR2_RC_PD_INSERTED: + ds = "IR2: PD Inserted"; + break; + case MPI_EVENT_IR2_RC_PD_REMOVED: + ds = "IR2: PD Removed"; + break; + case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: + ds = "IR2: Foreign CFG Detected"; + break; + case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: + ds = "IR2: Rebuild Medium Error"; + break; + default: + ds = "IR2"; + break; + } + break; + } + case MPI_EVENT_SAS_DISCOVERY: + { + if (evData0) + ds = "SAS Discovery: Start"; + else + ds = "SAS Discovery: Stop"; + break; + } + case MPI_EVENT_LOG_ENTRY_ADDED: + ds = "SAS Log Entry Added"; break; + /* * MPT base "custom" events may be added here... */ @@ -5578,7 +5932,8 @@ EventDescriptionStr(u8 event, u32 evData0) ds = "Unknown"; break; } - return ds; + if (ds) + strncpy(evStr, ds, EVENT_DESCR_STR_SZ); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -5600,7 +5955,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply int ii; int r = 0; int handlers = 0; - char *evStr; + char evStr[EVENT_DESCR_STR_SZ]; u8 event; /* @@ -5613,13 +5968,13 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply evData0 = le32_to_cpu(pEventReply->Data[0]); } - evStr = EventDescriptionStr(event, evData0); - devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", + EventDescriptionStr(event, evData0, evStr); + devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n", ioc->name, - evStr, - event)); + event, + evStr)); -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) +#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS) printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); for (ii = 0; ii < evDataLen; ii++) printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); @@ -5630,20 +5985,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * 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; @@ -5656,6 +5997,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } } break; + case MPI_EVENT_INTEGRATED_RAID: + mptbase_raid_process_event_data(ioc, + (MpiEventDataRaid_t *)pEventReply->Data); + break; + default: + break; } /* @@ -5665,7 +6012,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply 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; @@ -5686,7 +6033,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptEvHandlers[ii]) { - devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", + devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", ioc->name, ii)); r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; @@ -5698,8 +6045,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * If needed, send (a single) EventAck. */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { + devtverboseprintk((MYIOC_s_WARN_FMT + "EventAck required\n",ioc->name)); if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", ioc->name, ii)); } } @@ -5714,7 +6063,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC * - * Refer to lsi/fc_log.h. + * Refer to lsi/mpi_log_fc.h. */ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) @@ -5731,7 +6080,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * 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 @@ -5739,7 +6088,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) * 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"; @@ -5778,7 +6127,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) case 0x00080000: desc = "Outbound DMA Overrun"; break; - + case 0x00090000: desc = "Task Management"; break; @@ -5794,12 +6143,119 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) 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 */ + "Diag Message Error", /* 04h */ + "Task Terminated", /* 05h */ + "Enclosure Management", /* 06h */ + "Target Mode" /* 07h */ + }; + 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 */ + "Persistant Reservation Out Not Affiliation Owner", /* 15h */ + "Open Transmit DMA Abort", /* 16h */ + "IO Device Missing Delay Retry", /* 17h */ + NULL, /* 18h */ + NULL, /* 19h */ + NULL, /* 1Ah */ + NULL, /* 1Bh */ + NULL, /* 1Ch */ + NULL, /* 1Dh */ + NULL, /* 1Eh */ + NULL, /* 1Fh */ + "Enclosure Management" /* 20h */ + }; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * 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 + * + * Refer to lsi/mpi_log_sas.h. + */ +static void +mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) +{ +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; + + 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]; + } + + 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_sp_ioc_info - IOC information returned from SCSI Parallel IOC. @@ -5813,7 +6269,7 @@ static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) { u32 status = ioc_status & MPI_IOCSTATUS_MASK; - char *desc = ""; + char *desc = NULL; switch (status) { case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ @@ -5886,7 +6342,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - /* This error is checked in scsi_io_done(). Skip. + /* This error is checked in scsi_io_done(). Skip. desc = "SCSI Data Underrun"; */ break; @@ -5923,14 +6379,19 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) desc = "Others"; break; } - if (desc != "") + if (desc != NULL) printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +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); @@ -5943,9 +6404,7 @@ EXPORT_SYMBOL(mpt_get_msg_frame); 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_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); @@ -5953,25 +6412,10 @@ EXPORT_SYMBOL(mpt_lan_index); 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); - -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 -}; +EXPORT_SYMBOL(mptbase_sas_persist_operation); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -5983,12 +6427,6 @@ static int __init 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"); @@ -6000,10 +6438,7 @@ fusion_init(void) 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); @@ -6019,11 +6454,7 @@ fusion_init(void) #ifdef CONFIG_PROC_FS (void) procmpt_create(); #endif - r = pci_module_init(&mptbase_driver); - if(r) - return(r); - - return r; + return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -6039,7 +6470,6 @@ fusion_exit(void) dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - pci_unregister_driver(&mptbase_driver); mpt_reset_deregister(mpt_base_index); #ifdef CONFIG_PROC_FS @@ -6047,6 +6477,5 @@ fusion_exit(void) #endif } - module_init(fusion_init); module_exit(fusion_exit);