Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 278670
b: refs/heads/master
c: a32d0cd
h: refs/heads/master
v: v3
  • Loading branch information
Eliad Peller authored and Luciano Coelho committed Oct 11, 2011
1 parent 7b74052 commit dd3f02c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 36 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: 87627214738fcfd44803e90193f9f2f4583ce68b
refs/heads/master: a32d0cdfcb7e5d41f210e13cbc78dc86a5a85a08
6 changes: 3 additions & 3 deletions trunk/drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
* In order to avoid starvation of the TX path,
* call the work function directly.
*/
wl1271_tx_work_locked(wl, wl->vif);
wl1271_tx_work_locked(wl);
} else {
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
Expand Down Expand Up @@ -1537,7 +1537,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)

/* The FW is low on RX memory blocks, so send the dummy packet asap */
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
wl1271_tx_work_locked(wl, wl->vif);
wl1271_tx_work_locked(wl);

/*
* If the FW TX is busy, TX work will be scheduled by the threaded
Expand Down Expand Up @@ -2413,7 +2413,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
((wl->band != conf->channel->band) ||
(wl->channel != channel))) {
/* send all pending packets */
wl1271_tx_work_locked(wl, vif);
wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
wl->channel = channel;

Expand Down
79 changes: 48 additions & 31 deletions trunk/drivers/net/wireless/wl12xx/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,17 @@ static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
}

static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 extra, u32 buf_offset,
u8 hlid)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 len;
u32 total_blocks;
int id, ret = -EBUSY, ac;
u32 spare_blocks = wl->tx_spare_blocks;
bool is_dummy = false;

if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
Expand All @@ -235,8 +235,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
len = wl12xx_calc_packet_alignment(wl, total_len);

/* in case of a dummy packet, use default amount of spare mem blocks */
if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
if (unlikely(wl12xx_is_dummy_packet(wl, skb))) {
is_dummy = true;
spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
}

total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks;
Expand All @@ -261,7 +263,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_pkts[ac]++;

if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS &&
test_bit(hlid, wlvif->ap.sta_hlid_map))
wl->links[hlid].allocated_pkts++;

Expand All @@ -277,16 +279,16 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
return ret;
}

static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 extra,
struct ieee80211_tx_info *control, u8 hlid)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct timespec ts;
struct wl1271_tx_hw_descr *desc;
int aligned_len, ac, rate_idx;
s64 hosttime;
u16 tx_attr;
bool is_dummy;

desc = (struct wl1271_tx_hw_descr *) skb->data;

Expand All @@ -303,7 +305,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
hosttime = (timespec_to_ns(&ts) >> 10);
desc->start_time = cpu_to_le32(hosttime - wl->time_offset);

if (wlvif->bss_type != BSS_TYPE_AP_BSS)
is_dummy = wl12xx_is_dummy_packet(wl, skb);
if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS)
desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
else
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
Expand All @@ -312,7 +315,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
desc->tid = skb->priority;

if (wl12xx_is_dummy_packet(wl, skb)) {
if (is_dummy) {
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
Expand All @@ -329,7 +332,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
}

desc->hlid = hlid;
if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
if (is_dummy)
rate_idx = 0;
else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default
basic rates */
Expand Down Expand Up @@ -383,12 +388,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
}

/* caller must hold wl->mutex */
static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
u32 buf_offset)
static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 buf_offset)
{
struct ieee80211_tx_info *info;
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
u32 extra = 0;
int ret = 0;
u32 total_len;
Expand All @@ -402,11 +405,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,

/* TODO: handle dummy packets on multi-vifs */
is_dummy = wl12xx_is_dummy_packet(wl, skb);
if (is_dummy)
info->control.vif = wl->vif;

vif = info->control.vif;
wlvif = wl12xx_vif_to_data(vif);

if (info->control.hw_key &&
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
Expand All @@ -433,13 +431,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return -EINVAL;
}

ret = wl1271_tx_allocate(wl, vif, skb, extra, buf_offset, hlid);
ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid);
if (ret < 0)
return ret;

wl1271_tx_fill_hdr(wl, vif, skb, extra, info, hlid);
wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);

if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) {
if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, wlvif, hlid);
}
Expand Down Expand Up @@ -589,13 +587,19 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
return skb;
}

static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
{
unsigned long flags;
struct wl12xx_vif *wlvif;
struct sk_buff *skb = NULL;

skb = wl12xx_vif_skb_dequeue(wl, wlvif);
/* TODO: rememeber last vif and consider it */
wl12xx_for_each_wlvif(wl, wlvif) {
skb = wl12xx_vif_skb_dequeue(wl, wlvif);
if (skb)
break;
}

if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
int q;
Expand Down Expand Up @@ -639,24 +643,35 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
return ieee80211_is_data_present(hdr->frame_control);
}

void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
void wl1271_tx_work_locked(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl12xx_vif *wlvif;
struct sk_buff *skb;
u32 buf_offset = 0;
bool sent_packets = false;
bool had_data = false;
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
/* TODO: save bitmap of relevant stations */
bool is_sta = false;
int ret;

if (unlikely(wl->state == WL1271_STATE_OFF))
return;

while ((skb = wl1271_skb_dequeue(wl, wlvif))) {
while ((skb = wl1271_skb_dequeue(wl))) {
wlvif = NULL;
if (!wl12xx_is_dummy_packet(wl, skb)) {
struct ieee80211_tx_info *info;
struct ieee80211_vif *vif;

info = IEEE80211_SKB_CB(skb);
vif = info->control.vif;
wlvif = wl12xx_vif_to_data(vif);
}

if (wl1271_tx_is_data_present(skb))
had_data = true;

ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
if (ret == -EAGAIN) {
/*
* Aggregation buffer is full.
Expand All @@ -683,6 +698,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
}
buf_offset += ret;
wl->tx_packets_count++;
if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS)
is_sta = true;
}

out_ack:
Expand All @@ -702,7 +719,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)

wl1271_handle_tx_low_watermark(wl);
}
if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
if (is_sta && wl->conf.rx_streaming.interval && had_data &&
(wl->conf.rx_streaming.always ||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
u32 timeout = wl->conf.rx_streaming.duration;
Expand All @@ -727,7 +744,7 @@ void wl1271_tx_work(struct work_struct *work)
if (ret < 0)
goto out;

wl1271_tx_work_locked(wl, wl->vif);
wl1271_tx_work_locked(wl);

wl1271_ps_elp_sleep(wl);
out:
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/wl12xx/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
}

void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif);
void wl1271_tx_work_locked(struct wl1271 *wl);
void wl1271_tx_complete(struct wl1271 *wl);
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
Expand Down

0 comments on commit dd3f02c

Please sign in to comment.