blob: f109eeac358d86954f5ee8caefc4a0b310725dce [file] [log] [blame]
Forest Bond5449c682009-04-25 10:30:44 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: device_main.c
20 *
21 * Purpose: driver entry for initial, open, close, tx and rx.
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: Jan 8, 2003
26 *
27 * Functions:
28 *
Charles Clément013a4682010-06-15 10:39:24 -070029 * vt6655_probe - module initial (insmod) driver entry
30 * vt6655_remove - module remove entry
Forest Bond5449c682009-04-25 10:30:44 -040031 * device_free_info - device structure resource free function
Forest Bond5449c682009-04-25 10:30:44 -040032 * device_print_info - print out resource
Forest Bond5449c682009-04-25 10:30:44 -040033 * device_rx_srv - rx service function
Forest Bond5449c682009-04-25 10:30:44 -040034 * device_alloc_rx_buf - rx buffer pre-allocated function
Forest Bond5449c682009-04-25 10:30:44 -040035 * device_free_tx_buf - free tx buffer function
Forest Bond5449c682009-04-25 10:30:44 -040036 * device_init_rd0_ring- initial rd dma0 ring
37 * device_init_rd1_ring- initial rd dma1 ring
38 * device_init_td0_ring- initial tx dma0 ring buffer
39 * device_init_td1_ring- initial tx dma1 ring buffer
40 * device_init_registers- initial MAC & BBP & RF internal registers.
41 * device_init_rings- initial tx/rx ring buffer
Forest Bond5449c682009-04-25 10:30:44 -040042 * device_free_rings- free all allocated ring buffer
43 * device_tx_srv- tx interrupt service function
44 *
45 * Revision History:
46 */
47#undef __NO_VERSION__
48
Al Virof8054422013-04-06 18:11:22 -040049#include <linux/file.h>
Forest Bond5449c682009-04-25 10:30:44 -040050#include "device.h"
Forest Bond5449c682009-04-25 10:30:44 -040051#include "card.h"
Charles Clément79566eb2010-06-21 10:39:51 -070052#include "channel.h"
Forest Bond5449c682009-04-25 10:30:44 -040053#include "baseband.h"
Forest Bond5449c682009-04-25 10:30:44 -040054#include "mac.h"
Forest Bond5449c682009-04-25 10:30:44 -040055#include "power.h"
Forest Bond5449c682009-04-25 10:30:44 -040056#include "rxtx.h"
Forest Bond5449c682009-04-25 10:30:44 -040057#include "dpc.h"
Forest Bond5449c682009-04-25 10:30:44 -040058#include "rf.h"
Forest Bond5449c682009-04-25 10:30:44 -040059#include <linux/delay.h>
60#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090061#include <linux/slab.h>
Forest Bond5449c682009-04-25 10:30:44 -040062
Forest Bond5449c682009-04-25 10:30:44 -040063/*--------------------- Static Definitions -------------------------*/
Alex W Slaterbb72dd52015-02-26 20:09:26 +000064/*
65 * Define module options
66 */
Forest Bond5449c682009-04-25 10:30:44 -040067MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
68MODULE_LICENSE("GPL");
69MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
Forest Bond5449c682009-04-25 10:30:44 -040070
Joe Perches915006c2013-03-18 10:44:47 -070071#define DEVICE_PARAM(N, D)
Forest Bond5449c682009-04-25 10:30:44 -040072
73#define RX_DESC_MIN0 16
74#define RX_DESC_MAX0 128
75#define RX_DESC_DEF0 32
Joe Perches915006c2013-03-18 10:44:47 -070076DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
Forest Bond5449c682009-04-25 10:30:44 -040077
78#define RX_DESC_MIN1 16
79#define RX_DESC_MAX1 128
80#define RX_DESC_DEF1 32
Joe Perches915006c2013-03-18 10:44:47 -070081DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
Forest Bond5449c682009-04-25 10:30:44 -040082
83#define TX_DESC_MIN0 16
84#define TX_DESC_MAX0 128
85#define TX_DESC_DEF0 32
Joe Perches915006c2013-03-18 10:44:47 -070086DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
Forest Bond5449c682009-04-25 10:30:44 -040087
88#define TX_DESC_MIN1 16
89#define TX_DESC_MAX1 128
90#define TX_DESC_DEF1 64
Joe Perches915006c2013-03-18 10:44:47 -070091DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
Forest Bond5449c682009-04-25 10:30:44 -040092
Forest Bond5449c682009-04-25 10:30:44 -040093#define INT_WORKS_DEF 20
94#define INT_WORKS_MIN 10
95#define INT_WORKS_MAX 64
96
Joe Perches915006c2013-03-18 10:44:47 -070097DEVICE_PARAM(int_works, "Number of packets per interrupt services");
Forest Bond5449c682009-04-25 10:30:44 -040098
Forest Bond5449c682009-04-25 10:30:44 -040099#define RTS_THRESH_DEF 2347
100
Forest Bond5449c682009-04-25 10:30:44 -0400101#define FRAG_THRESH_DEF 2346
102
Forest Bond5449c682009-04-25 10:30:44 -0400103#define SHORT_RETRY_MIN 0
104#define SHORT_RETRY_MAX 31
105#define SHORT_RETRY_DEF 8
106
Forest Bond5449c682009-04-25 10:30:44 -0400107DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
108
109#define LONG_RETRY_MIN 0
110#define LONG_RETRY_MAX 15
111#define LONG_RETRY_DEF 4
112
Forest Bond5449c682009-04-25 10:30:44 -0400113DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
114
Forest Bond5449c682009-04-25 10:30:44 -0400115/* BasebandType[] baseband type selected
Anson Jacob9877f9d2016-07-08 21:27:05 -0400116 * 0: indicate 802.11a type
117 * 1: indicate 802.11b type
118 * 2: indicate 802.11g type
119 */
Forest Bond5449c682009-04-25 10:30:44 -0400120#define BBP_TYPE_MIN 0
121#define BBP_TYPE_MAX 2
122#define BBP_TYPE_DEF 2
123
124DEVICE_PARAM(BasebandType, "baseband type");
125
Alex W Slaterbb72dd52015-02-26 20:09:26 +0000126/*
127 * Static vars definitions
128 */
Guillaume Clement9e4c5c22014-07-22 22:08:28 +0200129static const struct pci_device_id vt6655_pci_id_table[] = {
Malcolm Priestley319755a2015-09-12 19:10:30 +0100130 { PCI_VDEVICE(VIA, 0x3253) },
Jim Liebdb6cb902009-07-23 17:20:49 -0700131 { 0, }
Forest Bond5449c682009-04-25 10:30:44 -0400132};
Forest Bond5449c682009-04-25 10:30:44 -0400133
134/*--------------------- Static Functions --------------------------*/
135
Charles Clément013a4682010-06-15 10:39:24 -0700136static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100137static void device_free_info(struct vnt_private *priv);
138static void device_print_info(struct vnt_private *priv);
Forest Bond5449c682009-04-25 10:30:44 -0400139
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100140static void device_init_rd0_ring(struct vnt_private *priv);
141static void device_init_rd1_ring(struct vnt_private *priv);
142static void device_init_td0_ring(struct vnt_private *priv);
143static void device_init_td1_ring(struct vnt_private *priv);
Forest Bond5449c682009-04-25 10:30:44 -0400144
Malcolm Priestley0924a892015-10-17 11:32:54 +0100145static int device_rx_srv(struct vnt_private *priv, unsigned int idx);
146static int device_tx_srv(struct vnt_private *priv, unsigned int idx);
Malcolm Priestley9cb693f2015-08-15 21:57:35 +0100147static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *);
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100148static void device_init_registers(struct vnt_private *priv);
Malcolm Priestleye2357272015-08-14 22:58:51 +0100149static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *);
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100150static void device_free_td0_ring(struct vnt_private *priv);
151static void device_free_td1_ring(struct vnt_private *priv);
152static void device_free_rd0_ring(struct vnt_private *priv);
153static void device_free_rd1_ring(struct vnt_private *priv);
154static void device_free_rings(struct vnt_private *priv);
Forest Bond5449c682009-04-25 10:30:44 -0400155
Forest Bond5449c682009-04-25 10:30:44 -0400156/*--------------------- Export Variables --------------------------*/
157
158/*--------------------- Export Functions --------------------------*/
159
Bill Pembertonf4e1b7c2012-11-19 13:26:53 -0500160static void vt6655_remove(struct pci_dev *pcid)
Forest Bond5449c682009-04-25 10:30:44 -0400161{
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100162 struct vnt_private *priv = pci_get_drvdata(pcid);
Forest Bond5449c682009-04-25 10:30:44 -0400163
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100164 if (priv == NULL)
Devendra Naga3ac9e0f2012-09-07 00:08:02 +0530165 return;
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100166 device_free_info(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400167}
168
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100169static void device_get_options(struct vnt_private *priv)
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530170{
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100171 struct vnt_options *opts = &priv->opts;
Forest Bond5449c682009-04-25 10:30:44 -0400172
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100173 opts->rx_descs0 = RX_DESC_DEF0;
174 opts->rx_descs1 = RX_DESC_DEF1;
175 opts->tx_descs[0] = TX_DESC_DEF0;
176 opts->tx_descs[1] = TX_DESC_DEF1;
177 opts->int_works = INT_WORKS_DEF;
Forest Bond5449c682009-04-25 10:30:44 -0400178
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100179 opts->short_retry = SHORT_RETRY_DEF;
180 opts->long_retry = LONG_RETRY_DEF;
181 opts->bbp_type = BBP_TYPE_DEF;
Forest Bond5449c682009-04-25 10:30:44 -0400182}
183
184static void
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100185device_set_options(struct vnt_private *priv)
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100186{
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100187 priv->byShortRetryLimit = priv->opts.short_retry;
188 priv->byLongRetryLimit = priv->opts.long_retry;
189 priv->byBBType = priv->opts.bbp_type;
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100190 priv->byPacketType = priv->byBBType;
191 priv->byAutoFBCtrl = AUTO_FB_0;
192 priv->bUpdateBBVGA = true;
193 priv->byPreambleType = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400194
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100195 pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit);
196 pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit);
197 pr_debug(" byPreambleType= %d\n", (int)priv->byPreambleType);
198 pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble);
199 pr_debug(" byBBType= %d\n", (int)priv->byBBType);
Forest Bond5449c682009-04-25 10:30:44 -0400200}
201
Alex W Slaterbb72dd52015-02-26 20:09:26 +0000202/*
203 * Initialisation of MAC & BBP registers
204 */
Forest Bond5449c682009-04-25 10:30:44 -0400205
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100206static void device_init_registers(struct vnt_private *priv)
Forest Bond5449c682009-04-25 10:30:44 -0400207{
Malcolm Priestley10d6f1b2014-10-29 17:44:04 +0000208 unsigned long flags;
Joe Perches915006c2013-03-18 10:44:47 -0700209 unsigned int ii;
210 unsigned char byValue;
Joe Perches915006c2013-03-18 10:44:47 -0700211 unsigned char byCCKPwrdBm = 0;
212 unsigned char byOFDMPwrdBm = 0;
Guillaume Clement6b711272014-07-25 01:06:16 +0200213
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +0000214 MACbShutdown(priv);
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100215 BBvSoftwareReset(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400216
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100217 /* Do MACbSoftwareReset in MACvInitialize */
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +0000218 MACbSoftwareReset(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400219
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100220 priv->bAES = false;
Forest Bond5449c682009-04-25 10:30:44 -0400221
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100222 /* Only used in 11g type, sync with ERP IE */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100223 priv->bProtectMode = false;
Forest Bond5449c682009-04-25 10:30:44 -0400224
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100225 priv->bNonERPPresent = false;
226 priv->bBarkerPreambleMd = false;
227 priv->wCurrentRate = RATE_1M;
228 priv->byTopOFDMBasicRate = RATE_24M;
229 priv->byTopCCKBasicRate = RATE_1M;
Forest Bond5449c682009-04-25 10:30:44 -0400230
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100231 /* init MAC */
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +0000232 MACvInitialize(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400233
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100234 /* Get Local ID */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100235 VNSvInPortB(priv->PortOffset + MAC_REG_LOCALID, &priv->byLocalID);
Forest Bond5449c682009-04-25 10:30:44 -0400236
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100237 spin_lock_irqsave(&priv->lock, flags);
Forest Bond5449c682009-04-25 10:30:44 -0400238
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100239 SROMvReadAllContents(priv->PortOffset, priv->abyEEPROM);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100240
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100241 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100242
243 /* Get Channel range */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100244 priv->byMinChannel = 1;
245 priv->byMaxChannel = CB_MAX_CHANNEL;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100246
247 /* Get Antena */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100248 byValue = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_ANTENNA);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100249 if (byValue & EEP_ANTINV)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100250 priv->bTxRxAntInv = true;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100251 else
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100252 priv->bTxRxAntInv = false;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100253
254 byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
255 /* if not set default is All */
256 if (byValue == 0)
257 byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
258
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100259 if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100260 priv->byAntennaCount = 2;
261 priv->byTxAntennaMode = ANT_B;
262 priv->dwTxAntennaSel = 1;
263 priv->dwRxAntennaSel = 1;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100264
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100265 if (priv->bTxRxAntInv)
266 priv->byRxAntennaMode = ANT_A;
Joe Perches915006c2013-03-18 10:44:47 -0700267 else
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100268 priv->byRxAntennaMode = ANT_B;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100269 } else {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100270 priv->byAntennaCount = 1;
271 priv->dwTxAntennaSel = 0;
272 priv->dwRxAntennaSel = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400273
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100274 if (byValue & EEP_ANTENNA_AUX) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100275 priv->byTxAntennaMode = ANT_A;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100276
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100277 if (priv->bTxRxAntInv)
278 priv->byRxAntennaMode = ANT_B;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100279 else
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100280 priv->byRxAntennaMode = ANT_A;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100281 } else {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100282 priv->byTxAntennaMode = ANT_B;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100283
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100284 if (priv->bTxRxAntInv)
285 priv->byRxAntennaMode = ANT_A;
Joe Perches915006c2013-03-18 10:44:47 -0700286 else
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100287 priv->byRxAntennaMode = ANT_B;
Joe Perches915006c2013-03-18 10:44:47 -0700288 }
289 }
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100290
Malcolm Priestley918185f2015-01-19 18:24:13 +0000291 /* Set initial antenna mode */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100292 BBvSetTxAntennaMode(priv, priv->byTxAntennaMode);
293 BBvSetRxAntennaMode(priv, priv->byRxAntennaMode);
Malcolm Priestley918185f2015-01-19 18:24:13 +0000294
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100295 /* zonetype initial */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100296 priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE];
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100297
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100298 if (!priv->bZoneRegExist)
299 priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE];
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100300
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100301 pr_debug("priv->byZoneType = %x\n", priv->byZoneType);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100302
303 /* Init RF module */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100304 RFbInit(priv);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100305
306 /* Get Desire Power Value */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100307 priv->byCurPwr = 0xFF;
308 priv->byCCKPwr = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_PWR_CCK);
309 priv->byOFDMPwrG = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_PWR_OFDMG);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100310
311 /* Load power Table */
312 for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100313 priv->abyCCKPwrTbl[ii + 1] =
314 SROMbyReadEmbedded(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100315 (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100316 if (priv->abyCCKPwrTbl[ii + 1] == 0)
317 priv->abyCCKPwrTbl[ii+1] = priv->byCCKPwr;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100318
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100319 priv->abyOFDMPwrTbl[ii + 1] =
320 SROMbyReadEmbedded(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100321 (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100322 if (priv->abyOFDMPwrTbl[ii + 1] == 0)
323 priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100324
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100325 priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
326 priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100327 }
328
329 /* recover 12,13 ,14channel for EUROPE by 11 channel */
Malcolm Priestleyf4cf6782014-10-29 17:55:19 +0000330 for (ii = 11; ii < 14; ii++) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100331 priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10];
332 priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10];
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100333 }
334
335 /* Load OFDM A Power Table */
336 for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100337 priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] =
338 SROMbyReadEmbedded(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100339 (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
340
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100341 priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] =
342 SROMbyReadEmbedded(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100343 (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
344 }
345
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100346 if (priv->byLocalID > REV_ID_VT3253_B1) {
347 MACvSelectPage1(priv->PortOffset);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100348
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100349 VNSvOutPortB(priv->PortOffset + MAC_REG_MSRCTL + 1,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100350 (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
351
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100352 MACvSelectPage0(priv->PortOffset);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100353 }
354
355 /* use relative tx timeout and 802.11i D4 */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100356 MACvWordRegBitsOn(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100357 MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
358
359 /* set performance parameter by registry */
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +0000360 MACvSetShortRetryLimit(priv, priv->byShortRetryLimit);
361 MACvSetLongRetryLimit(priv, priv->byLongRetryLimit);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100362
363 /* reset TSF counter */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100364 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100365 /* enable TSF counter */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100366 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100367
368 /* initialize BBP registers */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100369 BBbVT3253Init(priv);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100370
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100371 if (priv->bUpdateBBVGA) {
372 priv->byBBVGACurrent = priv->abyBBVGA[0];
373 priv->byBBVGANew = priv->byBBVGACurrent;
374 BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100375 }
376
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100377 BBvSetRxAntennaMode(priv, priv->byRxAntennaMode);
378 BBvSetTxAntennaMode(priv, priv->byTxAntennaMode);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100379
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100380 /* Set BB and packet type at the same time. */
381 /* Set Short Slot Time, xIFS, and RSPINF. */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100382 priv->wCurrentRate = RATE_54M;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100383
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100384 priv->bRadioOff = false;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100385
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100386 priv->byRadioCtl = SROMbyReadEmbedded(priv->PortOffset,
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100387 EEP_OFS_RADIOCTL);
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100388 priv->bHWRadioOff = false;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100389
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100390 if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) {
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100391 /* Get GPIO */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100392 MACvGPIOIn(priv->PortOffset, &priv->byGPIO);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100393
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100394 if (((priv->byGPIO & GPIO0_DATA) &&
395 !(priv->byRadioCtl & EEP_RADIOCTL_INV)) ||
396 (!(priv->byGPIO & GPIO0_DATA) &&
397 (priv->byRadioCtl & EEP_RADIOCTL_INV)))
398 priv->bHWRadioOff = true;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100399 }
400
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100401 if (priv->bHWRadioOff || priv->bRadioControlOff)
402 CARDbRadioPowerOff(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400403
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100404 /* get Permanent network address */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100405 SROMvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr);
406 pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr);
Forest Bond5449c682009-04-25 10:30:44 -0400407
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100408 /* reset Tx pointer */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100409 CARDvSafeResetRx(priv);
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100410 /* reset Rx pointer */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100411 CARDvSafeResetTx(priv);
Forest Bond5449c682009-04-25 10:30:44 -0400412
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100413 if (priv->byLocalID <= REV_ID_VT3253_A1)
414 MACvRegBitsOn(priv->PortOffset, MAC_REG_RCR, RCR_WPAERR);
Forest Bond5449c682009-04-25 10:30:44 -0400415
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100416 /* Turn On Rx DMA */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100417 MACvReceive0(priv->PortOffset);
418 MACvReceive1(priv->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400419
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100420 /* start the adapter */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100421 MACvStart(priv->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400422}
423
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100424static void device_print_info(struct vnt_private *priv)
Forest Bond5449c682009-04-25 10:30:44 -0400425{
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100426 dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n",
427 priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr,
428 (unsigned long)priv->PortOffset, priv->pcid->irq);
Forest Bond5449c682009-04-25 10:30:44 -0400429}
430
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100431static void device_free_info(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200432{
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100433 if (!priv)
Malcolm Priestley14e53002014-10-29 17:43:55 +0000434 return;
Forest Bond5449c682009-04-25 10:30:44 -0400435
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100436 if (priv->mac_hw)
437 ieee80211_unregister_hw(priv->hw);
Forest Bond5449c682009-04-25 10:30:44 -0400438
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100439 if (priv->PortOffset)
440 iounmap(priv->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400441
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100442 if (priv->pcid)
443 pci_release_regions(priv->pcid);
Malcolm Priestley14e53002014-10-29 17:43:55 +0000444
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100445 if (priv->hw)
446 ieee80211_free_hw(priv->hw);
Forest Bond5449c682009-04-25 10:30:44 -0400447}
Forest Bond5449c682009-04-25 10:30:44 -0400448
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100449static bool device_init_rings(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200450{
Joe Perches915006c2013-03-18 10:44:47 -0700451 void *vir_pool;
Forest Bond5449c682009-04-25 10:30:44 -0400452
Joe Perches915006c2013-03-18 10:44:47 -0700453 /*allocate all RD/TD rings a single pool*/
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100454 vir_pool = dma_zalloc_coherent(&priv->pcid->dev,
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100455 priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
456 priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
457 priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
458 priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100459 &priv->pool_dma, GFP_ATOMIC);
Joe Perches915006c2013-03-18 10:44:47 -0700460 if (vir_pool == NULL) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100461 dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
Joe Perches915006c2013-03-18 10:44:47 -0700462 return false;
463 }
Forest Bond5449c682009-04-25 10:30:44 -0400464
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100465 priv->aRD0Ring = vir_pool;
466 priv->aRD1Ring = vir_pool +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100467 priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400468
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100469 priv->rd0_pool_dma = priv->pool_dma;
470 priv->rd1_pool_dma = priv->rd0_pool_dma +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100471 priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400472
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100473 priv->tx0_bufs = dma_zalloc_coherent(&priv->pcid->dev,
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100474 priv->opts.tx_descs[0] * PKT_BUF_SZ +
475 priv->opts.tx_descs[1] * PKT_BUF_SZ +
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100476 CB_BEACON_BUF_SIZE +
477 CB_MAX_BUF_SIZE,
478 &priv->tx_bufs_dma0,
479 GFP_ATOMIC);
Namrata A Shettar7cfae242016-09-18 14:34:51 +0530480 if (!priv->tx0_bufs) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100481 dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100482
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100483 dma_free_coherent(&priv->pcid->dev,
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100484 priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
485 priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
486 priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
487 priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100488 vir_pool, priv->pool_dma);
Joe Perches915006c2013-03-18 10:44:47 -0700489 return false;
490 }
Forest Bond5449c682009-04-25 10:30:44 -0400491
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100492 priv->td0_pool_dma = priv->rd1_pool_dma +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100493 priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400494
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100495 priv->td1_pool_dma = priv->td0_pool_dma +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100496 priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400497
Alex W Slaterbb72dd52015-02-26 20:09:26 +0000498 /* vir_pool: pvoid type */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100499 priv->apTD0Rings = vir_pool
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100500 + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
501 + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400502
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100503 priv->apTD1Rings = vir_pool
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100504 + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
505 + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc)
506 + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
Forest Bond5449c682009-04-25 10:30:44 -0400507
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100508 priv->tx1_bufs = priv->tx0_bufs +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100509 priv->opts.tx_descs[0] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400510
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100511 priv->tx_beacon_bufs = priv->tx1_bufs +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100512 priv->opts.tx_descs[1] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400513
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100514 priv->pbyTmpBuff = priv->tx_beacon_bufs +
Joe Perches915006c2013-03-18 10:44:47 -0700515 CB_BEACON_BUF_SIZE;
Forest Bond5449c682009-04-25 10:30:44 -0400516
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100517 priv->tx_bufs_dma1 = priv->tx_bufs_dma0 +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100518 priv->opts.tx_descs[0] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400519
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100520 priv->tx_beacon_dma = priv->tx_bufs_dma1 +
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100521 priv->opts.tx_descs[1] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400522
Joe Perches915006c2013-03-18 10:44:47 -0700523 return true;
Forest Bond5449c682009-04-25 10:30:44 -0400524}
525
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100526static void device_free_rings(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200527{
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100528 dma_free_coherent(&priv->pcid->dev,
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100529 priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
530 priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
531 priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
532 priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100533 priv->aRD0Ring, priv->pool_dma);
Forest Bond5449c682009-04-25 10:30:44 -0400534
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100535 if (priv->tx0_bufs)
536 dma_free_coherent(&priv->pcid->dev,
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100537 priv->opts.tx_descs[0] * PKT_BUF_SZ +
538 priv->opts.tx_descs[1] * PKT_BUF_SZ +
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100539 CB_BEACON_BUF_SIZE +
540 CB_MAX_BUF_SIZE,
541 priv->tx0_bufs, priv->tx_bufs_dma0);
Forest Bond5449c682009-04-25 10:30:44 -0400542}
543
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100544static void device_init_rd0_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200545{
Joe Perches915006c2013-03-18 10:44:47 -0700546 int i;
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100547 dma_addr_t curr = priv->rd0_pool_dma;
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100548 struct vnt_rx_desc *desc;
Forest Bond5449c682009-04-25 10:30:44 -0400549
Joe Perches915006c2013-03-18 10:44:47 -0700550 /* Init the RD0 ring entries */
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100551 for (i = 0; i < priv->opts.rx_descs0;
Malcolm Priestley9cb693f2015-08-15 21:57:35 +0100552 i ++, curr += sizeof(struct vnt_rx_desc)) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100553 desc = &priv->aRD0Ring[i];
Malcolm Priestleye06cf9a2015-10-17 11:32:59 +0100554 desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_ATOMIC);
Malcolm Priestley217ed3a2015-07-22 19:16:33 +0100555
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100556 if (!device_alloc_rx_buf(priv, desc))
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100557 dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100558
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100559 desc->next = &(priv->aRD0Ring[(i+1) % priv->opts.rx_descs0]);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100560 desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
Joe Perches915006c2013-03-18 10:44:47 -0700561 }
Forest Bond5449c682009-04-25 10:30:44 -0400562
Joe Perches915006c2013-03-18 10:44:47 -0700563 if (i > 0)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100564 priv->aRD0Ring[i-1].next_desc = cpu_to_le32(priv->rd0_pool_dma);
565 priv->pCurrRD[0] = &priv->aRD0Ring[0];
Forest Bond5449c682009-04-25 10:30:44 -0400566}
567
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100568static void device_init_rd1_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200569{
Joe Perches915006c2013-03-18 10:44:47 -0700570 int i;
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100571 dma_addr_t curr = priv->rd1_pool_dma;
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100572 struct vnt_rx_desc *desc;
Forest Bond5449c682009-04-25 10:30:44 -0400573
Joe Perches915006c2013-03-18 10:44:47 -0700574 /* Init the RD1 ring entries */
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100575 for (i = 0; i < priv->opts.rx_descs1;
Malcolm Priestley9cb693f2015-08-15 21:57:35 +0100576 i ++, curr += sizeof(struct vnt_rx_desc)) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100577 desc = &priv->aRD1Ring[i];
Malcolm Priestleye06cf9a2015-10-17 11:32:59 +0100578 desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_ATOMIC);
Malcolm Priestley217ed3a2015-07-22 19:16:33 +0100579
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100580 if (!device_alloc_rx_buf(priv, desc))
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100581 dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100582
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100583 desc->next = &(priv->aRD1Ring[(i+1) % priv->opts.rx_descs1]);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100584 desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
Joe Perches915006c2013-03-18 10:44:47 -0700585 }
Forest Bond5449c682009-04-25 10:30:44 -0400586
Joe Perches915006c2013-03-18 10:44:47 -0700587 if (i > 0)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100588 priv->aRD1Ring[i-1].next_desc = cpu_to_le32(priv->rd1_pool_dma);
589 priv->pCurrRD[1] = &priv->aRD1Ring[0];
Forest Bond5449c682009-04-25 10:30:44 -0400590}
591
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100592static void device_free_rd0_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200593{
Joe Perches915006c2013-03-18 10:44:47 -0700594 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400595
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100596 for (i = 0; i < priv->opts.rx_descs0; i++) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100597 struct vnt_rx_desc *desc = &(priv->aRD0Ring[i]);
598 struct vnt_rd_info *rd_info = desc->rd_info;
Forest Bond5449c682009-04-25 10:30:44 -0400599
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100600 dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
601 priv->rx_buf_sz, DMA_FROM_DEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400602
Malcolm Priestley88defe22015-08-15 21:57:34 +0100603 dev_kfree_skb(rd_info->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400604
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100605 kfree(desc->rd_info);
Joe Perches915006c2013-03-18 10:44:47 -0700606 }
Forest Bond5449c682009-04-25 10:30:44 -0400607}
608
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100609static void device_free_rd1_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200610{
Joe Perches915006c2013-03-18 10:44:47 -0700611 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400612
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100613 for (i = 0; i < priv->opts.rx_descs1; i++) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100614 struct vnt_rx_desc *desc = &priv->aRD1Ring[i];
615 struct vnt_rd_info *rd_info = desc->rd_info;
Forest Bond5449c682009-04-25 10:30:44 -0400616
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100617 dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
618 priv->rx_buf_sz, DMA_FROM_DEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400619
Malcolm Priestley88defe22015-08-15 21:57:34 +0100620 dev_kfree_skb(rd_info->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400621
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100622 kfree(desc->rd_info);
Joe Perches915006c2013-03-18 10:44:47 -0700623 }
Forest Bond5449c682009-04-25 10:30:44 -0400624}
625
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100626static void device_init_td0_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200627{
Joe Perches915006c2013-03-18 10:44:47 -0700628 int i;
629 dma_addr_t curr;
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100630 struct vnt_tx_desc *desc;
Forest Bond5449c682009-04-25 10:30:44 -0400631
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100632 curr = priv->td0_pool_dma;
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100633 for (i = 0; i < priv->opts.tx_descs[0];
Malcolm Priestleye2357272015-08-14 22:58:51 +0100634 i++, curr += sizeof(struct vnt_tx_desc)) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100635 desc = &priv->apTD0Rings[i];
Malcolm Priestley068b9982015-10-17 11:33:00 +0100636 desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_ATOMIC);
Malcolm Priestley217ed3a2015-07-22 19:16:33 +0100637
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100638 desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ;
639 desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ;
Malcolm Priestley319755a2015-09-12 19:10:30 +0100640
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100641 desc->next = &(priv->apTD0Rings[(i+1) % priv->opts.tx_descs[0]]);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100642 desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
Joe Perches915006c2013-03-18 10:44:47 -0700643 }
Forest Bond5449c682009-04-25 10:30:44 -0400644
Joe Perches915006c2013-03-18 10:44:47 -0700645 if (i > 0)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100646 priv->apTD0Rings[i-1].next_desc = cpu_to_le32(priv->td0_pool_dma);
647 priv->apTailTD[0] = priv->apCurrTD[0] = &priv->apTD0Rings[0];
Forest Bond5449c682009-04-25 10:30:44 -0400648}
649
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100650static void device_init_td1_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200651{
Joe Perches915006c2013-03-18 10:44:47 -0700652 int i;
653 dma_addr_t curr;
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100654 struct vnt_tx_desc *desc;
Forest Bond5449c682009-04-25 10:30:44 -0400655
Joe Perches915006c2013-03-18 10:44:47 -0700656 /* Init the TD ring entries */
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100657 curr = priv->td1_pool_dma;
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100658 for (i = 0; i < priv->opts.tx_descs[1];
Malcolm Priestleye2357272015-08-14 22:58:51 +0100659 i++, curr += sizeof(struct vnt_tx_desc)) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100660 desc = &priv->apTD1Rings[i];
Malcolm Priestley068b9982015-10-17 11:33:00 +0100661 desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_ATOMIC);
Malcolm Priestley217ed3a2015-07-22 19:16:33 +0100662
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100663 desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ;
664 desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ;
Malcolm Priestley319755a2015-09-12 19:10:30 +0100665
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100666 desc->next = &(priv->apTD1Rings[(i + 1) % priv->opts.tx_descs[1]]);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100667 desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
Joe Perches915006c2013-03-18 10:44:47 -0700668 }
Forest Bond5449c682009-04-25 10:30:44 -0400669
Joe Perches915006c2013-03-18 10:44:47 -0700670 if (i > 0)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100671 priv->apTD1Rings[i-1].next_desc = cpu_to_le32(priv->td1_pool_dma);
672 priv->apTailTD[1] = priv->apCurrTD[1] = &priv->apTD1Rings[0];
Forest Bond5449c682009-04-25 10:30:44 -0400673}
674
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100675static void device_free_td0_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200676{
Joe Perches915006c2013-03-18 10:44:47 -0700677 int i;
Guillaume Clement6b711272014-07-25 01:06:16 +0200678
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100679 for (i = 0; i < priv->opts.tx_descs[0]; i++) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100680 struct vnt_tx_desc *desc = &priv->apTD0Rings[i];
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100681 struct vnt_td_info *td_info = desc->td_info;
Forest Bond5449c682009-04-25 10:30:44 -0400682
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100683 dev_kfree_skb(td_info->skb);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100684 kfree(desc->td_info);
Joe Perches915006c2013-03-18 10:44:47 -0700685 }
Forest Bond5449c682009-04-25 10:30:44 -0400686}
687
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100688static void device_free_td1_ring(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200689{
Joe Perches915006c2013-03-18 10:44:47 -0700690 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400691
Malcolm Priestleybc667b92015-10-17 11:33:01 +0100692 for (i = 0; i < priv->opts.tx_descs[1]; i++) {
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100693 struct vnt_tx_desc *desc = &priv->apTD1Rings[i];
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100694 struct vnt_td_info *td_info = desc->td_info;
Forest Bond5449c682009-04-25 10:30:44 -0400695
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100696 dev_kfree_skb(td_info->skb);
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100697 kfree(desc->td_info);
Joe Perches915006c2013-03-18 10:44:47 -0700698 }
Forest Bond5449c682009-04-25 10:30:44 -0400699}
700
Forest Bond5449c682009-04-25 10:30:44 -0400701/*-----------------------------------------------------------------*/
702
Malcolm Priestley0924a892015-10-17 11:32:54 +0100703static int device_rx_srv(struct vnt_private *priv, unsigned int idx)
Guillaume Clement84b50762014-07-25 01:06:18 +0200704{
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100705 struct vnt_rx_desc *rd;
Joe Perches915006c2013-03-18 10:44:47 -0700706 int works = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400707
Malcolm Priestley0924a892015-10-17 11:32:54 +0100708 for (rd = priv->pCurrRD[idx];
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100709 rd->rd0.owner == OWNED_BY_HOST;
710 rd = rd->next) {
Joe Perches915006c2013-03-18 10:44:47 -0700711 if (works++ > 15)
712 break;
Malcolm Priestleyb5eeed82015-05-31 10:35:28 +0100713
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100714 if (!rd->rd_info->skb)
Malcolm Priestleyb5eeed82015-05-31 10:35:28 +0100715 break;
716
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100717 if (vnt_receive_frame(priv, rd)) {
718 if (!device_alloc_rx_buf(priv, rd)) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100719 dev_err(&priv->pcid->dev,
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100720 "can not allocate rx buf\n");
Joe Perches915006c2013-03-18 10:44:47 -0700721 break;
722 }
723 }
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100724 rd->rd0.owner = OWNED_BY_NIC;
Joe Perches915006c2013-03-18 10:44:47 -0700725 }
Forest Bond5449c682009-04-25 10:30:44 -0400726
Malcolm Priestley0924a892015-10-17 11:32:54 +0100727 priv->pCurrRD[idx] = rd;
Forest Bond5449c682009-04-25 10:30:44 -0400728
Joe Perches915006c2013-03-18 10:44:47 -0700729 return works;
Forest Bond5449c682009-04-25 10:30:44 -0400730}
731
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100732static bool device_alloc_rx_buf(struct vnt_private *priv,
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100733 struct vnt_rx_desc *rd)
Guillaume Clement84b50762014-07-25 01:06:18 +0200734{
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100735 struct vnt_rd_info *rd_info = rd->rd_info;
Forest Bond5449c682009-04-25 10:30:44 -0400736
Malcolm Priestley5e011b42015-10-03 20:30:24 +0100737 rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz);
Namrata A Shettar8f4166d2016-09-18 14:35:13 +0530738 if (!rd_info->skb)
Joe Perches915006c2013-03-18 10:44:47 -0700739 return false;
Malcolm Priestley33b1c8c2014-10-29 17:43:36 +0000740
Malcolm Priestley5e011b42015-10-03 20:30:24 +0100741 rd_info->skb_dma =
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100742 dma_map_single(&priv->pcid->dev,
Malcolm Priestley5e011b42015-10-03 20:30:24 +0100743 skb_put(rd_info->skb, skb_tailroom(rd_info->skb)),
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100744 priv->rx_buf_sz, DMA_FROM_DEVICE);
Haneen Mohammed2fbf6d62016-02-11 21:34:40 +0300745 if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) {
746 dev_kfree_skb(rd_info->skb);
747 rd_info->skb = NULL;
748 return false;
749 }
Malcolm Priestley33b1c8c2014-10-29 17:43:36 +0000750
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100751 *((unsigned int *)&rd->rd0) = 0; /* FIX cast */
Forest Bond5449c682009-04-25 10:30:44 -0400752
Malcolm Priestley480fc5b2015-10-03 20:30:25 +0100753 rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
754 rd->rd0.owner = OWNED_BY_NIC;
755 rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
756 rd->buff_addr = cpu_to_le32(rd_info->skb_dma);
Forest Bond5449c682009-04-25 10:30:44 -0400757
Joe Perches915006c2013-03-18 10:44:47 -0700758 return true;
Forest Bond5449c682009-04-25 10:30:44 -0400759}
760
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000761static const u8 fallback_rate0[5][5] = {
762 {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
763 {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
764 {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
765 {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
766 {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
767};
768
769static const u8 fallback_rate1[5][5] = {
770 {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
771 {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
772 {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
773 {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
774 {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
775};
776
777static int vnt_int_report_rate(struct vnt_private *priv,
Malcolm Priestley54382852015-08-14 22:58:50 +0100778 struct vnt_td_info *context, u8 tsr0, u8 tsr1)
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000779{
780 struct vnt_tx_fifo_head *fifo_head;
781 struct ieee80211_tx_info *info;
782 struct ieee80211_rate *rate;
783 u16 fb_option;
784 u8 tx_retry = (tsr0 & TSR0_NCR);
785 s8 idx;
786
787 if (!context)
788 return -ENOMEM;
789
790 if (!context->skb)
791 return -EINVAL;
792
793 fifo_head = (struct vnt_tx_fifo_head *)context->buf;
794 fb_option = (le16_to_cpu(fifo_head->fifo_ctl) &
795 (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1));
796
797 info = IEEE80211_SKB_CB(context->skb);
798 idx = info->control.rates[0].idx;
799
800 if (fb_option && !(tsr1 & TSR1_TERR)) {
801 u8 tx_rate;
802 u8 retry = tx_retry;
803
804 rate = ieee80211_get_tx_rate(priv->hw, info);
805 tx_rate = rate->hw_value - RATE_18M;
806
807 if (retry > 4)
808 retry = 4;
809
810 if (fb_option & FIFOCTL_AUTO_FB_0)
811 tx_rate = fallback_rate0[tx_rate][retry];
812 else if (fb_option & FIFOCTL_AUTO_FB_1)
813 tx_rate = fallback_rate1[tx_rate][retry];
814
Johannes Berg57fbcce2016-04-12 15:56:15 +0200815 if (info->band == NL80211_BAND_5GHZ)
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000816 idx = tx_rate - RATE_6M;
817 else
818 idx = tx_rate;
819 }
820
821 ieee80211_tx_info_clear_status(info);
822
823 info->status.rates[0].count = tx_retry;
824
825 if (!(tsr1 & TSR1_TERR)) {
826 info->status.rates[0].idx = idx;
Malcolm Priestley6e44dc42015-04-09 20:53:44 +0100827
828 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
829 info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
830 else
831 info->flags |= IEEE80211_TX_STAT_ACK;
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000832 }
833
834 return 0;
835}
836
Malcolm Priestley0924a892015-10-17 11:32:54 +0100837static int device_tx_srv(struct vnt_private *priv, unsigned int idx)
Guillaume Clement84b50762014-07-25 01:06:18 +0200838{
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100839 struct vnt_tx_desc *desc;
Joe Perches915006c2013-03-18 10:44:47 -0700840 int works = 0;
841 unsigned char byTsr0;
842 unsigned char byTsr1;
Forest Bond5449c682009-04-25 10:30:44 -0400843
Malcolm Priestley0924a892015-10-17 11:32:54 +0100844 for (desc = priv->apTailTD[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) {
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100845 if (desc->td0.owner == OWNED_BY_NIC)
Joe Perches915006c2013-03-18 10:44:47 -0700846 break;
847 if (works++ > 15)
848 break;
Forest Bond5449c682009-04-25 10:30:44 -0400849
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100850 byTsr0 = desc->td0.tsr0;
851 byTsr1 = desc->td0.tsr1;
Forest Bond5449c682009-04-25 10:30:44 -0400852
Alex W Slaterbb72dd52015-02-26 20:09:26 +0000853 /* Only the status of first TD in the chain is correct */
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100854 if (desc->td1.tcr & TCR_STP) {
855 if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) {
Joe Perches915006c2013-03-18 10:44:47 -0700856 if (!(byTsr1 & TSR1_TERR)) {
857 if (byTsr0 != 0) {
Joe Perches48caf5a2014-08-17 09:17:04 -0700858 pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
Malcolm Priestley0924a892015-10-17 11:32:54 +0100859 (int)idx, byTsr1,
Joe Perches48caf5a2014-08-17 09:17:04 -0700860 byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -0700861 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700862 } else {
Joe Perches48caf5a2014-08-17 09:17:04 -0700863 pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n",
Malcolm Priestley0924a892015-10-17 11:32:54 +0100864 (int)idx, byTsr1, byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -0700865 }
866 }
Forest Bond5449c682009-04-25 10:30:44 -0400867
Joe Perches915006c2013-03-18 10:44:47 -0700868 if (byTsr1 & TSR1_TERR) {
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100869 if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) {
Joe Perches48caf5a2014-08-17 09:17:04 -0700870 pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
Malcolm Priestley0924a892015-10-17 11:32:54 +0100871 (int)idx, byTsr1, byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -0700872 }
Joe Perches915006c2013-03-18 10:44:47 -0700873 }
Malcolm Priestleyad3fee92015-04-11 20:29:41 +0100874
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100875 vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1);
Malcolm Priestleyad3fee92015-04-11 20:29:41 +0100876
Malcolm Priestley9f31b692015-10-03 20:30:27 +0100877 device_free_tx_buf(priv, desc);
Malcolm Priestley0924a892015-10-17 11:32:54 +0100878 priv->iTDUsed[idx]--;
Joe Perches915006c2013-03-18 10:44:47 -0700879 }
880 }
Forest Bond5449c682009-04-25 10:30:44 -0400881
Malcolm Priestley0924a892015-10-17 11:32:54 +0100882 priv->apTailTD[idx] = desc;
Forest Bond5449c682009-04-25 10:30:44 -0400883
Joe Perches915006c2013-03-18 10:44:47 -0700884 return works;
Forest Bond5449c682009-04-25 10:30:44 -0400885}
886
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100887static void device_error(struct vnt_private *priv, unsigned short status)
Guillaume Clement84b50762014-07-25 01:06:18 +0200888{
Joe Perches915006c2013-03-18 10:44:47 -0700889 if (status & ISR_FETALERR) {
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100890 dev_err(&priv->pcid->dev, "Hardware fatal error\n");
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100891
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +0000892 MACbShutdown(priv);
Joe Perches915006c2013-03-18 10:44:47 -0700893 return;
894 }
Forest Bond5449c682009-04-25 10:30:44 -0400895}
896
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100897static void device_free_tx_buf(struct vnt_private *priv,
Malcolm Priestley5e76c8f2015-10-03 20:30:23 +0100898 struct vnt_tx_desc *desc)
Guillaume Clement84b50762014-07-25 01:06:18 +0200899{
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100900 struct vnt_td_info *td_info = desc->td_info;
901 struct sk_buff *skb = td_info->skb;
Forest Bond5449c682009-04-25 10:30:44 -0400902
Malcolm Priestley3fa09172015-04-09 20:53:43 +0100903 if (skb)
Malcolm Priestley78e0e852015-10-03 20:30:22 +0100904 ieee80211_tx_status_irqsafe(priv->hw, skb);
Forest Bond5449c682009-04-25 10:30:44 -0400905
Malcolm Priestley12f2ee32015-10-03 20:30:26 +0100906 td_info->skb = NULL;
907 td_info->flags = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400908}
909
Malcolm Priestley64e4fd52015-02-01 11:59:39 +0000910static void vnt_check_bb_vga(struct vnt_private *priv)
911{
912 long dbm;
913 int i;
914
915 if (!priv->bUpdateBBVGA)
916 return;
917
918 if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
919 return;
920
921 if (!(priv->vif->bss_conf.assoc && priv->uCurrRSSI))
922 return;
923
924 RFvRSSITodBm(priv, (u8)priv->uCurrRSSI, &dbm);
925
926 for (i = 0; i < BB_VGA_LEVEL; i++) {
927 if (dbm < priv->ldBmThreshold[i]) {
928 priv->byBBVGANew = priv->abyBBVGA[i];
929 break;
930 }
931 }
932
933 if (priv->byBBVGANew == priv->byBBVGACurrent) {
934 priv->uBBVGADiffCount = 1;
935 return;
936 }
937
938 priv->uBBVGADiffCount++;
939
940 if (priv->uBBVGADiffCount == 1) {
941 /* first VGA diff gain */
942 BBvSetVGAGainOffset(priv, priv->byBBVGANew);
943
944 dev_dbg(&priv->pcid->dev,
945 "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
946 (int)dbm, priv->byBBVGANew,
947 priv->byBBVGACurrent,
948 (int)priv->uBBVGADiffCount);
949 }
950
951 if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
952 dev_dbg(&priv->pcid->dev,
953 "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
954 (int)dbm, priv->byBBVGANew,
955 priv->byBBVGACurrent,
956 (int)priv->uBBVGADiffCount);
957
958 BBvSetVGAGainOffset(priv, priv->byBBVGANew);
959 }
960}
961
Malcolm Priestley2995dfe2015-05-31 10:35:26 +0100962static void vnt_interrupt_process(struct vnt_private *priv)
Guillaume Clement84b50762014-07-25 01:06:18 +0200963{
Malcolm Priestley2995dfe2015-05-31 10:35:26 +0100964 struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
Joe Perches915006c2013-03-18 10:44:47 -0700965 int max_count = 0;
Malcolm Priestley700f6c02015-05-31 10:35:20 +0100966 u32 mib_counter;
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +0100967 u32 isr;
Malcolm Priestley6cff1f62014-07-23 21:35:11 +0100968 unsigned long flags;
Forest Bond5449c682009-04-25 10:30:44 -0400969
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +0100970 MACvReadISR(priv->PortOffset, &isr);
Forest Bond5449c682009-04-25 10:30:44 -0400971
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +0100972 if (isr == 0)
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +0100973 return;
Forest Bond5449c682009-04-25 10:30:44 -0400974
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +0100975 if (isr == 0xffffffff) {
976 pr_debug("isr = 0xffff\n");
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +0100977 return;
Joe Perches915006c2013-03-18 10:44:47 -0700978 }
Forest Bond5449c682009-04-25 10:30:44 -0400979
Malcolm Priestley2995dfe2015-05-31 10:35:26 +0100980 MACvIntDisable(priv->PortOffset);
Malcolm Priestley6cff1f62014-07-23 21:35:11 +0100981
Malcolm Priestley2995dfe2015-05-31 10:35:26 +0100982 spin_lock_irqsave(&priv->lock, flags);
Forest Bond5449c682009-04-25 10:30:44 -0400983
Malcolm Priestley700f6c02015-05-31 10:35:20 +0100984 /* Read low level stats */
Malcolm Priestley2995dfe2015-05-31 10:35:26 +0100985 MACvReadMIBCounter(priv->PortOffset, &mib_counter);
Forest Bond5449c682009-04-25 10:30:44 -0400986
Malcolm Priestley700f6c02015-05-31 10:35:20 +0100987 low_stats->dot11RTSSuccessCount += mib_counter & 0xff;
988 low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff;
989 low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff;
990 low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff;
991
Alex W Slaterbb72dd52015-02-26 20:09:26 +0000992 /*
993 * TBD....
994 * Must do this after doing rx/tx, cause ISR bit is slow
995 * than RD/TD write back
996 * update ISR counter
997 */
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +0100998 while (isr && priv->vif) {
999 MACvWriteISR(priv->PortOffset, isr);
Forest Bond5449c682009-04-25 10:30:44 -04001000
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001001 if (isr & ISR_FETALERR) {
Joe Perches48caf5a2014-08-17 09:17:04 -07001002 pr_debug(" ISR_FETALERR\n");
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001003 VNSvOutPortB(priv->PortOffset + MAC_REG_SOFTPWRCTL, 0);
1004 VNSvOutPortW(priv->PortOffset +
1005 MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001006 device_error(priv, isr);
Joe Perches915006c2013-03-18 10:44:47 -07001007 }
Forest Bond5449c682009-04-25 10:30:44 -04001008
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001009 if (isr & ISR_TBTT) {
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001010 if (priv->op_mode != NL80211_IFTYPE_ADHOC)
1011 vnt_check_bb_vga(priv);
Forest Bond5449c682009-04-25 10:30:44 -04001012
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001013 priv->bBeaconSent = false;
1014 if (priv->bEnablePSMode)
1015 PSbIsNextTBTTWakeUp((void *)priv);
Forest Bond5449c682009-04-25 10:30:44 -04001016
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001017 if ((priv->op_mode == NL80211_IFTYPE_AP ||
1018 priv->op_mode == NL80211_IFTYPE_ADHOC) &&
1019 priv->vif->bss_conf.enable_beacon) {
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +00001020 MACvOneShotTimer1MicroSec(priv,
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001021 (priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10);
Joe Perches915006c2013-03-18 10:44:47 -07001022 }
Forest Bond5449c682009-04-25 10:30:44 -04001023
Guido Martínez4e8a7e52014-04-19 16:44:59 -03001024 /* TODO: adhoc PS mode */
Forest Bond5449c682009-04-25 10:30:44 -04001025
Joe Perches915006c2013-03-18 10:44:47 -07001026 }
Forest Bond5449c682009-04-25 10:30:44 -04001027
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001028 if (isr & ISR_BNTX) {
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001029 if (priv->op_mode == NL80211_IFTYPE_ADHOC) {
1030 priv->bIsBeaconBufReadySet = false;
1031 priv->cbBeaconBufReadySetCnt = 0;
Joe Perches915006c2013-03-18 10:44:47 -07001032 }
Forest Bond5449c682009-04-25 10:30:44 -04001033
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001034 priv->bBeaconSent = true;
Joe Perches915006c2013-03-18 10:44:47 -07001035 }
Forest Bond5449c682009-04-25 10:30:44 -04001036
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001037 if (isr & ISR_RXDMA0)
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001038 max_count += device_rx_srv(priv, TYPE_RXDMA0);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001039
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001040 if (isr & ISR_RXDMA1)
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001041 max_count += device_rx_srv(priv, TYPE_RXDMA1);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001042
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001043 if (isr & ISR_TXDMA0)
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001044 max_count += device_tx_srv(priv, TYPE_TXDMA0);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001045
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001046 if (isr & ISR_AC0DMA)
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001047 max_count += device_tx_srv(priv, TYPE_AC0DMA);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001048
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001049 if (isr & ISR_SOFTTIMER1) {
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001050 if (priv->vif->bss_conf.enable_beacon)
1051 vnt_beacon_make(priv, priv->vif);
Joe Perches915006c2013-03-18 10:44:47 -07001052 }
Forest Bond5449c682009-04-25 10:30:44 -04001053
Malcolm Priestley54fbb2d2014-11-04 14:49:46 +00001054 /* If both buffers available wake the queue */
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001055 if (AVAIL_TD(priv, TYPE_TXDMA0) &&
1056 AVAIL_TD(priv, TYPE_AC0DMA) &&
1057 ieee80211_queue_stopped(priv->hw, 0))
1058 ieee80211_wake_queues(priv->hw);
Malcolm Priestley54fbb2d2014-11-04 14:49:46 +00001059
Malcolm Priestley41b9e5e2015-05-31 10:35:27 +01001060 MACvReadISR(priv->PortOffset, &isr);
Forest Bond5449c682009-04-25 10:30:44 -04001061
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001062 MACvReceive0(priv->PortOffset);
1063 MACvReceive1(priv->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -04001064
Malcolm Priestleybc667b92015-10-17 11:33:01 +01001065 if (max_count > priv->opts.int_works)
Joe Perches915006c2013-03-18 10:44:47 -07001066 break;
1067 }
Forest Bond5449c682009-04-25 10:30:44 -04001068
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001069 spin_unlock_irqrestore(&priv->lock, flags);
Forest Bond5449c682009-04-25 10:30:44 -04001070
Malcolm Priestley2995dfe2015-05-31 10:35:26 +01001071 MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE);
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +01001072}
Malcolm Priestley6cff1f62014-07-23 21:35:11 +01001073
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +01001074static void vnt_interrupt_work(struct work_struct *work)
1075{
1076 struct vnt_private *priv =
1077 container_of(work, struct vnt_private, interrupt_work);
Forest Bond5449c682009-04-25 10:30:44 -04001078
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +01001079 if (priv->vif)
1080 vnt_interrupt_process(priv);
1081}
1082
1083static irqreturn_t vnt_interrupt(int irq, void *arg)
1084{
1085 struct vnt_private *priv = arg;
1086
1087 if (priv->vif)
1088 schedule_work(&priv->interrupt_work);
1089
1090 return IRQ_HANDLED;
Forest Bond5449c682009-04-25 10:30:44 -04001091}
1092
Malcolm Priestley67013f22014-10-29 17:43:43 +00001093static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
1094{
1095 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Malcolm Priestleye2357272015-08-14 22:58:51 +01001096 struct vnt_tx_desc *head_td;
Malcolm Priestleyc3125302015-02-09 19:11:33 +00001097 u32 dma_idx;
Malcolm Priestley67013f22014-10-29 17:43:43 +00001098 unsigned long flags;
1099
1100 spin_lock_irqsave(&priv->lock, flags);
1101
Malcolm Priestleyc3125302015-02-09 19:11:33 +00001102 if (ieee80211_is_data(hdr->frame_control))
1103 dma_idx = TYPE_AC0DMA;
1104 else
Malcolm Priestley67013f22014-10-29 17:43:43 +00001105 dma_idx = TYPE_TXDMA0;
1106
1107 if (AVAIL_TD(priv, dma_idx) < 1) {
1108 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestley113d6dc2015-09-27 09:17:39 +01001109 ieee80211_stop_queues(priv->hw);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001110 return -ENOMEM;
1111 }
1112
1113 head_td = priv->apCurrTD[dma_idx];
1114
Malcolm Priestley9cc8eac2015-08-14 22:58:47 +01001115 head_td->td1.tcr = 0;
Malcolm Priestley67013f22014-10-29 17:43:43 +00001116
Malcolm Priestley54382852015-08-14 22:58:50 +01001117 head_td->td_info->skb = skb;
Malcolm Priestley67013f22014-10-29 17:43:43 +00001118
Malcolm Priestleyc3125302015-02-09 19:11:33 +00001119 if (dma_idx == TYPE_AC0DMA)
Malcolm Priestley54382852015-08-14 22:58:50 +01001120 head_td->td_info->flags = TD_FLAGS_NETIF_SKB;
Malcolm Priestleyc3125302015-02-09 19:11:33 +00001121
Malcolm Priestley67013f22014-10-29 17:43:43 +00001122 priv->apCurrTD[dma_idx] = head_td->next;
1123
1124 spin_unlock_irqrestore(&priv->lock, flags);
1125
1126 vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
1127
Malcolm Priestley67013f22014-10-29 17:43:43 +00001128 spin_lock_irqsave(&priv->lock, flags);
1129
1130 priv->bPWBitOn = false;
1131
Malcolm Priestleyb5745292014-12-21 12:56:34 +00001132 /* Set TSR1 & ReqCount in TxDescHead */
Malcolm Priestley9cc8eac2015-08-14 22:58:47 +01001133 head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU);
Malcolm Priestley54382852015-08-14 22:58:50 +01001134 head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count);
Malcolm Priestleyb5745292014-12-21 12:56:34 +00001135
Malcolm Priestley54382852015-08-14 22:58:50 +01001136 head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma);
Malcolm Priestley187e2a82015-02-01 11:59:38 +00001137
Malcolm Priestleyd65d2b252015-04-21 22:33:00 +01001138 /* Poll Transmit the adapter */
1139 wmb();
Malcolm Priestley5235ff62015-08-14 22:58:46 +01001140 head_td->td0.owner = OWNED_BY_NIC;
Malcolm Priestleyd65d2b252015-04-21 22:33:00 +01001141 wmb(); /* second memory barrier */
1142
Malcolm Priestley54382852015-08-14 22:58:50 +01001143 if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
Malcolm Priestley67013f22014-10-29 17:43:43 +00001144 MACvTransmitAC0(priv->PortOffset);
Malcolm Priestleyc3125302015-02-09 19:11:33 +00001145 else
Malcolm Priestley67013f22014-10-29 17:43:43 +00001146 MACvTransmit0(priv->PortOffset);
1147
Malcolm Priestleyd65d2b252015-04-21 22:33:00 +01001148 priv->iTDUsed[dma_idx]++;
1149
Malcolm Priestley67013f22014-10-29 17:43:43 +00001150 spin_unlock_irqrestore(&priv->lock, flags);
1151
1152 return 0;
1153}
1154
1155static void vnt_tx_80211(struct ieee80211_hw *hw,
1156 struct ieee80211_tx_control *control,
1157 struct sk_buff *skb)
1158{
1159 struct vnt_private *priv = hw->priv;
1160
Malcolm Priestley113d6dc2015-09-27 09:17:39 +01001161 if (vnt_tx_packet(priv, skb))
Malcolm Priestley67013f22014-10-29 17:43:43 +00001162 ieee80211_free_txskb(hw, skb);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001163}
1164
1165static int vnt_start(struct ieee80211_hw *hw)
1166{
1167 struct vnt_private *priv = hw->priv;
1168 int ret;
1169
1170 priv->rx_buf_sz = PKT_BUF_SZ;
1171 if (!device_init_rings(priv))
1172 return -ENOMEM;
1173
Sandhya Bankar50aefc12016-03-06 12:43:27 +05301174 ret = request_irq(priv->pcid->irq, vnt_interrupt,
Malcolm Priestley67013f22014-10-29 17:43:43 +00001175 IRQF_SHARED, "vt6655", priv);
1176 if (ret) {
1177 dev_dbg(&priv->pcid->dev, "failed to start irq\n");
1178 return ret;
1179 }
1180
1181 dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n");
1182 device_init_rd0_ring(priv);
1183 device_init_rd1_ring(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001184 device_init_td0_ring(priv);
1185 device_init_td1_ring(priv);
1186
1187 device_init_registers(priv);
1188
1189 dev_dbg(&priv->pcid->dev, "call MACvIntEnable\n");
1190 MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE);
1191
1192 ieee80211_wake_queues(hw);
1193
1194 return 0;
1195}
1196
1197static void vnt_stop(struct ieee80211_hw *hw)
1198{
1199 struct vnt_private *priv = hw->priv;
1200
1201 ieee80211_stop_queues(hw);
1202
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +01001203 cancel_work_sync(&priv->interrupt_work);
1204
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +00001205 MACbShutdown(priv);
1206 MACbSoftwareReset(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001207 CARDbRadioPowerOff(priv);
1208
1209 device_free_td0_ring(priv);
1210 device_free_td1_ring(priv);
1211 device_free_rd0_ring(priv);
1212 device_free_rd1_ring(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001213 device_free_rings(priv);
1214
1215 free_irq(priv->pcid->irq, priv);
1216}
1217
1218static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1219{
1220 struct vnt_private *priv = hw->priv;
1221
1222 priv->vif = vif;
1223
1224 switch (vif->type) {
1225 case NL80211_IFTYPE_STATION:
Malcolm Priestley67013f22014-10-29 17:43:43 +00001226 break;
1227 case NL80211_IFTYPE_ADHOC:
1228 MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST);
1229
1230 MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
1231
1232 break;
1233 case NL80211_IFTYPE_AP:
1234 MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST);
1235
1236 MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
1237
1238 break;
1239 default:
1240 return -EOPNOTSUPP;
1241 }
1242
1243 priv->op_mode = vif->type;
1244
1245 return 0;
1246}
1247
1248static void vnt_remove_interface(struct ieee80211_hw *hw,
1249 struct ieee80211_vif *vif)
1250{
1251 struct vnt_private *priv = hw->priv;
1252
1253 switch (vif->type) {
1254 case NL80211_IFTYPE_STATION:
Malcolm Priestley67013f22014-10-29 17:43:43 +00001255 break;
1256 case NL80211_IFTYPE_ADHOC:
1257 MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
1258 MACvRegBitsOff(priv->PortOffset,
1259 MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1260 MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
1261 break;
1262 case NL80211_IFTYPE_AP:
1263 MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
1264 MACvRegBitsOff(priv->PortOffset,
1265 MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1266 MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
1267 break;
1268 default:
1269 break;
1270 }
1271
1272 priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
1273}
1274
1275
1276static int vnt_config(struct ieee80211_hw *hw, u32 changed)
1277{
1278 struct vnt_private *priv = hw->priv;
1279 struct ieee80211_conf *conf = &hw->conf;
1280 u8 bb_type;
1281
1282 if (changed & IEEE80211_CONF_CHANGE_PS) {
1283 if (conf->flags & IEEE80211_CONF_PS)
1284 PSvEnablePowerSaving(priv, conf->listen_interval);
1285 else
1286 PSvDisablePowerSaving(priv);
1287 }
1288
1289 if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
1290 (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
Malcolm Priestleyd7a4cfa2015-01-19 18:24:10 +00001291 set_channel(priv, conf->chandef.chan);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001292
Johannes Berg57fbcce2016-04-12 15:56:15 +02001293 if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
Malcolm Priestley67013f22014-10-29 17:43:43 +00001294 bb_type = BB_TYPE_11A;
1295 else
1296 bb_type = BB_TYPE_11G;
1297
1298 if (priv->byBBType != bb_type) {
1299 priv->byBBType = bb_type;
1300
Malcolm Priestleybfb6c862014-11-07 19:06:06 +00001301 CARDbSetPhyParameter(priv, priv->byBBType);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001302 }
1303 }
1304
1305 if (changed & IEEE80211_CONF_CHANGE_POWER) {
1306 if (priv->byBBType == BB_TYPE_11B)
1307 priv->wCurrentRate = RATE_1M;
1308 else
1309 priv->wCurrentRate = RATE_54M;
1310
1311 RFbSetPower(priv, priv->wCurrentRate,
1312 conf->chandef.chan->hw_value);
1313 }
1314
1315 return 0;
1316}
1317
1318static void vnt_bss_info_changed(struct ieee80211_hw *hw,
1319 struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf,
1320 u32 changed)
1321{
1322 struct vnt_private *priv = hw->priv;
1323
1324 priv->current_aid = conf->aid;
1325
Malcolm Priestley8e8e9192015-07-09 17:01:24 +01001326 if (changed & BSS_CHANGED_BSSID && conf->bssid) {
Malcolm Priestley664a5c12015-04-21 22:33:02 +01001327 unsigned long flags;
1328
1329 spin_lock_irqsave(&priv->lock, flags);
1330
Malcolm Priestley67013f22014-10-29 17:43:43 +00001331 MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid);
1332
Malcolm Priestley664a5c12015-04-21 22:33:02 +01001333 spin_unlock_irqrestore(&priv->lock, flags);
1334 }
1335
Malcolm Priestley67013f22014-10-29 17:43:43 +00001336 if (changed & BSS_CHANGED_BASIC_RATES) {
1337 priv->basic_rates = conf->basic_rates;
1338
1339 CARDvUpdateBasicTopRate(priv);
1340
1341 dev_dbg(&priv->pcid->dev,
1342 "basic rates %x\n", conf->basic_rates);
1343 }
1344
1345 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1346 if (conf->use_short_preamble) {
1347 MACvEnableBarkerPreambleMd(priv->PortOffset);
1348 priv->byPreambleType = true;
1349 } else {
1350 MACvDisableBarkerPreambleMd(priv->PortOffset);
1351 priv->byPreambleType = false;
1352 }
1353 }
1354
1355 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1356 if (conf->use_cts_prot)
1357 MACvEnableProtectMD(priv->PortOffset);
1358 else
1359 MACvDisableProtectMD(priv->PortOffset);
1360 }
1361
1362 if (changed & BSS_CHANGED_ERP_SLOT) {
1363 if (conf->use_short_slot)
1364 priv->bShortSlotTime = true;
1365 else
1366 priv->bShortSlotTime = false;
1367
Malcolm Priestleybfb6c862014-11-07 19:06:06 +00001368 CARDbSetPhyParameter(priv, priv->byBBType);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001369 BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]);
1370 }
1371
1372 if (changed & BSS_CHANGED_TXPOWER)
1373 RFbSetPower(priv, priv->wCurrentRate,
1374 conf->chandef.chan->hw_value);
1375
1376 if (changed & BSS_CHANGED_BEACON_ENABLED) {
1377 dev_dbg(&priv->pcid->dev,
1378 "Beacon enable %d\n", conf->enable_beacon);
1379
1380 if (conf->enable_beacon) {
1381 vnt_beacon_enable(priv, vif, conf);
1382
Mike Krinkin84c00af2014-12-21 16:56:47 +03001383 MACvRegBitsOn(priv->PortOffset, MAC_REG_TCR,
1384 TCR_AUTOBCNTX);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001385 } else {
Mike Krinkin84c00af2014-12-21 16:56:47 +03001386 MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR,
1387 TCR_AUTOBCNTX);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001388 }
1389 }
1390
Malcolm Priestley1f171242015-08-02 12:34:46 +01001391 if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
1392 priv->op_mode != NL80211_IFTYPE_AP) {
1393 if (conf->assoc && conf->beacon_rate) {
Malcolm Priestley67013f22014-10-29 17:43:43 +00001394 CARDbUpdateTSF(priv, conf->beacon_rate->hw_value,
Malcolm Priestley032ed342015-04-21 22:33:01 +01001395 conf->sync_tsf);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001396
1397 CARDbSetBeaconPeriod(priv, conf->beacon_int);
1398
Malcolm Priestley738487f2014-11-12 21:11:09 +00001399 CARDvSetFirstNextTBTT(priv, conf->beacon_int);
Malcolm Priestleyc7b14ea2014-10-29 17:44:09 +00001400 } else {
1401 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL,
1402 TFTCTL_TSFCNTRST);
1403 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL,
1404 TFTCTL_TSFCNTREN);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001405 }
1406 }
1407}
1408
1409static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
1410 struct netdev_hw_addr_list *mc_list)
1411{
1412 struct vnt_private *priv = hw->priv;
1413 struct netdev_hw_addr *ha;
1414 u64 mc_filter = 0;
1415 u32 bit_nr = 0;
1416
1417 netdev_hw_addr_list_for_each(ha, mc_list) {
1418 bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
1419
1420 mc_filter |= 1ULL << (bit_nr & 0x3f);
1421 }
1422
1423 priv->mc_list_count = mc_list->count;
1424
1425 return mc_filter;
1426}
1427
1428static void vnt_configure(struct ieee80211_hw *hw,
1429 unsigned int changed_flags, unsigned int *total_flags, u64 multicast)
1430{
1431 struct vnt_private *priv = hw->priv;
1432 u8 rx_mode = 0;
1433
Johannes Bergdf140462015-04-22 14:40:58 +02001434 *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
Malcolm Priestley67013f22014-10-29 17:43:43 +00001435
1436 VNSvInPortB(priv->PortOffset + MAC_REG_RCR, &rx_mode);
1437
1438 dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode);
1439
Malcolm Priestley67013f22014-10-29 17:43:43 +00001440 if (changed_flags & FIF_ALLMULTI) {
1441 if (*total_flags & FIF_ALLMULTI) {
Malcolm Priestley95775d12015-01-11 10:26:12 +00001442 unsigned long flags;
1443
1444 spin_lock_irqsave(&priv->lock, flags);
1445
Malcolm Priestley67013f22014-10-29 17:43:43 +00001446 if (priv->mc_list_count > 2) {
1447 MACvSelectPage1(priv->PortOffset);
1448
1449 VNSvOutPortD(priv->PortOffset +
1450 MAC_REG_MAR0, 0xffffffff);
1451 VNSvOutPortD(priv->PortOffset +
1452 MAC_REG_MAR0 + 4, 0xffffffff);
1453
1454 MACvSelectPage0(priv->PortOffset);
1455 } else {
1456 MACvSelectPage1(priv->PortOffset);
1457
1458 VNSvOutPortD(priv->PortOffset +
1459 MAC_REG_MAR0, (u32)multicast);
1460 VNSvOutPortD(priv->PortOffset +
1461 MAC_REG_MAR0 + 4,
1462 (u32)(multicast >> 32));
1463
1464 MACvSelectPage0(priv->PortOffset);
1465 }
1466
Malcolm Priestley95775d12015-01-11 10:26:12 +00001467 spin_unlock_irqrestore(&priv->lock, flags);
1468
Malcolm Priestley67013f22014-10-29 17:43:43 +00001469 rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
1470 } else {
1471 rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
1472 }
1473 }
1474
1475 if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
1476 rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
1477
1478 if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
1479 rx_mode &= ~RCR_BSSID;
1480 else
1481 rx_mode |= RCR_BSSID;
1482 }
1483
1484 VNSvOutPortB(priv->PortOffset + MAC_REG_RCR, rx_mode);
1485
1486 dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode);
1487}
1488
1489static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1490 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1491 struct ieee80211_key_conf *key)
1492{
1493 struct vnt_private *priv = hw->priv;
1494
1495 switch (cmd) {
1496 case SET_KEY:
1497 if (vnt_set_keys(hw, sta, vif, key))
1498 return -EOPNOTSUPP;
1499 break;
1500 case DISABLE_KEY:
1501 if (test_bit(key->hw_key_idx, &priv->key_entry_inuse))
1502 clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
1503 default:
1504 break;
1505 }
1506
1507 return 0;
1508}
1509
Malcolm Priestley700f6c02015-05-31 10:35:20 +01001510static int vnt_get_stats(struct ieee80211_hw *hw,
1511 struct ieee80211_low_level_stats *stats)
1512{
1513 struct vnt_private *priv = hw->priv;
1514
1515 memcpy(stats, &priv->low_stats, sizeof(*stats));
1516
1517 return 0;
1518}
1519
Malcolm Priestley67013f22014-10-29 17:43:43 +00001520static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1521{
1522 struct vnt_private *priv = hw->priv;
1523 u64 tsf;
1524
Malcolm Priestley738487f2014-11-12 21:11:09 +00001525 CARDbGetCurrentTSF(priv, &tsf);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001526
1527 return tsf;
1528}
1529
1530static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1531 u64 tsf)
1532{
1533 struct vnt_private *priv = hw->priv;
1534
Malcolm Priestley738487f2014-11-12 21:11:09 +00001535 CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001536}
1537
1538static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1539{
1540 struct vnt_private *priv = hw->priv;
1541
1542 /* reset TSF counter */
1543 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
1544}
1545
1546static const struct ieee80211_ops vnt_mac_ops = {
1547 .tx = vnt_tx_80211,
1548 .start = vnt_start,
1549 .stop = vnt_stop,
1550 .add_interface = vnt_add_interface,
1551 .remove_interface = vnt_remove_interface,
1552 .config = vnt_config,
1553 .bss_info_changed = vnt_bss_info_changed,
1554 .prepare_multicast = vnt_prepare_multicast,
1555 .configure_filter = vnt_configure,
1556 .set_key = vnt_set_key,
Malcolm Priestley700f6c02015-05-31 10:35:20 +01001557 .get_stats = vnt_get_stats,
Malcolm Priestley67013f22014-10-29 17:43:43 +00001558 .get_tsf = vnt_get_tsf,
1559 .set_tsf = vnt_set_tsf,
1560 .reset_tsf = vnt_reset_tsf,
1561};
1562
Sören Brinkmannb7c9cd42014-12-04 20:33:41 -08001563static int vnt_init(struct vnt_private *priv)
Malcolm Priestley67013f22014-10-29 17:43:43 +00001564{
1565 SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr);
1566
Malcolm Priestley3d75b9e2014-10-29 17:43:44 +00001567 vnt_init_bands(priv);
1568
Malcolm Priestley67013f22014-10-29 17:43:43 +00001569 if (ieee80211_register_hw(priv->hw))
1570 return -ENODEV;
1571
1572 priv->mac_hw = true;
1573
1574 CARDbRadioPowerOff(priv);
1575
1576 return 0;
1577}
1578
1579static int
1580vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
1581{
Malcolm Priestley67013f22014-10-29 17:43:43 +00001582 struct vnt_private *priv;
1583 struct ieee80211_hw *hw;
1584 struct wiphy *wiphy;
1585 int rc;
1586
1587 dev_notice(&pcid->dev,
1588 "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
1589
1590 dev_notice(&pcid->dev,
1591 "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
1592
1593 hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops);
1594 if (!hw) {
1595 dev_err(&pcid->dev, "could not register ieee80211_hw\n");
1596 return -ENOMEM;
1597 }
1598
1599 priv = hw->priv;
Malcolm Priestleyf3179822015-09-12 19:10:33 +01001600 priv->pcid = pcid;
Malcolm Priestley67013f22014-10-29 17:43:43 +00001601
Malcolm Priestleyf3179822015-09-12 19:10:33 +01001602 spin_lock_init(&priv->lock);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001603
1604 priv->hw = hw;
1605
1606 SET_IEEE80211_DEV(priv->hw, &pcid->dev);
1607
1608 if (pci_enable_device(pcid)) {
1609 device_free_info(priv);
1610 return -ENODEV;
1611 }
1612
1613 dev_dbg(&pcid->dev,
1614 "Before get pci_info memaddr is %x\n", priv->memaddr);
1615
Malcolm Priestleya03b8b32015-09-12 19:10:38 +01001616 pci_set_master(pcid);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001617
Malcolm Priestleya03b8b32015-09-12 19:10:38 +01001618 priv->memaddr = pci_resource_start(pcid, 0);
1619 priv->ioaddr = pci_resource_start(pcid, 1);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001620 priv->PortOffset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK,
Malcolm Priestley319755a2015-09-12 19:10:30 +01001621 256);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001622 if (!priv->PortOffset) {
1623 dev_err(&pcid->dev, ": Failed to IO remapping ..\n");
1624 device_free_info(priv);
1625 return -ENODEV;
1626 }
1627
1628 rc = pci_request_regions(pcid, DEVICE_NAME);
1629 if (rc) {
1630 dev_err(&pcid->dev, ": Failed to find PCI device\n");
1631 device_free_info(priv);
1632 return -ENODEV;
1633 }
1634
Malcolm Priestleyd5806c52015-07-22 19:16:45 +01001635 if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) {
1636 dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n");
1637 device_free_info(priv);
1638 return -ENODEV;
1639 }
1640
Malcolm Priestleyff1ce1a2015-05-31 10:35:24 +01001641 INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
1642
Malcolm Priestley67013f22014-10-29 17:43:43 +00001643 /* do reset */
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +00001644 if (!MACbSoftwareReset(priv)) {
Malcolm Priestley67013f22014-10-29 17:43:43 +00001645 dev_err(&pcid->dev, ": Failed to access MAC hardware..\n");
1646 device_free_info(priv);
1647 return -ENODEV;
1648 }
1649 /* initial to reload eeprom */
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +00001650 MACvInitialize(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001651 MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr);
1652
Malcolm Priestley1f51d582015-03-07 17:04:55 +00001653 /* Get RFType */
1654 priv->byRFType = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_RFTYPE);
1655 priv->byRFType &= RF_MASK;
1656
1657 dev_dbg(&pcid->dev, "RF Type = %x\n", priv->byRFType);
1658
Malcolm Priestley67013f22014-10-29 17:43:43 +00001659 device_get_options(priv);
1660 device_set_options(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001661
1662 wiphy = priv->hw->wiphy;
1663
1664 wiphy->frag_threshold = FRAG_THRESH_DEF;
1665 wiphy->rts_threshold = RTS_THRESH_DEF;
1666 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1667 BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
1668
Johannes Berg30686bf2015-06-02 21:39:54 +02001669 ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
1670 ieee80211_hw_set(priv->hw, SIGNAL_DBM);
1671 ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
1672 ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
Malcolm Priestleyeda01f62015-07-09 17:01:25 +01001673 ieee80211_hw_set(priv->hw, SUPPORTS_PS);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001674
1675 priv->hw->max_signal = 100;
1676
1677 if (vnt_init(priv))
1678 return -ENODEV;
1679
1680 device_print_info(priv);
1681 pci_set_drvdata(pcid, priv);
1682
1683 return 0;
1684}
1685
Forest Bond5449c682009-04-25 10:30:44 -04001686/*------------------------------------------------------------------*/
Forest Bond5449c682009-04-25 10:30:44 -04001687
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001688#ifdef CONFIG_PM
1689static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state)
1690{
1691 struct vnt_private *priv = pci_get_drvdata(pcid);
1692 unsigned long flags;
1693
1694 spin_lock_irqsave(&priv->lock, flags);
1695
1696 pci_save_state(pcid);
1697
Malcolm Priestleyf9f853a2015-11-22 09:07:22 +00001698 MACbShutdown(priv);
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001699
1700 pci_disable_device(pcid);
1701 pci_set_power_state(pcid, pci_choose_state(pcid, state));
1702
1703 spin_unlock_irqrestore(&priv->lock, flags);
1704
1705 return 0;
1706}
1707
1708static int vt6655_resume(struct pci_dev *pcid)
1709{
1710
1711 pci_set_power_state(pcid, PCI_D0);
1712 pci_enable_wake(pcid, PCI_D0, 0);
1713 pci_restore_state(pcid);
1714
1715 return 0;
1716}
1717#endif
1718
Charles Clément013a4682010-06-15 10:39:24 -07001719MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table);
Forest Bond5449c682009-04-25 10:30:44 -04001720
1721static struct pci_driver device_driver = {
Peter Huewe34381c22011-01-10 23:28:06 +01001722 .name = DEVICE_NAME,
1723 .id_table = vt6655_pci_id_table,
1724 .probe = vt6655_probe,
1725 .remove = vt6655_remove,
Forest Bond5449c682009-04-25 10:30:44 -04001726#ifdef CONFIG_PM
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001727 .suspend = vt6655_suspend,
1728 .resume = vt6655_resume,
Forest Bond5449c682009-04-25 10:30:44 -04001729#endif
Forest Bond5449c682009-04-25 10:30:44 -04001730};
1731
Malcolm Priestleye75e8ca2015-06-16 23:43:12 +01001732module_pci_driver(device_driver);