[SCSI] sym53c8xx: fixes two bugs related to chip reset
This patch fixes two bugs pointed by James Bottomley: 1. the if (!sym_data->io_reset). That variable is only ever filled by a stack based completion. If we find it non empty it means this code has been entered twice and we have a severe problem, so that should just become a BUG_ON(sym_data->io_reset). 2. sym_data->io_reset should be set to NULL before the routine is exited otherwise the PCI recovery code could end up completing what will be a bogus pointer into the stack. Big thanks to James Bottomley for help with the patch. Signed-off-by: Krzysztof Helt <krzysztof.h1@w.pl> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
committed by
James Bottomley
parent
3a0086a80a
commit
d9aa3af09c
@@ -609,22 +609,24 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
|
|||||||
*/
|
*/
|
||||||
#define WAIT_FOR_PCI_RECOVERY 35
|
#define WAIT_FOR_PCI_RECOVERY 35
|
||||||
if (pci_channel_offline(pdev)) {
|
if (pci_channel_offline(pdev)) {
|
||||||
struct completion *io_reset;
|
|
||||||
int finished_reset = 0;
|
int finished_reset = 0;
|
||||||
init_completion(&eh_done);
|
init_completion(&eh_done);
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
/* Make sure we didn't race */
|
/* Make sure we didn't race */
|
||||||
if (pci_channel_offline(pdev)) {
|
if (pci_channel_offline(pdev)) {
|
||||||
if (!sym_data->io_reset)
|
BUG_ON(sym_data->io_reset);
|
||||||
sym_data->io_reset = &eh_done;
|
sym_data->io_reset = &eh_done;
|
||||||
io_reset = sym_data->io_reset;
|
|
||||||
} else {
|
} else {
|
||||||
finished_reset = 1;
|
finished_reset = 1;
|
||||||
}
|
}
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
if (!finished_reset)
|
if (!finished_reset)
|
||||||
finished_reset = wait_for_completion_timeout(io_reset,
|
finished_reset = wait_for_completion_timeout
|
||||||
|
(sym_data->io_reset,
|
||||||
WAIT_FOR_PCI_RECOVERY*HZ);
|
WAIT_FOR_PCI_RECOVERY*HZ);
|
||||||
|
spin_lock_irq(shost->host_lock);
|
||||||
|
sym_data->io_reset = NULL;
|
||||||
|
spin_unlock_irq(shost->host_lock);
|
||||||
if (!finished_reset)
|
if (!finished_reset)
|
||||||
return SCSI_FAILED;
|
return SCSI_FAILED;
|
||||||
}
|
}
|
||||||
@@ -1879,7 +1881,6 @@ static void sym2_io_resume(struct pci_dev *pdev)
|
|||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
if (sym_data->io_reset)
|
if (sym_data->io_reset)
|
||||||
complete_all(sym_data->io_reset);
|
complete_all(sym_data->io_reset);
|
||||||
sym_data->io_reset = NULL;
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user