rx.c 10.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/**
  * This file contains the handling of RX in wlan driver.
  */
#include <linux/etherdevice.h>
#include <linux/types.h>

#include "hostcmd.h"
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
#include "wext.h"

struct eth803hdr {
	u8 dest_addr[6];
	u8 src_addr[6];
	u16 h803_len;
} __attribute__ ((packed));

struct rfc1042hdr {
	u8 llc_dsap;
	u8 llc_ssap;
	u8 llc_ctrl;
	u8 snap_oui[3];
	u16 snap_type;
} __attribute__ ((packed));

struct rxpackethdr {
	struct rxpd rx_pd;
	struct eth803hdr eth803_hdr;
	struct rfc1042hdr rfc1042_hdr;
} __attribute__ ((packed));

struct rx80211packethdr {
	struct rxpd rx_pd;
	void *eth80211_hdr;
} __attribute__ ((packed));

38 39
static int process_rxed_802_11_packet(struct lbs_private *priv,
	struct sk_buff *skb);
40 41 42 43

/**
 *  @brief This function computes the avgSNR .
 *
44
 *  @param priv    A pointer to struct lbs_private structure
45 46
 *  @return 	   avgSNR
 */
47
static u8 lbs_getavgsnr(struct lbs_private *priv)
48 49 50
{
	u8 i;
	u16 temp = 0;
51
	if (priv->numSNRNF == 0)
52
		return 0;
53 54 55
	for (i = 0; i < priv->numSNRNF; i++)
		temp += priv->rawSNR[i];
	return (u8) (temp / priv->numSNRNF);
56 57 58 59 60 61

}

/**
 *  @brief This function computes the AvgNF
 *
62
 *  @param priv    A pointer to struct lbs_private structure
63 64
 *  @return 	   AvgNF
 */
65
static u8 lbs_getavgnf(struct lbs_private *priv)
66 67 68
{
	u8 i;
	u16 temp = 0;
69
	if (priv->numSNRNF == 0)
70
		return 0;
71 72 73
	for (i = 0; i < priv->numSNRNF; i++)
		temp += priv->rawNF[i];
	return (u8) (temp / priv->numSNRNF);
74 75 76 77 78 79

}

/**
 *  @brief This function save the raw SNR/NF to our internel buffer
 *
80
 *  @param priv    A pointer to struct lbs_private structure
81 82 83
 *  @param prxpd   A pointer to rxpd structure of received packet
 *  @return 	   n/a
 */
84
static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
85
{
86 87 88 89 90 91 92
	if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
		priv->numSNRNF++;
	priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
	priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
	priv->nextSNRNF++;
	if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
		priv->nextSNRNF = 0;
93 94 95 96 97 98
	return;
}

/**
 *  @brief This function computes the RSSI in received packet.
 *
99
 *  @param priv    A pointer to struct lbs_private structure
100 101 102
 *  @param prxpd   A pointer to rxpd structure of received packet
 *  @return 	   n/a
 */
103
static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
104 105
{

106
	lbs_deb_enter(LBS_DEB_RX);
107

108 109
	lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
	lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
110 111
	       priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
	       priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
112

113 114
	priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
	priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
115
	lbs_save_rawSNRNF(priv, p_rx_pd);
116

117 118
	priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
	priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
119
	lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
120 121
	       priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
	       priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
122

123 124 125
	priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
	    CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
		     priv->NF[TYPE_RXPD][TYPE_NOAVG]);
126

127 128 129
	priv->RSSI[TYPE_RXPD][TYPE_AVG] =
	    CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
		     priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
130

131
	lbs_deb_leave(LBS_DEB_RX);
132 133 134 135 136 137
}

/**
 *  @brief This function processes received packet and forwards it
 *  to kernel/upper layer
 *
138
 *  @param priv    A pointer to struct lbs_private
139 140 141
 *  @param skb     A pointer to skb which includes the received packet
 *  @return 	   0 or -1
 */
142
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
143 144
{
	int ret = 0;
145
	struct net_device *dev = priv->dev;
146 147 148 149 150 151
	struct rxpackethdr *p_rx_pkt;
	struct rxpd *p_rx_pd;
	int hdrchop;
	struct ethhdr *p_ethhdr;
	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };

152
	lbs_deb_enter(LBS_DEB_RX);
153

154 155
	BUG_ON(!skb);

156 157
	skb->ip_summed = CHECKSUM_NONE;

158
	if (priv->monitormode)
159 160 161 162
		return process_rxed_802_11_packet(priv, skb);

	p_rx_pkt = (struct rxpackethdr *) skb->data;
	p_rx_pd = &p_rx_pkt->rx_pd;
163 164
	if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
		dev = priv->mesh_dev;
165

166
	lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
167 168 169
		 min_t(unsigned int, skb->len, 100));

	if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
170
		lbs_deb_rx("rx err: frame received with bad length\n");
171 172 173 174 175 176 177 178
		priv->stats.rx_length_errors++;
		ret = 0;
		goto done;
	}

	/*
	 * Check rxpd status and update 802.3 stat,
	 */
179
	if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
180 181
		lbs_deb_rx("rx err: frame received with bad status\n");
		lbs_pr_alert("rxpd not ok\n");
182 183 184 185 186
		priv->stats.rx_errors++;
		ret = 0;
		goto done;
	}

187
	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
188 189
	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));

190
	lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
191
		sizeof(p_rx_pkt->eth803_hdr.dest_addr));
192
	lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
		sizeof(p_rx_pkt->eth803_hdr.src_addr));

	if (memcmp(&p_rx_pkt->rfc1042_hdr,
		   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
		/*
		 *  Replace the 803 header and rfc1042 header (llc/snap) with an
		 *    EthernetII header, keep the src/dst and snap_type (ethertype)
		 *
		 *  The firmware only passes up SNAP frames converting
		 *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
		 *
		 *  To create the Ethernet II, just move the src, dst address right
		 *    before the snap_type.
		 */
		p_ethhdr = (struct ethhdr *)
		    ((u8 *) & p_rx_pkt->eth803_hdr
		     + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
		     - sizeof(p_rx_pkt->eth803_hdr.dest_addr)
		     - sizeof(p_rx_pkt->eth803_hdr.src_addr)
		     - sizeof(p_rx_pkt->rfc1042_hdr.snap_type));

		memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
		       sizeof(p_ethhdr->h_source));
		memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
		       sizeof(p_ethhdr->h_dest));

		/* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
		 *   that was removed
		 */
		hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt;
	} else {
224
		lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
			(u8 *) & p_rx_pkt->rfc1042_hdr,
			sizeof(p_rx_pkt->rfc1042_hdr));

		/* Chop off the rxpd */
		hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt;
	}

	/* Chop off the leading header bytes so the skb points to the start of
	 *   either the reconstructed EthII frame or the 802.2/llc/snap frame
	 */
	skb_pull(skb, hdrchop);

	/* Take the data rate from the rxpd structure
	 * only if the rate is auto
	 */
240 241
	if (priv->auto_rate)
		priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
242

243
	lbs_compute_rssi(priv, p_rx_pd);
244

245
	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
246 247 248
	priv->stats.rx_bytes += skb->len;
	priv->stats.rx_packets++;

249
	skb->protocol = eth_type_trans(skb, dev);
250 251 252 253
	if (in_interrupt())
		netif_rx(skb);
	else
		netif_rx_ni(skb);
254

255 256
	ret = 0;
done:
257
	lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
258 259
	return ret;
}
260
EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

/**
 *  @brief This function converts Tx/Rx rates from the Marvell WLAN format
 *  (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
 *
 *  @param rate    Input rate
 *  @return 	   Output Rate (0 if invalid)
 */
static u8 convert_mv_rate_to_radiotap(u8 rate)
{
	switch (rate) {
	case 0:		/*   1 Mbps */
		return 2;
	case 1:		/*   2 Mbps */
		return 4;
	case 2:		/* 5.5 Mbps */
		return 11;
	case 3:		/*  11 Mbps */
		return 22;
280 281
	/* case 4: reserved */
	case 5:		/*   6 Mbps */
282
		return 12;
283
	case 6:		/*   9 Mbps */
284
		return 18;
285
	case 7:		/*  12 Mbps */
286
		return 24;
287
	case 8:		/*  18 Mbps */
288
		return 36;
289
	case 9:		/*  24 Mbps */
290
		return 48;
291
	case 10:		/*  36 Mbps */
292
		return 72;
293
	case 11:		/*  48 Mbps */
294
		return 96;
295
	case 12:		/*  54 Mbps */
296 297
		return 108;
	}
298
	lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
299 300 301 302 303 304 305
	return 0;
}

/**
 *  @brief This function processes a received 802.11 packet and forwards it
 *  to kernel/upper layer
 *
306
 *  @param priv    A pointer to struct lbs_private
307 308 309
 *  @param skb     A pointer to skb which includes the received packet
 *  @return 	   0 or -1
 */
310 311
static int process_rxed_802_11_packet(struct lbs_private *priv,
	struct sk_buff *skb)
312 313 314 315 316 317 318 319
{
	int ret = 0;

	struct rx80211packethdr *p_rx_pkt;
	struct rxpd *prxpd;
	struct rx_radiotap_hdr radiotap_hdr;
	struct rx_radiotap_hdr *pradiotap_hdr;

320
	lbs_deb_enter(LBS_DEB_RX);
321 322 323 324

	p_rx_pkt = (struct rx80211packethdr *) skb->data;
	prxpd = &p_rx_pkt->rx_pd;

325
	// lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
326 327

	if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
328
		lbs_deb_rx("rx err: frame received with bad length\n");
329
		priv->stats.rx_length_errors++;
330 331
		ret = -EINVAL;
		kfree(skb);
332 333 334 335 336 337
		goto done;
	}

	/*
	 * Check rxpd status and update 802.3 stat,
	 */
338
	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
339
		//lbs_deb_rx("rx err: frame received with bad status\n");
340 341 342
		priv->stats.rx_errors++;
	}

343
	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
344 345 346 347
	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));

	/* create the exported radio header */

348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	/* radiotap header */
	radiotap_hdr.hdr.it_version = 0;
	/* XXX must check this value for pad */
	radiotap_hdr.hdr.it_pad = 0;
	radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
	radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
	/* unknown values */
	radiotap_hdr.flags = 0;
	radiotap_hdr.chan_freq = 0;
	radiotap_hdr.chan_flags = 0;
	radiotap_hdr.antenna = 0;
	/* known values */
	radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
	/* XXX must check no carryout */
	radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
	radiotap_hdr.rx_flags = 0;
	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
		radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
	//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);

	/* chop the rxpd */
	skb_pull(skb, sizeof(struct rxpd));

	/* add space for the new radio header */
	if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
373 374 375 376 377
	    pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
		lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__);
		ret = -ENOMEM;
		kfree_skb(skb);
		goto done;
378 379
	}

380 381 382
	pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
	memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));

383 384 385
	/* Take the data rate from the rxpd structure
	 * only if the rate is auto
	 */
386 387
	if (priv->auto_rate)
		priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
388

389
	lbs_compute_rssi(priv, prxpd);
390

391
	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
392 393 394
	priv->stats.rx_bytes += skb->len;
	priv->stats.rx_packets++;

395 396
	skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
	netif_rx(skb);
397

398 399
	ret = 0;

400 401 402
done:
	lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
	return ret;
403
}