xref: /openbmc/linux/drivers/staging/vt6655/dpc.c (revision 7988cf07)
1d7c43082SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
25449c685SForest Bond /*
35449c685SForest Bond  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
45449c685SForest Bond  * All rights reserved.
55449c685SForest Bond  *
65449c685SForest Bond  * Purpose: handle dpc rx functions
75449c685SForest Bond  *
85449c685SForest Bond  * Author: Lyndon Chen
95449c685SForest Bond  *
105449c685SForest Bond  * Date: May 20, 2003
115449c685SForest Bond  *
125449c685SForest Bond  * Functions:
135449c685SForest Bond  *
145449c685SForest Bond  * Revision History:
155449c685SForest Bond  *
165449c685SForest Bond  */
175449c685SForest Bond 
185449c685SForest Bond #include "device.h"
195449c685SForest Bond #include "baseband.h"
205449c685SForest Bond #include "rf.h"
2104d52197SJames A Shackleford #include "dpc.h"
225449c685SForest Bond 
vnt_rx_data(struct vnt_private * priv,struct sk_buff * skb,u16 bytes_received)2333b1c8c1SMalcolm Priestley static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb,
2433b1c8c1SMalcolm Priestley 			u16 bytes_received)
2533b1c8c1SMalcolm Priestley {
2633b1c8c1SMalcolm Priestley 	struct ieee80211_hw *hw = priv->hw;
2733b1c8c1SMalcolm Priestley 	struct ieee80211_supported_band *sband;
2833b1c8c1SMalcolm Priestley 	struct ieee80211_rx_status rx_status = { 0 };
2933b1c8c1SMalcolm Priestley 	struct ieee80211_hdr *hdr;
3033b1c8c1SMalcolm Priestley 	__le16 fc;
3133b1c8c1SMalcolm Priestley 	u8 *rsr, *new_rsr, *rssi;
3233b1c8c1SMalcolm Priestley 	__le64 *tsf_time;
3333b1c8c1SMalcolm Priestley 	u16 frame_size;
3433b1c8c1SMalcolm Priestley 	int ii, r;
35d6ff1b52SColin Ian King 	u8 *rx_rate;
3633b1c8c1SMalcolm Priestley 	u8 *skb_data;
3733b1c8c1SMalcolm Priestley 	u8 rate_idx = 0;
3833b1c8c1SMalcolm Priestley 	u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
3933b1c8c1SMalcolm Priestley 	long rx_dbm;
4033b1c8c1SMalcolm Priestley 
4133b1c8c1SMalcolm Priestley 	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
4233b1c8c1SMalcolm Priestley 	frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2)));
4333b1c8c1SMalcolm Priestley 	if (frame_size > 2346 || frame_size < 14) {
4433b1c8c1SMalcolm Priestley 		dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n");
4533b1c8c1SMalcolm Priestley 		return false;
4633b1c8c1SMalcolm Priestley 	}
4733b1c8c1SMalcolm Priestley 
4833b1c8c1SMalcolm Priestley 	skb_data = (u8 *)skb->data;
4933b1c8c1SMalcolm Priestley 
5033b1c8c1SMalcolm Priestley 	rx_rate = skb_data + 1;
5133b1c8c1SMalcolm Priestley 
5233b1c8c1SMalcolm Priestley 	sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
5333b1c8c1SMalcolm Priestley 
5433b1c8c1SMalcolm Priestley 	for (r = RATE_1M; r < MAX_RATE; r++) {
5533b1c8c1SMalcolm Priestley 		if (*rx_rate == rate[r])
5633b1c8c1SMalcolm Priestley 			break;
5733b1c8c1SMalcolm Priestley 	}
5833b1c8c1SMalcolm Priestley 
5933b1c8c1SMalcolm Priestley 	priv->rx_rate = r;
6033b1c8c1SMalcolm Priestley 
6133b1c8c1SMalcolm Priestley 	for (ii = 0; ii < sband->n_bitrates; ii++) {
6233b1c8c1SMalcolm Priestley 		if (sband->bitrates[ii].hw_value == r) {
6333b1c8c1SMalcolm Priestley 			rate_idx = ii;
6433b1c8c1SMalcolm Priestley 				break;
6533b1c8c1SMalcolm Priestley 		}
6633b1c8c1SMalcolm Priestley 	}
6733b1c8c1SMalcolm Priestley 
6833b1c8c1SMalcolm Priestley 	if (ii == sband->n_bitrates) {
6933b1c8c1SMalcolm Priestley 		dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate);
7033b1c8c1SMalcolm Priestley 		return false;
7133b1c8c1SMalcolm Priestley 	}
7233b1c8c1SMalcolm Priestley 
7333b1c8c1SMalcolm Priestley 	tsf_time = (__le64 *)(skb_data + bytes_received - 12);
7433b1c8c1SMalcolm Priestley 	new_rsr = skb_data + bytes_received - 3;
7533b1c8c1SMalcolm Priestley 	rssi = skb_data + bytes_received - 2;
7633b1c8c1SMalcolm Priestley 	rsr = skb_data + bytes_received - 1;
776d854127SMalcolm Priestley 	if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
786d854127SMalcolm Priestley 		return false;
7933b1c8c1SMalcolm Priestley 
8033b1c8c1SMalcolm Priestley 	RFvRSSITodBm(priv, *rssi, &rx_dbm);
8133b1c8c1SMalcolm Priestley 
8233b1c8c1SMalcolm Priestley 	priv->byBBPreEDRSSI = (u8)rx_dbm + 1;
83*7988cf07SAlberto Merciai 	priv->current_rssi = *rssi;
8433b1c8c1SMalcolm Priestley 
8533b1c8c1SMalcolm Priestley 	skb_pull(skb, 4);
8633b1c8c1SMalcolm Priestley 	skb_trim(skb, frame_size);
8733b1c8c1SMalcolm Priestley 
8833b1c8c1SMalcolm Priestley 	rx_status.mactime = le64_to_cpu(*tsf_time);
8933b1c8c1SMalcolm Priestley 	rx_status.band = hw->conf.chandef.chan->band;
9033b1c8c1SMalcolm Priestley 	rx_status.signal = rx_dbm;
9133b1c8c1SMalcolm Priestley 	rx_status.flag = 0;
9233b1c8c1SMalcolm Priestley 	rx_status.freq = hw->conf.chandef.chan->center_freq;
9333b1c8c1SMalcolm Priestley 
946d854127SMalcolm Priestley 	if (!(*rsr & RSR_CRCOK))
956d854127SMalcolm Priestley 		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
966d854127SMalcolm Priestley 
9733b1c8c1SMalcolm Priestley 	hdr = (struct ieee80211_hdr *)(skb->data);
9833b1c8c1SMalcolm Priestley 	fc = hdr->frame_control;
9933b1c8c1SMalcolm Priestley 
10033b1c8c1SMalcolm Priestley 	rx_status.rate_idx = rate_idx;
10133b1c8c1SMalcolm Priestley 
10233b1c8c1SMalcolm Priestley 	if (ieee80211_has_protected(fc)) {
103e9c1caeaSTommaso Merciai 		if (priv->local_id > REV_ID_VT3253_A1)
1046d854127SMalcolm Priestley 			rx_status.flag |= RX_FLAG_DECRYPTED;
1056d854127SMalcolm Priestley 
1066d854127SMalcolm Priestley 		/* Drop packet */
1076d854127SMalcolm Priestley 		if (!(*new_rsr & NEWRSR_DECRYPTOK))
1086d854127SMalcolm Priestley 			return false;
10933b1c8c1SMalcolm Priestley 	}
11033b1c8c1SMalcolm Priestley 
11133b1c8c1SMalcolm Priestley 	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
11233b1c8c1SMalcolm Priestley 
11333b1c8c1SMalcolm Priestley 	ieee80211_rx_irqsafe(priv->hw, skb);
11433b1c8c1SMalcolm Priestley 
11533b1c8c1SMalcolm Priestley 	return true;
11633b1c8c1SMalcolm Priestley }
11733b1c8c1SMalcolm Priestley 
vnt_receive_frame(struct vnt_private * priv,struct vnt_rx_desc * curr_rd)1189cb693f6SMalcolm Priestley bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd)
11933b1c8c1SMalcolm Priestley {
12088defe2bSMalcolm Priestley 	struct vnt_rd_info *rd_info = curr_rd->rd_info;
12133b1c8c1SMalcolm Priestley 	struct sk_buff *skb;
12233b1c8c1SMalcolm Priestley 	u16 frame_size;
12333b1c8c1SMalcolm Priestley 
12433b1c8c1SMalcolm Priestley 	skb = rd_info->skb;
12533b1c8c1SMalcolm Priestley 
126a1c6dcdaSQuentin Lambert 	dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
127a1c6dcdaSQuentin Lambert 			 priv->rx_buf_sz, DMA_FROM_DEVICE);
12833b1c8c1SMalcolm Priestley 
1299fc7091cSMalcolm Priestley 	frame_size = le16_to_cpu(curr_rd->rd1.req_count)
130de1c1862SMalcolm Priestley 			- le16_to_cpu(curr_rd->rd0.res_count);
13133b1c8c1SMalcolm Priestley 
13233b1c8c1SMalcolm Priestley 	if ((frame_size > 2364) || (frame_size < 33)) {
13333b1c8c1SMalcolm Priestley 		/* Frame Size error drop this packet.*/
13433b1c8c1SMalcolm Priestley 		dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size);
13533b1c8c1SMalcolm Priestley 		dev_kfree_skb_irq(skb);
13633b1c8c1SMalcolm Priestley 		return true;
13733b1c8c1SMalcolm Priestley 	}
13833b1c8c1SMalcolm Priestley 
13933b1c8c1SMalcolm Priestley 	if (vnt_rx_data(priv, skb, frame_size))
14033b1c8c1SMalcolm Priestley 		return true;
14133b1c8c1SMalcolm Priestley 
14233b1c8c1SMalcolm Priestley 	dev_kfree_skb_irq(skb);
14333b1c8c1SMalcolm Priestley 
14433b1c8c1SMalcolm Priestley 	return true;
14533b1c8c1SMalcolm Priestley }
146