diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index ae91b57c8422..c1fa42edd363 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6716,6 +6716,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) ar->num_started_vdevs = 0; ar->num_created_vdevs = 0; ar->num_peers = 0; + ar->num_stations = 0; ar->allocated_vdev_map = 0; /* Configure monitor status ring with default rx_filter to get rx status diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index d3491ff08e6e..7d2f292e20c5 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include "htc.h" @@ -328,11 +329,14 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); for (i = 0; i < tx_skb_cnt; i++) { + nskb = skb_peek(&hif_dev->tx.tx_skb_queue); + if (!nskb) + break; + + if (tx_buf->offset + nskb->len + 4 > MAX_TX_BUF_SIZE) + break; + nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue); - - /* Should never be NULL */ - BUG_ON(!nskb); - hif_dev->tx.tx_skb_cnt--; buf = tx_buf->buf; @@ -342,13 +346,8 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); buf += 4; memcpy(buf, nskb->data, nskb->len); - tx_buf->len = nskb->len + 4; - - if (i < (tx_skb_cnt - 1)) - tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4; - - if (i == (tx_skb_cnt - 1)) - tx_buf->len += tx_buf->offset; + tx_buf->len = tx_buf->offset + nskb->len + 4; + tx_buf->offset += round_up(nskb->len + 4, 4); __skb_queue_tail(&tx_buf->skb_queue, nskb); TX_STAT_INC(hif_dev, skb_queued); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6c33e898b300..4d2b75d0212e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -281,7 +281,6 @@ struct ath9k_htc_rxbuf { struct ath9k_htc_rx { struct list_head rxbuf; spinlock_t rxbuflock; - bool initialized; }; #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 6de78ae85726..911eaa4f776a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -910,6 +910,9 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, ath9k_init_leds(priv); ath9k_start_rfkill_poll(priv); + /* signal completion to ath9k_htc_rxep() and ath9k_wmi_event_tasklet() */ + smp_store_release(&priv->initialized, true); + return 0; err_world: @@ -966,10 +969,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, htc_handle->drv_priv = priv; - /* Allow ath9k_wmi_event_tasklet() to operate. */ - smp_wmb(); - priv->initialized = true; - return 0; err_init: diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index bed7ea2425a0..95f48c7dca15 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -1141,8 +1141,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; unsigned long flags; - /* Check if ath9k_rx_init() completed. */ - if (!data_race(priv->rx.initialized)) + /* Check if ath9k_init_device() completed. */ + if (!smp_load_acquire(&priv->initialized)) goto err; spin_lock_irqsave(&priv->rx.rxbuflock, flags); @@ -1200,10 +1200,6 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv) list_add_tail(&rxbuf->list, &priv->rx.rxbuf); } - /* Allow ath9k_htc_rxep() to operate. */ - smp_wmb(); - priv->rx.initialized = true; - return 0; err: diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 284e8c13b043..4a08babb6d9d 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -146,6 +146,12 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t) unsigned long flags; u16 cmd_id; + /* Check if ath9k_init_device() completed. */ + if (!smp_load_acquire(&priv->initialized)) { + tasklet_schedule(t); + return; + } + do { spin_lock_irqsave(&wmi->wmi_lock, flags); skb = __skb_dequeue(&wmi->wmi_event_queue); @@ -155,12 +161,6 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t) } spin_unlock_irqrestore(&wmi->wmi_lock, flags); - /* Check if ath9k_htc_probe_device() completed. */ - if (!data_race(priv->initialized)) { - kfree_skb(skb); - continue; - } - hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); @@ -206,9 +206,16 @@ static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) { skb_pull(skb, sizeof(struct wmi_cmd_hdr)); - if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0) + if (wmi->cmd_rsp_buf && wmi->cmd_rsp_len) { + if (skb->len < wmi->cmd_rsp_len) { + wmi->cmd_rsp_status = -EMSGSIZE; + goto complete; + } memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); + } + wmi->cmd_rsp_status = 0; +complete: complete(&wmi->cmd_wait); } @@ -300,6 +307,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, /* record the rsp buffer and length */ wmi->cmd_rsp_buf = rsp_buf; wmi->cmd_rsp_len = rsp_len; + wmi->cmd_rsp_status = 0; wmi->last_seq_id = wmi->tx_seq_id; spin_unlock_irqrestore(&wmi->wmi_lock, flags); @@ -356,9 +364,13 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, return -ETIMEDOUT; } + spin_lock_irqsave(&wmi->wmi_lock, flags); + ret = wmi->cmd_rsp_status; + spin_unlock_irqrestore(&wmi->wmi_lock, flags); + mutex_unlock(&wmi->op_mutex); - return 0; + return ret; out: ath_dbg(common, WMI, "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 5c3b710b8f31..0bb9d31f1a1c 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -157,6 +157,7 @@ struct wmi { u16 tx_seq_id; u8 *cmd_rsp_buf; u32 cmd_rsp_len; + int cmd_rsp_status; bool stopped; struct list_head pending_tx_events;