Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e943789e authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: provide ieee80211_sta_eosp()



The irqsafe version ieee80211_sta_eosp_irqsafe() exists, but
drivers must not mix calls to any irqsafe/non-irqsafe function.
Both ath9k and iwlwifi, the likely first users of this interface,
use non-irqsafe RX/TX/TX status so must also use a non-irqsafe
version of this function. Since no driver uses the _irqsafe()
version, remove that.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 560d2682
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -437,7 +437,7 @@
      </section>
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
!Finclude/net/mac80211.h ieee80211_beacon_get
!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
!Finclude/net/mac80211.h ieee80211_sta_eosp
!Finclude/net/mac80211.h ieee80211_frame_release_type
!Finclude/net/mac80211.h ieee80211_sta_ps_transition
!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
+14 −11
Original line number Diff line number Diff line
@@ -1946,14 +1946,14 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
 * filter those response frames except in the case of frames that
 * are buffered in the driver -- those must remain buffered to avoid
 * reordering. Because it is possible that no frames are released
 * in this case, the driver must call ieee80211_sta_eosp_irqsafe()
 * in this case, the driver must call ieee80211_sta_eosp()
 * to indicate to mac80211 that the service period ended anyway.
 *
 * Finally, if frames from multiple TIDs are released from mac80211
 * but the driver might reorder them, it must clear & set the flags
 * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
 * and also take care of the EOSP and MORE_DATA bits in the frame.
 * The driver may also use ieee80211_sta_eosp_irqsafe() in this case.
 * The driver may also use ieee80211_sta_eosp() in this case.
 */

/**
@@ -2506,7 +2506,7 @@ enum ieee80211_roc_type {
 *	setting the EOSP flag in the QoS header of the frames. Also, when the
 *	service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
 *	on the last frame in the SP. Alternatively, it may call the function
 *	ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP.
 *	ieee80211_sta_eosp() to inform mac80211 of the end of the SP.
 *	This callback must be atomic.
 * @allow_buffered_frames: Prepare device to allow the given number of frames
 *	to go out to the given station. The frames will be sent by mac80211
@@ -2517,7 +2517,7 @@ enum ieee80211_roc_type {
 *	them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
 *	on the last frame and clear it on all others and also handle the EOSP
 *	bit in the QoS header correctly. Alternatively, it can also call the
 *	ieee80211_sta_eosp_irqsafe() function.
 *	ieee80211_sta_eosp() function.
 *	The @tids parameter is a bitmap and tells the driver which TIDs the
 *	frames will be on; it will at most have two bits set.
 *	This callback must be atomic.
@@ -3857,14 +3857,17 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
 * %IEEE80211_TX_STATUS_EOSP bit and call this function instead.
 * This applies for PS-Poll as well as uAPSD.
 *
 * Note that there is no non-_irqsafe version right now as
 * it wasn't needed, but just like _tx_status() and _rx()
 * must not be mixed in irqsafe/non-irqsafe versions, this
 * function must not be mixed with those either. Use the
 * all irqsafe, or all non-irqsafe, don't mix! If you need
 * the non-irqsafe version of this, you need to add it.
 * Note that just like with _tx_status() and _rx() drivers must
 * not mix calls to irqsafe/non-irqsafe versions, this function
 * must not be mixed with those either. Use the all irqsafe, or
 * all non-irqsafe, don't mix!
 *
 * NB: the _irqsafe version of this function doesn't exist, no
 *     driver needs it right now. Don't call this function if
 *     you'd need the _irqsafe version, look at the git history
 *     and restore the _irqsafe version!
 */
void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta);
void ieee80211_sta_eosp(struct ieee80211_sta *pubsta);

/**
 * ieee80211_iter_keys - iterate keys programmed into the device
+0 −5
Original line number Diff line number Diff line
@@ -800,11 +800,6 @@ enum sdata_queue_type {
enum {
	IEEE80211_RX_MSG	= 1,
	IEEE80211_TX_STATUS_MSG	= 2,
	IEEE80211_EOSP_MSG	= 3,
};

struct skb_eosp_msg_data {
	u8 sta[ETH_ALEN], iface[ETH_ALEN];
};

enum queue_stop_reason {
+0 −14
Original line number Diff line number Diff line
@@ -226,8 +226,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
static void ieee80211_tasklet_handler(unsigned long data)
{
	struct ieee80211_local *local = (struct ieee80211_local *) data;
	struct sta_info *sta, *tmp;
	struct skb_eosp_msg_data *eosp_data;
	struct sk_buff *skb;

	while ((skb = skb_dequeue(&local->skb_queue)) ||
@@ -243,18 +241,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
			skb->pkt_type = 0;
			ieee80211_tx_status(&local->hw, skb);
			break;
		case IEEE80211_EOSP_MSG:
			eosp_data = (void *)skb->cb;
			for_each_sta_info(local, eosp_data->sta, sta, tmp) {
				/* skip wrong virtual interface */
				if (memcmp(eosp_data->iface,
					   sta->sdata->vif.addr, ETH_ALEN))
					continue;
				clear_sta_flag(sta, WLAN_STA_SP);
				break;
			}
			dev_kfree_skb(skb);
			break;
		default:
			WARN(1, "mac80211: Packet is of unknown type %d\n",
			     skb->pkt_type);
+3 −17
Original line number Diff line number Diff line
@@ -1390,30 +1390,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_sta_block_awake);

void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta)
void ieee80211_sta_eosp(struct ieee80211_sta *pubsta)
{
	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
	struct ieee80211_local *local = sta->local;
	struct sk_buff *skb;
	struct skb_eosp_msg_data *data;

	trace_api_eosp(local, pubsta);

	skb = alloc_skb(0, GFP_ATOMIC);
	if (!skb) {
		/* too bad ... but race is better than loss */
	clear_sta_flag(sta, WLAN_STA_SP);
		return;
	}

	data = (void *)skb->cb;
	memcpy(data->sta, pubsta->addr, ETH_ALEN);
	memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN);
	skb->pkt_type = IEEE80211_EOSP_MSG;
	skb_queue_tail(&local->skb_queue, skb);
	tasklet_schedule(&local->tasklet);
}
EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe);
EXPORT_SYMBOL(ieee80211_sta_eosp);

void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
				u8 tid, bool buffered)