Commit 8b1ff56a authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[PATCH] PATCH [5/8] qla2xxx: Rework ISR registration

Rework interrupt-handler registration in anticipation of future
chip types.
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent a4f7980f
...@@ -246,7 +246,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); ...@@ -246,7 +246,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
/* /*
* Global Function Prototypes in qla_isr.c source file. * Global Function Prototypes in qla_isr.c source file.
*/ */
extern irqreturn_t qla2x00_intr_handler(int, void *, struct pt_regs *); extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *);
extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *);
extern void qla2x00_process_response_queue(struct scsi_qla_host *); extern void qla2x00_process_response_queue(struct scsi_qla_host *);
/* /*
......
...@@ -117,7 +117,10 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *); ...@@ -117,7 +117,10 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *);
static inline void static inline void
qla2x00_poll(scsi_qla_host_t *ha) qla2x00_poll(scsi_qla_host_t *ha)
{ {
qla2x00_intr_handler(0, ha, NULL); if (IS_QLA2100(ha) || IS_QLA2200(ha))
qla2100_intr_handler(0, ha, NULL);
else
qla2300_intr_handler(0, ha, NULL);
} }
......
...@@ -30,7 +30,7 @@ static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); ...@@ -30,7 +30,7 @@ static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *); static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *);
/** /**
* qla2x00_intr_handler() - Process interrupts for the ISP. * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq: * @irq:
* @dev_id: SCSI driver HA context * @dev_id: SCSI driver HA context
* @regs: * @regs:
...@@ -40,20 +40,14 @@ static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *); ...@@ -40,20 +40,14 @@ static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *);
* Returns handled flag. * Returns handled flag.
*/ */
irqreturn_t irqreturn_t
qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
scsi_qla_host_t *ha; scsi_qla_host_t *ha;
device_reg_t *reg; device_reg_t *reg;
int status;
unsigned long flags;
unsigned long iter;
uint32_t mbx; uint32_t mbx;
int status = 0;
unsigned long flags = 0;
unsigned long mbx_flags = 0;
unsigned long intr_iter;
uint32_t stat;
uint16_t hccr;
/* Don't loop forever, interrupt are OFF */
intr_iter = 50;
ha = (scsi_qla_host_t *) dev_id; ha = (scsi_qla_host_t *) dev_id;
if (!ha) { if (!ha) {
...@@ -63,107 +57,40 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -63,107 +57,40 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
} }
reg = ha->iobase; reg = ha->iobase;
status = 0;
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
for (iter = 50; iter--; ) {
for (;;) { if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
/* Relax CPU! */
if (!(intr_iter--))
break; break;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) { if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0) WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
break; RD_REG_WORD(&reg->hccr);
if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
/* Get mailbox data. */
mbx = RD_MAILBOX_REG(ha, reg, 0);
if (mbx > 0x3fff && mbx < 0x8000) {
qla2x00_mbx_completion(ha,
(uint16_t)mbx);
status |= MBX_INTERRUPT;
} else if (mbx > 0x7fff && mbx < 0xc000) {
qla2x00_async_event(ha, mbx);
} else {
/*EMPTY*/
DEBUG2(printk("scsi(%ld): Unrecognized "
"interrupt type (%d)\n",
ha->host_no, mbx));
}
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
/* Workaround for ISP2100 chip. */
if (IS_QLA2100(ha))
RD_REG_WORD(&reg->semaphore);
} else {
qla2x00_process_response_queue(ha);
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
}
} else /* IS_QLA23XX(ha) */ {
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_PAUSED) {
hccr = RD_REG_WORD(&reg->hccr);
if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
qla_printk(KERN_INFO, ha,
"Parity error -- HCCR=%x.\n", hccr);
else
qla_printk(KERN_INFO, ha,
"RISC paused -- HCCR=%x\n", hccr);
/*
* Issue a "HARD" reset in order for the RISC
* interrupt bit to be cleared. Schedule a big
* hammmer to get out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;
} else if ((stat & HSR_RISC_INT) == 0)
break;
mbx = MSW(stat); /* Get mailbox data. */
switch (stat & 0xff) { mbx = RD_MAILBOX_REG(ha, reg, 0);
case 0x13: if (mbx > 0x3fff && mbx < 0x8000) {
qla2x00_process_response_queue(ha);
break;
case 0x1:
case 0x2:
case 0x10:
case 0x11:
qla2x00_mbx_completion(ha, (uint16_t)mbx); qla2x00_mbx_completion(ha, (uint16_t)mbx);
status |= MBX_INTERRUPT; status |= MBX_INTERRUPT;
} else if (mbx > 0x7fff && mbx < 0xc000) {
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
break;
case 0x12:
qla2x00_async_event(ha, mbx);
break;
case 0x15:
mbx = mbx << 16 | MBA_CMPLT_1_16BIT;
qla2x00_async_event(ha, mbx);
break;
case 0x16:
mbx = mbx << 16 | MBA_SCSI_COMPLETION;
qla2x00_async_event(ha, mbx); qla2x00_async_event(ha, mbx);
break; } else {
default: /*EMPTY*/
DEBUG2(printk("scsi(%ld): Unrecognized " DEBUG2(printk("scsi(%ld): Unrecognized "
"interrupt type (%d)\n", "interrupt type (%d)\n",
ha->host_no, stat & 0xff)); ha->host_no, mbx));
break;
} }
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
RD_REG_WORD(&reg->semaphore);
} else {
qla2x00_process_response_queue(ha);
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT); WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD_RELAXED(&reg->hccr); RD_REG_WORD(&reg->hccr);
} }
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
qla2x00_next(ha); qla2x00_next(ha);
...@@ -172,48 +99,130 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -172,48 +99,130 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) { (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
spin_lock_irqsave(&ha->mbx_reg_lock, flags);
/* There was a mailbox completion */ set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
DEBUG3(printk("%s(%ld): Going to get mbx reg lock.\n", up(&ha->mbx_intr_sem);
__func__, ha->host_no));
spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
}
if (ha->mcp == NULL) { if (!list_empty(&ha->done_queue))
DEBUG3(printk("%s(%ld): Error mbx pointer.\n", qla2x00_done(ha);
__func__, ha->host_no));
} else {
DEBUG3(printk("%s(%ld): Going to set mbx intr flags. "
"cmd=%x.\n",
__func__, ha->host_no, ha->mcp->mb[0]));
}
set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
DEBUG3(printk("%s(%ld): Going to wake up mbx function for " return (IRQ_HANDLED);
"completion.\n", }
__func__, ha->host_no));
up(&ha->mbx_intr_sem); /**
* qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
* @irq:
* @dev_id: SCSI driver HA context
* @regs:
*
* Called by system whenever the host adapter generates an interrupt.
*
* Returns handled flag.
*/
irqreturn_t
qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
scsi_qla_host_t *ha;
device_reg_t *reg;
int status;
unsigned long flags;
unsigned long iter;
uint32_t stat;
uint32_t mbx;
uint16_t hccr;
DEBUG3(printk("%s(%ld): Going to release mbx reg lock.\n", ha = (scsi_qla_host_t *) dev_id;
__func__, ha->host_no)); if (!ha) {
printk(KERN_INFO
"%s(): NULL host pointer\n", __func__);
return (IRQ_NONE);
}
reg = ha->iobase;
status = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
for (iter = 50; iter--; ) {
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_PAUSED) {
hccr = RD_REG_WORD(&reg->hccr);
if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
qla_printk(KERN_INFO, ha,
"Parity error -- HCCR=%x.\n", hccr);
else
qla_printk(KERN_INFO, ha,
"RISC paused -- HCCR=%x\n", hccr);
spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); /*
* Issue a "HARD" reset in order for the RISC
* interrupt bit to be cleared. Schedule a big
* hammmer to get out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;
} else if ((stat & HSR_RISC_INT) == 0)
break;
mbx = MSW(stat);
switch (stat & 0xff) {
case 0x13:
qla2x00_process_response_queue(ha);
break;
case 0x1:
case 0x2:
case 0x10:
case 0x11:
qla2x00_mbx_completion(ha, (uint16_t)mbx);
status |= MBX_INTERRUPT;
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
break;
case 0x12:
qla2x00_async_event(ha, mbx);
break;
case 0x15:
mbx = mbx << 16 | MBA_CMPLT_1_16BIT;
qla2x00_async_event(ha, mbx);
break;
case 0x16:
mbx = mbx << 16 | MBA_SCSI_COMPLETION;
qla2x00_async_event(ha, mbx);
break;
default:
DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
"(%d)\n",
ha->host_no, stat & 0xff));
break;
}
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD_RELAXED(&reg->hccr);
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (!list_empty(&ha->done_queue)) qla2x00_next(ha);
qla2x00_done(ha); ha->last_irq_cpu = smp_processor_id();
ha->total_isr_cnt++;
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) {
spin_lock_irqsave(&ha->mbx_reg_lock, flags);
/* Wakeup the DPC routine */ set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
if ((!ha->flags.mbox_busy && up(&ha->mbx_intr_sem);
(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) &&
ha->dpc_wait && !ha->dpc_active) {
up(ha->dpc_wait); spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
} }
if (!list_empty(&ha->done_queue))
qla2x00_done(ha);
return (IRQ_HANDLED); return (IRQ_HANDLED);
} }
......
...@@ -2062,8 +2062,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ...@@ -2062,8 +2062,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
host->unique_id = ha->instance; host->unique_id = ha->instance;
host->max_id = ha->max_targets; host->max_id = ha->max_targets;
if (request_irq(host->irq, qla2x00_intr_handler, SA_INTERRUPT|SA_SHIRQ, if (IS_QLA2100(ha) || IS_QLA2200(ha))
ha->brd_info->drv_name, ha)) { ret = request_irq(host->irq, qla2100_intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
else
ret = request_irq(host->irq, qla2300_intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
if (ret != 0) {
qla_printk(KERN_WARNING, ha, qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n", "Failed to reserve interrupt %d already in use.\n",
host->irq); host->irq);
......
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