}
}
-static int send_event(struct pcmcia_socket *s, event_t event, int priority);
-
static void shutdown_socket(struct pcmcia_socket *s)
{
client_t **c;
======================================================================*/
+
+static int pcmcia_send_event(struct pcmcia_socket *s, event_t event, int priority)
+{
+ int ret;
+
+ if (!s->callback)
+ return 0;
+ if (!try_module_get(s->callback->owner))
+ return 0;
+
+ ret = s->callback->event(s, event, priority);
+
+ module_put(s->callback->owner);
+
+ 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;
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;
return CS_OUT_OF_RESOURCE;
} /* register_client */
+/* register pcmcia_callback */
+int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
+{
+ int ret = 0;
+
+ /* s->skt_sem also protects s->callback */
+ down(&s->skt_sem);
+
+ if (c) {
+ /* registration */
+ if (s->callback) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ s->callback = c;
+
+ if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
+ pcmcia_send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ } else
+ s->callback = NULL;
+ err:
+ up(&s->skt_sem);
+
+ return ret;
+}
+EXPORT_SYMBOL(pccard_register_pcmcia);
+
/*====================================================================*/
int pcmcia_release_configuration(client_handle_t handle)
/* Socket state information */
struct pcmcia_bus_socket {
atomic_t refcount;
- client_handle_t handle;
+ struct pcmcia_callback callback;
int state;
user_info_t *user;
int req_pending, req_result;
======================================================================*/
-static int ds_event(event_t event, int priority,
- event_callback_args_t *args)
+static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
- struct pcmcia_bus_socket *s;
+ struct pcmcia_bus_socket *s = skt->pcmcia;
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, args->client_handle);
- s = args->client_data;
+ event, priority, s);
switch (event) {
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_dev->class_data;
- client_reg_t client_reg;
- bind_req_t bind;
struct pcmcia_bus_socket *s;
int ret;
s->parent = socket;
/* Set up hotline to Card Services */
- client_reg.dev_info = bind.dev_info = &dev_info;
-
- bind.Socket = socket;
- bind.Function = BIND_FN_ALL;
- ret = pcmcia_bind_device(&bind);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindDevice, ret);
- kfree(s);
- return -EINVAL;
- }
+ s->callback.owner = THIS_MODULE;
+ s->callback.event = &ds_event;
+ socket->pcmcia = s;
- client_reg.Attributes = INFO_MASTER_CLIENT;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.event_handler = &ds_event;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = s;
- ret = pcmcia_register_client(&s->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, RegisterClient, ret);
- kfree(s);
- return -EINVAL;
+ ret = pccard_register_pcmcia(socket, &s->callback);
+ if (ret) {
+ printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+ pcmcia_put_bus_socket(s);
+ socket->pcmcia = NULL;
+ return (ret);
}
- socket->pcmcia = s;
-
return 0;
}
if (!socket || !socket->pcmcia)
return;
- flush_scheduled_work();
+ pccard_register_pcmcia(socket, NULL);
- pcmcia_deregister_client(socket->pcmcia->handle);
+ flush_scheduled_work();
socket->pcmcia->state |= DS_SOCKET_DEAD;
pcmcia_put_bus_socket(socket->pcmcia);