Commit 1975b337 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:
 "Six minor fixes to device drivers and one to the multipath alua
  handler.

  The most extensive fix is the zfcp port remove prevention one, but
  it's impact is only s390"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: libsas: delete sas port if expander discover failed
  scsi: libsas: only clear phy->in_shutdown after shutdown event done
  scsi: scsi_dh_alua: Fix possible null-ptr-deref
  scsi: smartpqi: properly set both the DMA mask and the coherent DMA mask
  scsi: zfcp: fix to prevent port_remove with pure auto scan LUNs (only sdevs)
  scsi: zfcp: fix missing zfcp_port reference put on -EBUSY from port_remove
  scsi: libcxgbi: add a check for NULL pointer in cxgbi_check_route()
parents 7b3064f0 3b054179
...@@ -167,6 +167,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[]; ...@@ -167,6 +167,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[];
extern struct mutex zfcp_sysfs_port_units_mutex; extern struct mutex zfcp_sysfs_port_units_mutex;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[];
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
/* zfcp_unit.c */ /* zfcp_unit.c */
extern int zfcp_unit_add(struct zfcp_port *, u64); extern int zfcp_unit_add(struct zfcp_port *, u64);
......
...@@ -129,6 +129,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) ...@@ -129,6 +129,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
zfcp_sdev->erp_action.port = port; zfcp_sdev->erp_action.port = port;
mutex_lock(&zfcp_sysfs_port_units_mutex);
if (zfcp_sysfs_port_is_removing(port)) {
/* port is already gone */
mutex_unlock(&zfcp_sysfs_port_units_mutex);
put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
return -ENXIO;
}
mutex_unlock(&zfcp_sysfs_port_units_mutex);
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
if (unit) if (unit)
put_device(&unit->dev); put_device(&unit->dev);
......
...@@ -235,6 +235,53 @@ static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, ...@@ -235,6 +235,53 @@ static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
static void zfcp_sysfs_port_set_removing(struct zfcp_port *const port)
{
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
atomic_set(&port->units, -1);
}
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port)
{
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
return atomic_read(&port->units) == -1;
}
static bool zfcp_sysfs_port_in_use(struct zfcp_port *const port)
{
struct zfcp_adapter *const adapter = port->adapter;
unsigned long flags;
struct scsi_device *sdev;
bool in_use = true;
mutex_lock(&zfcp_sysfs_port_units_mutex);
if (atomic_read(&port->units) > 0)
goto unlock_port_units_mutex; /* zfcp_unit(s) under port */
spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
__shost_for_each_device(sdev, adapter->scsi_host) {
const struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
if (sdev->sdev_state == SDEV_DEL ||
sdev->sdev_state == SDEV_CANCEL)
continue;
if (zsdev->port != port)
continue;
/* alive scsi_device under port of interest */
goto unlock_host_lock;
}
/* port is about to be removed, so no more unit_add or slave_alloc */
zfcp_sysfs_port_set_removing(port);
in_use = false;
unlock_host_lock:
spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
unlock_port_units_mutex:
mutex_unlock(&zfcp_sysfs_port_units_mutex);
return in_use;
}
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -257,15 +304,11 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, ...@@ -257,15 +304,11 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
else else
retval = 0; retval = 0;
mutex_lock(&zfcp_sysfs_port_units_mutex); if (zfcp_sysfs_port_in_use(port)) {
if (atomic_read(&port->units) > 0) {
retval = -EBUSY; retval = -EBUSY;
mutex_unlock(&zfcp_sysfs_port_units_mutex); put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
goto out; goto out;
} }
/* port is about to be removed, so no more unit_add */
atomic_set(&port->units, -1);
mutex_unlock(&zfcp_sysfs_port_units_mutex);
write_lock_irq(&adapter->port_list_lock); write_lock_irq(&adapter->port_list_lock);
list_del(&port->list); list_del(&port->list);
......
...@@ -124,7 +124,7 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) ...@@ -124,7 +124,7 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
int retval = 0; int retval = 0;
mutex_lock(&zfcp_sysfs_port_units_mutex); mutex_lock(&zfcp_sysfs_port_units_mutex);
if (atomic_read(&port->units) == -1) { if (zfcp_sysfs_port_is_removing(port)) {
/* port is already gone */ /* port is already gone */
retval = -ENODEV; retval = -ENODEV;
goto out; goto out;
...@@ -168,8 +168,14 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) ...@@ -168,8 +168,14 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
write_lock_irq(&port->unit_list_lock); write_lock_irq(&port->unit_list_lock);
list_add_tail(&unit->list, &port->unit_list); list_add_tail(&unit->list, &port->unit_list);
write_unlock_irq(&port->unit_list_lock); write_unlock_irq(&port->unit_list_lock);
/*
* lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex
* due to zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc()
*/
mutex_unlock(&zfcp_sysfs_port_units_mutex);
zfcp_unit_scsi_scan(unit); zfcp_unit_scsi_scan(unit);
return retval;
out: out:
mutex_unlock(&zfcp_sysfs_port_units_mutex); mutex_unlock(&zfcp_sysfs_port_units_mutex);
......
...@@ -639,6 +639,10 @@ cxgbi_check_route(struct sockaddr *dst_addr, int ifindex) ...@@ -639,6 +639,10 @@ cxgbi_check_route(struct sockaddr *dst_addr, int ifindex)
if (ndev->flags & IFF_LOOPBACK) { if (ndev->flags & IFF_LOOPBACK) {
ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr); ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
if (!ndev) {
err = -ENETUNREACH;
goto rel_neigh;
}
mtu = ndev->mtu; mtu = ndev->mtu;
pr_info("rt dev %s, loopback -> %s, mtu %u.\n", pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
n->dev->name, ndev->name, mtu); n->dev->name, ndev->name, mtu);
......
...@@ -1160,10 +1160,8 @@ static int __init alua_init(void) ...@@ -1160,10 +1160,8 @@ static int __init alua_init(void)
int r; int r;
kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0); kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0);
if (!kaluad_wq) { if (!kaluad_wq)
/* Temporary failure, bypass */ return -ENOMEM;
return SCSI_DH_DEV_TEMP_BUSY;
}
r = scsi_register_device_handler(&alua_dh); r = scsi_register_device_handler(&alua_dh);
if (r != 0) { if (r != 0) {
......
...@@ -1019,6 +1019,8 @@ static struct domain_device *sas_ex_discover_expander( ...@@ -1019,6 +1019,8 @@ static struct domain_device *sas_ex_discover_expander(
list_del(&child->dev_list_node); list_del(&child->dev_list_node);
spin_unlock_irq(&parent->port->dev_list_lock); spin_unlock_irq(&parent->port->dev_list_lock);
sas_put_device(child); sas_put_device(child);
sas_port_delete(phy->port);
phy->port = NULL;
return NULL; return NULL;
} }
list_add_tail(&child->siblings, &parent->ex_dev.children); list_add_tail(&child->siblings, &parent->ex_dev.children);
......
...@@ -35,7 +35,6 @@ static void sas_phye_loss_of_signal(struct work_struct *work) ...@@ -35,7 +35,6 @@ static void sas_phye_loss_of_signal(struct work_struct *work)
struct asd_sas_event *ev = to_asd_sas_event(work); struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy; struct asd_sas_phy *phy = ev->phy;
phy->in_shutdown = 0;
phy->error = 0; phy->error = 0;
sas_deform_port(phy, 1); sas_deform_port(phy, 1);
} }
...@@ -45,7 +44,6 @@ static void sas_phye_oob_done(struct work_struct *work) ...@@ -45,7 +44,6 @@ static void sas_phye_oob_done(struct work_struct *work)
struct asd_sas_event *ev = to_asd_sas_event(work); struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy; struct asd_sas_phy *phy = ev->phy;
phy->in_shutdown = 0;
phy->error = 0; phy->error = 0;
} }
...@@ -126,6 +124,7 @@ static void sas_phye_shutdown(struct work_struct *work) ...@@ -126,6 +124,7 @@ static void sas_phye_shutdown(struct work_struct *work)
ret); ret);
} else } else
pr_notice("phy%d is not enabled, cannot shutdown\n", phy->id); pr_notice("phy%d is not enabled, cannot shutdown\n", phy->id);
phy->in_shutdown = 0;
} }
/* ---------- Phy class registration ---------- */ /* ---------- Phy class registration ---------- */
......
...@@ -7291,7 +7291,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info) ...@@ -7291,7 +7291,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
else else
mask = DMA_BIT_MASK(32); mask = DMA_BIT_MASK(32);
rc = dma_set_mask(&ctrl_info->pci_dev->dev, mask); rc = dma_set_mask_and_coherent(&ctrl_info->pci_dev->dev, mask);
if (rc) { if (rc) {
dev_err(&ctrl_info->pci_dev->dev, "failed to set DMA mask\n"); dev_err(&ctrl_info->pci_dev->dev, "failed to set DMA mask\n");
goto disable_device; goto disable_device;
......
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