Commit c30b5b8c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-5.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging driver fixes from Greg KH:
 "Here are three small fixes for staging drivers for 5.17-rc8 or -final,
  which ever comes next.

  They resolve some reported problems:

   - rtl8723bs wifi driver deadlock fix for reported problem that is a
     revert of a previous patch. Also a documentation fix is added so
     that the same problem hopefully can not come back again.

   - gdm724x driver use-after-free fix for a reported problem.

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'staging-5.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging:
  staging: rtl8723bs: Improve the comment explaining the locking rules
  staging: rtl8723bs: Fix access-point mode deadlock
  staging: gdm724x: fix use after free in gdm_lte_rx()
parents 55b4083b 342e7c6e
...@@ -76,14 +76,15 @@ static void tx_complete(void *arg) ...@@ -76,14 +76,15 @@ static void tx_complete(void *arg)
static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type) static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
{ {
int ret; int ret, len;
len = skb->len + ETH_HLEN;
ret = netif_rx_ni(skb); ret = netif_rx_ni(skb);
if (ret == NET_RX_DROP) { if (ret == NET_RX_DROP) {
nic->stats.rx_dropped++; nic->stats.rx_dropped++;
} else { } else {
nic->stats.rx_packets++; nic->stats.rx_packets++;
nic->stats.rx_bytes += skb->len + ETH_HLEN; nic->stats.rx_bytes += len;
} }
return 0; return 0;
......
...@@ -5907,6 +5907,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) ...@@ -5907,6 +5907,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
struct sta_info *psta_bmc; struct sta_info *psta_bmc;
struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pxmitframe = NULL;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct sta_priv *pstapriv = &padapter->stapriv; struct sta_priv *pstapriv = &padapter->stapriv;
/* for BC/MC Frames */ /* for BC/MC Frames */
...@@ -5917,7 +5918,8 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) ...@@ -5917,7 +5918,8 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
msleep(10);/* 10ms, ATIM(HIQ) Windows */ msleep(10);/* 10ms, ATIM(HIQ) Windows */
spin_lock_bh(&psta_bmc->sleep_q.lock); /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&psta_bmc->sleep_q); xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
...@@ -5940,7 +5942,8 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) ...@@ -5940,7 +5942,8 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
rtw_hal_xmitframe_enqueue(padapter, pxmitframe); rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
} }
spin_unlock_bh(&psta_bmc->sleep_q.lock); /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
spin_unlock_bh(&pxmitpriv->lock);
/* check hi queue and bmc_sleepq */ /* check hi queue and bmc_sleepq */
rtw_chk_hi_queue_cmd(padapter); rtw_chk_hi_queue_cmd(padapter);
......
...@@ -957,8 +957,10 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ ...@@ -957,8 +957,10 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) { if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
struct list_head *xmitframe_plist, *xmitframe_phead; struct list_head *xmitframe_plist, *xmitframe_phead;
struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pxmitframe = NULL;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
spin_lock_bh(&psta->sleep_q.lock); /* spin_lock_bh(&psta->sleep_q.lock); */
spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&psta->sleep_q); xmitframe_phead = get_list_head(&psta->sleep_q);
xmitframe_plist = get_next(xmitframe_phead); xmitframe_plist = get_next(xmitframe_phead);
...@@ -989,10 +991,12 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ ...@@ -989,10 +991,12 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
update_beacon(padapter, WLAN_EID_TIM, NULL, true); update_beacon(padapter, WLAN_EID_TIM, NULL, true);
} }
spin_unlock_bh(&psta->sleep_q.lock); /* spin_unlock_bh(&psta->sleep_q.lock); */
spin_unlock_bh(&pxmitpriv->lock);
} else { } else {
spin_unlock_bh(&psta->sleep_q.lock); /* spin_unlock_bh(&psta->sleep_q.lock); */
spin_unlock_bh(&pxmitpriv->lock);
if (pstapriv->tim_bitmap&BIT(psta->aid)) { if (pstapriv->tim_bitmap&BIT(psta->aid)) {
if (psta->sleepq_len == 0) { if (psta->sleepq_len == 0) {
......
...@@ -293,48 +293,46 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) ...@@ -293,48 +293,46 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
/* list_del_init(&psta->wakeup_list); */ /* list_del_init(&psta->wakeup_list); */
spin_lock_bh(&psta->sleep_q.lock); spin_lock_bh(&pxmitpriv->lock);
rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
psta->sleepq_len = 0; psta->sleepq_len = 0;
spin_unlock_bh(&psta->sleep_q.lock);
spin_lock_bh(&pxmitpriv->lock);
/* vo */ /* vo */
spin_lock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
phwxmit = pxmitpriv->hwxmits; phwxmit = pxmitpriv->hwxmits;
phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
pstaxmitpriv->vo_q.qcnt = 0; pstaxmitpriv->vo_q.qcnt = 0;
spin_unlock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */
/* vi */ /* vi */
spin_lock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
phwxmit = pxmitpriv->hwxmits+1; phwxmit = pxmitpriv->hwxmits+1;
phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
pstaxmitpriv->vi_q.qcnt = 0; pstaxmitpriv->vi_q.qcnt = 0;
spin_unlock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */
/* be */ /* be */
spin_lock_bh(&pstaxmitpriv->be_q.sta_pending.lock); /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
list_del_init(&(pstaxmitpriv->be_q.tx_pending)); list_del_init(&(pstaxmitpriv->be_q.tx_pending));
phwxmit = pxmitpriv->hwxmits+2; phwxmit = pxmitpriv->hwxmits+2;
phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
pstaxmitpriv->be_q.qcnt = 0; pstaxmitpriv->be_q.qcnt = 0;
spin_unlock_bh(&pstaxmitpriv->be_q.sta_pending.lock); /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */
/* bk */ /* bk */
spin_lock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
phwxmit = pxmitpriv->hwxmits+3; phwxmit = pxmitpriv->hwxmits+3;
phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
pstaxmitpriv->bk_q.qcnt = 0; pstaxmitpriv->bk_q.qcnt = 0;
spin_unlock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */
spin_unlock_bh(&pxmitpriv->lock); spin_unlock_bh(&pxmitpriv->lock);
......
...@@ -1734,12 +1734,15 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram ...@@ -1734,12 +1734,15 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram
struct list_head *plist, *phead, *tmp; struct list_head *plist, *phead, *tmp;
struct xmit_frame *pxmitframe; struct xmit_frame *pxmitframe;
spin_lock_bh(&pframequeue->lock);
phead = get_list_head(pframequeue); phead = get_list_head(pframequeue);
list_for_each_safe(plist, tmp, phead) { list_for_each_safe(plist, tmp, phead) {
pxmitframe = list_entry(plist, struct xmit_frame, list); pxmitframe = list_entry(plist, struct xmit_frame, list);
rtw_free_xmitframe(pxmitpriv, pxmitframe); rtw_free_xmitframe(pxmitpriv, pxmitframe);
} }
spin_unlock_bh(&pframequeue->lock);
} }
s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
...@@ -1794,7 +1797,6 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) ...@@ -1794,7 +1797,6 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
struct sta_info *psta; struct sta_info *psta;
struct tx_servq *ptxservq; struct tx_servq *ptxservq;
struct pkt_attrib *pattrib = &pxmitframe->attrib; struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct xmit_priv *xmit_priv = &padapter->xmitpriv;
struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
signed int res = _SUCCESS; signed int res = _SUCCESS;
...@@ -1812,14 +1814,12 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) ...@@ -1812,14 +1814,12 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
spin_lock_bh(&xmit_priv->lock);
if (list_empty(&ptxservq->tx_pending)) if (list_empty(&ptxservq->tx_pending))
list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue)); list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
ptxservq->qcnt++; ptxservq->qcnt++;
phwxmits[ac_index].accnt++; phwxmits[ac_index].accnt++;
spin_unlock_bh(&xmit_priv->lock);
exit: exit:
...@@ -2202,10 +2202,11 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) ...@@ -2202,10 +2202,11 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pxmitframe = NULL;
struct sta_priv *pstapriv = &padapter->stapriv; struct sta_priv *pstapriv = &padapter->stapriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
psta_bmc = rtw_get_bcmc_stainfo(padapter); psta_bmc = rtw_get_bcmc_stainfo(padapter);
spin_lock_bh(&psta->sleep_q.lock); spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&psta->sleep_q); xmitframe_phead = get_list_head(&psta->sleep_q);
list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
...@@ -2306,7 +2307,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) ...@@ -2306,7 +2307,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
_exit: _exit:
spin_unlock_bh(&psta->sleep_q.lock); spin_unlock_bh(&pxmitpriv->lock);
if (update_mask) if (update_mask)
update_beacon(padapter, WLAN_EID_TIM, NULL, true); update_beacon(padapter, WLAN_EID_TIM, NULL, true);
...@@ -2318,8 +2319,9 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst ...@@ -2318,8 +2319,9 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pxmitframe = NULL;
struct sta_priv *pstapriv = &padapter->stapriv; struct sta_priv *pstapriv = &padapter->stapriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
spin_lock_bh(&psta->sleep_q.lock); spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&psta->sleep_q); xmitframe_phead = get_list_head(&psta->sleep_q);
list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
...@@ -2372,7 +2374,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst ...@@ -2372,7 +2374,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
} }
} }
spin_unlock_bh(&psta->sleep_q.lock); spin_unlock_bh(&pxmitpriv->lock);
} }
void enqueue_pending_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) void enqueue_pending_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
......
...@@ -502,7 +502,9 @@ s32 rtl8723bs_hal_xmit( ...@@ -502,7 +502,9 @@ s32 rtl8723bs_hal_xmit(
rtw_issue_addbareq_cmd(padapter, pxmitframe); rtw_issue_addbareq_cmd(padapter, pxmitframe);
} }
spin_lock_bh(&pxmitpriv->lock);
err = rtw_xmitframe_enqueue(padapter, pxmitframe); err = rtw_xmitframe_enqueue(padapter, pxmitframe);
spin_unlock_bh(&pxmitpriv->lock);
if (err != _SUCCESS) { if (err != _SUCCESS) {
rtw_free_xmitframe(pxmitpriv, pxmitframe); rtw_free_xmitframe(pxmitpriv, pxmitframe);
......
...@@ -102,13 +102,17 @@ there are several "locks" in mlme_priv, ...@@ -102,13 +102,17 @@ there are several "locks" in mlme_priv,
since mlme_priv is a shared resource between many threads, since mlme_priv is a shared resource between many threads,
like ISR/Call-Back functions, the OID handlers, and even timer functions. like ISR/Call-Back functions, the OID handlers, and even timer functions.
Each struct __queue has its own locks, already. Each struct __queue has its own locks, already.
Other items are protected by mlme_priv.lock. Other items in mlme_priv are protected by mlme_priv.lock, while items in
xmit_priv are protected by xmit_priv.lock.
To avoid possible dead lock, any thread trying to modifiying mlme_priv To avoid possible dead lock, any thread trying to modifiying mlme_priv
SHALL not lock up more than one locks at a time! SHALL not lock up more than one locks at a time!
The only exception is that queue functions which take the __queue.lock
may be called with the xmit_priv.lock held. In this case the order
MUST always be first lock xmit_priv.lock and then call any queue functions
which take __queue.lock.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment