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 {
3 = operational card */
int io_base; /* base io address of the socket */
unsigned int pending_events; /* Pending events on this interface */
struct pcmcia_socket socket;
struct pci_dev *dev; /* The PCI device for the socket */
};
......@@ -319,23 +317,6 @@ static int to_cycles(int ns)
/* 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)
{
int i;
......@@ -383,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
}
if (events) {
sockets[i].pending_events |= events;
schedule_work(&i82092aa_task);
pcmcia_parse_events(&sockets[i].socket, events);
}
active |= events;
}
......
......@@ -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,
struct pt_regs *regs)
{
......@@ -914,20 +885,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
continue;
}
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)
events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
else {
......@@ -938,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
ISA_UNLOCK(i, flags);
DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events);
if (events) {
spin_lock(&pending_event_lock);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&pcic_task);
}
if (events)
pcmcia_parse_events(&socket[i].socket, events);
active |= events;
}
if (!active) break;
......
......@@ -38,15 +38,13 @@
#include <linux/init.h>
#include <linux/config.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/notifier.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/io.h>
......@@ -263,29 +261,27 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
return ret;
}
static spinlock_t status_lock = SPIN_LOCK_UNLOCKED;
/* sa1100_pcmcia_task_handler()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 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.
/* sa1100_check_status()
* ^^^^^^^^^^^^^^^^^^^^^
*/
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;
DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
do {
unsigned int status;
unsigned long flags;
status = sa1100_pcmcia_skt_state(skt);
spin_lock_irqsave(&status_lock, flags);
events = (status ^ skt->status) & skt->cs_state.csc_mask;
skt->status = status;
spin_unlock_irqrestore(&status_lock, flags);
DEBUG(2, "events: %s%s%s%s%s%s\n",
events == 0 ? "<NONE>" : "",
......@@ -311,7 +307,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
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
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&skt->work);
sa1100_check_status(skt);
return IRQ_HANDLED;
}
......@@ -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.dev.dev = dev;
INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
init_timer(&skt->poll_timer);
skt->poll_timer.function = sa1100_pcmcia_poll_event;
skt->poll_timer.data = (unsigned long)skt;
......
......@@ -73,7 +73,6 @@ struct sa1100_pcmcia_socket {
unsigned int irq_state;
struct timer_list poll_timer;
struct work_struct work;
};
struct pcmcia_low_level {
......
......@@ -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)
{
int i, quick = 0;
......@@ -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;
}
if (events) {
spin_lock(&pending_event_lock);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
schedule_work(&tcic_task);
pcmcia_parse_events(&socket_table[i].socket, events);
}
}
......
......@@ -250,7 +250,6 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (state->flags & SS_DEBOUNCED) {
/* The insertion debounce period has ended. Clear any pending insertion events */
socket->events &= ~SS_DETECT;
state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */
}
yenta_set_power(socket, state);
......@@ -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)
{
unsigned int events;
......@@ -440,10 +426,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
events = yenta_events(socket);
if (events) {
spin_lock(&socket->event_lock);
socket->events |= events;
spin_unlock(&socket->event_lock);
schedule_work(&socket->tq_task);
pcmcia_parse_events(&socket->socket, events);
return IRQ_HANDLED;
}
return IRQ_NONE;
......@@ -853,7 +836,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* prepare struct yenta_socket */
socket->dev = dev;
pci_set_drvdata(dev, socket);
spin_lock_init(&socket->event_lock);
/*
* Do some basic sanity checking..
......@@ -896,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* 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)) {
/* No IRQ or request_irq failed. Poll */
socket->cb_irq = 0; /* But zero is a valid IRQ number. */
......
......@@ -99,9 +99,6 @@ struct yenta_socket {
struct pci_dev *dev;
int cb_irq, io_irq;
void *base;
spinlock_t event_lock;
unsigned int events;
struct work_struct tq_task;
struct timer_list poll_timer;
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