diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 269 |
1 files changed, 196 insertions, 73 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index a11a909340b..8b88118e20e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3,7 +3,7 @@ * for access to MPT (Message Passing Technology) firmware. * * This code is based on drivers/scsi/mpt2sas/mpt2_base.c - * Copyright (C) 2007-2010 LSI Corporation + * Copyright (C) 2007-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or @@ -57,6 +57,7 @@ #include <linux/sort.h> #include <linux/io.h> #include <linux/time.h> +#include <linux/kthread.h> #include <linux/aer.h> #include "mpt2sas_base.h" @@ -87,19 +88,6 @@ static int disable_discovery = -1; module_param(disable_discovery, int, 0); MODULE_PARM_DESC(disable_discovery, " disable discovery "); - -/* diag_buffer_enable is bitwise - * bit 0 set = TRACE - * bit 1 set = SNAPSHOT - * bit 2 set = EXTENDED - * - * Either bit can be set, or both - */ -static int diag_buffer_enable; -module_param(diag_buffer_enable, int, 0); -MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " - "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); - /** * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. * @@ -118,10 +106,34 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) ioc->fwfault_debug = mpt2sas_fwfault_debug; return 0; } + module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt2sas_fwfault_debug, 0644); /** + * mpt2sas_remove_dead_ioc_func - kthread context to remove dead ioc + * @arg: input argument, used to derive ioc + * + * Return 0 if controller is removed from pci subsystem. + * Return -1 for other case. + */ +static int mpt2sas_remove_dead_ioc_func(void *arg) +{ + struct MPT2SAS_ADAPTER *ioc = (struct MPT2SAS_ADAPTER *)arg; + struct pci_dev *pdev; + + if ((ioc == NULL)) + return -1; + + pdev = ioc->pdev; + if ((pdev == NULL)) + return -1; + pci_stop_and_remove_bus_device_locked(pdev); + return 0; +} + + +/** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc * Context: sleep. @@ -136,13 +148,63 @@ _base_fault_reset_work(struct work_struct *work) unsigned long flags; u32 doorbell; int rc; + struct task_struct *p; spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->pci_error_recovery) goto rearm_timer; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); doorbell = mpt2sas_base_get_iocstate(ioc, 0); + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) { + printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n", + ioc->name, __func__); + + /* It may be possible that EEH recovery can resolve some of + * pci bus failure issues rather removing the dead ioc function + * by considering controller is in a non-operational state. So + * here priority is given to the EEH recovery. If it doesn't + * not resolve this issue, mpt2sas driver will consider this + * controller to non-operational state and remove the dead ioc + * function. + */ + if (ioc->non_operational_loop++ < 5) { + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, + flags); + goto rearm_timer; + } + + /* + * Call _scsih_flush_pending_cmds callback so that we flush all + * pending commands back to OS. This call is required to aovid + * deadlock at block layer. Dead IOC will fail to do diag reset, + * and this call is safe since dead ioc will never return any + * command back from HW. + */ + ioc->schedule_dead_ioc_flush_running_cmds(ioc); + /* + * Set remove_host flag early since kernel thread will + * take some time to execute. + */ + ioc->remove_host = 1; + /*Remove the Dead Host */ + p = kthread_run(mpt2sas_remove_dead_ioc_func, ioc, + "mpt2sas_dead_ioc_%d", ioc->id); + if (IS_ERR(p)) { + printk(MPT2SAS_ERR_FMT + "%s: Running mpt2sas_dead_ioc thread failed !!!!\n", + ioc->name, __func__); + } else { + printk(MPT2SAS_ERR_FMT + "%s: Running mpt2sas_dead_ioc thread success !!!!\n", + ioc->name, __func__); + } + + return; /* don't rearm timer */ + } + + ioc->non_operational_loop = 0; + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); @@ -607,7 +669,7 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) return; /* eat the loginfos associated with task aborts */ - if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == + if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info == 0x31140000 || log_info == 0x31130000)) return; @@ -649,6 +711,11 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u16 ioc_status; mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (unlikely(!mpi_reply)) { + printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } ioc_status = le16_to_cpu(mpi_reply->IOCStatus); #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if ((ioc_status & MPI2_IOCSTATUS_MASK) && @@ -701,10 +768,9 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. + * Returns void. */ -static u8 +static void _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) { Mpi2EventNotificationReply_t *mpi_reply; @@ -713,9 +779,9 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); if (!mpi_reply) - return 1; + return; if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) - return 1; + return; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING _base_display_event_data(ioc, mpi_reply); #endif @@ -745,7 +811,7 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) /* ctl callback handler */ mpt2sas_ctl_event_callback(ioc, msix_index, reply); - return 1; + return; } /** @@ -880,16 +946,18 @@ _base_interrupt(int irq, void *bus_id) else if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) goto next; - if (smid) + if (smid) { cb_idx = _base_get_cb_idx(ioc, smid); - if (smid && cb_idx != 0xFF) { - rc = mpt_callbacks[cb_idx](ioc, smid, msix_index, - reply); + if ((likely(cb_idx < MPT_MAX_CALLBACKS)) + && (likely(mpt_callbacks[cb_idx] != NULL))) { + rc = mpt_callbacks[cb_idx](ioc, smid, + msix_index, reply); if (reply) - _base_display_reply_info(ioc, smid, msix_index, - reply); + _base_display_reply_info(ioc, smid, + msix_index, reply); if (rc) mpt2sas_base_free_smid(ioc, smid); + } } if (!smid) _base_async_event(ioc, msix_index, reply); @@ -1340,8 +1408,6 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) int i; u8 try_msix = 0; - INIT_LIST_HEAD(&ioc->reply_queue_list); - if (msix_disable == -1 || msix_disable == 0) try_msix = 1; @@ -1351,7 +1417,7 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) if (_base_check_enable_msix(ioc) != 0) goto try_ioapic; - ioc->reply_queue_count = min_t(u8, ioc->cpu_count, + ioc->reply_queue_count = min_t(int, ioc->cpu_count, ioc->msix_vector_count); entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), @@ -1420,6 +1486,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) if (pci_enable_device_mem(pdev)) { printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: " "failed\n", ioc->name); + ioc->bars = 0; return -ENODEV; } @@ -1428,6 +1495,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) MPT2SAS_DRIVER_NAME)) { printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: " "failed\n", ioc->name); + ioc->bars = 0; r = -ENODEV; goto out_fail; } @@ -1671,14 +1739,14 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) list_for_each_entry_safe(chain_req, next, &ioc->scsi_lookup[i].chain_list, tracker_list) { list_del_init(&chain_req->tracker_list); - list_add_tail(&chain_req->tracker_list, + list_add(&chain_req->tracker_list, &ioc->free_chain_list); } } ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].scmd = NULL; ioc->scsi_lookup[i].direct_io = 0; - list_add_tail(&ioc->scsi_lookup[i].tracker_list, + list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); @@ -1696,13 +1764,13 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) /* hi-priority */ i = smid - ioc->hi_priority_smid; ioc->hpr_lookup[i].cb_idx = 0xFF; - list_add_tail(&ioc->hpr_lookup[i].tracker_list, + list_add(&ioc->hpr_lookup[i].tracker_list, &ioc->hpr_free_list); } else if (smid <= ioc->hba_queue_depth) { /* internal queue */ i = smid - ioc->internal_smid; ioc->internal_lookup[i].cb_idx = 0xFF; - list_add_tail(&ioc->internal_lookup[i].tracker_list, + list_add(&ioc->internal_lookup[i].tracker_list, &ioc->internal_free_list); } spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); @@ -1921,6 +1989,10 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc) printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, MPT2SAS_INTEL_RMS2LL040_BRANDING); break; + case MPT2SAS_INTEL_SSD910_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_SSD910_BRANDING); + break; default: break; } @@ -1930,6 +2002,30 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc) printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, MPT2SAS_INTEL_RS25GB008_BRANDING); break; + case MPT2SAS_INTEL_RMS25JB080_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25JB080_BRANDING); + break; + case MPT2SAS_INTEL_RMS25JB040_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25JB040_BRANDING); + break; + case MPT2SAS_INTEL_RMS25KB080_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25KB080_BRANDING); + break; + case MPT2SAS_INTEL_RMS25KB040_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25KB040_BRANDING); + break; + case MPT2SAS_INTEL_RMS25LB040_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25LB040_BRANDING); + break; + case MPT2SAS_INTEL_RMS25LB080_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25LB080_BRANDING); + break; default: break; } @@ -1997,12 +2093,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) { int i = 0; char desc[16]; - u8 revision; u32 iounit_pg1_flags; u32 bios_version; bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision); strncpy(desc, ioc->manu_pg0.ChipName, 16); printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), " "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", @@ -2011,7 +2105,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, ioc->facts.FWVersion.Word & 0x000000FF, - revision, + ioc->pdev->revision, (bios_version & 0xFF000000) >> 24, (bios_version & 0x00FF0000) >> 16, (bios_version & 0x0000FF00) >> 8, @@ -2408,23 +2502,25 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* reply free queue sizing - taking into account for 64 FW events */ ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; + /* calculate reply descriptor post queue depth */ + ioc->reply_post_queue_depth = ioc->hba_queue_depth + + ioc->reply_free_queue_depth + 1; /* align the reply post queue on the next 16 count boundary */ - if (!ioc->reply_free_queue_depth % 16) - ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16; - else - ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + - 32 - (ioc->reply_free_queue_depth % 16); + if (ioc->reply_post_queue_depth % 16) + ioc->reply_post_queue_depth += 16 - + (ioc->reply_post_queue_depth % 16); + + if (ioc->reply_post_queue_depth > facts->MaxReplyDescriptorPostQueueDepth) { - ioc->reply_post_queue_depth = min_t(u16, - (facts->MaxReplyDescriptorPostQueueDepth - - (facts->MaxReplyDescriptorPostQueueDepth % 16)), - (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16))); - ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16; - ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64; + ioc->reply_post_queue_depth = + facts->MaxReplyDescriptorPostQueueDepth - + (facts->MaxReplyDescriptorPostQueueDepth % 16); + ioc->hba_queue_depth = + ((ioc->reply_post_queue_depth - 64) / 2) - 1; + ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; } - dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, @@ -2515,6 +2611,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( GFP_KERNEL, ioc->chain_pages); + if (!ioc->chain_lookup) { + printk(MPT2SAS_ERR_FMT "chain_lookup: get_free_pages failed, " + "sz(%d)\n", ioc->name, (int)sz); + goto out; + } ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, ioc->request_sz, 16, 0); if (!ioc->chain_dma_pool) { @@ -3113,8 +3214,8 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) ioc->ioc_link_reset_in_progress = 1; - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || @@ -3215,8 +3316,8 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, request = mpt2sas_base_get_msg_frame(ioc, smid); ioc->base_cmds.smid = smid; memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { @@ -3723,8 +3824,8 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) mpi_request->EventMasks[i] = cpu_to_le32(ioc->event_masks[i]); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { printk(MPT2SAS_ERR_FMT "%s: timeout\n", @@ -3836,11 +3937,15 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, &ioc->chip->HostDiagnostic); - /* don't access any registers for 50 milliseconds */ - msleep(50); + /* This delay allows the chip PCIe hardware time to finish reset tasks*/ + if (sleep_flag == CAN_SLEEP) + msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); + else + mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); - /* 300 second max wait */ - for (count = 0; count < 3000000 ; count++) { + /* Approximately 300 second max wait */ + for (count = 0; count < (300000000 / + MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) { host_diagnostic = readl(&ioc->chip->HostDiagnostic); @@ -3849,11 +3954,13 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) break; - /* wait 100 msec */ + /* Wait to pass the second read delay window */ if (sleep_flag == CAN_SLEEP) - msleep(1); + msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC + /1000); else - mdelay(1); + mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC + /1000); } if (host_diagnostic & MPI2_DIAG_HCB_MODE) { @@ -4090,7 +4197,8 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (ioc->is_driver_loading) { if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier == 0x80) { - hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 & + hide_flag = (u8) ( + le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) & MFG_PAGE10_HIDE_SSDS_MASK); if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) ioc->mfg_pg10_hide_flag = hide_flag; @@ -4120,18 +4228,25 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); - _base_mask_interrupts(ioc); - ioc->shost_recovery = 1; - _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - ioc->shost_recovery = 0; + if (ioc->chip_phys && ioc->chip) { + _base_mask_interrupts(ioc); + ioc->shost_recovery = 1; + _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); + ioc->shost_recovery = 0; + } + _base_free_irq(ioc); _base_disable_msix(ioc); - if (ioc->chip_phys) + + if (ioc->chip_phys && ioc->chip) iounmap(ioc->chip); ioc->chip_phys = 0; - pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); + + if (pci_is_enabled(pdev)) { + pci_release_selected_regions(ioc->pdev, ioc->bars); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + } return; } @@ -4177,7 +4292,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) r = mpt2sas_base_map_resources(ioc); if (r) - return r; + goto out_free_resources; if (ioc->is_warpdrive) { ioc->reply_post_host_index[0] = @@ -4216,7 +4331,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; init_waitqueue_head(&ioc->reset_wq); - /* allocate memory pd handle bitmask list */ ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); if (ioc->facts.MaxDevHandle % 8) @@ -4227,7 +4341,12 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) r = -ENOMEM; goto out_free_resources; } - + ioc->blocking_handles = kzalloc(ioc->pd_handles_sz, + GFP_KERNEL); + if (!ioc->blocking_handles) { + r = -ENOMEM; + goto out_free_resources; + } ioc->fwfault_debug = mpt2sas_fwfault_debug; /* base internal command bits */ @@ -4298,6 +4417,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) goto out_free_resources; + ioc->non_operational_loop = 0; return 0; @@ -4311,6 +4431,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (ioc->is_warpdrive) kfree(ioc->reply_post_host_index); kfree(ioc->pd_handles); + kfree(ioc->blocking_handles); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); kfree(ioc->scsih_cmds.reply); @@ -4352,6 +4473,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) if (ioc->is_warpdrive) kfree(ioc->reply_post_host_index); kfree(ioc->pd_handles); + kfree(ioc->blocking_handles); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); kfree(ioc->ctl_cmds.sense); @@ -4485,7 +4607,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n", ioc->name, __func__); r = 0; - goto out; + goto out_unlocked; } if (mpt2sas_fwfault_debug) @@ -4541,6 +4663,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); mutex_unlock(&ioc->reset_in_progress_mutex); + out_unlocked: dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, __func__)); return r; |
