Add pcmcia devices without cardmgr's interaction If it's a "static" socket or the non-static socket has all its resources set up, there's no reason why the PCMCIA core can't detect and set up pcmcia devices without cardmgr's interaction. Matching is still done in userspace, though; and if the PCMCIA core misses something, cardmgr can still add devices... Signed-off-by: Dominik Brodowski Index: 2.6.10-rc3/drivers/pcmcia/cs_internal.h =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/cs_internal.h 2004-12-06 15:07:18.807198912 +0100 +++ 2.6.10-rc3/drivers/pcmcia/cs_internal.h 2004-12-06 15:07:32.862062248 +0100 @@ -161,6 +161,7 @@ struct pcmcia_callback{ struct module *owner; int (*event) (struct pcmcia_socket *s, event_t event, int priority); + int (*resources_done) (struct pcmcia_socket *s); }; int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); Index: 2.6.10-rc3/drivers/pcmcia/ds.c =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/ds.c 2004-12-06 15:07:18.808198760 +0100 +++ 2.6.10-rc3/drivers/pcmcia/ds.c 2004-12-06 15:07:42.955527808 +0100 @@ -540,6 +540,35 @@ } +static int pcmcia_card_add(struct pcmcia_socket *s) +{ + cisinfo_t cisinfo; + cistpl_longlink_mfc_t mfc; + unsigned int no_funcs, i; + int ret = 0; + + if (!(s->resource_setup_done)) + return -EAGAIN; /* try again, but later... */ + + pcmcia_validate_mem(s); + ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); + if (ret || !cisinfo.Chains) { + ds_dbg(0, "invalid CIS or invalid resources\n"); + return -ENODEV; + } + + if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) + no_funcs = mfc.nfn; + else + no_funcs = 1; + + for (i=0; i < no_funcs; i++) + pcmcia_device_add(s->pcmcia, i); + + return (ret); +} + + static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { struct pcmcia_device * p_dev = to_pcmcia_dev(dev); struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); @@ -673,8 +702,8 @@ case CS_EVENT_CARD_INSERTION: s->state |= DS_SOCKET_PRESENT; + pcmcia_card_add(skt); handle_event(s, event); - send_event(skt, event, priority); break; case CS_EVENT_EJECTION_REQUEST: @@ -761,7 +790,12 @@ } else p_dev->cardmgr = p_drv; + /* + * Prevent this racing with a card insertion. + */ + down(&s->parent->skt_sem); bus_rescan_devices(&pcmcia_bus_type); + up(&s->parent->skt_sem); /* check whether the driver indeed matched. I don't care if this * is racy or not, because it can only happen on cardmgr access @@ -832,10 +866,6 @@ pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */ - /* - * Prevent this racing with a card insertion. - */ - down(&s->skt_sem); *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = s; @@ -872,11 +902,9 @@ EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); } - up(&s->skt_sem); return CS_SUCCESS; out_no_resource: - up(&s->skt_sem); pcmcia_put_dev(p_dev); return CS_OUT_OF_RESOURCE; } /* register_client */ @@ -1456,6 +1484,7 @@ /* Set up hotline to Card Services */ s->callback.owner = THIS_MODULE; s->callback.event = &ds_event; + s->callback.resources_done = &pcmcia_card_add; socket->pcmcia = s; ret = pccard_register_pcmcia(socket, &s->callback); Index: 2.6.10-rc3/drivers/pcmcia/socket_sysfs.c =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/socket_sysfs.c 2004-12-06 15:07:18.808198760 +0100 +++ 2.6.10-rc3/drivers/pcmcia/socket_sysfs.c 2004-12-06 15:07:32.864061944 +0100 @@ -141,7 +141,17 @@ s->resource_setup_done = 1; spin_unlock_irqrestore(&s->lock, flags); - /* later on, a call which starts PCMCIA device registration will be added here */ + down(&s->skt_sem); + if ((s->callback) && + (s->state & SOCKET_PRESENT) && + !(s->state & SOCKET_CARDBUS)) { + if (try_module_get(s->callback->owner)) { + s->callback->resources_done(s); + module_put(s->callback->owner); + } + } + up(&s->skt_sem); + return count; } spin_unlock_irqrestore(&s->lock, flags);