Commit 47baacef authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 2708bcf5 2af67469
...@@ -465,10 +465,17 @@ t2_init_arch(void) ...@@ -465,10 +465,17 @@ t2_init_arch(void)
*(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */ *(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */
*(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */ *(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */
*(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */ *(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */
#if 0
/* !!! DO NOT EVER TOUCH THIS !!! */ /*
*(vulp)T2_HAE_4 = 0; mb(); /* Dense MEM HAE */ * We also now zero out HAE_4, the dense memory HAE, so that
#endif * we need not account for its "offset" when accessing dense
* memory resources which we allocated in our normal way. This
* HAE would need to stay untouched were we to keep the SRM
* resource settings.
*
* Thus we can now run standard X servers on SABLE/LYNX. :-)
*/
*(vulp)T2_HAE_4 = 0; mb();
} }
void void
......
...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct thread_info *childti = p->thread_info; struct thread_info *childti = p->thread_info;
struct pt_regs * childregs; struct pt_regs * childregs;
struct switch_stack * childstack, *stack; struct switch_stack * childstack, *stack;
unsigned long stack_offset; unsigned long stack_offset, settls;
stack_offset = PAGE_SIZE - sizeof(struct pt_regs); stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
if (!(regs->ps & 8)) if (!(regs->ps & 8))
...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
(stack_offset + PAGE_SIZE + (long) childti); (stack_offset + PAGE_SIZE + (long) childti);
*childregs = *regs; *childregs = *regs;
settls = regs->r20;
childregs->r0 = 0; childregs->r0 = 0;
childregs->r19 = 0; childregs->r19 = 0;
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childti->pcb.flags = 1; /* set FEN, clear everything else */ childti->pcb.flags = 1; /* set FEN, clear everything else */
/* Set a new TLS for the child thread? Peek back into the /* Set a new TLS for the child thread? Peek back into the
syscall arguments that we saved on syscall entry. */ syscall arguments that we saved on syscall entry. Oops,
except we'd have clobbered it with the parent/child set
of r20. Read the saved copy. */
/* Note: if CLONE_SETTLS is not set, then we must inherit the /* Note: if CLONE_SETTLS is not set, then we must inherit the
value from the parent, which will have been set by the block value from the parent, which will have been set by the block
copy in dup_task_struct. This is non-intuitive, but is copy in dup_task_struct. This is non-intuitive, but is
required for proper operation in the case of a threaded required for proper operation in the case of a threaded
application calling fork. */ application calling fork. */
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = regs->r20; childti->pcb.unique = settls;
return 0; return 0;
} }
......
...@@ -231,18 +231,6 @@ static const lookup_t service_table[] = { ...@@ -231,18 +231,6 @@ static const lookup_t service_table[] = {
======================================================================*/ ======================================================================*/
static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
int error;
if (handler && !try_module_get(s->ss_entry->owner))
return -ENODEV;
error = s->ss_entry->register_callback(s, handler, info);
if (!handler)
module_put(s->ss_entry->owner);
return error;
}
static int get_socket_status(struct pcmcia_socket *s, int *val) static int get_socket_status(struct pcmcia_socket *s, int *val)
{ {
return s->ss_entry->get_status(s, val); return s->ss_entry->get_status(s, val);
...@@ -363,6 +351,7 @@ static int pcmcia_add_socket(struct class_device *class_dev) ...@@ -363,6 +351,7 @@ static int pcmcia_add_socket(struct class_device *class_dev)
wait_for_completion(&socket->thread_done); wait_for_completion(&socket->thread_done);
BUG_ON(!socket->thread); BUG_ON(!socket->thread);
pcmcia_parse_events(socket, SS_DETECT);
return 0; return 0;
} }
...@@ -723,6 +712,9 @@ static int socket_insert(struct pcmcia_socket *skt) ...@@ -723,6 +712,9 @@ static int socket_insert(struct pcmcia_socket *skt)
{ {
int ret; int ret;
if (!try_module_get(skt->owner))
return CS_NO_CARD;
ret = socket_setup(skt, setup_delay); ret = socket_setup(skt, setup_delay);
if (ret == CS_SUCCESS) { if (ret == CS_SUCCESS) {
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
...@@ -733,8 +725,10 @@ static int socket_insert(struct pcmcia_socket *skt) ...@@ -733,8 +725,10 @@ static int socket_insert(struct pcmcia_socket *skt)
#endif #endif
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
skt->socket.flags &= ~SS_DEBOUNCED; skt->socket.flags &= ~SS_DEBOUNCED;
} else } else {
socket_shutdown(skt); socket_shutdown(skt);
module_put(skt->owner);
}
return ret; return ret;
} }
...@@ -778,14 +772,55 @@ static int socket_resume(struct pcmcia_socket *skt) ...@@ -778,14 +772,55 @@ static int socket_resume(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
} }
skt->socket.flags &= ~SS_DEBOUNCED; skt->socket.flags &= ~SS_DEBOUNCED;
} else } else {
unsigned int old_state = skt->state;
socket_shutdown(skt); socket_shutdown(skt);
if (old_state & SOCKET_PRESENT)
module_put(skt->owner);
}
skt->state &= ~SOCKET_SUSPEND; skt->state &= ~SOCKET_SUSPEND;
return CS_SUCCESS; return CS_SUCCESS;
} }
static void socket_remove(struct pcmcia_socket *skt)
{
socket_shutdown(skt);
module_put(skt->owner);
}
/*
* Process a socket card detect status change.
*
* If we don't have a card already present, delay the detect event for
* about 20ms (to be on the safe side) before reading the socket status.
*
* Some i82365-based systems send multiple SS_DETECT events during card
* insertion, and the "card present" status bit seems to bounce. This
* will probably be true with GPIO-based card detection systems after
* the product has aged.
*/
static void socket_detect_change(struct pcmcia_socket *skt)
{
if (!(skt->state & SOCKET_SUSPEND)) {
int status;
if (!(skt->state & SOCKET_PRESENT)) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(2));
}
get_socket_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_remove(skt);
if (!(skt->state & SOCKET_PRESENT) &&
(status & SS_DETECT))
socket_insert(skt);
}
}
static int pccardd(void *__skt) static int pccardd(void *__skt)
{ {
struct pcmcia_socket *skt = __skt; struct pcmcia_socket *skt = __skt;
...@@ -809,17 +844,8 @@ static int pccardd(void *__skt) ...@@ -809,17 +844,8 @@ static int pccardd(void *__skt)
if (events) { if (events) {
down(&skt->skt_sem); down(&skt->skt_sem);
if (events & SS_DETECT && !(skt->state & SOCKET_SUSPEND)) { if (events & SS_DETECT)
int status; socket_detect_change(skt);
get_socket_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_shutdown(skt);
if (!(skt->state & SOCKET_PRESENT) &&
(status & SS_DETECT))
socket_insert(skt);
}
if (events & SS_BATDEAD) if (events & SS_BATDEAD)
send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
if (events & SS_BATWARN) if (events & SS_BATWARN)
...@@ -839,21 +865,17 @@ static int pccardd(void *__skt) ...@@ -839,21 +865,17 @@ static int pccardd(void *__skt)
} }
remove_wait_queue(&skt->thread_wait, &wait); remove_wait_queue(&skt->thread_wait, &wait);
socket_shutdown(skt);
complete_and_exit(&skt->thread_done, 0); complete_and_exit(&skt->thread_done, 0);
} }
static void parse_events(void *info, u_int events) void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
{ {
struct pcmcia_socket *s = info;
spin_lock(&s->thread_lock); spin_lock(&s->thread_lock);
s->thread_events |= events; s->thread_events |= events;
spin_unlock(&s->thread_lock); spin_unlock(&s->thread_lock);
wake_up(&s->thread_wait); wake_up(&s->thread_wait);
} /* parse_events */ } /* pcmcia_parse_events */
/*====================================================================== /*======================================================================
...@@ -1114,9 +1136,6 @@ int pcmcia_deregister_client(client_handle_t handle) ...@@ -1114,9 +1136,6 @@ int pcmcia_deregister_client(client_handle_t handle)
handle->event_handler = NULL; handle->event_handler = NULL;
} }
if (--s->real_clients == 0)
register_callback(s, NULL, NULL);
return CS_SUCCESS; return CS_SUCCESS;
} /* deregister_client */ } /* deregister_client */
...@@ -1531,11 +1550,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) ...@@ -1531,11 +1550,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
if (client == NULL) if (client == NULL)
return CS_OUT_OF_RESOURCE; return CS_OUT_OF_RESOURCE;
if (++s->real_clients == 1) {
register_callback(s, &parse_events, s);
parse_events(s, SS_DETECT);
}
*handle = client; *handle = client;
client->state &= ~CLIENT_UNBOUND; client->state &= ~CLIENT_UNBOUND;
client->Socket = s; client->Socket = s;
...@@ -2213,7 +2227,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req) ...@@ -2213,7 +2227,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
if (ret != 0) if (ret != 0)
break; break;
socket_shutdown(skt); socket_remove(skt);
ret = CS_SUCCESS; ret = CS_SUCCESS;
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);
...@@ -2504,6 +2518,7 @@ EXPORT_SYMBOL(pcmcia_write_memory); ...@@ -2504,6 +2518,7 @@ EXPORT_SYMBOL(pcmcia_write_memory);
EXPORT_SYMBOL(dead_socket); EXPORT_SYMBOL(dead_socket);
EXPORT_SYMBOL(CardServices); EXPORT_SYMBOL(CardServices);
EXPORT_SYMBOL(MTDHelperEntry); EXPORT_SYMBOL(MTDHelperEntry);
EXPORT_SYMBOL(pcmcia_parse_events);
struct class pcmcia_socket_class = { struct class pcmcia_socket_class = {
.name = "pcmcia_socket", .name = "pcmcia_socket",
......
...@@ -64,10 +64,8 @@ static struct pci_driver i82092aa_pci_drv = { ...@@ -64,10 +64,8 @@ static struct pci_driver i82092aa_pci_drv = {
/* the pccard structure and its functions */ /* the pccard structure and its functions */
static struct pccard_operations i82092aa_operations = { static struct pccard_operations i82092aa_operations = {
.owner = THIS_MODULE,
.init = i82092aa_init, .init = i82092aa_init,
.suspend = i82092aa_suspend, .suspend = i82092aa_suspend,
.register_callback = i82092aa_register_callback,
.get_status = i82092aa_get_status, .get_status = i82092aa_get_status,
.get_socket = i82092aa_get_socket, .get_socket = i82092aa_get_socket,
.set_socket = i82092aa_set_socket, .set_socket = i82092aa_set_socket,
...@@ -85,12 +83,6 @@ struct socket_info { ...@@ -85,12 +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 */
void (*handler)(void *info, u_int events);
/* callback to the driver of the card */
void *info; /* to be passed to the handler */
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 */
}; };
...@@ -142,6 +134,7 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic ...@@ -142,6 +134,7 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic
sockets[i].socket.map_size = 0x1000; sockets[i].socket.map_size = 0x1000;
sockets[i].socket.irq_mask = 0; sockets[i].socket.irq_mask = 0;
sockets[i].socket.pci_irq = dev->irq; sockets[i].socket.pci_irq = dev->irq;
sockets[i].socket.owner = THIS_MODULE;
sockets[i].number = i; sockets[i].number = i;
...@@ -324,23 +317,6 @@ static int to_cycles(int ns) ...@@ -324,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 (sockets[i].handler)
sockets[i].handler(sockets[i].info, 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;
...@@ -367,8 +343,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -367,8 +343,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
csc = indirect_read(i,I365_CSC); /* card status change register */ csc = indirect_read(i,I365_CSC); /* card status change register */
if ((csc==0) || /* no events on this socket */ if (csc==0) /* no events on this socket */
(sockets[i].handler==NULL)) /* no way to handle events */
continue; continue;
handled = 1; handled = 1;
events = 0; events = 0;
...@@ -389,8 +364,7 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -389,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;
} }
...@@ -475,16 +449,6 @@ static int i82092aa_suspend(struct pcmcia_socket *sock) ...@@ -475,16 +449,6 @@ static int i82092aa_suspend(struct pcmcia_socket *sock)
return retval; return retval;
} }
static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info)
{
unsigned int sock = container_of(socket, struct socket_info, socket)->number;
enter("i82092aa_register_callback");
sockets[sock].handler = handler;
sockets[sock].info = info;
leave("i82092aa_register_callback");
return 0;
} /* i82092aa_register_callback */
static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
{ {
unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned int sock = container_of(socket, struct socket_info, socket)->number;
......
...@@ -35,7 +35,6 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma ...@@ -35,7 +35,6 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma
static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
static int i82092aa_init(struct pcmcia_socket *socket); static int i82092aa_init(struct pcmcia_socket *socket);
static int i82092aa_suspend(struct pcmcia_socket *socket); static int i82092aa_suspend(struct pcmcia_socket *socket);
static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info);
#endif #endif
...@@ -164,8 +164,6 @@ struct i82365_socket { ...@@ -164,8 +164,6 @@ struct i82365_socket {
ioaddr_t ioaddr; ioaddr_t ioaddr;
u_short psock; u_short psock;
u_char cs_irq, intr; u_char cs_irq, intr;
void (*handler)(void *info, u_int events);
void *info;
union { union {
cirrus_state_t cirrus; cirrus_state_t cirrus;
vg46x_state_t vg46x; vg46x_state_t vg46x;
...@@ -863,35 +861,6 @@ static void __init isa_probe(void) ...@@ -863,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 (socket[i].handler)
socket[i].handler(socket[i].info, 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)
{ {
...@@ -911,26 +880,12 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -911,26 +880,12 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
handled = 1; handled = 1;
ISA_LOCK(i, flags); ISA_LOCK(i, flags);
csc = i365_get(i, I365_CSC); csc = i365_get(i, I365_CSC);
if ((csc == 0) || (!socket[i].handler) || if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) {
(i365_get(i, I365_IDENT) & 0x70)) {
ISA_UNLOCK(i, flags); ISA_UNLOCK(i, flags);
continue; continue;
} }
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 {
...@@ -941,12 +896,9 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, ...@@ -941,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;
...@@ -968,16 +920,6 @@ static void pcic_interrupt_wrapper(u_long data) ...@@ -968,16 +920,6 @@ static void pcic_interrupt_wrapper(u_long data)
/*====================================================================*/ /*====================================================================*/
static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
socket[sock].handler = handler;
socket[sock].info = info;
return 0;
} /* pcic_register_callback */
/*====================================================================*/
static int i365_get_status(u_short sock, u_int *value) static int i365_get_status(u_short sock, u_int *value)
{ {
u_int status; u_int status;
...@@ -1400,10 +1342,8 @@ static int pcic_suspend(struct pcmcia_socket *sock) ...@@ -1400,10 +1342,8 @@ static int pcic_suspend(struct pcmcia_socket *sock)
} }
static struct pccard_operations pcic_operations = { static struct pccard_operations pcic_operations = {
.owner = THIS_MODULE,
.init = pcic_init, .init = pcic_init,
.suspend = pcic_suspend, .suspend = pcic_suspend,
.register_callback = pcic_register_callback,
.get_status = pcic_get_status, .get_status = pcic_get_status,
.get_socket = pcic_get_socket, .get_socket = pcic_get_socket,
.set_socket = pcic_set_socket, .set_socket = pcic_set_socket,
...@@ -1464,6 +1404,7 @@ static int __init init_i82365(void) ...@@ -1464,6 +1404,7 @@ static int __init init_i82365(void)
for (i = 0; i < sockets; i++) { for (i = 0; i < sockets; i++) {
socket[i].socket.dev.dev = &i82365_device.dev; socket[i].socket.dev.dev = &i82365_device.dev;
socket[i].socket.ss_entry = &pcic_operations; socket[i].socket.ss_entry = &pcic_operations;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i; socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket); ret = pcmcia_register_socket(&socket[i].socket);
if (ret && i--) { if (ret && i--) {
......
...@@ -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>" : "",
...@@ -295,8 +291,8 @@ static void sa1100_pcmcia_task_handler(void *data) ...@@ -295,8 +291,8 @@ static void sa1100_pcmcia_task_handler(void *data)
events & SS_BATWARN ? "BATWARN " : "", events & SS_BATWARN ? "BATWARN " : "",
events & SS_STSCHG ? "STSCHG " : ""); events & SS_STSCHG ? "STSCHG " : "");
if (events && skt->handler != NULL) if (events)
skt->handler(skt->handler_info, events); pcmcia_parse_events(&skt->socket, events);
} while (events); } while (events);
} }
...@@ -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,44 +326,11 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r ...@@ -330,44 +326,11 @@ 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;
} }
/* sa1100_pcmcia_register_callback()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Implements the register_callback() operation for the in-kernel
* PCMCIA service (formerly SS_RegisterCallback in Card Services). If
* the function pointer `handler' is not NULL, remember the callback
* location in the state for `sock', and increment the usage counter
* for the driver module. (The callback is invoked from the interrupt
* service routine, sa1100_pcmcia_interrupt(), to notify Card Services
* of interesting events.) Otherwise, clear the callback pointer in the
* socket state and decrement the module usage count.
*
* Returns: 0
*/
static int
sa1100_pcmcia_register_callback(struct pcmcia_socket *sock,
void (*handler)(void *, unsigned int),
void *info)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
if (handler) {
if (!try_module_get(skt->ops->owner))
return -ENODEV;
skt->handler_info = info;
skt->handler = handler;
} else {
skt->handler = NULL;
module_put(skt->ops->owner);
}
return 0;
}
/* sa1100_pcmcia_get_status() /* sa1100_pcmcia_get_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
...@@ -655,10 +618,8 @@ static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); ...@@ -655,10 +618,8 @@ static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static struct pccard_operations sa11xx_pcmcia_operations = { static struct pccard_operations sa11xx_pcmcia_operations = {
.owner = THIS_MODULE,
.init = sa1100_pcmcia_sock_init, .init = sa1100_pcmcia_sock_init,
.suspend = sa1100_pcmcia_suspend, .suspend = sa1100_pcmcia_suspend,
.register_callback = sa1100_pcmcia_register_callback,
.get_status = sa1100_pcmcia_get_status, .get_status = sa1100_pcmcia_get_status,
.get_socket = sa1100_pcmcia_get_socket, .get_socket = sa1100_pcmcia_get_socket,
.set_socket = sa1100_pcmcia_set_socket, .set_socket = sa1100_pcmcia_set_socket,
...@@ -765,10 +726,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -765,10 +726,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
memset(skt, 0, sizeof(*skt)); memset(skt, 0, sizeof(*skt));
skt->socket.ss_entry = &sa11xx_pcmcia_operations; skt->socket.ss_entry = &sa11xx_pcmcia_operations;
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;
......
...@@ -59,8 +59,6 @@ struct sa1100_pcmcia_socket { ...@@ -59,8 +59,6 @@ struct sa1100_pcmcia_socket {
unsigned int status; unsigned int status;
socket_state_t cs_state; socket_state_t cs_state;
void (*handler)(void *, unsigned int);
void *handler_info;
unsigned short spd_io[MAX_IO_WIN]; unsigned short spd_io[MAX_IO_WIN];
unsigned short spd_mem[MAX_WIN]; unsigned short spd_mem[MAX_WIN];
...@@ -75,7 +73,6 @@ struct sa1100_pcmcia_socket { ...@@ -75,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 {
......
...@@ -116,8 +116,6 @@ static struct pccard_operations tcic_operations; ...@@ -116,8 +116,6 @@ static struct pccard_operations tcic_operations;
struct tcic_socket { struct tcic_socket {
u_short psock; u_short psock;
void (*handler)(void *info, u_int events);
void *info;
u_char last_sstat; u_char last_sstat;
u_char id; u_char id;
struct pcmcia_socket socket; struct pcmcia_socket socket;
...@@ -433,10 +431,9 @@ static int __init init_tcic(void) ...@@ -433,10 +431,9 @@ static int __init init_tcic(void)
for (i = 0; i < sock; i++) { for (i = 0; i < sock; i++) {
if ((i == ignore) || is_active(i)) continue; if ((i == ignore) || is_active(i)) continue;
socket_table[sockets].psock = i; socket_table[sockets].psock = i;
socket_table[sockets].handler = NULL;
socket_table[sockets].info = NULL;
socket_table[sockets].id = get_tcic_id(); socket_table[sockets].id = get_tcic_id();
socket_table[sockets].socket.owner = THIS_MODULE;
/* only 16-bit cards, memory windows must be size-aligned */ /* only 16-bit cards, memory windows must be size-aligned */
/* No PCI or CardBus support */ /* No PCI or CardBus support */
socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN; socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
...@@ -558,26 +555,6 @@ static void __exit exit_tcic(void) ...@@ -558,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 (socket_table[i].handler)
socket_table[i].handler(socket_table[i].info, 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;
...@@ -605,7 +582,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -605,7 +582,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR); tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
quick = 1; quick = 1;
} }
if ((latch == 0) || (socket_table[psock].handler == NULL)) if (latch == 0)
continue; continue;
events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0; events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0; events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
...@@ -617,10 +594,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) ...@@ -617,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);
} }
} }
...@@ -645,16 +619,6 @@ static void tcic_timer(u_long data) ...@@ -645,16 +619,6 @@ static void tcic_timer(u_long data)
/*====================================================================*/ /*====================================================================*/
static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
socket_table[psock].handler = handler;
socket_table[psock].info = info;
return 0;
} /* tcic_register_callback */
/*====================================================================*/
static int tcic_get_status(struct pcmcia_socket *sock, u_int *value) static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
{ {
u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
...@@ -915,10 +879,8 @@ static int tcic_suspend(struct pcmcia_socket *sock) ...@@ -915,10 +879,8 @@ static int tcic_suspend(struct pcmcia_socket *sock)
} }
static struct pccard_operations tcic_operations = { static struct pccard_operations tcic_operations = {
.owner = THIS_MODULE,
.init = tcic_init, .init = tcic_init,
.suspend = tcic_suspend, .suspend = tcic_suspend,
.register_callback = tcic_register_callback,
.get_status = tcic_get_status, .get_status = tcic_get_status,
.get_socket = tcic_get_socket, .get_socket = tcic_get_socket,
.set_socket = tcic_set_socket, .set_socket = tcic_set_socket,
......
...@@ -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 (socket->handler)
socket->handler(socket->info, 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;
...@@ -771,21 +754,9 @@ static void yenta_close(struct pci_dev *dev) ...@@ -771,21 +754,9 @@ static void yenta_close(struct pci_dev *dev)
} }
static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
socket->handler = handler;
socket->info = info;
return 0;
}
static struct pccard_operations yenta_socket_operations = { static struct pccard_operations yenta_socket_operations = {
.owner = THIS_MODULE,
.init = yenta_init, .init = yenta_init,
.suspend = yenta_suspend, .suspend = yenta_suspend,
.register_callback = yenta_register_callback,
.get_status = yenta_get_status, .get_status = yenta_get_status,
.get_socket = yenta_get_socket, .get_socket = yenta_get_socket,
.set_socket = yenta_set_socket, .set_socket = yenta_set_socket,
...@@ -860,11 +831,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -860,11 +831,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
socket->socket.ss_entry = &yenta_socket_operations; socket->socket.ss_entry = &yenta_socket_operations;
socket->socket.dev.dev = &dev->dev; socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket; socket->socket.driver_data = socket;
socket->socket.owner = THIS_MODULE;
/* 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..
...@@ -907,8 +878,6 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -907,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,11 +99,6 @@ struct yenta_socket { ...@@ -99,11 +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;
void (*handler)(void *, unsigned int);
void *info;
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;
......
...@@ -119,7 +119,6 @@ typedef struct cb_bridge_map { ...@@ -119,7 +119,6 @@ typedef struct cb_bridge_map {
struct pcmcia_socket; struct pcmcia_socket;
struct pccard_operations { struct pccard_operations {
struct module *owner;
int (*init)(struct pcmcia_socket *sock); int (*init)(struct pcmcia_socket *sock);
int (*suspend)(struct pcmcia_socket *sock); int (*suspend)(struct pcmcia_socket *sock);
int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info); int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
...@@ -169,6 +168,7 @@ struct config_t; ...@@ -169,6 +168,7 @@ struct config_t;
struct region_t; struct region_t;
struct pcmcia_socket { struct pcmcia_socket {
struct module *owner;
spinlock_t lock; spinlock_t lock;
struct pccard_operations * ss_entry; struct pccard_operations * ss_entry;
socket_state_t socket; socket_state_t socket;
...@@ -235,6 +235,7 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr); ...@@ -235,6 +235,7 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr);
extern void pcmcia_parse_events(struct pcmcia_socket *socket, unsigned int events);
extern int pcmcia_register_socket(struct pcmcia_socket *socket); extern int pcmcia_register_socket(struct pcmcia_socket *socket);
extern void pcmcia_unregister_socket(struct pcmcia_socket *socket); extern void pcmcia_unregister_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