diff options
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 132 |
1 files changed, 110 insertions, 22 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 74022316fc6..d890b2b8a93 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -91,9 +91,9 @@ static int mfcounter = 0; * Public data... */ int mpt_lan_index = -1; -static int mpt_stm_index = -1; +int mpt_stm_index = -1; -static struct proc_dir_entry *mpt_proc_root_dir; +struct proc_dir_entry *mpt_proc_root_dir; #define WHOINIT_UNKNOWN 0xAA @@ -148,7 +148,6 @@ 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); @@ -313,13 +312,13 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) 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 == SCSI) + else if (ioc->bus_type == SPI) mpt_sp_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 == SCSI && + if (ioc->bus_type == SPI && cb_idx != mpt_stm_index && cb_idx != mpt_lan_index) mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); @@ -1118,6 +1117,65 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) return -1; } +int +mpt_alt_ioc_wait(MPT_ADAPTER *ioc) +{ + int loop_count = 30 * 4; /* Wait 30 seconds */ + int status = -1; /* -1 means failed to get board READY */ + + do { + spin_lock(&ioc->initializing_hba_lock); + if (ioc->initializing_hba_lock_flag == 0) { + ioc->initializing_hba_lock_flag=1; + spin_unlock(&ioc->initializing_hba_lock); + status = 0; + break; + } + spin_unlock(&ioc->initializing_hba_lock); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/4); + } while (--loop_count); + + return status; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery + * @ioc: Pointer to MPT adapter structure + * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. + * + * This routine performs all the steps necessary to bring the IOC + * to a OPERATIONAL state. + * + * Special Note: This function was added with spin lock's so as to allow + * the dv(domain validation) work thread to succeed on the other channel + * that maybe occuring at the same time when this function is called. + * Without this lock, the dv would fail when message frames were + * requested during hba bringup on the alternate ioc. + */ +static int +mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag) +{ + int r; + + if(ioc->alt_ioc) { + if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) + return r; + } + + r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, + CAN_SLEEP); + + if(ioc->alt_ioc) { + spin_lock(&ioc->alt_ioc->initializing_hba_lock); + ioc->alt_ioc->initializing_hba_lock_flag=0; + spin_unlock(&ioc->alt_ioc->initializing_hba_lock); + } + +return r; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_attach - Install a PCI intelligent MPT adapter. @@ -1173,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) 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; @@ -1186,6 +1243,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); + spin_lock_init(&ioc->fc_rescan_work_lock); + spin_lock_init(&ioc->fc_rport_lock); + spin_lock_init(&ioc->initializing_hba_lock); /* Initialize the event logging. */ @@ -1208,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) */ 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++; @@ -1314,9 +1378,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) 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->prod_name = "LSI53C1030"; - ioc->bus_type = SCSI; + ioc->bus_type = SPI; /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ @@ -1329,7 +1397,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { ioc->prod_name = "LSI53C1035"; - ioc->bus_type = SCSI; + ioc->bus_type = SPI; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { ioc->prod_name = "LSISAS1064"; @@ -1408,8 +1476,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) */ mpt_detect_bound_ports(ioc, pdev); - if ((r = mpt_do_ioc_recovery(ioc, - MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { + if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); @@ -1563,7 +1630,7 @@ mpt_resume(struct pci_dev *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 */ @@ -1656,7 +1723,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; } @@ -1772,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) 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; } @@ -1780,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* (re)Enable alt-IOC! (reply interrupt) */ 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; } @@ -1821,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * (FCPortPage0_t stuff) */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) GetFcPortPage0(ioc, ii); + (void) mptbase_GetFcPortPage0(ioc, ii); } if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && @@ -2983,7 +3050,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) /* Clear the internal flash bad bit - autoincrementing register, * so must do two writes. */ - if (ioc->bus_type == SCSI) { + if (ioc->bus_type == SPI) { /* * 1030 and 1035 H/W errata, workaround to access * the ClearFlashBadSignatureBit @@ -3093,7 +3160,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) int cnt,cntdn; dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if (ioc->bus_type == SCSI) { + if (ioc->bus_type == SPI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. */ @@ -3521,7 +3588,7 @@ initChainBuffers(MPT_ADAPTER *ioc) dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n", ioc->name, numSGE, num_sge, num_chain)); - if (ioc->bus_type == SCSI) + if (ioc->bus_type == SPI) num_chain *= MPT_SCSI_CAN_QUEUE; else num_chain *= MPT_FC_CAN_QUEUE; @@ -4140,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * GetFcPortPage0 - Fetch FCPort config Page0. + * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: IOC Port number * @@ -4150,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc) * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ -static int -GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) +int +mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) { ConfigPageHeader_t hdr; CONFIGPARMS cfg; @@ -4161,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) int data_sz; int copy_sz; int rc; + int count = 400; + /* Get FCPort Page 0 header */ hdr.PageVersion = 0; @@ -4184,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) rc = -ENOMEM; ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); if (ppage0_alloc) { + + try_again: memset((u8 *)ppage0_alloc, 0, data_sz); cfg.physAddr = page0_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; @@ -4215,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + /* + * if still doing discovery, + * hang loose a while until finished + */ + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { + if (count-- > 0) { + msleep_interruptible(100); + goto try_again; + } + printk(MYIOC_s_INFO_FMT "Firmware discovery not" + " complete.\n", + ioc->name); + } } pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); @@ -6271,6 +6355,7 @@ EXPORT_SYMBOL(mpt_resume); EXPORT_SYMBOL(mpt_suspend); #endif EXPORT_SYMBOL(ioc_list); +EXPORT_SYMBOL(mpt_proc_root_dir); EXPORT_SYMBOL(mpt_register); EXPORT_SYMBOL(mpt_deregister); EXPORT_SYMBOL(mpt_event_register); @@ -6288,6 +6373,7 @@ EXPORT_SYMBOL(mpt_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); EXPORT_SYMBOL(mpt_lan_index); +EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); EXPORT_SYMBOL(mpt_toolbox); @@ -6296,6 +6382,8 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); +EXPORT_SYMBOL(mpt_alt_ioc_wait); +EXPORT_SYMBOL(mptbase_GetFcPortPage0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |