xref: /linux/drivers/net/wireless/intel/ipw2x00/libipw_tx.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1c891f3b9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2367a1092SKalle Valo /******************************************************************************
3367a1092SKalle Valo 
4367a1092SKalle Valo   Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
5367a1092SKalle Valo 
6367a1092SKalle Valo 
7367a1092SKalle Valo   Contact Information:
8367a1092SKalle Valo   Intel Linux Wireless <ilw@linux.intel.com>
9367a1092SKalle Valo   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
10367a1092SKalle Valo 
11367a1092SKalle Valo ******************************************************************************/
12367a1092SKalle Valo #include <linux/compiler.h>
13367a1092SKalle Valo #include <linux/errno.h>
14367a1092SKalle Valo #include <linux/if_arp.h>
15367a1092SKalle Valo #include <linux/in6.h>
16367a1092SKalle Valo #include <linux/in.h>
17367a1092SKalle Valo #include <linux/ip.h>
18367a1092SKalle Valo #include <linux/kernel.h>
19367a1092SKalle Valo #include <linux/module.h>
20367a1092SKalle Valo #include <linux/netdevice.h>
21367a1092SKalle Valo #include <linux/proc_fs.h>
22367a1092SKalle Valo #include <linux/skbuff.h>
23367a1092SKalle Valo #include <linux/slab.h>
24367a1092SKalle Valo #include <linux/tcp.h>
25367a1092SKalle Valo #include <linux/types.h>
26367a1092SKalle Valo #include <linux/wireless.h>
27367a1092SKalle Valo #include <linux/etherdevice.h>
287c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
29367a1092SKalle Valo 
30367a1092SKalle Valo #include "libipw.h"
31367a1092SKalle Valo 
32367a1092SKalle Valo /*
33367a1092SKalle Valo 
34367a1092SKalle Valo 802.11 Data Frame
35367a1092SKalle Valo 
36367a1092SKalle Valo       ,-------------------------------------------------------------------.
37367a1092SKalle Valo Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
38367a1092SKalle Valo       |------|------|---------|---------|---------|------|---------|------|
39367a1092SKalle Valo Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
40367a1092SKalle Valo       |      | tion | (BSSID) |         |         | ence |  data   |      |
41367a1092SKalle Valo       `--------------------------------------------------|         |------'
42367a1092SKalle Valo Total: 28 non-data bytes                                 `----.----'
43367a1092SKalle Valo 							      |
44367a1092SKalle Valo        .- 'Frame data' expands, if WEP enabled, to <----------'
45367a1092SKalle Valo        |
46367a1092SKalle Valo        V
47367a1092SKalle Valo       ,-----------------------.
48367a1092SKalle Valo Bytes |  4  |   0-2296  |  4  |
49367a1092SKalle Valo       |-----|-----------|-----|
50367a1092SKalle Valo Desc. | IV  | Encrypted | ICV |
51367a1092SKalle Valo       |     | Packet    |     |
52367a1092SKalle Valo       `-----|           |-----'
53367a1092SKalle Valo 	    `-----.-----'
54367a1092SKalle Valo 		  |
55367a1092SKalle Valo        .- 'Encrypted Packet' expands to
56367a1092SKalle Valo        |
57367a1092SKalle Valo        V
58367a1092SKalle Valo       ,---------------------------------------------------.
59367a1092SKalle Valo Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
60367a1092SKalle Valo       |------|------|---------|----------|------|---------|
61367a1092SKalle Valo Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
62367a1092SKalle Valo       | DSAP | SSAP |         |          |      | Packet  |
63367a1092SKalle Valo       | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
64367a1092SKalle Valo       `----------------------------------------------------
65367a1092SKalle Valo Total: 8 non-data bytes
66367a1092SKalle Valo 
67367a1092SKalle Valo 802.3 Ethernet Data Frame
68367a1092SKalle Valo 
69367a1092SKalle Valo       ,-----------------------------------------.
70367a1092SKalle Valo Bytes |   6   |   6   |  2   |  Variable |   4  |
71367a1092SKalle Valo       |-------|-------|------|-----------|------|
72367a1092SKalle Valo Desc. | Dest. | Source| Type | IP Packet |  fcs |
73367a1092SKalle Valo       |  MAC  |  MAC  |      |           |      |
74367a1092SKalle Valo       `-----------------------------------------'
75367a1092SKalle Valo Total: 18 non-data bytes
76367a1092SKalle Valo 
77367a1092SKalle Valo In the event that fragmentation is required, the incoming payload is split into
78367a1092SKalle Valo N parts of size ieee->fts.  The first fragment contains the SNAP header and the
79367a1092SKalle Valo remaining packets are just data.
80367a1092SKalle Valo 
81367a1092SKalle Valo If encryption is enabled, each fragment payload size is reduced by enough space
82367a1092SKalle Valo to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
83367a1092SKalle Valo So if you have 1500 bytes of payload with ieee->fts set to 500 without
84367a1092SKalle Valo encryption it will take 3 frames.  With WEP it will take 4 frames as the
85367a1092SKalle Valo payload of each frame is reduced to 492 bytes.
86367a1092SKalle Valo 
87367a1092SKalle Valo * SKB visualization
88367a1092SKalle Valo *
89367a1092SKalle Valo *  ,- skb->data
90367a1092SKalle Valo * |
91367a1092SKalle Valo * |    ETHERNET HEADER        ,-<-- PAYLOAD
92367a1092SKalle Valo * |                           |     14 bytes from skb->data
93367a1092SKalle Valo * |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
94367a1092SKalle Valo * |                       | | |
95367a1092SKalle Valo * |,-Dest.--. ,--Src.---. | | |
96367a1092SKalle Valo * |  6 bytes| | 6 bytes | | | |
97367a1092SKalle Valo * v         | |         | | | |
98367a1092SKalle Valo * 0         | v       1 | v | v           2
99367a1092SKalle Valo * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
100367a1092SKalle Valo *     ^     | ^         | ^ |
101367a1092SKalle Valo *     |     | |         | | |
102367a1092SKalle Valo *     |     | |         | `T' <---- 2 bytes for Type
103367a1092SKalle Valo *     |     | |         |
104367a1092SKalle Valo *     |     | '---SNAP--' <-------- 6 bytes for SNAP
105367a1092SKalle Valo *     |     |
106367a1092SKalle Valo *     `-IV--' <-------------------- 4 bytes for IV (WEP)
107367a1092SKalle Valo *
108367a1092SKalle Valo *      SNAP HEADER
109367a1092SKalle Valo *
110367a1092SKalle Valo */
111367a1092SKalle Valo 
112367a1092SKalle Valo static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
113367a1092SKalle Valo static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
114367a1092SKalle Valo 
libipw_copy_snap(u8 * data,__be16 h_proto)115367a1092SKalle Valo static int libipw_copy_snap(u8 * data, __be16 h_proto)
116367a1092SKalle Valo {
117367a1092SKalle Valo 	struct libipw_snap_hdr *snap;
118367a1092SKalle Valo 	u8 *oui;
119367a1092SKalle Valo 
120367a1092SKalle Valo 	snap = (struct libipw_snap_hdr *)data;
121367a1092SKalle Valo 	snap->dsap = 0xaa;
122367a1092SKalle Valo 	snap->ssap = 0xaa;
123367a1092SKalle Valo 	snap->ctrl = 0x03;
124367a1092SKalle Valo 
125367a1092SKalle Valo 	if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX))
126367a1092SKalle Valo 		oui = P802_1H_OUI;
127367a1092SKalle Valo 	else
128367a1092SKalle Valo 		oui = RFC1042_OUI;
129367a1092SKalle Valo 	snap->oui[0] = oui[0];
130367a1092SKalle Valo 	snap->oui[1] = oui[1];
131367a1092SKalle Valo 	snap->oui[2] = oui[2];
132367a1092SKalle Valo 
133367a1092SKalle Valo 	memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16));
134367a1092SKalle Valo 
135367a1092SKalle Valo 	return SNAP_SIZE + sizeof(u16);
136367a1092SKalle Valo }
137367a1092SKalle Valo 
libipw_encrypt_fragment(struct libipw_device * ieee,struct sk_buff * frag,int hdr_len)138367a1092SKalle Valo static int libipw_encrypt_fragment(struct libipw_device *ieee,
139367a1092SKalle Valo 					     struct sk_buff *frag, int hdr_len)
140367a1092SKalle Valo {
141367a1092SKalle Valo 	struct lib80211_crypt_data *crypt =
142367a1092SKalle Valo 		ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
143367a1092SKalle Valo 	int res;
144367a1092SKalle Valo 
145367a1092SKalle Valo 	if (crypt == NULL)
146367a1092SKalle Valo 		return -1;
147367a1092SKalle Valo 
148367a1092SKalle Valo 	/* To encrypt, frame format is:
149367a1092SKalle Valo 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
150367a1092SKalle Valo 	atomic_inc(&crypt->refcnt);
151367a1092SKalle Valo 	res = 0;
152367a1092SKalle Valo 	if (crypt->ops && crypt->ops->encrypt_mpdu)
153367a1092SKalle Valo 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
154367a1092SKalle Valo 
155367a1092SKalle Valo 	atomic_dec(&crypt->refcnt);
156367a1092SKalle Valo 	if (res < 0) {
157367a1092SKalle Valo 		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
158367a1092SKalle Valo 		       ieee->dev->name, frag->len);
159367a1092SKalle Valo 		ieee->ieee_stats.tx_discards++;
160367a1092SKalle Valo 		return -1;
161367a1092SKalle Valo 	}
162367a1092SKalle Valo 
163367a1092SKalle Valo 	return 0;
164367a1092SKalle Valo }
165367a1092SKalle Valo 
libipw_txb_free(struct libipw_txb * txb)166367a1092SKalle Valo void libipw_txb_free(struct libipw_txb *txb)
167367a1092SKalle Valo {
168367a1092SKalle Valo 	int i;
169367a1092SKalle Valo 	if (unlikely(!txb))
170367a1092SKalle Valo 		return;
171367a1092SKalle Valo 	for (i = 0; i < txb->nr_frags; i++)
172367a1092SKalle Valo 		if (txb->fragments[i])
173367a1092SKalle Valo 			dev_kfree_skb_any(txb->fragments[i]);
174367a1092SKalle Valo 	kfree(txb);
175367a1092SKalle Valo }
176367a1092SKalle Valo 
libipw_alloc_txb(int nr_frags,int txb_size,int headroom,gfp_t gfp_mask)177367a1092SKalle Valo static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size,
178367a1092SKalle Valo 						 int headroom, gfp_t gfp_mask)
179367a1092SKalle Valo {
180367a1092SKalle Valo 	struct libipw_txb *txb;
181367a1092SKalle Valo 	int i;
1826f78f4a4SLen Baker 
183*3588e643SChen Ni 	txb = kzalloc(struct_size(txb, fragments, nr_frags), gfp_mask);
184367a1092SKalle Valo 	if (!txb)
185367a1092SKalle Valo 		return NULL;
186367a1092SKalle Valo 
187367a1092SKalle Valo 	txb->nr_frags = nr_frags;
188367a1092SKalle Valo 	txb->frag_size = txb_size;
189367a1092SKalle Valo 
190367a1092SKalle Valo 	for (i = 0; i < nr_frags; i++) {
191367a1092SKalle Valo 		txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
192367a1092SKalle Valo 						    gfp_mask);
193367a1092SKalle Valo 		if (unlikely(!txb->fragments[i])) {
194367a1092SKalle Valo 			i--;
195367a1092SKalle Valo 			break;
196367a1092SKalle Valo 		}
197367a1092SKalle Valo 		skb_reserve(txb->fragments[i], headroom);
198367a1092SKalle Valo 	}
199367a1092SKalle Valo 	if (unlikely(i != nr_frags)) {
200367a1092SKalle Valo 		while (i >= 0)
201367a1092SKalle Valo 			dev_kfree_skb_any(txb->fragments[i--]);
202367a1092SKalle Valo 		kfree(txb);
203367a1092SKalle Valo 		return NULL;
204367a1092SKalle Valo 	}
205367a1092SKalle Valo 	return txb;
206367a1092SKalle Valo }
207367a1092SKalle Valo 
libipw_classify(struct sk_buff * skb)208367a1092SKalle Valo static int libipw_classify(struct sk_buff *skb)
209367a1092SKalle Valo {
210367a1092SKalle Valo 	struct ethhdr *eth;
211367a1092SKalle Valo 	struct iphdr *ip;
212367a1092SKalle Valo 
213367a1092SKalle Valo 	eth = (struct ethhdr *)skb->data;
214367a1092SKalle Valo 	if (eth->h_proto != htons(ETH_P_IP))
215367a1092SKalle Valo 		return 0;
216367a1092SKalle Valo 
217367a1092SKalle Valo 	ip = ip_hdr(skb);
218367a1092SKalle Valo 	switch (ip->tos & 0xfc) {
219367a1092SKalle Valo 	case 0x20:
220367a1092SKalle Valo 		return 2;
221367a1092SKalle Valo 	case 0x40:
222367a1092SKalle Valo 		return 1;
223367a1092SKalle Valo 	case 0x60:
224367a1092SKalle Valo 		return 3;
225367a1092SKalle Valo 	case 0x80:
226367a1092SKalle Valo 		return 4;
227367a1092SKalle Valo 	case 0xa0:
228367a1092SKalle Valo 		return 5;
229367a1092SKalle Valo 	case 0xc0:
230367a1092SKalle Valo 		return 6;
231367a1092SKalle Valo 	case 0xe0:
232367a1092SKalle Valo 		return 7;
233367a1092SKalle Valo 	default:
234367a1092SKalle Valo 		return 0;
235367a1092SKalle Valo 	}
236367a1092SKalle Valo }
237367a1092SKalle Valo 
238367a1092SKalle Valo /* Incoming skb is converted to a txb which consists of
239367a1092SKalle Valo  * a block of 802.11 fragment packets (stored as skbs) */
libipw_xmit(struct sk_buff * skb,struct net_device * dev)240367a1092SKalle Valo netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
241367a1092SKalle Valo {
242367a1092SKalle Valo 	struct libipw_device *ieee = netdev_priv(dev);
243367a1092SKalle Valo 	struct libipw_txb *txb = NULL;
244367a1092SKalle Valo 	struct libipw_hdr_3addrqos *frag_hdr;
245367a1092SKalle Valo 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
246367a1092SKalle Valo 	    rts_required;
247367a1092SKalle Valo 	unsigned long flags;
248367a1092SKalle Valo 	int encrypt, host_encrypt, host_encrypt_msdu;
249367a1092SKalle Valo 	__be16 ether_type;
250367a1092SKalle Valo 	int bytes, fc, hdr_len;
251367a1092SKalle Valo 	struct sk_buff *skb_frag;
252367a1092SKalle Valo 	struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */
253367a1092SKalle Valo 		.duration_id = 0,
254367a1092SKalle Valo 		.seq_ctl = 0,
255367a1092SKalle Valo 		.qos_ctl = 0
256367a1092SKalle Valo 	};
257367a1092SKalle Valo 	u8 dest[ETH_ALEN], src[ETH_ALEN];
258367a1092SKalle Valo 	struct lib80211_crypt_data *crypt;
259367a1092SKalle Valo 	int priority = skb->priority;
260367a1092SKalle Valo 	int snapped = 0;
261367a1092SKalle Valo 
262367a1092SKalle Valo 	if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
263367a1092SKalle Valo 		return NETDEV_TX_BUSY;
264367a1092SKalle Valo 
265367a1092SKalle Valo 	spin_lock_irqsave(&ieee->lock, flags);
266367a1092SKalle Valo 
267367a1092SKalle Valo 	/* If there is no driver handler to take the TXB, dont' bother
268367a1092SKalle Valo 	 * creating it... */
269367a1092SKalle Valo 	if (!ieee->hard_start_xmit) {
270367a1092SKalle Valo 		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
271367a1092SKalle Valo 		goto success;
272367a1092SKalle Valo 	}
273367a1092SKalle Valo 
274367a1092SKalle Valo 	if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
275367a1092SKalle Valo 		printk(KERN_WARNING "%s: skb too small (%d).\n",
276367a1092SKalle Valo 		       ieee->dev->name, skb->len);
277367a1092SKalle Valo 		goto success;
278367a1092SKalle Valo 	}
279367a1092SKalle Valo 
280367a1092SKalle Valo 	ether_type = ((struct ethhdr *)skb->data)->h_proto;
281367a1092SKalle Valo 
282367a1092SKalle Valo 	crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
283367a1092SKalle Valo 
284367a1092SKalle Valo 	encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
285367a1092SKalle Valo 	    ieee->sec.encrypt;
286367a1092SKalle Valo 
287367a1092SKalle Valo 	host_encrypt = ieee->host_encrypt && encrypt && crypt;
288367a1092SKalle Valo 	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
289367a1092SKalle Valo 
290367a1092SKalle Valo 	if (!encrypt && ieee->ieee802_1x &&
291367a1092SKalle Valo 	    ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {
292367a1092SKalle Valo 		dev->stats.tx_dropped++;
293367a1092SKalle Valo 		goto success;
294367a1092SKalle Valo 	}
295367a1092SKalle Valo 
296367a1092SKalle Valo 	/* Save source and destination addresses */
297367a1092SKalle Valo 	skb_copy_from_linear_data(skb, dest, ETH_ALEN);
298367a1092SKalle Valo 	skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);
299367a1092SKalle Valo 
300367a1092SKalle Valo 	if (host_encrypt)
301367a1092SKalle Valo 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
302367a1092SKalle Valo 		    IEEE80211_FCTL_PROTECTED;
303367a1092SKalle Valo 	else
304367a1092SKalle Valo 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
305367a1092SKalle Valo 
306367a1092SKalle Valo 	if (ieee->iw_mode == IW_MODE_INFRA) {
307367a1092SKalle Valo 		fc |= IEEE80211_FCTL_TODS;
308367a1092SKalle Valo 		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
309367a1092SKalle Valo 		memcpy(header.addr1, ieee->bssid, ETH_ALEN);
310367a1092SKalle Valo 		memcpy(header.addr2, src, ETH_ALEN);
311367a1092SKalle Valo 		memcpy(header.addr3, dest, ETH_ALEN);
312367a1092SKalle Valo 	} else if (ieee->iw_mode == IW_MODE_ADHOC) {
313367a1092SKalle Valo 		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
314367a1092SKalle Valo 		memcpy(header.addr1, dest, ETH_ALEN);
315367a1092SKalle Valo 		memcpy(header.addr2, src, ETH_ALEN);
316367a1092SKalle Valo 		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
317367a1092SKalle Valo 	}
318367a1092SKalle Valo 	hdr_len = LIBIPW_3ADDR_LEN;
319367a1092SKalle Valo 
320367a1092SKalle Valo 	if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
321367a1092SKalle Valo 		fc |= IEEE80211_STYPE_QOS_DATA;
322367a1092SKalle Valo 		hdr_len += 2;
323367a1092SKalle Valo 
324367a1092SKalle Valo 		skb->priority = libipw_classify(skb);
325367a1092SKalle Valo 		header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID);
326367a1092SKalle Valo 	}
327367a1092SKalle Valo 	header.frame_ctl = cpu_to_le16(fc);
328367a1092SKalle Valo 
329367a1092SKalle Valo 	/* Advance the SKB to the start of the payload */
330367a1092SKalle Valo 	skb_pull(skb, sizeof(struct ethhdr));
331367a1092SKalle Valo 
332367a1092SKalle Valo 	/* Determine total amount of storage required for TXB packets */
333367a1092SKalle Valo 	bytes = skb->len + SNAP_SIZE + sizeof(u16);
334367a1092SKalle Valo 
335367a1092SKalle Valo 	/* Encrypt msdu first on the whole data packet. */
336367a1092SKalle Valo 	if ((host_encrypt || host_encrypt_msdu) &&
337367a1092SKalle Valo 	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
338367a1092SKalle Valo 		int res = 0;
339367a1092SKalle Valo 		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
340367a1092SKalle Valo 		    crypt->ops->extra_msdu_postfix_len;
341367a1092SKalle Valo 		struct sk_buff *skb_new = dev_alloc_skb(len);
342367a1092SKalle Valo 
343367a1092SKalle Valo 		if (unlikely(!skb_new))
344367a1092SKalle Valo 			goto failed;
345367a1092SKalle Valo 
346367a1092SKalle Valo 		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
34759ae1d12SJohannes Berg 		skb_put_data(skb_new, &header, hdr_len);
348367a1092SKalle Valo 		snapped = 1;
349367a1092SKalle Valo 		libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
350367a1092SKalle Valo 				    ether_type);
351367a1092SKalle Valo 		skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);
352367a1092SKalle Valo 		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
353367a1092SKalle Valo 		if (res < 0) {
354367a1092SKalle Valo 			LIBIPW_ERROR("msdu encryption failed\n");
355367a1092SKalle Valo 			dev_kfree_skb_any(skb_new);
356367a1092SKalle Valo 			goto failed;
357367a1092SKalle Valo 		}
358367a1092SKalle Valo 		dev_kfree_skb_any(skb);
359367a1092SKalle Valo 		skb = skb_new;
360367a1092SKalle Valo 		bytes += crypt->ops->extra_msdu_prefix_len +
361367a1092SKalle Valo 		    crypt->ops->extra_msdu_postfix_len;
362367a1092SKalle Valo 		skb_pull(skb, hdr_len);
363367a1092SKalle Valo 	}
364367a1092SKalle Valo 
365367a1092SKalle Valo 	if (host_encrypt || ieee->host_open_frag) {
366367a1092SKalle Valo 		/* Determine fragmentation size based on destination (multicast
367367a1092SKalle Valo 		 * and broadcast are not fragmented) */
368367a1092SKalle Valo 		if (is_multicast_ether_addr(dest) ||
369367a1092SKalle Valo 		    is_broadcast_ether_addr(dest))
370367a1092SKalle Valo 			frag_size = MAX_FRAG_THRESHOLD;
371367a1092SKalle Valo 		else
372367a1092SKalle Valo 			frag_size = ieee->fts;
373367a1092SKalle Valo 
374367a1092SKalle Valo 		/* Determine amount of payload per fragment.  Regardless of if
375367a1092SKalle Valo 		 * this stack is providing the full 802.11 header, one will
376367a1092SKalle Valo 		 * eventually be affixed to this fragment -- so we must account
377367a1092SKalle Valo 		 * for it when determining the amount of payload space. */
378367a1092SKalle Valo 		bytes_per_frag = frag_size - hdr_len;
379367a1092SKalle Valo 		if (ieee->config &
380367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
381367a1092SKalle Valo 			bytes_per_frag -= LIBIPW_FCS_LEN;
382367a1092SKalle Valo 
383367a1092SKalle Valo 		/* Each fragment may need to have room for encryption
384367a1092SKalle Valo 		 * pre/postfix */
385e8366bbaSHaowen Bai 		if (host_encrypt && crypt && crypt->ops)
386367a1092SKalle Valo 			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
387367a1092SKalle Valo 			    crypt->ops->extra_mpdu_postfix_len;
388367a1092SKalle Valo 
389367a1092SKalle Valo 		/* Number of fragments is the total
390367a1092SKalle Valo 		 * bytes_per_frag / payload_per_fragment */
391367a1092SKalle Valo 		nr_frags = bytes / bytes_per_frag;
392367a1092SKalle Valo 		bytes_last_frag = bytes % bytes_per_frag;
393367a1092SKalle Valo 		if (bytes_last_frag)
394367a1092SKalle Valo 			nr_frags++;
395367a1092SKalle Valo 		else
396367a1092SKalle Valo 			bytes_last_frag = bytes_per_frag;
397367a1092SKalle Valo 	} else {
398367a1092SKalle Valo 		nr_frags = 1;
399367a1092SKalle Valo 		bytes_per_frag = bytes_last_frag = bytes;
400367a1092SKalle Valo 		frag_size = bytes + hdr_len;
401367a1092SKalle Valo 	}
402367a1092SKalle Valo 
403367a1092SKalle Valo 	rts_required = (frag_size > ieee->rts
404367a1092SKalle Valo 			&& ieee->config & CFG_LIBIPW_RTS);
405367a1092SKalle Valo 	if (rts_required)
406367a1092SKalle Valo 		nr_frags++;
407367a1092SKalle Valo 
408367a1092SKalle Valo 	/* When we allocate the TXB we allocate enough space for the reserve
409367a1092SKalle Valo 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
410367a1092SKalle Valo 	 * postfix, header, FCS, etc.) */
411367a1092SKalle Valo 	txb = libipw_alloc_txb(nr_frags, frag_size,
412367a1092SKalle Valo 				  ieee->tx_headroom, GFP_ATOMIC);
413367a1092SKalle Valo 	if (unlikely(!txb)) {
414367a1092SKalle Valo 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
415367a1092SKalle Valo 		       ieee->dev->name);
416367a1092SKalle Valo 		goto failed;
417367a1092SKalle Valo 	}
418367a1092SKalle Valo 	txb->encrypted = encrypt;
419367a1092SKalle Valo 	if (host_encrypt)
420367a1092SKalle Valo 		txb->payload_size = frag_size * (nr_frags - 1) +
421367a1092SKalle Valo 		    bytes_last_frag;
422367a1092SKalle Valo 	else
423367a1092SKalle Valo 		txb->payload_size = bytes;
424367a1092SKalle Valo 
425367a1092SKalle Valo 	if (rts_required) {
426367a1092SKalle Valo 		skb_frag = txb->fragments[0];
4274df864c1SJohannes Berg 		frag_hdr = skb_put(skb_frag, hdr_len);
428367a1092SKalle Valo 
429367a1092SKalle Valo 		/*
430367a1092SKalle Valo 		 * Set header frame_ctl to the RTS.
431367a1092SKalle Valo 		 */
432367a1092SKalle Valo 		header.frame_ctl =
433367a1092SKalle Valo 		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
434367a1092SKalle Valo 		memcpy(frag_hdr, &header, hdr_len);
435367a1092SKalle Valo 
436367a1092SKalle Valo 		/*
437367a1092SKalle Valo 		 * Restore header frame_ctl to the original data setting.
438367a1092SKalle Valo 		 */
439367a1092SKalle Valo 		header.frame_ctl = cpu_to_le16(fc);
440367a1092SKalle Valo 
441367a1092SKalle Valo 		if (ieee->config &
442367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
443367a1092SKalle Valo 			skb_put(skb_frag, 4);
444367a1092SKalle Valo 
445367a1092SKalle Valo 		txb->rts_included = 1;
446367a1092SKalle Valo 		i = 1;
447367a1092SKalle Valo 	} else
448367a1092SKalle Valo 		i = 0;
449367a1092SKalle Valo 
450367a1092SKalle Valo 	for (; i < nr_frags; i++) {
451367a1092SKalle Valo 		skb_frag = txb->fragments[i];
452367a1092SKalle Valo 
453367a1092SKalle Valo 		if (host_encrypt)
454367a1092SKalle Valo 			skb_reserve(skb_frag,
455367a1092SKalle Valo 				    crypt->ops->extra_mpdu_prefix_len);
456367a1092SKalle Valo 
45759ae1d12SJohannes Berg 		frag_hdr = skb_put_data(skb_frag, &header, hdr_len);
458367a1092SKalle Valo 
459367a1092SKalle Valo 		/* If this is not the last fragment, then add the MOREFRAGS
460367a1092SKalle Valo 		 * bit to the frame control */
461367a1092SKalle Valo 		if (i != nr_frags - 1) {
462367a1092SKalle Valo 			frag_hdr->frame_ctl =
463367a1092SKalle Valo 			    cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
464367a1092SKalle Valo 			bytes = bytes_per_frag;
465367a1092SKalle Valo 		} else {
466367a1092SKalle Valo 			/* The last fragment takes the remaining length */
467367a1092SKalle Valo 			bytes = bytes_last_frag;
468367a1092SKalle Valo 		}
469367a1092SKalle Valo 
470367a1092SKalle Valo 		if (i == 0 && !snapped) {
471367a1092SKalle Valo 			libipw_copy_snap(skb_put
472367a1092SKalle Valo 					    (skb_frag, SNAP_SIZE + sizeof(u16)),
473367a1092SKalle Valo 					    ether_type);
474367a1092SKalle Valo 			bytes -= SNAP_SIZE + sizeof(u16);
475367a1092SKalle Valo 		}
476367a1092SKalle Valo 
477367a1092SKalle Valo 		skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes);
478367a1092SKalle Valo 
479367a1092SKalle Valo 		/* Advance the SKB... */
480367a1092SKalle Valo 		skb_pull(skb, bytes);
481367a1092SKalle Valo 
482367a1092SKalle Valo 		/* Encryption routine will move the header forward in order
483367a1092SKalle Valo 		 * to insert the IV between the header and the payload */
484367a1092SKalle Valo 		if (host_encrypt)
485367a1092SKalle Valo 			libipw_encrypt_fragment(ieee, skb_frag, hdr_len);
486367a1092SKalle Valo 
487367a1092SKalle Valo 		if (ieee->config &
488367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
489367a1092SKalle Valo 			skb_put(skb_frag, 4);
490367a1092SKalle Valo 	}
491367a1092SKalle Valo 
492367a1092SKalle Valo       success:
493367a1092SKalle Valo 	spin_unlock_irqrestore(&ieee->lock, flags);
494367a1092SKalle Valo 
495367a1092SKalle Valo 	dev_kfree_skb_any(skb);
496367a1092SKalle Valo 
497367a1092SKalle Valo 	if (txb) {
498367a1092SKalle Valo 		netdev_tx_t ret = (*ieee->hard_start_xmit)(txb, dev, priority);
499367a1092SKalle Valo 		if (ret == NETDEV_TX_OK) {
500367a1092SKalle Valo 			dev->stats.tx_packets++;
501367a1092SKalle Valo 			dev->stats.tx_bytes += txb->payload_size;
502367a1092SKalle Valo 			return NETDEV_TX_OK;
503367a1092SKalle Valo 		}
504367a1092SKalle Valo 
505367a1092SKalle Valo 		libipw_txb_free(txb);
506367a1092SKalle Valo 	}
507367a1092SKalle Valo 
508367a1092SKalle Valo 	return NETDEV_TX_OK;
509367a1092SKalle Valo 
510367a1092SKalle Valo       failed:
511367a1092SKalle Valo 	spin_unlock_irqrestore(&ieee->lock, flags);
512367a1092SKalle Valo 	netif_stop_queue(dev);
513367a1092SKalle Valo 	dev->stats.tx_errors++;
514367a1092SKalle Valo 	return NETDEV_TX_BUSY;
515367a1092SKalle Valo }
516367a1092SKalle Valo EXPORT_SYMBOL(libipw_xmit);
517367a1092SKalle Valo 
518367a1092SKalle Valo EXPORT_SYMBOL(libipw_txb_free);
519