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@xxxxxxxxx> --- drivers/staging/vt6656/device.h | 1 + drivers/staging/vt6656/main_usb.c | 1 + drivers/staging/vt6656/rxtx.c | 91 ++++++++++++++++++------------- drivers/staging/vt6656/rxtx.h | 8 ++- drivers/staging/vt6656/usbpipe.c | 2 +- 5 files changed, 61 insertions(+), 42 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index d19d802b5d4f..074b98dfac91 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -240,6 +240,7 @@ struct vnt_usb_send_context { struct sk_buff *skb; struct urb *urb; struct ieee80211_hdr *hdr; + void *tx_buffer; unsigned int buf_len; u32 frame_len; u16 tx_hdr_size; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b5790d4d7152..930ee424ecdf 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1053,6 +1053,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) ieee80211_hw_set(priv->hw, SUPPORTS_PS); ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK); + priv->hw->extra_tx_headroom = sizeof(struct vnt_tx_buffer); priv->hw->max_signal = 100; SET_IEEE80211_DEV(priv->hw, &intf->dev); 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); diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index 3c36a4b893dc..819b45394673 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -77,14 +77,12 @@ struct vnt_tx_datahead_g { __le16 duration_a; __le16 time_stamp_off_b; __le16 time_stamp_off_a; - struct ieee80211_hdr hdr; } __packed; struct vnt_tx_datahead_ab { struct vnt_phy_field ab; __le16 duration; __le16 time_stamp_off; - struct ieee80211_hdr hdr; } __packed; /* RTS buffer header */ @@ -161,10 +159,14 @@ struct vnt_tx_fifo_head { __le16 current_rate; } __packed; -struct vnt_tx_buffer { +struct vnt_tx_usb_header { u8 type; u8 pkt_no; __le16 tx_byte_count; +} __packed; + +struct vnt_tx_buffer { + struct vnt_tx_usb_header usb; struct vnt_tx_fifo_head fifo_head; union vnt_tx_head tx_head; } __packed; diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 06dedf291db2..904645fa0eb0 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -466,7 +466,7 @@ int vnt_tx_context(struct vnt_private *priv, usb_fill_bulk_urb(urb, priv->usb, usb_sndbulkpipe(priv->usb, 3), - context->data, + context->tx_buffer, context->buf_len, vnt_tx_context_complete, context); -- 2.25.1