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