ath9k_htc: Use SKB's private area for TX parameters
For all packets sent through the USB_WLAN_TX_PIPE endpoint, the private area of the SKB's tx_info can be used to store driver-specific information. For packets sent through USB_REG_OUT_PIPE, this will not make a difference since they are routed through a separate routine that doesn't access the private region. This would help in situations where TX information is required in the URB callback. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e723f3900c
commit
40dc9e4b86
|
@ -284,9 +284,9 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
|
static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||||
|
@ -305,12 +305,14 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
|
||||||
__skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
|
__skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
|
||||||
hif_dev->tx.tx_skb_cnt++;
|
hif_dev->tx.tx_skb_cnt++;
|
||||||
|
|
||||||
/* Send normal frames immediately */
|
tx_ctl = HTC_SKB_CB(skb);
|
||||||
if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL)))
|
|
||||||
|
/* Send normal/mgmt/beacon frames immediately */
|
||||||
|
if (tx_ctl->type != ATH9K_HTC_AMPDU)
|
||||||
__hif_usb_tx(hif_dev);
|
__hif_usb_tx(hif_dev);
|
||||||
|
|
||||||
/* Check if AMPDUs have to be sent immediately */
|
/* Check if AMPDUs have to be sent immediately */
|
||||||
if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) &&
|
if ((tx_ctl->type == ATH9K_HTC_AMPDU) &&
|
||||||
(hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
|
(hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
|
||||||
(hif_dev->tx.tx_skb_cnt < 2)) {
|
(hif_dev->tx.tx_skb_cnt < 2)) {
|
||||||
__hif_usb_tx(hif_dev);
|
__hif_usb_tx(hif_dev);
|
||||||
|
@ -352,15 +354,14 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
|
static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
switch (pipe_id) {
|
switch (pipe_id) {
|
||||||
case USB_WLAN_TX_PIPE:
|
case USB_WLAN_TX_PIPE:
|
||||||
ret = hif_usb_send_tx(hif_dev, skb, tx_ctl);
|
ret = hif_usb_send_tx(hif_dev, skb);
|
||||||
break;
|
break;
|
||||||
case USB_REG_OUT_PIPE:
|
case USB_REG_OUT_PIPE:
|
||||||
ret = hif_usb_send_regout(hif_dev, skb);
|
ret = hif_usb_send_regout(hif_dev, skb);
|
||||||
|
|
|
@ -67,8 +67,11 @@ enum htc_opmode {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr)
|
#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr)
|
||||||
#define ATH9K_HTC_AMPDU 1
|
|
||||||
|
#define ATH9K_HTC_AMPDU 1
|
||||||
#define ATH9K_HTC_NORMAL 2
|
#define ATH9K_HTC_NORMAL 2
|
||||||
|
#define ATH9K_HTC_BEACON 3
|
||||||
|
#define ATH9K_HTC_MGMT 4
|
||||||
|
|
||||||
#define ATH9K_HTC_TX_CTSONLY 0x1
|
#define ATH9K_HTC_TX_CTSONLY 0x1
|
||||||
#define ATH9K_HTC_TX_RTSCTS 0x2
|
#define ATH9K_HTC_TX_RTSCTS 0x2
|
||||||
|
@ -288,6 +291,15 @@ struct ath9k_htc_tx_ctl {
|
||||||
u8 type; /* ATH9K_HTC_* */
|
u8 type; /* ATH9K_HTC_* */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) >
|
||||||
|
IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
|
||||||
|
return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
||||||
|
|
||||||
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
|
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
|
||||||
|
|
|
@ -341,7 +341,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
struct ath9k_htc_vif *avp;
|
struct ath9k_htc_vif *avp;
|
||||||
struct tx_beacon_header beacon_hdr;
|
struct tx_beacon_header beacon_hdr;
|
||||||
struct ath9k_htc_tx_ctl tx_ctl;
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
struct ieee80211_mgmt *mgmt;
|
struct ieee80211_mgmt *mgmt;
|
||||||
struct sk_buff *beacon;
|
struct sk_buff *beacon;
|
||||||
|
@ -349,7 +349,6 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
|
memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
|
||||||
memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
|
|
||||||
|
|
||||||
spin_lock_bh(&priv->beacon_lock);
|
spin_lock_bh(&priv->beacon_lock);
|
||||||
|
|
||||||
|
@ -384,12 +383,16 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
||||||
hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
|
hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_ctl.type = ATH9K_HTC_NORMAL;
|
tx_ctl = HTC_SKB_CB(beacon);
|
||||||
|
memset(tx_ctl, 0, sizeof(*tx_ctl));
|
||||||
|
|
||||||
|
tx_ctl->type = ATH9K_HTC_BEACON;
|
||||||
|
|
||||||
beacon_hdr.vif_index = avp->index;
|
beacon_hdr.vif_index = avp->index;
|
||||||
tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
|
tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
|
||||||
memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr));
|
memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr));
|
||||||
|
|
||||||
ret = htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl);
|
ret = htc_send(priv->htc, beacon, priv->beacon_ep);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (ret == -ENOMEM) {
|
if (ret == -ENOMEM) {
|
||||||
ath_dbg(common, ATH_DBG_BSTUCK,
|
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||||
|
|
|
@ -89,13 +89,16 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
|
||||||
struct ieee80211_vif *vif = tx_info->control.vif;
|
struct ieee80211_vif *vif = tx_info->control.vif;
|
||||||
struct ath9k_htc_sta *ista;
|
struct ath9k_htc_sta *ista;
|
||||||
struct ath9k_htc_vif *avp = NULL;
|
struct ath9k_htc_vif *avp = NULL;
|
||||||
struct ath9k_htc_tx_ctl tx_ctl;
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
enum htc_endpoint_id epid;
|
enum htc_endpoint_id epid;
|
||||||
u16 qnum;
|
u16 qnum;
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
u8 *tx_fhdr;
|
u8 *tx_fhdr;
|
||||||
u8 sta_idx, vif_idx;
|
u8 sta_idx, vif_idx;
|
||||||
|
|
||||||
|
tx_ctl = HTC_SKB_CB(skb);
|
||||||
|
memset(tx_ctl, 0, sizeof(*tx_ctl));
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
fc = hdr->frame_control;
|
fc = hdr->frame_control;
|
||||||
|
|
||||||
|
@ -126,8 +129,6 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
|
||||||
sta_idx = priv->vif_sta_pos[vif_idx];
|
sta_idx = priv->vif_sta_pos[vif_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
|
|
||||||
|
|
||||||
if (ieee80211_is_data(fc)) {
|
if (ieee80211_is_data(fc)) {
|
||||||
struct tx_frame_hdr tx_hdr;
|
struct tx_frame_hdr tx_hdr;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
@ -139,10 +140,10 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
|
||||||
tx_hdr.vif_idx = vif_idx;
|
tx_hdr.vif_idx = vif_idx;
|
||||||
|
|
||||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
|
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||||
tx_ctl.type = ATH9K_HTC_AMPDU;
|
tx_ctl->type = ATH9K_HTC_AMPDU;
|
||||||
tx_hdr.data_type = ATH9K_HTC_AMPDU;
|
tx_hdr.data_type = ATH9K_HTC_AMPDU;
|
||||||
} else {
|
} else {
|
||||||
tx_ctl.type = ATH9K_HTC_NORMAL;
|
tx_ctl->type = ATH9K_HTC_NORMAL;
|
||||||
tx_hdr.data_type = ATH9K_HTC_NORMAL;
|
tx_hdr.data_type = ATH9K_HTC_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +213,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
|
||||||
mgmt->u.probe_resp.timestamp = avp->tsfadjust;
|
mgmt->u.probe_resp.timestamp = avp->tsfadjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_ctl.type = ATH9K_HTC_NORMAL;
|
tx_ctl->type = ATH9K_HTC_MGMT;
|
||||||
|
|
||||||
mgmt_hdr.node_idx = sta_idx;
|
mgmt_hdr.node_idx = sta_idx;
|
||||||
mgmt_hdr.vif_idx = vif_idx;
|
mgmt_hdr.vif_idx = vif_idx;
|
||||||
|
@ -230,7 +231,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
|
||||||
epid = priv->mgmt_ep;
|
epid = priv->mgmt_ep;
|
||||||
}
|
}
|
||||||
send:
|
send:
|
||||||
return htc_send(priv->htc, skb, epid, &tx_ctl);
|
return htc_send(priv->htc, skb, epid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
|
static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "htc.h"
|
#include "htc.h"
|
||||||
|
|
||||||
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
||||||
u16 len, u8 flags, u8 epid,
|
u16 len, u8 flags, u8 epid)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
struct htc_frame_hdr *hdr;
|
struct htc_frame_hdr *hdr;
|
||||||
struct htc_endpoint *endpoint = &target->endpoint[epid];
|
struct htc_endpoint *endpoint = &target->endpoint[epid];
|
||||||
|
@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
||||||
hdr->flags = flags;
|
hdr->flags = flags;
|
||||||
hdr->payload_len = cpu_to_be16(len);
|
hdr->payload_len = cpu_to_be16(len);
|
||||||
|
|
||||||
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
|
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
|
||||||
tx_ctl);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
|
||||||
|
|
||||||
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
|
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
|
||||||
|
|
||||||
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
|
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target)
|
||||||
|
|
||||||
target->htc_flags |= HTC_OP_START_WAIT;
|
target->htc_flags |= HTC_OP_START_WAIT;
|
||||||
|
|
||||||
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
|
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target,
|
||||||
conn_msg->dl_pipeid = endpoint->dl_pipeid;
|
conn_msg->dl_pipeid = endpoint->dl_pipeid;
|
||||||
conn_msg->ul_pipeid = endpoint->ul_pipeid;
|
conn_msg->ul_pipeid = endpoint->ul_pipeid;
|
||||||
|
|
||||||
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
|
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -287,9 +287,9 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
||||||
enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
|
enum htc_endpoint_id epid)
|
||||||
{
|
{
|
||||||
return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl);
|
return htc_issue_send(target, skb, skb->len, 0, epid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void htc_stop(struct htc_target *target)
|
void htc_stop(struct htc_target *target)
|
||||||
|
|
|
@ -35,8 +35,7 @@ struct ath9k_htc_hif {
|
||||||
|
|
||||||
void (*start) (void *hif_handle, u8 pipe);
|
void (*start) (void *hif_handle, u8 pipe);
|
||||||
void (*stop) (void *hif_handle, u8 pipe);
|
void (*stop) (void *hif_handle, u8 pipe);
|
||||||
int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf,
|
int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf);
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum htc_endpoint_id {
|
enum htc_endpoint_id {
|
||||||
|
@ -206,7 +205,7 @@ int htc_connect_service(struct htc_target *target,
|
||||||
struct htc_service_connreq *service_connreq,
|
struct htc_service_connreq *service_connreq,
|
||||||
enum htc_endpoint_id *conn_rsp_eid);
|
enum htc_endpoint_id *conn_rsp_eid);
|
||||||
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
||||||
enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl);
|
enum htc_endpoint_id eid);
|
||||||
void htc_stop(struct htc_target *target);
|
void htc_stop(struct htc_target *target);
|
||||||
void htc_start(struct htc_target *target);
|
void htc_start(struct htc_target *target);
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
|
||||||
hdr->command_id = cpu_to_be16(cmd);
|
hdr->command_id = cpu_to_be16(cmd);
|
||||||
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
|
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
|
||||||
|
|
||||||
return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL);
|
return htc_send(wmi->htc, skb, wmi->ctrl_epid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||||
|
|
Reference in New Issue