X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpnp%2Fcard.c;h=91c047a7e635d832d7090bf62522a99e6dca8e34;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=97eeecfaef1b712682d7a4224682f4463c356050;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 97eeecfae..91c047a7e 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -5,21 +5,13 @@ * */ -#include #include #include - -#ifdef CONFIG_PNP_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - #include #include "base.h" LIST_HEAD(pnp_cards); -LIST_HEAD(pnp_card_drivers); +static LIST_HEAD(pnp_card_drivers); static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) @@ -54,7 +46,7 @@ static void card_remove(struct pnp_dev * dev) { dev->card_link = NULL; } - + static void card_remove_first(struct pnp_dev * dev) { struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); @@ -67,29 +59,34 @@ static void card_remove_first(struct pnp_dev * dev) card_remove(dev); } -static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv) +static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) { - const struct pnp_card_device_id *id = match_card(drv,card); - if (id) { - struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link)); - if (!clink) - return 0; - clink->card = card; - clink->driver = drv; - if (drv->probe) { - if (drv->probe(clink, id)>=0) - return 1; - else { - struct pnp_dev * dev; - card_for_each_dev(card, dev) { - if (dev->card_link == clink) - pnp_release_card_device(dev); - } - kfree(clink); - } - } else - return 1; + const struct pnp_card_device_id *id; + struct pnp_card_link *clink; + struct pnp_dev *dev; + + if (!drv->probe) + return 0; + id = match_card(drv,card); + if (!id) + return 0; + + clink = pnp_alloc(sizeof(*clink)); + if (!clink) + return 0; + clink->card = card; + clink->driver = drv; + clink->pm_state = PMSG_ON; + + if (drv->probe(clink, id) >= 0) + return 1; + + /* Recovery */ + card_for_each_dev(card, dev) { + if (dev->card_link == clink) + pnp_release_card_device(dev); } + kfree(clink); return 0; } @@ -140,7 +137,7 @@ static void pnp_release_card(struct device *dmdev) } -static ssize_t pnp_show_card_name(struct device *dmdev, char *buf) +static ssize_t pnp_show_card_name(struct device *dmdev, struct device_attribute *attr, char *buf) { char *str = buf; struct pnp_card *card = to_pnp_card(dmdev); @@ -150,7 +147,7 @@ static ssize_t pnp_show_card_name(struct device *dmdev, char *buf) static DEVICE_ATTR(name,S_IRUGO,pnp_show_card_name,NULL); -static ssize_t pnp_show_card_ids(struct device *dmdev, char *buf) +static ssize_t pnp_show_card_ids(struct device *dmdev, struct device_attribute *attr, char *buf) { char *str = buf; struct pnp_card *card = to_pnp_card(dmdev); @@ -167,9 +164,17 @@ static DEVICE_ATTR(card_id,S_IRUGO,pnp_show_card_ids,NULL); static int pnp_interface_attach_card(struct pnp_card *card) { - device_create_file(&card->dev,&dev_attr_name); - device_create_file(&card->dev,&dev_attr_card_id); + int rc = device_create_file(&card->dev,&dev_attr_name); + if (rc) return rc; + + rc = device_create_file(&card->dev,&dev_attr_card_id); + if (rc) goto err_name; + return 0; + +err_name: + device_remove_file(&card->dev,&dev_attr_name); + return rc; } /** @@ -259,7 +264,6 @@ int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) /** * pnp_remove_card_device- removes a device from the specified card - * @card: pointer to the card to remove from * @dev: pointer to the device to remove */ @@ -274,7 +278,7 @@ void pnp_remove_card_device(struct pnp_dev * dev) /** * pnp_request_card_device - Searches for a PnP device under the specified card - * @lcard: pointer to the card link, cannot be NULL + * @clink: pointer to the card link, cannot be NULL * @id: pointer to a PnP ID structure that explains the rules for finding the device * @from: Starting place to search from. If NULL it will start from the begining. */ @@ -310,16 +314,20 @@ found: down_write(&dev->dev.bus->subsys.rwsem); dev->card_link = clink; dev->dev.driver = &drv->link.driver; - if (drv->link.driver.probe) { - if (drv->link.driver.probe(&dev->dev)) { - dev->dev.driver = NULL; - return NULL; - } - } - device_bind_driver(&dev->dev); + if (pnp_bus_type.probe(&dev->dev)) + goto err_out; + if (device_bind_driver(&dev->dev)) + goto err_out; + up_write(&dev->dev.bus->subsys.rwsem); return dev; + +err_out: + dev->dev.driver = NULL; + dev->card_link = NULL; + up_write(&dev->dev.bus->subsys.rwsem); + return NULL; } /** @@ -339,6 +347,28 @@ void pnp_release_card_device(struct pnp_dev * dev) up_write(&dev->dev.bus->subsys.rwsem); } +/* + * suspend/resume callbacks + */ +static int card_suspend(struct pnp_dev *dev, pm_message_t state) +{ + struct pnp_card_link *link = dev->card_link; + if (link->pm_state.event == state.event) + return 0; + link->pm_state = state; + return link->driver->suspend(link, state); +} + +static int card_resume(struct pnp_dev *dev) +{ + struct pnp_card_link *link = dev->card_link; + if (link->pm_state.event == PM_EVENT_ON) + return 0; + link->pm_state = PMSG_ON; + link->driver->resume(link); + return 0; +} + /** * pnp_register_card_driver - registers a PnP card driver with the PnP Layer * @drv: pointer to the driver to register @@ -346,7 +376,7 @@ void pnp_release_card_device(struct pnp_dev * dev) int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count = 0; + int error; struct list_head *pos, *temp; drv->link.name = drv->name; @@ -354,17 +384,22 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) drv->link.flags = drv->flags; drv->link.probe = NULL; drv->link.remove = &card_remove_first; + drv->link.suspend = drv->suspend ? card_suspend : NULL; + drv->link.resume = drv->resume ? card_resume : NULL; + + error = pnp_register_driver(&drv->link); + if (error < 0) + return error; spin_lock(&pnp_lock); list_add_tail(&drv->global_list, &pnp_card_drivers); spin_unlock(&pnp_lock); - pnp_register_driver(&drv->link); list_for_each_safe(pos,temp,&pnp_cards){ struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); - count += card_probe(card,drv); + card_probe(card,drv); } - return count; + return 0; } /** @@ -380,11 +415,13 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv) pnp_unregister_driver(&drv->link); } +#if 0 EXPORT_SYMBOL(pnp_add_card); EXPORT_SYMBOL(pnp_remove_card); EXPORT_SYMBOL(pnp_add_card_device); EXPORT_SYMBOL(pnp_remove_card_device); EXPORT_SYMBOL(pnp_add_card_id); +#endif /* 0 */ EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_register_card_driver);