blob: 83e4162c0094c4b2bed6853bc8cfb5636011191a [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
31 * vt6655_init_info - device structure resource allocation function
Forest Bond5449c682009-04-25 10:30:44 -040032 * device_free_info - device structure resource free function
33 * device_get_pci_info - get allocated pci io/mem resource
34 * device_print_info - print out resource
Forest Bond5449c682009-04-25 10:30:44 -040035 * device_intr - interrupt handle function
Forest Bond5449c682009-04-25 10:30:44 -040036 * device_rx_srv - rx service function
Forest Bond5449c682009-04-25 10:30:44 -040037 * device_alloc_rx_buf - rx buffer pre-allocated function
Forest Bond5449c682009-04-25 10:30:44 -040038 * device_free_tx_buf - free tx buffer function
Forest Bond5449c682009-04-25 10:30:44 -040039 * device_init_rd0_ring- initial rd dma0 ring
40 * device_init_rd1_ring- initial rd dma1 ring
41 * device_init_td0_ring- initial tx dma0 ring buffer
42 * device_init_td1_ring- initial tx dma1 ring buffer
43 * device_init_registers- initial MAC & BBP & RF internal registers.
44 * device_init_rings- initial tx/rx ring buffer
Forest Bond5449c682009-04-25 10:30:44 -040045 * device_free_rings- free all allocated ring buffer
46 * device_tx_srv- tx interrupt service function
47 *
48 * Revision History:
49 */
50#undef __NO_VERSION__
51
Al Virof8054422013-04-06 18:11:22 -040052#include <linux/file.h>
Forest Bond5449c682009-04-25 10:30:44 -040053#include "device.h"
Forest Bond5449c682009-04-25 10:30:44 -040054#include "card.h"
Charles Clément79566eb2010-06-21 10:39:51 -070055#include "channel.h"
Forest Bond5449c682009-04-25 10:30:44 -040056#include "baseband.h"
Forest Bond5449c682009-04-25 10:30:44 -040057#include "mac.h"
Forest Bond5449c682009-04-25 10:30:44 -040058#include "power.h"
Forest Bond5449c682009-04-25 10:30:44 -040059#include "rxtx.h"
Forest Bond5449c682009-04-25 10:30:44 -040060#include "dpc.h"
Forest Bond5449c682009-04-25 10:30:44 -040061#include "rf.h"
Forest Bond5449c682009-04-25 10:30:44 -040062#include <linux/delay.h>
63#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090064#include <linux/slab.h>
Forest Bond5449c682009-04-25 10:30:44 -040065
Forest Bond5449c682009-04-25 10:30:44 -040066/*--------------------- Static Definitions -------------------------*/
Forest Bond5449c682009-04-25 10:30:44 -040067//
68// Define module options
69//
Forest Bond5449c682009-04-25 10:30:44 -040070MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
71MODULE_LICENSE("GPL");
72MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
Forest Bond5449c682009-04-25 10:30:44 -040073
Joe Perches915006c2013-03-18 10:44:47 -070074#define DEVICE_PARAM(N, D)
Forest Bond5449c682009-04-25 10:30:44 -040075
76#define RX_DESC_MIN0 16
77#define RX_DESC_MAX0 128
78#define RX_DESC_DEF0 32
Joe Perches915006c2013-03-18 10:44:47 -070079DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
Forest Bond5449c682009-04-25 10:30:44 -040080
81#define RX_DESC_MIN1 16
82#define RX_DESC_MAX1 128
83#define RX_DESC_DEF1 32
Joe Perches915006c2013-03-18 10:44:47 -070084DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
Forest Bond5449c682009-04-25 10:30:44 -040085
86#define TX_DESC_MIN0 16
87#define TX_DESC_MAX0 128
88#define TX_DESC_DEF0 32
Joe Perches915006c2013-03-18 10:44:47 -070089DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
Forest Bond5449c682009-04-25 10:30:44 -040090
91#define TX_DESC_MIN1 16
92#define TX_DESC_MAX1 128
93#define TX_DESC_DEF1 64
Joe Perches915006c2013-03-18 10:44:47 -070094DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
Forest Bond5449c682009-04-25 10:30:44 -040095
Forest Bond5449c682009-04-25 10:30:44 -040096#define INT_WORKS_DEF 20
97#define INT_WORKS_MIN 10
98#define INT_WORKS_MAX 64
99
Joe Perches915006c2013-03-18 10:44:47 -0700100DEVICE_PARAM(int_works, "Number of packets per interrupt services");
Forest Bond5449c682009-04-25 10:30:44 -0400101
Forest Bond5449c682009-04-25 10:30:44 -0400102#define RTS_THRESH_DEF 2347
103
Forest Bond5449c682009-04-25 10:30:44 -0400104#define FRAG_THRESH_DEF 2346
105
Forest Bond5449c682009-04-25 10:30:44 -0400106#define SHORT_RETRY_MIN 0
107#define SHORT_RETRY_MAX 31
108#define SHORT_RETRY_DEF 8
109
Forest Bond5449c682009-04-25 10:30:44 -0400110DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
111
112#define LONG_RETRY_MIN 0
113#define LONG_RETRY_MAX 15
114#define LONG_RETRY_DEF 4
115
Forest Bond5449c682009-04-25 10:30:44 -0400116DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
117
Forest Bond5449c682009-04-25 10:30:44 -0400118/* BasebandType[] baseband type selected
119 0: indicate 802.11a type
120 1: indicate 802.11b type
121 2: indicate 802.11g type
122*/
123#define BBP_TYPE_MIN 0
124#define BBP_TYPE_MAX 2
125#define BBP_TYPE_DEF 2
126
127DEVICE_PARAM(BasebandType, "baseband type");
128
Forest Bond5449c682009-04-25 10:30:44 -0400129#define DIVERSITY_ANT_DEF 0
130
131DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode");
132
Forest Bond5449c682009-04-25 10:30:44 -0400133//
134// Static vars definitions
135//
Joe Perches915006c2013-03-18 10:44:47 -0700136static CHIP_INFO chip_info_table[] = {
137 { VT3253, "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
138 256, 1, DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
139 {0, NULL}
Forest Bond5449c682009-04-25 10:30:44 -0400140};
141
Guillaume Clement9e4c5c22014-07-22 22:08:28 +0200142static const struct pci_device_id vt6655_pci_id_table[] = {
Jim Liebdb6cb902009-07-23 17:20:49 -0700143 { PCI_VDEVICE(VIA, 0x3253), (kernel_ulong_t)chip_info_table},
144 { 0, }
Forest Bond5449c682009-04-25 10:30:44 -0400145};
Forest Bond5449c682009-04-25 10:30:44 -0400146
147/*--------------------- Static Functions --------------------------*/
148
Charles Clément013a4682010-06-15 10:39:24 -0700149static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100150static void vt6655_init_info(struct pci_dev *pcid,
151 struct vnt_private **ppDevice, PCHIP_INFO);
152static void device_free_info(struct vnt_private *pDevice);
153static bool device_get_pci_info(struct vnt_private *, struct pci_dev *pcid);
154static void device_print_info(struct vnt_private *pDevice);
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100155static void device_init_diversity_timer(struct vnt_private *pDevice);
Joe Perches915006c2013-03-18 10:44:47 -0700156static irqreturn_t device_intr(int irq, void *dev_instance);
Forest Bond5449c682009-04-25 10:30:44 -0400157
Forest Bond5449c682009-04-25 10:30:44 -0400158#ifdef CONFIG_PM
159static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
Guillaume Clement9e4c5c22014-07-22 22:08:28 +0200160static struct notifier_block device_notifier = {
Peter Huewe34381c22011-01-10 23:28:06 +0100161 .notifier_call = device_notify_reboot,
162 .next = NULL,
163 .priority = 0,
Forest Bond5449c682009-04-25 10:30:44 -0400164};
165#endif
Forest Bond5449c682009-04-25 10:30:44 -0400166
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100167static void device_init_rd0_ring(struct vnt_private *pDevice);
168static void device_init_rd1_ring(struct vnt_private *pDevice);
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100169static void device_init_td0_ring(struct vnt_private *pDevice);
170static void device_init_td1_ring(struct vnt_private *pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400171
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100172static int device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx);
173static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx);
174static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pDesc);
175static void device_init_registers(struct vnt_private *pDevice);
176static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc);
177static void device_free_td0_ring(struct vnt_private *pDevice);
178static void device_free_td1_ring(struct vnt_private *pDevice);
179static void device_free_rd0_ring(struct vnt_private *pDevice);
180static void device_free_rd1_ring(struct vnt_private *pDevice);
181static void device_free_rings(struct vnt_private *pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400182
Forest Bond5449c682009-04-25 10:30:44 -0400183/*--------------------- Export Variables --------------------------*/
184
185/*--------------------- Export Functions --------------------------*/
186
Joe Perches915006c2013-03-18 10:44:47 -0700187static char *get_chip_name(int chip_id)
Devendra Naga3ac9e0f2012-09-07 00:08:02 +0530188{
189 int i;
Guillaume Clement6b711272014-07-25 01:06:16 +0200190
Devendra Naga3ac9e0f2012-09-07 00:08:02 +0530191 for (i = 0; chip_info_table[i].name != NULL; i++)
192 if (chip_info_table[i].chip_id == chip_id)
193 break;
194 return chip_info_table[i].name;
Forest Bond5449c682009-04-25 10:30:44 -0400195}
196
Bill Pembertonf4e1b7c2012-11-19 13:26:53 -0500197static void vt6655_remove(struct pci_dev *pcid)
Forest Bond5449c682009-04-25 10:30:44 -0400198{
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100199 struct vnt_private *pDevice = pci_get_drvdata(pcid);
Forest Bond5449c682009-04-25 10:30:44 -0400200
Devendra Naga3ac9e0f2012-09-07 00:08:02 +0530201 if (pDevice == NULL)
202 return;
203 device_free_info(pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400204}
205
Malcolm Priestley46fa0ec2014-09-22 21:27:47 +0100206static void device_get_options(struct vnt_private *pDevice)
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530207{
208 POPTIONS pOpts = &(pDevice->sOpts);
Forest Bond5449c682009-04-25 10:30:44 -0400209
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530210 pOpts->nRxDescs0 = RX_DESC_DEF0;
211 pOpts->nRxDescs1 = RX_DESC_DEF1;
212 pOpts->nTxDescs[0] = TX_DESC_DEF0;
213 pOpts->nTxDescs[1] = TX_DESC_DEF1;
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530214 pOpts->int_works = INT_WORKS_DEF;
Forest Bond5449c682009-04-25 10:30:44 -0400215
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530216 pOpts->short_retry = SHORT_RETRY_DEF;
217 pOpts->long_retry = LONG_RETRY_DEF;
218 pOpts->bbp_type = BBP_TYPE_DEF;
Devendra Nagabf76ebd2012-09-07 00:08:03 +0530219 pOpts->flags |= DEVICE_FLAGS_DiversityANT;
Forest Bond5449c682009-04-25 10:30:44 -0400220}
221
222static void
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100223device_set_options(struct vnt_private *pDevice)
224{
Joe Perches915006c2013-03-18 10:44:47 -0700225 pDevice->byShortRetryLimit = pDevice->sOpts.short_retry;
226 pDevice->byLongRetryLimit = pDevice->sOpts.long_retry;
Joe Perches915006c2013-03-18 10:44:47 -0700227 pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0;
Joe Perches915006c2013-03-18 10:44:47 -0700228 pDevice->byBBType = pDevice->sOpts.bbp_type;
Malcolm Priestleybf8918d2014-11-07 19:06:08 +0000229 pDevice->byPacketType = pDevice->byBBType;
Forest Bond5449c682009-04-25 10:30:44 -0400230 pDevice->byAutoFBCtrl = AUTO_FB_0;
Joe Perches915006c2013-03-18 10:44:47 -0700231 pDevice->bUpdateBBVGA = true;
Joe Perches915006c2013-03-18 10:44:47 -0700232 pDevice->byPreambleType = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400233
Joe Perches48caf5a2014-08-17 09:17:04 -0700234 pr_debug(" byShortRetryLimit= %d\n", (int)pDevice->byShortRetryLimit);
235 pr_debug(" byLongRetryLimit= %d\n", (int)pDevice->byLongRetryLimit);
236 pr_debug(" byPreambleType= %d\n", (int)pDevice->byPreambleType);
237 pr_debug(" byShortPreamble= %d\n", (int)pDevice->byShortPreamble);
Joe Perches48caf5a2014-08-17 09:17:04 -0700238 pr_debug(" byBBType= %d\n", (int)pDevice->byBBType);
Joe Perches48caf5a2014-08-17 09:17:04 -0700239 pr_debug(" pDevice->bDiversityRegCtlON= %d\n",
240 (int)pDevice->bDiversityRegCtlON);
Forest Bond5449c682009-04-25 10:30:44 -0400241}
242
Forest Bond5449c682009-04-25 10:30:44 -0400243//
Justin P. Mattock789d1ae2012-08-20 08:43:13 -0700244// Initialisation of MAC & BBP registers
Forest Bond5449c682009-04-25 10:30:44 -0400245//
246
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100247static void device_init_registers(struct vnt_private *pDevice)
Forest Bond5449c682009-04-25 10:30:44 -0400248{
Malcolm Priestley10d6f1b2014-10-29 17:44:04 +0000249 unsigned long flags;
Joe Perches915006c2013-03-18 10:44:47 -0700250 unsigned int ii;
251 unsigned char byValue;
252 unsigned char byValue1;
253 unsigned char byCCKPwrdBm = 0;
254 unsigned char byOFDMPwrdBm = 0;
Guillaume Clement6b711272014-07-25 01:06:16 +0200255
Joe Perches915006c2013-03-18 10:44:47 -0700256 MACbShutdown(pDevice->PortOffset);
Malcolm Priestleya5f0eef2014-11-06 20:02:01 +0000257 BBvSoftwareReset(pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400258
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100259 /* Do MACbSoftwareReset in MACvInitialize */
260 MACbSoftwareReset(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400261
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100262 pDevice->bAES = false;
Forest Bond5449c682009-04-25 10:30:44 -0400263
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100264 /* Only used in 11g type, sync with ERP IE */
265 pDevice->bProtectMode = false;
Forest Bond5449c682009-04-25 10:30:44 -0400266
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100267 pDevice->bNonERPPresent = false;
268 pDevice->bBarkerPreambleMd = false;
269 pDevice->wCurrentRate = RATE_1M;
270 pDevice->byTopOFDMBasicRate = RATE_24M;
271 pDevice->byTopCCKBasicRate = RATE_1M;
Forest Bond5449c682009-04-25 10:30:44 -0400272
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100273 /* Target to IF pin while programming to RF chip. */
274 pDevice->byRevId = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400275
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100276 /* init MAC */
277 MACvInitialize(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400278
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100279 /* Get Local ID */
280 VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &pDevice->byLocalID);
Forest Bond5449c682009-04-25 10:30:44 -0400281
Malcolm Priestley10d6f1b2014-10-29 17:44:04 +0000282 spin_lock_irqsave(&pDevice->lock, flags);
Forest Bond5449c682009-04-25 10:30:44 -0400283
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100284 SROMvReadAllContents(pDevice->PortOffset, pDevice->abyEEPROM);
285
Malcolm Priestley10d6f1b2014-10-29 17:44:04 +0000286 spin_unlock_irqrestore(&pDevice->lock, flags);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100287
288 /* Get Channel range */
289 pDevice->byMinChannel = 1;
290 pDevice->byMaxChannel = CB_MAX_CHANNEL;
291
292 /* Get Antena */
293 byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
294 if (byValue & EEP_ANTINV)
295 pDevice->bTxRxAntInv = true;
296 else
297 pDevice->bTxRxAntInv = false;
298
299 byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
300 /* if not set default is All */
301 if (byValue == 0)
302 byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
303
304 pDevice->ulDiversityNValue = 100*260;
305 pDevice->ulDiversityMValue = 100*16;
306 pDevice->byTMax = 1;
307 pDevice->byTMax2 = 4;
308 pDevice->ulSQ3TH = 0;
309 pDevice->byTMax3 = 64;
310
311 if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
312 pDevice->byAntennaCount = 2;
313 pDevice->byTxAntennaMode = ANT_B;
314 pDevice->dwTxAntennaSel = 1;
315 pDevice->dwRxAntennaSel = 1;
316
317 if (pDevice->bTxRxAntInv)
318 pDevice->byRxAntennaMode = ANT_A;
Joe Perches915006c2013-03-18 10:44:47 -0700319 else
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100320 pDevice->byRxAntennaMode = ANT_B;
Forest Bond5449c682009-04-25 10:30:44 -0400321
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100322 byValue1 = SROMbyReadEmbedded(pDevice->PortOffset,
323 EEP_OFS_ANTENNA);
Joe Perchesf2046f92013-03-18 20:55:36 -0700324
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100325 if ((byValue1 & 0x08) == 0)
326 pDevice->bDiversityEnable = false;
327 else
328 pDevice->bDiversityEnable = true;
329 } else {
330 pDevice->bDiversityEnable = false;
331 pDevice->byAntennaCount = 1;
332 pDevice->dwTxAntennaSel = 0;
333 pDevice->dwRxAntennaSel = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400334
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100335 if (byValue & EEP_ANTENNA_AUX) {
336 pDevice->byTxAntennaMode = ANT_A;
337
338 if (pDevice->bTxRxAntInv)
339 pDevice->byRxAntennaMode = ANT_B;
340 else
341 pDevice->byRxAntennaMode = ANT_A;
342 } else {
Joe Perches915006c2013-03-18 10:44:47 -0700343 pDevice->byTxAntennaMode = ANT_B;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100344
Teodora Baluta1208f142013-11-10 17:12:42 +0200345 if (pDevice->bTxRxAntInv)
Joe Perches915006c2013-03-18 10:44:47 -0700346 pDevice->byRxAntennaMode = ANT_A;
347 else
348 pDevice->byRxAntennaMode = ANT_B;
Joe Perches915006c2013-03-18 10:44:47 -0700349 }
350 }
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100351
Joe Perches48caf5a2014-08-17 09:17:04 -0700352 pr_debug("bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n",
353 pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue,
354 (int)pDevice->ulDiversityMValue, pDevice->byTMax,
355 pDevice->byTMax2);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100356
357 /* zonetype initial */
358 pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100359
360 /* Get RFType */
361 pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
362
363 /* force change RevID for VT3253 emu */
364 if ((pDevice->byRFType & RF_EMU) != 0)
365 pDevice->byRevId = 0x80;
366
367 pDevice->byRFType &= RF_MASK;
Joe Perches48caf5a2014-08-17 09:17:04 -0700368 pr_debug("pDevice->byRFType = %x\n", pDevice->byRFType);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100369
370 if (!pDevice->bZoneRegExist)
371 pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
372
Joe Perches48caf5a2014-08-17 09:17:04 -0700373 pr_debug("pDevice->byZoneType = %x\n", pDevice->byZoneType);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100374
375 /* Init RF module */
376 RFbInit(pDevice);
377
378 /* Get Desire Power Value */
379 pDevice->byCurPwr = 0xFF;
380 pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK);
381 pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG);
382
383 /* Load power Table */
384 for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
385 pDevice->abyCCKPwrTbl[ii + 1] =
386 SROMbyReadEmbedded(pDevice->PortOffset,
387 (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
388 if (pDevice->abyCCKPwrTbl[ii + 1] == 0)
389 pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr;
390
391 pDevice->abyOFDMPwrTbl[ii + 1] =
392 SROMbyReadEmbedded(pDevice->PortOffset,
393 (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
394 if (pDevice->abyOFDMPwrTbl[ii + 1] == 0)
395 pDevice->abyOFDMPwrTbl[ii + 1] = pDevice->byOFDMPwrG;
396
397 pDevice->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
398 pDevice->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
399 }
400
401 /* recover 12,13 ,14channel for EUROPE by 11 channel */
Malcolm Priestleyf4cf6782014-10-29 17:55:19 +0000402 for (ii = 11; ii < 14; ii++) {
403 pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
404 pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100405 }
406
407 /* Load OFDM A Power Table */
408 for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
409 pDevice->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] =
410 SROMbyReadEmbedded(pDevice->PortOffset,
411 (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
412
413 pDevice->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] =
414 SROMbyReadEmbedded(pDevice->PortOffset,
415 (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
416 }
417
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100418 if (pDevice->byLocalID > REV_ID_VT3253_B1) {
419 MACvSelectPage1(pDevice->PortOffset);
420
421 VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1,
422 (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
423
424 MACvSelectPage0(pDevice->PortOffset);
425 }
426
427 /* use relative tx timeout and 802.11i D4 */
428 MACvWordRegBitsOn(pDevice->PortOffset,
429 MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
430
431 /* set performance parameter by registry */
432 MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit);
433 MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit);
434
435 /* reset TSF counter */
436 VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
437 /* enable TSF counter */
438 VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
439
440 /* initialize BBP registers */
441 BBbVT3253Init(pDevice);
442
443 if (pDevice->bUpdateBBVGA) {
444 pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
445 pDevice->byBBVGANew = pDevice->byBBVGACurrent;
446 BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
447 }
448
Malcolm Priestleya5f0eef2014-11-06 20:02:01 +0000449 BBvSetRxAntennaMode(pDevice, pDevice->byRxAntennaMode);
450 BBvSetTxAntennaMode(pDevice, pDevice->byTxAntennaMode);
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100451
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100452 /* Set BB and packet type at the same time. */
453 /* Set Short Slot Time, xIFS, and RSPINF. */
Malcolm Priestleybfa4b0f2014-11-05 21:08:55 +0000454 pDevice->wCurrentRate = RATE_54M;
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100455
Malcolm Priestley9f34de32014-07-28 23:26:25 +0100456 pDevice->bRadioOff = false;
457
458 pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset,
459 EEP_OFS_RADIOCTL);
460 pDevice->bHWRadioOff = false;
461
462 if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) {
463 /* Get GPIO */
464 MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
465
466 if (((pDevice->byGPIO & GPIO0_DATA) &&
467 !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) ||
468 (!(pDevice->byGPIO & GPIO0_DATA) &&
469 (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
470 pDevice->bHWRadioOff = true;
471 }
472
Guido Martínezbc5cf652014-04-19 16:45:00 -0300473 if (pDevice->bHWRadioOff || pDevice->bRadioControlOff)
Joe Perches915006c2013-03-18 10:44:47 -0700474 CARDbRadioPowerOff(pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400475
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100476 /* get Permanent network address */
477 SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
Joe Perches48caf5a2014-08-17 09:17:04 -0700478 pr_debug("Network address = %pM\n", pDevice->abyCurrentNetAddr);
Forest Bond5449c682009-04-25 10:30:44 -0400479
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100480 /* reset Tx pointer */
481 CARDvSafeResetRx(pDevice);
482 /* reset Rx pointer */
483 CARDvSafeResetTx(pDevice);
Forest Bond5449c682009-04-25 10:30:44 -0400484
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100485 if (pDevice->byLocalID <= REV_ID_VT3253_A1)
486 MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR);
Forest Bond5449c682009-04-25 10:30:44 -0400487
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100488 /* Turn On Rx DMA */
489 MACvReceive0(pDevice->PortOffset);
490 MACvReceive1(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400491
Malcolm Priestley3500a1d2014-07-28 23:26:26 +0100492 /* start the adapter */
493 MACvStart(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400494}
495
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100496static void device_init_diversity_timer(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200497{
Joe Perches915006c2013-03-18 10:44:47 -0700498 init_timer(&pDevice->TimerSQ3Tmax1);
499 pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice;
Malcolm Priestleye11cdc32014-10-29 17:56:02 +0000500 pDevice->TimerSQ3Tmax1.function = TimerSQ3CallBack;
Joe Perches915006c2013-03-18 10:44:47 -0700501 pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
Forest Bond5449c682009-04-25 10:30:44 -0400502
Joe Perches915006c2013-03-18 10:44:47 -0700503 init_timer(&pDevice->TimerSQ3Tmax2);
504 pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice;
Malcolm Priestleye11cdc32014-10-29 17:56:02 +0000505 pDevice->TimerSQ3Tmax2.function = TimerSQ3CallBack;
Joe Perches915006c2013-03-18 10:44:47 -0700506 pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
Forest Bond5449c682009-04-25 10:30:44 -0400507
Joe Perches915006c2013-03-18 10:44:47 -0700508 init_timer(&pDevice->TimerSQ3Tmax3);
509 pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice;
Malcolm Priestleye11cdc32014-10-29 17:56:02 +0000510 pDevice->TimerSQ3Tmax3.function = TimerState1CallBack;
Joe Perches915006c2013-03-18 10:44:47 -0700511 pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
Forest Bond5449c682009-04-25 10:30:44 -0400512}
513
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100514static void device_print_info(struct vnt_private *pDevice)
Forest Bond5449c682009-04-25 10:30:44 -0400515{
Malcolm Priestleybc5d4312014-10-29 17:43:46 +0000516 dev_info(&pDevice->pcid->dev, "%s\n", get_chip_name(pDevice->chip_id));
Forest Bond5449c682009-04-25 10:30:44 -0400517
Malcolm Priestleybc5d4312014-10-29 17:43:46 +0000518 dev_info(&pDevice->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n",
519 pDevice->abyCurrentNetAddr, (unsigned long)pDevice->ioaddr,
520 (unsigned long)pDevice->PortOffset, pDevice->pcid->irq);
Forest Bond5449c682009-04-25 10:30:44 -0400521}
522
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100523static void vt6655_init_info(struct pci_dev *pcid,
524 struct vnt_private **ppDevice,
525 PCHIP_INFO pChip_info)
526{
Malcolm Priestley1bd63752014-08-10 15:47:02 +0100527 memset(*ppDevice, 0, sizeof(**ppDevice));
Forest Bond5449c682009-04-25 10:30:44 -0400528
Joe Perches915006c2013-03-18 10:44:47 -0700529 (*ppDevice)->pcid = pcid;
530 (*ppDevice)->chip_id = pChip_info->chip_id;
531 (*ppDevice)->io_size = pChip_info->io_size;
532 (*ppDevice)->nTxQueues = pChip_info->nTxQueue;
533 (*ppDevice)->multicast_limit = 32;
Forest Bond5449c682009-04-25 10:30:44 -0400534
Joe Perches915006c2013-03-18 10:44:47 -0700535 spin_lock_init(&((*ppDevice)->lock));
Forest Bond5449c682009-04-25 10:30:44 -0400536}
537
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100538static bool device_get_pci_info(struct vnt_private *pDevice,
539 struct pci_dev *pcid)
Guillaume Clement84b50762014-07-25 01:06:18 +0200540{
Joe Perches915006c2013-03-18 10:44:47 -0700541 u16 pci_cmd;
542 u8 b;
543 unsigned int cis_addr;
Forest Bond5449c682009-04-25 10:30:44 -0400544
Joe Perches915006c2013-03-18 10:44:47 -0700545 pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId);
546 pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pDevice->SubSystemID);
547 pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID);
548 pci_read_config_word(pcid, PCI_COMMAND, (u16 *)&(pci_cmd));
Forest Bond5449c682009-04-25 10:30:44 -0400549
Joe Perches915006c2013-03-18 10:44:47 -0700550 pci_set_master(pcid);
Forest Bond5449c682009-04-25 10:30:44 -0400551
Joe Perches915006c2013-03-18 10:44:47 -0700552 pDevice->memaddr = pci_resource_start(pcid, 0);
553 pDevice->ioaddr = pci_resource_start(pcid, 1);
Forest Bond5449c682009-04-25 10:30:44 -0400554
Joe Perches915006c2013-03-18 10:44:47 -0700555 cis_addr = pci_resource_start(pcid, 2);
Forest Bond5449c682009-04-25 10:30:44 -0400556
Joe Perches915006c2013-03-18 10:44:47 -0700557 pDevice->pcid = pcid;
Forest Bond5449c682009-04-25 10:30:44 -0400558
Joe Perches915006c2013-03-18 10:44:47 -0700559 pci_read_config_byte(pcid, PCI_COMMAND, &b);
560 pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER));
Forest Bond5449c682009-04-25 10:30:44 -0400561
Joe Perches915006c2013-03-18 10:44:47 -0700562 return true;
Forest Bond5449c682009-04-25 10:30:44 -0400563}
564
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100565static void device_free_info(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200566{
Malcolm Priestley14e53002014-10-29 17:43:55 +0000567 if (!pDevice)
568 return;
Forest Bond5449c682009-04-25 10:30:44 -0400569
Malcolm Priestley14e53002014-10-29 17:43:55 +0000570 if (pDevice->mac_hw)
571 ieee80211_unregister_hw(pDevice->hw);
Forest Bond5449c682009-04-25 10:30:44 -0400572
Joe Perches915006c2013-03-18 10:44:47 -0700573 if (pDevice->PortOffset)
Guillaume Clement16834402014-07-22 22:08:26 +0200574 iounmap(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -0400575
Joe Perches915006c2013-03-18 10:44:47 -0700576 if (pDevice->pcid)
577 pci_release_regions(pDevice->pcid);
Malcolm Priestley14e53002014-10-29 17:43:55 +0000578
579 if (pDevice->hw)
580 ieee80211_free_hw(pDevice->hw);
Forest Bond5449c682009-04-25 10:30:44 -0400581}
Forest Bond5449c682009-04-25 10:30:44 -0400582
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100583static bool device_init_rings(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200584{
Joe Perches915006c2013-03-18 10:44:47 -0700585 void *vir_pool;
Forest Bond5449c682009-04-25 10:30:44 -0400586
Joe Perches915006c2013-03-18 10:44:47 -0700587 /*allocate all RD/TD rings a single pool*/
Joe Perches8b983be2014-08-08 14:24:48 -0700588 vir_pool = pci_zalloc_consistent(pDevice->pcid,
589 pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
590 pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
591 pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
592 pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
593 &pDevice->pool_dma);
Joe Perches915006c2013-03-18 10:44:47 -0700594 if (vir_pool == NULL) {
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100595 dev_err(&pDevice->pcid->dev, "allocate desc dma memory failed\n");
Joe Perches915006c2013-03-18 10:44:47 -0700596 return false;
597 }
Forest Bond5449c682009-04-25 10:30:44 -0400598
Joe Perches915006c2013-03-18 10:44:47 -0700599 pDevice->aRD0Ring = vir_pool;
600 pDevice->aRD1Ring = vir_pool +
601 pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400602
Joe Perches915006c2013-03-18 10:44:47 -0700603 pDevice->rd0_pool_dma = pDevice->pool_dma;
604 pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
605 pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400606
Joe Perches8b983be2014-08-08 14:24:48 -0700607 pDevice->tx0_bufs = pci_zalloc_consistent(pDevice->pcid,
608 pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
609 pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
610 CB_BEACON_BUF_SIZE +
611 CB_MAX_BUF_SIZE,
612 &pDevice->tx_bufs_dma0);
Joe Perches915006c2013-03-18 10:44:47 -0700613 if (pDevice->tx0_bufs == NULL) {
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100614 dev_err(&pDevice->pcid->dev, "allocate buf dma memory failed\n");
615
Joe Perches915006c2013-03-18 10:44:47 -0700616 pci_free_consistent(pDevice->pcid,
617 pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
618 pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
619 pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
620 pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
621 vir_pool, pDevice->pool_dma
622 );
623 return false;
624 }
Forest Bond5449c682009-04-25 10:30:44 -0400625
Joe Perches915006c2013-03-18 10:44:47 -0700626 pDevice->td0_pool_dma = pDevice->rd1_pool_dma +
627 pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400628
Joe Perches915006c2013-03-18 10:44:47 -0700629 pDevice->td1_pool_dma = pDevice->td0_pool_dma +
630 pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400631
Joe Perches915006c2013-03-18 10:44:47 -0700632 // vir_pool: pvoid type
633 pDevice->apTD0Rings = vir_pool
634 + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
635 + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400636
Joe Perches915006c2013-03-18 10:44:47 -0700637 pDevice->apTD1Rings = vir_pool
638 + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
639 + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
640 + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
Forest Bond5449c682009-04-25 10:30:44 -0400641
Joe Perches915006c2013-03-18 10:44:47 -0700642 pDevice->tx1_bufs = pDevice->tx0_bufs +
643 pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400644
Joe Perches915006c2013-03-18 10:44:47 -0700645 pDevice->tx_beacon_bufs = pDevice->tx1_bufs +
646 pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400647
Joe Perches915006c2013-03-18 10:44:47 -0700648 pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs +
649 CB_BEACON_BUF_SIZE;
Forest Bond5449c682009-04-25 10:30:44 -0400650
Joe Perches915006c2013-03-18 10:44:47 -0700651 pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 +
652 pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400653
Joe Perches915006c2013-03-18 10:44:47 -0700654 pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 +
655 pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
Forest Bond5449c682009-04-25 10:30:44 -0400656
Joe Perches915006c2013-03-18 10:44:47 -0700657 return true;
Forest Bond5449c682009-04-25 10:30:44 -0400658}
659
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100660static void device_free_rings(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200661{
Joe Perches915006c2013-03-18 10:44:47 -0700662 pci_free_consistent(pDevice->pcid,
663 pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
664 pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
665 pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
666 pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
667 ,
668 pDevice->aRD0Ring, pDevice->pool_dma
669 );
Forest Bond5449c682009-04-25 10:30:44 -0400670
Joe Perches915006c2013-03-18 10:44:47 -0700671 if (pDevice->tx0_bufs)
672 pci_free_consistent(pDevice->pcid,
673 pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
674 pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
675 CB_BEACON_BUF_SIZE +
676 CB_MAX_BUF_SIZE,
677 pDevice->tx0_bufs, pDevice->tx_bufs_dma0
678 );
Forest Bond5449c682009-04-25 10:30:44 -0400679}
680
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100681static void device_init_rd0_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200682{
Joe Perches915006c2013-03-18 10:44:47 -0700683 int i;
684 dma_addr_t curr = pDevice->rd0_pool_dma;
685 PSRxDesc pDesc;
Forest Bond5449c682009-04-25 10:30:44 -0400686
Joe Perches915006c2013-03-18 10:44:47 -0700687 /* Init the RD0 ring entries */
688 for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
689 pDesc = &(pDevice->aRD0Ring[i]);
690 pDesc->pRDInfo = alloc_rd_info();
691 ASSERT(pDesc->pRDInfo);
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100692 if (!device_alloc_rx_buf(pDevice, pDesc))
693 dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
694
Joe Perches915006c2013-03-18 10:44:47 -0700695 pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
696 pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
697 pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
698 }
Forest Bond5449c682009-04-25 10:30:44 -0400699
Joe Perches915006c2013-03-18 10:44:47 -0700700 if (i > 0)
701 pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma);
702 pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
Forest Bond5449c682009-04-25 10:30:44 -0400703}
704
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100705static void device_init_rd1_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200706{
Joe Perches915006c2013-03-18 10:44:47 -0700707 int i;
708 dma_addr_t curr = pDevice->rd1_pool_dma;
709 PSRxDesc pDesc;
Forest Bond5449c682009-04-25 10:30:44 -0400710
Joe Perches915006c2013-03-18 10:44:47 -0700711 /* Init the RD1 ring entries */
712 for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
713 pDesc = &(pDevice->aRD1Ring[i]);
714 pDesc->pRDInfo = alloc_rd_info();
715 ASSERT(pDesc->pRDInfo);
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100716 if (!device_alloc_rx_buf(pDevice, pDesc))
717 dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
718
Joe Perches915006c2013-03-18 10:44:47 -0700719 pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
720 pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
721 pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
722 }
Forest Bond5449c682009-04-25 10:30:44 -0400723
Joe Perches915006c2013-03-18 10:44:47 -0700724 if (i > 0)
725 pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma);
726 pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
Forest Bond5449c682009-04-25 10:30:44 -0400727}
728
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100729static void device_free_rd0_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200730{
Joe Perches915006c2013-03-18 10:44:47 -0700731 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400732
Joe Perches915006c2013-03-18 10:44:47 -0700733 for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) {
734 PSRxDesc pDesc = &(pDevice->aRD0Ring[i]);
735 PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo;
Forest Bond5449c682009-04-25 10:30:44 -0400736
Joe Perches915006c2013-03-18 10:44:47 -0700737 pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
738 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400739
Joe Perches915006c2013-03-18 10:44:47 -0700740 dev_kfree_skb(pRDInfo->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400741
Tapasweni Pathak61d566a2014-10-08 20:41:48 +0530742 kfree(pDesc->pRDInfo);
Joe Perches915006c2013-03-18 10:44:47 -0700743 }
Forest Bond5449c682009-04-25 10:30:44 -0400744}
745
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100746static void device_free_rd1_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200747{
Joe Perches915006c2013-03-18 10:44:47 -0700748 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400749
Joe Perches915006c2013-03-18 10:44:47 -0700750 for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) {
751 PSRxDesc pDesc = &(pDevice->aRD1Ring[i]);
752 PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo;
Forest Bond5449c682009-04-25 10:30:44 -0400753
Joe Perches915006c2013-03-18 10:44:47 -0700754 pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
755 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400756
Joe Perches915006c2013-03-18 10:44:47 -0700757 dev_kfree_skb(pRDInfo->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400758
Tapasweni Pathak61d566a2014-10-08 20:41:48 +0530759 kfree(pDesc->pRDInfo);
Joe Perches915006c2013-03-18 10:44:47 -0700760 }
Forest Bond5449c682009-04-25 10:30:44 -0400761}
762
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100763static void device_init_td0_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200764{
Joe Perches915006c2013-03-18 10:44:47 -0700765 int i;
766 dma_addr_t curr;
767 PSTxDesc pDesc;
Forest Bond5449c682009-04-25 10:30:44 -0400768
Joe Perches915006c2013-03-18 10:44:47 -0700769 curr = pDevice->td0_pool_dma;
770 for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
771 pDesc = &(pDevice->apTD0Rings[i]);
772 pDesc->pTDInfo = alloc_td_info();
773 ASSERT(pDesc->pTDInfo);
774 if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
775 pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
776 pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
777 }
778 pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
779 pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
780 pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
781 }
Forest Bond5449c682009-04-25 10:30:44 -0400782
Joe Perches915006c2013-03-18 10:44:47 -0700783 if (i > 0)
784 pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma);
785 pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
Forest Bond5449c682009-04-25 10:30:44 -0400786}
787
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100788static void device_init_td1_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200789{
Joe Perches915006c2013-03-18 10:44:47 -0700790 int i;
791 dma_addr_t curr;
792 PSTxDesc pDesc;
Forest Bond5449c682009-04-25 10:30:44 -0400793
Joe Perches915006c2013-03-18 10:44:47 -0700794 /* Init the TD ring entries */
795 curr = pDevice->td1_pool_dma;
796 for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) {
797 pDesc = &(pDevice->apTD1Rings[i]);
798 pDesc->pTDInfo = alloc_td_info();
799 ASSERT(pDesc->pTDInfo);
800 if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
801 pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
802 pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
803 }
804 pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]);
805 pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
806 pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
807 }
Forest Bond5449c682009-04-25 10:30:44 -0400808
Joe Perches915006c2013-03-18 10:44:47 -0700809 if (i > 0)
810 pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma);
811 pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
Forest Bond5449c682009-04-25 10:30:44 -0400812}
813
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100814static void device_free_td0_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200815{
Joe Perches915006c2013-03-18 10:44:47 -0700816 int i;
Guillaume Clement6b711272014-07-25 01:06:16 +0200817
Joe Perches915006c2013-03-18 10:44:47 -0700818 for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
819 PSTxDesc pDesc = &(pDevice->apTD0Rings[i]);
820 PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
Forest Bond5449c682009-04-25 10:30:44 -0400821
Joe Perches915006c2013-03-18 10:44:47 -0700822 if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
823 pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
824 pTDInfo->skb->len, PCI_DMA_TODEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400825
Joe Perches915006c2013-03-18 10:44:47 -0700826 if (pTDInfo->skb)
827 dev_kfree_skb(pTDInfo->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400828
Tapasweni Pathak61d566a2014-10-08 20:41:48 +0530829 kfree(pDesc->pTDInfo);
Joe Perches915006c2013-03-18 10:44:47 -0700830 }
Forest Bond5449c682009-04-25 10:30:44 -0400831}
832
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100833static void device_free_td1_ring(struct vnt_private *pDevice)
Guillaume Clement84b50762014-07-25 01:06:18 +0200834{
Joe Perches915006c2013-03-18 10:44:47 -0700835 int i;
Forest Bond5449c682009-04-25 10:30:44 -0400836
Joe Perches915006c2013-03-18 10:44:47 -0700837 for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
838 PSTxDesc pDesc = &(pDevice->apTD1Rings[i]);
839 PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
Forest Bond5449c682009-04-25 10:30:44 -0400840
Joe Perches915006c2013-03-18 10:44:47 -0700841 if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
842 pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
843 pTDInfo->skb->len, PCI_DMA_TODEVICE);
Forest Bond5449c682009-04-25 10:30:44 -0400844
Joe Perches915006c2013-03-18 10:44:47 -0700845 if (pTDInfo->skb)
846 dev_kfree_skb(pTDInfo->skb);
Forest Bond5449c682009-04-25 10:30:44 -0400847
Tapasweni Pathak61d566a2014-10-08 20:41:48 +0530848 kfree(pDesc->pTDInfo);
Joe Perches915006c2013-03-18 10:44:47 -0700849 }
Forest Bond5449c682009-04-25 10:30:44 -0400850}
851
Forest Bond5449c682009-04-25 10:30:44 -0400852/*-----------------------------------------------------------------*/
853
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100854static int device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx)
Guillaume Clement84b50762014-07-25 01:06:18 +0200855{
Joe Perches915006c2013-03-18 10:44:47 -0700856 PSRxDesc pRD;
857 int works = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400858
Joe Perches915006c2013-03-18 10:44:47 -0700859 for (pRD = pDevice->pCurrRD[uIdx];
860 pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST;
861 pRD = pRD->next) {
Joe Perches915006c2013-03-18 10:44:47 -0700862 if (works++ > 15)
863 break;
Malcolm Priestley33b1c8c2014-10-29 17:43:36 +0000864 if (vnt_receive_frame(pDevice, pRD)) {
Joe Perches915006c2013-03-18 10:44:47 -0700865 if (!device_alloc_rx_buf(pDevice, pRD)) {
Malcolm Priestley42f709e2014-09-22 21:27:46 +0100866 dev_err(&pDevice->pcid->dev,
867 "can not allocate rx buf\n");
Joe Perches915006c2013-03-18 10:44:47 -0700868 break;
869 }
870 }
871 pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
Joe Perches915006c2013-03-18 10:44:47 -0700872 }
Forest Bond5449c682009-04-25 10:30:44 -0400873
Joe Perches915006c2013-03-18 10:44:47 -0700874 pDevice->pCurrRD[uIdx] = pRD;
Forest Bond5449c682009-04-25 10:30:44 -0400875
Joe Perches915006c2013-03-18 10:44:47 -0700876 return works;
Forest Bond5449c682009-04-25 10:30:44 -0400877}
878
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100879static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pRD)
Guillaume Clement84b50762014-07-25 01:06:18 +0200880{
Joe Perches915006c2013-03-18 10:44:47 -0700881 PDEVICE_RD_INFO pRDInfo = pRD->pRDInfo;
Forest Bond5449c682009-04-25 10:30:44 -0400882
Joe Perches915006c2013-03-18 10:44:47 -0700883 pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
Joe Perches915006c2013-03-18 10:44:47 -0700884 if (pRDInfo->skb == NULL)
885 return false;
886 ASSERT(pRDInfo->skb);
Malcolm Priestley33b1c8c2014-10-29 17:43:36 +0000887
888 pRDInfo->skb_dma =
889 pci_map_single(pDevice->pcid,
890 skb_put(pRDInfo->skb, skb_tailroom(pRDInfo->skb)),
891 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
892
Joe Perches915006c2013-03-18 10:44:47 -0700893 *((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */
Forest Bond5449c682009-04-25 10:30:44 -0400894
Joe Perches915006c2013-03-18 10:44:47 -0700895 pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
896 pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
897 pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
898 pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma);
Forest Bond5449c682009-04-25 10:30:44 -0400899
Joe Perches915006c2013-03-18 10:44:47 -0700900 return true;
Forest Bond5449c682009-04-25 10:30:44 -0400901}
902
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000903static const u8 fallback_rate0[5][5] = {
904 {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
905 {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
906 {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
907 {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
908 {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
909};
910
911static const u8 fallback_rate1[5][5] = {
912 {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
913 {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
914 {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
915 {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
916 {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
917};
918
919static int vnt_int_report_rate(struct vnt_private *priv,
920 PDEVICE_TD_INFO context, u8 tsr0, u8 tsr1)
921{
922 struct vnt_tx_fifo_head *fifo_head;
923 struct ieee80211_tx_info *info;
924 struct ieee80211_rate *rate;
925 u16 fb_option;
926 u8 tx_retry = (tsr0 & TSR0_NCR);
927 s8 idx;
928
929 if (!context)
930 return -ENOMEM;
931
932 if (!context->skb)
933 return -EINVAL;
934
935 fifo_head = (struct vnt_tx_fifo_head *)context->buf;
936 fb_option = (le16_to_cpu(fifo_head->fifo_ctl) &
937 (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1));
938
939 info = IEEE80211_SKB_CB(context->skb);
940 idx = info->control.rates[0].idx;
941
942 if (fb_option && !(tsr1 & TSR1_TERR)) {
943 u8 tx_rate;
944 u8 retry = tx_retry;
945
946 rate = ieee80211_get_tx_rate(priv->hw, info);
947 tx_rate = rate->hw_value - RATE_18M;
948
949 if (retry > 4)
950 retry = 4;
951
952 if (fb_option & FIFOCTL_AUTO_FB_0)
953 tx_rate = fallback_rate0[tx_rate][retry];
954 else if (fb_option & FIFOCTL_AUTO_FB_1)
955 tx_rate = fallback_rate1[tx_rate][retry];
956
957 if (info->band == IEEE80211_BAND_5GHZ)
958 idx = tx_rate - RATE_6M;
959 else
960 idx = tx_rate;
961 }
962
963 ieee80211_tx_info_clear_status(info);
964
965 info->status.rates[0].count = tx_retry;
966
967 if (!(tsr1 & TSR1_TERR)) {
968 info->status.rates[0].idx = idx;
969 info->flags |= IEEE80211_TX_STAT_ACK;
970 }
971
972 return 0;
973}
974
Malcolm Priestley3f8597f2014-08-10 15:46:55 +0100975static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx)
Guillaume Clement84b50762014-07-25 01:06:18 +0200976{
Joe Perches915006c2013-03-18 10:44:47 -0700977 PSTxDesc pTD;
Joe Perches915006c2013-03-18 10:44:47 -0700978 int works = 0;
979 unsigned char byTsr0;
980 unsigned char byTsr1;
Forest Bond5449c682009-04-25 10:30:44 -0400981
Joe Perches915006c2013-03-18 10:44:47 -0700982 for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) {
Joe Perches915006c2013-03-18 10:44:47 -0700983 if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
984 break;
985 if (works++ > 15)
986 break;
Forest Bond5449c682009-04-25 10:30:44 -0400987
Joe Perches915006c2013-03-18 10:44:47 -0700988 byTsr0 = pTD->m_td0TD0.byTSR0;
989 byTsr1 = pTD->m_td0TD0.byTSR1;
Forest Bond5449c682009-04-25 10:30:44 -0400990
Joe Perches915006c2013-03-18 10:44:47 -0700991 //Only the status of first TD in the chain is correct
992 if (pTD->m_td1TD1.byTCR & TCR_STP) {
Joe Perches915006c2013-03-18 10:44:47 -0700993 if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
Forest Bond5449c682009-04-25 10:30:44 -0400994
Malcolm Priestley59918bea2014-10-29 17:43:48 +0000995 vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1);
Forest Bond5449c682009-04-25 10:30:44 -0400996
Joe Perches915006c2013-03-18 10:44:47 -0700997 if (!(byTsr1 & TSR1_TERR)) {
998 if (byTsr0 != 0) {
Joe Perches48caf5a2014-08-17 09:17:04 -0700999 pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
1000 (int)uIdx, byTsr1,
1001 byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -07001002 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001003 } else {
Joe Perches48caf5a2014-08-17 09:17:04 -07001004 pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n",
1005 (int)uIdx, byTsr1, byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -07001006 }
1007 }
Forest Bond5449c682009-04-25 10:30:44 -04001008
Joe Perches915006c2013-03-18 10:44:47 -07001009 if (byTsr1 & TSR1_TERR) {
1010 if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
Joe Perches48caf5a2014-08-17 09:17:04 -07001011 pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
1012 (int)uIdx, byTsr1, byTsr0);
Joe Perches915006c2013-03-18 10:44:47 -07001013 }
Joe Perches915006c2013-03-18 10:44:47 -07001014 }
1015 device_free_tx_buf(pDevice, pTD);
1016 pDevice->iTDUsed[uIdx]--;
1017 }
1018 }
Forest Bond5449c682009-04-25 10:30:44 -04001019
Joe Perches915006c2013-03-18 10:44:47 -07001020 pDevice->apTailTD[uIdx] = pTD;
Forest Bond5449c682009-04-25 10:30:44 -04001021
Joe Perches915006c2013-03-18 10:44:47 -07001022 return works;
Forest Bond5449c682009-04-25 10:30:44 -04001023}
1024
Malcolm Priestley3f8597f2014-08-10 15:46:55 +01001025static void device_error(struct vnt_private *pDevice, unsigned short status)
Guillaume Clement84b50762014-07-25 01:06:18 +02001026{
Joe Perches915006c2013-03-18 10:44:47 -07001027 if (status & ISR_FETALERR) {
Malcolm Priestley42f709e2014-09-22 21:27:46 +01001028 dev_err(&pDevice->pcid->dev, "Hardware fatal error\n");
1029
Joe Perches915006c2013-03-18 10:44:47 -07001030 MACbShutdown(pDevice->PortOffset);
1031 return;
1032 }
Forest Bond5449c682009-04-25 10:30:44 -04001033}
1034
Malcolm Priestley3f8597f2014-08-10 15:46:55 +01001035static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc)
Guillaume Clement84b50762014-07-25 01:06:18 +02001036{
Joe Perches915006c2013-03-18 10:44:47 -07001037 PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
1038 struct sk_buff *skb = pTDInfo->skb;
Forest Bond5449c682009-04-25 10:30:44 -04001039
Joe Perches915006c2013-03-18 10:44:47 -07001040 // pre-allocated buf_dma can't be unmapped.
1041 if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
1042 pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len,
1043 PCI_DMA_TODEVICE);
1044 }
Forest Bond5449c682009-04-25 10:30:44 -04001045
Malcolm Priestley59918bea2014-10-29 17:43:48 +00001046 if (pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
1047 ieee80211_tx_status_irqsafe(pDevice->hw, skb);
1048 else
Joe Perches915006c2013-03-18 10:44:47 -07001049 dev_kfree_skb_irq(skb);
Forest Bond5449c682009-04-25 10:30:44 -04001050
Joe Perches915006c2013-03-18 10:44:47 -07001051 pTDInfo->skb_dma = 0;
Guillaume Clement70ae5432014-07-25 01:06:28 +02001052 pTDInfo->skb = NULL;
Joe Perches915006c2013-03-18 10:44:47 -07001053 pTDInfo->byFlags = 0;
Forest Bond5449c682009-04-25 10:30:44 -04001054}
1055
Guillaume Clement84b50762014-07-25 01:06:18 +02001056static irqreturn_t device_intr(int irq, void *dev_instance)
1057{
Malcolm Priestleye70abce2014-10-29 17:43:47 +00001058 struct vnt_private *pDevice = dev_instance;
Joe Perches915006c2013-03-18 10:44:47 -07001059 int max_count = 0;
1060 unsigned long dwMIBCounter = 0;
Joe Perches915006c2013-03-18 10:44:47 -07001061 unsigned char byOrgPageSel = 0;
1062 int handled = 0;
Joe Perches915006c2013-03-18 10:44:47 -07001063 int ii = 0;
Malcolm Priestley6cff1f62014-07-23 21:35:11 +01001064 unsigned long flags;
Forest Bond5449c682009-04-25 10:30:44 -04001065
Joe Perches915006c2013-03-18 10:44:47 -07001066 MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
Forest Bond5449c682009-04-25 10:30:44 -04001067
Joe Perches915006c2013-03-18 10:44:47 -07001068 if (pDevice->dwIsr == 0)
1069 return IRQ_RETVAL(handled);
Forest Bond5449c682009-04-25 10:30:44 -04001070
Joe Perches915006c2013-03-18 10:44:47 -07001071 if (pDevice->dwIsr == 0xffffffff) {
Joe Perches48caf5a2014-08-17 09:17:04 -07001072 pr_debug("dwIsr = 0xffff\n");
Joe Perches915006c2013-03-18 10:44:47 -07001073 return IRQ_RETVAL(handled);
1074 }
Forest Bond5449c682009-04-25 10:30:44 -04001075
Joe Perches915006c2013-03-18 10:44:47 -07001076 handled = 1;
1077 MACvIntDisable(pDevice->PortOffset);
Malcolm Priestley6cff1f62014-07-23 21:35:11 +01001078
1079 spin_lock_irqsave(&pDevice->lock, flags);
Forest Bond5449c682009-04-25 10:30:44 -04001080
Joe Perches915006c2013-03-18 10:44:47 -07001081 //Make sure current page is 0
1082 VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001083 if (byOrgPageSel == 1)
Joe Perches915006c2013-03-18 10:44:47 -07001084 MACvSelectPage0(pDevice->PortOffset);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001085 else
Joe Perches915006c2013-03-18 10:44:47 -07001086 byOrgPageSel = 0;
Forest Bond5449c682009-04-25 10:30:44 -04001087
Joe Perches915006c2013-03-18 10:44:47 -07001088 MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
1089 // TBD....
1090 // Must do this after doing rx/tx, cause ISR bit is slow
1091 // than RD/TD write back
1092 // update ISR counter
1093 STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter);
1094 while (pDevice->dwIsr != 0) {
Joe Perches915006c2013-03-18 10:44:47 -07001095 STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
1096 MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr);
Forest Bond5449c682009-04-25 10:30:44 -04001097
Joe Perches915006c2013-03-18 10:44:47 -07001098 if (pDevice->dwIsr & ISR_FETALERR) {
Joe Perches48caf5a2014-08-17 09:17:04 -07001099 pr_debug(" ISR_FETALERR\n");
Joe Perches915006c2013-03-18 10:44:47 -07001100 VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0);
1101 VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
1102 device_error(pDevice, pDevice->dwIsr);
1103 }
Forest Bond5449c682009-04-25 10:30:44 -04001104
Joe Perches915006c2013-03-18 10:44:47 -07001105 if (pDevice->dwIsr & ISR_TBTT) {
Malcolm Priestley59918bea2014-10-29 17:43:48 +00001106 if (pDevice->vif &&
1107 pDevice->op_mode != NL80211_IFTYPE_ADHOC) {
1108 if (pDevice->bUpdateBBVGA &&
Malcolm Priestleyd8558022014-10-29 17:44:08 +00001109 !(pDevice->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
Malcolm Priestley59918bea2014-10-29 17:43:48 +00001110 pDevice->vif->bss_conf.assoc &&
1111 pDevice->uCurrRSSI) {
Joe Perches915006c2013-03-18 10:44:47 -07001112 long ldBm;
Forest Bond5449c682009-04-25 10:30:44 -04001113
Joe Perches915006c2013-03-18 10:44:47 -07001114 RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm);
1115 for (ii = 0; ii < BB_VGA_LEVEL; ii++) {
1116 if (ldBm < pDevice->ldBmThreshold[ii]) {
1117 pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
1118 break;
1119 }
1120 }
1121 if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
1122 pDevice->uBBVGADiffCount++;
1123 if (pDevice->uBBVGADiffCount == 1) {
1124 // first VGA diff gain
1125 BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
Joe Perches48caf5a2014-08-17 09:17:04 -07001126 pr_debug("First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
1127 (int)ldBm,
1128 pDevice->byBBVGANew,
1129 pDevice->byBBVGACurrent,
1130 (int)pDevice->uBBVGADiffCount);
Joe Perches915006c2013-03-18 10:44:47 -07001131 }
1132 if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
Joe Perches48caf5a2014-08-17 09:17:04 -07001133 pr_debug("RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
1134 (int)ldBm,
1135 pDevice->byBBVGANew,
1136 pDevice->byBBVGACurrent,
1137 (int)pDevice->uBBVGADiffCount);
Joe Perches915006c2013-03-18 10:44:47 -07001138 BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
1139 }
1140 } else {
1141 pDevice->uBBVGADiffCount = 1;
1142 }
1143 }
1144 }
Forest Bond5449c682009-04-25 10:30:44 -04001145
Joe Perches915006c2013-03-18 10:44:47 -07001146 pDevice->bBeaconSent = false;
Guido Martínezbc5cf652014-04-19 16:45:00 -03001147 if (pDevice->bEnablePSMode)
Joe Perches915006c2013-03-18 10:44:47 -07001148 PSbIsNextTBTTWakeUp((void *)pDevice);
Forest Bond5449c682009-04-25 10:30:44 -04001149
Malcolm Priestleye70abce2014-10-29 17:43:47 +00001150 if ((pDevice->op_mode == NL80211_IFTYPE_AP ||
1151 pDevice->op_mode == NL80211_IFTYPE_ADHOC) &&
1152 pDevice->vif->bss_conf.enable_beacon) {
Joe Perches915006c2013-03-18 10:44:47 -07001153 MACvOneShotTimer1MicroSec(pDevice->PortOffset,
Malcolm Priestleye70abce2014-10-29 17:43:47 +00001154 (pDevice->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10);
Joe Perches915006c2013-03-18 10:44:47 -07001155 }
Forest Bond5449c682009-04-25 10:30:44 -04001156
Guido Martínez4e8a7e52014-04-19 16:44:59 -03001157 /* TODO: adhoc PS mode */
Forest Bond5449c682009-04-25 10:30:44 -04001158
Joe Perches915006c2013-03-18 10:44:47 -07001159 }
Forest Bond5449c682009-04-25 10:30:44 -04001160
Joe Perches915006c2013-03-18 10:44:47 -07001161 if (pDevice->dwIsr & ISR_BNTX) {
Malcolm Priestleya9873672014-08-30 22:25:49 +01001162 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
Joe Perches915006c2013-03-18 10:44:47 -07001163 pDevice->bIsBeaconBufReadySet = false;
1164 pDevice->cbBeaconBufReadySetCnt = 0;
1165 }
Forest Bond5449c682009-04-25 10:30:44 -04001166
Joe Perches915006c2013-03-18 10:44:47 -07001167 pDevice->bBeaconSent = true;
Joe Perches915006c2013-03-18 10:44:47 -07001168 }
Forest Bond5449c682009-04-25 10:30:44 -04001169
Guido Martínezbc5cf652014-04-19 16:45:00 -03001170 if (pDevice->dwIsr & ISR_RXDMA0)
Joe Perches915006c2013-03-18 10:44:47 -07001171 max_count += device_rx_srv(pDevice, TYPE_RXDMA0);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001172
1173 if (pDevice->dwIsr & ISR_RXDMA1)
Joe Perches915006c2013-03-18 10:44:47 -07001174 max_count += device_rx_srv(pDevice, TYPE_RXDMA1);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001175
1176 if (pDevice->dwIsr & ISR_TXDMA0)
Joe Perches915006c2013-03-18 10:44:47 -07001177 max_count += device_tx_srv(pDevice, TYPE_TXDMA0);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001178
1179 if (pDevice->dwIsr & ISR_AC0DMA)
Joe Perches915006c2013-03-18 10:44:47 -07001180 max_count += device_tx_srv(pDevice, TYPE_AC0DMA);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001181
Joe Perches915006c2013-03-18 10:44:47 -07001182 if (pDevice->dwIsr & ISR_SOFTTIMER1) {
Malcolm Priestleye70abce2014-10-29 17:43:47 +00001183 if (pDevice->vif) {
1184 if (pDevice->vif->bss_conf.enable_beacon)
1185 vnt_beacon_make(pDevice, pDevice->vif);
Joe Perches915006c2013-03-18 10:44:47 -07001186 }
Joe Perches915006c2013-03-18 10:44:47 -07001187 }
Forest Bond5449c682009-04-25 10:30:44 -04001188
Malcolm Priestley54fbb2d2014-11-04 14:49:46 +00001189 /* If both buffers available wake the queue */
1190 if (pDevice->vif) {
1191 if (AVAIL_TD(pDevice, TYPE_TXDMA0) &&
1192 AVAIL_TD(pDevice, TYPE_AC0DMA) &&
1193 ieee80211_queue_stopped(pDevice->hw, 0))
1194 ieee80211_wake_queues(pDevice->hw);
1195 }
1196
Joe Perches915006c2013-03-18 10:44:47 -07001197 MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
Forest Bond5449c682009-04-25 10:30:44 -04001198
Joe Perches915006c2013-03-18 10:44:47 -07001199 MACvReceive0(pDevice->PortOffset);
1200 MACvReceive1(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -04001201
Joe Perches915006c2013-03-18 10:44:47 -07001202 if (max_count > pDevice->sOpts.int_works)
1203 break;
1204 }
Forest Bond5449c682009-04-25 10:30:44 -04001205
Guido Martínezbc5cf652014-04-19 16:45:00 -03001206 if (byOrgPageSel == 1)
Joe Perches915006c2013-03-18 10:44:47 -07001207 MACvSelectPage1(pDevice->PortOffset);
Forest Bond5449c682009-04-25 10:30:44 -04001208
Malcolm Priestley6cff1f62014-07-23 21:35:11 +01001209 spin_unlock_irqrestore(&pDevice->lock, flags);
1210
Joe Perches915006c2013-03-18 10:44:47 -07001211 MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
Forest Bond5449c682009-04-25 10:30:44 -04001212
Joe Perches915006c2013-03-18 10:44:47 -07001213 return IRQ_RETVAL(handled);
Forest Bond5449c682009-04-25 10:30:44 -04001214}
1215
Malcolm Priestley67013f22014-10-29 17:43:43 +00001216static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
1217{
1218 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1219 PSTxDesc head_td;
1220 u32 dma_idx = TYPE_AC0DMA;
1221 unsigned long flags;
1222
1223 spin_lock_irqsave(&priv->lock, flags);
1224
1225 if (!ieee80211_is_data(hdr->frame_control))
1226 dma_idx = TYPE_TXDMA0;
1227
1228 if (AVAIL_TD(priv, dma_idx) < 1) {
1229 spin_unlock_irqrestore(&priv->lock, flags);
1230 return -ENOMEM;
1231 }
1232
1233 head_td = priv->apCurrTD[dma_idx];
1234
1235 head_td->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
1236
1237 head_td->pTDInfo->skb = skb;
1238
1239 priv->iTDUsed[dma_idx]++;
1240
1241 /* Take ownership */
1242 wmb();
1243 head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
1244
1245 /* get Next */
1246 wmb();
1247 priv->apCurrTD[dma_idx] = head_td->next;
1248
1249 spin_unlock_irqrestore(&priv->lock, flags);
1250
1251 vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
1252
1253 if (MACbIsRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
1254 MACbPSWakeup(priv->PortOffset);
1255
1256 spin_lock_irqsave(&priv->lock, flags);
1257
1258 priv->bPWBitOn = false;
1259
1260 head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
1261
1262 if (dma_idx == TYPE_AC0DMA)
1263 MACvTransmitAC0(priv->PortOffset);
1264 else
1265 MACvTransmit0(priv->PortOffset);
1266
1267 spin_unlock_irqrestore(&priv->lock, flags);
1268
1269 return 0;
1270}
1271
1272static void vnt_tx_80211(struct ieee80211_hw *hw,
1273 struct ieee80211_tx_control *control,
1274 struct sk_buff *skb)
1275{
1276 struct vnt_private *priv = hw->priv;
1277
1278 ieee80211_stop_queues(hw);
1279
1280 if (vnt_tx_packet(priv, skb)) {
1281 ieee80211_free_txskb(hw, skb);
1282
1283 ieee80211_wake_queues(hw);
1284 }
1285}
1286
1287static int vnt_start(struct ieee80211_hw *hw)
1288{
1289 struct vnt_private *priv = hw->priv;
1290 int ret;
1291
1292 priv->rx_buf_sz = PKT_BUF_SZ;
1293 if (!device_init_rings(priv))
1294 return -ENOMEM;
1295
1296 ret = request_irq(priv->pcid->irq, &device_intr,
1297 IRQF_SHARED, "vt6655", priv);
1298 if (ret) {
1299 dev_dbg(&priv->pcid->dev, "failed to start irq\n");
1300 return ret;
1301 }
1302
1303 dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n");
1304 device_init_rd0_ring(priv);
1305 device_init_rd1_ring(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001306 device_init_td0_ring(priv);
1307 device_init_td1_ring(priv);
1308
1309 device_init_registers(priv);
1310
1311 dev_dbg(&priv->pcid->dev, "call MACvIntEnable\n");
1312 MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE);
1313
1314 ieee80211_wake_queues(hw);
1315
1316 return 0;
1317}
1318
1319static void vnt_stop(struct ieee80211_hw *hw)
1320{
1321 struct vnt_private *priv = hw->priv;
1322
1323 ieee80211_stop_queues(hw);
1324
1325 MACbShutdown(priv->PortOffset);
1326 MACbSoftwareReset(priv->PortOffset);
1327 CARDbRadioPowerOff(priv);
1328
1329 device_free_td0_ring(priv);
1330 device_free_td1_ring(priv);
1331 device_free_rd0_ring(priv);
1332 device_free_rd1_ring(priv);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001333 device_free_rings(priv);
1334
1335 free_irq(priv->pcid->irq, priv);
1336}
1337
1338static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1339{
1340 struct vnt_private *priv = hw->priv;
1341
1342 priv->vif = vif;
1343
1344 switch (vif->type) {
1345 case NL80211_IFTYPE_STATION:
1346 if (priv->bDiversityRegCtlON)
1347 device_init_diversity_timer(priv);
1348 break;
1349 case NL80211_IFTYPE_ADHOC:
1350 MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST);
1351
1352 MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
1353
1354 break;
1355 case NL80211_IFTYPE_AP:
1356 MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST);
1357
1358 MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
1359
1360 break;
1361 default:
1362 return -EOPNOTSUPP;
1363 }
1364
1365 priv->op_mode = vif->type;
1366
1367 return 0;
1368}
1369
1370static void vnt_remove_interface(struct ieee80211_hw *hw,
1371 struct ieee80211_vif *vif)
1372{
1373 struct vnt_private *priv = hw->priv;
1374
1375 switch (vif->type) {
1376 case NL80211_IFTYPE_STATION:
1377 if (priv->bDiversityRegCtlON) {
1378 del_timer(&priv->TimerSQ3Tmax1);
1379 del_timer(&priv->TimerSQ3Tmax2);
1380 del_timer(&priv->TimerSQ3Tmax3);
1381 }
1382 break;
1383 case NL80211_IFTYPE_ADHOC:
1384 MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
1385 MACvRegBitsOff(priv->PortOffset,
1386 MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1387 MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
1388 break;
1389 case NL80211_IFTYPE_AP:
1390 MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
1391 MACvRegBitsOff(priv->PortOffset,
1392 MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1393 MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
1394 break;
1395 default:
1396 break;
1397 }
1398
1399 priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
1400}
1401
1402
1403static int vnt_config(struct ieee80211_hw *hw, u32 changed)
1404{
1405 struct vnt_private *priv = hw->priv;
1406 struct ieee80211_conf *conf = &hw->conf;
1407 u8 bb_type;
1408
1409 if (changed & IEEE80211_CONF_CHANGE_PS) {
1410 if (conf->flags & IEEE80211_CONF_PS)
1411 PSvEnablePowerSaving(priv, conf->listen_interval);
1412 else
1413 PSvDisablePowerSaving(priv);
1414 }
1415
1416 if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
1417 (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
1418 set_channel(priv, conf->chandef.chan->hw_value);
1419
1420 if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
1421 bb_type = BB_TYPE_11A;
1422 else
1423 bb_type = BB_TYPE_11G;
1424
1425 if (priv->byBBType != bb_type) {
1426 priv->byBBType = bb_type;
1427
Malcolm Priestleybfb6c862014-11-07 19:06:06 +00001428 CARDbSetPhyParameter(priv, priv->byBBType);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001429 }
1430 }
1431
1432 if (changed & IEEE80211_CONF_CHANGE_POWER) {
1433 if (priv->byBBType == BB_TYPE_11B)
1434 priv->wCurrentRate = RATE_1M;
1435 else
1436 priv->wCurrentRate = RATE_54M;
1437
1438 RFbSetPower(priv, priv->wCurrentRate,
1439 conf->chandef.chan->hw_value);
1440 }
1441
1442 return 0;
1443}
1444
1445static void vnt_bss_info_changed(struct ieee80211_hw *hw,
1446 struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf,
1447 u32 changed)
1448{
1449 struct vnt_private *priv = hw->priv;
1450
1451 priv->current_aid = conf->aid;
1452
1453 if (changed & BSS_CHANGED_BSSID)
1454 MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid);
1455
1456 if (changed & BSS_CHANGED_BASIC_RATES) {
1457 priv->basic_rates = conf->basic_rates;
1458
1459 CARDvUpdateBasicTopRate(priv);
1460
1461 dev_dbg(&priv->pcid->dev,
1462 "basic rates %x\n", conf->basic_rates);
1463 }
1464
1465 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1466 if (conf->use_short_preamble) {
1467 MACvEnableBarkerPreambleMd(priv->PortOffset);
1468 priv->byPreambleType = true;
1469 } else {
1470 MACvDisableBarkerPreambleMd(priv->PortOffset);
1471 priv->byPreambleType = false;
1472 }
1473 }
1474
1475 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1476 if (conf->use_cts_prot)
1477 MACvEnableProtectMD(priv->PortOffset);
1478 else
1479 MACvDisableProtectMD(priv->PortOffset);
1480 }
1481
1482 if (changed & BSS_CHANGED_ERP_SLOT) {
1483 if (conf->use_short_slot)
1484 priv->bShortSlotTime = true;
1485 else
1486 priv->bShortSlotTime = false;
1487
Malcolm Priestleybfb6c862014-11-07 19:06:06 +00001488 CARDbSetPhyParameter(priv, priv->byBBType);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001489 BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]);
1490 }
1491
1492 if (changed & BSS_CHANGED_TXPOWER)
1493 RFbSetPower(priv, priv->wCurrentRate,
1494 conf->chandef.chan->hw_value);
1495
1496 if (changed & BSS_CHANGED_BEACON_ENABLED) {
1497 dev_dbg(&priv->pcid->dev,
1498 "Beacon enable %d\n", conf->enable_beacon);
1499
1500 if (conf->enable_beacon) {
1501 vnt_beacon_enable(priv, vif, conf);
1502
1503 MACvRegBitsOn(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
1504 } else {
1505 MACvRegBitsOff(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
1506 }
1507 }
1508
1509 if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) {
1510 if (conf->assoc) {
1511 CARDbUpdateTSF(priv, conf->beacon_rate->hw_value,
1512 conf->sync_device_ts, conf->sync_tsf);
1513
1514 CARDbSetBeaconPeriod(priv, conf->beacon_int);
1515
Malcolm Priestley738487f2014-11-12 21:11:09 +00001516 CARDvSetFirstNextTBTT(priv, conf->beacon_int);
Malcolm Priestleyc7b14ea2014-10-29 17:44:09 +00001517 } else {
1518 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL,
1519 TFTCTL_TSFCNTRST);
1520 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL,
1521 TFTCTL_TSFCNTREN);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001522 }
1523 }
1524}
1525
1526static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
1527 struct netdev_hw_addr_list *mc_list)
1528{
1529 struct vnt_private *priv = hw->priv;
1530 struct netdev_hw_addr *ha;
1531 u64 mc_filter = 0;
1532 u32 bit_nr = 0;
1533
1534 netdev_hw_addr_list_for_each(ha, mc_list) {
1535 bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
1536
1537 mc_filter |= 1ULL << (bit_nr & 0x3f);
1538 }
1539
1540 priv->mc_list_count = mc_list->count;
1541
1542 return mc_filter;
1543}
1544
1545static void vnt_configure(struct ieee80211_hw *hw,
1546 unsigned int changed_flags, unsigned int *total_flags, u64 multicast)
1547{
1548 struct vnt_private *priv = hw->priv;
1549 u8 rx_mode = 0;
1550
1551 *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_PROMISC_IN_BSS |
1552 FIF_BCN_PRBRESP_PROMISC;
1553
1554 VNSvInPortB(priv->PortOffset + MAC_REG_RCR, &rx_mode);
1555
1556 dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode);
1557
1558 if (changed_flags & FIF_PROMISC_IN_BSS) {
1559 /* unconditionally log net taps */
1560 if (*total_flags & FIF_PROMISC_IN_BSS)
1561 rx_mode |= RCR_UNICAST;
1562 else
1563 rx_mode &= ~RCR_UNICAST;
1564 }
1565
1566 if (changed_flags & FIF_ALLMULTI) {
1567 if (*total_flags & FIF_ALLMULTI) {
1568 if (priv->mc_list_count > 2) {
1569 MACvSelectPage1(priv->PortOffset);
1570
1571 VNSvOutPortD(priv->PortOffset +
1572 MAC_REG_MAR0, 0xffffffff);
1573 VNSvOutPortD(priv->PortOffset +
1574 MAC_REG_MAR0 + 4, 0xffffffff);
1575
1576 MACvSelectPage0(priv->PortOffset);
1577 } else {
1578 MACvSelectPage1(priv->PortOffset);
1579
1580 VNSvOutPortD(priv->PortOffset +
1581 MAC_REG_MAR0, (u32)multicast);
1582 VNSvOutPortD(priv->PortOffset +
1583 MAC_REG_MAR0 + 4,
1584 (u32)(multicast >> 32));
1585
1586 MACvSelectPage0(priv->PortOffset);
1587 }
1588
1589 rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
1590 } else {
1591 rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
1592 }
1593 }
1594
1595 if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
1596 rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
1597
1598 if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
1599 rx_mode &= ~RCR_BSSID;
1600 else
1601 rx_mode |= RCR_BSSID;
1602 }
1603
1604 VNSvOutPortB(priv->PortOffset + MAC_REG_RCR, rx_mode);
1605
1606 dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode);
1607}
1608
1609static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1610 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1611 struct ieee80211_key_conf *key)
1612{
1613 struct vnt_private *priv = hw->priv;
1614
1615 switch (cmd) {
1616 case SET_KEY:
1617 if (vnt_set_keys(hw, sta, vif, key))
1618 return -EOPNOTSUPP;
1619 break;
1620 case DISABLE_KEY:
1621 if (test_bit(key->hw_key_idx, &priv->key_entry_inuse))
1622 clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
1623 default:
1624 break;
1625 }
1626
1627 return 0;
1628}
1629
1630static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1631{
1632 struct vnt_private *priv = hw->priv;
1633 u64 tsf;
1634
Malcolm Priestley738487f2014-11-12 21:11:09 +00001635 CARDbGetCurrentTSF(priv, &tsf);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001636
1637 return tsf;
1638}
1639
1640static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1641 u64 tsf)
1642{
1643 struct vnt_private *priv = hw->priv;
1644
Malcolm Priestley738487f2014-11-12 21:11:09 +00001645 CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001646}
1647
1648static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1649{
1650 struct vnt_private *priv = hw->priv;
1651
1652 /* reset TSF counter */
1653 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
1654}
1655
1656static const struct ieee80211_ops vnt_mac_ops = {
1657 .tx = vnt_tx_80211,
1658 .start = vnt_start,
1659 .stop = vnt_stop,
1660 .add_interface = vnt_add_interface,
1661 .remove_interface = vnt_remove_interface,
1662 .config = vnt_config,
1663 .bss_info_changed = vnt_bss_info_changed,
1664 .prepare_multicast = vnt_prepare_multicast,
1665 .configure_filter = vnt_configure,
1666 .set_key = vnt_set_key,
1667 .get_tsf = vnt_get_tsf,
1668 .set_tsf = vnt_set_tsf,
1669 .reset_tsf = vnt_reset_tsf,
1670};
1671
1672int vnt_init(struct vnt_private *priv)
1673{
1674 SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr);
1675
Malcolm Priestley3d75b9e2014-10-29 17:43:44 +00001676 vnt_init_bands(priv);
1677
Malcolm Priestley67013f22014-10-29 17:43:43 +00001678 if (ieee80211_register_hw(priv->hw))
1679 return -ENODEV;
1680
1681 priv->mac_hw = true;
1682
1683 CARDbRadioPowerOff(priv);
1684
1685 return 0;
1686}
1687
1688static int
1689vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
1690{
1691 PCHIP_INFO pChip_info = (PCHIP_INFO)ent->driver_data;
1692 struct vnt_private *priv;
1693 struct ieee80211_hw *hw;
1694 struct wiphy *wiphy;
1695 int rc;
1696
1697 dev_notice(&pcid->dev,
1698 "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
1699
1700 dev_notice(&pcid->dev,
1701 "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
1702
1703 hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops);
1704 if (!hw) {
1705 dev_err(&pcid->dev, "could not register ieee80211_hw\n");
1706 return -ENOMEM;
1707 }
1708
1709 priv = hw->priv;
1710
1711 vt6655_init_info(pcid, &priv, pChip_info);
1712
1713 priv->hw = hw;
1714
1715 SET_IEEE80211_DEV(priv->hw, &pcid->dev);
1716
1717 if (pci_enable_device(pcid)) {
1718 device_free_info(priv);
1719 return -ENODEV;
1720 }
1721
1722 dev_dbg(&pcid->dev,
1723 "Before get pci_info memaddr is %x\n", priv->memaddr);
1724
1725 if (!device_get_pci_info(priv, pcid)) {
1726 dev_err(&pcid->dev, ": Failed to find PCI device.\n");
1727 device_free_info(priv);
1728 return -ENODEV;
1729 }
1730
1731#ifdef DEBUG
1732 dev_dbg(&pcid->dev,
1733 "after get pci_info memaddr is %x, io addr is %x,io_size is %d\n",
1734 priv->memaddr, priv->ioaddr, priv->io_size);
1735 {
1736 int i;
1737 u32 bar, len;
1738 u32 address[] = {
1739 PCI_BASE_ADDRESS_0,
1740 PCI_BASE_ADDRESS_1,
1741 PCI_BASE_ADDRESS_2,
1742 PCI_BASE_ADDRESS_3,
1743 PCI_BASE_ADDRESS_4,
1744 PCI_BASE_ADDRESS_5,
1745 0};
1746 for (i = 0; address[i]; i++) {
1747 pci_read_config_dword(pcid, address[i], &bar);
1748
1749 dev_dbg(&pcid->dev, "bar %d is %x\n", i, bar);
1750
1751 if (!bar) {
1752 dev_dbg(&pcid->dev,
1753 "bar %d not implemented\n", i);
1754 continue;
1755 }
1756
1757 if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
1758 /* This is IO */
1759
1760 len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xffff);
1761 len = len & ~(len - 1);
1762
1763 dev_dbg(&pcid->dev,
1764 "IO space: len in IO %x, BAR %d\n",
1765 len, i);
1766 } else {
1767 len = bar & 0xfffffff0;
1768 len = ~len + 1;
1769
1770 dev_dbg(&pcid->dev,
1771 "len in MEM %x, BAR %d\n", len, i);
1772 }
1773 }
1774 }
1775#endif
1776
1777 priv->PortOffset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK,
1778 priv->io_size);
1779 if (!priv->PortOffset) {
1780 dev_err(&pcid->dev, ": Failed to IO remapping ..\n");
1781 device_free_info(priv);
1782 return -ENODEV;
1783 }
1784
1785 rc = pci_request_regions(pcid, DEVICE_NAME);
1786 if (rc) {
1787 dev_err(&pcid->dev, ": Failed to find PCI device\n");
1788 device_free_info(priv);
1789 return -ENODEV;
1790 }
1791
1792 /* do reset */
1793 if (!MACbSoftwareReset(priv->PortOffset)) {
1794 dev_err(&pcid->dev, ": Failed to access MAC hardware..\n");
1795 device_free_info(priv);
1796 return -ENODEV;
1797 }
1798 /* initial to reload eeprom */
1799 MACvInitialize(priv->PortOffset);
1800 MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr);
1801
1802 device_get_options(priv);
1803 device_set_options(priv);
1804 /* Mask out the options cannot be set to the chip */
1805 priv->sOpts.flags &= pChip_info->flags;
1806
1807 /* Enable the chip specified capabilities */
1808 priv->flags = priv->sOpts.flags | (pChip_info->flags & 0xff000000UL);
Malcolm Priestley67013f22014-10-29 17:43:43 +00001809
1810 wiphy = priv->hw->wiphy;
1811
1812 wiphy->frag_threshold = FRAG_THRESH_DEF;
1813 wiphy->rts_threshold = RTS_THRESH_DEF;
1814 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1815 BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
1816
1817 priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
1818 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
1819 IEEE80211_HW_SIGNAL_DBM |
1820 IEEE80211_HW_TIMING_BEACON_ONLY;
1821
1822 priv->hw->max_signal = 100;
1823
1824 if (vnt_init(priv))
1825 return -ENODEV;
1826
1827 device_print_info(priv);
1828 pci_set_drvdata(pcid, priv);
1829
1830 return 0;
1831}
1832
Forest Bond5449c682009-04-25 10:30:44 -04001833/*------------------------------------------------------------------*/
Forest Bond5449c682009-04-25 10:30:44 -04001834
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001835#ifdef CONFIG_PM
1836static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state)
1837{
1838 struct vnt_private *priv = pci_get_drvdata(pcid);
1839 unsigned long flags;
1840
1841 spin_lock_irqsave(&priv->lock, flags);
1842
1843 pci_save_state(pcid);
1844
1845 MACbShutdown(priv->PortOffset);
1846
1847 pci_disable_device(pcid);
1848 pci_set_power_state(pcid, pci_choose_state(pcid, state));
1849
1850 spin_unlock_irqrestore(&priv->lock, flags);
1851
1852 return 0;
1853}
1854
1855static int vt6655_resume(struct pci_dev *pcid)
1856{
1857
1858 pci_set_power_state(pcid, PCI_D0);
1859 pci_enable_wake(pcid, PCI_D0, 0);
1860 pci_restore_state(pcid);
1861
1862 return 0;
1863}
1864#endif
1865
Charles Clément013a4682010-06-15 10:39:24 -07001866MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table);
Forest Bond5449c682009-04-25 10:30:44 -04001867
1868static struct pci_driver device_driver = {
Peter Huewe34381c22011-01-10 23:28:06 +01001869 .name = DEVICE_NAME,
1870 .id_table = vt6655_pci_id_table,
1871 .probe = vt6655_probe,
1872 .remove = vt6655_remove,
Forest Bond5449c682009-04-25 10:30:44 -04001873#ifdef CONFIG_PM
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001874 .suspend = vt6655_suspend,
1875 .resume = vt6655_resume,
Forest Bond5449c682009-04-25 10:30:44 -04001876#endif
Forest Bond5449c682009-04-25 10:30:44 -04001877};
1878
Charles Clément013a4682010-06-15 10:39:24 -07001879static int __init vt6655_init_module(void)
Forest Bond5449c682009-04-25 10:30:44 -04001880{
Joe Perches915006c2013-03-18 10:44:47 -07001881 int ret;
Forest Bond5449c682009-04-25 10:30:44 -04001882
Forest Bond5449c682009-04-25 10:30:44 -04001883 ret = pci_register_driver(&device_driver);
Forest Bond5449c682009-04-25 10:30:44 -04001884#ifdef CONFIG_PM
Joe Perches915006c2013-03-18 10:44:47 -07001885 if (ret >= 0)
1886 register_reboot_notifier(&device_notifier);
Forest Bond5449c682009-04-25 10:30:44 -04001887#endif
Forest Bond5449c682009-04-25 10:30:44 -04001888
Joe Perches915006c2013-03-18 10:44:47 -07001889 return ret;
Forest Bond5449c682009-04-25 10:30:44 -04001890}
1891
Charles Clément013a4682010-06-15 10:39:24 -07001892static void __exit vt6655_cleanup_module(void)
Forest Bond5449c682009-04-25 10:30:44 -04001893{
Forest Bond5449c682009-04-25 10:30:44 -04001894#ifdef CONFIG_PM
Joe Perches915006c2013-03-18 10:44:47 -07001895 unregister_reboot_notifier(&device_notifier);
Forest Bond5449c682009-04-25 10:30:44 -04001896#endif
Joe Perches915006c2013-03-18 10:44:47 -07001897 pci_unregister_driver(&device_driver);
Forest Bond5449c682009-04-25 10:30:44 -04001898}
1899
Charles Clément013a4682010-06-15 10:39:24 -07001900module_init(vt6655_init_module);
1901module_exit(vt6655_cleanup_module);
Forest Bond5449c682009-04-25 10:30:44 -04001902
Forest Bond5449c682009-04-25 10:30:44 -04001903#ifdef CONFIG_PM
1904static int
1905device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
1906{
Joe Perches915006c2013-03-18 10:44:47 -07001907 struct pci_dev *pdev = NULL;
Guillaume Clement6b711272014-07-25 01:06:16 +02001908
Joe Perches915006c2013-03-18 10:44:47 -07001909 switch (event) {
1910 case SYS_DOWN:
1911 case SYS_HALT:
1912 case SYS_POWER_OFF:
1913 for_each_pci_dev(pdev) {
1914 if (pci_dev_driver(pdev) == &device_driver) {
1915 if (pci_get_drvdata(pdev))
Malcolm Priestley000fe0f2014-10-29 17:43:45 +00001916 vt6655_suspend(pdev, PMSG_HIBERNATE);
Joe Perches915006c2013-03-18 10:44:47 -07001917 }
1918 }
1919 }
1920 return NOTIFY_DONE;
Forest Bond5449c682009-04-25 10:30:44 -04001921}
Forest Bond5449c682009-04-25 10:30:44 -04001922#endif