Commit 99c9e0a1 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley

[SCSI] sym53c8xx: Make interrupt handler capable of returning IRQ_NONE

Make sym_interrupt return an irqreturn_t instead of void, and take a
Scsi_Host instead of a sym_hcb.  Pass the Scsi_Host to the interrupt
handler instead of the sym_hcb.  Rename the host_data to sym_data.
Keep a pci_dev pointer in the sym_data.  Rename the Scsi_Host from
instance to shost.
Signed-off-by: default avatarMatthew Wilcox <willy@linux.intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8022fbda
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
*/ */
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -549,21 +548,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, ...@@ -549,21 +548,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
*/ */
static irqreturn_t sym53c8xx_intr(int irq, void *dev_id) static irqreturn_t sym53c8xx_intr(int irq, void *dev_id)
{ {
struct sym_hcb *np = dev_id; struct Scsi_Host *shost = dev_id;
struct sym_data *sym_data = shost_priv(shost);
irqreturn_t result;
/* Avoid spinloop trying to handle interrupts on frozen device */ /* Avoid spinloop trying to handle interrupts on frozen device */
if (pci_channel_offline(np->s.device)) if (pci_channel_offline(sym_data->pdev))
return IRQ_NONE; return IRQ_NONE;
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
spin_lock(np->s.host->host_lock); spin_lock(shost->host_lock);
sym_interrupt(np); result = sym_interrupt(shost);
spin_unlock(np->s.host->host_lock); spin_unlock(shost->host_lock);
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n"); if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
return IRQ_HANDLED; return result;
} }
/* /*
...@@ -613,22 +614,19 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) ...@@ -613,22 +614,19 @@ 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 host_data *hostdata = shost_priv(host); struct sym_data *sym_data = shost_priv(host);
struct completion *io_reset; struct completion *io_reset;
int finished_reset = 0; int finished_reset = 0;
init_completion(&eh_done); init_completion(&eh_done);
spin_lock_irq(host->host_lock); spin_lock_irq(host->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 (!hostdata->io_reset) if (!sym_data->io_reset)
hostdata->io_reset = &eh_done; sym_data->io_reset = &eh_done;
io_reset = hostdata->io_reset; io_reset = sym_data->io_reset;
} else { } else {
io_reset = NULL;
}
if (!pci_channel_offline(pdev))
finished_reset = 1; finished_reset = 1;
}
spin_unlock_irq(host->host_lock); spin_unlock_irq(host->host_lock);
if (!finished_reset) if (!finished_reset)
finished_reset = wait_for_completion_timeout(io_reset, finished_reset = wait_for_completion_timeout(io_reset,
...@@ -1273,9 +1271,9 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) ...@@ -1273,9 +1271,9 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
int unit, struct sym_device *dev) int unit, struct sym_device *dev)
{ {
struct host_data *host_data; struct sym_data *sym_data;
struct sym_hcb *np = NULL; struct sym_hcb *np = NULL;
struct Scsi_Host *instance = NULL; struct Scsi_Host *shost;
struct pci_dev *pdev = dev->pdev; struct pci_dev *pdev = dev->pdev;
unsigned long flags; unsigned long flags;
struct sym_fw *fw; struct sym_fw *fw;
...@@ -1289,15 +1287,12 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1289,15 +1287,12 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
*/ */
fw = sym_find_firmware(&dev->chip); fw = sym_find_firmware(&dev->chip);
if (!fw) if (!fw)
goto attach_failed; return NULL;
/* shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
* Allocate host_data structure if (!shost)
*/ return NULL;
instance = scsi_host_alloc(tpnt, sizeof(*host_data)); sym_data = shost_priv(shost);
if (!instance)
goto attach_failed;
host_data = (struct host_data *) instance->hostdata;
/* /*
* Allocate immediately the host control block, * Allocate immediately the host control block,
...@@ -1310,8 +1305,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1310,8 +1305,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
goto attach_failed; goto attach_failed;
np->s.device = pdev; np->s.device = pdev;
np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */ np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
host_data->ncb = np; sym_data->ncb = np;
np->s.host = instance; sym_data->pdev = pdev;
np->s.host = shost;
pci_set_drvdata(pdev, np); pci_set_drvdata(pdev, np);
...@@ -1358,7 +1354,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1358,7 +1354,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
if (dev->ram_base) if (dev->ram_base)
np->ram_ba = (u32)dev->ram_base; np->ram_ba = (u32)dev->ram_base;
if (sym_hcb_attach(instance, fw, dev->nvram)) if (sym_hcb_attach(shost, fw, dev->nvram))
goto attach_failed; goto attach_failed;
/* /*
...@@ -1366,7 +1362,8 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1366,7 +1362,8 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* If we synchonize the C code with SCRIPTS on interrupt, * If we synchonize the C code with SCRIPTS on interrupt,
* we do not want to share the INTR line at all. * we do not want to share the INTR line at all.
*/ */
if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) { if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX,
shost)) {
printf_err("%s: request irq %u failure\n", printf_err("%s: request irq %u failure\n",
sym_name(np), pdev->irq); sym_name(np), pdev->irq);
goto attach_failed; goto attach_failed;
...@@ -1376,7 +1373,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1376,7 +1373,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* After SCSI devices have been opened, we cannot * After SCSI devices have been opened, we cannot
* reset the bus safely, so we do it here. * reset the bus safely, so we do it here.
*/ */
spin_lock_irqsave(instance->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
if (sym_reset_scsi_bus(np, 0)) if (sym_reset_scsi_bus(np, 0))
goto reset_failed; goto reset_failed;
...@@ -1398,37 +1395,37 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1398,37 +1395,37 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Fill Linux host instance structure * Fill Linux host instance structure
* and return success. * and return success.
*/ */
instance->max_channel = 0; shost->max_channel = 0;
instance->this_id = np->myaddr; shost->this_id = np->myaddr;
instance->max_id = np->maxwide ? 16 : 8; shost->max_id = np->maxwide ? 16 : 8;
instance->max_lun = SYM_CONF_MAX_LUN; shost->max_lun = SYM_CONF_MAX_LUN;
instance->unique_id = pci_resource_start(pdev, 0); shost->unique_id = pci_resource_start(pdev, 0);
instance->cmd_per_lun = SYM_CONF_MAX_TAG; shost->cmd_per_lun = SYM_CONF_MAX_TAG;
instance->can_queue = (SYM_CONF_MAX_START-2); shost->can_queue = (SYM_CONF_MAX_START-2);
instance->sg_tablesize = SYM_CONF_MAX_SG; shost->sg_tablesize = SYM_CONF_MAX_SG;
instance->max_cmd_len = 16; shost->max_cmd_len = 16;
BUG_ON(sym2_transport_template == NULL); BUG_ON(sym2_transport_template == NULL);
instance->transportt = sym2_transport_template; shost->transportt = sym2_transport_template;
/* 53c896 rev 1 errata: DMA may not cross 16MB boundary */ /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */
if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2) if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2)
instance->dma_boundary = 0xFFFFFF; shost->dma_boundary = 0xFFFFFF;
spin_unlock_irqrestore(instance->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
return instance; return shost;
reset_failed: reset_failed:
printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, " printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
"TERMINATION, DEVICE POWER etc.!\n", sym_name(np)); "TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
spin_unlock_irqrestore(instance->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
attach_failed: attach_failed:
if (!instance) if (!shost)
return NULL; return NULL;
printf_info("%s: giving up ...\n", sym_name(np)); printf_info("%s: giving up ...\n", sym_name(np));
if (np) if (np)
sym_free_resources(np, pdev); sym_free_resources(np, pdev);
scsi_host_put(instance); scsi_host_put(shost);
return NULL; return NULL;
} }
...@@ -1702,7 +1699,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev, ...@@ -1702,7 +1699,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
{ {
struct sym_device sym_dev; struct sym_device sym_dev;
struct sym_nvram nvram; struct sym_nvram nvram;
struct Scsi_Host *instance; struct Scsi_Host *shost;
memset(&sym_dev, 0, sizeof(sym_dev)); memset(&sym_dev, 0, sizeof(sym_dev));
memset(&nvram, 0, sizeof(nvram)); memset(&nvram, 0, sizeof(nvram));
...@@ -1729,13 +1726,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev, ...@@ -1729,13 +1726,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
sym_get_nvram(&sym_dev, &nvram); sym_get_nvram(&sym_dev, &nvram);
instance = sym_attach(&sym2_template, attach_count, &sym_dev); shost = sym_attach(&sym2_template, attach_count, &sym_dev);
if (!instance) if (!shost)
goto free; goto free;
if (scsi_add_host(instance, &pdev->dev)) if (scsi_add_host(shost, &pdev->dev))
goto detach; goto detach;
scsi_scan_host(instance); scsi_scan_host(shost);
attach_count++; attach_count++;
...@@ -1884,12 +1881,12 @@ static void sym2_io_resume(struct pci_dev *pdev) ...@@ -1884,12 +1881,12 @@ static void sym2_io_resume(struct pci_dev *pdev)
{ {
struct sym_hcb *np = pci_get_drvdata(pdev); struct sym_hcb *np = pci_get_drvdata(pdev);
struct Scsi_Host *shost = np->s.host; struct Scsi_Host *shost = np->s.host;
struct host_data *hostdata = shost_priv(shost); struct sym_data *sym_data = shost_priv(shost);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
if (hostdata->io_reset) if (sym_data->io_reset)
complete_all(hostdata->io_reset); complete_all(sym_data->io_reset);
hostdata->io_reset = NULL; sym_data->io_reset = NULL;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -217,14 +218,15 @@ struct sym_device { ...@@ -217,14 +218,15 @@ struct sym_device {
/* /*
* Driver host data structure. * Driver host data structure.
*/ */
struct host_data { struct sym_data {
struct sym_hcb *ncb; struct sym_hcb *ncb;
struct completion *io_reset; /* PCI error handling */ struct completion *io_reset; /* PCI error handling */
struct pci_dev *pdev;
}; };
static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host) static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
{ {
return ((struct host_data *)host->hostdata)->ncb; return ((struct sym_data *)host->hostdata)->ncb;
} }
#include "sym_fw.h" #include "sym_fw.h"
......
...@@ -2760,8 +2760,9 @@ static void sym_int_ma (struct sym_hcb *np) ...@@ -2760,8 +2760,9 @@ static void sym_int_ma (struct sym_hcb *np)
* Use at your own decision and risk. * Use at your own decision and risk.
*/ */
void sym_interrupt (struct sym_hcb *np) irqreturn_t sym_interrupt(struct Scsi_Host *shost)
{ {
struct sym_hcb *np = sym_get_hcb(shost);
u_char istat, istatc; u_char istat, istatc;
u_char dstat; u_char dstat;
u_short sist; u_short sist;
...@@ -2786,7 +2787,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2786,7 +2787,7 @@ void sym_interrupt (struct sym_hcb *np)
} }
if (!(istat & (SIP|DIP))) if (!(istat & (SIP|DIP)))
return; return (istat & INTF) ? IRQ_HANDLED : IRQ_NONE;
#if 0 /* We should never get this one */ #if 0 /* We should never get this one */
if (istat & CABRT) if (istat & CABRT)
...@@ -2818,7 +2819,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2818,7 +2819,7 @@ void sym_interrupt (struct sym_hcb *np)
* never clear. */ * never clear. */
if (unlikely(sist == 0xffff && dstat == 0xff)) { if (unlikely(sist == 0xffff && dstat == 0xff)) {
if (pci_channel_offline(np->s.device)) if (pci_channel_offline(np->s.device))
return; return IRQ_NONE;
} }
} while (istatc & (SIP|DIP)); } while (istatc & (SIP|DIP));
...@@ -2856,7 +2857,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2856,7 +2857,7 @@ void sym_interrupt (struct sym_hcb *np)
else if (dstat & SIR) sym_int_sir(np); else if (dstat & SIR) sym_int_sir(np);
else if (dstat & SSI) OUTONB_STD(); else if (dstat & SSI) OUTONB_STD();
else goto unknown_int; else goto unknown_int;
return; return IRQ_HANDLED;
} }
/* /*
...@@ -2873,7 +2874,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2873,7 +2874,7 @@ void sym_interrupt (struct sym_hcb *np)
if (sist & RST) { if (sist & RST) {
printf("%s: SCSI BUS reset detected.\n", sym_name(np)); printf("%s: SCSI BUS reset detected.\n", sym_name(np));
sym_start_up (np, 1); sym_start_up (np, 1);
return; return IRQ_HANDLED;
} }
OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */ OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
...@@ -2885,7 +2886,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2885,7 +2886,7 @@ void sym_interrupt (struct sym_hcb *np)
else if (sist & STO) sym_int_sto (np); else if (sist & STO) sym_int_sto (np);
else if (sist & UDC) sym_int_udc (np); else if (sist & UDC) sym_int_udc (np);
else goto unknown_int; else goto unknown_int;
return; return IRQ_HANDLED;
} }
/* /*
...@@ -2900,7 +2901,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2900,7 +2901,7 @@ void sym_interrupt (struct sym_hcb *np)
if ((sist & (GEN|HTH|SGE)) || if ((sist & (GEN|HTH|SGE)) ||
(dstat & (MDPE|BF|ABRT|IID))) { (dstat & (MDPE|BF|ABRT|IID))) {
sym_start_reset(np); sym_start_reset(np);
return; return IRQ_HANDLED;
} }
unknown_int: unknown_int:
...@@ -2911,6 +2912,7 @@ void sym_interrupt (struct sym_hcb *np) ...@@ -2911,6 +2912,7 @@ void sym_interrupt (struct sym_hcb *np)
printf( "%s: unknown interrupt(s) ignored, " printf( "%s: unknown interrupt(s) ignored, "
"ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n", "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
sym_name(np), istat, dstat, sist); sym_name(np), istat, dstat, sist);
return IRQ_NONE;
} }
/* /*
......
...@@ -1056,7 +1056,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn); ...@@ -1056,7 +1056,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp); void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif #endif
void sym_start_up(struct sym_hcb *np, int reason); void sym_start_up(struct sym_hcb *np, int reason);
void sym_interrupt(struct sym_hcb *np); irqreturn_t sym_interrupt(struct Scsi_Host *);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task); int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order); struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp); void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
......
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