diff options
author | Malcolm Priestley <tvboxspy@gmail.com> | 2020-05-16 11:35:22 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-19 16:17:18 +0200 |
commit | abfd23743d479137ad9912597ca13383f73f01f8 (patch) | |
tree | ebbfdc031634c4a675f777bdce96ede54d1f47c9 /drivers/staging/vt6656/rxtx.c | |
parent | 16438cf707c924a675afba15d05a19ac2843e7d2 (diff) |
staging: vt6656: Use sk_buff buffer for tx header
mac80211 can provide space for the driver to put a tx header on
the skb buffer instead coping the entire frame on to a local
buffer with the header.
To use this extra_tx_headroom must be set in mac80211 with the largest
possible header which is struct vnt_tx_buffer.
The driver has 8 possible combinations of tx header size which
are found in vnt_get_hdr_size replacing vnt_mac_hdr_pos.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
Link: https://lore.kernel.org/r/7b967bfc-1d4b-4b45-efab-d54f16cca226@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/vt6656/rxtx.c')
-rw-r--r-- | drivers/staging/vt6656/rxtx.c | 91 |
1 files changed, 53 insertions, 38 deletions
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 8348ffe6ebfa..792833f8192a 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -188,19 +188,6 @@ static __le16 vnt_get_cts_duration(struct vnt_usb_send_context *context) context->frame_len, info); } -static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context, - struct ieee80211_hdr *hdr) -{ - u8 *head = tx_context->data + offsetof(struct vnt_tx_buffer, fifo_head); - u8 *hdr_pos = (u8 *)hdr; - - tx_context->hdr = hdr; - if (!tx_context->hdr) - return 0; - - return (u16)(hdr_pos - head); -} - static void vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, struct vnt_tx_datahead_g *buf) { @@ -221,8 +208,6 @@ static void vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, priv->top_cck_basic_rate); - - tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); } static void vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, @@ -241,8 +226,6 @@ static void vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, /* Get Duration and TimeStampOff */ buf->duration = hdr->duration_id; buf->time_stamp_off = vnt_time_stamp_off(priv, rate); - - tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); } static void vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context, @@ -479,6 +462,39 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context, } } +static u16 vnt_get_hdr_size(struct ieee80211_tx_info *info) +{ + u16 size = sizeof(struct vnt_tx_datahead_ab); + + if (info->control.use_cts_prot) { + if (info->control.use_rts) + size = sizeof(struct vnt_rts_g); + else + size = sizeof(struct vnt_cts); + } else if (info->control.use_rts) { + size = sizeof(struct vnt_rts_ab); + } + + if (info->control.hw_key) { + if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP) + size += sizeof(struct vnt_mic_hdr); + } + + /* Get rrv_time header */ + if (info->control.use_cts_prot) { + if (info->control.use_rts) + size += sizeof(struct vnt_rrv_time_rts); + else + size += sizeof(struct vnt_rrv_time_cts); + } else { + size += sizeof(struct vnt_rrv_time_ab); + } + + size += sizeof(struct vnt_tx_fifo_head); + + return size; +} + int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -531,12 +547,29 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) tx_context->need_ack = false; tx_context->frame_len = skb->len + 4; tx_context->tx_rate = rate->hw_value; + tx_context->hdr = hdr; spin_unlock_irqrestore(&priv->lock, flags); - tx_buffer = (struct vnt_tx_buffer *)tx_context->data; - tx_buffer_head = &tx_buffer->fifo_head; + tx_header_size = vnt_get_hdr_size(info); tx_body_size = skb->len; + tx_bytes = tx_header_size + tx_body_size; + tx_header_size += sizeof(struct vnt_tx_usb_header); + + tx_buffer = skb_push(skb, tx_header_size); + tx_buffer_head = &tx_buffer->fifo_head; + + /* Fill USB header */ + tx_buffer->usb.tx_byte_count = cpu_to_le16(tx_bytes); + tx_buffer->usb.pkt_no = tx_context->pkt_no; + tx_buffer->usb.type = 0x00; + + tx_context->type = CONTEXT_DATA_PACKET; + tx_context->tx_buffer = tx_buffer; + tx_context->buf_len = skb->len; + + /* Return skb->data to mac80211 header */ + skb_pull(skb, tx_header_size); /*Set fifo controls */ if (pkt_type == PK_TYPE_11A) @@ -603,18 +636,8 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) vnt_generate_tx_parameter(tx_context, tx_buffer, &mic_hdr, need_mic, need_rts); - tx_header_size = tx_context->tx_hdr_size; - if (!tx_header_size) { - tx_context->in_use = false; - return -ENOMEM; - } - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); - tx_bytes = tx_header_size + tx_body_size; - - memcpy(tx_context->hdr, skb->data, tx_body_size); - if (info->control.hw_key) { tx_key = info->control.hw_key; if (tx_key->keylen > 0) @@ -625,15 +648,6 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - tx_buffer->tx_byte_count = cpu_to_le16(tx_bytes); - tx_buffer->pkt_no = tx_context->pkt_no; - tx_buffer->type = 0x00; - - tx_bytes += 4; - - tx_context->type = CONTEXT_DATA_PACKET; - tx_context->buf_len = tx_bytes; - spin_lock_irqsave(&priv->lock, flags); if (vnt_tx_context(priv, tx_context)) { @@ -725,6 +739,7 @@ static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb) beacon_buffer->type = 0x01; context->type = CONTEXT_BEACON_PACKET; + context->tx_buffer = &context->data; context->buf_len = count + 4; /* USB header */ spin_lock_irqsave(&priv->lock, flags); |