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 <tvbox...@gmail.com>
---
 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
_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to