Ohad, > -----Original Message----- > From: linux-omap-owner@xxxxxxxxxxxxxxx [mailto:linux-omap- > owner@xxxxxxxxxxxxxxx] On Behalf Of Ohad Ben-Cohen > Sent: Wednesday, August 11, 2010 11:52 PM > To: linux-wireless@xxxxxxxxxxxxxxx; linux-mmc@xxxxxxxxxxxxxxx; linux- > omap@xxxxxxxxxxxxxxx > Cc: Ido Yariv; Mark Brown; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; > Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm@linux- > foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; > Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen > Subject: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board > data > > Dynamically create and register a platform driver, that will > be used to to receive board-specific information like irq and > reference clock numbers. > > The driver is created dynamically in order to avoid the 1-device > limitation of a fixed platform driver name. > > Signed-off-by: Ohad Ben-Cohen <ohad@xxxxxxxxxx> > --- > drivers/net/wireless/wl12xx/wl1271.h | 12 ++++ > drivers/net/wireless/wl12xx/wl1271_sdio.c | 103 > +++++++++++++++++++++++++++-- > 2 files changed, 108 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/wireless/wl12xx/wl1271.h > b/drivers/net/wireless/wl12xx/wl1271.h > index faa5925..013eabb 100644 > --- a/drivers/net/wireless/wl12xx/wl1271.h > +++ b/drivers/net/wireless/wl12xx/wl1271.h > @@ -31,6 +31,7 @@ > #include <linux/list.h> > #include <linux/bitops.h> > #include <net/mac80211.h> > +#include <linux/platform_device.h> > > #include "wl1271_conf.h" > #include "wl1271_ini.h" > @@ -319,8 +320,19 @@ struct wl1271_if_operations { > void (*disable_irq)(struct wl1271 *wl); > }; > > +/* exact size needed for "wl1271_plat.x" */ > +#define WL12XX_PLAT_NAME_LEN 14 > + > +struct wl12xx_plat_instance { > + struct platform_driver pdriver; > + char name[WL12XX_PLAT_NAME_LEN]; > + struct wl12xx_platform_data *pdata; > + struct completion data_ready; > +}; > + > struct wl1271 { > struct platform_device *plat_dev; > + struct wl12xx_plat_instance *pinstance; > struct ieee80211_hw *hw; > bool mac80211_registered; > > diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c > b/drivers/net/wireless/wl12xx/wl1271_sdio.c > index c41293a..68b512b 100644 > --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c > +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c > @@ -28,7 +28,11 @@ > #include <linux/mmc/sdio_func.h> > #include <linux/mmc/sdio_ids.h> > #include <linux/mmc/card.h> > +#include <linux/mmc/host.h> > +#include <linux/wl12xx.h> > #include <linux/gpio.h> > +#include <linux/platform_device.h> > +#include <linux/completion.h> > > #include "wl1271.h" > #include "wl12xx_80211.h" > @@ -182,10 +186,84 @@ static struct wl1271_if_operations sdio_ops = { > .disable_irq = wl1271_sdio_disable_interrupts > }; > > +static int wl1271_plat_probe(struct platform_device *pdev) > +{ > + struct wl12xx_platform_data *pdata; > + struct platform_driver *pdriver; > + struct wl12xx_plat_instance *pinstance; > + What about checking for pdev here before extracting pdata? > + pdata = pdev->dev.platform_data; > + if (!pdata) { > + wl1271_error("no platform data"); > + return -ENODEV; > + } > + > + pdriver = container_of(pdev->dev.driver, struct platform_driver, > + driver); > + pinstance = container_of(pdriver, struct wl12xx_plat_instance, > pdriver); > + > + pinstance->pdata = pdata; > + > + complete(&pinstance->data_ready); > + > + return 0; > +} > + > +static struct wl12xx_platform_data *wl1271_get_data(struct wl1271 *wl, > int id) > +{ > + int ret; > + struct wl12xx_plat_instance *pinstance; > + > + #define WL1271_PLAT_NAME "wl1271_plat.%d" > + > + pinstance = kzalloc(sizeof(*pinstance), GFP_KERNEL); > + if (!pinstance) > + return ERR_PTR(-ENOMEM); > + > + init_completion(&pinstance->data_ready); > + > + pinstance->pdriver.probe = wl1271_plat_probe; > + > + ret = snprintf(pinstance->name, sizeof(pinstance->name), > + WL1271_PLAT_NAME, id); > + if (ret >= WL12XX_PLAT_NAME_LEN) { > + wl1271_error("truncated plat drv name\n"); > + goto out_free; > + } > + > + pinstance->pdriver.driver.name = pinstance->name; > + pinstance->pdriver.driver.owner = THIS_MODULE; > + > + ret = platform_driver_register(&pinstance->pdriver); > + if (ret < 0) { > + wl1271_error("failed to register plat driver: %d", ret); > + goto out_free; > + } > + > + ret = wait_for_completion_interruptible_timeout(&pinstance- > >data_ready, > + msecs_to_jiffies(15000)); > + if (ret <= 0) { > + wl1271_error("can't get platform device (%d)", ret); > + ret = (ret == 0 ? -EAGAIN : ret); > + goto unreg; > + } > + > + wl->pinstance = pinstance; > + > + return pinstance->pdata; > + > +unreg: > + platform_driver_unregister(&pinstance->pdriver); > +out_free: > + kfree(pinstance); > + return ERR_PTR(ret); > +} > + > static int __devinit wl1271_probe(struct sdio_func *func, > const struct sdio_device_id *id) > { > struct ieee80211_hw *hw; > + struct wl12xx_platform_data *wlan_data; > struct wl1271 *wl; > int ret; > > @@ -205,17 +283,24 @@ static int __devinit wl1271_probe(struct sdio_func > *func, > /* Grab access to FN0 for ELP reg. */ > func->card->quirks |= MMC_QUIRK_LENIENT_FN0; > > + wlan_data = wl1271_get_data(wl, func->card->host->index); > + if (IS_ERR(wlan_data)) { > + ret = PTR_ERR(wlan_data); > + wl1271_error("missing wlan data (needed for irq/ref_clk)!"); > + goto out_free; > + } > + > wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); > if (wl->irq < 0) { > ret = wl->irq; > wl1271_error("could not get irq!"); > - goto out_free; > + goto put_data; > } > > ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); > if (ret < 0) { > wl1271_error("request_irq() failed: %d", ret); > - goto out_free; > + goto put_data; > } > > set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); > @@ -236,13 +321,13 @@ static int __devinit wl1271_probe(struct sdio_func > *func, > > return 0; > > - out_irq: > +out_irq: > free_irq(wl->irq, wl); > - > - > - out_free: > +put_data: > + platform_driver_unregister(&wl->pinstance->pdriver); > + kfree(wl->pinstance); > +out_free: > wl1271_free_hw(wl); > - > return ret; > } > > @@ -253,6 +338,10 @@ static void __devexit wl1271_remove(struct sdio_func > *func) > free_irq(wl->irq, wl); > > wl1271_unregister_hw(wl); > + > + platform_driver_unregister(&wl->pinstance->pdriver); > + kfree(wl->pinstance); > + > wl1271_free_hw(wl); > } > > -- > 1.7.0.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html