summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fnic/fnic_nvme.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc-core.c3
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c13
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c45
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c8
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c5
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c4
-rw-r--r--drivers/scsi/scsi_bsg.c47
8 files changed, 93 insertions, 34 deletions
diff --git a/drivers/scsi/fnic/fnic_nvme.c b/drivers/scsi/fnic/fnic_nvme.c
index b237948dcafd..00d9d5d439a3 100644
--- a/drivers/scsi/fnic/fnic_nvme.c
+++ b/drivers/scsi/fnic/fnic_nvme.c
@@ -2216,7 +2216,7 @@ int nvfnic_add_tport(struct fnic *fnic, struct fnic_tport_s *tport,
int nvfnic_add_lport(struct fnic *fnic)
{
- struct nvme_fc_port_info pinfo;
+ struct nvme_fc_port_info pinfo = {};
struct fnic_iport_s *iport = &fnic->iport;
int ret = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index b3bc3ce872d6..3534ac45e9b8 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -1894,7 +1894,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
}
/**
- * ibmvfc_relogin - Log back into the specified device
+ * ibmvfc_scsi_relogin - Log back into the specified device
* @sdev: scsi device struct
*
**/
@@ -4987,6 +4987,7 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
* ibmvfc_alloc_target - Allocate and initialize an ibmvfc target
* @vhost: ibmvfc host struct
* @target: Holds SCSI ID to allocate target forand the WWPN
+ * @protocol: protocol of the target to allocate
*
* Returns:
* 0 on success / other on failure
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index f0152b043e18..b95f187297ae 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1973,12 +1973,23 @@ megasas_set_nvme_device_properties(struct scsi_device *sdev,
{
struct megasas_instance *instance;
u32 mr_nvme_pg_size;
+ u64 max_prp_io;
instance = (struct megasas_instance *)sdev->host->hostdata;
mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
MR_DEFAULT_NVME_PAGE_SIZE);
- lim->max_hw_sectors = max_io_size / 512;
+ /*
+ * megasas_make_prp_nvme() builds the PRP list in cmd->sg_frame without
+ * bounding it against that buffer, and spends one entry per page of
+ * it on the chain pointer. Cap the transfer at what the buffer holds,
+ * less one page for lists that start off a page boundary.
+ */
+ max_prp_io = (u64)((instance->max_chain_frame_sz / sizeof(u64)) -
+ (instance->max_chain_frame_sz / mr_nvme_pg_size) - 1) *
+ mr_nvme_pg_size;
+
+ lim->max_hw_sectors = min_t(u64, max_io_size, max_prp_io) >> SECTOR_SHIFT;
lim->virt_boundary_mask = mr_nvme_pg_size - 1;
}
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index f80a21ec161b..0f7380448718 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -1094,10 +1094,13 @@ static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc)
{
struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next;
struct mpi3mr_stgt_priv_data *tgt_priv;
+ struct scsi_target *starget;
+ unsigned long flags;
dprint_reset(mrioc, "refresh target devices: check for removals\n");
list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list,
list) {
+ spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
if (((tgtdev->dev_handle == MPI3MR_INVALID_DEV_HANDLE) ||
tgtdev->is_hidden) &&
tgtdev->host_exposed && tgtdev->starget &&
@@ -1106,6 +1109,7 @@ static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc)
tgt_priv->dev_removed = 1;
atomic_set(&tgt_priv->block_io, 0);
}
+ spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
}
list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list,
@@ -1127,15 +1131,25 @@ static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc)
tgtdev = NULL;
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
if ((tgtdev->dev_handle != MPI3MR_INVALID_DEV_HANDLE) &&
- !tgtdev->is_hidden) {
- if (!tgtdev->host_exposed)
+ !tgtdev->is_hidden) {
+ if (!tgtdev->host_exposed) {
mpi3mr_report_tgtdev_to_host(mrioc,
- tgtdev->perst_id);
- else if (tgtdev->starget)
- starget_for_each_device(tgtdev->starget,
- (void *)tgtdev, mpi3mr_update_sdev);
- }
+ tgtdev->perst_id);
+ continue;
+ }
+ spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
+ starget = tgtdev->starget;
+ if (starget)
+ get_device(&starget->dev);
+ spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
+ if (starget) {
+ starget_for_each_device(starget, (void *)tgtdev,
+ mpi3mr_update_sdev);
+ put_device(&starget->dev);
+ }
+ }
}
+ dprint_reset(mrioc, "refresh target devices: done\n");
}
/**
@@ -1515,6 +1529,8 @@ static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc,
struct mpi3_device_page0 *dev_pg0)
{
struct mpi3mr_tgt_dev *tgtdev = NULL;
+ struct scsi_target *starget;
+ unsigned long flags;
u16 dev_handle = 0, perst_id = 0;
perst_id = le16_to_cpu(dev_pg0->persistent_id);
@@ -1535,9 +1551,18 @@ static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc,
mpi3mr_report_tgtdev_to_host(mrioc, perst_id);
if (tgtdev->is_hidden && tgtdev->host_exposed)
mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
- if (!tgtdev->is_hidden && tgtdev->host_exposed && tgtdev->starget)
- starget_for_each_device(tgtdev->starget, (void *)tgtdev,
- mpi3mr_update_sdev);
+ if (!tgtdev->is_hidden && tgtdev->host_exposed) {
+ spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
+ starget = tgtdev->starget;
+ if (starget)
+ get_device(&starget->dev);
+ spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
+ if (starget) {
+ starget_for_each_device(starget, (void *)tgtdev,
+ mpi3mr_update_sdev);
+ put_device(&starget->dev);
+ }
+ }
out:
if (tgtdev)
mpi3mr_tgtdev_put(tgtdev);
diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c
index 240f67a8e2e3..232af978d737 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
@@ -1428,9 +1428,15 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
}
port = sas_port_alloc_num(mr_sas_node->parent_dev);
+ if (!port) {
+ ioc_err(mrioc, "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ goto out_fail;
+ }
if ((sas_port_add(port))) {
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
+ sas_port_free(port);
goto out_fail;
}
@@ -1501,6 +1507,8 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
port_siblings)
list_del(&mr_sas_phy->port_siblings);
+ if (tgtdev)
+ mpi3mr_tgtdev_put(tgtdev);
kfree(mr_sas_port);
return NULL;
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index fed7aeffec58..1af25a22611a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -3238,7 +3238,10 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
* corresponding to high iops queues.
*/
if (ioc->high_iops_queues) {
- mask = cpumask_of_node(dev_to_node(&ioc->pdev->dev));
+ int node = dev_to_node(&ioc->pdev->dev);
+
+ mask = (node == NUMA_NO_NODE) ?
+ cpu_online_mask : cpumask_of_node(node);
for (index = 0; index < ioc->high_iops_queues;
index++) {
irq = pci_irq_vector(ioc->pdev, index);
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index e93ea76b565e..54b35893261a 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1029,8 +1029,8 @@ static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
&(pm8001_ha->irq_vector[i]));
if (rc) {
for (j = 0; j < i; j++) {
- free_irq(pci_irq_vector(pm8001_ha->pdev, i),
- &(pm8001_ha->irq_vector[i]));
+ free_irq(pci_irq_vector(pm8001_ha->pdev, j),
+ &pm8001_ha->irq_vector[j]);
}
pci_free_irq_vectors(pm8001_ha->pdev);
break;
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index e80dec53174e..5eec248a77a6 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -18,6 +18,7 @@ struct scsi_bsg_uring_cmd_pdu {
struct bio *bio; /* mapped user buffer, unmap in task work */
struct request *req; /* block request, freed in task work */
u64 response_addr; /* user space response buffer address */
+ u32 max_response_len; /* user response buffer size */
};
static_assert(sizeof(struct scsi_bsg_uring_cmd_pdu) <= sizeof_field(struct io_uring_cmd, pdu));
@@ -45,8 +46,8 @@ static void scsi_bsg_uring_task_cb(struct io_tw_req tw_req, io_tw_token_t tw)
if (scsi_status_is_check_condition(scmd->result)) {
driver_status = DRIVER_SENSE;
if (pdu->response_addr)
- sense_len_wr = min_t(u8, scmd->sense_len,
- SCSI_SENSE_BUFFERSIZE);
+ sense_len_wr = min_t(unsigned int, pdu->max_response_len,
+ scmd->sense_len);
}
if (sense_len_wr) {
@@ -76,12 +77,10 @@ static enum rq_end_io_ret scsi_bsg_uring_cmd_done(struct request *req,
static int scsi_bsg_map_user_buffer(struct request *req,
struct io_uring_cmd *ioucmd,
- unsigned int issue_flags, gfp_t gfp_mask)
+ unsigned int issue_flags, gfp_t gfp_mask,
+ bool is_write, u64 buf_addr,
+ unsigned long buf_len)
{
- const struct bsg_uring_cmd *cmd = io_uring_sqe128_cmd(ioucmd->sqe, struct bsg_uring_cmd);
- bool is_write = cmd->dout_xfer_len > 0;
- u64 buf_addr = is_write ? cmd->dout_xferp : cmd->din_xferp;
- unsigned long buf_len = is_write ? cmd->dout_xfer_len : cmd->din_xfer_len;
struct iov_iter iter;
int ret;
@@ -104,21 +103,28 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
unsigned int issue_flags, bool open_for_write)
{
struct scsi_bsg_uring_cmd_pdu *pdu = scsi_bsg_uring_cmd_pdu(ioucmd);
- const struct bsg_uring_cmd *cmd = io_uring_sqe128_cmd(ioucmd->sqe, struct bsg_uring_cmd);
+ const struct bsg_uring_cmd *cmd =
+ io_uring_sqe128_cmd(ioucmd->sqe, struct bsg_uring_cmd);
struct scsi_cmnd *scmd;
struct request *req;
blk_mq_req_flags_t blk_flags = 0;
gfp_t gfp_mask = GFP_KERNEL;
+ u64 request = READ_ONCE(cmd->request);
+ u32 request_len = READ_ONCE(cmd->request_len);
+ u64 dout_xferp = READ_ONCE(cmd->dout_xferp);
+ u32 dout_xfer_len = READ_ONCE(cmd->dout_xfer_len);
+ u64 din_xferp = READ_ONCE(cmd->din_xferp);
+ u32 din_xfer_len = READ_ONCE(cmd->din_xfer_len);
int ret;
if (cmd->protocol != BSG_PROTOCOL_SCSI ||
cmd->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
return -EINVAL;
- if (!cmd->request || cmd->request_len == 0)
+ if (!request || request_len == 0)
return -EINVAL;
- if (cmd->dout_xfer_len && cmd->din_xfer_len) {
+ if (dout_xfer_len && din_xfer_len) {
pr_warn_once("BIDI support in bsg has been removed.\n");
return -EOPNOTSUPP;
}
@@ -131,20 +137,20 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
gfp_mask = GFP_NOWAIT;
}
- req = scsi_alloc_request(q, cmd->dout_xfer_len ?
+ req = scsi_alloc_request(q, dout_xfer_len ?
REQ_OP_DRV_OUT : REQ_OP_DRV_IN, blk_flags);
if (IS_ERR(req))
return PTR_ERR(req);
scmd = blk_mq_rq_to_pdu(req);
- if (cmd->request_len > sizeof(scmd->cmnd)) {
+ if (request_len > sizeof(scmd->cmnd)) {
ret = -EINVAL;
goto out_free_req;
}
- scmd->cmd_len = cmd->request_len;
+ scmd->cmd_len = request_len;
scmd->allowed = SG_DEFAULT_RETRIES;
- if (copy_from_user(scmd->cmnd, uptr64(cmd->request), cmd->request_len)) {
+ if (copy_from_user(scmd->cmnd, uptr64(request), request_len)) {
ret = -EFAULT;
goto out_free_req;
}
@@ -155,11 +161,16 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
}
pdu->response_addr = cmd->response;
- scmd->sense_len = cmd->max_response_len ?
- min(cmd->max_response_len, SCSI_SENSE_BUFFERSIZE) : SCSI_SENSE_BUFFERSIZE;
+ pdu->max_response_len = cmd->max_response_len;
- if (cmd->dout_xfer_len || cmd->din_xfer_len) {
- ret = scsi_bsg_map_user_buffer(req, ioucmd, issue_flags, gfp_mask);
+ if (dout_xfer_len || din_xfer_len) {
+ bool is_write = dout_xfer_len > 0;
+ u64 buf_addr = is_write ? dout_xferp : din_xferp;
+ unsigned long buf_len = is_write ? dout_xfer_len : din_xfer_len;
+
+ ret = scsi_bsg_map_user_buffer(req, ioucmd, issue_flags,
+ gfp_mask, is_write, buf_addr,
+ buf_len);
if (ret)
goto out_free_req;
pdu->bio = req->bio;