Commit 4472e85a authored by David S. Miller's avatar David S. Miller

[QLOGICPTI]: Fix SMP locking, tested by Chris Ricker.

parent 2e33ed69
...@@ -319,7 +319,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -319,7 +319,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
risc_code_addr = 0x1000; /* all load addresses are at 0x1000 */ risc_code_addr = 0x1000; /* all load addresses are at 0x1000 */
spin_lock_irqsave(&qpti->lock, flags); spin_lock_irqsave(host->host_lock, flags);
sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL);
...@@ -367,7 +367,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -367,7 +367,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
if (qlogicpti_mbox_command(qpti, param, 1)) { if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n", printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -378,7 +378,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -378,7 +378,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
(param[0] != MBOX_COMMAND_COMPLETE)) { (param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: Cannot set initiator SCSI ID.\n", printk(KERN_EMERG "qlogicpti%d: Cannot set initiator SCSI ID.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -393,7 +393,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -393,7 +393,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
if (qlogicpti_mbox_command(qpti, param, 1)) { if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot init response queue.\n", printk(KERN_EMERG "qlogicpti%d: Cannot init response queue.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -405,7 +405,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -405,7 +405,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
if (qlogicpti_mbox_command(qpti, param, 1)) { if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot init request queue.\n", printk(KERN_EMERG "qlogicpti%d: Cannot init request queue.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -451,7 +451,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -451,7 +451,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
qlogicpti_mbox_command(qpti, param, 0); qlogicpti_mbox_command(qpti, param, 0);
qpti->send_marker = 1; qpti->send_marker = 1;
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 0; return 0;
} }
...@@ -459,6 +459,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) ...@@ -459,6 +459,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
{ {
struct Scsi_Host *host = qpti->qhost;
unsigned short csum = 0; unsigned short csum = 0;
unsigned short param[6]; unsigned short param[6];
unsigned short *risc_code, risc_code_addr, risc_code_length; unsigned short *risc_code, risc_code_addr, risc_code_length;
...@@ -469,7 +470,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -469,7 +470,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */ risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */
risc_code_length = sbus_risc_code_length01; risc_code_length = sbus_risc_code_length01;
spin_lock_irqsave(&qpti->lock, flags); spin_lock_irqsave(host->host_lock, flags);
/* Verify the checksum twice, one before loading it, and once /* Verify the checksum twice, one before loading it, and once
* afterwards via the mailbox commands. * afterwards via the mailbox commands.
...@@ -477,7 +478,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -477,7 +478,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
for (i = 0; i < risc_code_length; i++) for (i = 0; i < risc_code_length; i++)
csum += risc_code[i]; csum += risc_code[i];
if (csum) { if (csum) {
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!", printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
qpti->qpti_id); qpti->qpti_id);
return 1; return 1;
...@@ -489,7 +490,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -489,7 +490,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET)) while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET))
udelay(20); udelay(20);
if (!timeout) { if (!timeout) {
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id); printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id);
return 1; return 1;
} }
...@@ -529,7 +530,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -529,7 +530,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
if (qlogicpti_mbox_command(qpti, param, 1)) { if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n", printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -542,7 +543,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -542,7 +543,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
param[0] != MBOX_COMMAND_COMPLETE) { param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
} }
...@@ -562,7 +563,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -562,7 +563,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) { (param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n", printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -576,7 +577,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -576,7 +577,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) { (param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n", printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -592,7 +593,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -592,7 +593,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) { (param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n", printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 1; return 1;
} }
...@@ -609,7 +610,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) ...@@ -609,7 +610,7 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
qlogicpti_mbox_command(qpti, param, 1); qlogicpti_mbox_command(qpti, param, 1);
} }
spin_unlock_irqrestore(&qpti->lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 0; return 0;
} }
...@@ -844,8 +845,6 @@ static int __init qlogicpti_detect(Scsi_Host_Template *tpnt) ...@@ -844,8 +845,6 @@ static int __init qlogicpti_detect(Scsi_Host_Template *tpnt)
} }
qpti = (struct qlogicpti *) qpti_host->hostdata; qpti = (struct qlogicpti *) qpti_host->hostdata;
spin_lock_init(&qpti->lock);
/* We are wide capable, 16 targets. */ /* We are wide capable, 16 targets. */
qpti_host->max_id = MAX_TARGETS; qpti_host->max_id = MAX_TARGETS;
...@@ -1171,7 +1170,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, ...@@ -1171,7 +1170,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd,
void (*done)(Scsi_Cmnd *)) void (*done)(Scsi_Cmnd *))
{ {
struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata; struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
unsigned long flags;
/* /*
* done checking this host adapter? * done checking this host adapter?
...@@ -1188,8 +1186,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, ...@@ -1188,8 +1186,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd,
return qlogicpti_queuecommand(Cmnd, ourdone); return qlogicpti_queuecommand(Cmnd, ourdone);
} }
spin_lock_irqsave(&qpti->lock, flags);
/* /*
* We've peeked at all targets for this bus- time * We've peeked at all targets for this bus- time
* to set parameters for devices for real now. * to set parameters for devices for real now.
...@@ -1231,8 +1227,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, ...@@ -1231,8 +1227,6 @@ static int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd,
if (qpti == NULL) if (qpti == NULL)
Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand; Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand;
spin_unlock_irqrestore(&qpti->lock, flags);
return qlogicpti_queuecommand(Cmnd, done); return qlogicpti_queuecommand(Cmnd, done);
} }
...@@ -1249,14 +1243,11 @@ static int qlogicpti_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)) ...@@ -1249,14 +1243,11 @@ static int qlogicpti_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
struct Scsi_Host *host = Cmnd->device->host; struct Scsi_Host *host = Cmnd->device->host;
struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
struct Command_Entry *cmd; struct Command_Entry *cmd;
unsigned long flags;
u_int out_ptr; u_int out_ptr;
int in_ptr; int in_ptr;
Cmnd->scsi_done = done; Cmnd->scsi_done = done;
spin_lock_irqsave(&qpti->lock, flags);
in_ptr = qpti->req_in_ptr; in_ptr = qpti->req_in_ptr;
cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr]; cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];
out_ptr = sbus_readw(qpti->qregs + MBOX4); out_ptr = sbus_readw(qpti->qregs + MBOX4);
...@@ -1281,15 +1272,12 @@ static int qlogicpti_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)) ...@@ -1281,15 +1272,12 @@ static int qlogicpti_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
update_can_queue(host, in_ptr, out_ptr); update_can_queue(host, in_ptr, out_ptr);
spin_unlock_irqrestore(&qpti->lock, flags);
return 0; return 0;
toss_command: toss_command:
printk(KERN_EMERG "qlogicpti%d: request queue overflow\n", printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",
qpti->qpti_id); qpti->qpti_id);
spin_unlock_irqrestore(&qpti->lock, flags);
/* Unfortunately, unless you use the new EH code, which /* Unfortunately, unless you use the new EH code, which
* we don't, the midlayer will ignore the return value, * we don't, the midlayer will ignore the return value,
* which is insane. We pick up the pieces like this. * which is insane. We pick up the pieces like this.
...@@ -1447,12 +1435,10 @@ static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1447,12 +1435,10 @@ static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs)
unsigned long flags; unsigned long flags;
Scsi_Cmnd *dq; Scsi_Cmnd *dq;
spin_lock_irqsave(&qpti->lock, flags); spin_lock_irqsave(qpti->qhost->host_lock, flags);
dq = qlogicpti_intr_handler(qpti); dq = qlogicpti_intr_handler(qpti);
spin_unlock(&qpti->lock);
if (dq != NULL) { if (dq != NULL) {
spin_lock(qpti->qhost->host_lock);
do { do {
Scsi_Cmnd *next; Scsi_Cmnd *next;
...@@ -1460,9 +1446,8 @@ static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1460,9 +1446,8 @@ static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs)
dq->scsi_done(dq); dq->scsi_done(dq);
dq = next; dq = next;
} while (dq != NULL); } while (dq != NULL);
spin_unlock(qpti->qhost->host_lock);
} }
local_irq_restore(flags); spin_unlock_irqrestore(qpti->qhost->host_lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1473,15 +1458,12 @@ static int qlogicpti_abort(Scsi_Cmnd *Cmnd) ...@@ -1473,15 +1458,12 @@ static int qlogicpti_abort(Scsi_Cmnd *Cmnd)
struct Scsi_Host *host = Cmnd->device->host; struct Scsi_Host *host = Cmnd->device->host;
struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
int return_status = SUCCESS; int return_status = SUCCESS;
unsigned long flags;
u32 cmd_cookie; u32 cmd_cookie;
int i; int i;
printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n", printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n",
(int)Cmnd->device->id, (int)Cmnd->device->lun); (int)Cmnd->device->id, (int)Cmnd->device->lun);
spin_lock_irqsave(&qpti->lock, flags);
qlogicpti_disable_irqs(qpti); qlogicpti_disable_irqs(qpti);
/* Find the 32-bit cookie we gave to the firmware for /* Find the 32-bit cookie we gave to the firmware for
...@@ -1504,8 +1486,6 @@ static int qlogicpti_abort(Scsi_Cmnd *Cmnd) ...@@ -1504,8 +1486,6 @@ static int qlogicpti_abort(Scsi_Cmnd *Cmnd)
qlogicpti_enable_irqs(qpti); qlogicpti_enable_irqs(qpti);
spin_unlock_irqrestore(&qpti->lock, flags);
return return_status; return return_status;
} }
...@@ -1515,12 +1495,9 @@ static int qlogicpti_reset(Scsi_Cmnd *Cmnd) ...@@ -1515,12 +1495,9 @@ static int qlogicpti_reset(Scsi_Cmnd *Cmnd)
struct Scsi_Host *host = Cmnd->device->host; struct Scsi_Host *host = Cmnd->device->host;
struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
int return_status = SUCCESS; int return_status = SUCCESS;
unsigned long flags;
printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n"); printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n");
spin_lock_irqsave(&qpti->lock, flags);
qlogicpti_disable_irqs(qpti); qlogicpti_disable_irqs(qpti);
param[0] = MBOX_BUS_RESET; param[0] = MBOX_BUS_RESET;
...@@ -1533,8 +1510,6 @@ static int qlogicpti_reset(Scsi_Cmnd *Cmnd) ...@@ -1533,8 +1510,6 @@ static int qlogicpti_reset(Scsi_Cmnd *Cmnd)
qlogicpti_enable_irqs(qpti); qlogicpti_enable_irqs(qpti);
spin_unlock_irqrestore(&qpti->lock, flags);
return return_status; return return_status;
} }
......
...@@ -335,7 +335,6 @@ struct pti_queue_entry { ...@@ -335,7 +335,6 @@ struct pti_queue_entry {
/* Software state for the driver. */ /* Software state for the driver. */
struct qlogicpti { struct qlogicpti {
/* These are the hot elements in the cache, so they come first. */ /* These are the hot elements in the cache, so they come first. */
spinlock_t lock; /* Driver mutex */
unsigned long qregs; /* Adapter registers */ unsigned long qregs; /* Adapter registers */
struct pti_queue_entry *res_cpu; /* Ptr to RESPONSE bufs (CPU) */ struct pti_queue_entry *res_cpu; /* Ptr to RESPONSE bufs (CPU) */
struct pti_queue_entry *req_cpu; /* Ptr to REQUEST bufs (CPU) */ struct pti_queue_entry *req_cpu; /* Ptr to REQUEST bufs (CPU) */
......
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