mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-28 07:04:00 +08:00
wl18xx: implement immediate Tx completion
Implement immediate Tx completion for the 18xx family. Move 18xx specific Tx code to new tx.c/h files and create helper header files for definitions. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
30e2dd798d
commit
872b345fba
@ -1,3 +1,3 @@
|
||||
wl18xx-objs = main.o
|
||||
wl18xx-objs = main.o tx.o
|
||||
|
||||
obj-$(CONFIG_WL18XX) += wl18xx.o
|
||||
|
@ -33,11 +33,9 @@
|
||||
|
||||
#include "reg.h"
|
||||
#include "conf.h"
|
||||
#include "tx.h"
|
||||
#include "wl18xx.h"
|
||||
|
||||
#define WL18XX_TX_HW_BLOCK_SPARE 1
|
||||
#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
|
||||
#define WL18XX_TX_HW_BLOCK_SIZE 268
|
||||
|
||||
static const u8 wl18xx_rate_to_idx_2ghz[] = {
|
||||
/* MCS rates are used only with 11n */
|
||||
@ -470,6 +468,11 @@ static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
|
||||
return data_len - sizeof(*desc);
|
||||
}
|
||||
|
||||
static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
|
||||
{
|
||||
wl18xx_tx_immediate_complete(wl);
|
||||
}
|
||||
|
||||
static struct wlcore_ops wl18xx_ops = {
|
||||
.identify_chip = wl18xx_identify_chip,
|
||||
.boot = wl18xx_boot,
|
||||
@ -480,6 +483,8 @@ static struct wlcore_ops wl18xx_ops = {
|
||||
.set_tx_desc_data_len = wl18xx_set_tx_desc_data_len,
|
||||
.get_rx_buf_align = wl18xx_get_rx_buf_align,
|
||||
.get_rx_packet_len = wl18xx_get_rx_packet_len,
|
||||
.tx_immediate_compl = wl18xx_tx_immediate_completion,
|
||||
.tx_delayed_compl = NULL,
|
||||
};
|
||||
|
||||
int __devinit wl18xx_probe(struct platform_device *pdev)
|
||||
|
126
drivers/net/wireless/ti/wl18xx/tx.c
Normal file
126
drivers/net/wireless/ti/wl18xx/tx.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
#include "../wlcore/cmd.h"
|
||||
#include "../wlcore/debug.h"
|
||||
#include "../wlcore/acx.h"
|
||||
#include "../wlcore/tx.h"
|
||||
|
||||
#include "wl18xx.h"
|
||||
#include "tx.h"
|
||||
|
||||
static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
|
||||
{
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb;
|
||||
int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK;
|
||||
bool tx_success;
|
||||
|
||||
/* check for id legality */
|
||||
if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
|
||||
wl1271_warning("illegal id in tx completion: %d", id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* a zero bit indicates Tx success */
|
||||
tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX));
|
||||
|
||||
|
||||
skb = wl->tx_frames[id];
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (wl12xx_is_dummy_packet(wl, skb)) {
|
||||
wl1271_free_tx_id(wl, id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the TX status info */
|
||||
if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
/* no real data about Tx completion */
|
||||
info->status.rates[0].idx = -1;
|
||||
info->status.rates[0].count = 0;
|
||||
info->status.rates[0].flags = 0;
|
||||
info->status.ack_signal = -1;
|
||||
|
||||
if (!tx_success)
|
||||
wl->stats.retry_count++;
|
||||
|
||||
/*
|
||||
* TODO: update sequence number for encryption? seems to be
|
||||
* unsupported for now. needed for recovery with encryption.
|
||||
*/
|
||||
|
||||
/* remove private header from packet */
|
||||
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
|
||||
|
||||
/* remove TKIP header space if present */
|
||||
if (info->control.hw_key &&
|
||||
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
||||
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen);
|
||||
skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d",
|
||||
id, skb, tx_success);
|
||||
|
||||
/* return the packet to the stack */
|
||||
skb_queue_tail(&wl->deferred_tx_queue, skb);
|
||||
queue_work(wl->freezable_wq, &wl->netstack_work);
|
||||
wl1271_free_tx_id(wl, id);
|
||||
}
|
||||
|
||||
void wl18xx_tx_immediate_complete(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_fw_status_priv *status_priv =
|
||||
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
u8 i;
|
||||
|
||||
/* nothing to do here */
|
||||
if (priv->last_fw_rls_idx == status_priv->fw_release_idx)
|
||||
return;
|
||||
|
||||
/* freed Tx descriptors */
|
||||
wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d",
|
||||
priv->last_fw_rls_idx, status_priv->fw_release_idx);
|
||||
|
||||
if (status_priv->fw_release_idx >= WL18XX_FW_MAX_TX_STATUS_DESC) {
|
||||
wl1271_error("invalid desc release index %d",
|
||||
status_priv->fw_release_idx);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = priv->last_fw_rls_idx;
|
||||
i != status_priv->fw_release_idx;
|
||||
i = (i + 1) % WL18XX_FW_MAX_TX_STATUS_DESC) {
|
||||
wl18xx_tx_complete_packet(wl,
|
||||
status_priv->released_tx_desc[i]);
|
||||
|
||||
wl->tx_results_count++;
|
||||
}
|
||||
|
||||
priv->last_fw_rls_idx = status_priv->fw_release_idx;
|
||||
}
|
36
drivers/net/wireless/ti/wl18xx/tx.h
Normal file
36
drivers/net/wireless/ti/wl18xx/tx.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL18XX_TX_H__
|
||||
#define __WL18XX_TX_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
|
||||
#define WL18XX_TX_HW_BLOCK_SPARE 1
|
||||
#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
|
||||
#define WL18XX_TX_HW_BLOCK_SIZE 268
|
||||
|
||||
#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
|
||||
#define WL18XX_TX_STATUS_STAT_BIT_IDX 7
|
||||
|
||||
void wl18xx_tx_immediate_complete(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL12XX_TX_H__ */
|
@ -28,6 +28,9 @@
|
||||
struct wl18xx_priv {
|
||||
/* buffer for sending commands to FW */
|
||||
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
|
||||
|
||||
/* Index of last released Tx desc in FW */
|
||||
u8 last_fw_rls_idx;
|
||||
};
|
||||
|
||||
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
|
||||
|
@ -72,7 +72,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
|
||||
return id;
|
||||
}
|
||||
|
||||
static void wl1271_free_tx_id(struct wl1271 *wl, int id)
|
||||
void wl1271_free_tx_id(struct wl1271 *wl, int id)
|
||||
{
|
||||
if (__test_and_clear_bit(id, wl->tx_frames_map)) {
|
||||
if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc))
|
||||
@ -82,6 +82,7 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
|
||||
wl->tx_frames_cnt--;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(wl1271_free_tx_id);
|
||||
|
||||
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
|
||||
struct sk_buff *skb)
|
||||
@ -127,6 +128,7 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
|
||||
{
|
||||
return wl->dummy_packet == skb;
|
||||
}
|
||||
EXPORT_SYMBOL(wl12xx_is_dummy_packet);
|
||||
|
||||
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct sk_buff *skb)
|
||||
|
@ -237,6 +237,7 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
|
||||
void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids);
|
||||
unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl,
|
||||
unsigned int packet_length);
|
||||
void wl1271_free_tx_id(struct wl1271 *wl, int id);
|
||||
|
||||
/* from main.c */
|
||||
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
|
||||
|
Loading…
Reference in New Issue
Block a user