Commit 4da2b1eb authored by Finn Thain's avatar Finn Thain Committed by Martin K. Petersen

scsi: mac_esp: Replace bogus memory barrier with spinlock

Commit da244654 ("[SCSI] mac_esp: fix for quadras with two esp
chips") added mac_scsi_esp_intr() to handle the IRQ lines from a pair of
on-board ESP chips (a normal shared IRQ did not work).

Proper mutual exclusion was missing from that patch. This patch fixes
race conditions between comparison and assignment of esp_chips[]
pointers.
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 62d57f20
...@@ -55,6 +55,7 @@ struct mac_esp_priv { ...@@ -55,6 +55,7 @@ struct mac_esp_priv {
int error; int error;
}; };
static struct esp *esp_chips[2]; static struct esp *esp_chips[2];
static DEFINE_SPINLOCK(esp_chips_lock);
#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
platform_get_drvdata((struct platform_device *) \ platform_get_drvdata((struct platform_device *) \
...@@ -562,15 +563,18 @@ static int esp_mac_probe(struct platform_device *dev) ...@@ -562,15 +563,18 @@ static int esp_mac_probe(struct platform_device *dev)
} }
host->irq = IRQ_MAC_SCSI; host->irq = IRQ_MAC_SCSI;
esp_chips[dev->id] = esp;
mb(); /* The request_irq() call is intended to succeed for the first device
if (esp_chips[!dev->id] == NULL) { * and fail for the second device.
err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); */
if (err < 0) { err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
esp_chips[dev->id] = NULL; spin_lock(&esp_chips_lock);
goto fail_free_priv; if (err < 0 && esp_chips[!dev->id] == NULL) {
} spin_unlock(&esp_chips_lock);
goto fail_free_priv;
} }
esp_chips[dev->id] = esp;
spin_unlock(&esp_chips_lock);
err = scsi_esp_register(esp, &dev->dev); err = scsi_esp_register(esp, &dev->dev);
if (err) if (err)
...@@ -579,8 +583,13 @@ static int esp_mac_probe(struct platform_device *dev) ...@@ -579,8 +583,13 @@ static int esp_mac_probe(struct platform_device *dev)
return 0; return 0;
fail_free_irq: fail_free_irq:
if (esp_chips[!dev->id] == NULL) spin_lock(&esp_chips_lock);
esp_chips[dev->id] = NULL;
if (esp_chips[!dev->id] == NULL) {
spin_unlock(&esp_chips_lock);
free_irq(host->irq, esp); free_irq(host->irq, esp);
} else
spin_unlock(&esp_chips_lock);
fail_free_priv: fail_free_priv:
kfree(mep); kfree(mep);
fail_free_command_block: fail_free_command_block:
...@@ -599,9 +608,13 @@ static int esp_mac_remove(struct platform_device *dev) ...@@ -599,9 +608,13 @@ static int esp_mac_remove(struct platform_device *dev)
scsi_esp_unregister(esp); scsi_esp_unregister(esp);
spin_lock(&esp_chips_lock);
esp_chips[dev->id] = NULL; esp_chips[dev->id] = NULL;
if (!(esp_chips[0] || esp_chips[1])) if (esp_chips[!dev->id] == NULL) {
spin_unlock(&esp_chips_lock);
free_irq(irq, NULL); free_irq(irq, NULL);
} else
spin_unlock(&esp_chips_lock);
kfree(mep); kfree(mep);
......
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