pcmcia: split up central event handler
Split up the central event handler for 16bit cards into three individual functions. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
Родитель
216d7cdd3b
Коммит
7b24e79882
|
@ -252,30 +252,6 @@ struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr)
|
|||
}
|
||||
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
|
||||
|
||||
/*
|
||||
* The central event handler. Send_event() sends an event to the
|
||||
* 16-bit subsystem, which then calls the relevant device drivers.
|
||||
* Parse_events() interprets the event bits from
|
||||
* a card status change report. Do_shutdown() handles the high
|
||||
* priority stuff associated with a card removal.
|
||||
*/
|
||||
|
||||
/* NOTE: send_event needs to be called with skt->sem held. */
|
||||
|
||||
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
|
||||
{
|
||||
if ((s->state & SOCKET_CARDBUS) && (event != CS_EVENT_CARD_REMOVAL))
|
||||
return 0;
|
||||
|
||||
dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",
|
||||
event, priority, s->callback);
|
||||
|
||||
if (!s->callback)
|
||||
return 0;
|
||||
|
||||
return s->callback->event(s, event, priority);
|
||||
}
|
||||
|
||||
static int socket_reset(struct pcmcia_socket *skt)
|
||||
{
|
||||
int status, i;
|
||||
|
@ -318,7 +294,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
|
|||
|
||||
dev_dbg(&s->dev, "shutdown\n");
|
||||
|
||||
send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
|
||||
if (s->callback)
|
||||
s->callback->remove(s);
|
||||
|
||||
mutex_lock(&s->ops_mutex);
|
||||
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
|
||||
|
@ -469,7 +446,8 @@ static int socket_insert(struct pcmcia_socket *skt)
|
|||
dev_dbg(&skt->dev, "insert done\n");
|
||||
mutex_unlock(&skt->ops_mutex);
|
||||
|
||||
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
|
||||
if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
|
||||
skt->callback->add(skt);
|
||||
} else {
|
||||
mutex_unlock(&skt->ops_mutex);
|
||||
socket_shutdown(skt);
|
||||
|
@ -546,8 +524,8 @@ static int socket_late_resume(struct pcmcia_socket *skt)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
|
||||
if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
|
||||
skt->callback->early_resume(skt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -766,7 +744,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
|
|||
s->callback = c;
|
||||
|
||||
if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
|
||||
send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
|
||||
s->callback->add(s);
|
||||
} else
|
||||
s->callback = NULL;
|
||||
err:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
||||
*
|
||||
* (C) 1999 David A. Hinds
|
||||
* (C) 2003 - 2008 Dominik Brodowski
|
||||
* (C) 2003 - 2010 Dominik Brodowski
|
||||
*
|
||||
*
|
||||
* This file contains definitions _only_ needed by the PCMCIA core modules.
|
||||
|
@ -106,11 +106,12 @@ void cb_free(struct pcmcia_socket *s);
|
|||
|
||||
struct pcmcia_callback{
|
||||
struct module *owner;
|
||||
int (*event) (struct pcmcia_socket *s,
|
||||
event_t event, int priority);
|
||||
int (*add) (struct pcmcia_socket *s);
|
||||
int (*remove) (struct pcmcia_socket *s);
|
||||
void (*requery) (struct pcmcia_socket *s);
|
||||
int (*validate) (struct pcmcia_socket *s, unsigned int *i);
|
||||
int (*suspend) (struct pcmcia_socket *s);
|
||||
int (*early_resume) (struct pcmcia_socket *s);
|
||||
int (*resume) (struct pcmcia_socket *s);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
||||
*
|
||||
* (C) 1999 David A. Hinds
|
||||
* (C) 2003 - 2006 Dominik Brodowski
|
||||
* (C) 2003 - 2010 Dominik Brodowski
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -1208,76 +1208,57 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
The card status event handler.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
/* Normally, the event is passed to individual drivers after
|
||||
* informing userspace. Only for CS_EVENT_CARD_REMOVAL this
|
||||
* is inversed to maintain historic compatibility.
|
||||
*/
|
||||
|
||||
static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
|
||||
static int pcmcia_bus_remove(struct pcmcia_socket *skt)
|
||||
{
|
||||
struct pcmcia_socket *s = pcmcia_get_socket(skt);
|
||||
atomic_set(&skt->present, 0);
|
||||
pcmcia_card_remove(skt, NULL);
|
||||
|
||||
if (!s) {
|
||||
dev_printk(KERN_ERR, &skt->dev,
|
||||
"PCMCIA obtaining reference to socket " \
|
||||
"failed, event 0x%x lost!\n", event);
|
||||
return -ENODEV;
|
||||
mutex_lock(&skt->ops_mutex);
|
||||
destroy_cis_cache(skt);
|
||||
pcmcia_cleanup_irq(skt);
|
||||
mutex_unlock(&skt->ops_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcmcia_bus_add(struct pcmcia_socket *skt)
|
||||
{
|
||||
atomic_set(&skt->present, 1);
|
||||
|
||||
mutex_lock(&skt->ops_mutex);
|
||||
skt->pcmcia_state.has_pfc = 0;
|
||||
destroy_cis_cache(skt); /* to be on the safe side... */
|
||||
mutex_unlock(&skt->ops_mutex);
|
||||
|
||||
pcmcia_card_add(skt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
|
||||
{
|
||||
if (!verify_cis_cache(skt)) {
|
||||
pcmcia_put_socket(skt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
|
||||
event, priority, skt);
|
||||
dev_dbg(&skt->dev, "cis mismatch - different card\n");
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
atomic_set(&skt->present, 0);
|
||||
pcmcia_card_remove(skt, NULL);
|
||||
mutex_lock(&s->ops_mutex);
|
||||
destroy_cis_cache(s);
|
||||
pcmcia_cleanup_irq(s);
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
break;
|
||||
/* first, remove the card */
|
||||
pcmcia_bus_remove(skt);
|
||||
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
atomic_set(&skt->present, 1);
|
||||
mutex_lock(&s->ops_mutex);
|
||||
s->pcmcia_state.has_pfc = 0;
|
||||
destroy_cis_cache(s); /* to be on the safe side... */
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
pcmcia_card_add(skt);
|
||||
break;
|
||||
mutex_lock(&skt->ops_mutex);
|
||||
destroy_cis_cache(skt);
|
||||
kfree(skt->fake_cis);
|
||||
skt->fake_cis = NULL;
|
||||
skt->functions = 0;
|
||||
mutex_unlock(&skt->ops_mutex);
|
||||
|
||||
case CS_EVENT_PM_RESUME:
|
||||
if (verify_cis_cache(skt) != 0) {
|
||||
dev_dbg(&skt->dev, "cis mismatch - different card\n");
|
||||
/* first, remove the card */
|
||||
ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
|
||||
mutex_lock(&s->ops_mutex);
|
||||
destroy_cis_cache(skt);
|
||||
kfree(skt->fake_cis);
|
||||
skt->fake_cis = NULL;
|
||||
s->functions = 0;
|
||||
mutex_unlock(&s->ops_mutex);
|
||||
/* now, add the new card */
|
||||
ds_event(skt, CS_EVENT_CARD_INSERTION,
|
||||
CS_EVENT_PRI_LOW);
|
||||
}
|
||||
break;
|
||||
/* now, add the new card */
|
||||
pcmcia_bus_add(skt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pcmcia_put_socket(s);
|
||||
|
||||
return 0;
|
||||
} /* ds_event */
|
||||
|
||||
/*
|
||||
* NOTE: This is racy. There's no guarantee the card will still be
|
||||
|
@ -1306,10 +1287,12 @@ EXPORT_SYMBOL(pcmcia_dev_present);
|
|||
|
||||
static struct pcmcia_callback pcmcia_bus_callback = {
|
||||
.owner = THIS_MODULE,
|
||||
.event = ds_event,
|
||||
.add = pcmcia_bus_add,
|
||||
.remove = pcmcia_bus_remove,
|
||||
.requery = pcmcia_requery,
|
||||
.validate = pccard_validate_cis,
|
||||
.suspend = pcmcia_bus_suspend,
|
||||
.early_resume = pcmcia_bus_early_resume,
|
||||
.resume = pcmcia_bus_resume,
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче