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