Commit 1d7be70b authored by Russell King's avatar Russell King

[PCMCIA] Remove now obsolete work queues, spinlocks and variables.

Since the cs.c pcmcia core has a per-socket thread, we don't need each
socket driver having a work queue and associated complexity.

Therefore, remove this complexity and allow the socket drivers to call
pcmcia_parse_events directly from their interrupt or timer handlers.
parent 2941bfd0
...@@ -83,8 +83,6 @@ struct socket_info { ...@@ -83,8 +83,6 @@ struct socket_info {
3 = operational card */ 3 = operational card */
int io_base; /* base io address of the socket */ int io_base; /* base io address of the socket */
unsigned int pending_events; /* Pending events on this interface */
struct pcmcia_socket socket; struct pcmcia_socket socket;
struct pci_dev *dev; /* The PCI device for the socket */ struct pci_dev *dev; /* The PCI device for the socket */
}; };
...@@ -319,23 +317,6 @@ static int to_cycles(int ns) ...@@ -319,23 +317,6 @@ static int to_cycles(int ns)
/* Interrupt handler functionality */ /* Interrupt handler functionality */
static void i82092aa_bh(void *dummy)
{
unsigned int events;
int i;
for (i=0; i < socket_count; i++) {
events = xchg(&(sockets[i].pending_events),0);
printk("events = %x \n",events);
if (events)
pcmcia_parse_events(&sockets[i].socket, events);
}
}
static DECLARE_WORK(i82092aa_task, i82092aa_bh, NULL);
static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
{ {
int i; int i;
...@@ -383,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -383,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
} }
if (events) { if (events) {
sockets[i].pending_events |= events; pcmcia_parse_events(&sockets[i].socket, events);
schedule_work(&i82092aa_task);
} }
active |= events; active |= events;
} }
......
...@@ -861,35 +861,6 @@ static void __init isa_probe(void) ...@@ -861,35 +861,6 @@ static void __init isa_probe(void)
/*====================================================================*/ /*====================================================================*/
static u_int pending_events[8];
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
static void pcic_bh(void *dummy)
{
u_int events;
int i;
for (i=0; i < sockets; i++) {
spin_lock_irq(&pending_event_lock);
events = pending_events[i];
pending_events[i] = 0;
spin_unlock_irq(&pending_event_lock);
/*
SS_DETECT events need a small delay here. The reason for this is that
the "is there a card" electronics need time to see the card after the
"we have a card coming in" electronics have seen it.
*/
if (events & SS_DETECT)
mdelay(4);
if (events)
pcmcia_parse_events(&socket[i].socket, events);
}
}
static DECLARE_WORK(pcic_task, pcic_bh, NULL);
static unsigned long last_detect_jiffies;
static irqreturn_t pcic_interrupt(int irq, void *dev, static irqreturn_t pcic_interrupt(int irq, void *dev,
struct pt_regs *regs) struct pt_regs *regs)
{ {
...@@ -915,19 +886,6 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -915,19 +886,6 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
} }
events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0; events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
/* Several sockets will send multiple "new card detected"
events in rapid succession. However, the rest of the pcmcia expects
only one such event. We just ignore these events by having a
timeout */
if (events) {
if ((jiffies - last_detect_jiffies)<(HZ/20))
events = 0;
last_detect_jiffies = jiffies;
}
if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD) if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
else { else {
...@@ -938,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -938,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
ISA_UNLOCK(i, flags); ISA_UNLOCK(i, flags);
DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events); DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events);
if (events) { if (events)
spin_lock(&pending_event_lock); pcmcia_parse_events(&socket[i].socket, events);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&pcic_task);
}
active |= events; active |= events;
} }
if (!active) break; if (!active) break;
......
...@@ -38,15 +38,13 @@ ...@@ -38,15 +38,13 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/version.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -263,29 +261,27 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock) ...@@ -263,29 +261,27 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
return ret; return ret;
} }
static spinlock_t status_lock = SPIN_LOCK_UNLOCKED;
/* sa1100_pcmcia_task_handler() /* sa1100_check_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ^^^^^^^^^^^^^^^^^^^^^
* Processes serviceable socket events using the "eventd" thread context.
*
* Event processing (specifically, the invocation of the Card Services event
* callback) occurs in this thread rather than in the actual interrupt
* handler due to the use of scheduling operations in the PCMCIA core.
*/ */
static void sa1100_pcmcia_task_handler(void *data) static void sa1100_check_status(struct sa1100_pcmcia_socket *skt)
{ {
struct sa1100_pcmcia_socket *skt = data;
unsigned int events; unsigned int events;
DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
do { do {
unsigned int status; unsigned int status;
unsigned long flags;
status = sa1100_pcmcia_skt_state(skt); status = sa1100_pcmcia_skt_state(skt);
spin_lock_irqsave(&status_lock, flags);
events = (status ^ skt->status) & skt->cs_state.csc_mask; events = (status ^ skt->status) & skt->cs_state.csc_mask;
skt->status = status; skt->status = status;
spin_unlock_irqrestore(&status_lock, flags);
DEBUG(2, "events: %s%s%s%s%s%s\n", DEBUG(2, "events: %s%s%s%s%s%s\n",
events == 0 ? "<NONE>" : "", events == 0 ? "<NONE>" : "",
...@@ -311,7 +307,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy) ...@@ -311,7 +307,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD); mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD);
schedule_work(&skt->work); sa1100_check_status(skt);
} }
...@@ -330,7 +326,7 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r ...@@ -330,7 +326,7 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&skt->work); sa1100_check_status(skt);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -733,8 +729,6 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -733,8 +729,6 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
skt->socket.owner = ops->owner; skt->socket.owner = ops->owner;
skt->socket.dev.dev = dev; skt->socket.dev.dev = dev;
INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
init_timer(&skt->poll_timer); init_timer(&skt->poll_timer);
skt->poll_timer.function = sa1100_pcmcia_poll_event; skt->poll_timer.function = sa1100_pcmcia_poll_event;
skt->poll_timer.data = (unsigned long)skt; skt->poll_timer.data = (unsigned long)skt;
......
...@@ -73,7 +73,6 @@ struct sa1100_pcmcia_socket { ...@@ -73,7 +73,6 @@ struct sa1100_pcmcia_socket {
unsigned int irq_state; unsigned int irq_state;
struct timer_list poll_timer; struct timer_list poll_timer;
struct work_struct work;
}; };
struct pcmcia_low_level { struct pcmcia_low_level {
......
...@@ -555,26 +555,6 @@ static void __exit exit_tcic(void) ...@@ -555,26 +555,6 @@ static void __exit exit_tcic(void)
/*====================================================================*/ /*====================================================================*/
static u_int pending_events[2];
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
static void tcic_bh(void *dummy)
{
u_int events;
int i;
for (i=0; i < sockets; i++) {
spin_lock_irq(&pending_event_lock);
events = pending_events[i];
pending_events[i] = 0;
spin_unlock_irq(&pending_event_lock);
if (events)
pcmcia_parse_events(&socket_table[i].socket, events);
}
}
static DECLARE_WORK(tcic_task, tcic_bh, NULL);
static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
{ {
int i, quick = 0; int i, quick = 0;
...@@ -614,10 +594,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -614,10 +594,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0; events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
} }
if (events) { if (events) {
spin_lock(&pending_event_lock); pcmcia_parse_events(&socket_table[i].socket, events);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&tcic_task);
} }
} }
......
...@@ -250,7 +250,6 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) ...@@ -250,7 +250,6 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (state->flags & SS_DEBOUNCED) { if (state->flags & SS_DEBOUNCED) {
/* The insertion debounce period has ended. Clear any pending insertion events */ /* The insertion debounce period has ended. Clear any pending insertion events */
socket->events &= ~SS_DETECT;
state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */
} }
yenta_set_power(socket, state); yenta_set_power(socket, state);
...@@ -420,19 +419,6 @@ static unsigned int yenta_events(struct yenta_socket *socket) ...@@ -420,19 +419,6 @@ static unsigned int yenta_events(struct yenta_socket *socket)
} }
static void yenta_bh(void *data)
{
struct yenta_socket *socket = data;
unsigned int events;
spin_lock_irq(&socket->event_lock);
events = socket->events;
socket->events = 0;
spin_unlock_irq(&socket->event_lock);
if (events)
pcmcia_parse_events(&socket->socket, events);
}
static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int events; unsigned int events;
...@@ -440,10 +426,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -440,10 +426,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
events = yenta_events(socket); events = yenta_events(socket);
if (events) { if (events) {
spin_lock(&socket->event_lock); pcmcia_parse_events(&socket->socket, events);
socket->events |= events;
spin_unlock(&socket->event_lock);
schedule_work(&socket->tq_task);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
...@@ -853,7 +836,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -853,7 +836,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* prepare struct yenta_socket */ /* prepare struct yenta_socket */
socket->dev = dev; socket->dev = dev;
pci_set_drvdata(dev, socket); pci_set_drvdata(dev, socket);
spin_lock_init(&socket->event_lock);
/* /*
* Do some basic sanity checking.. * Do some basic sanity checking..
...@@ -896,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -896,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* We must finish initialization here */ /* We must finish initialization here */
INIT_WORK(&socket->tq_task, yenta_bh, socket);
if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
/* No IRQ or request_irq failed. Poll */ /* No IRQ or request_irq failed. Poll */
socket->cb_irq = 0; /* But zero is a valid IRQ number. */ socket->cb_irq = 0; /* But zero is a valid IRQ number. */
......
...@@ -99,9 +99,6 @@ struct yenta_socket { ...@@ -99,9 +99,6 @@ struct yenta_socket {
struct pci_dev *dev; struct pci_dev *dev;
int cb_irq, io_irq; int cb_irq, io_irq;
void *base; void *base;
spinlock_t event_lock;
unsigned int events;
struct work_struct tq_task;
struct timer_list poll_timer; struct timer_list poll_timer;
struct pcmcia_socket socket; struct pcmcia_socket socket;
......
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