yenta_socket "nobody cared - Disabling IRQ #4"
Daniel Ritz
daniel.ritz at gmx.ch
Fri Mar 18 16:43:24 EST 2005
hi
it's the second time now i see this problem with an atheros chipset in
combination with a TI bridge. last time it was the 1225...
attached a patch that could help...
rgds
-daniel
--------------
for TI bridges: turn off interrupts during card power-on. this seems
to be neccessary for some combination of TI bridges with at least CB cards
with atheros chipset...problem is that they produce an interrupt storm
during power-on so the kernel happens to disable the IRQ which is a bad
thing (tm).
adds a generic hook function so that a socket driver can hook into
almost anywhere (by adding more hook points of course). this is the
cleanest way i can think of. and it allows adding more workarounds
for more problems...
for the TI specific interrupt on-off stuff just save the MFUNC register
and set it to 0 to disable all interrupts, restore it afterwards.
Signed-off-by: Daniel Ritz <daniel.ritz at gmx.ch>
--- 1.22/drivers/pcmcia/ti113x.h 2005-03-11 21:32:12 +01:00
+++ edited/drivers/pcmcia/ti113x.h 2005-03-18 22:06:12 +01:00
@@ -591,6 +591,35 @@
}
}
+
+/*
+ * TI specifiy parts for generic hook. generic hook really is specifiy to the
+ * chipset so there's no point having it in yenta_socket.c (for now)
+ *
+ * some TI's with some CB's produces interrupt storm on power on. it has been
+ * seen with atheros wlan cards on TI1225 and TI1410. solution is simply to
+ * disable any CB interrupts during this time.
+ */
+static int ti12xx_hook(struct pcmcia_socket *sock, int operation)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+ switch (operation) {
+ case HOOK_POWER_PRE:
+ socket->saved_state[0] = config_readl(socket, TI122X_MFUNC);
+ config_writel(socket, TI122X_MFUNC, 0);
+ break;
+
+ case HOOK_POWER_POST:
+ config_writel(socket, TI122X_MFUNC, socket->saved_state[0]);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int ti12xx_override(struct yenta_socket *socket)
{
u32 val, val_orig;
@@ -633,6 +662,9 @@
ti12xx_irqroute_func0(socket);
else
ti12xx_irqroute_func1(socket);
+
+ /* install generic hook */
+ socket->socket.ops->generic_hook = ti12xx_hook;
return ti_override(socket);
}
--- 1.125/drivers/pcmcia/cs.c 2005-03-11 21:32:13 +01:00
+++ edited/drivers/pcmcia/cs.c 2005-03-12 21:22:38 +01:00
@@ -508,6 +508,10 @@
cs_err(skt, "unsupported voltage key.\n");
return CS_BAD_TYPE;
}
+
+ if (skt->ops->generic_hook)
+ skt->ops->generic_hook(skt, HOOK_POWER_PRE);
+
skt->socket.flags = 0;
skt->ops->set_socket(skt, &skt->socket);
@@ -522,7 +526,12 @@
return CS_BAD_TYPE;
}
- return socket_reset(skt);
+ status = socket_reset(skt);
+
+ if (skt->ops->generic_hook)
+ skt->ops->generic_hook(skt, HOOK_POWER_POST);
+
+ return status;
}
/*
--- 1.48/include/pcmcia/ss.h 2005-03-11 21:32:13 +01:00
+++ edited/include/pcmcia/ss.h 2005-03-12 21:22:39 +01:00
@@ -77,6 +77,11 @@
/* Use this just for bridge windows */
#define MAP_IOSPACE 0x20
+/* generic hook operations */
+#define HOOK_POWER_PRE 0x01
+#define HOOK_POWER_POST 0x02
+
+
typedef struct pccard_io_map {
u_char map;
u_char flags;
@@ -113,6 +118,7 @@
int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
nt (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
+ int (*generic_hook)(struct pcmcia_socket *sock, int operation);
};
struct pccard_resource_ops {
More information about the linux-pcmcia
mailing list