diff options
Diffstat (limited to 'drivers/staging/wfx')
-rw-r--r-- | drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt | 11 | ||||
-rw-r--r-- | drivers/staging/wfx/bh.c | 8 | ||||
-rw-r--r-- | drivers/staging/wfx/bus_sdio.c | 16 | ||||
-rw-r--r-- | drivers/staging/wfx/bus_spi.c | 45 | ||||
-rw-r--r-- | drivers/staging/wfx/data_rx.c | 3 | ||||
-rw-r--r-- | drivers/staging/wfx/data_tx.c | 12 | ||||
-rw-r--r-- | drivers/staging/wfx/data_tx.h | 2 | ||||
-rw-r--r-- | drivers/staging/wfx/hif_api_cmd.h | 4 | ||||
-rw-r--r-- | drivers/staging/wfx/hif_tx.c | 15 | ||||
-rw-r--r-- | drivers/staging/wfx/hif_tx.h | 2 | ||||
-rw-r--r-- | drivers/staging/wfx/hif_tx_mib.h | 15 | ||||
-rw-r--r-- | drivers/staging/wfx/hwio.c | 2 | ||||
-rw-r--r-- | drivers/staging/wfx/main.c | 23 | ||||
-rw-r--r-- | drivers/staging/wfx/main.h | 1 | ||||
-rw-r--r-- | drivers/staging/wfx/queue.c | 20 | ||||
-rw-r--r-- | drivers/staging/wfx/sta.c | 30 |
16 files changed, 111 insertions, 98 deletions
diff --git a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt index 081d58abd5ac..17db67559f5e 100644 --- a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt +++ b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt @@ -6,7 +6,7 @@ SPI You have to declare the WFxxx chip in your device tree. Required properties: - - compatible: Should be "silabs,wfx-spi" + - compatible: Should be "silabs,wf200" - reg: Chip select address of device - spi-max-frequency: Maximum SPI clocking speed of device in Hz - interrupts-extended: Should contain interrupt line (interrupt-parent + @@ -15,6 +15,7 @@ Required properties: Optional properties: - reset-gpios: phandle of gpio that will be used to reset chip during probe. Without this property, you may encounter issues with warm boot. + (Legacy: when compatible == "silabs,wfx-spi", the gpio is inverted.) Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional SPI connection related properties, @@ -23,12 +24,12 @@ Example: &spi1 { wfx { - compatible = "silabs,wfx-spi"; + compatible = "silabs,wf200"; pinctrl-names = "default"; pinctrl-0 = <&wfx_irq &wfx_gpios>; interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>; wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; reg = <0>; spi-max-frequency = <42000000>; }; @@ -44,7 +45,7 @@ case. Thus declaring WFxxx chip in device tree is strongly recommended (and may become mandatory in the future). Required properties: - - compatible: Should be "silabs,wfx-sdio" + - compatible: Should be "silabs,wf200" - reg: Should be 1 In addition, it is recommended to declare a mmc-pwrseq on SDIO host above WFx. @@ -70,7 +71,7 @@ Example: #size = <0>; mmc@1 { - compatible = "silabs,wfx-sdio"; + compatible = "silabs,wf200"; reg = <1>; pinctrl-names = "default"; pinctrl-0 = <&wfx_wakeup>; diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c index 983c41d1fe7c..9fcab00a3733 100644 --- a/drivers/staging/wfx/bh.c +++ b/drivers/staging/wfx/bh.c @@ -20,13 +20,13 @@ static void device_wakeup(struct wfx_dev *wdev) { if (!wdev->pdata.gpio_wakeup) return; - if (gpiod_get_value(wdev->pdata.gpio_wakeup)) + if (gpiod_get_value_cansleep(wdev->pdata.gpio_wakeup)) return; - gpiod_set_value(wdev->pdata.gpio_wakeup, 1); + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); if (wfx_api_older_than(wdev, 1, 4)) { if (!completion_done(&wdev->hif.ctrl_ready)) - udelay(2000); + usleep_range(2000, 2500); } else { // completion.h does not provide any function to wait // completion without consume it (a kind of @@ -45,7 +45,7 @@ static void device_release(struct wfx_dev *wdev) if (!wdev->pdata.gpio_wakeup) return; - gpiod_set_value(wdev->pdata.gpio_wakeup, 0); + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0); } static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c index f8901164c206..dedc3ff58d3e 100644 --- a/drivers/staging/wfx/bus_sdio.c +++ b/drivers/staging/wfx/bus_sdio.c @@ -200,25 +200,23 @@ static int wfx_sdio_probe(struct sdio_func *func, if (ret) goto err0; - ret = wfx_sdio_irq_subscribe(bus); - if (ret) - goto err1; - bus->core = wfx_init_common(&func->dev, &wfx_sdio_pdata, &wfx_sdio_hwbus_ops, bus); if (!bus->core) { ret = -EIO; - goto err2; + goto err1; } + ret = wfx_sdio_irq_subscribe(bus); + if (ret) + goto err1; + ret = wfx_probe(bus->core); if (ret) - goto err3; + goto err2; return 0; -err3: - wfx_free_common(bus->core); err2: wfx_sdio_irq_unsubscribe(bus); err1: @@ -234,7 +232,6 @@ static void wfx_sdio_remove(struct sdio_func *func) struct wfx_sdio_priv *bus = sdio_get_drvdata(func); wfx_release(bus->core); - wfx_free_common(bus->core); wfx_sdio_irq_unsubscribe(bus); sdio_claim_host(func); sdio_disable_func(func); @@ -254,6 +251,7 @@ MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids); #ifdef CONFIG_OF static const struct of_device_id wfx_sdio_of_match[] = { { .compatible = "silabs,wfx-sdio" }, + { .compatible = "silabs,wf200" }, { }, }; MODULE_DEVICE_TABLE(of, wfx_sdio_of_match); diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index 40bc33035de2..61e99b09decb 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -27,6 +27,8 @@ MODULE_PARM_DESC(gpio_reset, "gpio number for reset. -1 for none."); #define SET_WRITE 0x7FFF /* usage: and operation */ #define SET_READ 0x8000 /* usage: or operation */ +#define WFX_RESET_INVERTED 1 + static const struct wfx_platform_data wfx_spi_pdata = { .file_fw = "wfm_wf200", .file_pds = "wf200.pds", @@ -154,6 +156,11 @@ static void wfx_spi_request_rx(struct work_struct *work) wfx_bh_request_rx(bus->core); } +static void wfx_flush_irq_work(void *w) +{ + flush_work(w); +} + static size_t wfx_spi_align_size(void *priv, size_t size) { // Most of SPI controllers avoid DMA if buffer size is not 32bit aligned @@ -201,28 +208,31 @@ static int wfx_spi_probe(struct spi_device *func) if (!bus->gpio_reset) { dev_warn(&func->dev, "try to load firmware anyway\n"); } else { - gpiod_set_value(bus->gpio_reset, 0); - udelay(100); - gpiod_set_value(bus->gpio_reset, 1); - udelay(2000); + if (spi_get_device_id(func)->driver_data & WFX_RESET_INVERTED) + gpiod_toggle_active_low(bus->gpio_reset); + gpiod_set_value_cansleep(bus->gpio_reset, 1); + usleep_range(100, 150); + gpiod_set_value_cansleep(bus->gpio_reset, 0); + usleep_range(2000, 2500); } - ret = devm_request_irq(&func->dev, func->irq, wfx_spi_irq_handler, - IRQF_TRIGGER_RISING, "wfx", bus); - if (ret) - return ret; - INIT_WORK(&bus->request_rx, wfx_spi_request_rx); bus->core = wfx_init_common(&func->dev, &wfx_spi_pdata, &wfx_spi_hwbus_ops, bus); if (!bus->core) return -EIO; - ret = wfx_probe(bus->core); + ret = devm_add_action_or_reset(&func->dev, wfx_flush_irq_work, + &bus->request_rx); if (ret) - wfx_free_common(bus->core); + return ret; - return ret; + ret = devm_request_irq(&func->dev, func->irq, wfx_spi_irq_handler, + IRQF_TRIGGER_RISING, "wfx", bus); + if (ret) + return ret; + + return wfx_probe(bus->core); } static int wfx_spi_remove(struct spi_device *func) @@ -230,11 +240,6 @@ static int wfx_spi_remove(struct spi_device *func) struct wfx_spi_priv *bus = spi_get_drvdata(func); wfx_release(bus->core); - wfx_free_common(bus->core); - // A few IRQ will be sent during device release. Hopefully, no IRQ - // should happen after wdev/wvif are released. - devm_free_irq(&func->dev, func->irq, bus); - flush_work(&bus->request_rx); return 0; } @@ -244,14 +249,16 @@ static int wfx_spi_remove(struct spi_device *func) * stripped. */ static const struct spi_device_id wfx_spi_id[] = { - { "wfx-spi", 0 }, + { "wfx-spi", WFX_RESET_INVERTED }, + { "wf200", 0 }, { }, }; MODULE_DEVICE_TABLE(spi, wfx_spi_id); #ifdef CONFIG_OF static const struct of_device_id wfx_spi_of_match[] = { - { .compatible = "silabs,wfx-spi" }, + { .compatible = "silabs,wfx-spi", .data = (void *)WFX_RESET_INVERTED }, + { .compatible = "silabs,wf200" }, { }, }; MODULE_DEVICE_TABLE(of, wfx_spi_of_match); diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index 5d198457c6ce..c5b83fedeb55 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -17,7 +17,7 @@ static int wfx_drop_encrypt_data(struct wfx_dev *wdev, const struct hif_ind_rx *arg, struct sk_buff *skb) { - struct ieee80211_hdr *frame = (struct ieee80211_hdr *) skb->data; + struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; size_t hdrlen = ieee80211_hdrlen(frame->frame_control); size_t iv_len, icv_len; @@ -62,7 +62,6 @@ static int wfx_drop_encrypt_data(struct wfx_dev *wdev, memmove(skb->data + iv_len, skb->data, hdrlen); skb_pull(skb, iv_len); return 0; - } void wfx_rx_cb(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 20f4740734f2..42183c70d4df 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -227,7 +227,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif) memzcmp(policies[i].rates, sizeof(policies[i].rates))) break; if (i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES) { - policies[i].uploaded = 1; + policies[i].uploaded = true; memcpy(tmp_rates, policies[i].rates, sizeof(tmp_rates)); spin_unlock_bh(&wvif->tx_policy_cache.lock); hif_set_tx_rate_retry_policy(wvif, i, tmp_rates); @@ -300,11 +300,11 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, } static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif, - struct ieee80211_sta *sta, - struct ieee80211_hdr *hdr) + struct ieee80211_sta *sta, + struct ieee80211_hdr *hdr) { struct wfx_sta_priv *sta_priv = - sta ? (struct wfx_sta_priv *) &sta->drv_priv : NULL; + sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL; const u8 *da = ieee80211_get_DA(hdr); if (sta_priv && sta_priv->link_id) @@ -368,7 +368,7 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) } static u8 wfx_tx_get_rate_id(struct wfx_vif *wvif, - struct ieee80211_tx_info *tx_info) + struct ieee80211_tx_info *tx_info) { bool tx_policy_renew = false; u8 rate_id; @@ -430,7 +430,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; int queue_id = tx_info->hw_queue; - size_t offset = (size_t) skb->data & 3; + size_t offset = (size_t)skb->data & 3; int wmsg_len = sizeof(struct hif_msg) + sizeof(struct hif_req_tx) + offset; diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 04b2147101b6..c545dd75449b 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -61,7 +61,7 @@ static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) static inline struct hif_req_tx *wfx_skb_txreq(struct sk_buff *skb) { struct hif_msg *hif = (struct hif_msg *)skb->data; - struct hif_req_tx *req = (struct hif_req_tx *) hif->body; + struct hif_req_tx *req = (struct hif_req_tx *)hif->body; return req; } diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index 5554d6eddbf3..071b71e2a107 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -95,10 +95,6 @@ struct hif_req_reset { struct hif_reset_flags reset_flags; } __packed; -struct hif_cnf_reset { - u32 status; -} __packed; - struct hif_req_read_mib { u16 mib_id; u16 reserved; diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 2428363371fa..77bca43aca42 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -140,6 +140,7 @@ int hif_shutdown(struct wfx_dev *wdev) else control_reg_write(wdev, 0); mutex_unlock(&wdev->hif_cmd.lock); + mutex_unlock(&wdev->hif_cmd.key_renew_lock); kfree(hif); return ret; } @@ -289,7 +290,7 @@ int hif_stop_scan(struct wfx_vif *wvif) } int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, - const struct ieee80211_channel *channel, const u8 *ssidie) + struct ieee80211_channel *channel, const u8 *ssid, int ssidlen) { int ret; struct hif_msg *hif; @@ -307,9 +308,9 @@ int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, body->basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); memcpy(body->bssid, conf->bssid, sizeof(body->bssid)); - if (!conf->ibss_joined && ssidie) { - body->ssid_length = cpu_to_le32(ssidie[1]); - memcpy(body->ssid, &ssidie[2], ssidie[1]); + if (!conf->ibss_joined && ssid) { + body->ssid_length = cpu_to_le32(ssidlen); + memcpy(body->ssid, ssid, ssidlen); } wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); @@ -427,9 +428,9 @@ int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, struct hif_msg *hif; struct hif_req_start *body = wfx_alloc_hif(sizeof(*body), &hif); - body->dtim_period = conf->dtim_period, - body->short_preamble = conf->use_short_preamble, - body->channel_number = cpu_to_le16(channel->hw_value), + body->dtim_period = conf->dtim_period; + body->short_preamble = conf->use_short_preamble; + body->channel_number = cpu_to_le16(channel->hw_value); body->beacon_interval = cpu_to_le32(conf->beacon_int); body->basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index 20977e461718..f8520a14c14c 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -46,7 +46,7 @@ int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211, int chan_start, int chan_num); int hif_stop_scan(struct wfx_vif *wvif); int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, - const struct ieee80211_channel *channel, const u8 *ssidie); + struct ieee80211_channel *channel, const u8 *ssid, int ssidlen); int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout); int hif_set_bss_params(struct wfx_vif *wvif, const struct hif_req_set_bss_params *arg); diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index bf3769c2a9b6..26b1406f9f6c 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -191,10 +191,10 @@ static inline int hif_set_block_ack_policy(struct wfx_vif *wvif, } static inline int hif_set_association_mode(struct wfx_vif *wvif, - struct ieee80211_bss_conf *info, - struct ieee80211_sta_ht_cap *ht_cap) + struct ieee80211_bss_conf *info) { int basic_rates = wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates); + struct ieee80211_sta *sta = NULL; struct hif_mib_set_association_mode val = { .preambtype_use = 1, .mode = 1, @@ -204,12 +204,17 @@ static inline int hif_set_association_mode(struct wfx_vif *wvif, .basic_rate_set = cpu_to_le32(basic_rates) }; + rcu_read_lock(); // protect sta + if (info->bssid && !info->ibss_joined) + sta = ieee80211_find_sta(wvif->vif, info->bssid); + // FIXME: it is strange to not retrieve all information from bss_info - if (ht_cap && ht_cap->ht_supported) { - val.mpdu_start_spacing = ht_cap->ampdu_density; + if (sta && sta->ht_cap.ht_supported) { + val.mpdu_start_spacing = sta->ht_cap.ampdu_density; if (!(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - val.greenfield = !!(ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD); + val.greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); } + rcu_read_unlock(); return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_ASSOCIATION_MODE, &val, sizeof(val)); diff --git a/drivers/staging/wfx/hwio.c b/drivers/staging/wfx/hwio.c index 47e04c59ed93..d3a141d95a0e 100644 --- a/drivers/staging/wfx/hwio.c +++ b/drivers/staging/wfx/hwio.c @@ -142,7 +142,7 @@ static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf, goto err; if (!(cfg & prefetch)) break; - udelay(200); + usleep_range(200, 250); } if (i == 20) { ret = -ETIMEDOUT; diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 84adad64fc30..3c4c240229ad 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -262,6 +262,16 @@ static int wfx_send_pdata_pds(struct wfx_dev *wdev) return ret; } +static void wfx_free_common(void *data) +{ + struct wfx_dev *wdev = data; + + mutex_destroy(&wdev->rx_stats_lock); + mutex_destroy(&wdev->conf_mutex); + wfx_tx_queues_deinit(wdev); + ieee80211_free_hw(wdev->hw); +} + struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_data *pdata, const struct hwbus_ops *hwbus_ops, @@ -332,15 +342,10 @@ struct wfx_dev *wfx_init_common(struct device *dev, wfx_init_hif_cmd(&wdev->hif_cmd); wfx_tx_queues_init(wdev); - return wdev; -} + if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) + return NULL; -void wfx_free_common(struct wfx_dev *wdev) -{ - mutex_destroy(&wdev->rx_stats_lock); - mutex_destroy(&wdev->conf_mutex); - wfx_tx_queues_deinit(wdev); - ieee80211_free_hw(wdev->hw); + return wdev; } int wfx_probe(struct wfx_dev *wdev) @@ -420,7 +425,7 @@ int wfx_probe(struct wfx_dev *wdev) "enable 'quiescent' power mode with gpio %d and PDS file %s\n", desc_to_gpio(wdev->pdata.gpio_wakeup), wdev->pdata.file_pds); - gpiod_set_value(wdev->pdata.gpio_wakeup, 1); + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); control_reg_write(wdev, 0); hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT); } else { diff --git a/drivers/staging/wfx/main.h b/drivers/staging/wfx/main.h index 875f8c227803..9c9410072def 100644 --- a/drivers/staging/wfx/main.h +++ b/drivers/staging/wfx/main.h @@ -34,7 +34,6 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_data *pdata, const struct hwbus_ops *hwbus_ops, void *hwbus_priv); -void wfx_free_common(struct wfx_dev *wdev); int wfx_probe(struct wfx_dev *wdev); void wfx_release(struct wfx_dev *wdev); diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 0bcc61feee1d..39d9127ce4b9 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -130,12 +130,12 @@ static void wfx_tx_queue_clear(struct wfx_dev *wdev, struct wfx_queue *queue, spin_lock_bh(&queue->queue.lock); while ((item = __skb_dequeue(&queue->queue)) != NULL) skb_queue_head(gc_list, item); - spin_lock_bh(&stats->pending.lock); + spin_lock_nested(&stats->pending.lock, 1); for (i = 0; i < ARRAY_SIZE(stats->link_map_cache); ++i) { stats->link_map_cache[i] -= queue->link_map_cache[i]; queue->link_map_cache[i] = 0; } - spin_unlock_bh(&stats->pending.lock); + spin_unlock(&stats->pending.lock); spin_unlock_bh(&queue->queue.lock); } @@ -207,9 +207,9 @@ void wfx_tx_queue_put(struct wfx_dev *wdev, struct wfx_queue *queue, ++queue->link_map_cache[tx_priv->link_id]; - spin_lock_bh(&stats->pending.lock); + spin_lock_nested(&stats->pending.lock, 1); ++stats->link_map_cache[tx_priv->link_id]; - spin_unlock_bh(&stats->pending.lock); + spin_unlock(&stats->pending.lock); spin_unlock_bh(&queue->queue.lock); } @@ -237,11 +237,11 @@ static struct sk_buff *wfx_tx_queue_get(struct wfx_dev *wdev, __skb_unlink(skb, &queue->queue); --queue->link_map_cache[tx_priv->link_id]; - spin_lock_bh(&stats->pending.lock); + spin_lock_nested(&stats->pending.lock, 1); __skb_queue_tail(&stats->pending, skb); if (!--stats->link_map_cache[tx_priv->link_id]) wakeup_stats = true; - spin_unlock_bh(&stats->pending.lock); + spin_unlock(&stats->pending.lock); } spin_unlock_bh(&queue->queue.lock); if (wakeup_stats) @@ -259,10 +259,10 @@ int wfx_pending_requeue(struct wfx_dev *wdev, struct sk_buff *skb) spin_lock_bh(&queue->queue.lock); ++queue->link_map_cache[tx_priv->link_id]; - spin_lock_bh(&stats->pending.lock); + spin_lock_nested(&stats->pending.lock, 1); ++stats->link_map_cache[tx_priv->link_id]; __skb_unlink(skb, &stats->pending); - spin_unlock_bh(&stats->pending.lock); + spin_unlock(&stats->pending.lock); __skb_queue_tail(&queue->queue, skb); spin_unlock_bh(&queue->queue.lock); return 0; @@ -481,7 +481,6 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) struct wfx_queue *vif_queue = NULL; u32 tx_allowed_mask = 0; u32 vif_tx_allowed_mask = 0; - const struct wfx_tx_priv *tx_priv = NULL; struct wfx_vif *wvif; int not_found; int burst; @@ -541,8 +540,7 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) skb = wfx_tx_queue_get(wdev, queue, tx_allowed_mask); if (!skb) continue; - tx_priv = wfx_skb_tx_priv(skb); - hif = (struct hif_msg *) skb->data; + hif = (struct hif_msg *)skb->data; wvif = wdev_to_wvif(wdev, hif->interface); WARN_ON(!wvif); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 03d0f224ffdb..9d430346a58b 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -293,7 +293,6 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; int old_uapsd = wvif->uapsd_mask; - int ret = 0; WARN_ON(queue >= hw->queues); @@ -307,7 +306,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, wfx_update_pm(wvif); } mutex_unlock(&wdev->conf_mutex); - return ret; + return 0; } int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) @@ -491,9 +490,11 @@ static void wfx_set_mfp(struct wfx_vif *wvif, static void wfx_do_join(struct wfx_vif *wvif) { int ret; - const u8 *ssidie; struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; struct cfg80211_bss *bss = NULL; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + const u8 *ssidie = NULL; + int ssidlen = 0; wfx_tx_lock_flush(wvif->wdev); @@ -514,11 +515,14 @@ static void wfx_do_join(struct wfx_vif *wvif) if (!wvif->beacon_int) wvif->beacon_int = 1; - rcu_read_lock(); + rcu_read_lock(); // protect ssidie if (!conf->ibss_joined) ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); - else - ssidie = NULL; + if (ssidie) { + ssidlen = ssidie[1]; + memcpy(ssid, &ssidie[2], ssidie[1]); + } + rcu_read_unlock(); wfx_tx_flush(wvif->wdev); @@ -527,10 +531,8 @@ static void wfx_do_join(struct wfx_vif *wvif) wfx_set_mfp(wvif, bss); - /* Perform actual join */ wvif->wdev->tx_burst_idx = -1; - ret = hif_join(wvif, conf, wvif->channel, ssidie); - rcu_read_unlock(); + ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen); if (ret) { ieee80211_connection_loss(wvif->vif); wvif->join_complete_status = -1; @@ -605,7 +607,9 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int i; for (i = 0; i < ARRAY_SIZE(sta_priv->buffered); i++) - WARN(sta_priv->buffered[i], "release station while Tx is in progress"); + if (sta_priv->buffered[i]) + dev_warn(wvif->wdev->dev, "release station while %d pending frame on queue %d", + sta_priv->buffered[i], i); // FIXME: see note in wfx_sta_add() if (vif->type == NL80211_IFTYPE_STATION) return 0; @@ -689,6 +693,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, wfx_rate_mask_to_hw(wvif->wdev, sta->supp_rates[wvif->channel->band]); else wvif->bss_params.operational_rate_set = -1; + rcu_read_unlock(); if (sta && info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) hif_dual_cts_protection(wvif, true); @@ -701,8 +706,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, wvif->bss_params.beacon_lost_count = 20; wvif->bss_params.aid = info->aid; - hif_set_association_mode(wvif, info, sta ? &sta->ht_cap : NULL); - rcu_read_unlock(); + hif_set_association_mode(wvif, info); if (!info->ibss_joined) { hif_keep_alive_period(wvif, 30 /* sec */); @@ -904,7 +908,7 @@ static void wfx_update_tim_work(struct work_struct *work) int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { struct wfx_dev *wdev = hw->priv; - struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *) &sta->drv_priv; + struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv; struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id); schedule_work(&wvif->update_tim_work); |