Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
net
wireless
ath
ath9k
ar9002_mac.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2008-2011 Atheros Communications Inc.
3
*
4
* Permission to use, copy, modify, and/or distribute this software for any
5
* purpose with or without fee is hereby granted, provided that the above
6
* copyright notice and this permission notice appear in all copies.
7
*
8
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
*/
16
17
#include "
hw.h
"
18
#include <linux/export.h>
19
20
#define AR_BufLen 0x00000fff
21
22
static
void
ar9002_hw_rx_enable(
struct
ath_hw
*
ah
)
23
{
24
REG_WRITE
(ah,
AR_CR
,
AR_CR_RXE
);
25
}
26
27
static
void
ar9002_hw_set_desc_link(
void
*
ds
,
u32
ds_link
)
28
{
29
((
struct
ath_desc
*) ds)->ds_link =
ds_link
;
30
}
31
32
static
bool
ar9002_hw_get_isr(
struct
ath_hw
*
ah
,
enum
ath9k_int
*masked)
33
{
34
u32
isr
= 0;
35
u32
mask2 = 0;
36
struct
ath9k_hw_capabilities
*pCap = &ah->
caps
;
37
u32
sync_cause = 0;
38
bool
fatal_int =
false
;
39
struct
ath_common
*
common
= ath9k_hw_common(ah);
40
41
if
(!
AR_SREV_9100
(ah)) {
42
if
(
REG_READ
(ah,
AR_INTR_ASYNC_CAUSE
) &
AR_INTR_MAC_IRQ
) {
43
if
((
REG_READ
(ah,
AR_RTC_STATUS
) &
AR_RTC_STATUS_M
)
44
==
AR_RTC_STATUS_ON
) {
45
isr =
REG_READ
(ah,
AR_ISR
);
46
}
47
}
48
49
sync_cause =
REG_READ
(ah,
AR_INTR_SYNC_CAUSE
) &
50
AR_INTR_SYNC_DEFAULT
;
51
52
*masked = 0;
53
54
if
(!isr && !sync_cause)
55
return
false
;
56
}
else
{
57
*masked = 0;
58
isr =
REG_READ
(ah,
AR_ISR
);
59
}
60
61
if
(isr) {
62
if
(isr &
AR_ISR_BCNMISC
) {
63
u32
isr2;
64
isr2 =
REG_READ
(ah,
AR_ISR_S2
);
65
if
(isr2 &
AR_ISR_S2_TIM
)
66
mask2 |=
ATH9K_INT_TIM
;
67
if
(isr2 &
AR_ISR_S2_DTIM
)
68
mask2 |=
ATH9K_INT_DTIM
;
69
if
(isr2 &
AR_ISR_S2_DTIMSYNC
)
70
mask2 |=
ATH9K_INT_DTIMSYNC
;
71
if
(isr2 & (
AR_ISR_S2_CABEND
))
72
mask2 |=
ATH9K_INT_CABEND
;
73
if
(isr2 &
AR_ISR_S2_GTT
)
74
mask2 |=
ATH9K_INT_GTT
;
75
if
(isr2 &
AR_ISR_S2_CST
)
76
mask2 |=
ATH9K_INT_CST
;
77
if
(isr2 &
AR_ISR_S2_TSFOOR
)
78
mask2 |=
ATH9K_INT_TSFOOR
;
79
}
80
81
isr =
REG_READ
(ah,
AR_ISR_RAC
);
82
if
(isr == 0xffffffff) {
83
*masked = 0;
84
return
false
;
85
}
86
87
*masked = isr &
ATH9K_INT_COMMON
;
88
89
if
(isr & (
AR_ISR_RXMINTR
|
AR_ISR_RXINTM
|
90
AR_ISR_RXOK
|
AR_ISR_RXERR
))
91
*masked |=
ATH9K_INT_RX
;
92
93
if
(isr &
94
(
AR_ISR_TXOK
|
AR_ISR_TXDESC
|
AR_ISR_TXERR
|
95
AR_ISR_TXEOL
)) {
96
u32
s0_s, s1_s;
97
98
*masked |=
ATH9K_INT_TX
;
99
100
s0_s =
REG_READ
(ah,
AR_ISR_S0_S
);
101
ah->
intr_txqs
|=
MS
(s0_s,
AR_ISR_S0_QCU_TXOK
);
102
ah->
intr_txqs
|=
MS
(s0_s,
AR_ISR_S0_QCU_TXDESC
);
103
104
s1_s =
REG_READ
(ah,
AR_ISR_S1_S
);
105
ah->
intr_txqs
|=
MS
(s1_s,
AR_ISR_S1_QCU_TXERR
);
106
ah->
intr_txqs
|=
MS
(s1_s,
AR_ISR_S1_QCU_TXEOL
);
107
}
108
109
if
(isr &
AR_ISR_RXORN
) {
110
ath_dbg
(common,
INTERRUPT
,
111
"receive FIFO overrun interrupt\n"
);
112
}
113
114
*masked |= mask2;
115
}
116
117
if
(
AR_SREV_9100
(ah))
118
return
true
;
119
120
if
(isr &
AR_ISR_GENTMR
) {
121
u32
s5_s;
122
123
s5_s =
REG_READ
(ah,
AR_ISR_S5_S
);
124
ah->
intr_gen_timer_trigger
=
125
MS
(s5_s,
AR_ISR_S5_GENTIMER_TRIG
);
126
127
ah->
intr_gen_timer_thresh
=
128
MS
(s5_s,
AR_ISR_S5_GENTIMER_THRESH
);
129
130
if
(ah->
intr_gen_timer_trigger
)
131
*masked |=
ATH9K_INT_GENTIMER
;
132
133
if
((s5_s &
AR_ISR_S5_TIM_TIMER
) &&
134
!(pCap->
hw_caps
&
ATH9K_HW_CAP_AUTOSLEEP
))
135
*masked |=
ATH9K_INT_TIM_TIMER
;
136
}
137
138
if
(sync_cause) {
139
ath9k_debug_sync_cause(common, sync_cause);
140
fatal_int =
141
(sync_cause &
142
(
AR_INTR_SYNC_HOST1_FATAL
|
AR_INTR_SYNC_HOST1_PERR
))
143
?
true
:
false
;
144
145
if
(fatal_int) {
146
if
(sync_cause &
AR_INTR_SYNC_HOST1_FATAL
) {
147
ath_dbg
(common,
ANY
,
148
"received PCI FATAL interrupt\n"
);
149
}
150
if
(sync_cause &
AR_INTR_SYNC_HOST1_PERR
) {
151
ath_dbg
(common,
ANY
,
152
"received PCI PERR interrupt\n"
);
153
}
154
*masked |=
ATH9K_INT_FATAL
;
155
}
156
if
(sync_cause &
AR_INTR_SYNC_RADM_CPL_TIMEOUT
) {
157
ath_dbg
(common,
INTERRUPT
,
158
"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"
);
159
REG_WRITE
(ah,
AR_RC
,
AR_RC_HOSTIF
);
160
REG_WRITE
(ah,
AR_RC
, 0);
161
*masked |=
ATH9K_INT_FATAL
;
162
}
163
if
(sync_cause &
AR_INTR_SYNC_LOCAL_TIMEOUT
) {
164
ath_dbg
(common,
INTERRUPT
,
165
"AR_INTR_SYNC_LOCAL_TIMEOUT\n"
);
166
}
167
168
REG_WRITE
(ah,
AR_INTR_SYNC_CAUSE_CLR
, sync_cause);
169
(
void
)
REG_READ
(ah,
AR_INTR_SYNC_CAUSE_CLR
);
170
}
171
172
return
true
;
173
}
174
175
static
void
176
ar9002_set_txdesc(
struct
ath_hw
*ah,
void
*
ds
,
struct
ath_tx_info
*
i
)
177
{
178
struct
ar5416_desc
*ads =
AR5416DESC
(ds);
179
u32
ctl1,
ctl6
;
180
181
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
182
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
183
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
184
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
185
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
186
187
ACCESS_ONCE
(ads->
ds_link
) = i->
link
;
188
ACCESS_ONCE
(ads->
ds_data
) = i->
buf_addr
[0];
189
190
ctl1 = i->
buf_len
[0] | (i->
is_last
? 0 :
AR_TxMore
);
191
ctl6 =
SM
(i->
keytype
,
AR_EncrType
);
192
193
if
(
AR_SREV_9285
(ah)) {
194
ads->ds_ctl8 = 0;
195
ads->ds_ctl9 = 0;
196
ads->ds_ctl10 = 0;
197
ads->ds_ctl11 = 0;
198
}
199
200
if
((i->
is_first
|| i->
is_last
) &&
201
i->
aggr
!=
AGGR_BUF_MIDDLE
&& i->
aggr
!=
AGGR_BUF_LAST
) {
202
ACCESS_ONCE
(ads->ds_ctl2) =
set11nTries
(i->
rates
, 0)
203
|
set11nTries
(i->
rates
, 1)
204
|
set11nTries
(i->
rates
, 2)
205
|
set11nTries
(i->
rates
, 3)
206
| (i->
dur_update
?
AR_DurUpdateEna
: 0)
207
|
SM
(0,
AR_BurstDur
);
208
209
ACCESS_ONCE
(ads->ds_ctl3) =
set11nRate
(i->
rates
, 0)
210
|
set11nRate
(i->
rates
, 1)
211
|
set11nRate
(i->
rates
, 2)
212
|
set11nRate
(i->
rates
, 3);
213
}
else
{
214
ACCESS_ONCE
(ads->ds_ctl2) = 0;
215
ACCESS_ONCE
(ads->ds_ctl3) = 0;
216
}
217
218
if
(!i->
is_first
) {
219
ACCESS_ONCE
(ads->
ds_ctl0
) = 0;
220
ACCESS_ONCE
(ads->
ds_ctl1
) = ctl1;
221
ACCESS_ONCE
(ads->ds_ctl6) =
ctl6
;
222
return
;
223
}
224
225
ctl1 |= (i->
keyix
!=
ATH9K_TXKEYIX_INVALID
?
SM
(i->
keyix
,
AR_DestIdx
) : 0)
226
| SM(i->
type
,
AR_FrameType
)
227
| (i->
flags
&
ATH9K_TXDESC_NOACK
?
AR_NoAck
: 0)
228
| (i->
flags
&
ATH9K_TXDESC_EXT_ONLY
?
AR_ExtOnly
: 0)
229
| (i->
flags
&
ATH9K_TXDESC_EXT_AND_CTL
?
AR_ExtAndCtl
: 0);
230
231
switch
(i->
aggr
) {
232
case
AGGR_BUF_FIRST
:
233
ctl6 |=
SM
(i->
aggr_len
,
AR_AggrLen
);
234
/* fall through */
235
case
AGGR_BUF_MIDDLE
:
236
ctl1 |=
AR_IsAggr
|
AR_MoreAggr
;
237
ctl6 |=
SM
(i->
ndelim
,
AR_PadDelim
);
238
break
;
239
case
AGGR_BUF_LAST
:
240
ctl1 |=
AR_IsAggr
;
241
break
;
242
case
AGGR_BUF_NONE
:
243
break
;
244
}
245
246
ACCESS_ONCE
(ads->
ds_ctl0
) = (i->
pkt_len
&
AR_FrameLen
)
247
| (i->
flags
&
ATH9K_TXDESC_VMF
?
AR_VirtMoreFrag
: 0)
248
|
SM
(i->
txpower
,
AR_XmitPower
)
249
| (i->
flags
&
ATH9K_TXDESC_VEOL
?
AR_VEOL
: 0)
250
| (i->
flags
&
ATH9K_TXDESC_INTREQ
?
AR_TxIntrReq
: 0)
251
| (i->
keyix
!=
ATH9K_TXKEYIX_INVALID
?
AR_DestIdxValid
: 0)
252
| (i->
flags
&
ATH9K_TXDESC_CLRDMASK
?
AR_ClrDestMask
: 0)
253
| (i->
flags
&
ATH9K_TXDESC_RTSENA
?
AR_RTSEnable
:
254
(i->
flags
&
ATH9K_TXDESC_CTSENA
?
AR_CTSEnable
: 0));
255
256
ACCESS_ONCE
(ads->
ds_ctl1
) = ctl1;
257
ACCESS_ONCE
(ads->ds_ctl6) =
ctl6
;
258
259
if
(i->
aggr
==
AGGR_BUF_MIDDLE
|| i->
aggr
==
AGGR_BUF_LAST
)
260
return
;
261
262
ACCESS_ONCE
(ads->ds_ctl4) =
set11nPktDurRTSCTS
(i->
rates
, 0)
263
|
set11nPktDurRTSCTS
(i->
rates
, 1);
264
265
ACCESS_ONCE
(ads->ds_ctl5) =
set11nPktDurRTSCTS
(i->
rates
, 2)
266
|
set11nPktDurRTSCTS
(i->
rates
, 3);
267
268
ACCESS_ONCE
(ads->ds_ctl7) =
set11nRateFlags
(i->
rates
, 0)
269
|
set11nRateFlags
(i->
rates
, 1)
270
|
set11nRateFlags
(i->
rates
, 2)
271
|
set11nRateFlags
(i->
rates
, 3)
272
|
SM
(i->
rtscts_rate
,
AR_RTSCTSRate
);
273
}
274
275
static
int
ar9002_hw_proc_txdesc(
struct
ath_hw
*ah,
void
*ds,
276
struct
ath_tx_status
*
ts
)
277
{
278
struct
ar5416_desc
*ads =
AR5416DESC
(ds);
279
u32
status
;
280
281
status =
ACCESS_ONCE
(ads->ds_txstatus9);
282
if
((status &
AR_TxDone
) == 0)
283
return
-
EINPROGRESS
;
284
285
ts->
ts_tstamp
= ads->AR_SendTimestamp;
286
ts->
ts_status
= 0;
287
ts->
ts_flags
= 0;
288
289
if
(status &
AR_TxOpExceeded
)
290
ts->
ts_status
|=
ATH9K_TXERR_XTXOP
;
291
ts->
tid
=
MS
(status,
AR_TxTid
);
292
ts->
ts_rateindex
=
MS
(status,
AR_FinalTxIdx
);
293
ts->
ts_seqnum
=
MS
(status,
AR_SeqNum
);
294
295
status =
ACCESS_ONCE
(ads->ds_txstatus0);
296
ts->
ts_rssi_ctl0
=
MS
(status,
AR_TxRSSIAnt00
);
297
ts->
ts_rssi_ctl1
=
MS
(status,
AR_TxRSSIAnt01
);
298
ts->
ts_rssi_ctl2
=
MS
(status,
AR_TxRSSIAnt02
);
299
if
(status &
AR_TxBaStatus
) {
300
ts->
ts_flags
|=
ATH9K_TX_BA
;
301
ts->
ba_low
= ads->AR_BaBitmapLow;
302
ts->
ba_high
= ads->AR_BaBitmapHigh;
303
}
304
305
status =
ACCESS_ONCE
(ads->ds_txstatus1);
306
if
(status &
AR_FrmXmitOK
)
307
ts->
ts_status
|=
ATH9K_TX_ACKED
;
308
else
{
309
if
(status &
AR_ExcessiveRetries
)
310
ts->
ts_status
|=
ATH9K_TXERR_XRETRY
;
311
if
(status &
AR_Filtered
)
312
ts->
ts_status
|=
ATH9K_TXERR_FILT
;
313
if
(status &
AR_FIFOUnderrun
) {
314
ts->
ts_status
|=
ATH9K_TXERR_FIFO
;
315
ath9k_hw_updatetxtriglevel
(ah,
true
);
316
}
317
}
318
if
(status &
AR_TxTimerExpired
)
319
ts->
ts_status
|=
ATH9K_TXERR_TIMER_EXPIRED
;
320
if
(status &
AR_DescCfgErr
)
321
ts->
ts_flags
|=
ATH9K_TX_DESC_CFG_ERR
;
322
if
(status &
AR_TxDataUnderrun
) {
323
ts->
ts_flags
|=
ATH9K_TX_DATA_UNDERRUN
;
324
ath9k_hw_updatetxtriglevel
(ah,
true
);
325
}
326
if
(status &
AR_TxDelimUnderrun
) {
327
ts->
ts_flags
|=
ATH9K_TX_DELIM_UNDERRUN
;
328
ath9k_hw_updatetxtriglevel
(ah,
true
);
329
}
330
ts->
ts_shortretry
=
MS
(status,
AR_RTSFailCnt
);
331
ts->
ts_longretry
=
MS
(status,
AR_DataFailCnt
);
332
ts->
ts_virtcol
=
MS
(status,
AR_VirtRetryCnt
);
333
334
status =
ACCESS_ONCE
(ads->ds_txstatus5);
335
ts->
ts_rssi
=
MS
(status,
AR_TxRSSICombined
);
336
ts->
ts_rssi_ext0
=
MS
(status,
AR_TxRSSIAnt10
);
337
ts->
ts_rssi_ext1
=
MS
(status,
AR_TxRSSIAnt11
);
338
ts->
ts_rssi_ext2
=
MS
(status,
AR_TxRSSIAnt12
);
339
340
ts->
evm0
= ads->AR_TxEVM0;
341
ts->
evm1
= ads->AR_TxEVM1;
342
ts->
evm2
= ads->AR_TxEVM2;
343
344
return
0;
345
}
346
347
void
ath9k_hw_setuprxdesc
(
struct
ath_hw
*ah,
struct
ath_desc
*ds,
348
u32
size
,
u32
flags
)
349
{
350
struct
ar5416_desc
*ads =
AR5416DESC
(ds);
351
352
ads->
ds_ctl1
= size &
AR_BufLen
;
353
if
(flags &
ATH9K_RXDESC_INTREQ
)
354
ads->
ds_ctl1
|=
AR_RxIntrReq
;
355
356
memset
(&ads->
u
.
rx
, 0,
sizeof
(ads->
u
.
rx
));
357
}
358
EXPORT_SYMBOL
(
ath9k_hw_setuprxdesc
);
359
360
void
ar9002_hw_attach_mac_ops
(
struct
ath_hw
*ah)
361
{
362
struct
ath_hw_ops
*
ops
= ath9k_hw_ops(ah);
363
364
ops->
rx_enable
= ar9002_hw_rx_enable;
365
ops->
set_desc_link
= ar9002_hw_set_desc_link;
366
ops->
get_isr
= ar9002_hw_get_isr;
367
ops->
set_txdesc
= ar9002_set_txdesc;
368
ops->
proc_txdesc
= ar9002_hw_proc_txdesc;
369
}
Generated on Thu Jan 10 2013 14:08:54 for Linux Kernel by
1.8.2