X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fwl1251%2Fsdio.c;h=d141d838c800734af51daf7476e8488b7002be8e;hb=49a086ec91d906f90799a4937300a60107c27df4;hp=f78694295c397f053f4a00115ff2aff22d8a4379;hpb=7fd21be75dce605e7cf273bd64b6d733d422fb04;p=pandora-kernel.git diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index f78694295c39..d141d838c800 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -31,6 +31,15 @@ #include "wl1251.h" +static bool force_nvs_file = false; +module_param(force_nvs_file, bool, 0644); +MODULE_PARM_DESC(force_nvs_file, "Force loading NVS data from file, " + "not EEPROM. Default: n/N/0"); +static bool dump_eeprom = false; +module_param(dump_eeprom, bool, 0644); +MODULE_PARM_DESC(dump_eeprom, "Dump EEPROM on module load and makes it " + "accessable through debugfs. Default: n/N/0"); + #ifndef SDIO_VENDOR_ID_TI #define SDIO_VENDOR_ID_TI 0x104c #endif @@ -151,16 +160,6 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) sdio_release_host(func); } -/* Interrupts when using dedicated WLAN_IRQ pin */ -static irqreturn_t wl1251_line_irq(int irq, void *cookie) -{ - struct wl1251 *wl = cookie; - - ieee80211_queue_work(wl->hw, &wl->irq_work); - - return IRQ_HANDLED; -} - static void wl1251_enable_line_irq(struct wl1251 *wl) { return enable_irq(wl->irq); @@ -218,10 +217,64 @@ static struct wl1251_if_operations wl1251_sdio_ops = { .power = wl1251_sdio_set_power, }; +static ssize_t +wl1251_show_long_doze(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct wl1251 *wl = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", wl->long_doze_mode); +} + +static ssize_t +wl1251_set_long_doze(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wl1251 *wl = dev_get_drvdata(dev); + int val, ret; + + ret = kstrtoint(buf, 10, &val); + if (ret < 0) + return ret; + + wl->long_doze_mode = !!val; + return count; +} + +static ssize_t +wl1251_show_ps_rate_thr(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct wl1251 *wl = dev_get_drvdata(dev); + return sprintf(buf, "%u\n", wl->ps_rate_threshold); +} + +static ssize_t +wl1251_set_ps_rate_thr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wl1251 *wl = dev_get_drvdata(dev); + unsigned int val; + int ret; + + ret = kstrtouint(buf, 10, &val); + if (ret < 0) + return ret; + + wl->ps_rate_threshold = val; + return count; +} + +static struct device_attribute wl1251_attrs[] = { + __ATTR(long_doze_mode, S_IRUGO | S_IWUGO, + wl1251_show_long_doze, wl1251_set_long_doze), + __ATTR(ps_rate_threshold, S_IRUGO | S_IWUGO, + wl1251_show_ps_rate_thr, wl1251_set_ps_rate_thr), +}; + static int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { - int ret; + int ret, t; struct wl1251 *wl; struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; @@ -259,15 +312,21 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl->use_eeprom = wl12xx_board_data->use_eeprom; } + if (force_nvs_file) + wl->use_eeprom = false; + wl->dump_eeprom = dump_eeprom; + if (wl->irq) { - ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); + irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); + + ret = request_threaded_irq(wl->irq, NULL, wl1251_irq, + IRQF_ONESHOT, "wl1251", wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); goto disable; } irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - disable_irq(wl->irq); wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; @@ -286,6 +345,16 @@ static int wl1251_sdio_probe(struct sdio_func *func, sdio_set_drvdata(func, wl); + for (t = 0; t < ARRAY_SIZE(wl1251_attrs); t++) { + ret = device_create_file(&func->dev, &wl1251_attrs[t]); + if (ret) { + while (--t >= 0) + device_remove_file(&func->dev, + &wl1251_attrs[t]); + goto out_free_irq; + } + } + /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); @@ -309,14 +378,18 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) { struct wl1251 *wl = sdio_get_drvdata(func); struct wl1251_sdio *wl_sdio = wl->if_priv; + int t; /* Undo decrement done above in wl1251_probe */ pm_runtime_get_noresume(&func->dev); + for (t = 0; t < ARRAY_SIZE(wl1251_attrs); t++) + device_remove_file(&func->dev, &wl1251_attrs[t]); + if (wl->irq) free_irq(wl->irq, wl); - kfree(wl_sdio); wl1251_free_hw(wl); + kfree(wl_sdio); sdio_claim_host(func); sdio_release_irq(func);