Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 278221
b: refs/heads/master
c: 11127e9
h: refs/heads/master
i:
  278219: 03b61fa
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Nov 21, 2011
1 parent 0f09bf4 commit fb5fb86
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 74e4dbfd57a38c4ec4131cebdbfa3d621d38dd6a
refs/heads/master: 11127e9121d4dd9da868cf0fd89dcac35f7f0fa3
22 changes: 17 additions & 5 deletions trunk/include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1760,11 +1760,21 @@ enum ieee80211_frame_release_type {
* skb contains the buffer starting from the IEEE 802.11 header.
* The low-level driver should send the frame out based on
* configuration in the TX control data. This handler should,
* preferably, never fail and stop queues appropriately, more
* importantly, however, it must never fail for A-MPDU-queues.
* This function should return NETDEV_TX_OK except in very
* limited cases.
* Must be implemented and atomic.
* preferably, never fail and stop queues appropriately.
* This must be implemented if @tx_frags is not.
* Must be atomic.
*
* @tx_frags: Called to transmit multiple fragments of a single MSDU.
* This handler must consume all fragments, sending out some of
* them only is useless and it can't ask for some of them to be
* queued again. If the frame is not fragmented the queue has a
* single SKB only. To avoid issues with the networking stack
* when TX status is reported the frames should be removed from
* the skb queue.
* If this is used, the tx_info @vif and @sta pointers will be
* invalid -- you must not use them in that case.
* This must be implemented if @tx isn't.
* Must be atomic.
*
* @start: Called before the first netdevice attached to the hardware
* is enabled. This should turn on the hardware and must turn on
Expand Down Expand Up @@ -2101,6 +2111,8 @@ enum ieee80211_frame_release_type {
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct sk_buff_head *skbs);
int (*start)(struct ieee80211_hw *hw);
void (*stop)(struct ieee80211_hw *hw);
#ifdef CONFIG_PM
Expand Down
8 changes: 8 additions & 0 deletions trunk/net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
local->ops->tx(&local->hw, skb);
}

static inline void drv_tx_frags(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct sk_buff_head *skbs)
{
local->ops->tx_frags(&local->hw, vif, sta, skbs);
}

static inline int drv_start(struct ieee80211_local *local)
{
int ret;
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,

local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);

BUG_ON(!ops->tx);
BUG_ON(!ops->tx && !ops->tx_frags);
BUG_ON(!ops->start);
BUG_ON(!ops->stop);
BUG_ON(!ops->config);
Expand Down
94 changes: 60 additions & 34 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1200,24 +1200,15 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
return TX_CONTINUE;
}

/*
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool __ieee80211_tx(struct ieee80211_local *local,
struct sk_buff_head *skbs, int led_len,
struct sta_info *sta, bool txpending)
static bool ieee80211_tx_frags(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct sk_buff_head *skbs,
bool txpending)
{
struct sk_buff *skb, *tmp;
struct ieee80211_tx_info *info;
struct ieee80211_sub_if_data *sdata;
unsigned long flags;
__le16 fc;

if (WARN_ON(skb_queue_empty(skbs)))
return true;

skb = skb_peek(skbs);
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;

skb_queue_walk_safe(skbs, skb, tmp) {
int q = skb_get_queue_mapping(skb);
Expand All @@ -1242,37 +1233,72 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

info = IEEE80211_SKB_CB(skb);
info->control.vif = vif;
info->control.sta = sta;

sdata = vif_to_sdata(info->control.vif);
__skb_unlink(skb, skbs);
drv_tx(local, skb);
}

switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
info->control.vif = NULL;
break;
case NL80211_IFTYPE_AP_VLAN:
info->control.vif = &container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap)->vif;
break;
default:
/* keep */
break;
}
return true;
}

if (sta && sta->uploaded)
info->control.sta = &sta->sta;
else
info->control.sta = NULL;
/*
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool __ieee80211_tx(struct ieee80211_local *local,
struct sk_buff_head *skbs, int led_len,
struct sta_info *sta, bool txpending)
{
struct ieee80211_tx_info *info;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_vif *vif;
struct ieee80211_sta *pubsta;
struct sk_buff *skb;
bool result = true;
__le16 fc;

__skb_unlink(skb, skbs);
drv_tx(local, skb);
if (WARN_ON(skb_queue_empty(skbs)))
return true;

skb = skb_peek(skbs);
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
info = IEEE80211_SKB_CB(skb);
sdata = vif_to_sdata(info->control.vif);
if (sta && !sta->uploaded)
sta = NULL;

if (sta)
pubsta = &sta->sta;
else
pubsta = NULL;

switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
sdata = NULL;
vif = NULL;
break;
case NL80211_IFTYPE_AP_VLAN:
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap);
/* fall through */
default:
vif = &sdata->vif;
break;
}

if (local->ops->tx_frags)
drv_tx_frags(local, vif, pubsta, skbs);
else
result = ieee80211_tx_frags(local, vif, pubsta, skbs,
txpending);

ieee80211_tpt_led_trig_tx(local, fc, led_len);
ieee80211_led_tx(local, 1);

WARN_ON(!skb_queue_empty(skbs));

return true;
return result;
}

/*
Expand Down

0 comments on commit fb5fb86

Please sign in to comment.