aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c182
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c20
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dump.h121
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
7 files changed, 337 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 31e48c25a692..ba874cff8648 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -623,7 +623,7 @@ struct rt2x00_dev {
623 * required for deregistration of debugfs. 623 * required for deregistration of debugfs.
624 */ 624 */
625#ifdef CONFIG_RT2X00_LIB_DEBUGFS 625#ifdef CONFIG_RT2X00_LIB_DEBUGFS
626 const struct rt2x00debug_intf *debugfs_intf; 626 struct rt2x00debug_intf *debugfs_intf;
627#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 627#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
628 628
629 /* 629 /*
@@ -791,6 +791,12 @@ struct rt2x00_dev {
791 ring_loop(__entry, (__dev)->tx, ring_end(__dev)) 791 ring_loop(__entry, (__dev)->tx, ring_end(__dev))
792 792
793/* 793/*
794 * Compute an array index from a pointer to an element and the base pointer.
795 */
796#define ARRAY_INDEX(__elem, __base) \
797 ( ((char *)(__elem) - (char *)(__base)) / sizeof(*(__elem)) )
798
799/*
794 * Generic RF access. 800 * Generic RF access.
795 * The RF is being accessed by word index. 801 * The RF is being accessed by word index.
796 */ 802 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 3aa7e0ab513b..e72c98133c05 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -26,10 +26,12 @@
26#include <linux/debugfs.h> 26#include <linux/debugfs.h>
27#include <linux/kernel.h> 27#include <linux/kernel.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/poll.h>
29#include <linux/uaccess.h> 30#include <linux/uaccess.h>
30 31
31#include "rt2x00.h" 32#include "rt2x00.h"
32#include "rt2x00lib.h" 33#include "rt2x00lib.h"
34#include "rt2x00dump.h"
33 35
34#define PRINT_LINE_LEN_MAX 32 36#define PRINT_LINE_LEN_MAX 32
35 37
@@ -58,6 +60,8 @@ struct rt2x00debug_intf {
58 * - eeprom offset/value files 60 * - eeprom offset/value files
59 * - bbp offset/value files 61 * - bbp offset/value files
60 * - rf offset/value files 62 * - rf offset/value files
63 * - frame dump folder
64 * - frame dump file
61 */ 65 */
62 struct dentry *driver_folder; 66 struct dentry *driver_folder;
63 struct dentry *driver_entry; 67 struct dentry *driver_entry;
@@ -72,6 +76,24 @@ struct rt2x00debug_intf {
72 struct dentry *bbp_val_entry; 76 struct dentry *bbp_val_entry;
73 struct dentry *rf_off_entry; 77 struct dentry *rf_off_entry;
74 struct dentry *rf_val_entry; 78 struct dentry *rf_val_entry;
79 struct dentry *frame_folder;
80 struct dentry *frame_dump_entry;
81
82 /*
83 * The frame dump file only allows a single reader,
84 * so we need to store the current state here.
85 */
86 unsigned long frame_dump_flags;
87#define FRAME_DUMP_FILE_OPEN 1
88
89 /*
90 * We queue each frame before dumping it to the user,
91 * per read command we will pass a single skb structure
92 * so we should be prepared to queue multiple sk buffers
93 * before sending it to userspace.
94 */
95 struct sk_buff_head frame_dump_skbqueue;
96 wait_queue_head_t frame_dump_waitqueue;
75 97
76 /* 98 /*
77 * Driver and chipset files will use a data buffer 99 * Driver and chipset files will use a data buffer
@@ -90,6 +112,63 @@ struct rt2x00debug_intf {
90 unsigned int offset_rf; 112 unsigned int offset_rf;
91}; 113};
92 114
115void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
116 struct sk_buff *skb)
117{
118 struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
119 struct skb_desc *desc = get_skb_desc(skb);
120 struct sk_buff *skbcopy;
121 struct rt2x00dump_hdr *dump_hdr;
122 struct timeval timestamp;
123 unsigned int ring_index;
124 unsigned int entry_index;
125
126 do_gettimeofday(&timestamp);
127 ring_index = ARRAY_INDEX(desc->ring, rt2x00dev->rx);
128 entry_index = ARRAY_INDEX(desc->entry, desc->ring->entry);
129
130 if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
131 return;
132
133 if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
134 DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
135 return;
136 }
137
138 skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
139 GFP_ATOMIC);
140 if (!skbcopy) {
141 DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
142 return;
143 }
144
145 dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
146 dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
147 dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
148 dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
149 dump_hdr->data_length = cpu_to_le32(desc->data_len);
150 dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
151 dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
152 dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
153 dump_hdr->type = cpu_to_le16(desc->frame_type);
154 dump_hdr->ring_index = ring_index;
155 dump_hdr->entry_index = entry_index;
156 dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
157 dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
158
159 memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
160 memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
161
162 skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
163 wake_up_interruptible(&intf->frame_dump_waitqueue);
164
165 /*
166 * Verify that the file has not been closed while we were working.
167 */
168 if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
169 skb_queue_purge(&intf->frame_dump_skbqueue);
170}
171
93static int rt2x00debug_file_open(struct inode *inode, struct file *file) 172static int rt2x00debug_file_open(struct inode *inode, struct file *file)
94{ 173{
95 struct rt2x00debug_intf *intf = inode->i_private; 174 struct rt2x00debug_intf *intf = inode->i_private;
@@ -111,6 +190,89 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
111 return 0; 190 return 0;
112} 191}
113 192
193static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
194{
195 struct rt2x00debug_intf *intf = inode->i_private;
196 int retval;
197
198 retval = rt2x00debug_file_open(inode, file);
199 if (retval)
200 return retval;
201
202 if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
203 rt2x00debug_file_release(inode, file);
204 return -EBUSY;
205 }
206
207 return 0;
208}
209
210static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
211{
212 struct rt2x00debug_intf *intf = inode->i_private;
213
214 skb_queue_purge(&intf->frame_dump_skbqueue);
215
216 clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
217
218 return rt2x00debug_file_release(inode, file);
219}
220
221static ssize_t rt2x00debug_read_ring_dump(struct file *file,
222 char __user *buf,
223 size_t length,
224 loff_t *offset)
225{
226 struct rt2x00debug_intf *intf = file->private_data;
227 struct sk_buff *skb;
228 size_t status;
229 int retval;
230
231 if (file->f_flags & O_NONBLOCK)
232 return -EAGAIN;
233
234 retval =
235 wait_event_interruptible(intf->frame_dump_waitqueue,
236 (skb =
237 skb_dequeue(&intf->frame_dump_skbqueue)));
238 if (retval)
239 return retval;
240
241 status = min((size_t)skb->len, length);
242 if (copy_to_user(buf, skb->data, status)) {
243 status = -EFAULT;
244 goto exit;
245 }
246
247 *offset += status;
248
249exit:
250 kfree_skb(skb);
251
252 return status;
253}
254
255static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
256 poll_table *wait)
257{
258 struct rt2x00debug_intf *intf = file->private_data;
259
260 poll_wait(file, &intf->frame_dump_waitqueue, wait);
261
262 if (!skb_queue_empty(&intf->frame_dump_skbqueue))
263 return POLLOUT | POLLWRNORM;
264
265 return 0;
266}
267
268static const struct file_operations rt2x00debug_fop_ring_dump = {
269 .owner = THIS_MODULE,
270 .read = rt2x00debug_read_ring_dump,
271 .poll = rt2x00debug_poll_ring_dump,
272 .open = rt2x00debug_open_ring_dump,
273 .release = rt2x00debug_release_ring_dump,
274};
275
114#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ 276#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
115static ssize_t rt2x00debug_read_##__name(struct file *file, \ 277static ssize_t rt2x00debug_read_##__name(struct file *file, \
116 char __user *buf, \ 278 char __user *buf, \
@@ -339,6 +501,20 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
339 501
340#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY 502#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
341 503
504 intf->frame_folder =
505 debugfs_create_dir("frame", intf->driver_folder);
506 if (IS_ERR(intf->frame_folder))
507 goto exit;
508
509 intf->frame_dump_entry =
510 debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
511 intf, &rt2x00debug_fop_ring_dump);
512 if (IS_ERR(intf->frame_dump_entry))
513 goto exit;
514
515 skb_queue_head_init(&intf->frame_dump_skbqueue);
516 init_waitqueue_head(&intf->frame_dump_waitqueue);
517
342 return; 518 return;
343 519
344exit: 520exit:
@@ -350,11 +526,15 @@ exit:
350 526
351void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) 527void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
352{ 528{
353 const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; 529 struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
354 530
355 if (unlikely(!intf)) 531 if (unlikely(!intf))
356 return; 532 return;
357 533
534 skb_queue_purge(&intf->frame_dump_skbqueue);
535
536 debugfs_remove(intf->frame_dump_entry);
537 debugfs_remove(intf->frame_folder);
358 debugfs_remove(intf->rf_val_entry); 538 debugfs_remove(intf->rf_val_entry);
359 debugfs_remove(intf->rf_off_entry); 539 debugfs_remove(intf->rf_off_entry);
360 debugfs_remove(intf->bbp_val_entry); 540 debugfs_remove(intf->bbp_val_entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 4f32ee8f4cb7..48e251561f83 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -28,6 +28,7 @@
28 28
29#include "rt2x00.h" 29#include "rt2x00.h"
30#include "rt2x00lib.h" 30#include "rt2x00lib.h"
31#include "rt2x00dump.h"
31 32
32/* 33/*
33 * Ring handler. 34 * Ring handler.
@@ -511,9 +512,11 @@ void rt2x00lib_txdone(struct data_entry *entry,
511 } 512 }
512 513
513 /* 514 /*
514 * Send the tx_status to mac80211, 515 * Send the tx_status to mac80211 & debugfs.
515 * that method also cleans up the skb structure. 516 * mac80211 will clean up the skb structure.
516 */ 517 */
518 get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
519 rt2x00debug_dump_frame(rt2x00dev, entry->skb);
517 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); 520 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
518 entry->skb = NULL; 521 entry->skb = NULL;
519} 522}
@@ -563,8 +566,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
563 rx_status->antenna = rt2x00dev->link.ant.active.rx; 566 rx_status->antenna = rt2x00dev->link.ant.active.rx;
564 567
565 /* 568 /*
566 * Send frame to mac80211 569 * Send frame to mac80211 & debugfs
567 */ 570 */
571 get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
572 rt2x00debug_dump_frame(rt2x00dev, skb);
568 ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status); 573 ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
569} 574}
570EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); 575EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -715,6 +720,15 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
715 */ 720 */
716 skbdesc->entry->skb = skb; 721 skbdesc->entry->skb = skb;
717 memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control)); 722 memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
723
724 /*
725 * The frame has been completely initialized and ready
726 * for sending to the device. The caller will push the
727 * frame to the device, but we are going to push the
728 * frame to debugfs here.
729 */
730 skbdesc->frame_type = DUMP_FRAME_TX;
731 rt2x00debug_dump_frame(rt2x00dev, skb);
718} 732}
719EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); 733EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
720 734
diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h
new file mode 100644
index 000000000000..99f3f367adce
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00dump.h
@@ -0,0 +1,121 @@
1/*
2 Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: rt2x00dump
23 Abstract: Data structures for the rt2x00debug & userspace.
24 */
25
26#ifndef RT2X00DUMP_H
27#define RT2X00DUMP_H
28
29/**
30 * DOC: Introduction
31 *
32 * This header is intended to be exported to userspace,
33 * to make the structures and enumerations available to userspace
34 * applications. This means that all data types should be exportable.
35 *
36 * When rt2x00 is compiled with debugfs support enabled,
37 * it is possible to capture all data coming in and out of the device
38 * by reading the frame dump file. This file can have only a single reader.
39 * The following frames will be reported:
40 * - All incoming frames (rx)
41 * - All outgoing frames (tx, including beacon and atim)
42 * - All completed frames (txdone including atim)
43 *
44 * The data is send to the file using the following format:
45 *
46 * [rt2x00dump header][hardware descriptor][ieee802.11 frame]
47 *
48 * rt2x00dump header: The description of the dumped frame, as well as
49 * additional information usefull for debugging. See &rt2x00dump_hdr.
50 * hardware descriptor: Descriptor that was used to receive or transmit
51 * the frame.
52 * ieee802.11 frame: The actual frame that was received or transmitted.
53 */
54
55/**
56 * enum rt2x00_dump_type - Frame type
57 *
58 * These values are used for the @type member of &rt2x00dump_hdr.
59 * @DUMP_FRAME_RXDONE: This frame has been received by the hardware.
60 * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware.
61 * @DUMP_FRAME_TXDONE: This frame indicates the device has handled
62 * the tx event which has either succeeded or failed. A frame
63 * with this type should also have been reported with as a
64 * %DUMP_FRAME_TX frame.
65 */
66enum rt2x00_dump_type {
67 DUMP_FRAME_RXDONE = 1,
68 DUMP_FRAME_TX = 2,
69 DUMP_FRAME_TXDONE = 3,
70};
71
72/**
73 * struct rt2x00dump_hdr - Dump frame header
74 *
75 * Each frame dumped to the debugfs file starts with this header
76 * attached. This header contains the description of the actual
77 * frame which was dumped.
78 *
79 * New fields inside the structure must be appended to the end of
80 * the structure. This way userspace tools compiled for earlier
81 * header versions can still correctly handle the frame dump
82 * (although they will not handle all data passed to them in the dump).
83 *
84 * @version: Header version should always be set to %DUMP_HEADER_VERSION.
85 * This field must be checked by userspace to determine if it can
86 * handle this frame.
87 * @header_length: The length of the &rt2x00dump_hdr structure. This is
88 * used for compatibility reasons so userspace can easily determine
89 * the location of the next field in the dump.
90 * @desc_length: The length of the device descriptor.
91 * @data_length: The length of the frame data (including the ieee802.11 header.
92 * @chip_rt: RT chipset
93 * @chip_rf: RF chipset
94 * @chip_rev: Chipset revision
95 * @type: The frame type (&rt2x00_dump_type)
96 * @ring_index: The index number of the data ring.
97 * @entry_index: The index number of the entry inside the data ring.
98 * @timestamp_sec: Timestamp - seconds
99 * @timestamp_usec: Timestamp - microseconds
100 */
101struct rt2x00dump_hdr {
102 __le32 version;
103#define DUMP_HEADER_VERSION 2
104
105 __le32 header_length;
106 __le32 desc_length;
107 __le32 data_length;
108
109 __le16 chip_rt;
110 __le16 chip_rf;
111 __le32 chip_rev;
112
113 __le16 type;
114 __u8 ring_index;
115 __u8 entry_index;
116
117 __le32 timestamp_sec;
118 __le32 timestamp_usec;
119};
120
121#endif /* RT2X00DUMP_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 73194112f45c..0bf10ffec70a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -80,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
80#ifdef CONFIG_RT2X00_LIB_DEBUGFS 80#ifdef CONFIG_RT2X00_LIB_DEBUGFS
81void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); 81void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
82void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); 82void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
83void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
83#else 84#else
84static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) 85static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
85{ 86{
@@ -88,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
88static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) 89static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
89{ 90{
90} 91}
92
93static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
94 struct skb_buff *skb)
95{
96}
91#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 97#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
92 98
93/* 99/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index c1d7c10e58fe..483380819f9d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -178,8 +178,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
178 * Fill in skb descriptor 178 * Fill in skb descriptor
179 */ 179 */
180 skbdesc = get_skb_desc(skb); 180 skbdesc = get_skb_desc(skb);
181 skbdesc->desc_len = desc.size; 181 skbdesc->desc_len = entry->ring->desc_size;
182 skbdesc->data_len = entry->ring->desc_size; 182 skbdesc->data_len = skb->len;
183 skbdesc->desc = entry->priv; 183 skbdesc->desc = entry->priv;
184 skbdesc->data = skb->data; 184 skbdesc->data = skb->data;
185 skbdesc->ring = ring; 185 skbdesc->ring = ring;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index fd6b61c97619..9778fae313ab 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -307,9 +307,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
307 * Fill in skb descriptor 307 * Fill in skb descriptor
308 */ 308 */
309 skbdesc = get_skb_desc(entry->skb); 309 skbdesc = get_skb_desc(entry->skb);
310 skbdesc->desc_len = desc.size; 310 skbdesc->desc_len = entry->ring->desc_size;
311 skbdesc->data_len = entry->ring->desc_size; 311 skbdesc->data_len = entry->skb->len;
312 skbdesc->desc = entry->skb->data + desc.size; 312 skbdesc->desc = entry->skb->data - skbdesc->desc_len;
313 skbdesc->data = entry->skb->data; 313 skbdesc->data = entry->skb->data;
314 skbdesc->ring = ring; 314 skbdesc->ring = ring;
315 skbdesc->entry = entry; 315 skbdesc->entry = entry;