Commit 2c843d48 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Christoph Hellwig

[PATCH] AHA152x driver hangs on PCMCIA

On Mon, Jul 21, 2003 at 08:11:37AM -0600, Bhavesh P. Davda wrote:
> David Hinds approves of this patch (Thanks, Dave!). Please apply to 2.4.22

And here's a 2.6 version.
parent cbb2050f
...@@ -1868,12 +1868,31 @@ static void run(void) ...@@ -1868,12 +1868,31 @@ static void run(void)
static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
{ {
struct Scsi_Host *shpnt = lookup_irq(irqno); struct Scsi_Host *shpnt = lookup_irq(irqno);
unsigned char rev, dmacntrl0;
if (!shpnt) { if (!shpnt) {
printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno); printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno);
return IRQ_NONE; return IRQ_NONE;
} }
/*
* Read a couple of registers that are known to not be all 1's. If
* we read all 1's (-1), that means that either:
*
* a. The host adapter chip has gone bad, and we cannot control it,
* OR
* b. The host adapter is a PCMCIA card that has been ejected
*
* In either case, we cannot do anything with the host adapter at
* this point in time. So just ignore the interrupt and return.
* In the latter case, the interrupt might actually be meant for
* someone else sharing this IRQ, and that driver will handle it.
*/
rev = GETPORT(REV);
dmacntrl0 = GETPORT(DMACNTRL0);
if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
return IRQ_NONE;
/* no more interrupts from the controller, while we're busy. /* no more interrupts from the controller, while we're busy.
INTEN is restored by the BH handler */ INTEN is restored by the BH handler */
CLRBITS(DMACNTRL0, INTEN); CLRBITS(DMACNTRL0, INTEN);
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <linux/major.h> #include <linux/major.h>
...@@ -102,7 +101,7 @@ typedef struct scsi_info_t { ...@@ -102,7 +101,7 @@ typedef struct scsi_info_t {
struct Scsi_Host *host; struct Scsi_Host *host;
} scsi_info_t; } scsi_info_t;
static void aha152x_release_cs(u_long arg); static void aha152x_release_cs(dev_link_t *link);
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
...@@ -126,9 +125,6 @@ static dev_link_t *aha152x_attach(void) ...@@ -126,9 +125,6 @@ static dev_link_t *aha152x_attach(void)
if (!info) return NULL; if (!info) return NULL;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
init_timer(&link->release);
link->release.function = &aha152x_release_cs;
link->release.data = (u_long)link;
link->io.NumPorts1 = 0x20; link->io.NumPorts1 = 0x20;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
...@@ -181,9 +177,8 @@ static void aha152x_detach(dev_link_t *link) ...@@ -181,9 +177,8 @@ static void aha152x_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
del_timer(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
aha152x_release_cs((u_long)link); aha152x_release_cs(link);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK; link->state |= DEV_STALE_LINK;
return; return;
...@@ -290,13 +285,12 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -290,13 +285,12 @@ static void aha152x_config_cs(dev_link_t *link)
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
aha152x_release_cs((u_long)link); aha152x_release_cs(link);
return; return;
} }
static void aha152x_release_cs(u_long arg) static void aha152x_release_cs(dev_link_t *link)
{ {
dev_link_t *link = (dev_link_t *)arg;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
scsi_remove_host(info->host); scsi_remove_host(info->host);
...@@ -325,7 +319,7 @@ static int aha152x_event(event_t event, int priority, ...@@ -325,7 +319,7 @@ static int aha152x_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL: case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT; link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
mod_timer(&link->release, jiffies + HZ/20); aha152x_release_cs(link);
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <linux/major.h> #include <linux/major.h>
...@@ -90,7 +89,7 @@ extern void fdomain_setup(char *str, int *ints); ...@@ -90,7 +89,7 @@ extern void fdomain_setup(char *str, int *ints);
extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ); extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt );
extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
static void fdomain_release(u_long arg); static void fdomain_release(dev_link_t *link);
static int fdomain_event(event_t event, int priority, static int fdomain_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
...@@ -116,10 +115,6 @@ static dev_link_t *fdomain_attach(void) ...@@ -116,10 +115,6 @@ static dev_link_t *fdomain_attach(void)
if (!info) return NULL; if (!info) return NULL;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
init_timer(&link->release);
link->release.function = &fdomain_release;
link->release.data = (u_long)link;
link->io.NumPorts1 = 0x10; link->io.NumPorts1 = 0x10;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.IOAddrLines = 10; link->io.IOAddrLines = 10;
...@@ -171,9 +166,8 @@ static void fdomain_detach(dev_link_t *link) ...@@ -171,9 +166,8 @@ static void fdomain_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
del_timer(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
fdomain_release((u_long)link); fdomain_release(link);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK; link->state |= DEV_STALE_LINK;
return; return;
...@@ -266,16 +260,15 @@ static void fdomain_config(dev_link_t *link) ...@@ -266,16 +260,15 @@ static void fdomain_config(dev_link_t *link)
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
fdomain_release((u_long)link); fdomain_release(link);
return; return;
} /* fdomain_config */ } /* fdomain_config */
/*====================================================================*/ /*====================================================================*/
static void fdomain_release(u_long arg) static void fdomain_release(dev_link_t *link)
{ {
dev_link_t *link = (dev_link_t *)arg;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
DEBUG(0, "fdomain_release(0x%p)\n", link); DEBUG(0, "fdomain_release(0x%p)\n", link);
...@@ -307,7 +300,7 @@ static int fdomain_event(event_t event, int priority, ...@@ -307,7 +300,7 @@ static int fdomain_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL: case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT; link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
mod_timer(&link->release, jiffies + HZ/20); fdomain_release(link);
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -1477,10 +1476,6 @@ static dev_link_t *nsp_cs_attach(void) ...@@ -1477,10 +1476,6 @@ static dev_link_t *nsp_cs_attach(void)
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
/* Initialize the dev_link_t structure */
link->release.function = &nsp_cs_release;
link->release.data = (u_long)link;
/* The io structure describes IO port mapping */ /* The io structure describes IO port mapping */
link->io.NumPorts1 = 0x10; link->io.NumPorts1 = 0x10;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
...@@ -1558,9 +1553,8 @@ static void nsp_cs_detach(dev_link_t *link) ...@@ -1558,9 +1553,8 @@ static void nsp_cs_detach(dev_link_t *link)
return; return;
} }
del_timer(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
nsp_cs_release((u_long)link); nsp_cs_release(link);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK; link->state |= DEV_STALE_LINK;
return; return;
...@@ -1780,7 +1774,7 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1780,7 +1774,7 @@ static void nsp_cs_config(dev_link_t *link)
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
nsp_cs_release((u_long)link); nsp_cs_release(link);
return; return;
} /* nsp_cs_config */ } /* nsp_cs_config */
...@@ -1792,9 +1786,8 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1792,9 +1786,8 @@ static void nsp_cs_config(dev_link_t *link)
device, and release the PCMCIA configuration. If the device is device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed. still open, this will be postponed until it is closed.
======================================================================*/ ======================================================================*/
static void nsp_cs_release(u_long arg) static void nsp_cs_release(dev_link_t *link)
{ {
dev_link_t *link = (dev_link_t *)arg;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link); DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link);
...@@ -1866,7 +1859,7 @@ static int nsp_cs_event(event_t event, ...@@ -1866,7 +1859,7 @@ static int nsp_cs_event(event_t event,
link->state &= ~DEV_PRESENT; link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
((scsi_info_t *)link->priv)->stop = 1; ((scsi_info_t *)link->priv)->stop = 1;
mod_timer(&link->release, jiffies + HZ/20); nsp_cs_release(link);
} }
break; break;
...@@ -1933,7 +1926,7 @@ static void __exit nsp_cs_exit(void) ...@@ -1933,7 +1926,7 @@ static void __exit nsp_cs_exit(void)
/* XXX: this really needs to move into generic code.. */ /* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) { while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) { if (dev_list->state & DEV_CONFIG) {
nsp_cs_release((u_long)dev_list); nsp_cs_release(dev_list);
} }
nsp_cs_detach(dev_list); nsp_cs_detach(dev_list);
} }
......
...@@ -272,7 +272,7 @@ typedef struct _nsp_hw_data { ...@@ -272,7 +272,7 @@ typedef struct _nsp_hw_data {
static void nsp_cs_release(u_long arg); static void nsp_cs_release(dev_link_t *link);
static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args); static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args);
static dev_link_t *nsp_cs_attach(void); static dev_link_t *nsp_cs_attach(void);
static void nsp_cs_detach(dev_link_t *); static void nsp_cs_detach(dev_link_t *);
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/io.h> #include <asm/io.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
...@@ -90,7 +89,7 @@ typedef struct scsi_info_t { ...@@ -90,7 +89,7 @@ typedef struct scsi_info_t {
unsigned short manf_id; unsigned short manf_id;
} scsi_info_t; } scsi_info_t;
static void qlogic_release(u_long arg); static void qlogic_release(dev_link_t *link);
static int qlogic_event(event_t event, int priority, event_callback_args_t * args); static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
static dev_link_t *qlogic_attach(void); static dev_link_t *qlogic_attach(void);
...@@ -117,10 +116,6 @@ static dev_link_t *qlogic_attach(void) ...@@ -117,10 +116,6 @@ static dev_link_t *qlogic_attach(void)
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
init_timer(&link->release);
link->release.function = &qlogic_release;
link->release.data = (u_long) link;
link->io.NumPorts1 = 16; link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.IOAddrLines = 10; link->io.IOAddrLines = 10;
...@@ -170,9 +165,8 @@ static void qlogic_detach(dev_link_t * link) ...@@ -170,9 +165,8 @@ static void qlogic_detach(dev_link_t * link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
qlogic_release((u_long) link); qlogic_release(link);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK; link->state |= DEV_STALE_LINK;
return; return;
...@@ -279,16 +273,15 @@ static void qlogic_config(dev_link_t * link) ...@@ -279,16 +273,15 @@ static void qlogic_config(dev_link_t * link)
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
qlogic_release((u_long) link); qlogic_release(link);
return; return;
} /* qlogic_config */ } /* qlogic_config */
/*====================================================================*/ /*====================================================================*/
static void qlogic_release(u_long arg) static void qlogic_release(dev_link_t *link)
{ {
dev_link_t *link = (dev_link_t *) arg;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
DEBUG(0, "qlogic_release(0x%p)\n", link); DEBUG(0, "qlogic_release(0x%p)\n", link);
...@@ -319,7 +312,7 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg ...@@ -319,7 +312,7 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg
case CS_EVENT_CARD_REMOVAL: case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT; link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
mod_timer(&link->release, jiffies + HZ / 20); qlogic_release(link);
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
......
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