Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.20. Major changes: ath9k * fix use-after-free in ath9k_hif_usb_rx_cb()
This commit is contained in:
@@ -1165,7 +1165,7 @@ void ath11k_hal_srng_shadow_update_hp_tp(struct ath11k_base *ab,
|
|||||||
lockdep_assert_held(&srng->lock);
|
lockdep_assert_held(&srng->lock);
|
||||||
|
|
||||||
/* check whether the ring is emptry. Update the shadow
|
/* check whether the ring is emptry. Update the shadow
|
||||||
* HP only when then ring isn't' empty.
|
* HP only when then ring isn't empty.
|
||||||
*/
|
*/
|
||||||
if (srng->ring_dir == HAL_SRNG_DIR_SRC &&
|
if (srng->ring_dir == HAL_SRNG_DIR_SRC &&
|
||||||
*srng->u.src_ring.tp_addr != srng->u.src_ring.hp)
|
*srng->u.src_ring.tp_addr != srng->u.src_ring.hp)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ struct ath6kl_usb {
|
|||||||
u8 *diag_cmd_buffer;
|
u8 *diag_cmd_buffer;
|
||||||
u8 *diag_resp_buffer;
|
u8 *diag_resp_buffer;
|
||||||
struct ath6kl *ar;
|
struct ath6kl *ar;
|
||||||
|
struct workqueue_struct *wq;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* usb urb object */
|
/* usb urb object */
|
||||||
@@ -478,7 +479,7 @@ static void ath6kl_usb_flush_all(struct ath6kl_usb *ar_usb)
|
|||||||
* Flushing any pending I/O may schedule work this call will block
|
* Flushing any pending I/O may schedule work this call will block
|
||||||
* until all scheduled work runs to completion.
|
* until all scheduled work runs to completion.
|
||||||
*/
|
*/
|
||||||
flush_scheduled_work();
|
flush_workqueue(ar_usb->wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb)
|
static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb)
|
||||||
@@ -544,7 +545,7 @@ static void ath6kl_usb_recv_complete(struct urb *urb)
|
|||||||
|
|
||||||
/* note: queue implements a lock */
|
/* note: queue implements a lock */
|
||||||
skb_queue_tail(&pipe->io_comp_queue, skb);
|
skb_queue_tail(&pipe->io_comp_queue, skb);
|
||||||
schedule_work(&pipe->io_complete_work);
|
queue_work(pipe->ar_usb->wq, &pipe->io_complete_work);
|
||||||
|
|
||||||
cleanup_recv_urb:
|
cleanup_recv_urb:
|
||||||
ath6kl_usb_cleanup_recv_urb(urb_context);
|
ath6kl_usb_cleanup_recv_urb(urb_context);
|
||||||
@@ -579,7 +580,7 @@ static void ath6kl_usb_usb_transmit_complete(struct urb *urb)
|
|||||||
|
|
||||||
/* note: queue implements a lock */
|
/* note: queue implements a lock */
|
||||||
skb_queue_tail(&pipe->io_comp_queue, skb);
|
skb_queue_tail(&pipe->io_comp_queue, skb);
|
||||||
schedule_work(&pipe->io_complete_work);
|
queue_work(pipe->ar_usb->wq, &pipe->io_complete_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath6kl_usb_io_comp_work(struct work_struct *work)
|
static void ath6kl_usb_io_comp_work(struct work_struct *work)
|
||||||
@@ -619,6 +620,7 @@ static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb)
|
|||||||
|
|
||||||
kfree(ar_usb->diag_cmd_buffer);
|
kfree(ar_usb->diag_cmd_buffer);
|
||||||
kfree(ar_usb->diag_resp_buffer);
|
kfree(ar_usb->diag_resp_buffer);
|
||||||
|
destroy_workqueue(ar_usb->wq);
|
||||||
|
|
||||||
kfree(ar_usb);
|
kfree(ar_usb);
|
||||||
}
|
}
|
||||||
@@ -631,9 +633,15 @@ static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface)
|
|||||||
int status = 0;
|
int status = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* ath6kl_usb_destroy() needs ar_usb != NULL && ar_usb->wq != NULL. */
|
||||||
ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL);
|
ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL);
|
||||||
if (ar_usb == NULL)
|
if (ar_usb == NULL)
|
||||||
goto fail_ath6kl_usb_create;
|
return NULL;
|
||||||
|
ar_usb->wq = alloc_workqueue("ath6kl_wq", 0, 0);
|
||||||
|
if (!ar_usb->wq) {
|
||||||
|
kfree(ar_usb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
usb_set_intfdata(interface, ar_usb);
|
usb_set_intfdata(interface, ar_usb);
|
||||||
spin_lock_init(&(ar_usb->cs_lock));
|
spin_lock_init(&(ar_usb->cs_lock));
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
|
|||||||
else
|
else
|
||||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
|
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
|
||||||
|
|
||||||
/* on AR92xx, the highest bit of count will make the the chip send
|
/* on AR92xx, the highest bit of count will make the chip send
|
||||||
* spectral samples endlessly. Check if this really was intended,
|
* spectral samples endlessly. Check if this really was intended,
|
||||||
* and fix otherwise.
|
* and fix otherwise.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -244,11 +244,11 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
|
|||||||
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
||||||
skb, txok);
|
skb, txok);
|
||||||
if (txok) {
|
if (txok) {
|
||||||
TX_STAT_INC(skb_success);
|
TX_STAT_INC(hif_dev, skb_success);
|
||||||
TX_STAT_ADD(skb_success_bytes, ln);
|
TX_STAT_ADD(hif_dev, skb_success_bytes, ln);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TX_STAT_INC(skb_failed);
|
TX_STAT_INC(hif_dev, skb_failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ static void hif_usb_tx_cb(struct urb *urb)
|
|||||||
hif_dev->tx.tx_buf_cnt++;
|
hif_dev->tx.tx_buf_cnt++;
|
||||||
if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
|
if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
|
||||||
__hif_usb_tx(hif_dev); /* Check for pending SKBs */
|
__hif_usb_tx(hif_dev); /* Check for pending SKBs */
|
||||||
TX_STAT_INC(buf_completed);
|
TX_STAT_INC(hif_dev, buf_completed);
|
||||||
spin_unlock(&hif_dev->tx.tx_lock);
|
spin_unlock(&hif_dev->tx.tx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
|||||||
tx_buf->len += tx_buf->offset;
|
tx_buf->len += tx_buf->offset;
|
||||||
|
|
||||||
__skb_queue_tail(&tx_buf->skb_queue, nskb);
|
__skb_queue_tail(&tx_buf->skb_queue, nskb);
|
||||||
TX_STAT_INC(skb_queued);
|
TX_STAT_INC(hif_dev, skb_queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
|
usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
|
||||||
@@ -369,7 +369,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
|||||||
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
||||||
hif_dev->tx.tx_buf_cnt++;
|
hif_dev->tx.tx_buf_cnt++;
|
||||||
} else {
|
} else {
|
||||||
TX_STAT_INC(buf_queued);
|
TX_STAT_INC(hif_dev, buf_queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -514,7 +514,7 @@ static void hif_usb_sta_drain(void *hif_handle, u8 idx)
|
|||||||
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
||||||
skb, false);
|
skb, false);
|
||||||
hif_dev->tx.tx_skb_cnt--;
|
hif_dev->tx.tx_skb_cnt--;
|
||||||
TX_STAT_INC(skb_failed);
|
TX_STAT_INC(hif_dev, skb_failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,14 +585,14 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
|||||||
pkt_tag = get_unaligned_le16(ptr + index + 2);
|
pkt_tag = get_unaligned_le16(ptr + index + 2);
|
||||||
|
|
||||||
if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
|
if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
|
||||||
RX_STAT_INC(skb_dropped);
|
RX_STAT_INC(hif_dev, skb_dropped);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt_len > 2 * MAX_RX_BUF_SIZE) {
|
if (pkt_len > 2 * MAX_RX_BUF_SIZE) {
|
||||||
dev_err(&hif_dev->udev->dev,
|
dev_err(&hif_dev->udev->dev,
|
||||||
"ath9k_htc: invalid pkt_len (%x)\n", pkt_len);
|
"ath9k_htc: invalid pkt_len (%x)\n", pkt_len);
|
||||||
RX_STAT_INC(skb_dropped);
|
RX_STAT_INC(hif_dev, skb_dropped);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +618,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
skb_reserve(nskb, 32);
|
skb_reserve(nskb, 32);
|
||||||
RX_STAT_INC(skb_allocated);
|
RX_STAT_INC(hif_dev, skb_allocated);
|
||||||
|
|
||||||
memcpy(nskb->data, &(skb->data[chk_idx+4]),
|
memcpy(nskb->data, &(skb->data[chk_idx+4]),
|
||||||
hif_dev->rx_transfer_len);
|
hif_dev->rx_transfer_len);
|
||||||
@@ -639,7 +639,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
skb_reserve(nskb, 32);
|
skb_reserve(nskb, 32);
|
||||||
RX_STAT_INC(skb_allocated);
|
RX_STAT_INC(hif_dev, skb_allocated);
|
||||||
|
|
||||||
memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
|
memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
|
||||||
skb_put(nskb, pkt_len);
|
skb_put(nskb, pkt_len);
|
||||||
@@ -649,10 +649,10 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
for (i = 0; i < pool_index; i++) {
|
for (i = 0; i < pool_index; i++) {
|
||||||
RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len);
|
RX_STAT_ADD(hif_dev, skb_completed_bytes, skb_pool[i]->len);
|
||||||
ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
|
ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
|
||||||
skb_pool[i]->len, USB_WLAN_RX_PIPE);
|
skb_pool[i]->len, USB_WLAN_RX_PIPE);
|
||||||
RX_STAT_INC(skb_completed);
|
RX_STAT_INC(hif_dev, skb_completed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -327,14 +327,18 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
||||||
|
#define __STAT_SAFE(hif_dev, expr) ((hif_dev)->htc_handle->drv_priv ? (expr) : 0)
|
||||||
|
#define CAB_STAT_INC(priv) ((priv)->debug.tx_stats.cab_queued++)
|
||||||
|
#define TX_QSTAT_INC(priv, q) ((priv)->debug.tx_stats.queue_stats[q]++)
|
||||||
|
|
||||||
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
|
#define TX_STAT_INC(hif_dev, c) \
|
||||||
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
|
__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++)
|
||||||
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++)
|
#define TX_STAT_ADD(hif_dev, c, a) \
|
||||||
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a)
|
__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c += a)
|
||||||
#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++
|
#define RX_STAT_INC(hif_dev, c) \
|
||||||
|
__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c++)
|
||||||
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
|
#define RX_STAT_ADD(hif_dev, c, a) \
|
||||||
|
__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c += a)
|
||||||
|
|
||||||
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
|
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
|
||||||
struct ath_rx_status *rs);
|
struct ath_rx_status *rs);
|
||||||
@@ -374,13 +378,13 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
|
|||||||
struct ethtool_stats *stats, u64 *data);
|
struct ethtool_stats *stats, u64 *data);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define TX_STAT_INC(c) do { } while (0)
|
#define TX_STAT_INC(hif_dev, c)
|
||||||
#define TX_STAT_ADD(c, a) do { } while (0)
|
#define TX_STAT_ADD(hif_dev, c, a)
|
||||||
#define RX_STAT_INC(c) do { } while (0)
|
#define RX_STAT_INC(hif_dev, c)
|
||||||
#define RX_STAT_ADD(c, a) do { } while (0)
|
#define RX_STAT_ADD(hif_dev, c, a)
|
||||||
#define CAB_STAT_INC do { } while (0)
|
|
||||||
|
|
||||||
#define TX_QSTAT_INC(c) do { } while (0)
|
#define CAB_STAT_INC(priv)
|
||||||
|
#define TX_QSTAT_INC(priv, c)
|
||||||
|
|
||||||
static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
|
static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
|
||||||
struct ath_rx_status *rs)
|
struct ath_rx_status *rs)
|
||||||
|
|||||||
@@ -944,7 +944,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
|
|||||||
priv->hw = hw;
|
priv->hw = hw;
|
||||||
priv->htc = htc_handle;
|
priv->htc = htc_handle;
|
||||||
priv->dev = dev;
|
priv->dev = dev;
|
||||||
htc_handle->drv_priv = priv;
|
|
||||||
SET_IEEE80211_DEV(hw, priv->dev);
|
SET_IEEE80211_DEV(hw, priv->dev);
|
||||||
|
|
||||||
ret = ath9k_htc_wait_for_target(priv);
|
ret = ath9k_htc_wait_for_target(priv);
|
||||||
@@ -965,6 +964,8 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err_init;
|
goto err_init;
|
||||||
|
|
||||||
|
htc_handle->drv_priv = priv;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_init:
|
err_init:
|
||||||
|
|||||||
@@ -106,20 +106,20 @@ static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
|
|||||||
|
|
||||||
switch (qnum) {
|
switch (qnum) {
|
||||||
case 0:
|
case 0:
|
||||||
TX_QSTAT_INC(IEEE80211_AC_VO);
|
TX_QSTAT_INC(priv, IEEE80211_AC_VO);
|
||||||
epid = priv->data_vo_ep;
|
epid = priv->data_vo_ep;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
TX_QSTAT_INC(IEEE80211_AC_VI);
|
TX_QSTAT_INC(priv, IEEE80211_AC_VI);
|
||||||
epid = priv->data_vi_ep;
|
epid = priv->data_vi_ep;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
TX_QSTAT_INC(IEEE80211_AC_BE);
|
TX_QSTAT_INC(priv, IEEE80211_AC_BE);
|
||||||
epid = priv->data_be_ep;
|
epid = priv->data_be_ep;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
default:
|
default:
|
||||||
TX_QSTAT_INC(IEEE80211_AC_BK);
|
TX_QSTAT_INC(priv, IEEE80211_AC_BK);
|
||||||
epid = priv->data_bk_ep;
|
epid = priv->data_bk_ep;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -328,7 +328,7 @@ static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv,
|
|||||||
memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
|
memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
|
||||||
|
|
||||||
if (is_cab) {
|
if (is_cab) {
|
||||||
CAB_STAT_INC;
|
CAB_STAT_INC(priv);
|
||||||
tx_ctl->epid = priv->cab_ep;
|
tx_ctl->epid = priv->cab_ep;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1961,7 +1961,7 @@ struct wcn36xx_hal_config_bss_params {
|
|||||||
|
|
||||||
/* HAL should update the existing BSS entry, if this flag is set.
|
/* HAL should update the existing BSS entry, if this flag is set.
|
||||||
* UMAC will set this flag in case of reassoc, where we want to
|
* UMAC will set this flag in case of reassoc, where we want to
|
||||||
* resue the the old BSSID and still return success 0 = Add, 1 =
|
* resue the old BSSID and still return success 0 = Add, 1 =
|
||||||
* Update */
|
* Update */
|
||||||
u8 action;
|
u8 action;
|
||||||
|
|
||||||
@@ -2098,7 +2098,7 @@ struct wcn36xx_hal_config_bss_params_v1 {
|
|||||||
|
|
||||||
/* HAL should update the existing BSS entry, if this flag is set.
|
/* HAL should update the existing BSS entry, if this flag is set.
|
||||||
* UMAC will set this flag in case of reassoc, where we want to
|
* UMAC will set this flag in case of reassoc, where we want to
|
||||||
* resue the the old BSSID and still return success 0 = Add, 1 =
|
* resue the old BSSID and still return success 0 = Add, 1 =
|
||||||
* Update */
|
* Update */
|
||||||
u8 action;
|
u8 action;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user