summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aacraid/linit.c13
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h8
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c63
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c1
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c89
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c23
-rw-r--r--drivers/scsi/libiscsi.c22
-rw-r--r--drivers/scsi/libiscsi_tcp.c11
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c21
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/scsi_lib.c15
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c2
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c6
-rw-r--r--drivers/scsi/ufs/ufs-hisi.c11
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c2
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.h2
-rw-r--r--drivers/scsi/ufs/ufshcd.h2
-rw-r--r--drivers/scsi/virtio_scsi.c2
25 files changed, 244 insertions, 75 deletions
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index a45f81ec80ce..8e28a505f7e8 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -413,13 +413,16 @@ static int aac_slave_configure(struct scsi_device *sdev)
if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS && aac->sa_firmware) {
devtype = aac->hba_map[chn][tid].devtype;
- if (devtype == AAC_DEVTYPE_NATIVE_RAW)
+ if (devtype == AAC_DEVTYPE_NATIVE_RAW) {
depth = aac->hba_map[chn][tid].qd_limit;
- else if (devtype == AAC_DEVTYPE_ARC_RAW)
+ set_timeout = 1;
+ goto common_config;
+ }
+ if (devtype == AAC_DEVTYPE_ARC_RAW) {
set_qd_dev_type = true;
-
- set_timeout = 1;
- goto common_config;
+ set_timeout = 1;
+ goto common_config;
+ }
}
if (aac->jbod && (sdev->type == TYPE_DISK))
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 6c87bd34509a..9bfa9f12d81e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
#include <linux/dmapool.h>
#include <linux/iopoll.h>
#include <linux/lcm.h>
+#include <linux/libata.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_address.h>
@@ -94,6 +95,11 @@ enum {
PORT_TYPE_SATA = (1U << 0),
};
+enum dev_status {
+ HISI_SAS_DEV_INIT,
+ HISI_SAS_DEV_NORMAL,
+};
+
enum {
HISI_SAS_INT_ABT_CMD = 0,
HISI_SAS_INT_ABT_DEV = 1,
@@ -161,6 +167,7 @@ struct hisi_sas_phy {
u8 in_reset;
u8 reserved[2];
u32 phy_type;
+ u32 code_violation_err_count;
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
};
@@ -194,6 +201,7 @@ struct hisi_sas_device {
struct hisi_sas_dq *dq;
struct list_head list;
enum sas_device_type dev_type;
+ enum dev_status dev_status;
int device_id;
int sata_idx;
spinlock_t lock; /* For protecting slots */
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 13ca5a0bdf6b..14bac4966c87 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -10,6 +10,7 @@
*/
#include "hisi_sas.h"
+#include "../libsas/sas_internal.h"
#define DRV_NAME "hisi_sas"
#define DEV_IS_GONE(dev) \
@@ -707,6 +708,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
hisi_hba->devices[i].device_id = i;
sas_dev = &hisi_hba->devices[i];
+ sas_dev->dev_status = HISI_SAS_DEV_INIT;
sas_dev->dev_type = device->dev_type;
sas_dev->hisi_hba = hisi_hba;
sas_dev->sas_device = device;
@@ -731,6 +733,8 @@ static int hisi_sas_init_device(struct domain_device *device)
struct hisi_sas_tmf_task tmf_task;
int retry = HISI_SAS_SRST_ATA_DISK_CNT;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct device *dev = hisi_hba->dev;
+ struct sas_phy *local_phy;
switch (device->dev_type) {
case SAS_END_DEVICE:
@@ -746,6 +750,31 @@ static int hisi_sas_init_device(struct domain_device *device)
case SAS_SATA_PM:
case SAS_SATA_PM_PORT:
case SAS_SATA_PENDING:
+ /*
+ * send HARD RESET to clear previous affiliation of
+ * STP target port
+ */
+ local_phy = sas_get_local_phy(device);
+ if (!scsi_is_sas_phy_local(local_phy)) {
+ unsigned long deadline = ata_deadline(jiffies, 20000);
+ struct sata_device *sata_dev = &device->sata_dev;
+ struct ata_host *ata_host = sata_dev->ata_host;
+ struct ata_port_operations *ops = ata_host->ops;
+ struct ata_port *ap = sata_dev->ap;
+ struct ata_link *link;
+ unsigned int classes;
+
+ ata_for_each_link(link, ap, EDGE)
+ rc = ops->hardreset(link, &classes,
+ deadline);
+ }
+ sas_put_local_phy(local_phy);
+ if (rc) {
+ dev_warn(dev, "SATA disk hardreset fail: 0x%x\n",
+ rc);
+ return rc;
+ }
+
while (retry-- > 0) {
rc = hisi_sas_softreset_ata_disk(device);
if (!rc)
@@ -808,6 +837,7 @@ static int hisi_sas_dev_found(struct domain_device *device)
rc = hisi_sas_init_device(device);
if (rc)
goto err_out;
+ sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
return 0;
err_out:
@@ -980,7 +1010,8 @@ static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
- task->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (!slot->is_internal && task->task_proto != SAS_PROTOCOL_SMP)
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
}
@@ -1713,20 +1744,23 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun)
static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
{
struct sas_phy *local_phy = sas_get_local_phy(device);
- int rc, reset_type = (device->dev_type == SAS_SATA_DEV ||
- (device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number];
struct hisi_sas_phy *phy = container_of(sas_phy,
struct hisi_sas_phy, sas_phy);
DECLARE_COMPLETION_ONSTACK(phyreset);
+ int rc, reset_type;
if (scsi_is_sas_phy_local(local_phy)) {
phy->in_reset = 1;
phy->reset_completion = &phyreset;
}
+ reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT ||
+ !dev_is_sata(device)) ? 1 : 0;
+
rc = sas_phy_reset(local_phy, reset_type);
sas_put_local_phy(local_phy);
@@ -1742,8 +1776,13 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
/* report PHY down if timed out */
if (!ret)
hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
- } else
+ } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) {
+ /*
+ * If in init state, we rely on caller to wait for link to be
+ * ready; otherwise, delay.
+ */
msleep(2000);
+ }
return rc;
}
@@ -1762,6 +1801,12 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
}
hisi_sas_dereg_device(hisi_hba, device);
+ if (dev_is_sata(device)) {
+ rc = hisi_sas_softreset_ata_disk(device);
+ if (rc)
+ return TMF_RESP_FUNC_FAILED;
+ }
+
rc = hisi_sas_debug_I_T_nexus_reset(device);
if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
@@ -2125,9 +2170,18 @@ static int hisi_sas_write_gpio(struct sas_ha_struct *sha, u8 reg_type,
static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
{
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ struct sas_phy *sphy = sas_phy->phy;
+ struct sas_phy_data *d = sphy->hostdata;
+
phy->phy_attached = 0;
phy->phy_type = 0;
phy->port = NULL;
+
+ if (d->enable)
+ sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+ else
+ sphy->negotiated_linkrate = SAS_PHY_DISABLED;
}
void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
@@ -2253,6 +2307,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba)
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
hisi_hba->devices[i].device_id = i;
+ hisi_hba->devices[i].dev_status = HISI_SAS_DEV_INIT;
}
for (i = 0; i < hisi_hba->queue_count; i++) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index e40cc6b3b67b..89160ab3efb0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -868,6 +868,7 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
hisi_hba->devices[i].device_id = i;
sas_dev = &hisi_hba->devices[i];
+ sas_dev->dev_status = HISI_SAS_DEV_INIT;
sas_dev->dev_type = device->dev_type;
sas_dev->hisi_hba = hisi_hba;
sas_dev->sas_device = device;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 9ec8848ec541..086695a4099f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -129,6 +129,7 @@
#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
#define CMD_HDR_PIR_OFF 8
#define CMD_HDR_PIR_MSK (0x1 << CMD_HDR_PIR_OFF)
+#define SERDES_CFG (PORT_BASE + 0x1c)
#define SL_CFG (PORT_BASE + 0x84)
#define AIP_LIMIT (PORT_BASE + 0x90)
#define SL_CONTROL (PORT_BASE + 0x94)
@@ -181,6 +182,8 @@
#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
#define CHL_INT2 (PORT_BASE + 0x1bc)
#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
+#define CHL_INT2_RX_DISP_ERR_OFF 28
+#define CHL_INT2_RX_CODE_ERR_OFF 29
#define CHL_INT2_RX_INVLD_DW_OFF 30
#define CHL_INT2_STP_LINK_TIMEOUT_OFF 31
#define CHL_INT0_MSK (PORT_BASE + 0x1c0)
@@ -523,6 +526,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
}
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
prog_phy_link_rate);
+ hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
@@ -544,6 +548,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01);
hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32);
+ hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME,
+ 0x30f4240);
/* used for 12G negotiate */
hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff);
@@ -1344,7 +1350,8 @@ static void prep_abort_v3_hw(struct hisi_hba *hisi_hba,
static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
{
- int i, res;
+ int i;
+ irqreturn_t res;
u32 context, port_id, link_rate;
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -1575,6 +1582,39 @@ static void handle_chl_int1_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT1, irq_value);
}
+static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ struct sas_phy *sphy = sas_phy->phy;
+ unsigned long flags;
+ u32 reg_value;
+
+ spin_lock_irqsave(&phy->lock, flags);
+
+ /* loss dword sync */
+ reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
+ sphy->loss_of_dword_sync_count += reg_value;
+
+ /* phy reset problem */
+ reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
+ sphy->phy_reset_problem_count += reg_value;
+
+ /* invalid dword */
+ reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
+ sphy->invalid_dword_count += reg_value;
+
+ /* disparity err */
+ reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
+ sphy->running_disparity_error_count += reg_value;
+
+ /* code violation error */
+ reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_CODE_ERR);
+ phy->code_violation_err_count += reg_value;
+
+ spin_unlock_irqrestore(&phy->lock, flags);
+}
+
static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
u32 irq_msk = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2_MSK);
@@ -1582,6 +1622,9 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct pci_dev *pci_dev = hisi_hba->pci_dev;
struct device *dev = hisi_hba->dev;
+ static const u32 msk = BIT(CHL_INT2_RX_DISP_ERR_OFF) |
+ BIT(CHL_INT2_RX_CODE_ERR_OFF) |
+ BIT(CHL_INT2_RX_INVLD_DW_OFF);
irq_value &= ~irq_msk;
if (!irq_value)
@@ -1602,6 +1645,25 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
}
+ if (pci_dev->revision > 0x20 && (irq_value & msk)) {
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ struct sas_phy *sphy = sas_phy->phy;
+
+ phy_get_events_v3_hw(hisi_hba, phy_no);
+
+ if (irq_value & BIT(CHL_INT2_RX_INVLD_DW_OFF))
+ dev_info(dev, "phy%d invalid dword cnt: %u\n", phy_no,
+ sphy->invalid_dword_count);
+
+ if (irq_value & BIT(CHL_INT2_RX_CODE_ERR_OFF))
+ dev_info(dev, "phy%d code violation cnt: %u\n", phy_no,
+ phy->code_violation_err_count);
+
+ if (irq_value & BIT(CHL_INT2_RX_DISP_ERR_OFF))
+ dev_info(dev, "phy%d disparity error cnt: %u\n", phy_no,
+ sphy->running_disparity_error_count);
+ }
+
if ((irq_value & BIT(CHL_INT2_RX_INVLD_DW_OFF)) &&
(pci_dev->revision == 0x20)) {
u32 reg_value;
@@ -2230,31 +2292,6 @@ static u32 get_phys_state_v3_hw(struct hisi_hba *hisi_hba)
return hisi_sas_read32(hisi_hba, PHY_STATE);
}
-static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
-{
- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_phy *sphy = sas_phy->phy;
- u32 reg_value;
-
- /* loss dword sync */
- reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
- sphy->loss_of_dword_sync_count += reg_value;
-
- /* phy reset problem */
- reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
- sphy->phy_reset_problem_count += reg_value;
-
- /* invalid dword */
- reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
- sphy->invalid_dword_count += reg_value;
-
- /* disparity err */
- reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
- sphy->running_disparity_error_count += reg_value;
-
-}
-
static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 1135e74646e2..8cec5230fe31 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -96,6 +96,7 @@ static int client_reserve = 1;
static char partition_name[96] = "UNKNOWN";
static unsigned int partition_number = -1;
static LIST_HEAD(ibmvscsi_head);
+static DEFINE_SPINLOCK(ibmvscsi_driver_lock);
static struct scsi_transport_template *ibmvscsi_transport_template;
@@ -2270,7 +2271,9 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
dev_set_drvdata(&vdev->dev, hostdata);
+ spin_lock(&ibmvscsi_driver_lock);
list_add_tail(&hostdata->host_list, &ibmvscsi_head);
+ spin_unlock(&ibmvscsi_driver_lock);
return 0;
add_srp_port_failed:
@@ -2292,15 +2295,27 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
static int ibmvscsi_remove(struct vio_dev *vdev)
{
struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev);
- list_del(&hostdata->host_list);
- unmap_persist_bufs(hostdata);
+ unsigned long flags;
+
+ srp_remove_host(hostdata->host);
+ scsi_remove_host(hostdata->host);
+
+ purge_requests(hostdata, DID_ERROR);
+
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
release_event_pool(&hostdata->pool, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+
ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
max_events);
kthread_stop(hostdata->work_thread);
- srp_remove_host(hostdata->host);
- scsi_remove_host(hostdata->host);
+ unmap_persist_bufs(hostdata);
+
+ spin_lock(&ibmvscsi_driver_lock);
+ list_del(&hostdata->host_list);
+ spin_unlock(&ibmvscsi_driver_lock);
+
scsi_host_put(hostdata->host);
return 0;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 21309d5b456d..e893949a3d11 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -798,7 +798,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
* @datalen: len of buffer
*
* iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
- * then completes the command and task.
+ * then completes the command and task. called under back_lock
**/
static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
struct iscsi_task *task, char *data,
@@ -894,6 +894,9 @@ out:
* @conn: iscsi connection
* @hdr: iscsi pdu
* @task: scsi command task
+ *
+ * iscsi_data_in_rsp sets up the scsi_cmnd fields based on the data received
+ * then completes the command and task. called under back_lock
**/
static void
iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
@@ -978,6 +981,16 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
return 0;
}
+/**
+ * iscsi_nop_out_rsp - SCSI NOP Response processing
+ * @task: scsi command task
+ * @nop: the nop structure
+ * @data: where to put the data
+ * @datalen: length of data
+ *
+ * iscsi_nop_out_rsp handles nop response from use or
+ * from user space. called under back_lock
+ **/
static int iscsi_nop_out_rsp(struct iscsi_task *task,
struct iscsi_nopin *nop, char *data, int datalen)
{
@@ -1750,7 +1763,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
return 0;
prepd_reject:
+ spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
+ spin_unlock_bh(&session->back_lock);
reject:
spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
@@ -1758,7 +1773,9 @@ reject:
return SCSI_MLQUEUE_TARGET_BUSY;
prepd_fault:
+ spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
+ spin_unlock_bh(&session->back_lock);
fault:
spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
@@ -3075,8 +3092,9 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
state = ISCSI_TASK_ABRT_SESS_RECOV;
if (task->state == ISCSI_TASK_PENDING)
state = ISCSI_TASK_COMPLETED;
+ spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, state);
-
+ spin_unlock_bh(&session->back_lock);
}
}
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 9923e9e3b884..c3fe3f3a78f5 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -129,12 +129,17 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
BUG_ON(sg->length == 0);
/*
+ * We always map for the recv path.
+ *
* If the page count is greater than one it is ok to send
* to the network layer's zero copy send path. If not we
- * have to go the slow sendmsg path. We always map for the
- * recv path.
+ * have to go the slow sendmsg path.
+ *
+ * Same goes for slab pages: skb_can_coalesce() allows
+ * coalescing neighboring slab objects into a single frag which
+ * triggers one of hardened usercopy checks.
*/
- if (page_count(sg_page(sg)) >= 1 && !recv)
+ if (!recv && page_count(sg_page(sg)) >= 1 && !PageSlab(sg_page(sg)))
return;
if (recv) {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 3b5873f6751e..7fcdaed3fa94 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4090,7 +4090,7 @@ lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc)
/* Sanity check to ensure our sizing is right for both SCSI and NVME */
if (sizeof(struct lpfc_io_buf) > LPFC_COMMON_IO_BUF_SZ) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
- "6426 Common buffer size %ld exceeds %d\n",
+ "6426 Common buffer size %zd exceeds %d\n",
sizeof(struct lpfc_io_buf),
LPFC_COMMON_IO_BUF_SZ);
return 0;
@@ -10052,7 +10052,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
{
struct pci_dev *pdev = phba->pcidev;
unsigned long bar0map_len, bar1map_len, bar2map_len;
- int error = -ENODEV;
+ int error;
uint32_t if_type;
if (!pdev)
@@ -10071,7 +10071,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
*/
if (pci_read_config_dword(pdev, LPFC_SLI_INTF,
&phba->sli4_hba.sli_intf.word0)) {
- return error;
+ return -ENODEV;
}
/* There is no SLI3 failback for SLI4 devices. */
@@ -10081,7 +10081,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
"2894 SLI_INTF reg contents invalid "
"sli_intf reg 0x%x\n",
phba->sli4_hba.sli_intf.word0);
- return error;
+ return -ENODEV;
}
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
@@ -10105,7 +10105,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for SLI4 PCI config "
"registers.\n");
- goto out;
+ return -ENODEV;
}
phba->pci_bar0_memmap_p = phba->sli4_hba.conf_regs_memmap_p;
/* Set up BAR0 PCI config space register memory map */
@@ -10116,7 +10116,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
dev_printk(KERN_ERR, &pdev->dev,
"FATAL - No BAR0 mapping for SLI4, if_type 2\n");
- goto out;
+ return -ENODEV;
}
phba->sli4_hba.conf_regs_memmap_p =
ioremap(phba->pci_bar0_map, bar0map_len);
@@ -10124,7 +10124,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for SLI4 PCI config "
"registers.\n");
- goto out;
+ return -ENODEV;
}
lpfc_sli4_bar0_register_memmap(phba, if_type);
}
@@ -10170,6 +10170,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
if (!phba->sli4_hba.drbl_regs_memmap_p) {
dev_err(&pdev->dev,
"ioremap failed for SLI4 HBA doorbell registers.\n");
+ error = -ENOMEM;
goto out_iounmap_conf;
}
phba->pci_bar2_memmap_p = phba->sli4_hba.drbl_regs_memmap_p;
@@ -10219,6 +10220,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
if (!phba->sli4_hba.dpp_regs_memmap_p) {
dev_err(&pdev->dev,
"ioremap failed for SLI4 HBA dpp registers.\n");
+ error = -ENOMEM;
goto out_iounmap_ctrl;
}
phba->pci_bar4_memmap_p = phba->sli4_hba.dpp_regs_memmap_p;
@@ -10249,7 +10251,7 @@ out_iounmap_ctrl:
iounmap(phba->sli4_hba.ctrl_regs_memmap_p);
out_iounmap_conf:
iounmap(phba->sli4_hba.conf_regs_memmap_p);
-out:
+
return error;
}
@@ -11137,7 +11139,8 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
lpfc_sli4_ras_dma_free(phba);
/* Stop the SLI4 device port */
- phba->pport->work_port_events = 0;
+ if (phba->pport)
+ phba->pport->work_port_events = 0;
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 55ab9d3ee4ba..1aa00d2c3f74 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -965,7 +965,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
struct lpfc_nodelist *ndlp;
struct lpfc_nvme_fcpreq_priv *freqpriv;
struct lpfc_nvme_lport *lport;
- uint32_t code, status, idx, cpu;
+ uint32_t code, status, idx;
uint16_t cid, sqhd, data;
uint32_t *ptr;
@@ -1138,6 +1138,7 @@ out_err:
lpfc_nvme_ktime(phba, lpfc_ncmd);
}
if (phba->cpucheck_on & LPFC_CHECK_NVME_IO) {
+ uint32_t cpu;
idx = lpfc_ncmd->cur_iocbq.hba_wqidx;
cpu = smp_processor_id();
if (cpu < LPFC_CHECK_CPU_CNT) {
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index d0817facdae3..57b4a463b589 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -9881,7 +9881,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
* The WQE can be either 64 or 128 bytes,
*/
- lockdep_assert_held(&phba->hbalock);
+ lockdep_assert_held(&pring->ring_lock);
if (piocb->sli4_xritag == NO_XRI) {
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index dace907744a5..293f5cf524d7 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3924,12 +3924,12 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
/*
* The cur_state should not last for more than max_wait secs
*/
- for (i = 0; i < max_wait; i++) {
+ for (i = 0; i < max_wait * 50; i++) {
curr_abs_state = instance->instancet->
read_fw_status_reg(instance);
if (abs_state == curr_abs_state) {
- msleep(1000);
+ msleep(20);
} else
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 2eb1ae721a7d..f928c4d3a1ef 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1652,6 +1652,8 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr,
}
rval = kstrtol(buf, 10, &type);
+ if (rval)
+ return rval;
speed = type;
if (type == 40 || type == 80 || type == 160 ||
type == 320) {
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index ead17288e2a7..5819a45ac5ef 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -193,6 +193,8 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
for (i = 0; i < vha->hw->max_qpairs; i++) {
qpair = vha->hw->queue_pair_map[i];
+ if (!qpair)
+ continue;
qla_core_sbt_cmd += qpair->tgt_counters.qla_core_sbt_cmd;
core_qla_que_buf += qpair->tgt_counters.core_qla_que_buf;
qla_core_ret_ctio += qpair->tgt_counters.qla_core_ret_ctio;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 420045155ba0..0c700b140ce7 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -4991,6 +4991,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
if ((domain & 0xf0) == 0xf0)
continue;
+ /* Bypass if not same domain and area of adapter. */
+ if (area && domain && ((area != vha->d_id.b.area) ||
+ (domain != vha->d_id.b.domain)) &&
+ (ha->current_topology == ISP_CFG_NL))
+ continue;
+
+
/* Bypass invalid local loop ID. */
if (loop_id > LAST_LOCAL_LOOP_ID)
continue;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 63f8e3c19841..456a41d2e2c6 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1132,7 +1132,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
/* if initiator doing write or target doing read */
if (direction_to_device) {
for_each_sg(sgl, sg, tot_dsds, i) {
- dma_addr_t sle_phys = sg_phys(sg);
+ u64 sle_phys = sg_phys(sg);
/* If SGE addr + len flips bits in upper 32-bits */
if (MSD(sle_phys + sg->length) ^ MSD(sle_phys)) {
@@ -1178,7 +1178,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe023,
"%s: sg[%x] (phys=%llx sglen=%x) ldma_sg_len: %x dif_bundl_len: %x ldma_needed: %x\n",
- __func__, i, sg_phys(sg), sglen, ldma_sg_len,
+ __func__, i, (u64)sg_phys(sg), sglen, ldma_sg_len,
difctx->dif_bundl_len, ldma_needed);
while (sglen) {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 677f82fdf56f..91f576d743fe 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1517,7 +1517,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
goto eh_reset_failed;
}
err = 2;
- if (do_reset(fcport, cmd->device->lun, blk_mq_rq_cpu(cmd->request) + 1)
+ if (do_reset(fcport, cmd->device->lun, 1)
!= QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x800c,
"do_reset failed for cmd=%p.\n", cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 20189675677a..601b9f1de267 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -585,10 +585,17 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
if (!blk_rq_is_scsi(req)) {
WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
cmd->flags &= ~SCMD_INITIALIZED;
- destroy_rcu_head(&cmd->rcu);
}
/*
+ * Calling rcu_barrier() is not necessary here because the
+ * SCSI error handler guarantees that the function called by
+ * call_rcu() has been called before scsi_end_request() is
+ * called.
+ */
+ destroy_rcu_head(&cmd->rcu);
+
+ /*
* In the MQ case the command gets freed by __blk_mq_end_request,
* so we have to do all cleanup that depends on it earlier.
*
@@ -2541,8 +2548,10 @@ void scsi_device_resume(struct scsi_device *sdev)
* device deleted during suspend)
*/
mutex_lock(&sdev->state_mutex);
- sdev->quiesced_by = NULL;
- blk_clear_pm_only(sdev->request_queue);
+ if (sdev->quiesced_by) {
+ sdev->quiesced_by = NULL;
+ blk_clear_pm_only(sdev->request_queue);
+ }
if (sdev->sdev_state == SDEV_QUIESCE)
scsi_device_set_state(sdev, SDEV_RUNNING);
mutex_unlock(&sdev->state_mutex);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 0508831d6fb9..0a82e93566dc 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -2200,6 +2200,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
/* flush running scans then delete devices */
flush_work(&session->scan_work);
+ /* flush running unbind operations */
+ flush_work(&session->unbind_work);
__iscsi_unbind_session(&session->unbind_work);
/* hw iscsi may not have removed all connections from session */
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 5d9ccbab7581..75ec43aa8df3 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2764,6 +2764,12 @@ static void pqi_process_raid_io_error(struct pqi_io_request *io_request)
sshdr.sense_key == HARDWARE_ERROR &&
sshdr.asc == 0x3e &&
sshdr.ascq == 0x1) {
+ struct pqi_ctrl_info *ctrl_info = shost_to_hba(scmd->device->host);
+ struct pqi_scsi_dev *device = scmd->device->hostdata;
+
+ if (printk_ratelimit())
+ scmd_printk(KERN_ERR, scmd, "received 'logical unit failure' from controller for scsi %d:%d:%d:%d\n",
+ ctrl_info->scsi_host->host_no, device->bus, device->target, device->lun);
pqi_take_device_offline(scmd->device, "RAID");
host_byte = DID_NO_CONNECT;
}
diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
index f2d3df357a97..0e855b5afe82 100644
--- a/drivers/scsi/ufs/ufs-hisi.c
+++ b/drivers/scsi/ufs/ufs-hisi.c
@@ -640,7 +640,7 @@ static int ufs_hi3670_init(struct ufs_hba *hba)
return 0;
}
-static struct ufs_hba_variant_ops ufs_hba_hi3660_vops = {
+static const struct ufs_hba_variant_ops ufs_hba_hi3660_vops = {
.name = "hi3660",
.init = ufs_hi3660_init,
.link_startup_notify = ufs_hisi_link_startup_notify,
@@ -649,7 +649,7 @@ static struct ufs_hba_variant_ops ufs_hba_hi3660_vops = {
.resume = ufs_hisi_resume,
};
-static struct ufs_hba_variant_ops ufs_hba_hi3670_vops = {
+static const struct ufs_hba_variant_ops ufs_hba_hi3670_vops = {
.name = "hi3670",
.init = ufs_hi3670_init,
.link_startup_notify = ufs_hisi_link_startup_notify,
@@ -669,13 +669,10 @@ MODULE_DEVICE_TABLE(of, ufs_hisi_of_match);
static int ufs_hisi_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
- struct ufs_hba_variant_ops *vops;
- struct device *dev = &pdev->dev;
- of_id = of_match_node(ufs_hisi_of_match, dev->of_node);
- vops = (struct ufs_hba_variant_ops *)of_id->data;
+ of_id = of_match_node(ufs_hisi_of_match, pdev->dev.of_node);
- return ufshcd_pltfrm_init(pdev, vops);
+ return ufshcd_pltfrm_init(pdev, of_id->data);
}
static int ufs_hisi_remove(struct platform_device *pdev)
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 895a9b5ac989..27213676329c 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -297,7 +297,7 @@ static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba)
* Returns 0 on success, non-zero value on failure
*/
int ufshcd_pltfrm_init(struct platform_device *pdev,
- struct ufs_hba_variant_ops *vops)
+ const struct ufs_hba_variant_ops *vops)
{
struct ufs_hba *hba;
void __iomem *mmio_base;
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h
index df64c4180340..1f29e1fd6d52 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.h
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.h
@@ -17,7 +17,7 @@
#include "ufshcd.h"
int ufshcd_pltfrm_init(struct platform_device *pdev,
- struct ufs_hba_variant_ops *vops);
+ const struct ufs_hba_variant_ops *vops);
void ufshcd_pltfrm_shutdown(struct platform_device *pdev);
#ifdef CONFIG_PM
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 69ba7445d2b3..ecfa898b9ccc 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -546,7 +546,7 @@ struct ufs_hba {
int nutrs;
int nutmrs;
u32 ufs_version;
- struct ufs_hba_variant_ops *vops;
+ const struct ufs_hba_variant_ops *vops;
void *priv;
unsigned int irq;
bool is_irq_enabled;
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 1a6f150cd2d8..8af01777d09c 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -586,7 +586,6 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc)
return FAILED;
memset(cmd, 0, sizeof(*cmd));
- cmd->sc = sc;
cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){
.type = VIRTIO_SCSI_T_TMF,
.subtype = cpu_to_virtio32(vscsi->vdev,
@@ -645,7 +644,6 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
return FAILED;
memset(cmd, 0, sizeof(*cmd));
- cmd->sc = sc;
cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){
.type = VIRTIO_SCSI_T_TMF,
.subtype = VIRTIO_SCSI_T_TMF_ABORT_TASK,