Commit 9afc1163 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Ten updates: one non code maintainer update for vmw_pvscsi, five code
  updates for ibmvfc and four for UFS.

  All are either trivial patches or bug fixes"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: vmw_pvscsi: MAINTAINERS: Update maintainer
  scsi: ufs: Convert sysfs sprintf/snprintf family to sysfs_emit
  scsi: ufs: Remove redundant checks of !hba in suspend/resume callbacks
  scsi: ufs: ufs-qcom: Disable interrupt in reset path
  scsi: ufs: Minor adjustments to error handling
  scsi: ibmvfc: Reinitialize sub-CRQs and perform channel enquiry after LPM
  scsi: ibmvfc: Store return code of H_FREE_SUB_CRQ during cleanup
  scsi: ibmvfc: Treat H_CLOSED as success during sub-CRQ registration
  scsi: ibmvfc: Fix invalid sub-CRQ handles after hard reset
  scsi: ibmvfc: Simplify handling of sub-CRQ initialization
parents ce307084 11129634
...@@ -19166,7 +19166,7 @@ S: Maintained ...@@ -19166,7 +19166,7 @@ S: Maintained
F: drivers/infiniband/hw/vmw_pvrdma/ F: drivers/infiniband/hw/vmw_pvrdma/
VMware PVSCSI driver VMware PVSCSI driver
M: Jim Gill <jgill@vmware.com> M: Vishal Bhakta <vbhakta@vmware.com>
M: VMware PV-Drivers <pv-drivers@vmware.com> M: VMware PV-Drivers <pv-drivers@vmware.com>
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
S: Maintained S: Maintained
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/bsg-lib.h> #include <linux/bsg-lib.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/rtas.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
...@@ -158,6 +159,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *); ...@@ -158,6 +159,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *);
static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *); static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *);
static void ibmvfc_tgt_move_login(struct ibmvfc_target *); static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
static void ibmvfc_release_sub_crqs(struct ibmvfc_host *);
static void ibmvfc_init_sub_crqs(struct ibmvfc_host *);
static const char *unknown_error = "unknown error"; static const char *unknown_error = "unknown error";
static long h_reg_sub_crq(unsigned long unit_address, unsigned long ioba, static long h_reg_sub_crq(unsigned long unit_address, unsigned long ioba,
...@@ -899,6 +903,9 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) ...@@ -899,6 +903,9 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
{ {
int rc = 0; int rc = 0;
struct vio_dev *vdev = to_vio_dev(vhost->dev); struct vio_dev *vdev = to_vio_dev(vhost->dev);
unsigned long flags;
ibmvfc_release_sub_crqs(vhost);
/* Re-enable the CRQ */ /* Re-enable the CRQ */
do { do {
...@@ -910,6 +917,15 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) ...@@ -910,6 +917,15 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
if (rc) if (rc)
dev_err(vhost->dev, "Error enabling adapter (rc=%d)\n", rc); dev_err(vhost->dev, "Error enabling adapter (rc=%d)\n", rc);
spin_lock_irqsave(vhost->host->host_lock, flags);
spin_lock(vhost->crq.q_lock);
vhost->do_enquiry = 1;
vhost->using_channels = 0;
spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
ibmvfc_init_sub_crqs(vhost);
return rc; return rc;
} }
...@@ -926,8 +942,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) ...@@ -926,8 +942,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
unsigned long flags; unsigned long flags;
struct vio_dev *vdev = to_vio_dev(vhost->dev); struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_queue *crq = &vhost->crq; struct ibmvfc_queue *crq = &vhost->crq;
struct ibmvfc_queue *scrq;
int i; ibmvfc_release_sub_crqs(vhost);
/* Close the CRQ */ /* Close the CRQ */
do { do {
...@@ -947,16 +963,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) ...@@ -947,16 +963,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
memset(crq->msgs.crq, 0, PAGE_SIZE); memset(crq->msgs.crq, 0, PAGE_SIZE);
crq->cur = 0; crq->cur = 0;
if (vhost->scsi_scrqs.scrqs) {
for (i = 0; i < nr_scsi_hw_queues; i++) {
scrq = &vhost->scsi_scrqs.scrqs[i];
spin_lock(scrq->q_lock);
memset(scrq->msgs.scrq, 0, PAGE_SIZE);
scrq->cur = 0;
spin_unlock(scrq->q_lock);
}
}
/* And re-open it again */ /* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address, rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
crq->msg_token, PAGE_SIZE); crq->msg_token, PAGE_SIZE);
...@@ -966,9 +972,12 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) ...@@ -966,9 +972,12 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
dev_warn(vhost->dev, "Partner adapter not ready\n"); dev_warn(vhost->dev, "Partner adapter not ready\n");
else if (rc != 0) else if (rc != 0)
dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc); dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc);
spin_unlock(vhost->crq.q_lock); spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags); spin_unlock_irqrestore(vhost->host->host_lock, flags);
ibmvfc_init_sub_crqs(vhost);
return rc; return rc;
} }
...@@ -5642,7 +5651,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost, ...@@ -5642,7 +5651,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE, rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE,
&scrq->cookie, &scrq->hw_irq); &scrq->cookie, &scrq->hw_irq);
if (rc) { /* H_CLOSED indicates successful register, but no CRQ partner */
if (rc && rc != H_CLOSED) {
dev_warn(dev, "Error registering sub-crq: %d\n", rc); dev_warn(dev, "Error registering sub-crq: %d\n", rc);
if (rc == H_PARAMETER) if (rc == H_PARAMETER)
dev_warn_once(dev, "Firmware may not support MQ\n"); dev_warn_once(dev, "Firmware may not support MQ\n");
...@@ -5675,8 +5685,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost, ...@@ -5675,8 +5685,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
irq_failed: irq_failed:
do { do {
plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie); rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); } while (rtas_busy_delay(rc));
reg_failed: reg_failed:
ibmvfc_free_queue(vhost, scrq); ibmvfc_free_queue(vhost, scrq);
LEAVE; LEAVE;
...@@ -5694,6 +5704,7 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index) ...@@ -5694,6 +5704,7 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
free_irq(scrq->irq, scrq); free_irq(scrq->irq, scrq);
irq_dispose_mapping(scrq->irq); irq_dispose_mapping(scrq->irq);
scrq->irq = 0;
do { do {
rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,
...@@ -5707,17 +5718,21 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index) ...@@ -5707,17 +5718,21 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
LEAVE; LEAVE;
} }
static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost) static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
{ {
int i, j; int i, j;
ENTER; ENTER;
if (!vhost->mq_enabled)
return;
vhost->scsi_scrqs.scrqs = kcalloc(nr_scsi_hw_queues, vhost->scsi_scrqs.scrqs = kcalloc(nr_scsi_hw_queues,
sizeof(*vhost->scsi_scrqs.scrqs), sizeof(*vhost->scsi_scrqs.scrqs),
GFP_KERNEL); GFP_KERNEL);
if (!vhost->scsi_scrqs.scrqs) if (!vhost->scsi_scrqs.scrqs) {
return -1; vhost->do_enquiry = 0;
return;
}
for (i = 0; i < nr_scsi_hw_queues; i++) { for (i = 0; i < nr_scsi_hw_queues; i++) {
if (ibmvfc_register_scsi_channel(vhost, i)) { if (ibmvfc_register_scsi_channel(vhost, i)) {
...@@ -5726,13 +5741,12 @@ static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost) ...@@ -5726,13 +5741,12 @@ static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
kfree(vhost->scsi_scrqs.scrqs); kfree(vhost->scsi_scrqs.scrqs);
vhost->scsi_scrqs.scrqs = NULL; vhost->scsi_scrqs.scrqs = NULL;
vhost->scsi_scrqs.active_queues = 0; vhost->scsi_scrqs.active_queues = 0;
LEAVE; vhost->do_enquiry = 0;
return -1; break;
} }
} }
LEAVE; LEAVE;
return 0;
} }
static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost) static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost)
...@@ -5999,11 +6013,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -5999,11 +6013,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
goto remove_shost; goto remove_shost;
} }
if (vhost->mq_enabled) { ibmvfc_init_sub_crqs(vhost);
rc = ibmvfc_init_sub_crqs(vhost);
if (rc)
dev_warn(dev, "Failed to allocate Sub-CRQs. rc=%d\n", rc);
}
if (shost_to_fc_host(shost)->rqst_q) if (shost_to_fc_host(shost)->rqst_q)
blk_queue_max_segments(shost_to_fc_host(shost)->rqst_q, 1); blk_queue_max_segments(shost_to_fc_host(shost)->rqst_q, 1);
......
...@@ -253,12 +253,17 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba) ...@@ -253,12 +253,17 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba)
{ {
int ret = 0; int ret = 0;
struct ufs_qcom_host *host = ufshcd_get_variant(hba); struct ufs_qcom_host *host = ufshcd_get_variant(hba);
bool reenable_intr = false;
if (!host->core_reset) { if (!host->core_reset) {
dev_warn(hba->dev, "%s: reset control not set\n", __func__); dev_warn(hba->dev, "%s: reset control not set\n", __func__);
goto out; goto out;
} }
reenable_intr = hba->is_irq_enabled;
disable_irq(hba->irq);
hba->is_irq_enabled = false;
ret = reset_control_assert(host->core_reset); ret = reset_control_assert(host->core_reset);
if (ret) { if (ret) {
dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n", dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
...@@ -280,6 +285,11 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba) ...@@ -280,6 +285,11 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba)
usleep_range(1000, 1100); usleep_range(1000, 1100);
if (reenable_intr) {
enable_irq(hba->irq);
hba->is_irq_enabled = true;
}
out: out:
return ret; return ret;
} }
......
...@@ -95,8 +95,6 @@ ...@@ -95,8 +95,6 @@
16, 4, buf, __len, false); \ 16, 4, buf, __len, false); \
} while (0) } while (0)
static bool early_suspend;
int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
const char *prefix) const char *prefix)
{ {
...@@ -1535,7 +1533,7 @@ static ssize_t ufshcd_clkscale_enable_show(struct device *dev, ...@@ -1535,7 +1533,7 @@ static ssize_t ufshcd_clkscale_enable_show(struct device *dev,
{ {
struct ufs_hba *hba = dev_get_drvdata(dev); struct ufs_hba *hba = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", hba->clk_scaling.is_enabled); return sysfs_emit(buf, "%d\n", hba->clk_scaling.is_enabled);
} }
static ssize_t ufshcd_clkscale_enable_store(struct device *dev, static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
...@@ -4987,6 +4985,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) ...@@ -4987,6 +4985,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
* UFS device needs urgent BKOPs. * UFS device needs urgent BKOPs.
*/ */
if (!hba->pm_op_in_progress && if (!hba->pm_op_in_progress &&
!ufshcd_eh_in_progress(hba) &&
ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) && ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&
schedule_work(&hba->eeh_work)) { schedule_work(&hba->eeh_work)) {
/* /*
...@@ -5784,13 +5783,20 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) ...@@ -5784,13 +5783,20 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
ufshcd_suspend_clkscaling(hba); ufshcd_suspend_clkscaling(hba);
ufshcd_clk_scaling_allow(hba, false); ufshcd_clk_scaling_allow(hba, false);
} }
ufshcd_scsi_block_requests(hba);
/* Drain ufshcd_queuecommand() */
down_write(&hba->clk_scaling_lock);
up_write(&hba->clk_scaling_lock);
cancel_work_sync(&hba->eeh_work);
} }
static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
{ {
ufshcd_scsi_unblock_requests(hba);
ufshcd_release(hba); ufshcd_release(hba);
if (ufshcd_is_clkscaling_supported(hba)) if (ufshcd_is_clkscaling_supported(hba))
ufshcd_clk_scaling_suspend(hba, false); ufshcd_clk_scaling_suspend(hba, false);
ufshcd_clear_ua_wluns(hba);
pm_runtime_put(hba->dev); pm_runtime_put(hba->dev);
} }
...@@ -5882,8 +5888,8 @@ static void ufshcd_err_handler(struct work_struct *work) ...@@ -5882,8 +5888,8 @@ static void ufshcd_err_handler(struct work_struct *work)
spin_unlock_irqrestore(hba->host->host_lock, flags); spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_err_handling_prepare(hba); ufshcd_err_handling_prepare(hba);
spin_lock_irqsave(hba->host->host_lock, flags); spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_scsi_block_requests(hba); if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
hba->ufshcd_state = UFSHCD_STATE_RESET; hba->ufshcd_state = UFSHCD_STATE_RESET;
/* Complete requests that have door-bell cleared by h/w */ /* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba); ufshcd_complete_requests(hba);
...@@ -6042,12 +6048,8 @@ static void ufshcd_err_handler(struct work_struct *work) ...@@ -6042,12 +6048,8 @@ static void ufshcd_err_handler(struct work_struct *work)
} }
ufshcd_clear_eh_in_progress(hba); ufshcd_clear_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags); spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_scsi_unblock_requests(hba);
ufshcd_err_handling_unprepare(hba); ufshcd_err_handling_unprepare(hba);
up(&hba->host_sem); up(&hba->host_sem);
if (!err && needs_reset)
ufshcd_clear_ua_wluns(hba);
} }
/** /**
...@@ -7858,6 +7860,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) ...@@ -7858,6 +7860,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
unsigned long flags; unsigned long flags;
ktime_t start = ktime_get(); ktime_t start = ktime_get();
hba->ufshcd_state = UFSHCD_STATE_RESET;
ret = ufshcd_link_startup(hba); ret = ufshcd_link_startup(hba);
if (ret) if (ret)
goto out; goto out;
...@@ -8972,11 +8976,6 @@ int ufshcd_system_suspend(struct ufs_hba *hba) ...@@ -8972,11 +8976,6 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
int ret = 0; int ret = 0;
ktime_t start = ktime_get(); ktime_t start = ktime_get();
if (!hba) {
early_suspend = true;
return 0;
}
down(&hba->host_sem); down(&hba->host_sem);
if (!hba->is_powered) if (!hba->is_powered)
...@@ -9028,14 +9027,6 @@ int ufshcd_system_resume(struct ufs_hba *hba) ...@@ -9028,14 +9027,6 @@ int ufshcd_system_resume(struct ufs_hba *hba)
int ret = 0; int ret = 0;
ktime_t start = ktime_get(); ktime_t start = ktime_get();
if (!hba)
return -EINVAL;
if (unlikely(early_suspend)) {
early_suspend = false;
down(&hba->host_sem);
}
if (!hba->is_powered || pm_runtime_suspended(hba->dev)) if (!hba->is_powered || pm_runtime_suspended(hba->dev))
/* /*
* Let the runtime resume take care of resuming * Let the runtime resume take care of resuming
...@@ -9068,9 +9059,6 @@ int ufshcd_runtime_suspend(struct ufs_hba *hba) ...@@ -9068,9 +9059,6 @@ int ufshcd_runtime_suspend(struct ufs_hba *hba)
int ret = 0; int ret = 0;
ktime_t start = ktime_get(); ktime_t start = ktime_get();
if (!hba)
return -EINVAL;
if (!hba->is_powered) if (!hba->is_powered)
goto out; goto out;
else else
...@@ -9109,9 +9097,6 @@ int ufshcd_runtime_resume(struct ufs_hba *hba) ...@@ -9109,9 +9097,6 @@ int ufshcd_runtime_resume(struct ufs_hba *hba)
int ret = 0; int ret = 0;
ktime_t start = ktime_get(); ktime_t start = ktime_get();
if (!hba)
return -EINVAL;
if (!hba->is_powered) if (!hba->is_powered)
goto out; goto out;
else else
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Maintained by: Jim Gill <jgill@vmware.com>
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Maintained by: Jim Gill <jgill@vmware.com>
*
*/ */
#ifndef _VMW_PVSCSI_H_ #ifndef _VMW_PVSCSI_H_
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment