Commit d4fc9683 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:
 "Three driver fixes. Two (alua and hpsa) are in hard to trigger
  attach/detach situations but the mp3sas one involves a polled to
  interrupt switch over that could trigger in any high IOPS situation"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: mpt3sas: Fix timeouts observed while reenabling IRQ
  scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
  scsi: hpsa: Fix memory leak in hpsa_init_one()
parents bf3e7628 5feed64f
...@@ -658,8 +658,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) ...@@ -658,8 +658,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(h, list_for_each_entry_rcu(h,
&tmp_pg->dh_list, node) { &tmp_pg->dh_list, node) {
/* h->sdev should always be valid */ if (!h->sdev)
BUG_ON(!h->sdev); continue;
h->sdev->access_state = desc[0]; h->sdev->access_state = desc[0];
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -705,7 +705,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) ...@@ -705,7 +705,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
pg->expiry = 0; pg->expiry = 0;
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(h, &pg->dh_list, node) { list_for_each_entry_rcu(h, &pg->dh_list, node) {
BUG_ON(!h->sdev); if (!h->sdev)
continue;
h->sdev->access_state = h->sdev->access_state =
(pg->state & SCSI_ACCESS_STATE_MASK); (pg->state & SCSI_ACCESS_STATE_MASK);
if (pg->pref) if (pg->pref)
...@@ -1147,7 +1148,6 @@ static void alua_bus_detach(struct scsi_device *sdev) ...@@ -1147,7 +1148,6 @@ static void alua_bus_detach(struct scsi_device *sdev)
spin_lock(&h->pg_lock); spin_lock(&h->pg_lock);
pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)); pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock));
rcu_assign_pointer(h->pg, NULL); rcu_assign_pointer(h->pg, NULL);
h->sdev = NULL;
spin_unlock(&h->pg_lock); spin_unlock(&h->pg_lock);
if (pg) { if (pg) {
spin_lock_irq(&pg->lock); spin_lock_irq(&pg->lock);
...@@ -1156,6 +1156,7 @@ static void alua_bus_detach(struct scsi_device *sdev) ...@@ -1156,6 +1156,7 @@ static void alua_bus_detach(struct scsi_device *sdev)
kref_put(&pg->kref, release_port_group); kref_put(&pg->kref, release_port_group);
} }
sdev->handler_data = NULL; sdev->handler_data = NULL;
synchronize_rcu();
kfree(h); kfree(h);
} }
......
...@@ -8855,7 +8855,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -8855,7 +8855,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* hook into SCSI subsystem */ /* hook into SCSI subsystem */
rc = hpsa_scsi_add_host(h); rc = hpsa_scsi_add_host(h);
if (rc) if (rc)
goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ goto clean8; /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
/* Monitor the controller for firmware lockups */ /* Monitor the controller for firmware lockups */
h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
...@@ -8870,6 +8870,8 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -8870,6 +8870,8 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
HPSA_EVENT_MONITOR_INTERVAL); HPSA_EVENT_MONITOR_INTERVAL);
return 0; return 0;
clean8: /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
kfree(h->lastlogicals);
clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */
hpsa_free_performant_mode(h); hpsa_free_performant_mode(h);
h->access.set_intr_mask(h, HPSA_INTR_OFF); h->access.set_intr_mask(h, HPSA_INTR_OFF);
......
...@@ -1740,6 +1740,13 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget) ...@@ -1740,6 +1740,13 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget)
reply_q->irq_poll_scheduled = false; reply_q->irq_poll_scheduled = false;
reply_q->irq_line_enable = true; reply_q->irq_line_enable = true;
enable_irq(reply_q->os_irq); enable_irq(reply_q->os_irq);
/*
* Go for one more round of processing the
* reply descriptor post queue incase if HBA
* Firmware has posted some reply descriptors
* while reenabling the IRQ.
*/
_base_process_reply_queue(reply_q);
} }
return num_entries; return num_entries;
......
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