Merge pull request #91 from MastaG/fix-linux-7.3-cfg80211

fix: support Linux 7.3 cfg80211 API

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MinQ
2026-09-24 20:08:38 +08:00
committed by GitHub
co-authored by Claude Opus 5.5
7 changed files with 208 additions and 34 deletions
+16
View File
@@ -335,6 +335,12 @@ struct apm_probe_sta {
u8 sta_mac_addr[6]; u8 sta_mac_addr[6];
u8 vif_idx; u8 vif_idx;
u64 probe_id; u64 probe_id;
/*
* 7.3+ only: the cookie cfg80211_ops::probe_peer() was called with,
* echoed back via cfg80211_probe_status() once the probe completes.
* See rwnx_cfg80211_probe_client().
*/
u64 cookie;
struct work_struct apmprobestaWork; struct work_struct apmprobestaWork;
struct workqueue_struct *apmprobesta_wq; struct workqueue_struct *apmprobesta_wq;
}; };
@@ -675,6 +681,16 @@ struct rwnx_roc_elem {
bool mgmt_roc; bool mgmt_roc;
/* Indicate if we have switch on the RoC channel */ /* Indicate if we have switch on the RoC channel */
bool on_chan; bool on_chan;
/*
* The cookie reported to cfg80211 for this RoC, via
* cfg80211_ready_on_channel() / cfg80211_remain_on_channel_expired().
* On 7.3+, for a RoC started directly by cfg80211_ops::remain_on_channel(),
* this is the cookie cfg80211 pre-assigned; on every older kernel, and
* always for the purely-internal RoC started from inside mgmt_tx, it is
* rwnx_hw->roc_cookie_cnt at RoC-start time. See
* rwnx_cfg80211_remain_on_channel_().
*/
u64 cookie;
}; };
/* Structure containing channel survey information received from MAC */ /* Structure containing channel survey information received from MAC */
+132 -19
View File
@@ -3940,7 +3940,21 @@ void apm_probe_sta_work_process(struct work_struct *work)
spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock);
printk("sta %pM found = %d\n", mac, found); printk("sta %pM found = %d\n", mac, found);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) #if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
/*
* 7.3 added an MLO link_id parameter between cookie and acked. This
* driver has no MLO support, and -1 is the documented value for
* "non-MLO" (see the cfg80211_probe_status() kerneldoc). The cookie
* source also changes here: sta_probe.cookie is the value cfg80211
* pre-assigned via probe_peer(), which now must be echoed back
* instead of the driver's own probe_id counter -- see
* rwnx_cfg80211_probe_client().
*/
if(found)
cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.cookie, -1, 1, 0, false, GFP_ATOMIC);
else
cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.cookie, -1, 0, 0, false, GFP_ATOMIC);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
if(found) if(found)
cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC); cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC);
else else
@@ -4497,11 +4511,20 @@ int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
/** /**
* @probe_client: probe an associated client, must return a cookie that it * @probe_peer: probe an associated client. Before 7.3 the driver returns a
* later passes to cfg80211_probe_status(). * cookie of its own and passes the same value to cfg80211_probe_status()
* later; from 7.3 the cookie is assigned by cfg80211, passed in, and must
* be echoed back unchanged. Renamed from @probe_client upstream; kept as
* rwnx_cfg80211_probe_client() here since only the cfg80211_ops field
* name changed, not this driver's own naming.
*/ */
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u64 cookie)
#else
int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u64 *cookie) const u8 *peer, u64 *cookie)
#endif
{ {
//struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *vif = netdev_priv(dev); struct rwnx_vif *vif = netdev_priv(dev);
@@ -4525,9 +4548,21 @@ int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
memcpy(vif->sta_probe.sta_mac_addr, peer, 6); memcpy(vif->sta_probe.sta_mac_addr, peer, 6);
queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
/*
* 7.3 made this an input parameter: cfg80211 pre-assigns the cookie
* before calling us instead of us inventing one and returning it. Save
* it before queueing the work: the worker may run on another CPU as
* soon as it is queued, and it echoes this value back via
* cfg80211_probe_status() once the probe completes.
*/
vif->sta_probe.cookie = cookie;
#else
*cookie = vif->sta_probe.probe_id; *cookie = vif->sta_probe.probe_id;
#endif
queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork);
return 0; return 0;
} }
@@ -4728,6 +4763,7 @@ rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy,
struct wireless_dev *wdev = &rwnx_vif->wdev; struct wireless_dev *wdev = &rwnx_vif->wdev;
#endif #endif
struct rwnx_roc_elem *roc_elem; struct rwnx_roc_elem *roc_elem;
u64 roc_cookie;
struct mm_add_if_cfm add_if_cfm; struct mm_add_if_cfm add_if_cfm;
struct mm_remain_on_channel_cfm roc_cfm; struct mm_remain_on_channel_cfm roc_cfm;
int error; int error;
@@ -4819,6 +4855,34 @@ rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy,
/* Initialize the OFFCHAN TX queue to allow off-channel transmissions */ /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */
rwnx_txq_offchan_init(rwnx_vif); rwnx_txq_offchan_init(rwnx_vif);
/*
* Decide the cookie before the element is published and the request
* sent: the RX path can deliver the channel-switch indication and
* call cfg80211_ready_on_channel() with roc_elem->cookie before this
* thread resumes, so it must already be the final value by then.
* Taking one snapshot here also keeps that value and the one reported
* back to the caller below identical: rwnx_send_roc() sleeps, and the
* RoC expiry handler increments roc_cookie_cnt, so re-reading the
* counter afterwards could return a different value than the one
* already reported to cfg80211.
*/
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
/*
* mgmt_roc_flag is false only for the direct cfg80211
* .remain_on_channel call path (see rwnx_cfg80211_remain_on_channel()
* below), where on 7.3+ *cookie already holds the value cfg80211
* pre-assigned and must be honored rather than overwritten. The
* purely-internal RoC this function also serves (started from
* inside mgmt_tx, mgmt_roc_flag true) never goes through that
* cfg80211 op, so there is no pre-assigned value to honor there --
* keep inventing one, exactly as on every older kernel.
*/
roc_cookie = mgmt_roc_flag ? (u64)(rwnx_hw->roc_cookie_cnt) : *cookie;
#else
roc_cookie = (u64)(rwnx_hw->roc_cookie_cnt);
#endif
roc_elem->cookie = roc_cookie;
/* Forward the information to the FMAC */ /* Forward the information to the FMAC */
rwnx_hw->roc_elem = roc_elem; rwnx_hw->roc_elem = roc_elem;
error = rwnx_send_roc(rwnx_hw, rwnx_vif, chan, duration, &roc_cfm); error = rwnx_send_roc(rwnx_hw, rwnx_vif, chan, duration, &roc_cfm);
@@ -4827,7 +4891,12 @@ rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy,
if (error == 0) { if (error == 0) {
/* Set the cookie value */ /* Set the cookie value */
*cookie = (u64)(rwnx_hw->roc_cookie_cnt); #if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
if (mgmt_roc_flag)
*cookie = roc_cookie;
#else
*cookie = roc_cookie;
#endif
if(roc_cfm.status) { if(roc_cfm.status) {
// failed to roc // failed to roc
rwnx_hw->roc_elem = NULL; rwnx_hw->roc_elem = NULL;
@@ -4857,18 +4926,42 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
enum nl80211_channel_type channel_type, enum nl80211_channel_type channel_type,
#endif #endif
unsigned int duration, u64 *cookie unsigned int duration,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 2, 0) #if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
/*
* 7.3 made this cookie an input parameter: cfg80211
* pre-assigns it before calling us instead of us
* inventing one and returning it. See
* rwnx_cfg80211_remain_on_channel_(). rx_addr is
* unused for the reason given in the 7.2 arm below:
* it is always NULL for this driver.
*/
u64 cookie, const u8 *rx_addr
#elif AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 2, 0)
/* /*
* 7.2 added an optional receive address filter for the off-channel * 7.2 added an optional receive address filter for the off-channel
* period. cfg80211 refuses a non-NULL one unless the driver sets * period. cfg80211 refuses a non-NULL one unless the driver sets
* NL80211_EXT_FEATURE_ROC_ADDR_FILTER, which this one does not, so it * NL80211_EXT_FEATURE_ROC_ADDR_FILTER, which this one does not, so it
* is always NULL here. mac80211 ignores it in the same way. * is always NULL here. mac80211 ignores it in the same way.
*/ */
, const u8 *rx_addr u64 *cookie, const u8 *rx_addr
#else
u64 *cookie
#endif #endif
) )
{ {
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
/*
* 7.3 passes the cookie by value, while the shared helper still takes a
* pointer because its internal caller invents one. Only the argument
* differs, so pick it here and leave the call itself alone.
*/
u64 local_cookie = cookie;
u64 *cookie_ptr = &local_cookie;
#else
u64 *cookie_ptr = cookie;
#endif
return rwnx_cfg80211_remain_on_channel_(wiphy, return rwnx_cfg80211_remain_on_channel_(wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
wdev, wdev,
@@ -4879,7 +4972,7 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
channel_type, channel_type,
#endif #endif
duration, cookie, false); duration, cookie_ptr, false);
} }
/** /**
@@ -5057,7 +5150,17 @@ struct ieee80211_channel *rwnx_cfg80211_get_channel(struct wiphy *wiphy)
/** /**
* @mgmt_tx: Transmit a management frame. * @mgmt_tx: Transmit a management frame.
*/ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) #if (AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0))
static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params,
/*
* 7.3 made this cookie an input parameter: cfg80211
* pre-assigns it before calling us instead of us
* inventing one and returning it. See
* rwnx_start_mgmt_xmit().
*/
u64 cookie)
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params, struct cfg80211_mgmt_tx_params *params,
u64 *cookie) u64 *cookie)
@@ -5072,7 +5175,7 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
bool dont_wait_for_ack, bool dont_wait_for_ack,
#endif #endif
u64 *cookie) u64 *cookie)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ #endif /* AICWF_CFG80211_VERSION_CODE >= 7.3 / LINUX_VERSION_CODE >= 3.14 */
{ {
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
@@ -5159,7 +5262,8 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
return -EINVAL; return -EINVAL;
} }
} else { } else {
u64 cookie; /* The internal RoC's own cookie; deliberately not the mgmt_tx one. */
u64 roc_cookie;
int error; int error;
AICWFDBG(LOGINFO, "mgmt rx remain on chan\n"); AICWFDBG(LOGINFO, "mgmt rx remain on chan\n");
@@ -5167,13 +5271,13 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
/* Start a ROC procedure for 30ms */ /* Start a ROC procedure for 30ms */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel,
30, &cookie, true); 30, &roc_cookie, true);
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, NL80211_CHAN_NO_HT, error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, NL80211_CHAN_NO_HT,
30, &cookie, true); 30, &roc_cookie, true);
#else #else
error = rwnx_cfg80211_remain_on_channel_(wiphy, dev, channel, NL80211_CHAN_NO_HT, error = rwnx_cfg80211_remain_on_channel_(wiphy, dev, channel, NL80211_CHAN_NO_HT,
30, &cookie, true); 30, &roc_cookie, true);
#endif #endif
if (error) { if (error) {
@@ -5190,11 +5294,16 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
#endif #endif
send_frame: send_frame:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) #if (AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0))
return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, cookie); {
u64 local_cookie = cookie;
return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, &local_cookie, true);
}
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, cookie, false);
#else #else
return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie); return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie, false);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ #endif /* AICWF_CFG80211_VERSION_CODE >= 7.3 / LINUX_VERSION_CODE >= 3.14 */
} }
/** /**
@@ -6552,7 +6661,11 @@ static struct cfg80211_ops rwnx_cfg80211_ops = {
.change_beacon = rwnx_cfg80211_change_beacon, .change_beacon = rwnx_cfg80211_change_beacon,
.stop_ap = rwnx_cfg80211_stop_ap, .stop_ap = rwnx_cfg80211_stop_ap,
.set_monitor_channel = rwnx_cfg80211_set_monitor_channel, .set_monitor_channel = rwnx_cfg80211_set_monitor_channel,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
.probe_peer = rwnx_cfg80211_probe_client,
#else
.probe_client = rwnx_cfg80211_probe_client, .probe_client = rwnx_cfg80211_probe_client,
#endif
// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register, // .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register,
.set_wiphy_params = rwnx_cfg80211_set_wiphy_params, .set_wiphy_params = rwnx_cfg80211_set_wiphy_params,
.set_txq_params = rwnx_cfg80211_set_txq_params, .set_txq_params = rwnx_cfg80211_set_txq_params,
+5
View File
@@ -99,8 +99,13 @@ int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef); struct cfg80211_chan_def *chandef);
#endif #endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0)
int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u64 cookie);
#else
int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u64 *cookie); const u8 *peer, u64 *cookie);
#endif
void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy, void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
struct net_device *dev, struct net_device *dev,
+6 -6
View File
@@ -123,13 +123,13 @@ static inline int rwnx_rx_chan_switch_ind(struct rwnx_hw *rwnx_hw,
if (!roc_elem->mgmt_roc) { if (!roc_elem->mgmt_roc) {
/* Inform the host that we have switch on the indicated off-channel */ /* Inform the host that we have switch on the indicated off-channel */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
cfg80211_ready_on_channel(roc_elem->wdev->netdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_ready_on_channel(roc_elem->wdev->netdev, roc_elem->cookie,
roc_elem->chan, NL80211_CHAN_HT20, roc_elem->duration, GFP_ATOMIC); roc_elem->chan, NL80211_CHAN_HT20, roc_elem->duration, GFP_ATOMIC);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) #elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
cfg80211_ready_on_channel(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_ready_on_channel(roc_elem->wdev, roc_elem->cookie,
roc_elem->chan, NL80211_CHAN_HT20, roc_elem->duration, GFP_ATOMIC); roc_elem->chan, NL80211_CHAN_HT20, roc_elem->duration, GFP_ATOMIC);
#else #else
cfg80211_ready_on_channel(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_ready_on_channel(roc_elem->wdev, roc_elem->cookie,
roc_elem->chan, roc_elem->duration, GFP_ATOMIC); roc_elem->chan, roc_elem->duration, GFP_ATOMIC);
#endif #endif
} }
@@ -245,13 +245,13 @@ static inline int rwnx_rx_remain_on_channel_exp_ind(struct rwnx_hw *rwnx_hw,
/* Inform the host that off-channel period has expired */ /* Inform the host that off-channel period has expired */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
cfg80211_remain_on_channel_expired(roc_elem->wdev->netdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_remain_on_channel_expired(roc_elem->wdev->netdev, roc_elem->cookie,
roc_elem->chan, NL80211_CHAN_HT20, GFP_ATOMIC); roc_elem->chan, NL80211_CHAN_HT20, GFP_ATOMIC);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) #elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
cfg80211_remain_on_channel_expired(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_remain_on_channel_expired(roc_elem->wdev, roc_elem->cookie,
roc_elem->chan, NL80211_CHAN_HT20, GFP_ATOMIC); roc_elem->chan, NL80211_CHAN_HT20, GFP_ATOMIC);
#else #else
cfg80211_remain_on_channel_expired(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), cfg80211_remain_on_channel_expired(roc_elem->wdev, roc_elem->cookie,
roc_elem->chan, GFP_ATOMIC); roc_elem->chan, GFP_ATOMIC);
#endif #endif
} }
+2 -2
View File
@@ -775,9 +775,9 @@ rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_v
params.len = skb->len; params.len = skb->len;
params.buf = skb->data; params.buf = skb->data;
ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, &params, false, &cookie); ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, &params, false, &cookie, false);
#else #else
ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie); ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie, false);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
return ret; return ret;
+33 -4
View File
@@ -1325,6 +1325,7 @@ int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg)
sw_txhdr->rwnx_sta = sta; sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = rwnx_vif; sw_txhdr->rwnx_vif = rwnx_vif;
sw_txhdr->skb = skb; sw_txhdr->skb = skb;
sw_txhdr->cookie = (unsigned long)skb;
sw_txhdr->headroom = headroom; sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr);
@@ -1541,6 +1542,7 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev)
sw_txhdr->rwnx_sta = sta; sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = rwnx_vif; sw_txhdr->rwnx_vif = rwnx_vif;
sw_txhdr->skb = skb; sw_txhdr->skb = skb;
sw_txhdr->cookie = (unsigned long)skb;
sw_txhdr->headroom = headroom; sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr);
@@ -1630,7 +1632,12 @@ free:
* @params: Mgmt frame parameters * @params: Mgmt frame parameters
* @offchan: Indicate whether the frame must be send via the offchan TXQ. * @offchan: Indicate whether the frame must be send via the offchan TXQ.
* (is is redundant with params->offchan ?) * (is is redundant with params->offchan ?)
* @cookie: updated with a unique value to identify the frame with upper layer * @cookie: on return, the value cfg80211_mgmt_tx_status() will report for
* this frame: invented here (the skb pointer) unless
* @use_given_cookie is set, in which case *@cookie is kept.
* @use_given_cookie: *@cookie already holds the cookie cfg80211 assigned
* (7.3+, the direct .mgmt_tx path only); honour it instead of
* inventing one. Every other caller passes false.
* *
*/ */
@@ -1638,7 +1645,7 @@ free:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
struct cfg80211_mgmt_tx_params *params, bool offchan, struct cfg80211_mgmt_tx_params *params, bool offchan,
u64 *cookie) u64 *cookie, bool use_given_cookie)
#else #else
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
struct ieee80211_channel *channel, bool offchan, struct ieee80211_channel *channel, bool offchan,
@@ -1649,7 +1656,7 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
bool dont_wait_for_ack, bool dont_wait_for_ack,
#endif #endif
u64 *cookie) u64 *cookie, bool use_given_cookie)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
{ {
struct rwnx_hw *rwnx_hw = vif->rwnx_hw; struct rwnx_hw *rwnx_hw = vif->rwnx_hw;
@@ -1703,6 +1710,17 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
return -ENOMEM; return -ENOMEM;
} }
/*
* use_given_cookie is true only for the direct cfg80211 .mgmt_tx call
* path on 7.3+, where *cookie already holds the value cfg80211
* pre-assigned and must be echoed back via cfg80211_mgmt_tx_status()
* later -- see rwnx_cfg80211_mgmt_tx(). TDLS's internal reuse of this
* function (use_given_cookie == false) never goes through that cfg80211
* op, so it still gets an invented, locally-unique cookie exactly as
* before this fix, and on every kernel older than 7.3 every caller
* passes use_given_cookie == false, also leaving this unchanged.
*/
if (!use_given_cookie)
*cookie = (unsigned long)skb; *cookie = (unsigned long)skb;
/* /*
@@ -1773,6 +1791,7 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
sw_txhdr->rwnx_sta = sta; sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = vif; sw_txhdr->rwnx_vif = vif;
sw_txhdr->skb = skb; sw_txhdr->skb = skb;
sw_txhdr->cookie = *cookie;
sw_txhdr->headroom = headroom; sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr);
#ifdef CONFIG_RWNX_AMSDUS_TX #ifdef CONFIG_RWNX_AMSDUS_TX
@@ -1924,6 +1943,7 @@ void rwnx_probersp_work(struct work_struct *work)
sw_txhdr->rwnx_sta = sta; sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = rwnx_vif; sw_txhdr->rwnx_vif = rwnx_vif;
sw_txhdr->skb = skb; sw_txhdr->skb = skb;
sw_txhdr->cookie = (unsigned long)skb;
sw_txhdr->headroom = headroom; sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr);
#ifdef CONFIG_RWNX_AMSDUS_TX #ifdef CONFIG_RWNX_AMSDUS_TX
@@ -2278,6 +2298,15 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
sw_txhdr->rwnx_sta = sta; sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = vif; sw_txhdr->rwnx_vif = vif;
sw_txhdr->skb = skb_mgmt; sw_txhdr->skb = skb_mgmt;
/*
* Injected frames are flagged TXU_CNTRL_MGMT below and complete through
* the same path as management frames, which reports sw_txhdr->cookie to
* cfg80211_mgmt_tx_status(). There is no cfg80211-assigned cookie for an
* injected frame, so this is the skb-derived value that path reported
* before the field existed. Not gated on 7.3: this path runs on every
* kernel with CONFIG_RWNX_MON_XMIT.
*/
sw_txhdr->cookie = (unsigned long)skb_mgmt;
sw_txhdr->headroom = headroom; sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb_mgmt->len - offsetof(struct rwnx_txhdr, hw_hdr); sw_txhdr->map_len = skb_mgmt->len - offsetof(struct rwnx_txhdr, hw_hdr);
sw_txhdr->raw_frame = 1; sw_txhdr->raw_frame = 1;
@@ -2389,7 +2418,7 @@ int rwnx_txdatacfm(void *pthis, void *host_id)
#endif #endif
/* Confirm transmission to CFG80211 */ /* Confirm transmission to CFG80211 */
cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev, cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev,
(unsigned long)skb, sw_txhdr->cookie,
(skb->data + sw_txhdr->headroom), (skb->data + sw_txhdr->headroom),
sw_txhdr->frame_len, sw_txhdr->frame_len,
rwnx_txst.acknowledged, rwnx_txst.acknowledged,
+13 -2
View File
@@ -130,6 +130,17 @@ struct rwnx_sw_txhdr {
#endif #endif
u32 need_cfm; u32 need_cfm;
struct sk_buff *skb; struct sk_buff *skb;
/*
* The cookie cfg80211_mgmt_tx_status() reports for this frame. sw_txhdr
* comes from a kmem_cache and is never zeroed, so every allocation site
* sets this: (unsigned long)skb, which is what the completion path
* reported before the field existed, except in rwnx_start_mgmt_xmit(),
* which stores the cfg80211-assigned cookie it was handed on 7.3+ (see
* use_given_cookie there). Only frames flagged TXU_CNTRL_MGMT are ever
* reported, but the field is initialised unconditionally so that filter
* is not what keeps it safe.
*/
u64 cookie;
size_t map_len; size_t map_len;
dma_addr_t dma_addr; dma_addr_t dma_addr;
@@ -158,7 +169,7 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
struct cfg80211_mgmt_tx_params *params, bool offchan, struct cfg80211_mgmt_tx_params *params, bool offchan,
u64 *cookie); u64 *cookie, bool use_given_cookie);
#else #else
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
struct ieee80211_channel *channel, bool offchan, struct ieee80211_channel *channel, bool offchan,
@@ -169,7 +180,7 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
bool dont_wait_for_ack, bool dont_wait_for_ack,
#endif #endif
u64 *cookie); u64 *cookie, bool use_given_cookie);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
#ifdef CONFIG_RWNX_MON_XMIT #ifdef CONFIG_RWNX_MON_XMIT
netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb,