Commit | Line | Data |
---|---|---|
d7c43082 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
5449c685 FB |
2 | /* |
3 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | |
4 | * All rights reserved. | |
5 | * | |
5449c685 FB |
6 | * File: device_main.c |
7 | * | |
8 | * Purpose: driver entry for initial, open, close, tx and rx. | |
9 | * | |
10 | * Author: Lyndon Chen | |
11 | * | |
12 | * Date: Jan 8, 2003 | |
13 | * | |
14 | * Functions: | |
15 | * | |
013a468c CC |
16 | * vt6655_probe - module initial (insmod) driver entry |
17 | * vt6655_remove - module remove entry | |
5449c685 | 18 | * device_free_info - device structure resource free function |
5449c685 | 19 | * device_print_info - print out resource |
5449c685 | 20 | * device_rx_srv - rx service function |
5449c685 | 21 | * device_alloc_rx_buf - rx buffer pre-allocated function |
5341ee0a | 22 | * device_free_rx_buf - free rx buffer function |
5449c685 | 23 | * device_free_tx_buf - free tx buffer function |
5449c685 FB |
24 | * device_init_rd0_ring- initial rd dma0 ring |
25 | * device_init_rd1_ring- initial rd dma1 ring | |
26 | * device_init_td0_ring- initial tx dma0 ring buffer | |
27 | * device_init_td1_ring- initial tx dma1 ring buffer | |
28 | * device_init_registers- initial MAC & BBP & RF internal registers. | |
29 | * device_init_rings- initial tx/rx ring buffer | |
5449c685 FB |
30 | * device_free_rings- free all allocated ring buffer |
31 | * device_tx_srv- tx interrupt service function | |
32 | * | |
33 | * Revision History: | |
34 | */ | |
35 | #undef __NO_VERSION__ | |
36 | ||
f805442e | 37 | #include <linux/file.h> |
5449c685 | 38 | #include "device.h" |
5449c685 | 39 | #include "card.h" |
79566eb2 | 40 | #include "channel.h" |
5449c685 | 41 | #include "baseband.h" |
5449c685 | 42 | #include "mac.h" |
5449c685 | 43 | #include "power.h" |
5449c685 | 44 | #include "rxtx.h" |
5449c685 | 45 | #include "dpc.h" |
5449c685 | 46 | #include "rf.h" |
5449c685 FB |
47 | #include <linux/delay.h> |
48 | #include <linux/kthread.h> | |
5a0e3ad6 | 49 | #include <linux/slab.h> |
5449c685 | 50 | |
5449c685 | 51 | /*--------------------- Static Definitions -------------------------*/ |
bb72dd53 AS |
52 | /* |
53 | * Define module options | |
54 | */ | |
5449c685 FB |
55 | MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); |
56 | MODULE_LICENSE("GPL"); | |
57 | MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); | |
5449c685 | 58 | |
915006cd | 59 | #define DEVICE_PARAM(N, D) |
5449c685 FB |
60 | |
61 | #define RX_DESC_MIN0 16 | |
62 | #define RX_DESC_MAX0 128 | |
63 | #define RX_DESC_DEF0 32 | |
915006cd | 64 | DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0"); |
5449c685 FB |
65 | |
66 | #define RX_DESC_MIN1 16 | |
67 | #define RX_DESC_MAX1 128 | |
68 | #define RX_DESC_DEF1 32 | |
915006cd | 69 | DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1"); |
5449c685 FB |
70 | |
71 | #define TX_DESC_MIN0 16 | |
72 | #define TX_DESC_MAX0 128 | |
73 | #define TX_DESC_DEF0 32 | |
915006cd | 74 | DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0"); |
5449c685 FB |
75 | |
76 | #define TX_DESC_MIN1 16 | |
77 | #define TX_DESC_MAX1 128 | |
78 | #define TX_DESC_DEF1 64 | |
915006cd | 79 | DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1"); |
5449c685 | 80 | |
5449c685 FB |
81 | #define INT_WORKS_DEF 20 |
82 | #define INT_WORKS_MIN 10 | |
83 | #define INT_WORKS_MAX 64 | |
84 | ||
915006cd | 85 | DEVICE_PARAM(int_works, "Number of packets per interrupt services"); |
5449c685 | 86 | |
5449c685 FB |
87 | #define RTS_THRESH_DEF 2347 |
88 | ||
5449c685 FB |
89 | #define FRAG_THRESH_DEF 2346 |
90 | ||
5449c685 FB |
91 | #define SHORT_RETRY_MIN 0 |
92 | #define SHORT_RETRY_MAX 31 | |
93 | #define SHORT_RETRY_DEF 8 | |
94 | ||
5449c685 FB |
95 | DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); |
96 | ||
97 | #define LONG_RETRY_MIN 0 | |
98 | #define LONG_RETRY_MAX 15 | |
99 | #define LONG_RETRY_DEF 4 | |
100 | ||
5449c685 FB |
101 | DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); |
102 | ||
5449c685 | 103 | /* BasebandType[] baseband type selected |
9877f9de AJ |
104 | * 0: indicate 802.11a type |
105 | * 1: indicate 802.11b type | |
106 | * 2: indicate 802.11g type | |
107 | */ | |
5449c685 FB |
108 | #define BBP_TYPE_MIN 0 |
109 | #define BBP_TYPE_MAX 2 | |
110 | #define BBP_TYPE_DEF 2 | |
111 | ||
112 | DEVICE_PARAM(BasebandType, "baseband type"); | |
113 | ||
bb72dd53 AS |
114 | /* |
115 | * Static vars definitions | |
116 | */ | |
9e4c5c28 | 117 | static const struct pci_device_id vt6655_pci_id_table[] = { |
319755a7 | 118 | { PCI_VDEVICE(VIA, 0x3253) }, |
db6cb903 | 119 | { 0, } |
5449c685 | 120 | }; |
5449c685 FB |
121 | |
122 | /*--------------------- Static Functions --------------------------*/ | |
123 | ||
013a468c | 124 | static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); |
78e0e853 MP |
125 | static void device_free_info(struct vnt_private *priv); |
126 | static void device_print_info(struct vnt_private *priv); | |
5449c685 | 127 | |
5341ee0a JHK |
128 | static int device_init_rd0_ring(struct vnt_private *priv); |
129 | static int device_init_rd1_ring(struct vnt_private *priv); | |
130 | static int device_init_td0_ring(struct vnt_private *priv); | |
131 | static int device_init_td1_ring(struct vnt_private *priv); | |
5449c685 | 132 | |
0924a89b MP |
133 | static int device_rx_srv(struct vnt_private *priv, unsigned int idx); |
134 | static int device_tx_srv(struct vnt_private *priv, unsigned int idx); | |
9cb693f6 | 135 | static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *); |
a1182cda SF |
136 | static void device_free_rx_buf(struct vnt_private *priv, |
137 | struct vnt_rx_desc *rd); | |
78e0e853 | 138 | static void device_init_registers(struct vnt_private *priv); |
e2357271 | 139 | static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *); |
78e0e853 MP |
140 | static void device_free_td0_ring(struct vnt_private *priv); |
141 | static void device_free_td1_ring(struct vnt_private *priv); | |
142 | static void device_free_rd0_ring(struct vnt_private *priv); | |
143 | static void device_free_rd1_ring(struct vnt_private *priv); | |
144 | static void device_free_rings(struct vnt_private *priv); | |
5449c685 | 145 | |
5449c685 FB |
146 | /*--------------------- Export Variables --------------------------*/ |
147 | ||
148 | /*--------------------- Export Functions --------------------------*/ | |
149 | ||
f4e1b7c8 | 150 | static void vt6655_remove(struct pci_dev *pcid) |
5449c685 | 151 | { |
78e0e853 | 152 | struct vnt_private *priv = pci_get_drvdata(pcid); |
5449c685 | 153 | |
3621014a | 154 | if (!priv) |
3ac9e0fd | 155 | return; |
78e0e853 | 156 | device_free_info(priv); |
5449c685 FB |
157 | } |
158 | ||
78e0e853 | 159 | static void device_get_options(struct vnt_private *priv) |
bf76ebd9 | 160 | { |
bc667b99 | 161 | struct vnt_options *opts = &priv->opts; |
bf76ebd9 | 162 | |
bc667b99 MP |
163 | opts->rx_descs0 = RX_DESC_DEF0; |
164 | opts->rx_descs1 = RX_DESC_DEF1; | |
165 | opts->tx_descs[0] = TX_DESC_DEF0; | |
166 | opts->tx_descs[1] = TX_DESC_DEF1; | |
167 | opts->int_works = INT_WORKS_DEF; | |
bf76ebd9 | 168 | |
bc667b99 MP |
169 | opts->short_retry = SHORT_RETRY_DEF; |
170 | opts->long_retry = LONG_RETRY_DEF; | |
171 | opts->bbp_type = BBP_TYPE_DEF; | |
5449c685 FB |
172 | } |
173 | ||
174 | static void | |
78e0e853 | 175 | device_set_options(struct vnt_private *priv) |
3f8597f4 | 176 | { |
bc667b99 MP |
177 | priv->byShortRetryLimit = priv->opts.short_retry; |
178 | priv->byLongRetryLimit = priv->opts.long_retry; | |
179 | priv->byBBType = priv->opts.bbp_type; | |
78e0e853 MP |
180 | priv->byPacketType = priv->byBBType; |
181 | priv->byAutoFBCtrl = AUTO_FB_0; | |
182 | priv->bUpdateBBVGA = true; | |
183 | priv->byPreambleType = 0; | |
184 | ||
185 | pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit); | |
186 | pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit); | |
187 | pr_debug(" byPreambleType= %d\n", (int)priv->byPreambleType); | |
188 | pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble); | |
189 | pr_debug(" byBBType= %d\n", (int)priv->byBBType); | |
5449c685 FB |
190 | } |
191 | ||
bb72dd53 AS |
192 | /* |
193 | * Initialisation of MAC & BBP registers | |
194 | */ | |
5449c685 | 195 | |
78e0e853 | 196 | static void device_init_registers(struct vnt_private *priv) |
5449c685 | 197 | { |
10d6f1b7 | 198 | unsigned long flags; |
915006cd JP |
199 | unsigned int ii; |
200 | unsigned char byValue; | |
915006cd JP |
201 | unsigned char byCCKPwrdBm = 0; |
202 | unsigned char byOFDMPwrdBm = 0; | |
6b711271 | 203 | |
f9f853af | 204 | MACbShutdown(priv); |
78e0e853 | 205 | BBvSoftwareReset(priv); |
915006cd | 206 | |
9f34de35 | 207 | /* Do MACbSoftwareReset in MACvInitialize */ |
f9f853af | 208 | MACbSoftwareReset(priv); |
915006cd | 209 | |
78e0e853 | 210 | priv->bAES = false; |
915006cd | 211 | |
9f34de35 | 212 | /* Only used in 11g type, sync with ERP IE */ |
78e0e853 | 213 | priv->bProtectMode = false; |
915006cd | 214 | |
78e0e853 MP |
215 | priv->bNonERPPresent = false; |
216 | priv->bBarkerPreambleMd = false; | |
217 | priv->wCurrentRate = RATE_1M; | |
218 | priv->byTopOFDMBasicRate = RATE_24M; | |
219 | priv->byTopCCKBasicRate = RATE_1M; | |
915006cd | 220 | |
9f34de35 | 221 | /* init MAC */ |
f9f853af | 222 | MACvInitialize(priv); |
9f34de35 MP |
223 | |
224 | /* Get Local ID */ | |
78e0e853 | 225 | VNSvInPortB(priv->PortOffset + MAC_REG_LOCALID, &priv->byLocalID); |
915006cd | 226 | |
78e0e853 | 227 | spin_lock_irqsave(&priv->lock, flags); |
915006cd | 228 | |
78e0e853 | 229 | SROMvReadAllContents(priv->PortOffset, priv->abyEEPROM); |
915006cd | 230 | |
78e0e853 | 231 | spin_unlock_irqrestore(&priv->lock, flags); |
915006cd | 232 | |
9f34de35 | 233 | /* Get Channel range */ |
78e0e853 MP |
234 | priv->byMinChannel = 1; |
235 | priv->byMaxChannel = CB_MAX_CHANNEL; | |
915006cd | 236 | |
9f34de35 | 237 | /* Get Antena */ |
78e0e853 | 238 | byValue = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_ANTENNA); |
9f34de35 | 239 | if (byValue & EEP_ANTINV) |
78e0e853 | 240 | priv->bTxRxAntInv = true; |
9f34de35 | 241 | else |
78e0e853 | 242 | priv->bTxRxAntInv = false; |
9f34de35 MP |
243 | |
244 | byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); | |
245 | /* if not set default is All */ | |
246 | if (byValue == 0) | |
247 | byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); | |
248 | ||
9f34de35 | 249 | if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { |
78e0e853 MP |
250 | priv->byAntennaCount = 2; |
251 | priv->byTxAntennaMode = ANT_B; | |
252 | priv->dwTxAntennaSel = 1; | |
253 | priv->dwRxAntennaSel = 1; | |
9f34de35 | 254 | |
78e0e853 MP |
255 | if (priv->bTxRxAntInv) |
256 | priv->byRxAntennaMode = ANT_A; | |
915006cd | 257 | else |
78e0e853 | 258 | priv->byRxAntennaMode = ANT_B; |
9f34de35 | 259 | } else { |
78e0e853 MP |
260 | priv->byAntennaCount = 1; |
261 | priv->dwTxAntennaSel = 0; | |
262 | priv->dwRxAntennaSel = 0; | |
915006cd | 263 | |
9f34de35 | 264 | if (byValue & EEP_ANTENNA_AUX) { |
78e0e853 | 265 | priv->byTxAntennaMode = ANT_A; |
915006cd | 266 | |
78e0e853 MP |
267 | if (priv->bTxRxAntInv) |
268 | priv->byRxAntennaMode = ANT_B; | |
9f34de35 | 269 | else |
78e0e853 | 270 | priv->byRxAntennaMode = ANT_A; |
9f34de35 | 271 | } else { |
78e0e853 | 272 | priv->byTxAntennaMode = ANT_B; |
9f34de35 | 273 | |
78e0e853 MP |
274 | if (priv->bTxRxAntInv) |
275 | priv->byRxAntennaMode = ANT_A; | |
915006cd | 276 | else |
78e0e853 | 277 | priv->byRxAntennaMode = ANT_B; |
915006cd | 278 | } |
9f34de35 | 279 | } |
5449c685 | 280 | |
918185f6 | 281 | /* Set initial antenna mode */ |
78e0e853 MP |
282 | BBvSetTxAntennaMode(priv, priv->byTxAntennaMode); |
283 | BBvSetRxAntennaMode(priv, priv->byRxAntennaMode); | |
918185f6 | 284 | |
9f34de35 | 285 | /* zonetype initial */ |
78e0e853 | 286 | priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE]; |
915006cd | 287 | |
78e0e853 MP |
288 | if (!priv->bZoneRegExist) |
289 | priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE]; | |
bc5cf656 | 290 | |
78e0e853 | 291 | pr_debug("priv->byZoneType = %x\n", priv->byZoneType); |
915006cd | 292 | |
9f34de35 | 293 | /* Init RF module */ |
78e0e853 | 294 | RFbInit(priv); |
915006cd | 295 | |
9f34de35 | 296 | /* Get Desire Power Value */ |
78e0e853 MP |
297 | priv->byCurPwr = 0xFF; |
298 | priv->byCCKPwr = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_PWR_CCK); | |
3bce4750 FCB |
299 | priv->byOFDMPwrG = SROMbyReadEmbedded(priv->PortOffset, |
300 | EEP_OFS_PWR_OFDMG); | |
f2046f93 | 301 | |
9f34de35 MP |
302 | /* Load power Table */ |
303 | for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { | |
78e0e853 MP |
304 | priv->abyCCKPwrTbl[ii + 1] = |
305 | SROMbyReadEmbedded(priv->PortOffset, | |
9f34de35 | 306 | (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL)); |
78e0e853 | 307 | if (priv->abyCCKPwrTbl[ii + 1] == 0) |
e5851dc0 | 308 | priv->abyCCKPwrTbl[ii + 1] = priv->byCCKPwr; |
5449c685 | 309 | |
78e0e853 MP |
310 | priv->abyOFDMPwrTbl[ii + 1] = |
311 | SROMbyReadEmbedded(priv->PortOffset, | |
9f34de35 | 312 | (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL)); |
78e0e853 MP |
313 | if (priv->abyOFDMPwrTbl[ii + 1] == 0) |
314 | priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG; | |
bc5cf656 | 315 | |
78e0e853 MP |
316 | priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm; |
317 | priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm; | |
9f34de35 | 318 | } |
bc5cf656 | 319 | |
9f34de35 | 320 | /* recover 12,13 ,14channel for EUROPE by 11 channel */ |
f4cf678f | 321 | for (ii = 11; ii < 14; ii++) { |
78e0e853 MP |
322 | priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10]; |
323 | priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10]; | |
9f34de35 | 324 | } |
5449c685 | 325 | |
9f34de35 MP |
326 | /* Load OFDM A Power Table */ |
327 | for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { | |
78e0e853 MP |
328 | priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = |
329 | SROMbyReadEmbedded(priv->PortOffset, | |
9f34de35 | 330 | (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL)); |
5449c685 | 331 | |
78e0e853 MP |
332 | priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = |
333 | SROMbyReadEmbedded(priv->PortOffset, | |
9f34de35 MP |
334 | (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm)); |
335 | } | |
5449c685 | 336 | |
78e0e853 MP |
337 | if (priv->byLocalID > REV_ID_VT3253_B1) { |
338 | MACvSelectPage1(priv->PortOffset); | |
5449c685 | 339 | |
78e0e853 | 340 | VNSvOutPortB(priv->PortOffset + MAC_REG_MSRCTL + 1, |
9f34de35 | 341 | (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN)); |
5449c685 | 342 | |
78e0e853 | 343 | MACvSelectPage0(priv->PortOffset); |
9f34de35 | 344 | } |
5449c685 | 345 | |
9f34de35 | 346 | /* use relative tx timeout and 802.11i D4 */ |
78e0e853 | 347 | MACvWordRegBitsOn(priv->PortOffset, |
9f34de35 | 348 | MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); |
5449c685 | 349 | |
9f34de35 | 350 | /* set performance parameter by registry */ |
f9f853af MP |
351 | MACvSetShortRetryLimit(priv, priv->byShortRetryLimit); |
352 | MACvSetLongRetryLimit(priv, priv->byLongRetryLimit); | |
5449c685 | 353 | |
9f34de35 | 354 | /* reset TSF counter */ |
78e0e853 | 355 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); |
9f34de35 | 356 | /* enable TSF counter */ |
78e0e853 | 357 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); |
5449c685 | 358 | |
9f34de35 | 359 | /* initialize BBP registers */ |
78e0e853 | 360 | BBbVT3253Init(priv); |
5449c685 | 361 | |
78e0e853 MP |
362 | if (priv->bUpdateBBVGA) { |
363 | priv->byBBVGACurrent = priv->abyBBVGA[0]; | |
364 | priv->byBBVGANew = priv->byBBVGACurrent; | |
365 | BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]); | |
9f34de35 | 366 | } |
5449c685 | 367 | |
78e0e853 MP |
368 | BBvSetRxAntennaMode(priv, priv->byRxAntennaMode); |
369 | BBvSetTxAntennaMode(priv, priv->byTxAntennaMode); | |
5449c685 | 370 | |
9f34de35 MP |
371 | /* Set BB and packet type at the same time. */ |
372 | /* Set Short Slot Time, xIFS, and RSPINF. */ | |
78e0e853 | 373 | priv->wCurrentRate = RATE_54M; |
bc5cf656 | 374 | |
78e0e853 | 375 | priv->bRadioOff = false; |
5449c685 | 376 | |
78e0e853 | 377 | priv->byRadioCtl = SROMbyReadEmbedded(priv->PortOffset, |
8b3f9afc | 378 | EEP_OFS_RADIOCTL); |
78e0e853 | 379 | priv->bHWRadioOff = false; |
5449c685 | 380 | |
78e0e853 | 381 | if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) { |
9f34de35 | 382 | /* Get GPIO */ |
78e0e853 | 383 | MACvGPIOIn(priv->PortOffset, &priv->byGPIO); |
9f34de35 | 384 | |
78e0e853 MP |
385 | if (((priv->byGPIO & GPIO0_DATA) && |
386 | !(priv->byRadioCtl & EEP_RADIOCTL_INV)) || | |
387 | (!(priv->byGPIO & GPIO0_DATA) && | |
388 | (priv->byRadioCtl & EEP_RADIOCTL_INV))) | |
389 | priv->bHWRadioOff = true; | |
915006cd | 390 | } |
9f34de35 | 391 | |
78e0e853 MP |
392 | if (priv->bHWRadioOff || priv->bRadioControlOff) |
393 | CARDbRadioPowerOff(priv); | |
5449c685 | 394 | |
3500a1da | 395 | /* get Permanent network address */ |
78e0e853 MP |
396 | SROMvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr); |
397 | pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr); | |
915006cd | 398 | |
3500a1da | 399 | /* reset Tx pointer */ |
78e0e853 | 400 | CARDvSafeResetRx(priv); |
3500a1da | 401 | /* reset Rx pointer */ |
78e0e853 | 402 | CARDvSafeResetTx(priv); |
5449c685 | 403 | |
78e0e853 MP |
404 | if (priv->byLocalID <= REV_ID_VT3253_A1) |
405 | MACvRegBitsOn(priv->PortOffset, MAC_REG_RCR, RCR_WPAERR); | |
5449c685 | 406 | |
3500a1da | 407 | /* Turn On Rx DMA */ |
78e0e853 MP |
408 | MACvReceive0(priv->PortOffset); |
409 | MACvReceive1(priv->PortOffset); | |
5449c685 | 410 | |
3500a1da | 411 | /* start the adapter */ |
78e0e853 | 412 | MACvStart(priv->PortOffset); |
5449c685 FB |
413 | } |
414 | ||
78e0e853 | 415 | static void device_print_info(struct vnt_private *priv) |
5449c685 | 416 | { |
78e0e853 MP |
417 | dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n", |
418 | priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr, | |
419 | (unsigned long)priv->PortOffset, priv->pcid->irq); | |
5449c685 FB |
420 | } |
421 | ||
78e0e853 | 422 | static void device_free_info(struct vnt_private *priv) |
84b50762 | 423 | { |
78e0e853 | 424 | if (!priv) |
14e53006 | 425 | return; |
5449c685 | 426 | |
78e0e853 MP |
427 | if (priv->mac_hw) |
428 | ieee80211_unregister_hw(priv->hw); | |
5449c685 | 429 | |
78e0e853 MP |
430 | if (priv->PortOffset) |
431 | iounmap(priv->PortOffset); | |
5449c685 | 432 | |
78e0e853 MP |
433 | if (priv->pcid) |
434 | pci_release_regions(priv->pcid); | |
14e53006 | 435 | |
78e0e853 MP |
436 | if (priv->hw) |
437 | ieee80211_free_hw(priv->hw); | |
5449c685 | 438 | } |
5449c685 | 439 | |
78e0e853 | 440 | static bool device_init_rings(struct vnt_private *priv) |
84b50762 | 441 | { |
915006cd | 442 | void *vir_pool; |
5449c685 | 443 | |
915006cd | 444 | /*allocate all RD/TD rings a single pool*/ |
750afb08 | 445 | vir_pool = dma_alloc_coherent(&priv->pcid->dev, |
73d85422 BO |
446 | priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + |
447 | priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + | |
448 | priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + | |
449 | priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), | |
750afb08 | 450 | &priv->pool_dma, GFP_ATOMIC); |
3621014a | 451 | if (!vir_pool) { |
78e0e853 | 452 | dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n"); |
915006cd JP |
453 | return false; |
454 | } | |
5449c685 | 455 | |
78e0e853 MP |
456 | priv->aRD0Ring = vir_pool; |
457 | priv->aRD1Ring = vir_pool + | |
bc667b99 | 458 | priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); |
78e0e853 MP |
459 | |
460 | priv->rd0_pool_dma = priv->pool_dma; | |
461 | priv->rd1_pool_dma = priv->rd0_pool_dma + | |
bc667b99 | 462 | priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); |
78e0e853 | 463 | |
750afb08 LC |
464 | priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev, |
465 | priv->opts.tx_descs[0] * PKT_BUF_SZ + priv->opts.tx_descs[1] * PKT_BUF_SZ + CB_BEACON_BUF_SIZE + CB_MAX_BUF_SIZE, | |
466 | &priv->tx_bufs_dma0, GFP_ATOMIC); | |
7cfae249 | 467 | if (!priv->tx0_bufs) { |
78e0e853 MP |
468 | dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); |
469 | ||
470 | dma_free_coherent(&priv->pcid->dev, | |
bc667b99 MP |
471 | priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + |
472 | priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + | |
473 | priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + | |
474 | priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), | |
78e0e853 | 475 | vir_pool, priv->pool_dma); |
915006cd JP |
476 | return false; |
477 | } | |
5449c685 | 478 | |
78e0e853 | 479 | priv->td0_pool_dma = priv->rd1_pool_dma + |
bc667b99 | 480 | priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); |
5449c685 | 481 | |
78e0e853 | 482 | priv->td1_pool_dma = priv->td0_pool_dma + |
bc667b99 | 483 | priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); |
5449c685 | 484 | |
bb72dd53 | 485 | /* vir_pool: pvoid type */ |
78e0e853 | 486 | priv->apTD0Rings = vir_pool |
bc667b99 MP |
487 | + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) |
488 | + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); | |
5449c685 | 489 | |
78e0e853 | 490 | priv->apTD1Rings = vir_pool |
bc667b99 MP |
491 | + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) |
492 | + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) | |
493 | + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); | |
5449c685 | 494 | |
78e0e853 | 495 | priv->tx1_bufs = priv->tx0_bufs + |
bc667b99 | 496 | priv->opts.tx_descs[0] * PKT_BUF_SZ; |
5449c685 | 497 | |
78e0e853 | 498 | priv->tx_beacon_bufs = priv->tx1_bufs + |
bc667b99 | 499 | priv->opts.tx_descs[1] * PKT_BUF_SZ; |
5449c685 | 500 | |
78e0e853 | 501 | priv->pbyTmpBuff = priv->tx_beacon_bufs + |
915006cd | 502 | CB_BEACON_BUF_SIZE; |
5449c685 | 503 | |
78e0e853 | 504 | priv->tx_bufs_dma1 = priv->tx_bufs_dma0 + |
bc667b99 | 505 | priv->opts.tx_descs[0] * PKT_BUF_SZ; |
5449c685 | 506 | |
78e0e853 | 507 | priv->tx_beacon_dma = priv->tx_bufs_dma1 + |
bc667b99 | 508 | priv->opts.tx_descs[1] * PKT_BUF_SZ; |
5449c685 | 509 | |
915006cd | 510 | return true; |
5449c685 FB |
511 | } |
512 | ||
78e0e853 | 513 | static void device_free_rings(struct vnt_private *priv) |
84b50762 | 514 | { |
78e0e853 | 515 | dma_free_coherent(&priv->pcid->dev, |
bc667b99 MP |
516 | priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + |
517 | priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + | |
518 | priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + | |
519 | priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), | |
78e0e853 MP |
520 | priv->aRD0Ring, priv->pool_dma); |
521 | ||
522 | if (priv->tx0_bufs) | |
523 | dma_free_coherent(&priv->pcid->dev, | |
bc667b99 MP |
524 | priv->opts.tx_descs[0] * PKT_BUF_SZ + |
525 | priv->opts.tx_descs[1] * PKT_BUF_SZ + | |
78e0e853 MP |
526 | CB_BEACON_BUF_SIZE + |
527 | CB_MAX_BUF_SIZE, | |
528 | priv->tx0_bufs, priv->tx_bufs_dma0); | |
5449c685 FB |
529 | } |
530 | ||
5341ee0a | 531 | static int device_init_rd0_ring(struct vnt_private *priv) |
84b50762 | 532 | { |
915006cd | 533 | int i; |
78e0e853 | 534 | dma_addr_t curr = priv->rd0_pool_dma; |
5e76c8f4 | 535 | struct vnt_rx_desc *desc; |
5341ee0a | 536 | int ret; |
915006cd JP |
537 | |
538 | /* Init the RD0 ring entries */ | |
bc667b99 | 539 | for (i = 0; i < priv->opts.rx_descs0; |
9cb693f6 | 540 | i ++, curr += sizeof(struct vnt_rx_desc)) { |
5e76c8f4 | 541 | desc = &priv->aRD0Ring[i]; |
88a527c4 | 542 | desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); |
5341ee0a JHK |
543 | if (!desc->rd_info) { |
544 | ret = -ENOMEM; | |
545 | goto err_free_desc; | |
546 | } | |
217ed3ab | 547 | |
5341ee0a | 548 | if (!device_alloc_rx_buf(priv, desc)) { |
78e0e853 | 549 | dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); |
5341ee0a JHK |
550 | ret = -ENOMEM; |
551 | goto err_free_rd; | |
552 | } | |
42f709ef | 553 | |
6089735a | 554 | desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0]; |
5e76c8f4 | 555 | desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); |
915006cd JP |
556 | } |
557 | ||
558 | if (i > 0) | |
78e0e853 MP |
559 | priv->aRD0Ring[i-1].next_desc = cpu_to_le32(priv->rd0_pool_dma); |
560 | priv->pCurrRD[0] = &priv->aRD0Ring[0]; | |
5341ee0a JHK |
561 | |
562 | return 0; | |
563 | ||
564 | err_free_rd: | |
565 | kfree(desc->rd_info); | |
566 | ||
567 | err_free_desc: | |
568 | while (--i) { | |
569 | desc = &priv->aRD0Ring[i]; | |
570 | device_free_rx_buf(priv, desc); | |
571 | kfree(desc->rd_info); | |
572 | } | |
573 | ||
574 | return ret; | |
5449c685 FB |
575 | } |
576 | ||
5341ee0a | 577 | static int device_init_rd1_ring(struct vnt_private *priv) |
84b50762 | 578 | { |
915006cd | 579 | int i; |
78e0e853 | 580 | dma_addr_t curr = priv->rd1_pool_dma; |
5e76c8f4 | 581 | struct vnt_rx_desc *desc; |
5341ee0a | 582 | int ret; |
915006cd JP |
583 | |
584 | /* Init the RD1 ring entries */ | |
bc667b99 | 585 | for (i = 0; i < priv->opts.rx_descs1; |
9cb693f6 | 586 | i ++, curr += sizeof(struct vnt_rx_desc)) { |
5e76c8f4 | 587 | desc = &priv->aRD1Ring[i]; |
88a527c4 | 588 | desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); |
5341ee0a JHK |
589 | if (!desc->rd_info) { |
590 | ret = -ENOMEM; | |
591 | goto err_free_desc; | |
592 | } | |
217ed3ab | 593 | |
5341ee0a | 594 | if (!device_alloc_rx_buf(priv, desc)) { |
78e0e853 | 595 | dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); |
5341ee0a JHK |
596 | ret = -ENOMEM; |
597 | goto err_free_rd; | |
598 | } | |
42f709ef | 599 | |
6089735a | 600 | desc->next = &priv->aRD1Ring[(i+1) % priv->opts.rx_descs1]; |
5e76c8f4 | 601 | desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); |
915006cd JP |
602 | } |
603 | ||
604 | if (i > 0) | |
78e0e853 MP |
605 | priv->aRD1Ring[i-1].next_desc = cpu_to_le32(priv->rd1_pool_dma); |
606 | priv->pCurrRD[1] = &priv->aRD1Ring[0]; | |
5341ee0a JHK |
607 | |
608 | return 0; | |
609 | ||
610 | err_free_rd: | |
611 | kfree(desc->rd_info); | |
612 | ||
613 | err_free_desc: | |
614 | while (--i) { | |
615 | desc = &priv->aRD1Ring[i]; | |
616 | device_free_rx_buf(priv, desc); | |
617 | kfree(desc->rd_info); | |
618 | } | |
619 | ||
620 | return ret; | |
5449c685 FB |
621 | } |
622 | ||
78e0e853 | 623 | static void device_free_rd0_ring(struct vnt_private *priv) |
84b50762 | 624 | { |
915006cd | 625 | int i; |
5449c685 | 626 | |
bc667b99 | 627 | for (i = 0; i < priv->opts.rx_descs0; i++) { |
6089735a | 628 | struct vnt_rx_desc *desc = &priv->aRD0Ring[i]; |
5449c685 | 629 | |
5341ee0a | 630 | device_free_rx_buf(priv, desc); |
5e76c8f4 | 631 | kfree(desc->rd_info); |
915006cd | 632 | } |
5449c685 FB |
633 | } |
634 | ||
78e0e853 | 635 | static void device_free_rd1_ring(struct vnt_private *priv) |
84b50762 | 636 | { |
915006cd | 637 | int i; |
5449c685 | 638 | |
bc667b99 | 639 | for (i = 0; i < priv->opts.rx_descs1; i++) { |
5e76c8f4 | 640 | struct vnt_rx_desc *desc = &priv->aRD1Ring[i]; |
5449c685 | 641 | |
5341ee0a | 642 | device_free_rx_buf(priv, desc); |
5e76c8f4 | 643 | kfree(desc->rd_info); |
915006cd | 644 | } |
5449c685 FB |
645 | } |
646 | ||
5341ee0a | 647 | static int device_init_td0_ring(struct vnt_private *priv) |
84b50762 | 648 | { |
915006cd JP |
649 | int i; |
650 | dma_addr_t curr; | |
5e76c8f4 | 651 | struct vnt_tx_desc *desc; |
5341ee0a | 652 | int ret; |
915006cd | 653 | |
78e0e853 | 654 | curr = priv->td0_pool_dma; |
bc667b99 | 655 | for (i = 0; i < priv->opts.tx_descs[0]; |
e2357271 | 656 | i++, curr += sizeof(struct vnt_tx_desc)) { |
5e76c8f4 | 657 | desc = &priv->apTD0Rings[i]; |
88a527c4 | 658 | desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); |
5341ee0a JHK |
659 | if (!desc->td_info) { |
660 | ret = -ENOMEM; | |
661 | goto err_free_desc; | |
662 | } | |
217ed3ab | 663 | |
5e76c8f4 MP |
664 | desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ; |
665 | desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ; | |
319755a7 | 666 | |
ebacc1a7 | 667 | desc->next = &(priv->apTD0Rings[(i + 1) % priv->opts.tx_descs[0]]); |
3bce4750 FCB |
668 | desc->next_desc = cpu_to_le32(curr + |
669 | sizeof(struct vnt_tx_desc)); | |
915006cd JP |
670 | } |
671 | ||
672 | if (i > 0) | |
ebacc1a7 | 673 | priv->apTD0Rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma); |
78e0e853 | 674 | priv->apTailTD[0] = priv->apCurrTD[0] = &priv->apTD0Rings[0]; |
5341ee0a JHK |
675 | |
676 | return 0; | |
677 | ||
678 | err_free_desc: | |
679 | while (--i) { | |
680 | desc = &priv->apTD0Rings[i]; | |
681 | kfree(desc->td_info); | |
682 | } | |
683 | ||
684 | return ret; | |
5449c685 FB |
685 | } |
686 | ||
5341ee0a | 687 | static int device_init_td1_ring(struct vnt_private *priv) |
84b50762 | 688 | { |
915006cd JP |
689 | int i; |
690 | dma_addr_t curr; | |
5e76c8f4 | 691 | struct vnt_tx_desc *desc; |
5341ee0a | 692 | int ret; |
915006cd JP |
693 | |
694 | /* Init the TD ring entries */ | |
78e0e853 | 695 | curr = priv->td1_pool_dma; |
bc667b99 | 696 | for (i = 0; i < priv->opts.tx_descs[1]; |
e2357271 | 697 | i++, curr += sizeof(struct vnt_tx_desc)) { |
5e76c8f4 | 698 | desc = &priv->apTD1Rings[i]; |
88a527c4 | 699 | desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); |
5341ee0a JHK |
700 | if (!desc->td_info) { |
701 | ret = -ENOMEM; | |
702 | goto err_free_desc; | |
703 | } | |
217ed3ab | 704 | |
5e76c8f4 MP |
705 | desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ; |
706 | desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ; | |
319755a7 | 707 | |
bc667b99 | 708 | desc->next = &(priv->apTD1Rings[(i + 1) % priv->opts.tx_descs[1]]); |
5e76c8f4 | 709 | desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc)); |
915006cd JP |
710 | } |
711 | ||
712 | if (i > 0) | |
ebacc1a7 | 713 | priv->apTD1Rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma); |
78e0e853 | 714 | priv->apTailTD[1] = priv->apCurrTD[1] = &priv->apTD1Rings[0]; |
5341ee0a JHK |
715 | |
716 | return 0; | |
717 | ||
718 | err_free_desc: | |
719 | while (--i) { | |
720 | desc = &priv->apTD1Rings[i]; | |
721 | kfree(desc->td_info); | |
722 | } | |
723 | ||
724 | return ret; | |
5449c685 FB |
725 | } |
726 | ||
78e0e853 | 727 | static void device_free_td0_ring(struct vnt_private *priv) |
84b50762 | 728 | { |
915006cd | 729 | int i; |
6b711271 | 730 | |
bc667b99 | 731 | for (i = 0; i < priv->opts.tx_descs[0]; i++) { |
5e76c8f4 | 732 | struct vnt_tx_desc *desc = &priv->apTD0Rings[i]; |
12f2ee35 | 733 | struct vnt_td_info *td_info = desc->td_info; |
5449c685 | 734 | |
12f2ee35 | 735 | dev_kfree_skb(td_info->skb); |
5e76c8f4 | 736 | kfree(desc->td_info); |
915006cd | 737 | } |
5449c685 FB |
738 | } |
739 | ||
78e0e853 | 740 | static void device_free_td1_ring(struct vnt_private *priv) |
84b50762 | 741 | { |
915006cd | 742 | int i; |
5449c685 | 743 | |
bc667b99 | 744 | for (i = 0; i < priv->opts.tx_descs[1]; i++) { |
5e76c8f4 | 745 | struct vnt_tx_desc *desc = &priv->apTD1Rings[i]; |
12f2ee35 | 746 | struct vnt_td_info *td_info = desc->td_info; |
5449c685 | 747 | |
12f2ee35 | 748 | dev_kfree_skb(td_info->skb); |
5e76c8f4 | 749 | kfree(desc->td_info); |
915006cd | 750 | } |
5449c685 FB |
751 | } |
752 | ||
5449c685 FB |
753 | /*-----------------------------------------------------------------*/ |
754 | ||
0924a89b | 755 | static int device_rx_srv(struct vnt_private *priv, unsigned int idx) |
84b50762 | 756 | { |
480fc5b8 | 757 | struct vnt_rx_desc *rd; |
915006cd | 758 | int works = 0; |
5449c685 | 759 | |
0924a89b | 760 | for (rd = priv->pCurrRD[idx]; |
480fc5b8 MP |
761 | rd->rd0.owner == OWNED_BY_HOST; |
762 | rd = rd->next) { | |
915006cd JP |
763 | if (works++ > 15) |
764 | break; | |
b5eeed8c | 765 | |
480fc5b8 | 766 | if (!rd->rd_info->skb) |
b5eeed8c MP |
767 | break; |
768 | ||
480fc5b8 MP |
769 | if (vnt_receive_frame(priv, rd)) { |
770 | if (!device_alloc_rx_buf(priv, rd)) { | |
78e0e853 | 771 | dev_err(&priv->pcid->dev, |
42f709ef | 772 | "can not allocate rx buf\n"); |
915006cd JP |
773 | break; |
774 | } | |
775 | } | |
480fc5b8 | 776 | rd->rd0.owner = OWNED_BY_NIC; |
915006cd JP |
777 | } |
778 | ||
0924a89b | 779 | priv->pCurrRD[idx] = rd; |
915006cd JP |
780 | |
781 | return works; | |
5449c685 FB |
782 | } |
783 | ||
78e0e853 | 784 | static bool device_alloc_rx_buf(struct vnt_private *priv, |
480fc5b8 | 785 | struct vnt_rx_desc *rd) |
84b50762 | 786 | { |
480fc5b8 | 787 | struct vnt_rd_info *rd_info = rd->rd_info; |
5449c685 | 788 | |
5e011b43 | 789 | rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz); |
8f4166d8 | 790 | if (!rd_info->skb) |
915006cd | 791 | return false; |
33b1c8c1 | 792 | |
5e011b43 | 793 | rd_info->skb_dma = |
78e0e853 | 794 | dma_map_single(&priv->pcid->dev, |
5e011b43 | 795 | skb_put(rd_info->skb, skb_tailroom(rd_info->skb)), |
78e0e853 | 796 | priv->rx_buf_sz, DMA_FROM_DEVICE); |
2fbf6d61 HM |
797 | if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) { |
798 | dev_kfree_skb(rd_info->skb); | |
799 | rd_info->skb = NULL; | |
800 | return false; | |
801 | } | |
33b1c8c1 | 802 | |
480fc5b8 | 803 | *((unsigned int *)&rd->rd0) = 0; /* FIX cast */ |
915006cd | 804 | |
480fc5b8 MP |
805 | rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); |
806 | rd->rd0.owner = OWNED_BY_NIC; | |
807 | rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); | |
808 | rd->buff_addr = cpu_to_le32(rd_info->skb_dma); | |
915006cd JP |
809 | |
810 | return true; | |
5449c685 FB |
811 | } |
812 | ||
5341ee0a | 813 | static void device_free_rx_buf(struct vnt_private *priv, |
73ad3e24 | 814 | struct vnt_rx_desc *rd) |
5341ee0a JHK |
815 | { |
816 | struct vnt_rd_info *rd_info = rd->rd_info; | |
817 | ||
818 | dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, | |
00bdd001 | 819 | priv->rx_buf_sz, DMA_FROM_DEVICE); |
5341ee0a JHK |
820 | dev_kfree_skb(rd_info->skb); |
821 | } | |
822 | ||
59918bea MP |
823 | static const u8 fallback_rate0[5][5] = { |
824 | {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, | |
825 | {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, | |
826 | {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, | |
827 | {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, | |
828 | {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} | |
829 | }; | |
830 | ||
831 | static const u8 fallback_rate1[5][5] = { | |
832 | {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, | |
833 | {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, | |
834 | {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, | |
835 | {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, | |
836 | {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} | |
837 | }; | |
838 | ||
839 | static int vnt_int_report_rate(struct vnt_private *priv, | |
54382859 | 840 | struct vnt_td_info *context, u8 tsr0, u8 tsr1) |
59918bea MP |
841 | { |
842 | struct vnt_tx_fifo_head *fifo_head; | |
843 | struct ieee80211_tx_info *info; | |
844 | struct ieee80211_rate *rate; | |
845 | u16 fb_option; | |
846 | u8 tx_retry = (tsr0 & TSR0_NCR); | |
847 | s8 idx; | |
848 | ||
849 | if (!context) | |
850 | return -ENOMEM; | |
851 | ||
852 | if (!context->skb) | |
853 | return -EINVAL; | |
854 | ||
855 | fifo_head = (struct vnt_tx_fifo_head *)context->buf; | |
856 | fb_option = (le16_to_cpu(fifo_head->fifo_ctl) & | |
857 | (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1)); | |
858 | ||
859 | info = IEEE80211_SKB_CB(context->skb); | |
860 | idx = info->control.rates[0].idx; | |
861 | ||
862 | if (fb_option && !(tsr1 & TSR1_TERR)) { | |
863 | u8 tx_rate; | |
864 | u8 retry = tx_retry; | |
865 | ||
866 | rate = ieee80211_get_tx_rate(priv->hw, info); | |
867 | tx_rate = rate->hw_value - RATE_18M; | |
868 | ||
869 | if (retry > 4) | |
870 | retry = 4; | |
871 | ||
872 | if (fb_option & FIFOCTL_AUTO_FB_0) | |
873 | tx_rate = fallback_rate0[tx_rate][retry]; | |
874 | else if (fb_option & FIFOCTL_AUTO_FB_1) | |
875 | tx_rate = fallback_rate1[tx_rate][retry]; | |
876 | ||
57fbcce3 | 877 | if (info->band == NL80211_BAND_5GHZ) |
59918bea MP |
878 | idx = tx_rate - RATE_6M; |
879 | else | |
880 | idx = tx_rate; | |
881 | } | |
882 | ||
883 | ieee80211_tx_info_clear_status(info); | |
884 | ||
885 | info->status.rates[0].count = tx_retry; | |
886 | ||
887 | if (!(tsr1 & TSR1_TERR)) { | |
888 | info->status.rates[0].idx = idx; | |
6e44dc4b MP |
889 | |
890 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | |
891 | info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; | |
892 | else | |
893 | info->flags |= IEEE80211_TX_STAT_ACK; | |
59918bea MP |
894 | } |
895 | ||
896 | return 0; | |
897 | } | |
898 | ||
0924a89b | 899 | static int device_tx_srv(struct vnt_private *priv, unsigned int idx) |
84b50762 | 900 | { |
9f31b695 | 901 | struct vnt_tx_desc *desc; |
915006cd JP |
902 | int works = 0; |
903 | unsigned char byTsr0; | |
904 | unsigned char byTsr1; | |
915006cd | 905 | |
0924a89b | 906 | for (desc = priv->apTailTD[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) { |
9f31b695 | 907 | if (desc->td0.owner == OWNED_BY_NIC) |
915006cd JP |
908 | break; |
909 | if (works++ > 15) | |
910 | break; | |
911 | ||
9f31b695 MP |
912 | byTsr0 = desc->td0.tsr0; |
913 | byTsr1 = desc->td0.tsr1; | |
915006cd | 914 | |
bb72dd53 | 915 | /* Only the status of first TD in the chain is correct */ |
9f31b695 MP |
916 | if (desc->td1.tcr & TCR_STP) { |
917 | if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) { | |
915006cd JP |
918 | if (!(byTsr1 & TSR1_TERR)) { |
919 | if (byTsr0 != 0) { | |
48caf5a0 | 920 | pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n", |
0924a89b | 921 | (int)idx, byTsr1, |
48caf5a0 | 922 | byTsr0); |
915006cd | 923 | } |
5e0cc8a2 | 924 | } else { |
48caf5a0 | 925 | pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n", |
0924a89b | 926 | (int)idx, byTsr1, byTsr0); |
915006cd JP |
927 | } |
928 | } | |
929 | ||
930 | if (byTsr1 & TSR1_TERR) { | |
9f31b695 | 931 | if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) { |
48caf5a0 | 932 | pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n", |
0924a89b | 933 | (int)idx, byTsr1, byTsr0); |
915006cd | 934 | } |
915006cd | 935 | } |
ad3fee9b | 936 | |
9f31b695 | 937 | vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1); |
ad3fee9b | 938 | |
9f31b695 | 939 | device_free_tx_buf(priv, desc); |
0924a89b | 940 | priv->iTDUsed[idx]--; |
915006cd | 941 | } |
915006cd JP |
942 | } |
943 | ||
0924a89b | 944 | priv->apTailTD[idx] = desc; |
915006cd JP |
945 | |
946 | return works; | |
5449c685 FB |
947 | } |
948 | ||
78e0e853 | 949 | static void device_error(struct vnt_private *priv, unsigned short status) |
84b50762 | 950 | { |
915006cd | 951 | if (status & ISR_FETALERR) { |
78e0e853 | 952 | dev_err(&priv->pcid->dev, "Hardware fatal error\n"); |
42f709ef | 953 | |
f9f853af | 954 | MACbShutdown(priv); |
915006cd JP |
955 | return; |
956 | } | |
5449c685 FB |
957 | } |
958 | ||
78e0e853 | 959 | static void device_free_tx_buf(struct vnt_private *priv, |
5e76c8f4 | 960 | struct vnt_tx_desc *desc) |
84b50762 | 961 | { |
12f2ee35 MP |
962 | struct vnt_td_info *td_info = desc->td_info; |
963 | struct sk_buff *skb = td_info->skb; | |
5449c685 | 964 | |
3fa0917b | 965 | if (skb) |
78e0e853 | 966 | ieee80211_tx_status_irqsafe(priv->hw, skb); |
5449c685 | 967 | |
12f2ee35 MP |
968 | td_info->skb = NULL; |
969 | td_info->flags = 0; | |
5449c685 FB |
970 | } |
971 | ||
64e4fd51 MP |
972 | static void vnt_check_bb_vga(struct vnt_private *priv) |
973 | { | |
974 | long dbm; | |
975 | int i; | |
976 | ||
977 | if (!priv->bUpdateBBVGA) | |
978 | return; | |
979 | ||
980 | if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | |
981 | return; | |
982 | ||
983 | if (!(priv->vif->bss_conf.assoc && priv->uCurrRSSI)) | |
984 | return; | |
985 | ||
986 | RFvRSSITodBm(priv, (u8)priv->uCurrRSSI, &dbm); | |
987 | ||
988 | for (i = 0; i < BB_VGA_LEVEL; i++) { | |
989 | if (dbm < priv->ldBmThreshold[i]) { | |
990 | priv->byBBVGANew = priv->abyBBVGA[i]; | |
991 | break; | |
992 | } | |
993 | } | |
994 | ||
995 | if (priv->byBBVGANew == priv->byBBVGACurrent) { | |
996 | priv->uBBVGADiffCount = 1; | |
997 | return; | |
998 | } | |
999 | ||
1000 | priv->uBBVGADiffCount++; | |
1001 | ||
1002 | if (priv->uBBVGADiffCount == 1) { | |
1003 | /* first VGA diff gain */ | |
1004 | BBvSetVGAGainOffset(priv, priv->byBBVGANew); | |
1005 | ||
1006 | dev_dbg(&priv->pcid->dev, | |
1007 | "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", | |
1008 | (int)dbm, priv->byBBVGANew, | |
1009 | priv->byBBVGACurrent, | |
1010 | (int)priv->uBBVGADiffCount); | |
1011 | } | |
1012 | ||
1013 | if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { | |
1014 | dev_dbg(&priv->pcid->dev, | |
1015 | "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", | |
1016 | (int)dbm, priv->byBBVGANew, | |
1017 | priv->byBBVGACurrent, | |
1018 | (int)priv->uBBVGADiffCount); | |
1019 | ||
1020 | BBvSetVGAGainOffset(priv, priv->byBBVGANew); | |
1021 | } | |
1022 | } | |
1023 | ||
2995dfe6 | 1024 | static void vnt_interrupt_process(struct vnt_private *priv) |
84b50762 | 1025 | { |
2995dfe6 | 1026 | struct ieee80211_low_level_stats *low_stats = &priv->low_stats; |
915006cd | 1027 | int max_count = 0; |
700f6c02 | 1028 | u32 mib_counter; |
41b9e5e5 | 1029 | u32 isr; |
6cff1f6a | 1030 | unsigned long flags; |
915006cd | 1031 | |
41b9e5e5 | 1032 | MACvReadISR(priv->PortOffset, &isr); |
915006cd | 1033 | |
41b9e5e5 | 1034 | if (isr == 0) |
ff1ce1a8 | 1035 | return; |
915006cd | 1036 | |
41b9e5e5 MP |
1037 | if (isr == 0xffffffff) { |
1038 | pr_debug("isr = 0xffff\n"); | |
ff1ce1a8 | 1039 | return; |
915006cd | 1040 | } |
915006cd | 1041 | |
2995dfe6 | 1042 | spin_lock_irqsave(&priv->lock, flags); |
915006cd | 1043 | |
700f6c02 | 1044 | /* Read low level stats */ |
2995dfe6 | 1045 | MACvReadMIBCounter(priv->PortOffset, &mib_counter); |
700f6c02 MP |
1046 | |
1047 | low_stats->dot11RTSSuccessCount += mib_counter & 0xff; | |
1048 | low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff; | |
1049 | low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff; | |
1050 | low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff; | |
915006cd | 1051 | |
bb72dd53 AS |
1052 | /* |
1053 | * TBD.... | |
1054 | * Must do this after doing rx/tx, cause ISR bit is slow | |
1055 | * than RD/TD write back | |
1056 | * update ISR counter | |
1057 | */ | |
41b9e5e5 MP |
1058 | while (isr && priv->vif) { |
1059 | MACvWriteISR(priv->PortOffset, isr); | |
915006cd | 1060 | |
41b9e5e5 | 1061 | if (isr & ISR_FETALERR) { |
48caf5a0 | 1062 | pr_debug(" ISR_FETALERR\n"); |
2995dfe6 MP |
1063 | VNSvOutPortB(priv->PortOffset + MAC_REG_SOFTPWRCTL, 0); |
1064 | VNSvOutPortW(priv->PortOffset + | |
1065 | MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); | |
41b9e5e5 | 1066 | device_error(priv, isr); |
915006cd JP |
1067 | } |
1068 | ||
41b9e5e5 | 1069 | if (isr & ISR_TBTT) { |
2995dfe6 MP |
1070 | if (priv->op_mode != NL80211_IFTYPE_ADHOC) |
1071 | vnt_check_bb_vga(priv); | |
915006cd | 1072 | |
2995dfe6 MP |
1073 | priv->bBeaconSent = false; |
1074 | if (priv->bEnablePSMode) | |
1075 | PSbIsNextTBTTWakeUp((void *)priv); | |
915006cd | 1076 | |
2995dfe6 MP |
1077 | if ((priv->op_mode == NL80211_IFTYPE_AP || |
1078 | priv->op_mode == NL80211_IFTYPE_ADHOC) && | |
1079 | priv->vif->bss_conf.enable_beacon) { | |
f9f853af | 1080 | MACvOneShotTimer1MicroSec(priv, |
2995dfe6 | 1081 | (priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); |
915006cd JP |
1082 | } |
1083 | ||
4e8a7e5f | 1084 | /* TODO: adhoc PS mode */ |
915006cd JP |
1085 | } |
1086 | ||
41b9e5e5 | 1087 | if (isr & ISR_BNTX) { |
2995dfe6 MP |
1088 | if (priv->op_mode == NL80211_IFTYPE_ADHOC) { |
1089 | priv->bIsBeaconBufReadySet = false; | |
1090 | priv->cbBeaconBufReadySetCnt = 0; | |
915006cd JP |
1091 | } |
1092 | ||
2995dfe6 | 1093 | priv->bBeaconSent = true; |
915006cd JP |
1094 | } |
1095 | ||
41b9e5e5 | 1096 | if (isr & ISR_RXDMA0) |
2995dfe6 | 1097 | max_count += device_rx_srv(priv, TYPE_RXDMA0); |
bc5cf656 | 1098 | |
41b9e5e5 | 1099 | if (isr & ISR_RXDMA1) |
2995dfe6 | 1100 | max_count += device_rx_srv(priv, TYPE_RXDMA1); |
bc5cf656 | 1101 | |
41b9e5e5 | 1102 | if (isr & ISR_TXDMA0) |
2995dfe6 | 1103 | max_count += device_tx_srv(priv, TYPE_TXDMA0); |
bc5cf656 | 1104 | |
41b9e5e5 | 1105 | if (isr & ISR_AC0DMA) |
2995dfe6 | 1106 | max_count += device_tx_srv(priv, TYPE_AC0DMA); |
bc5cf656 | 1107 | |
41b9e5e5 | 1108 | if (isr & ISR_SOFTTIMER1) { |
2995dfe6 MP |
1109 | if (priv->vif->bss_conf.enable_beacon) |
1110 | vnt_beacon_make(priv, priv->vif); | |
915006cd JP |
1111 | } |
1112 | ||
54fbb2da | 1113 | /* If both buffers available wake the queue */ |
2995dfe6 MP |
1114 | if (AVAIL_TD(priv, TYPE_TXDMA0) && |
1115 | AVAIL_TD(priv, TYPE_AC0DMA) && | |
1116 | ieee80211_queue_stopped(priv->hw, 0)) | |
1117 | ieee80211_wake_queues(priv->hw); | |
54fbb2da | 1118 | |
41b9e5e5 | 1119 | MACvReadISR(priv->PortOffset, &isr); |
915006cd | 1120 | |
2995dfe6 MP |
1121 | MACvReceive0(priv->PortOffset); |
1122 | MACvReceive1(priv->PortOffset); | |
915006cd | 1123 | |
bc667b99 | 1124 | if (max_count > priv->opts.int_works) |
915006cd JP |
1125 | break; |
1126 | } | |
1127 | ||
2995dfe6 | 1128 | spin_unlock_irqrestore(&priv->lock, flags); |
ff1ce1a8 MP |
1129 | } |
1130 | ||
1131 | static void vnt_interrupt_work(struct work_struct *work) | |
1132 | { | |
1133 | struct vnt_private *priv = | |
1134 | container_of(work, struct vnt_private, interrupt_work); | |
1135 | ||
1136 | if (priv->vif) | |
1137 | vnt_interrupt_process(priv); | |
3b9c2f2e MP |
1138 | |
1139 | MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE); | |
ff1ce1a8 | 1140 | } |
6cff1f6a | 1141 | |
ff1ce1a8 MP |
1142 | static irqreturn_t vnt_interrupt(int irq, void *arg) |
1143 | { | |
1144 | struct vnt_private *priv = arg; | |
915006cd | 1145 | |
cc26358f | 1146 | schedule_work(&priv->interrupt_work); |
ff1ce1a8 | 1147 | |
3b9c2f2e MP |
1148 | MACvIntDisable(priv->PortOffset); |
1149 | ||
ff1ce1a8 | 1150 | return IRQ_HANDLED; |
5449c685 | 1151 | } |
915006cd | 1152 | |
67013f2c MP |
1153 | static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) |
1154 | { | |
1155 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | |
e2357271 | 1156 | struct vnt_tx_desc *head_td; |
c3125305 | 1157 | u32 dma_idx; |
67013f2c MP |
1158 | unsigned long flags; |
1159 | ||
1160 | spin_lock_irqsave(&priv->lock, flags); | |
1161 | ||
c3125305 MP |
1162 | if (ieee80211_is_data(hdr->frame_control)) |
1163 | dma_idx = TYPE_AC0DMA; | |
1164 | else | |
67013f2c MP |
1165 | dma_idx = TYPE_TXDMA0; |
1166 | ||
1167 | if (AVAIL_TD(priv, dma_idx) < 1) { | |
1168 | spin_unlock_irqrestore(&priv->lock, flags); | |
113d6dc1 | 1169 | ieee80211_stop_queues(priv->hw); |
67013f2c MP |
1170 | return -ENOMEM; |
1171 | } | |
1172 | ||
1173 | head_td = priv->apCurrTD[dma_idx]; | |
1174 | ||
9cc8eac9 | 1175 | head_td->td1.tcr = 0; |
67013f2c | 1176 | |
54382859 | 1177 | head_td->td_info->skb = skb; |
67013f2c | 1178 | |
c3125305 | 1179 | if (dma_idx == TYPE_AC0DMA) |
54382859 | 1180 | head_td->td_info->flags = TD_FLAGS_NETIF_SKB; |
c3125305 | 1181 | |
67013f2c MP |
1182 | priv->apCurrTD[dma_idx] = head_td->next; |
1183 | ||
1184 | spin_unlock_irqrestore(&priv->lock, flags); | |
1185 | ||
1186 | vnt_generate_fifo_header(priv, dma_idx, head_td, skb); | |
1187 | ||
67013f2c MP |
1188 | spin_lock_irqsave(&priv->lock, flags); |
1189 | ||
1190 | priv->bPWBitOn = false; | |
1191 | ||
b5745290 | 1192 | /* Set TSR1 & ReqCount in TxDescHead */ |
9cc8eac9 | 1193 | head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU); |
54382859 | 1194 | head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count); |
b5745290 | 1195 | |
54382859 | 1196 | head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma); |
187e2a81 | 1197 | |
d65d2b25 MP |
1198 | /* Poll Transmit the adapter */ |
1199 | wmb(); | |
5235ff6a | 1200 | head_td->td0.owner = OWNED_BY_NIC; |
d65d2b25 MP |
1201 | wmb(); /* second memory barrier */ |
1202 | ||
54382859 | 1203 | if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB) |
67013f2c | 1204 | MACvTransmitAC0(priv->PortOffset); |
c3125305 | 1205 | else |
67013f2c MP |
1206 | MACvTransmit0(priv->PortOffset); |
1207 | ||
d65d2b25 MP |
1208 | priv->iTDUsed[dma_idx]++; |
1209 | ||
67013f2c MP |
1210 | spin_unlock_irqrestore(&priv->lock, flags); |
1211 | ||
1212 | return 0; | |
1213 | } | |
1214 | ||
1215 | static void vnt_tx_80211(struct ieee80211_hw *hw, | |
1216 | struct ieee80211_tx_control *control, | |
1217 | struct sk_buff *skb) | |
1218 | { | |
1219 | struct vnt_private *priv = hw->priv; | |
1220 | ||
113d6dc1 | 1221 | if (vnt_tx_packet(priv, skb)) |
67013f2c | 1222 | ieee80211_free_txskb(hw, skb); |
67013f2c MP |
1223 | } |
1224 | ||
1225 | static int vnt_start(struct ieee80211_hw *hw) | |
1226 | { | |
1227 | struct vnt_private *priv = hw->priv; | |
1228 | int ret; | |
1229 | ||
1230 | priv->rx_buf_sz = PKT_BUF_SZ; | |
1231 | if (!device_init_rings(priv)) | |
1232 | return -ENOMEM; | |
1233 | ||
50aefc19 | 1234 | ret = request_irq(priv->pcid->irq, vnt_interrupt, |
67013f2c MP |
1235 | IRQF_SHARED, "vt6655", priv); |
1236 | if (ret) { | |
1237 | dev_dbg(&priv->pcid->dev, "failed to start irq\n"); | |
1dc751a5 | 1238 | goto err_free_rings; |
67013f2c MP |
1239 | } |
1240 | ||
1241 | dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n"); | |
5341ee0a JHK |
1242 | ret = device_init_rd0_ring(priv); |
1243 | if (ret) | |
1dc751a5 | 1244 | goto err_free_irq; |
5341ee0a JHK |
1245 | ret = device_init_rd1_ring(priv); |
1246 | if (ret) | |
1247 | goto err_free_rd0_ring; | |
1248 | ret = device_init_td0_ring(priv); | |
1249 | if (ret) | |
1250 | goto err_free_rd1_ring; | |
1251 | ret = device_init_td1_ring(priv); | |
1252 | if (ret) | |
1253 | goto err_free_td0_ring; | |
67013f2c MP |
1254 | |
1255 | device_init_registers(priv); | |
1256 | ||
1257 | dev_dbg(&priv->pcid->dev, "call MACvIntEnable\n"); | |
1258 | MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE); | |
1259 | ||
1260 | ieee80211_wake_queues(hw); | |
1261 | ||
1262 | return 0; | |
5341ee0a JHK |
1263 | |
1264 | err_free_td0_ring: | |
1265 | device_free_td0_ring(priv); | |
1266 | err_free_rd1_ring: | |
1267 | device_free_rd1_ring(priv); | |
1268 | err_free_rd0_ring: | |
1269 | device_free_rd0_ring(priv); | |
1dc751a5 JHK |
1270 | err_free_irq: |
1271 | free_irq(priv->pcid->irq, priv); | |
1272 | err_free_rings: | |
1273 | device_free_rings(priv); | |
5341ee0a | 1274 | return ret; |
67013f2c MP |
1275 | } |
1276 | ||
1277 | static void vnt_stop(struct ieee80211_hw *hw) | |
1278 | { | |
1279 | struct vnt_private *priv = hw->priv; | |
1280 | ||
1281 | ieee80211_stop_queues(hw); | |
1282 | ||
ff1ce1a8 MP |
1283 | cancel_work_sync(&priv->interrupt_work); |
1284 | ||
f9f853af MP |
1285 | MACbShutdown(priv); |
1286 | MACbSoftwareReset(priv); | |
67013f2c MP |
1287 | CARDbRadioPowerOff(priv); |
1288 | ||
1289 | device_free_td0_ring(priv); | |
1290 | device_free_td1_ring(priv); | |
1291 | device_free_rd0_ring(priv); | |
1292 | device_free_rd1_ring(priv); | |
67013f2c MP |
1293 | device_free_rings(priv); |
1294 | ||
1295 | free_irq(priv->pcid->irq, priv); | |
1296 | } | |
1297 | ||
1298 | static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1299 | { | |
1300 | struct vnt_private *priv = hw->priv; | |
1301 | ||
1302 | priv->vif = vif; | |
1303 | ||
1304 | switch (vif->type) { | |
1305 | case NL80211_IFTYPE_STATION: | |
67013f2c MP |
1306 | break; |
1307 | case NL80211_IFTYPE_ADHOC: | |
1308 | MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); | |
1309 | ||
1310 | MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); | |
1311 | ||
1312 | break; | |
1313 | case NL80211_IFTYPE_AP: | |
1314 | MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); | |
1315 | ||
1316 | MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); | |
1317 | ||
1318 | break; | |
1319 | default: | |
1320 | return -EOPNOTSUPP; | |
1321 | } | |
1322 | ||
1323 | priv->op_mode = vif->type; | |
1324 | ||
1325 | return 0; | |
1326 | } | |
1327 | ||
1328 | static void vnt_remove_interface(struct ieee80211_hw *hw, | |
1329 | struct ieee80211_vif *vif) | |
1330 | { | |
1331 | struct vnt_private *priv = hw->priv; | |
1332 | ||
1333 | switch (vif->type) { | |
1334 | case NL80211_IFTYPE_STATION: | |
67013f2c MP |
1335 | break; |
1336 | case NL80211_IFTYPE_ADHOC: | |
1337 | MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1338 | MACvRegBitsOff(priv->PortOffset, | |
1339 | MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1340 | MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); | |
1341 | break; | |
1342 | case NL80211_IFTYPE_AP: | |
1343 | MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1344 | MACvRegBitsOff(priv->PortOffset, | |
1345 | MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1346 | MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); | |
1347 | break; | |
1348 | default: | |
1349 | break; | |
1350 | } | |
1351 | ||
1352 | priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; | |
1353 | } | |
1354 | ||
67013f2c MP |
1355 | static int vnt_config(struct ieee80211_hw *hw, u32 changed) |
1356 | { | |
1357 | struct vnt_private *priv = hw->priv; | |
1358 | struct ieee80211_conf *conf = &hw->conf; | |
1359 | u8 bb_type; | |
1360 | ||
1361 | if (changed & IEEE80211_CONF_CHANGE_PS) { | |
1362 | if (conf->flags & IEEE80211_CONF_PS) | |
1363 | PSvEnablePowerSaving(priv, conf->listen_interval); | |
1364 | else | |
1365 | PSvDisablePowerSaving(priv); | |
1366 | } | |
1367 | ||
1368 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || | |
1369 | (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { | |
d7a4cfa8 | 1370 | set_channel(priv, conf->chandef.chan); |
67013f2c | 1371 | |
57fbcce3 | 1372 | if (conf->chandef.chan->band == NL80211_BAND_5GHZ) |
67013f2c MP |
1373 | bb_type = BB_TYPE_11A; |
1374 | else | |
1375 | bb_type = BB_TYPE_11G; | |
1376 | ||
1377 | if (priv->byBBType != bb_type) { | |
1378 | priv->byBBType = bb_type; | |
1379 | ||
bfb6c863 | 1380 | CARDbSetPhyParameter(priv, priv->byBBType); |
67013f2c MP |
1381 | } |
1382 | } | |
1383 | ||
1384 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | |
1385 | if (priv->byBBType == BB_TYPE_11B) | |
1386 | priv->wCurrentRate = RATE_1M; | |
1387 | else | |
1388 | priv->wCurrentRate = RATE_54M; | |
1389 | ||
1390 | RFbSetPower(priv, priv->wCurrentRate, | |
1391 | conf->chandef.chan->hw_value); | |
1392 | } | |
1393 | ||
1394 | return 0; | |
1395 | } | |
1396 | ||
1397 | static void vnt_bss_info_changed(struct ieee80211_hw *hw, | |
7959c331 MS |
1398 | struct ieee80211_vif *vif, |
1399 | struct ieee80211_bss_conf *conf, u32 changed) | |
67013f2c MP |
1400 | { |
1401 | struct vnt_private *priv = hw->priv; | |
1402 | ||
1403 | priv->current_aid = conf->aid; | |
1404 | ||
8e8e9198 | 1405 | if (changed & BSS_CHANGED_BSSID && conf->bssid) { |
664a5c1d MP |
1406 | unsigned long flags; |
1407 | ||
1408 | spin_lock_irqsave(&priv->lock, flags); | |
1409 | ||
67013f2c MP |
1410 | MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid); |
1411 | ||
664a5c1d MP |
1412 | spin_unlock_irqrestore(&priv->lock, flags); |
1413 | } | |
1414 | ||
67013f2c MP |
1415 | if (changed & BSS_CHANGED_BASIC_RATES) { |
1416 | priv->basic_rates = conf->basic_rates; | |
1417 | ||
1418 | CARDvUpdateBasicTopRate(priv); | |
1419 | ||
1420 | dev_dbg(&priv->pcid->dev, | |
1421 | "basic rates %x\n", conf->basic_rates); | |
1422 | } | |
1423 | ||
1424 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | |
1425 | if (conf->use_short_preamble) { | |
1426 | MACvEnableBarkerPreambleMd(priv->PortOffset); | |
1427 | priv->byPreambleType = true; | |
1428 | } else { | |
1429 | MACvDisableBarkerPreambleMd(priv->PortOffset); | |
1430 | priv->byPreambleType = false; | |
1431 | } | |
1432 | } | |
1433 | ||
1434 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | |
1435 | if (conf->use_cts_prot) | |
1436 | MACvEnableProtectMD(priv->PortOffset); | |
1437 | else | |
1438 | MACvDisableProtectMD(priv->PortOffset); | |
1439 | } | |
1440 | ||
1441 | if (changed & BSS_CHANGED_ERP_SLOT) { | |
1442 | if (conf->use_short_slot) | |
1443 | priv->bShortSlotTime = true; | |
1444 | else | |
1445 | priv->bShortSlotTime = false; | |
1446 | ||
bfb6c863 | 1447 | CARDbSetPhyParameter(priv, priv->byBBType); |
67013f2c MP |
1448 | BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]); |
1449 | } | |
1450 | ||
1451 | if (changed & BSS_CHANGED_TXPOWER) | |
1452 | RFbSetPower(priv, priv->wCurrentRate, | |
1453 | conf->chandef.chan->hw_value); | |
1454 | ||
1455 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | |
1456 | dev_dbg(&priv->pcid->dev, | |
1457 | "Beacon enable %d\n", conf->enable_beacon); | |
1458 | ||
1459 | if (conf->enable_beacon) { | |
1460 | vnt_beacon_enable(priv, vif, conf); | |
1461 | ||
84c00afe MK |
1462 | MACvRegBitsOn(priv->PortOffset, MAC_REG_TCR, |
1463 | TCR_AUTOBCNTX); | |
67013f2c | 1464 | } else { |
84c00afe MK |
1465 | MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, |
1466 | TCR_AUTOBCNTX); | |
67013f2c MP |
1467 | } |
1468 | } | |
1469 | ||
1f171240 MP |
1470 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) && |
1471 | priv->op_mode != NL80211_IFTYPE_AP) { | |
1472 | if (conf->assoc && conf->beacon_rate) { | |
67013f2c | 1473 | CARDbUpdateTSF(priv, conf->beacon_rate->hw_value, |
032ed34a | 1474 | conf->sync_tsf); |
67013f2c MP |
1475 | |
1476 | CARDbSetBeaconPeriod(priv, conf->beacon_int); | |
1477 | ||
738487ff | 1478 | CARDvSetFirstNextTBTT(priv, conf->beacon_int); |
c7b14ea0 MP |
1479 | } else { |
1480 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, | |
1481 | TFTCTL_TSFCNTRST); | |
1482 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, | |
1483 | TFTCTL_TSFCNTREN); | |
67013f2c MP |
1484 | } |
1485 | } | |
1486 | } | |
1487 | ||
1488 | static u64 vnt_prepare_multicast(struct ieee80211_hw *hw, | |
7959c331 | 1489 | struct netdev_hw_addr_list *mc_list) |
67013f2c MP |
1490 | { |
1491 | struct vnt_private *priv = hw->priv; | |
1492 | struct netdev_hw_addr *ha; | |
1493 | u64 mc_filter = 0; | |
1494 | u32 bit_nr = 0; | |
1495 | ||
1496 | netdev_hw_addr_list_for_each(ha, mc_list) { | |
1497 | bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; | |
1498 | ||
1499 | mc_filter |= 1ULL << (bit_nr & 0x3f); | |
1500 | } | |
1501 | ||
1502 | priv->mc_list_count = mc_list->count; | |
1503 | ||
1504 | return mc_filter; | |
1505 | } | |
1506 | ||
1507 | static void vnt_configure(struct ieee80211_hw *hw, | |
7959c331 MS |
1508 | unsigned int changed_flags, |
1509 | unsigned int *total_flags, u64 multicast) | |
67013f2c MP |
1510 | { |
1511 | struct vnt_private *priv = hw->priv; | |
1512 | u8 rx_mode = 0; | |
1513 | ||
df140465 | 1514 | *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC; |
67013f2c MP |
1515 | |
1516 | VNSvInPortB(priv->PortOffset + MAC_REG_RCR, &rx_mode); | |
1517 | ||
1518 | dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode); | |
1519 | ||
67013f2c MP |
1520 | if (changed_flags & FIF_ALLMULTI) { |
1521 | if (*total_flags & FIF_ALLMULTI) { | |
95775d12 MP |
1522 | unsigned long flags; |
1523 | ||
1524 | spin_lock_irqsave(&priv->lock, flags); | |
1525 | ||
67013f2c MP |
1526 | if (priv->mc_list_count > 2) { |
1527 | MACvSelectPage1(priv->PortOffset); | |
1528 | ||
1529 | VNSvOutPortD(priv->PortOffset + | |
1530 | MAC_REG_MAR0, 0xffffffff); | |
1531 | VNSvOutPortD(priv->PortOffset + | |
1532 | MAC_REG_MAR0 + 4, 0xffffffff); | |
1533 | ||
1534 | MACvSelectPage0(priv->PortOffset); | |
1535 | } else { | |
1536 | MACvSelectPage1(priv->PortOffset); | |
1537 | ||
1538 | VNSvOutPortD(priv->PortOffset + | |
1539 | MAC_REG_MAR0, (u32)multicast); | |
1540 | VNSvOutPortD(priv->PortOffset + | |
1541 | MAC_REG_MAR0 + 4, | |
1542 | (u32)(multicast >> 32)); | |
1543 | ||
1544 | MACvSelectPage0(priv->PortOffset); | |
1545 | } | |
1546 | ||
95775d12 MP |
1547 | spin_unlock_irqrestore(&priv->lock, flags); |
1548 | ||
67013f2c MP |
1549 | rx_mode |= RCR_MULTICAST | RCR_BROADCAST; |
1550 | } else { | |
1551 | rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); | |
1552 | } | |
1553 | } | |
1554 | ||
1555 | if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) { | |
1556 | rx_mode |= RCR_MULTICAST | RCR_BROADCAST; | |
1557 | ||
1558 | if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) | |
1559 | rx_mode &= ~RCR_BSSID; | |
1560 | else | |
1561 | rx_mode |= RCR_BSSID; | |
1562 | } | |
1563 | ||
1564 | VNSvOutPortB(priv->PortOffset + MAC_REG_RCR, rx_mode); | |
1565 | ||
1566 | dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode); | |
1567 | } | |
1568 | ||
1569 | static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |
7959c331 MS |
1570 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
1571 | struct ieee80211_key_conf *key) | |
67013f2c MP |
1572 | { |
1573 | struct vnt_private *priv = hw->priv; | |
1574 | ||
1575 | switch (cmd) { | |
1576 | case SET_KEY: | |
1577 | if (vnt_set_keys(hw, sta, vif, key)) | |
1578 | return -EOPNOTSUPP; | |
1579 | break; | |
1580 | case DISABLE_KEY: | |
1581 | if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) | |
1582 | clear_bit(key->hw_key_idx, &priv->key_entry_inuse); | |
1583 | default: | |
1584 | break; | |
1585 | } | |
1586 | ||
1587 | return 0; | |
1588 | } | |
1589 | ||
700f6c02 MP |
1590 | static int vnt_get_stats(struct ieee80211_hw *hw, |
1591 | struct ieee80211_low_level_stats *stats) | |
1592 | { | |
1593 | struct vnt_private *priv = hw->priv; | |
1594 | ||
1595 | memcpy(stats, &priv->low_stats, sizeof(*stats)); | |
1596 | ||
1597 | return 0; | |
1598 | } | |
1599 | ||
67013f2c MP |
1600 | static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
1601 | { | |
1602 | struct vnt_private *priv = hw->priv; | |
1603 | u64 tsf; | |
1604 | ||
738487ff | 1605 | CARDbGetCurrentTSF(priv, &tsf); |
67013f2c MP |
1606 | |
1607 | return tsf; | |
1608 | } | |
1609 | ||
1610 | static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1611 | u64 tsf) | |
1612 | { | |
1613 | struct vnt_private *priv = hw->priv; | |
1614 | ||
738487ff | 1615 | CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int); |
67013f2c MP |
1616 | } |
1617 | ||
1618 | static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1619 | { | |
1620 | struct vnt_private *priv = hw->priv; | |
1621 | ||
1622 | /* reset TSF counter */ | |
1623 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); | |
1624 | } | |
1625 | ||
1626 | static const struct ieee80211_ops vnt_mac_ops = { | |
1627 | .tx = vnt_tx_80211, | |
1628 | .start = vnt_start, | |
1629 | .stop = vnt_stop, | |
1630 | .add_interface = vnt_add_interface, | |
1631 | .remove_interface = vnt_remove_interface, | |
1632 | .config = vnt_config, | |
1633 | .bss_info_changed = vnt_bss_info_changed, | |
1634 | .prepare_multicast = vnt_prepare_multicast, | |
1635 | .configure_filter = vnt_configure, | |
1636 | .set_key = vnt_set_key, | |
700f6c02 | 1637 | .get_stats = vnt_get_stats, |
67013f2c MP |
1638 | .get_tsf = vnt_get_tsf, |
1639 | .set_tsf = vnt_set_tsf, | |
1640 | .reset_tsf = vnt_reset_tsf, | |
1641 | }; | |
1642 | ||
b7c9cd45 | 1643 | static int vnt_init(struct vnt_private *priv) |
67013f2c MP |
1644 | { |
1645 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); | |
1646 | ||
3d75b9e2 MP |
1647 | vnt_init_bands(priv); |
1648 | ||
67013f2c MP |
1649 | if (ieee80211_register_hw(priv->hw)) |
1650 | return -ENODEV; | |
1651 | ||
1652 | priv->mac_hw = true; | |
1653 | ||
1654 | CARDbRadioPowerOff(priv); | |
1655 | ||
1656 | return 0; | |
1657 | } | |
1658 | ||
1659 | static int | |
1660 | vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) | |
1661 | { | |
67013f2c MP |
1662 | struct vnt_private *priv; |
1663 | struct ieee80211_hw *hw; | |
1664 | struct wiphy *wiphy; | |
1665 | int rc; | |
1666 | ||
1667 | dev_notice(&pcid->dev, | |
1668 | "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); | |
1669 | ||
1670 | dev_notice(&pcid->dev, | |
1671 | "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); | |
1672 | ||
1673 | hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops); | |
1674 | if (!hw) { | |
1675 | dev_err(&pcid->dev, "could not register ieee80211_hw\n"); | |
1676 | return -ENOMEM; | |
1677 | } | |
1678 | ||
1679 | priv = hw->priv; | |
f3179826 | 1680 | priv->pcid = pcid; |
67013f2c | 1681 | |
f3179826 | 1682 | spin_lock_init(&priv->lock); |
67013f2c MP |
1683 | |
1684 | priv->hw = hw; | |
1685 | ||
1686 | SET_IEEE80211_DEV(priv->hw, &pcid->dev); | |
1687 | ||
1688 | if (pci_enable_device(pcid)) { | |
1689 | device_free_info(priv); | |
1690 | return -ENODEV; | |
1691 | } | |
1692 | ||
1693 | dev_dbg(&pcid->dev, | |
1694 | "Before get pci_info memaddr is %x\n", priv->memaddr); | |
1695 | ||
a03b8b3e | 1696 | pci_set_master(pcid); |
67013f2c | 1697 | |
a03b8b3e MP |
1698 | priv->memaddr = pci_resource_start(pcid, 0); |
1699 | priv->ioaddr = pci_resource_start(pcid, 1); | |
67013f2c | 1700 | priv->PortOffset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK, |
319755a7 | 1701 | 256); |
67013f2c MP |
1702 | if (!priv->PortOffset) { |
1703 | dev_err(&pcid->dev, ": Failed to IO remapping ..\n"); | |
1704 | device_free_info(priv); | |
1705 | return -ENODEV; | |
1706 | } | |
1707 | ||
1708 | rc = pci_request_regions(pcid, DEVICE_NAME); | |
1709 | if (rc) { | |
1710 | dev_err(&pcid->dev, ": Failed to find PCI device\n"); | |
1711 | device_free_info(priv); | |
1712 | return -ENODEV; | |
1713 | } | |
1714 | ||
d5806c53 MP |
1715 | if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) { |
1716 | dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n"); | |
1717 | device_free_info(priv); | |
1718 | return -ENODEV; | |
1719 | } | |
1720 | ||
ff1ce1a8 MP |
1721 | INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); |
1722 | ||
67013f2c | 1723 | /* do reset */ |
f9f853af | 1724 | if (!MACbSoftwareReset(priv)) { |
67013f2c MP |
1725 | dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); |
1726 | device_free_info(priv); | |
1727 | return -ENODEV; | |
1728 | } | |
1729 | /* initial to reload eeprom */ | |
f9f853af | 1730 | MACvInitialize(priv); |
67013f2c MP |
1731 | MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr); |
1732 | ||
1f51d580 MP |
1733 | /* Get RFType */ |
1734 | priv->byRFType = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_RFTYPE); | |
1735 | priv->byRFType &= RF_MASK; | |
1736 | ||
1737 | dev_dbg(&pcid->dev, "RF Type = %x\n", priv->byRFType); | |
1738 | ||
67013f2c MP |
1739 | device_get_options(priv); |
1740 | device_set_options(priv); | |
67013f2c MP |
1741 | |
1742 | wiphy = priv->hw->wiphy; | |
1743 | ||
1744 | wiphy->frag_threshold = FRAG_THRESH_DEF; | |
1745 | wiphy->rts_threshold = RTS_THRESH_DEF; | |
1746 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | |
1747 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); | |
1748 | ||
30686bf7 JB |
1749 | ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY); |
1750 | ieee80211_hw_set(priv->hw, SIGNAL_DBM); | |
1751 | ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); | |
1752 | ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); | |
eda01f61 | 1753 | ieee80211_hw_set(priv->hw, SUPPORTS_PS); |
67013f2c MP |
1754 | |
1755 | priv->hw->max_signal = 100; | |
1756 | ||
80b15db5 NE |
1757 | if (vnt_init(priv)) { |
1758 | device_free_info(priv); | |
67013f2c | 1759 | return -ENODEV; |
80b15db5 | 1760 | } |
67013f2c MP |
1761 | |
1762 | device_print_info(priv); | |
1763 | pci_set_drvdata(pcid, priv); | |
1764 | ||
1765 | return 0; | |
1766 | } | |
1767 | ||
5449c685 | 1768 | /*------------------------------------------------------------------*/ |
5449c685 | 1769 | |
000fe0f5 MP |
1770 | #ifdef CONFIG_PM |
1771 | static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state) | |
1772 | { | |
1773 | struct vnt_private *priv = pci_get_drvdata(pcid); | |
1774 | unsigned long flags; | |
1775 | ||
1776 | spin_lock_irqsave(&priv->lock, flags); | |
1777 | ||
1778 | pci_save_state(pcid); | |
1779 | ||
f9f853af | 1780 | MACbShutdown(priv); |
000fe0f5 MP |
1781 | |
1782 | pci_disable_device(pcid); | |
000fe0f5 MP |
1783 | |
1784 | spin_unlock_irqrestore(&priv->lock, flags); | |
1785 | ||
42c8eb3f JJB |
1786 | pci_set_power_state(pcid, pci_choose_state(pcid, state)); |
1787 | ||
000fe0f5 MP |
1788 | return 0; |
1789 | } | |
1790 | ||
1791 | static int vt6655_resume(struct pci_dev *pcid) | |
1792 | { | |
000fe0f5 MP |
1793 | pci_set_power_state(pcid, PCI_D0); |
1794 | pci_enable_wake(pcid, PCI_D0, 0); | |
1795 | pci_restore_state(pcid); | |
1796 | ||
1797 | return 0; | |
1798 | } | |
1799 | #endif | |
1800 | ||
013a468c | 1801 | MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); |
5449c685 FB |
1802 | |
1803 | static struct pci_driver device_driver = { | |
34381c22 PH |
1804 | .name = DEVICE_NAME, |
1805 | .id_table = vt6655_pci_id_table, | |
1806 | .probe = vt6655_probe, | |
1807 | .remove = vt6655_remove, | |
5449c685 | 1808 | #ifdef CONFIG_PM |
000fe0f5 MP |
1809 | .suspend = vt6655_suspend, |
1810 | .resume = vt6655_resume, | |
5449c685 | 1811 | #endif |
5449c685 FB |
1812 | }; |
1813 | ||
e75e8cac | 1814 | module_pci_driver(device_driver); |