Commit e05b1590 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] pcmcia: call device drivers from ds, not from cs

Call the PCMCIA 16-bit device drivers from ds.c instead of cs.c. Also,
remove the delayed handling of CS_REMOVAL events, but keep the ordering
the same as it used to be due to the delay.
Signed-off-by: default avatarDominik Brodowski <linux@brodo.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f1395ea3
......@@ -401,10 +401,18 @@ static void shutdown_socket(struct pcmcia_socket *s)
======================================================================*/
static int pcmcia_send_event(struct pcmcia_socket *s, event_t event, int priority)
/* NOTE: send_event needs to be called with skt->sem held. */
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
int ret;
if (s->state & SOCKET_CARDBUS)
return 0;
cs_dbg(s, 1, "send_event(event %d, pri %d, callback 0x%p)\n",
event, priority, s->callback);
if (!s->callback)
return 0;
if (!try_module_get(s->callback->owner))
......@@ -417,35 +425,6 @@ static int pcmcia_send_event(struct pcmcia_socket *s, event_t event, int priorit
return ret;
}
/* NOTE: send_event needs to be called with skt->sem held. */
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
client_t *client = s->clients;
int ret;
cs_dbg(s, 1, "send_event(event %d, pri %d)\n",
event, priority);
ret = 0;
if (s->state & SOCKET_CARDBUS)
return 0;
ret = pcmcia_send_event(s, event, priority);
if (ret)
return (ret);
for (; client; client = client->next) {
if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
continue;
if (client->EventMask & event) {
ret = EVENT(client, event, priority);
if (ret != 0)
return ret;
}
}
return ret;
} /* send_event */
static void socket_remove_drivers(struct pcmcia_socket *skt)
{
client_t *client;
......@@ -1404,7 +1383,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)
pcmcia_send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else
s->callback = NULL;
err:
......
......@@ -117,7 +117,6 @@ struct pcmcia_bus_socket {
user_info_t *user;
int req_pending, req_result;
wait_queue_head_t queue, request;
struct work_struct removal;
socket_bind_t *bind;
struct pcmcia_socket *parent;
};
......@@ -471,48 +470,68 @@ static int handle_request(struct pcmcia_bus_socket *s, event_t event)
return CS_SUCCESS;
}
static void handle_removal(void *data)
{
struct pcmcia_bus_socket *s = data;
handle_event(s, CS_EVENT_CARD_REMOVAL);
s->state &= ~DS_SOCKET_REMOVAL_PENDING;
}
/*======================================================================
The card status event handler.
======================================================================*/
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
int ret = 0;
client_t *client;
for (client = s->clients; client; client = client->next) {
if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
continue;
if (client->EventMask & event) {
ret = EVENT(client, event, priority);
if (ret != 0)
return ret;
}
}
return ret;
} /* send_event */
/* 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)
{
struct pcmcia_bus_socket *s = skt->pcmcia;
struct pcmcia_bus_socket *s = skt->pcmcia;
int ret = 0;
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
event, priority, s);
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
event, priority, s);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
s->state &= ~DS_SOCKET_PRESENT;
if (!(s->state & DS_SOCKET_REMOVAL_PENDING)) {
s->state |= DS_SOCKET_REMOVAL_PENDING;
schedule_delayed_work(&s->removal, HZ/10);
}
break;
case CS_EVENT_CARD_INSERTION:
s->state |= DS_SOCKET_PRESENT;
handle_event(s, event);
break;
switch (event) {
case CS_EVENT_EJECTION_REQUEST:
return handle_request(s, event);
break;
case CS_EVENT_CARD_REMOVAL:
s->state &= ~DS_SOCKET_PRESENT;
send_event(skt, event, priority);
handle_event(s, event);
break;
default:
handle_event(s, event);
break;
case CS_EVENT_CARD_INSERTION:
s->state |= DS_SOCKET_PRESENT;
handle_event(s, event);
send_event(skt, event, priority);
break;
case CS_EVENT_EJECTION_REQUEST:
ret = handle_request(s, event);
if (ret)
break;
ret = send_event(skt, event, priority);
break;
default:
handle_event(s, event);
send_event(skt, event, priority);
break;
}
return 0;
......@@ -1099,7 +1118,6 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
init_waitqueue_head(&s->request);
/* initialize data */
INIT_WORK(&s->removal, handle_removal, s);
s->parent = socket;
/* Set up hotline to Card Services */
......@@ -1128,8 +1146,6 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev)
pccard_register_pcmcia(socket, NULL);
flush_scheduled_work();
socket->pcmcia->state |= DS_SOCKET_DEAD;
pcmcia_put_bus_socket(socket->pcmcia);
socket->pcmcia = NULL;
......
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