summaryrefslogtreecommitdiff
path: root/drivers/scsi/mpi3mr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpi3mr')
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c9
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c47
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c8
3 files changed, 51 insertions, 13 deletions
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 31b19ed1528e..681868716ebd 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -9,6 +9,7 @@
#include "mpi3mr.h"
#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/sched/mm.h>
static int
mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, u16 reset_reason);
@@ -1287,11 +1288,14 @@ out_failed:
static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc)
{
struct kobj_uevent_env *env;
+ unsigned int noio_flag;
int ret;
+ noio_flag = memalloc_noio_save();
+
env = kzalloc_obj(*env);
if (!env)
- return;
+ goto out_restore;
ret = add_uevent_var(env, "DRIVER=%s", mrioc->driver_name);
if (ret)
@@ -1326,7 +1330,8 @@ static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc)
out_free:
kfree(env);
-
+out_restore:
+ memalloc_noio_restore(noio_flag);
}
/**
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index 402d1f35d214..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);
@@ -5172,7 +5197,7 @@ static enum scsi_qc_status mpi3mr_qcmd(struct Scsi_Host *shost,
/* Avoid error handling escalation when device is removed or blocked */
- if (scmd->device->host->shost_state == SHOST_RECOVERY &&
+ if (scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY &&
scmd->cmnd[0] == TEST_UNIT_READY &&
(stgt_priv_data->dev_removed || (dev_handle == MPI3MR_INVALID_DEV_HANDLE))) {
scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07);
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;
}