Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
640f5950
Commit
640f5950
authored
Dec 19, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-linville' of
git://github.com/kvalo/ath6kl
parents
7c4559c9
7e95e365
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1809 additions
and
653 deletions
+1809
-653
drivers/net/wireless/ath/ath6kl/Kconfig
drivers/net/wireless/ath/ath6kl/Kconfig
+21
-4
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/Makefile
+25
-12
drivers/net/wireless/ath/ath6kl/bmi.c
drivers/net/wireless/ath/ath6kl/bmi.c
+50
-195
drivers/net/wireless/ath/ath6kl/bmi.h
drivers/net/wireless/ath/ath6kl/bmi.h
+0
-6
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
+298
-84
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/cfg80211.h
+4
-2
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/common.h
+1
-0
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/core.h
+80
-29
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/debug.c
+2
-2
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/debug.h
+1
-0
drivers/net/wireless/ath/ath6kl/hif-ops.h
drivers/net/wireless/ath/ath6kl/hif-ops.h
+30
-0
drivers/net/wireless/ath/ath6kl/hif.c
drivers/net/wireless/ath/ath6kl/hif.c
+5
-0
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/hif.h
+5
-0
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/htc.c
+9
-1
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/init.c
+225
-155
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/main.c
+20
-105
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/sdio.c
+317
-12
drivers/net/wireless/ath/ath6kl/target.h
drivers/net/wireless/ath/ath6kl/target.h
+1
-15
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/txrx.c
+8
-12
drivers/net/wireless/ath/ath6kl/usb.c
drivers/net/wireless/ath/ath6kl/usb.c
+431
-0
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.c
+146
-6
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath6kl/wmi.h
+130
-13
No files found.
drivers/net/wireless/ath/ath6kl/Kconfig
View file @
640f5950
config ATH6KL
tristate "Atheros ath6kl support"
tristate "Atheros mobile chipsets support"
config ATH6KL_SDIO
tristate "Atheros ath6kl SDIO support"
depends on ATH6KL
depends on MMC
depends on CFG80211
---help---
This module adds support for wireless adapters based on
Atheros AR6003 chipset running over SDIO. If you choose to
build it as a module, it will be called ath6kl. Pls note
that AR6002 and AR6001 are not supported by this driver.
Atheros AR6003 and AR6004 chipsets running over SDIO. If you
choose to build it as a module, it will be called ath6kl_sdio.
Please note that AR6002 and AR6001 are not supported by this
driver.
config ATH6KL_USB
tristate "Atheros ath6kl USB support"
depends on ATH6KL
depends on USB
depends on CFG80211
depends on EXPERIMENTAL
---help---
This module adds support for wireless adapters based on
Atheros AR6004 chipset running over USB. This is still under
implementation and it isn't functional. If you choose to
build it as a module, it will be called ath6kl_usb.
config ATH6KL_DEBUG
bool "Atheros ath6kl debugging"
...
...
drivers/net/wireless/ath/ath6kl/Makefile
View file @
640f5950
...
...
@@ -21,17 +21,30 @@
# Author(s): ="Atheros"
#------------------------------------------------------------------------------
obj-$(CONFIG_ATH6KL)
:=
ath6kl.o
ath6kl-y
+=
debug.o
ath6kl-y
+=
hif.o
ath6kl-y
+=
htc.o
ath6kl-y
+=
bmi.o
ath6kl-y
+=
cfg80211.o
ath6kl-y
+=
init.o
ath6kl-y
+=
main.o
ath6kl-y
+=
txrx.o
ath6kl-y
+=
wmi.o
ath6kl-y
+=
sdio.o
ath6kl-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
obj-$(CONFIG_ATH6KL_SDIO)
:=
ath6kl_sdio.o
ath6kl_sdio-y
+=
debug.o
ath6kl_sdio-y
+=
hif.o
ath6kl_sdio-y
+=
htc.o
ath6kl_sdio-y
+=
bmi.o
ath6kl_sdio-y
+=
cfg80211.o
ath6kl_sdio-y
+=
init.o
ath6kl_sdio-y
+=
main.o
ath6kl_sdio-y
+=
txrx.o
ath6kl_sdio-y
+=
wmi.o
ath6kl_sdio-y
+=
sdio.o
ath6kl_sdio-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
obj-$(CONFIG_ATH6KL_USB)
+=
ath6kl_usb.o
ath6kl_usb-y
+=
debug.o
ath6kl_usb-y
+=
hif.o
ath6kl_usb-y
+=
htc.o
ath6kl_usb-y
+=
bmi.o
ath6kl_usb-y
+=
cfg80211.o
ath6kl_usb-y
+=
init.o
ath6kl_usb-y
+=
main.o
ath6kl_usb-y
+=
txrx.o
ath6kl_usb-y
+=
wmi.o
ath6kl_usb-y
+=
usb.o
ath6kl_usb-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
ccflags-y
+=
-D__CHECK_ENDIAN__
drivers/net/wireless/ath/ath6kl/bmi.c
View file @
640f5950
...
...
@@ -19,165 +19,6 @@
#include "target.h"
#include "debug.h"
static
int
ath6kl_get_bmi_cmd_credits
(
struct
ath6kl
*
ar
)
{
u32
addr
;
unsigned
long
timeout
;
int
ret
;
ar
->
bmi
.
cmd_credits
=
0
;
/* Read the counter register to get the command credits */
addr
=
COUNT_DEC_ADDRESS
+
(
HTC_MAILBOX_NUM_MAX
+
ENDPOINT1
)
*
4
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
(
time_before
(
jiffies
,
timeout
)
&&
!
ar
->
bmi
.
cmd_credits
)
{
/*
* Hit the credit counter with a 4-byte access, the first byte
* read will hit the counter and cause a decrement, while the
* remaining 3 bytes has no effect. The rationale behind this
* is to make all HIF accesses 4-byte aligned.
*/
ret
=
hif_read_write_sync
(
ar
,
addr
,
(
u8
*
)
&
ar
->
bmi
.
cmd_credits
,
4
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to decrement the command credit count register: %d
\n
"
,
ret
);
return
ret
;
}
/* The counter is only 8 bits.
* Ignore anything in the upper 3 bytes
*/
ar
->
bmi
.
cmd_credits
&=
0xFF
;
}
if
(
!
ar
->
bmi
.
cmd_credits
)
{
ath6kl_err
(
"bmi communication timeout
\n
"
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
int
ath6kl_bmi_get_rx_lkahd
(
struct
ath6kl
*
ar
)
{
unsigned
long
timeout
;
u32
rx_word
=
0
;
int
ret
=
0
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
(
time_before
(
jiffies
,
timeout
)
&&
!
rx_word
)
{
ret
=
hif_read_write_sync
(
ar
,
RX_LOOKAHEAD_VALID_ADDRESS
,
(
u8
*
)
&
rx_word
,
sizeof
(
rx_word
),
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"unable to read RX_LOOKAHEAD_VALID
\n
"
);
return
ret
;
}
/* all we really want is one bit */
rx_word
&=
(
1
<<
ENDPOINT1
);
}
if
(
!
rx_word
)
{
ath6kl_err
(
"bmi_recv_buf FIFO empty
\n
"
);
return
-
EINVAL
;
}
return
ret
;
}
static
int
ath6kl_bmi_send_buf
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
int
ret
;
u32
addr
;
ret
=
ath6kl_get_bmi_cmd_credits
(
ar
);
if
(
ret
)
return
ret
;
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
hif_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_WR_SYNC_BYTE_INC
);
if
(
ret
)
ath6kl_err
(
"unable to send the bmi data to the device
\n
"
);
return
ret
;
}
static
int
ath6kl_bmi_recv_buf
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
int
ret
;
u32
addr
;
/*
* During normal bootup, small reads may be required.
* Rather than issue an HIF Read and then wait as the Target
* adds successive bytes to the FIFO, we wait here until
* we know that response data is available.
*
* This allows us to cleanly timeout on an unexpected
* Target failure rather than risk problems at the HIF level.
* In particular, this avoids SDIO timeouts and possibly garbage
* data on some host controllers. And on an interconnect
* such as Compact Flash (as well as some SDIO masters) which
* does not provide any indication on data timeout, it avoids
* a potential hang or garbage response.
*
* Synchronization is more difficult for reads larger than the
* size of the MBOX FIFO (128B), because the Target is unable
* to push the 129th byte of data until AFTER the Host posts an
* HIF Read and removes some FIFO data. So for large reads the
* Host proceeds to post an HIF Read BEFORE all the data is
* actually available to read. Fortunately, large BMI reads do
* not occur in practice -- they're supported for debug/development.
*
* So Host/Target BMI synchronization is divided into these cases:
* CASE 1: length < 4
* Should not happen
*
* CASE 2: 4 <= length <= 128
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
* response is available in the the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO
*
* For most uses, a small timeout should be sufficient and we will
* usually see a response quickly; but there may be some unusual
* (debug) cases of BMI_EXECUTE where we want an larger timeout.
* For now, we use an unbounded busy loop while waiting for
* BMI_EXECUTE.
*
* If BMI_EXECUTE ever needs to support longer-latency execution,
* especially in production, this code needs to be enhanced to sleep
* and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
* a function of Host processor speed.
*/
if
(
len
>=
4
)
{
/* NB: Currently, always true */
ret
=
ath6kl_bmi_get_rx_lkahd
(
ar
);
if
(
ret
)
return
ret
;
}
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
hif_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read the bmi data from the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
int
ath6kl_bmi_done
(
struct
ath6kl
*
ar
)
{
int
ret
;
...
...
@@ -190,7 +31,7 @@ int ath6kl_bmi_done(struct ath6kl *ar)
ar
->
bmi
.
done_sent
=
true
;
ret
=
ath6kl_
bmi_send_buf
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
ret
=
ath6kl_
hif_bmi_write
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
if
(
ret
)
{
ath6kl_err
(
"Unable to send bmi done: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -210,14 +51,20 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
return
-
EACCES
;
}
ret
=
ath6kl_
bmi_send_buf
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
ret
=
ath6kl_
hif_bmi_write
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
if
(
ret
)
{
ath6kl_err
(
"Unable to send get target info: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
version
,
sizeof
(
targ_info
->
version
));
if
(
ar
->
hif_type
==
ATH6KL_HIF_TYPE_USB
)
{
ret
=
ath6kl_hif_bmi_read
(
ar
,
(
u8
*
)
targ_info
,
sizeof
(
*
targ_info
));
}
else
{
ret
=
ath6kl_hif_bmi_read
(
ar
,
(
u8
*
)
&
targ_info
->
version
,
sizeof
(
targ_info
->
version
));
}
if
(
ret
)
{
ath6kl_err
(
"Unable to recv target info: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -225,7 +72,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
if
(
le32_to_cpu
(
targ_info
->
version
)
==
TARGET_VERSION_SENTINAL
)
{
/* Determine how many bytes are in the Target's targ_info */
ret
=
ath6kl_
bmi_recv_buf
(
ar
,
ret
=
ath6kl_
hif_bmi_read
(
ar
,
(
u8
*
)
&
targ_info
->
byte_count
,
sizeof
(
targ_info
->
byte_count
));
if
(
ret
)
{
...
...
@@ -244,7 +91,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
}
/* Read the remainder of the targ_info */
ret
=
ath6kl_
bmi_recv_buf
(
ar
,
ret
=
ath6kl_
hif_bmi_read
(
ar
,
((
u8
*
)
targ_info
)
+
sizeof
(
targ_info
->
byte_count
),
sizeof
(
*
targ_info
)
-
...
...
@@ -276,8 +123,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
return
-
EACCES
;
}
size
=
BMI_DATASZ_MAX
+
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
len
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
size
=
ar
->
bmi
.
max_data_size
+
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
len
);
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -290,8 +137,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
len_remain
=
len
;
while
(
len_remain
)
{
rx_len
=
(
len_remain
<
BMI_DATASZ_MAX
)
?
len_remain
:
BMI_DATASZ_MAX
;
rx_len
=
(
len_remain
<
ar
->
bmi
.
max_data_size
)
?
len_remain
:
ar
->
bmi
.
max_data_size
;
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
...
...
@@ -300,13 +147,13 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
rx_len
,
sizeof
(
rx_len
));
offset
+=
sizeof
(
len
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_
bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
rx_len
);
ret
=
ath6kl_
hif_bmi_read
(
ar
,
ar
->
bmi
.
cmd_buf
,
rx_len
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
...
...
@@ -326,7 +173,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
u32
offset
;
u32
len_remain
,
tx_len
;
const
u32
header
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
len
);
u8
aligned_buf
[
BMI_DATASZ_MAX
];
u8
aligned_buf
[
400
];
u8
*
src
;
if
(
ar
->
bmi
.
done_sent
)
{
...
...
@@ -334,12 +181,15 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
return
-
EACCES
;
}
if
((
BMI_DATASZ_MAX
+
header
)
>
MAX_BMI_CMDBUF_SZ
)
{
if
((
ar
->
bmi
.
max_data_size
+
header
)
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
BMI_DATASZ_MAX
+
header
);
if
(
WARN_ON
(
ar
->
bmi
.
max_data_size
>
sizeof
(
aligned_buf
)))
return
-
E2BIG
;
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
ar
->
bmi
.
max_data_size
+
header
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi write memory: addr: 0x%x, len: %d
\n
"
,
addr
,
len
);
...
...
@@ -348,7 +198,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
while
(
len_remain
)
{
src
=
&
buf
[
len
-
len_remain
];
if
(
len_remain
<
(
BMI_DATASZ_MAX
-
header
))
{
if
(
len_remain
<
(
ar
->
bmi
.
max_data_size
-
header
))
{
if
(
len_remain
&
3
)
{
/* align it with 4 bytes */
len_remain
=
len_remain
+
...
...
@@ -358,7 +208,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
}
tx_len
=
len_remain
;
}
else
{
tx_len
=
(
BMI_DATASZ_MAX
-
header
);
tx_len
=
(
ar
->
bmi
.
max_data_size
-
header
);
}
offset
=
0
;
...
...
@@ -371,7 +221,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
src
,
tx_len
);
offset
+=
tx_len
;
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
...
...
@@ -396,7 +246,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
param
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -413,13 +263,13 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
param
,
sizeof
(
*
param
));
offset
+=
sizeof
(
*
param
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_
bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
ret
=
ath6kl_
hif_bmi_read
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -443,7 +293,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -457,7 +307,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -479,7 +329,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -493,13 +343,13 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_
bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
ret
=
ath6kl_
hif_bmi_read
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -522,7 +372,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
param
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -540,7 +390,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
param
,
sizeof
(
param
));
offset
+=
sizeof
(
param
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -563,8 +413,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
return
-
EACCES
;
}
size
=
BMI_DATASZ_MAX
+
header
;
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
size
=
ar
->
bmi
.
max_data_size
+
header
;
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -575,8 +425,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
len_remain
=
len
;
while
(
len_remain
)
{
tx_len
=
(
len_remain
<
(
BMI_DATASZ_MAX
-
header
))
?
len_remain
:
(
BMI_DATASZ_MAX
-
header
);
tx_len
=
(
len_remain
<
(
ar
->
bmi
.
max_data_size
-
header
))
?
len_remain
:
(
ar
->
bmi
.
max_data_size
-
header
);
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
...
...
@@ -587,7 +437,7 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
tx_len
);
offset
+=
tx_len
;
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
...
...
@@ -613,7 +463,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
if
(
size
>
ar
->
bmi
.
max_cmd_size
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
...
...
@@ -629,7 +479,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
ret
=
ath6kl_
bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
ret
=
ath6kl_
hif_bmi_write
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to start LZ stream to the device: %d
\n
"
,
ret
);
...
...
@@ -677,8 +527,13 @@ void ath6kl_bmi_reset(struct ath6kl *ar)
int
ath6kl_bmi_init
(
struct
ath6kl
*
ar
)
{
ar
->
bmi
.
cmd_buf
=
kzalloc
(
MAX_BMI_CMDBUF_SZ
,
GFP_ATOMIC
);
if
(
WARN_ON
(
ar
->
bmi
.
max_data_size
==
0
))
return
-
EINVAL
;
/* cmd + addr + len + data_size */
ar
->
bmi
.
max_cmd_size
=
ar
->
bmi
.
max_data_size
+
(
sizeof
(
u32
)
*
3
);
ar
->
bmi
.
cmd_buf
=
kzalloc
(
ar
->
bmi
.
max_cmd_size
,
GFP_ATOMIC
);
if
(
!
ar
->
bmi
.
cmd_buf
)
return
-
ENOMEM
;
...
...
drivers/net/wireless/ath/ath6kl/bmi.h
View file @
640f5950
...
...
@@ -44,12 +44,6 @@
* BMI handles all required Target-side cache flushing.
*/
#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
(sizeof(u32) * 3
/* cmd + addr + len */
))
/* Maximum data size used for BMI transfers */
#define BMI_DATASZ_MAX 256
/* BMI Commands */
#define BMI_NO_COMMAND 0
...
...
drivers/net/wireless/ath/ath6kl/cfg80211.c
View file @
640f5950
...
...
@@ -23,10 +23,8 @@
#include "testmode.h"
static
unsigned
int
ath6kl_p2p
;
static
unsigned
int
multi_norm_if_support
;
module_param
(
ath6kl_p2p
,
uint
,
0644
);
module_param
(
multi_norm_if_support
,
uint
,
0644
);
#define RATETAB_ENT(_rate, _rateid, _flags) { \
.bitrate = (_rate), \
...
...
@@ -127,6 +125,37 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
#define CCKM_KRK_CIPHER_SUITE 0x004096ff
/* use for KRK */
/* returns true if scheduled scan was stopped */
static
bool
__ath6kl_cfg80211_sscan_stop
(
struct
ath6kl_vif
*
vif
)
{
struct
ath6kl
*
ar
=
vif
->
ar
;
if
(
ar
->
state
!=
ATH6KL_STATE_SCHED_SCAN
)
return
false
;
del_timer_sync
(
&
vif
->
sched_scan_timer
);
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_AWAKE
);
ar
->
state
=
ATH6KL_STATE_ON
;
return
true
;
}
static
void
ath6kl_cfg80211_sscan_disable
(
struct
ath6kl_vif
*
vif
)
{
struct
ath6kl
*
ar
=
vif
->
ar
;
bool
stopped
;
stopped
=
__ath6kl_cfg80211_sscan_stop
(
vif
);
if
(
!
stopped
)
return
;
cfg80211_sched_scan_stopped
(
ar
->
wiphy
);
}
static
int
ath6kl_set_wpa_version
(
struct
ath6kl_vif
*
vif
,
enum
nl80211_wpa_versions
wpa_version
)
{
...
...
@@ -205,6 +234,10 @@ static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
*
ar_cipher
=
AES_CRYPT
;
*
ar_cipher_len
=
0
;
break
;
case
WLAN_CIPHER_SUITE_SMS4
:
*
ar_cipher
=
WAPI_CRYPT
;
*
ar_cipher_len
=
0
;
break
;
default:
ath6kl_err
(
"cipher 0x%x not supported
\n
"
,
cipher
);
return
-
ENOTSUPP
;
...
...
@@ -355,7 +388,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
if
(
type
==
NL80211_IFTYPE_STATION
||
type
==
NL80211_IFTYPE_AP
||
type
==
NL80211_IFTYPE_ADHOC
)
{
for
(
i
=
0
;
i
<
MAX_NUM_VIF
;
i
++
)
{
for
(
i
=
0
;
i
<
ar
->
vif_max
;
i
++
)
{
if
((
ar
->
avail_idx_map
>>
i
)
&
BIT
(
0
))
{
*
if_idx
=
i
;
return
true
;
...
...
@@ -365,7 +398,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
if
(
type
==
NL80211_IFTYPE_P2P_CLIENT
||
type
==
NL80211_IFTYPE_P2P_GO
)
{
for
(
i
=
ar
->
max_norm_iface
;
i
<
MAX_NUM_VIF
;
i
++
)
{
for
(
i
=
ar
->
max_norm_iface
;
i
<
ar
->
vif_max
;
i
++
)
{
if
((
ar
->
avail_idx_map
>>
i
)
&
BIT
(
0
))
{
*
if_idx
=
i
;
return
true
;
...
...
@@ -382,6 +415,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
int
status
;
u8
nw_subtype
=
(
ar
->
p2p
)
?
SUBTYPE_P2PDEV
:
SUBTYPE_NONE
;
ath6kl_cfg80211_sscan_disable
(
vif
);
vif
->
sme_state
=
SME_CONNECTING
;
...
...
@@ -427,9 +463,12 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
if
(
sme
->
ie
&&
(
sme
->
ie_len
>
0
))
{
status
=
ath6kl_set_assoc_req_ies
(
vif
,
sme
->
ie
,
sme
->
ie_len
);
if
(
status
)
if
(
status
)
{
up
(
&
ar
->
sem
);
return
status
;
}
}
}
else
ar
->
connect_ctrl_flags
&=
~
CONNECT_WPS_FLAG
;
if
(
test_bit
(
CONNECTED
,
&
vif
->
flags
)
&&
vif
->
ssid_len
==
sme
->
ssid_len
&&
...
...
@@ -519,6 +558,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif
->
nw_type
=
vif
->
next_mode
;
if
(
vif
->
wdev
.
iftype
==
NL80211_IFTYPE_P2P_CLIENT
)
nw_subtype
=
SUBTYPE_P2PCLIENT
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: connect called with authmode %d dot11 auth %d"
" PW crypto %d PW crypto len %d GRP crypto %d"
...
...
@@ -536,7 +578,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif
->
grp_crypto
,
vif
->
grp_crypto_len
,
vif
->
ssid_len
,
vif
->
ssid
,
vif
->
req_bssid
,
vif
->
ch_hint
,
ar
->
connect_ctrl_flags
);
ar
->
connect_ctrl_flags
,
nw_subtype
);
up
(
&
ar
->
sem
);
...
...
@@ -563,17 +605,28 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return
0
;
}
static
int
ath6kl_add_bss_if_needed
(
struct
ath6kl_vif
*
vif
,
const
u8
*
bssid
,
static
int
ath6kl_add_bss_if_needed
(
struct
ath6kl_vif
*
vif
,
enum
network_type
nw_type
,
const
u8
*
bssid
,
struct
ieee80211_channel
*
chan
,
const
u8
*
beacon_ie
,
size_t
beacon_ie_len
)
{
struct
ath6kl
*
ar
=
vif
->
ar
;
struct
cfg80211_bss
*
bss
;
u16
cap_mask
,
cap_val
;
u8
*
ie
;
if
(
nw_type
&
ADHOC_NETWORK
)
{
cap_mask
=
WLAN_CAPABILITY_IBSS
;
cap_val
=
WLAN_CAPABILITY_IBSS
;
}
else
{
cap_mask
=
WLAN_CAPABILITY_ESS
;
cap_val
=
WLAN_CAPABILITY_ESS
;
}
bss
=
cfg80211_get_bss
(
ar
->
wiphy
,
chan
,
bssid
,
vif
->
ssid
,
vif
->
ssid_len
,
WLAN_CAPABILITY_ESS
,
WLAN_CAPABILITY_ESS
);
vif
->
ssid
,
vif
->
ssid_len
,
cap_mask
,
cap_val
);
if
(
bss
==
NULL
)
{
/*
* Since cfg80211 may not yet know about the BSS,
...
...
@@ -591,13 +644,12 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid,
memcpy
(
ie
+
2
,
vif
->
ssid
,
vif
->
ssid_len
);
memcpy
(
ie
+
2
+
vif
->
ssid_len
,
beacon_ie
,
beacon_ie_len
);
bss
=
cfg80211_inform_bss
(
ar
->
wiphy
,
chan
,
bssid
,
0
,
WLAN_CAPABILITY_ESS
,
100
,
bssid
,
0
,
cap_val
,
100
,
ie
,
2
+
vif
->
ssid_len
+
beacon_ie_len
,
0
,
GFP_KERNEL
);
if
(
bss
)
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"added dummy bss for "
"%pM prior to indicating connect/roamed "
"event
\n
"
,
bssid
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"added bss %pM to "
"cfg80211
\n
"
,
bssid
);
kfree
(
ie
);
}
else
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"cfg80211 already has a bss "
...
...
@@ -660,16 +712,16 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
chan
=
ieee80211_get_channel
(
ar
->
wiphy
,
(
int
)
channel
);
if
(
nw_type
&
ADHOC_NETWORK
)
{
cfg80211_ibss_joined
(
vif
->
ndev
,
bssid
,
GFP_KERNEL
);
if
(
ath6kl_add_bss_if_needed
(
vif
,
nw_type
,
bssid
,
chan
,
assoc_info
,
beacon_ie_len
)
<
0
)
{
ath6kl_err
(
"could not add cfg80211 bss entry
\n
"
);
return
;
}
if
(
ath6kl_add_bss_if_needed
(
vif
,
bssid
,
chan
,
assoc_info
,
beacon_ie_len
)
<
0
)
{
ath6kl_err
(
"could not add cfg80211 bss entry for "
"connect/roamed notification
\n
"
);
if
(
nw_type
&
ADHOC_NETWORK
)
{
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"ad-hoc %s selected
\n
"
,
nw_type
&
ADHOC_CREATOR
?
"creator"
:
"joiner"
);
cfg80211_ibss_joined
(
vif
->
ndev
,
bssid
,
GFP_KERNEL
);
return
;
}
...
...
@@ -691,12 +743,14 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
static
int
ath6kl_cfg80211_disconnect
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u16
reason_code
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
dev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: reason=%u
\n
"
,
__func__
,
reason_code
);
ath6kl_cfg80211_sscan_disable
(
vif
);
if
(
!
ath6kl_cfg80211_ready
(
vif
))
return
-
EIO
;
...
...
@@ -789,7 +843,7 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
static
int
ath6kl_cfg80211_scan
(
struct
wiphy
*
wiphy
,
struct
net_device
*
ndev
,
struct
cfg80211_scan_request
*
request
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
ndev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
ndev
);
s8
n_channels
=
0
;
u16
*
channels
=
NULL
;
...
...
@@ -799,6 +853,8 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
if
(
!
ath6kl_cfg80211_ready
(
vif
))
return
-
EIO
;
ath6kl_cfg80211_sscan_disable
(
vif
);
if
(
!
ar
->
usr_bss_filter
)
{
clear_bit
(
CLEAR_BSSFILTER_ON_BEACON
,
&
vif
->
flags
);
ret
=
ath6kl_wmi_bssfilter_cmd
(
...
...
@@ -824,6 +880,10 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
request
->
ssids
[
i
].
ssid
);
}
/*
* FIXME: we should clear the IE in fw if it's not set so just
* remove the check altogether
*/
if
(
request
->
ie
)
{
ret
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_FRAME_PROBE_REQ
,
...
...
@@ -860,9 +920,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
if
(
test_bit
(
CONNECTED
,
&
vif
->
flags
))
force_fg_scan
=
1
;
ret
=
ath6kl_wmi_startscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
0
,
n_channels
,
channels
);
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX
,
ar
->
fw_capabilities
))
{
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
* supported rates to advertise and xmit rates for
* probe requests
*/
ret
=
ath6kl_wmi_beginscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
0
,
n_channels
,
channels
,
request
->
no_cck
,
request
->
rates
);
}
else
{
ret
=
ath6kl_wmi_startscan_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_LONG_SCAN
,
force_fg_scan
,
false
,
0
,
0
,
n_channels
,
channels
);
}
if
(
ret
)
ath6kl_err
(
"wmi_startscan_cmd failed
\n
"
);
else
...
...
@@ -905,7 +981,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
const
u8
*
mac_addr
,
struct
key_params
*
params
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
ndev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
ndev
);
struct
ath6kl_key
*
key
=
NULL
;
u8
key_usage
;
...
...
@@ -937,13 +1013,19 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
key_usage
=
GROUP_USAGE
;
if
(
params
)
{
int
seq_len
=
params
->
seq_len
;
if
(
params
->
cipher
==
WLAN_CIPHER_SUITE_SMS4
&&
seq_len
>
ATH6KL_KEY_SEQ_LEN
)
{
/* Only first half of the WPI PN is configured */
seq_len
=
ATH6KL_KEY_SEQ_LEN
;
}
if
(
params
->
key_len
>
WLAN_MAX_KEY_LEN
||
params
->
seq_len
>
sizeof
(
key
->
seq
))
seq_len
>
sizeof
(
key
->
seq
))
return
-
EINVAL
;
key
->
key_len
=
params
->
key_len
;
memcpy
(
key
->
key
,
params
->
key
,
key
->
key_len
);
key
->
seq_len
=
params
->
seq_len
;
key
->
seq_len
=
seq_len
;
memcpy
(
key
->
seq
,
params
->
seq
,
key
->
seq_len
);
key
->
cipher
=
params
->
cipher
;
}
...
...
@@ -961,6 +1043,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
case
WLAN_CIPHER_SUITE_CCMP
:
key_type
=
AES_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_SMS4
:
key_type
=
WAPI_CRYPT
;
break
;
default:
return
-
ENOTSUPP
;
...
...
@@ -976,10 +1061,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
__func__
,
key_index
,
key
->
key_len
,
key_type
,
key_usage
,
key
->
seq_len
);
vif
->
def_txkey_index
=
key_index
;
if
(
vif
->
nw_type
==
AP_NETWORK
&&
!
pairwise
&&
(
key_type
==
TKIP_CRYPT
||
key_type
==
AES_CRYPT
)
&&
params
)
{
(
key_type
==
TKIP_CRYPT
||
key_type
==
AES_CRYPT
||
key_type
==
WAPI_CRYPT
)
&&
params
)
{
ar
->
ap_mode_bkey
.
valid
=
true
;
ar
->
ap_mode_bkey
.
key_index
=
key_index
;
ar
->
ap_mode_bkey
.
key_type
=
key_type
;
...
...
@@ -1012,8 +1096,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
return
0
;
}
return
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
vif
->
def_txkey_index
,
return
ath6kl_wmi_addkey_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
key_index
,
key_type
,
key_usage
,
key
->
key_len
,
key
->
seq
,
key
->
seq_len
,
key
->
key
,
KEY_OP_INIT_VAL
,
...
...
@@ -1024,7 +1107,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
u8
key_index
,
bool
pairwise
,
const
u8
*
mac_addr
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
ndev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
ndev
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: index %d
\n
"
,
__func__
,
key_index
);
...
...
@@ -1090,7 +1173,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
u8
key_index
,
bool
unicast
,
bool
multicast
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
ath6kl_priv
(
ndev
);
struct
ath6kl
*
ar
=
ath6kl_priv
(
ndev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
ndev
);
struct
ath6kl_key
*
key
=
NULL
;
u8
key_usage
;
...
...
@@ -1181,11 +1264,12 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
*/
static
int
ath6kl_cfg80211_set_txpower
(
struct
wiphy
*
wiphy
,
enum
nl80211_tx_power_setting
type
,
int
d
bm
)
int
m
bm
)
{
struct
ath6kl
*
ar
=
(
struct
ath6kl
*
)
wiphy_priv
(
wiphy
);
struct
ath6kl_vif
*
vif
;
u8
ath6kl_dbm
;
int
dbm
=
MBM_TO_DBM
(
mbm
);
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: type 0x%x, dbm %d
\n
"
,
__func__
,
type
,
dbm
);
...
...
@@ -1288,7 +1372,7 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
struct
net_device
*
ndev
;
u8
if_idx
,
nw_type
;
if
(
ar
->
num_vif
==
MAX_NUM_VIF
)
{
if
(
ar
->
num_vif
==
ar
->
vif_max
)
{
ath6kl_err
(
"Reached maximum number of supported vif
\n
"
);
return
ERR_PTR
(
-
EINVAL
);
}
...
...
@@ -1333,9 +1417,6 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: type %u
\n
"
,
__func__
,
type
);
if
(
!
ath6kl_cfg80211_ready
(
vif
))
return
-
EIO
;
switch
(
type
)
{
case
NL80211_IFTYPE_STATION
:
vif
->
next_mode
=
INFRA_NETWORK
;
...
...
@@ -1426,7 +1507,7 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
vif
->
grp_crypto
,
vif
->
grp_crypto_len
,
vif
->
ssid_len
,
vif
->
ssid
,
vif
->
req_bssid
,
vif
->
ch_hint
,
ar
->
connect_ctrl_flags
);
ar
->
connect_ctrl_flags
,
SUBTYPE_NONE
);
set_bit
(
CONNECT_PEND
,
&
vif
->
flags
);
return
0
;
...
...
@@ -1453,6 +1534,7 @@ static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_TKIP
,
WLAN_CIPHER_SUITE_CCMP
,
CCKM_KRK_CIPHER_SUITE
,
WLAN_CIPHER_SUITE_SMS4
,
};
static
bool
is_rate_legacy
(
s32
rate
)
...
...
@@ -1779,7 +1861,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
case
ATH6KL_CFG_SUSPEND_DEEPSLEEP
:
ath6kl_cfg80211_stop
(
ar
);
ath6kl_cfg80211_stop
_all
(
ar
);
/* save the current power mode before enabling power save */
ar
->
wmi
->
saved_pwr_mode
=
ar
->
wmi
->
pwr_mode
;
...
...
@@ -1796,7 +1878,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
case
ATH6KL_CFG_SUSPEND_CUTPOWER
:
ath6kl_cfg80211_stop
(
ar
);
ath6kl_cfg80211_stop
_all
(
ar
);
if
(
ar
->
state
==
ATH6KL_STATE_OFF
)
{
ath6kl_dbg
(
ATH6KL_DBG_SUSPEND
,
...
...
@@ -1816,6 +1898,13 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
break
;
case
ATH6KL_CFG_SUSPEND_SCHED_SCAN
:
/*
* Nothing needed for schedule scan, firmware is already in
* wow mode and sleeping most of the time.
*/
break
;
default:
break
;
}
...
...
@@ -1864,6 +1953,9 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
}
break
;
case
ATH6KL_STATE_SCHED_SCAN
:
break
;
default:
break
;
}
...
...
@@ -1987,7 +2079,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
int
ies_len
;
struct
wmi_connect_cmd
p
;
int
res
;
int
i
;
int
i
,
ret
;
ath6kl_dbg
(
ATH6KL_DBG_WLAN_CFG
,
"%s: add=%d
\n
"
,
__func__
,
add
);
...
...
@@ -2045,7 +2137,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
if
(
info
->
hidden_ssid
!=
NL80211_HIDDEN_SSID_NOT_IN_USE
)
return
-
EOPNOTSUPP
;
/* TODO */
vif
->
dot11_auth_mode
=
OPEN_AUTH
;
ret
=
ath6kl_set_auth_type
(
vif
,
info
->
auth_type
);
if
(
ret
)
return
ret
;
memset
(
&
p
,
0
,
sizeof
(
p
));
...
...
@@ -2081,6 +2175,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
case
WLAN_CIPHER_SUITE_CCMP
:
p
.
prwise_crypto_type
|=
AES_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_SMS4
:
p
.
prwise_crypto_type
|=
WAPI_CRYPT
;
break
;
}
}
if
(
p
.
prwise_crypto_type
==
0
)
{
...
...
@@ -2100,6 +2197,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
case
WLAN_CIPHER_SUITE_CCMP
:
p
.
grp_crypto_type
=
AES_CRYPT
;
break
;
case
WLAN_CIPHER_SUITE_SMS4
:
p
.
grp_crypto_type
=
WAPI_CRYPT
;
break
;
default:
p
.
grp_crypto_type
=
NONE_CRYPT
;
break
;
...
...
@@ -2114,6 +2214,16 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
p
.
dot11_auth_mode
=
vif
->
dot11_auth_mode
;
p
.
ch
=
cpu_to_le16
(
vif
->
next_chan
);
if
(
vif
->
wdev
.
iftype
==
NL80211_IFTYPE_P2P_GO
)
{
p
.
nw_subtype
=
SUBTYPE_P2PGO
;
}
else
{
/*
* Due to firmware limitation, it is not possible to
* do P2P mgmt operations in AP mode
*/
p
.
nw_subtype
=
SUBTYPE_NONE
;
}
res
=
ath6kl_wmi_ap_profile_commit
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
&
p
);
if
(
res
<
0
)
return
res
;
...
...
@@ -2279,9 +2389,23 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
}
*
cookie
=
id
;
return
ath6kl_wmi_send_action_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
id
,
chan
->
center_freq
,
wait
,
buf
,
len
);
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX
,
ar
->
fw_capabilities
))
{
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
* supported rates to advertise and xmit rates for
* probe requests
*/
return
ath6kl_wmi_send_mgmt_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
id
,
chan
->
center_freq
,
wait
,
buf
,
len
,
no_cck
);
}
else
{
return
ath6kl_wmi_send_action_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
id
,
chan
->
center_freq
,
wait
,
buf
,
len
);
}
}
static
void
ath6kl_mgmt_frame_register
(
struct
wiphy
*
wiphy
,
...
...
@@ -2302,6 +2426,90 @@ static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
}
}
static
int
ath6kl_cfg80211_sscan_start
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_sched_scan_request
*
request
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
u16
interval
;
int
ret
;
u8
i
;
if
(
ar
->
state
!=
ATH6KL_STATE_ON
)
return
-
EIO
;
if
(
vif
->
sme_state
!=
SME_DISCONNECTED
)
return
-
EBUSY
;
for
(
i
=
0
;
i
<
ar
->
wiphy
->
max_sched_scan_ssids
;
i
++
)
{
ath6kl_wmi_probedssid_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
i
,
DISABLE_SSID_FLAG
,
0
,
NULL
);
}
/* fw uses seconds, also make sure that it's >0 */
interval
=
max_t
(
u16
,
1
,
request
->
interval
/
1000
);
ath6kl_wmi_scanparams_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
interval
,
interval
,
10
,
0
,
0
,
0
,
3
,
0
,
0
,
0
);
if
(
request
->
n_ssids
&&
request
->
ssids
[
0
].
ssid_len
)
{
for
(
i
=
0
;
i
<
request
->
n_ssids
;
i
++
)
{
ath6kl_wmi_probedssid_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
i
,
SPECIFIC_SSID_FLAG
,
request
->
ssids
[
i
].
ssid_len
,
request
->
ssids
[
i
].
ssid
);
}
}
ret
=
ath6kl_wmi_set_wow_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_WOW_MODE_ENABLE
,
WOW_FILTER_SSID
,
WOW_HOST_REQ_DELAY
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to enable wow with ssid filter: %d
\n
"
,
ret
);
return
ret
;
}
/* this also clears IE in fw if it's not set */
ret
=
ath6kl_wmi_set_appie_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
WMI_FRAME_PROBE_REQ
,
request
->
ie
,
request
->
ie_len
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to set probe request IE for scheduled scan: %d"
,
ret
);
return
ret
;
}
ret
=
ath6kl_wmi_set_host_sleep_mode_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
ATH6KL_HOST_MODE_ASLEEP
);
if
(
ret
)
{
ath6kl_warn
(
"Failed to enable host sleep mode for sched scan: %d
\n
"
,
ret
);
return
ret
;
}
ar
->
state
=
ATH6KL_STATE_SCHED_SCAN
;
return
ret
;
}
static
int
ath6kl_cfg80211_sscan_stop
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
)
{
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
bool
stopped
;
stopped
=
__ath6kl_cfg80211_sscan_stop
(
vif
);
if
(
!
stopped
)
return
-
EIO
;
return
0
;
}
static
const
struct
ieee80211_txrx_stypes
ath6kl_mgmt_stypes
[
NUM_NL80211_IFTYPES
]
=
{
[
NL80211_IFTYPE_STATION
]
=
{
...
...
@@ -2359,25 +2567,17 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.
cancel_remain_on_channel
=
ath6kl_cancel_remain_on_channel
,
.
mgmt_tx
=
ath6kl_mgmt_tx
,
.
mgmt_frame_register
=
ath6kl_mgmt_frame_register
,
.
sched_scan_start
=
ath6kl_cfg80211_sscan_start
,
.
sched_scan_stop
=
ath6kl_cfg80211_sscan_stop
,
};
void
ath6kl_cfg80211_stop
(
struct
ath6kl
*
ar
)
void
ath6kl_cfg80211_stop
(
struct
ath6kl
_vif
*
vif
)
{
struct
ath6kl_vif
*
vif
;
/* FIXME: for multi vif */
vif
=
ath6kl_vif_first
(
ar
);
if
(
!
vif
)
{
/* save the current power mode before enabling power save */
ar
->
wmi
->
saved_pwr_mode
=
ar
->
wmi
->
pwr_mode
;
if
(
ath6kl_wmi_powermode_cmd
(
ar
->
wmi
,
0
,
REC_POWER
)
!=
0
)
ath6kl_warn
(
"ath6kl_deep_sleep_enable: "
"wmi_powermode_cmd failed
\n
"
);
return
;
}
ath6kl_cfg80211_sscan_disable
(
vif
);
switch
(
vif
->
sme_state
)
{
case
SME_DISCONNECTED
:
break
;
case
SME_CONNECTING
:
cfg80211_connect_result
(
vif
->
ndev
,
vif
->
bssid
,
NULL
,
0
,
NULL
,
0
,
...
...
@@ -2385,33 +2585,50 @@ void ath6kl_cfg80211_stop(struct ath6kl *ar)
GFP_KERNEL
);
break
;
case
SME_CONNECTED
:
default:
/*
* FIXME: oddly enough smeState is in DISCONNECTED during
* suspend, why? Need to send disconnected event in that
* state.
*/
cfg80211_disconnected
(
vif
->
ndev
,
0
,
NULL
,
0
,
GFP_KERNEL
);
break
;
}
if
(
test_bit
(
CONNECTED
,
&
vif
->
flags
)
||
test_bit
(
CONNECT_PEND
,
&
vif
->
flags
))
ath6kl_wmi_disconnect_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
);
ath6kl_wmi_disconnect_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
);
vif
->
sme_state
=
SME_DISCONNECTED
;
clear_bit
(
CONNECTED
,
&
vif
->
flags
);
clear_bit
(
CONNECT_PEND
,
&
vif
->
flags
);
/* disable scanning */
if
(
ath6kl_wmi_scanparams_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
0xFFFF
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
!=
0
)
printk
(
KERN_WARNING
"ath6kl: failed to disable scan "
"during suspend
\n
"
);
if
(
ath6kl_wmi_scanparams_cmd
(
vif
->
ar
->
wmi
,
vif
->
fw_vif_idx
,
0xFFFF
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
!=
0
)
ath6kl_warn
(
"failed to disable scan during stop
\n
"
);
ath6kl_cfg80211_scan_complete_event
(
vif
,
true
);
}
void
ath6kl_cfg80211_stop_all
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_vif
*
vif
;
vif
=
ath6kl_vif_first
(
ar
);
if
(
!
vif
)
{
/* save the current power mode before enabling power save */
ar
->
wmi
->
saved_pwr_mode
=
ar
->
wmi
->
pwr_mode
;
if
(
ath6kl_wmi_powermode_cmd
(
ar
->
wmi
,
0
,
REC_POWER
)
!=
0
)
ath6kl_warn
(
"ath6kl_deep_sleep_enable: "
"wmi_powermode_cmd failed
\n
"
);
return
;
}
/*
* FIXME: we should take ar->list_lock to protect changes in the
* vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
* sleeps.
*/
list_for_each_entry
(
vif
,
&
ar
->
vif_list
,
list
)
ath6kl_cfg80211_stop
(
vif
);
}
struct
ath6kl
*
ath6kl_core_alloc
(
struct
device
*
dev
)
{
struct
ath6kl
*
ar
;
...
...
@@ -2427,17 +2644,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
}
ar
=
wiphy_priv
(
wiphy
);
if
(
!
multi_norm_if_support
)
ar
->
p2p
=
!!
ath6kl_p2p
;
ar
->
p2p
=
!!
ath6kl_p2p
;
ar
->
wiphy
=
wiphy
;
ar
->
dev
=
dev
;
if
(
multi_norm_if_support
)
ar
->
max_norm_iface
=
2
;
else
ar
->
max_norm_iface
=
1
;
ar
->
vif_max
=
1
;
/* FIXME: Remove this once the multivif support is enabled */
ar
->
max_norm_iface
=
1
;
spin_lock_init
(
&
ar
->
lock
);
...
...
@@ -2459,9 +2671,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
ar
->
tx_pwr
=
0
;
ar
->
intra_bss
=
1
;
memset
(
&
ar
->
sc_params
,
0
,
sizeof
(
ar
->
sc_params
));
ar
->
sc_params
.
short_scan_ratio
=
WMI_SHORTSCANRATIO_DEFAULT
;
ar
->
sc_params
.
scan_ctrl_flags
=
DEFAULT_SCAN_CTRL_FLAGS
;
ar
->
lrssi_roam_threshold
=
DEF_LRSSI_ROAM_THRESHOLD
;
ar
->
state
=
ATH6KL_STATE_OFF
;
...
...
@@ -2522,6 +2731,8 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
wiphy
->
wowlan
.
pattern_min_len
=
1
;
wiphy
->
wowlan
.
pattern_max_len
=
WOW_PATTERN_SIZE
;
wiphy
->
max_sched_scan_ssids
=
10
;
ret
=
wiphy_register
(
wiphy
);
if
(
ret
<
0
)
{
ath6kl_err
(
"couldn't register wiphy device
\n
"
);
...
...
@@ -2541,6 +2752,9 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif)
setup_timer
(
&
vif
->
disconnect_timer
,
disconnect_timer_handler
,
(
unsigned
long
)
vif
->
ndev
);
setup_timer
(
&
vif
->
sched_scan_timer
,
ath6kl_wmi_sscan_timer
,
(
unsigned
long
)
vif
);
set_bit
(
WMM_ENABLED
,
&
vif
->
flags
);
spin_lock_init
(
&
vif
->
if_lock
);
...
...
drivers/net/wireless/ath/ath6kl/cfg80211.h
View file @
640f5950
...
...
@@ -20,7 +20,8 @@
enum
ath6kl_cfg_suspend_mode
{
ATH6KL_CFG_SUSPEND_DEEPSLEEP
,
ATH6KL_CFG_SUSPEND_CUTPOWER
,
ATH6KL_CFG_SUSPEND_WOW
ATH6KL_CFG_SUSPEND_WOW
,
ATH6KL_CFG_SUSPEND_SCHED_SCAN
,
};
struct
net_device
*
ath6kl_interface_add
(
struct
ath6kl
*
ar
,
char
*
name
,
...
...
@@ -52,6 +53,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
int
ath6kl_cfg80211_resume
(
struct
ath6kl
*
ar
);
void
ath6kl_cfg80211_stop
(
struct
ath6kl
*
ar
);
void
ath6kl_cfg80211_stop
(
struct
ath6kl_vif
*
vif
);
void
ath6kl_cfg80211_stop_all
(
struct
ath6kl
*
ar
);
#endif
/* ATH6KL_CFG80211_H */
drivers/net/wireless/ath/ath6kl/common.h
View file @
640f5950
...
...
@@ -71,6 +71,7 @@ enum crypto_type {
WEP_CRYPT
=
0x02
,
TKIP_CRYPT
=
0x04
,
AES_CRYPT
=
0x08
,
WAPI_CRYPT
=
0x10
,
};
struct
htc_endpoint_credit_dist
;
...
...
drivers/net/wireless/ath/ath6kl/core.h
View file @
640f5950
...
...
@@ -70,10 +70,20 @@ enum ath6kl_fw_ie_type {
ATH6KL_FW_IE_RESERVED_RAM_SIZE
=
5
,
ATH6KL_FW_IE_CAPABILITIES
=
6
,
ATH6KL_FW_IE_PATCH_ADDR
=
7
,
ATH6KL_FW_IE_BOARD_ADDR
=
8
,
ATH6KL_FW_IE_VIF_MAX
=
9
,
};
enum
ath6kl_fw_capability
{
ATH6KL_FW_CAPABILITY_HOST_P2P
=
0
,
ATH6KL_FW_CAPABILITY_SCHED_SCAN
=
1
,
/*
* Firmware is capable of supporting P2P mgmt operations on a
* station interface. After group formation, the station
* interface will become a P2P client/GO interface as the case may be
*/
ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX
,
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX
,
...
...
@@ -88,37 +98,47 @@ struct ath6kl_fw_ie {
};
/* AR6003 1.0 definitions */
#define AR6003_
REV1
_VERSION 0x300002ba
#define AR6003_
HW_1_0
_VERSION 0x300002ba
/* AR6003 2.0 definitions */
#define AR6003_REV2_VERSION 0x30000384
#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
#define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
#define AR6003_HW_2_0_VERSION 0x30000384
#define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910
#define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
#define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
#define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
#define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
#define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
#define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6003/hw2.0/bdata.SD31.bin"
/* AR6003 3.0 definitions */
#define AR6003_REV3_VERSION 0x30000582
#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
#define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
#define AR6003_HW_2_1_1_VERSION 0x30000582
#define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
#define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \
"ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
#define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
#define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
#define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
#define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
/* AR6004 1.0 definitions */
#define AR6004_REV1_VERSION 0x30000623
#define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin"
#define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin"
#define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin"
#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin"
#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin"
#define AR6004_HW_1_0_VERSION 0x30000623
#define AR6004_HW_1_0_FIRMWARE_2_FILE "ath6k/AR6004/hw1.0/fw-2.bin"
#define AR6004_HW_1_0_FIRMWARE_FILE "ath6k/AR6004/hw1.0/fw.ram.bin"
#define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin"
#define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6004/hw1.0/bdata.DB132.bin"
/* AR6004 1.1 definitions */
#define AR6004_HW_1_1_VERSION 0x30000001
#define AR6004_HW_1_1_FIRMWARE_2_FILE "ath6k/AR6004/hw1.1/fw-2.bin"
#define AR6004_HW_1_1_FIRMWARE_FILE "ath6k/AR6004/hw1.1/fw.ram.bin"
#define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin"
#define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \
"ath6k/AR6004/hw1.1/bdata.DB132.bin"
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)
...
...
@@ -272,6 +292,8 @@ struct ath6kl_bmi {
u32
cmd_credits
;
bool
done_sent
;
u8
*
cmd_buf
;
u32
max_data_size
;
u32
max_cmd_size
;
};
struct
target_stats
{
...
...
@@ -381,7 +403,16 @@ struct ath6kl_req_key {
u8
key_len
;
};
#define MAX_NUM_VIF 1
enum
ath6kl_hif_type
{
ATH6KL_HIF_TYPE_SDIO
,
ATH6KL_HIF_TYPE_USB
,
};
/*
* Driver's maximum limit, note that some firmwares support only one vif
* and the runtime (current) limit must be checked from ar->vif_max.
*/
#define ATH6KL_VIF_MAX 3
/* vif flags info */
enum
ath6kl_vif_state
{
...
...
@@ -424,7 +455,10 @@ struct ath6kl_vif {
struct
ath6kl_wep_key
wep_key_list
[
WMI_MAX_KEY_INDEX
+
1
];
struct
ath6kl_key
keys
[
WMI_MAX_KEY_INDEX
+
1
];
struct
aggr_info
*
aggr_cntxt
;
struct
timer_list
disconnect_timer
;
struct
timer_list
sched_scan_timer
;
struct
cfg80211_scan_request
*
scan_req
;
enum
sme_state
sme_state
;
int
reconnect_flag
;
...
...
@@ -442,6 +476,8 @@ struct ath6kl_vif {
#define WOW_LIST_ID 0
#define WOW_HOST_REQ_DELAY 500
/* ms */
#define ATH6KL_SCHED_SCAN_RESULT_DELAY 5000
/* ms */
/* Flag info */
enum
ath6kl_dev_state
{
WMI_ENABLED
,
...
...
@@ -460,6 +496,7 @@ enum ath6kl_state {
ATH6KL_STATE_DEEPSLEEP
,
ATH6KL_STATE_CUTPOWER
,
ATH6KL_STATE_WOW
,
ATH6KL_STATE_SCHED_SCAN
,
};
struct
ath6kl
{
...
...
@@ -474,11 +511,13 @@ struct ath6kl {
int
tx_pending
[
ENDPOINT_MAX
];
int
total_tx_data_pend
;
struct
htc_target
*
htc_target
;
enum
ath6kl_hif_type
hif_type
;
void
*
hif_priv
;
struct
list_head
vif_list
;
/* Lock to avoid race in vif_list entries among add/del/traverse */
spinlock_t
list_lock
;
u8
num_vif
;
unsigned
int
vif_max
;
u8
max_norm_iface
;
u8
avail_idx_map
;
spinlock_t
lock
;
...
...
@@ -517,7 +556,6 @@ struct ath6kl {
struct
list_head
amsdu_rx_buffer_queue
;
u8
rx_meta_ver
;
enum
wlan_low_pwr_state
wlan_pwr_state
;
struct
wmi_scan_params_cmd
sc_params
;
u8
mac_addr
[
ETH_ALEN
];
#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
struct
{
...
...
@@ -525,12 +563,25 @@ struct ath6kl {
size_t
rx_report_len
;
}
tm
;
struct
{
struct
ath6kl_hw
{
u32
id
;
const
char
*
name
;
u32
dataset_patch_addr
;
u32
app_load_addr
;
u32
app_start_override_addr
;
u32
board_ext_data_addr
;
u32
reserved_ram_size
;
u32
board_addr
;
u32
refclk_hz
;
u32
uarttx_pin
;
const
char
*
fw_otp
;
const
char
*
fw
;
const
char
*
fw_tcmd
;
const
char
*
fw_patch
;
const
char
*
fw_api2
;
const
char
*
fw_board
;
const
char
*
fw_default_board
;
}
hw
;
u16
conf_flags
;
...
...
@@ -583,7 +634,7 @@ struct ath6kl {
#endif
/* CONFIG_ATH6KL_DEBUG */
};
static
inline
void
*
ath6kl_priv
(
struct
net_device
*
dev
)
static
inline
struct
ath6kl
*
ath6kl_priv
(
struct
net_device
*
dev
)
{
return
((
struct
ath6kl_vif
*
)
netdev_priv
(
dev
))
->
ar
;
}
...
...
drivers/net/wireless/ath/ath6kl/debug.c
View file @
640f5950
...
...
@@ -1551,10 +1551,10 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
ath6kl
*
ar
=
file
->
private_data
;
char
buf
[
16
];
char
buf
[
32
];
int
len
;
len
=
snprintf
(
buf
,
sizeof
(
buf
),
"%u %u
\n
"
,
ar
->
listen_intvl_t
,
len
=
s
c
nprintf
(
buf
,
sizeof
(
buf
),
"%u %u
\n
"
,
ar
->
listen_intvl_t
,
ar
->
listen_intvl_b
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
...
...
drivers/net/wireless/ath/ath6kl/debug.h
View file @
640f5950
...
...
@@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_BOOT
=
BIT
(
18
),
/* driver init and fw boot */
ATH6KL_DBG_WMI_DUMP
=
BIT
(
19
),
ATH6KL_DBG_SUSPEND
=
BIT
(
20
),
ATH6KL_DBG_USB
=
BIT
(
21
),
ATH6KL_DBG_ANY
=
0xffffffff
/* enable all logs */
};
...
...
drivers/net/wireless/ath/ath6kl/hif-ops.h
View file @
640f5950
...
...
@@ -91,6 +91,36 @@ static inline int ath6kl_hif_suspend(struct ath6kl *ar,
return
ar
->
hif_ops
->
suspend
(
ar
,
wow
);
}
/*
* Read from the ATH6KL through its diagnostic window. No cooperation from
* the Target is required for this.
*/
static
inline
int
ath6kl_hif_diag_read32
(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
value
)
{
return
ar
->
hif_ops
->
diag_read32
(
ar
,
address
,
value
);
}
/*
* Write to the ATH6KL through its diagnostic window. No cooperation from
* the Target is required for this.
*/
static
inline
int
ath6kl_hif_diag_write32
(
struct
ath6kl
*
ar
,
u32
address
,
__le32
value
)
{
return
ar
->
hif_ops
->
diag_write32
(
ar
,
address
,
value
);
}
static
inline
int
ath6kl_hif_bmi_read
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
return
ar
->
hif_ops
->
bmi_read
(
ar
,
buf
,
len
);
}
static
inline
int
ath6kl_hif_bmi_write
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
return
ar
->
hif_ops
->
bmi_write
(
ar
,
buf
,
len
);
}
static
inline
int
ath6kl_hif_resume
(
struct
ath6kl
*
ar
)
{
ath6kl_dbg
(
ATH6KL_DBG_HIF
,
"hif resume
\n
"
);
...
...
drivers/net/wireless/ath/ath6kl/hif.c
View file @
640f5950
...
...
@@ -689,6 +689,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
ath6kl_dbg
(
ATH6KL_DBG_HIF
,
"hif block size %d mbox addr 0x%x
\n
"
,
dev
->
htc_cnxt
->
block_sz
,
dev
->
ar
->
mbox_info
.
htc_addr
);
/* usb doesn't support enabling interrupts */
/* FIXME: remove check once USB support is implemented */
if
(
dev
->
ar
->
hif_type
==
ATH6KL_HIF_TYPE_USB
)
return
0
;
status
=
ath6kl_hif_disable_intrs
(
dev
);
fail_setup:
...
...
drivers/net/wireless/ath/ath6kl/hif.h
View file @
640f5950
...
...
@@ -35,6 +35,7 @@
#define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024)
#define MANUFACTURER_ID_AR6003_BASE 0x300
#define MANUFACTURER_ID_AR6004_BASE 0x400
/* SDIO manufacturer ID and Codes */
#define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00
#define MANUFACTURER_CODE 0x271
/* Atheros */
...
...
@@ -244,6 +245,10 @@ struct ath6kl_hif_ops {
void
(
*
cleanup_scatter
)(
struct
ath6kl
*
ar
);
int
(
*
suspend
)(
struct
ath6kl
*
ar
,
struct
cfg80211_wowlan
*
wow
);
int
(
*
resume
)(
struct
ath6kl
*
ar
);
int
(
*
diag_read32
)(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
value
);
int
(
*
diag_write32
)(
struct
ath6kl
*
ar
,
u32
address
,
__le32
value
);
int
(
*
bmi_read
)(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
);
int
(
*
bmi_write
)(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
);
int
(
*
power_on
)(
struct
ath6kl
*
ar
);
int
(
*
power_off
)(
struct
ath6kl
*
ar
);
void
(
*
stop
)(
struct
ath6kl
*
ar
);
...
...
drivers/net/wireless/ath/ath6kl/htc.c
View file @
640f5950
...
...
@@ -2543,6 +2543,12 @@ int ath6kl_htc_wait_target(struct htc_target *target)
struct
htc_service_connect_resp
resp
;
int
status
;
/* FIXME: remove once USB support is implemented */
if
(
target
->
dev
->
ar
->
hif_type
==
ATH6KL_HIF_TYPE_USB
)
{
ath6kl_err
(
"HTC doesn't support USB yet. Patience!
\n
"
);
return
-
EOPNOTSUPP
;
}
/* we should be getting 1 control message that the target is ready */
packet
=
htc_wait_for_ctrl_msg
(
target
);
...
...
@@ -2772,7 +2778,9 @@ void ath6kl_htc_cleanup(struct htc_target *target)
{
struct
htc_packet
*
packet
,
*
tmp_packet
;
ath6kl_hif_cleanup_scatter
(
target
->
dev
->
ar
);
/* FIXME: remove check once USB support is implemented */
if
(
target
->
dev
->
ar
->
hif_type
!=
ATH6KL_HIF_TYPE_USB
)
ath6kl_hif_cleanup_scatter
(
target
->
dev
->
ar
);
list_for_each_entry_safe
(
packet
,
tmp_packet
,
&
target
->
free_ctrl_txbuf
,
list
)
{
...
...
drivers/net/wireless/ath/ath6kl/init.c
View file @
640f5950
...
...
@@ -33,6 +33,80 @@ module_param(debug_mask, uint, 0644);
module_param
(
testmode
,
uint
,
0644
);
module_param
(
suspend_cutpower
,
bool
,
0444
);
static
const
struct
ath6kl_hw
hw_list
[]
=
{
{
.
id
=
AR6003_HW_2_0_VERSION
,
.
name
=
"ar6003 hw 2.0"
,
.
dataset_patch_addr
=
0x57e884
,
.
app_load_addr
=
0x543180
,
.
board_ext_data_addr
=
0x57e500
,
.
reserved_ram_size
=
6912
,
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
8
,
/* hw2.0 needs override address hardcoded */
.
app_start_override_addr
=
0x944C00
,
.
fw_otp
=
AR6003_HW_2_0_OTP_FILE
,
.
fw
=
AR6003_HW_2_0_FIRMWARE_FILE
,
.
fw_tcmd
=
AR6003_HW_2_0_TCMD_FIRMWARE_FILE
,
.
fw_patch
=
AR6003_HW_2_0_PATCH_FILE
,
.
fw_api2
=
AR6003_HW_2_0_FIRMWARE_2_FILE
,
.
fw_board
=
AR6003_HW_2_0_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE
,
},
{
.
id
=
AR6003_HW_2_1_1_VERSION
,
.
name
=
"ar6003 hw 2.1.1"
,
.
dataset_patch_addr
=
0x57ff74
,
.
app_load_addr
=
0x1234
,
.
board_ext_data_addr
=
0x542330
,
.
reserved_ram_size
=
512
,
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
8
,
.
fw_otp
=
AR6003_HW_2_1_1_OTP_FILE
,
.
fw
=
AR6003_HW_2_1_1_FIRMWARE_FILE
,
.
fw_tcmd
=
AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE
,
.
fw_patch
=
AR6003_HW_2_1_1_PATCH_FILE
,
.
fw_api2
=
AR6003_HW_2_1_1_FIRMWARE_2_FILE
,
.
fw_board
=
AR6003_HW_2_1_1_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE
,
},
{
.
id
=
AR6004_HW_1_0_VERSION
,
.
name
=
"ar6004 hw 1.0"
,
.
dataset_patch_addr
=
0x57e884
,
.
app_load_addr
=
0x1234
,
.
board_ext_data_addr
=
0x437000
,
.
reserved_ram_size
=
19456
,
.
board_addr
=
0x433900
,
.
refclk_hz
=
26000000
,
.
uarttx_pin
=
11
,
.
fw
=
AR6004_HW_1_0_FIRMWARE_FILE
,
.
fw_api2
=
AR6004_HW_1_0_FIRMWARE_2_FILE
,
.
fw_board
=
AR6004_HW_1_0_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE
,
},
{
.
id
=
AR6004_HW_1_1_VERSION
,
.
name
=
"ar6004 hw 1.1"
,
.
dataset_patch_addr
=
0x57e884
,
.
app_load_addr
=
0x1234
,
.
board_ext_data_addr
=
0x437000
,
.
reserved_ram_size
=
11264
,
.
board_addr
=
0x43d400
,
.
refclk_hz
=
40000000
,
.
uarttx_pin
=
11
,
.
fw
=
AR6004_HW_1_1_FIRMWARE_FILE
,
.
fw_api2
=
AR6004_HW_1_1_FIRMWARE_2_FILE
,
.
fw_board
=
AR6004_HW_1_1_BOARD_DATA_FILE
,
.
fw_default_board
=
AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE
,
},
};
/*
* Include definitions here that can be used to tune the WLAN module
* behavior. Different customers can tune the behavior as per their needs,
...
...
@@ -58,7 +132,6 @@ module_param(suspend_cutpower, bool, 0444);
*/
#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
#define ATH6KL_DATA_OFFSET 64
struct
sk_buff
*
ath6kl_buf_alloc
(
int
size
)
...
...
@@ -348,11 +421,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
status
=
-
EIO
;
}
/*
* FIXME: Make sure p2p configurations are not applied to
* non-p2p capable interfaces when multivif support is enabled.
*/
if
(
ar
->
p2p
)
{
if
(
ar
->
p2p
&&
(
ar
->
vif_max
==
1
||
idx
))
{
ret
=
ath6kl_wmi_info_req_cmd
(
ar
->
wmi
,
idx
,
P2P_FLAG_CAPABILITIES_REQ
|
P2P_FLAG_MACADDR_REQ
|
...
...
@@ -365,11 +434,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
}
}
/*
* FIXME: Make sure p2p configurations are not applied to
* non-p2p capable interfaces when multivif support is enabled.
*/
if
(
ar
->
p2p
)
{
if
(
ar
->
p2p
&&
(
ar
->
vif_max
==
1
||
idx
))
{
/* Enable Probe Request reporting for P2P */
ret
=
ath6kl_wmi_probe_report_req_cmd
(
ar
->
wmi
,
idx
,
true
);
if
(
ret
)
{
...
...
@@ -385,7 +450,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
{
u32
param
,
ram_reserved_size
;
u8
fw_iftype
,
fw_mode
=
0
,
fw_submode
=
0
;
int
i
;
int
i
,
status
;
/*
* Note: Even though the firmware interface type is
...
...
@@ -397,7 +462,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
*/
fw_iftype
=
HI_OPTION_FW_MODE_BSS_STA
;
for
(
i
=
0
;
i
<
MAX_NUM_VIF
;
i
++
)
for
(
i
=
0
;
i
<
ar
->
vif_max
;
i
++
)
fw_mode
|=
fw_iftype
<<
(
i
*
HI_OPTION_FW_MODE_BITS
);
/*
...
...
@@ -411,15 +476,11 @@ int ath6kl_configure_target(struct ath6kl *ar)
fw_submode
|=
HI_OPTION_FW_SUBMODE_NONE
<<
(
i
*
HI_OPTION_FW_SUBMODE_BITS
);
for
(
i
=
ar
->
max_norm_iface
;
i
<
MAX_NUM_VIF
;
i
++
)
for
(
i
=
ar
->
max_norm_iface
;
i
<
ar
->
vif_max
;
i
++
)
fw_submode
|=
HI_OPTION_FW_SUBMODE_P2PDEV
<<
(
i
*
HI_OPTION_FW_SUBMODE_BITS
);
/*
* FIXME: This needs to be removed once the multivif
* support is enabled.
*/
if
(
ar
->
p2p
)
if
(
ar
->
p2p
&&
ar
->
vif_max
==
1
)
fw_submode
=
HI_OPTION_FW_SUBMODE_P2PDEV
;
param
=
HTC_PROTOCOL_VERSION
;
...
...
@@ -442,7 +503,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
return
-
EIO
;
}
param
|=
(
MAX_NUM_VIF
<<
HI_OPTION_NUM_DEV_SHIFT
);
param
|=
(
ar
->
vif_max
<<
HI_OPTION_NUM_DEV_SHIFT
);
param
|=
fw_mode
<<
HI_OPTION_FW_MODE_SHIFT
;
param
|=
fw_submode
<<
HI_OPTION_FW_SUBMODE_SHIFT
;
...
...
@@ -491,6 +552,24 @@ int ath6kl_configure_target(struct ath6kl *ar)
/* use default number of control buffers */
return
-
EIO
;
/* Configure GPIO AR600x UART */
param
=
ar
->
hw
.
uarttx_pin
;
status
=
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_dbg_uart_txpin
)),
(
u8
*
)
&
param
,
4
);
if
(
status
)
return
status
;
/* Configure target refclk_hz */
param
=
ar
->
hw
.
refclk_hz
;
status
=
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_refclk_hz
)),
(
u8
*
)
&
param
,
4
);
if
(
status
)
return
status
;
return
0
;
}
...
...
@@ -550,11 +629,11 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
static
const
char
*
get_target_ver_dir
(
const
struct
ath6kl
*
ar
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_
REV1
_VERSION
:
case
AR6003_
HW_1_0
_VERSION
:
return
"ath6k/AR6003/hw1.0"
;
case
AR6003_
REV2
_VERSION
:
case
AR6003_
HW_2_0
_VERSION
:
return
"ath6k/AR6003/hw2.0"
;
case
AR6003_
REV3
_VERSION
:
case
AR6003_
HW_2_1_1
_VERSION
:
return
"ath6k/AR6003/hw2.1.1"
;
}
ath6kl_warn
(
"%s: unsupported target version 0x%x.
\n
"
,
__func__
,
...
...
@@ -612,17 +691,10 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
if
(
ar
->
fw_board
!=
NULL
)
return
0
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_BOARD_DATA_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_BOARD_DATA_FILE
;
break
;
default:
filename
=
AR6003_REV3_BOARD_DATA_FILE
;
break
;
}
if
(
WARN_ON
(
ar
->
hw
.
fw_board
==
NULL
))
return
-
EINVAL
;
filename
=
ar
->
hw
.
fw_board
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_board
,
&
ar
->
fw_board_len
);
...
...
@@ -640,17 +712,7 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
ath6kl_warn
(
"Failed to get board file %s (%d), trying to find default board file.
\n
"
,
filename
,
ret
);
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_DEFAULT_BOARD_DATA_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_DEFAULT_BOARD_DATA_FILE
;
break
;
default:
filename
=
AR6003_REV3_DEFAULT_BOARD_DATA_FILE
;
break
;
}
filename
=
ar
->
hw
.
fw_default_board
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_board
,
&
ar
->
fw_board_len
);
...
...
@@ -674,19 +736,14 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar)
if
(
ar
->
fw_otp
!=
NULL
)
return
0
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_OTP_FILE
;
break
;
case
AR6004_REV1_VERSION
:
ath6kl_dbg
(
ATH6KL_DBG_TRC
,
"AR6004 doesn't need OTP file
\n
"
);
if
(
ar
->
hw
.
fw_otp
==
NULL
)
{
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"no OTP file configured for this hw
\n
"
);
return
0
;
break
;
default:
filename
=
AR6003_REV3_OTP_FILE
;
break
;
}
filename
=
ar
->
hw
.
fw_otp
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_otp
,
&
ar
->
fw_otp_len
);
if
(
ret
)
{
...
...
@@ -707,38 +764,22 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar)
return
0
;
if
(
testmode
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_TCMD_FIRMWARE_FILE
;
break
;
case
AR6003_REV3_VERSION
:
filename
=
AR6003_REV3_TCMD_FIRMWARE_FILE
;
break
;
case
AR6004_REV1_VERSION
:
ath6kl_warn
(
"testmode not supported with ar6004
\n
"
);
if
(
ar
->
hw
.
fw_tcmd
==
NULL
)
{
ath6kl_warn
(
"testmode not supported
\n
"
);
return
-
EOPNOTSUPP
;
default:
ath6kl_warn
(
"unknown target version: 0x%x
\n
"
,
ar
->
version
.
target_ver
);
return
-
EINVAL
;
}
filename
=
ar
->
hw
.
fw_tcmd
;
set_bit
(
TESTMODE
,
&
ar
->
flag
);
goto
get_fw
;
}
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_FIRMWARE_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_FIRMWARE_FILE
;
break
;
default:
filename
=
AR6003_REV3_FIRMWARE_FILE
;
break
;
}
if
(
WARN_ON
(
ar
->
hw
.
fw
==
NULL
))
return
-
EINVAL
;
filename
=
ar
->
hw
.
fw
;
get_fw:
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw
,
&
ar
->
fw_len
);
...
...
@@ -756,27 +797,20 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar)
const
char
*
filename
;
int
ret
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_PATCH_FILE
;
break
;
case
AR6004_REV1_VERSION
:
/* FIXME: implement for AR6004 */
if
(
ar
->
fw_patch
!=
NULL
)
return
0
;
break
;
default:
filename
=
AR6003_REV3_PATCH_FILE
;
break
;
}
if
(
ar
->
fw_patch
==
NULL
)
{
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_patch
,
&
ar
->
fw_patch_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get patch file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
if
(
ar
->
hw
.
fw_patch
==
NULL
)
return
0
;
filename
=
ar
->
hw
.
fw_patch
;
ret
=
ath6kl_get_fw
(
ar
,
filename
,
&
ar
->
fw_patch
,
&
ar
->
fw_patch_len
);
if
(
ret
)
{
ath6kl_err
(
"Failed to get patch file %s: %d
\n
"
,
filename
,
ret
);
return
ret
;
}
return
0
;
...
...
@@ -811,19 +845,10 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
int
ret
,
ie_id
,
i
,
index
,
bit
;
__le32
*
val
;
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
filename
=
AR6003_REV2_FIRMWARE_2_FILE
;
break
;
case
AR6003_REV3_VERSION
:
filename
=
AR6003_REV3_FIRMWARE_2_FILE
;
break
;
case
AR6004_REV1_VERSION
:
filename
=
AR6004_REV1_FIRMWARE_2_FILE
;
break
;
default:
if
(
ar
->
hw
.
fw_api2
==
NULL
)
return
-
EOPNOTSUPP
;
}
filename
=
ar
->
hw
.
fw_api2
;
ret
=
request_firmware
(
&
fw
,
filename
,
ar
->
dev
);
if
(
ret
)
...
...
@@ -913,12 +938,15 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
ar
->
hw
.
reserved_ram_size
);
break
;
case
ATH6KL_FW_IE_CAPABILITIES
:
if
(
ie_len
<
DIV_ROUND_UP
(
ATH6KL_FW_CAPABILITY_MAX
,
8
))
break
;
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found firmware capabilities ie (%zd B)
\n
"
,
ie_len
);
for
(
i
=
0
;
i
<
ATH6KL_FW_CAPABILITY_MAX
;
i
++
)
{
index
=
ALIGN
(
i
,
8
)
/
8
;
index
=
i
/
8
;
bit
=
i
%
8
;
if
(
data
[
index
]
&
(
1
<<
bit
))
...
...
@@ -937,9 +965,34 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
ar
->
hw
.
dataset_patch_addr
=
le32_to_cpup
(
val
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found patch address ie 0x%
d
\n
"
,
"found patch address ie 0x%
x
\n
"
,
ar
->
hw
.
dataset_patch_addr
);
break
;
case
ATH6KL_FW_IE_BOARD_ADDR
:
if
(
ie_len
!=
sizeof
(
*
val
))
break
;
val
=
(
__le32
*
)
data
;
ar
->
hw
.
board_addr
=
le32_to_cpup
(
val
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found board address ie 0x%x
\n
"
,
ar
->
hw
.
board_addr
);
break
;
case
ATH6KL_FW_IE_VIF_MAX
:
if
(
ie_len
!=
sizeof
(
*
val
))
break
;
val
=
(
__le32
*
)
data
;
ar
->
vif_max
=
min_t
(
unsigned
int
,
le32_to_cpup
(
val
),
ATH6KL_VIF_MAX
);
if
(
ar
->
vif_max
>
1
&&
!
ar
->
p2p
)
ar
->
max_norm_iface
=
2
;
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"found vif max ie %d
\n
"
,
ar
->
vif_max
);
break
;
default:
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"Unknown fw ie: %u
\n
"
,
le32_to_cpup
(
&
hdr
->
id
));
...
...
@@ -994,8 +1047,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
* For AR6004, host determine Target RAM address for
* writing board data.
*/
if
(
ar
->
target_type
==
TARGET_TYPE_AR6004
)
{
board_address
=
AR6004_REV1_BOARD_DATA_ADDRESS
;
if
(
ar
->
hw
.
board_addr
!=
0
)
{
board_address
=
ar
->
hw
.
board_addr
;
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_board_data
)),
...
...
@@ -1013,7 +1066,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
HI_ITEM
(
hi_board_ext_data
)),
(
u8
*
)
&
board_ext_address
,
4
);
if
(
board_ext_address
==
0
)
{
if
(
ar
->
target_type
==
TARGET_TYPE_AR6003
&&
board_ext_address
==
0
)
{
ath6kl_err
(
"Failed to get board file target address.
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -1033,8 +1087,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
break
;
}
if
(
ar
->
fw_board_len
==
(
board_data_size
+
board_ext_data_size
))
{
if
(
board_ext_address
&&
ar
->
fw_board_len
==
(
board_data_size
+
board_ext_data_size
))
{
/* write extended board data */
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
...
...
@@ -1092,8 +1146,8 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
bool
from_hw
=
false
;
int
ret
;
if
(
WARN_ON
(
ar
->
fw_otp
==
NULL
)
)
return
-
ENOENT
;
if
(
ar
->
fw_otp
==
NULL
)
return
0
;
address
=
ar
->
hw
.
app_load_addr
;
...
...
@@ -1142,7 +1196,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
int
ret
;
if
(
WARN_ON
(
ar
->
fw
==
NULL
))
return
-
ENOENT
;
return
0
;
address
=
ar
->
hw
.
app_load_addr
;
...
...
@@ -1172,8 +1226,8 @@ static int ath6kl_upload_patch(struct ath6kl *ar)
u32
address
,
param
;
int
ret
;
if
(
WARN_ON
(
ar
->
fw_patch
==
NULL
)
)
return
-
ENOENT
;
if
(
ar
->
fw_patch
==
NULL
)
return
0
;
address
=
ar
->
hw
.
dataset_patch_addr
;
...
...
@@ -1258,7 +1312,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
return
status
;
/* WAR to avoid SDIO CRC err */
if
(
ar
->
version
.
target_ver
==
AR6003_
REV2
_VERSION
)
{
if
(
ar
->
version
.
target_ver
==
AR6003_
HW_2_0
_VERSION
)
{
ath6kl_err
(
"temporary war to avoid sdio crc error
\n
"
);
param
=
0x20
;
...
...
@@ -1315,47 +1369,29 @@ static int ath6kl_init_upload(struct ath6kl *ar)
if
(
status
)
return
status
;
/* Configure GPIO AR6003 UART */
param
=
CONFIG_AR600x_DEBUG_UART_TX_PIN
;
status
=
ath6kl_bmi_write
(
ar
,
ath6kl_get_hi_item_addr
(
ar
,
HI_ITEM
(
hi_dbg_uart_txpin
)),
(
u8
*
)
&
param
,
4
);
return
status
;
}
static
int
ath6kl_init_hw_params
(
struct
ath6kl
*
ar
)
{
switch
(
ar
->
version
.
target_ver
)
{
case
AR6003_REV2_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV2_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
AR6003_REV2_APP_LOAD_ADDRESS
;
ar
->
hw
.
board_ext_data_addr
=
AR6003_REV2_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6003_REV2_RAM_RESERVE_SIZE
;
const
struct
ath6kl_hw
*
hw
;
int
i
;
/* hw2.0 needs override address hardcoded */
ar
->
hw
.
app_start_override_addr
=
0x944C00
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
hw_list
);
i
++
)
{
hw
=
&
hw_list
[
i
]
;
break
;
case
AR6003_REV3_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV3_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
0x1234
;
ar
->
hw
.
board_ext_data_addr
=
AR6003_REV3_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6003_REV3_RAM_RESERVE_SIZE
;
break
;
case
AR6004_REV1_VERSION
:
ar
->
hw
.
dataset_patch_addr
=
AR6003_REV2_DATASET_PATCH_ADDRESS
;
ar
->
hw
.
app_load_addr
=
AR6003_REV3_APP_LOAD_ADDRESS
;
ar
->
hw
.
board_ext_data_addr
=
AR6004_REV1_BOARD_EXT_DATA_ADDRESS
;
ar
->
hw
.
reserved_ram_size
=
AR6004_REV1_RAM_RESERVE_SIZE
;
break
;
default:
if
(
hw
->
id
==
ar
->
version
.
target_ver
)
break
;
}
if
(
i
==
ARRAY_SIZE
(
hw_list
))
{
ath6kl_err
(
"Unsupported hardware version: 0x%x
\n
"
,
ar
->
version
.
target_ver
);
return
-
EINVAL
;
}
ar
->
hw
=
*
hw
;
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x
\n
"
,
ar
->
version
.
target_ver
,
ar
->
target_type
,
...
...
@@ -1364,10 +1400,25 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
"app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x"
,
ar
->
hw
.
app_start_override_addr
,
ar
->
hw
.
board_ext_data_addr
,
ar
->
hw
.
reserved_ram_size
);
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"refclk_hz %d uarttx_pin %d"
,
ar
->
hw
.
refclk_hz
,
ar
->
hw
.
uarttx_pin
);
return
0
;
}
static
const
char
*
ath6kl_init_get_hif_name
(
enum
ath6kl_hif_type
type
)
{
switch
(
type
)
{
case
ATH6KL_HIF_TYPE_SDIO
:
return
"sdio"
;
case
ATH6KL_HIF_TYPE_USB
:
return
"usb"
;
}
return
NULL
;
}
int
ath6kl_init_hw_start
(
struct
ath6kl
*
ar
)
{
long
timeleft
;
...
...
@@ -1428,6 +1479,15 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
ath6kl_dbg
(
ATH6KL_DBG_BOOT
,
"firmware booted
\n
"
);
if
(
test_and_clear_bit
(
FIRST_BOOT
,
&
ar
->
flag
))
{
ath6kl_info
(
"%s %s fw %s%s
\n
"
,
ar
->
hw
.
name
,
ath6kl_init_get_hif_name
(
ar
->
hif_type
),
ar
->
wiphy
->
fw_version
,
test_bit
(
TESTMODE
,
&
ar
->
flag
)
?
" testmode"
:
""
);
}
if
(
ar
->
version
.
abi_ver
!=
ATH6KL_ABI_VERSION
)
{
ath6kl_err
(
"abi version mismatch: host(0x%x), target(0x%x)
\n
"
,
ATH6KL_ABI_VERSION
,
ar
->
version
.
abi_ver
);
...
...
@@ -1448,7 +1508,7 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
if
((
ath6kl_set_host_app_area
(
ar
))
!=
0
)
ath6kl_err
(
"unable to set the host app area
\n
"
);
for
(
i
=
0
;
i
<
MAX_NUM_VIF
;
i
++
)
{
for
(
i
=
0
;
i
<
ar
->
vif_max
;
i
++
)
{
ret
=
ath6kl_target_config_wlan_params
(
ar
,
i
);
if
(
ret
)
goto
err_htc_stop
;
...
...
@@ -1558,7 +1618,7 @@ int ath6kl_core_init(struct ath6kl *ar)
goto
err_node_cleanup
;
}
for
(
i
=
0
;
i
<
MAX_NUM_VIF
;
i
++
)
for
(
i
=
0
;
i
<
ar
->
vif_max
;
i
++
)
ar
->
avail_idx_map
|=
BIT
(
i
);
rtnl_lock
();
...
...
@@ -1603,7 +1663,17 @@ int ath6kl_core_init(struct ath6kl *ar)
ar
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_FW_ROAM
|
WIPHY_FLAG_HAVE_AP_SME
|
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
;
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
|
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
;
if
(
test_bit
(
ATH6KL_FW_CAPABILITY_SCHED_SCAN
,
ar
->
fw_capabilities
))
ar
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_SCHED_SCAN
;
ar
->
wiphy
->
probe_resp_offload
=
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U
;
set_bit
(
FIRST_BOOT
,
&
ar
->
flag
);
...
...
drivers/net/wireless/ath/ath6kl/main.c
View file @
640f5950
...
...
@@ -175,64 +175,6 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
ar
->
cookie_count
++
;
}
/* set the window address register (using 4-byte register access ). */
static
int
ath6kl_set_addrwin_reg
(
struct
ath6kl
*
ar
,
u32
reg_addr
,
u32
addr
)
{
int
status
;
s32
i
;
__le32
addr_val
;
/*
* Write bytes 1,2,3 of the register to set the upper address bytes,
* the LSB is written last to initiate the access cycle
*/
for
(
i
=
1
;
i
<=
3
;
i
++
)
{
/*
* Fill the buffer with the address byte value we want to
* hit 4 times. No need to worry about endianness as the
* same byte is copied to all four bytes of addr_val at
* any time.
*/
memset
((
u8
*
)
&
addr_val
,
((
u8
*
)
&
addr
)[
i
],
4
);
/*
* Hit each byte of the register address with a 4-byte
* write operation to the same address, this is a harmless
* operation.
*/
status
=
hif_read_write_sync
(
ar
,
reg_addr
+
i
,
(
u8
*
)
&
addr_val
,
4
,
HIF_WR_SYNC_BYTE_FIX
);
if
(
status
)
break
;
}
if
(
status
)
{
ath6kl_err
(
"failed to write initial bytes of 0x%x to window reg: 0x%X
\n
"
,
addr
,
reg_addr
);
return
status
;
}
/*
* Write the address register again, this time write the whole
* 4-byte value. The effect here is that the LSB write causes the
* cycle to start, the extra 3 byte write to bytes 1,2,3 has no
* effect since we are writing the same values again
*/
addr_val
=
cpu_to_le32
(
addr
);
status
=
hif_read_write_sync
(
ar
,
reg_addr
,
(
u8
*
)
&
(
addr_val
),
4
,
HIF_WR_SYNC_BYTE_INC
);
if
(
status
)
{
ath6kl_err
(
"failed to write 0x%x to window reg: 0x%X
\n
"
,
addr
,
reg_addr
);
return
status
;
}
return
0
;
}
/*
* Read from the hardware through its diagnostic window. No cooperation
* from the firmware is required for this.
...
...
@@ -241,14 +183,7 @@ int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value)
{
int
ret
;
/* set window register to start read cycle */
ret
=
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_READ_ADDR_ADDRESS
,
address
);
if
(
ret
)
return
ret
;
/* read the data */
ret
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
value
,
sizeof
(
*
value
),
HIF_RD_SYNC_BYTE_INC
);
ret
=
ath6kl_hif_diag_read32
(
ar
,
address
,
value
);
if
(
ret
)
{
ath6kl_warn
(
"failed to read32 through diagnose window: %d
\n
"
,
ret
);
...
...
@@ -266,18 +201,15 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value)
{
int
ret
;
/* set write data */
ret
=
hif_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
&
value
,
sizeof
(
value
),
HIF_WR_SYNC_BYTE_INC
);
ret
=
ath6kl_hif_diag_write32
(
ar
,
address
,
value
);
if
(
ret
)
{
ath6kl_err
(
"failed to write 0x%x during diagnose window to 0x%d
\n
"
,
address
,
value
);
return
ret
;
}
/* set window register, which starts the write cycle */
return
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_WRITE_ADDR_ADDRESS
,
address
);
return
0
;
}
int
ath6kl_diag_read
(
struct
ath6kl
*
ar
,
u32
address
,
void
*
data
,
u32
length
)
...
...
@@ -465,7 +397,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
case
NONE_AUTH
:
if
(
vif
->
prwise_crypto
==
WEP_CRYPT
)
ath6kl_install_static_wep_keys
(
vif
);
break
;
if
(
!
ik
->
valid
||
ik
->
key_type
!=
WAPI_CRYPT
)
break
;
/* for WAPI, we need to set the delayed group key, continue: */
case
WPA_PSK_AUTH
:
case
WPA2_PSK_AUTH
:
case
(
WPA_PSK_AUTH
|
WPA2_PSK_AUTH
):
...
...
@@ -534,6 +468,18 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
wpa_ie
=
pos
;
/* WPS IE */
break
;
/* overrides WPA/RSN IE */
}
}
else
if
(
pos
[
0
]
==
0x44
&&
wpa_ie
==
NULL
)
{
/*
* Note: WAPI Parameter Set IE re-uses Element ID that
* was officially allocated for BSS AC Access Delay. As
* such, we need to be a bit more careful on when
* parsing the frame. However, BSS AC Access Delay
* element is not supposed to be included in
* (Re)Association Request frames, so this should not
* cause problems.
*/
wpa_ie
=
pos
;
/* WAPI IE */
break
;
}
pos
+=
2
+
pos
[
1
];
}
...
...
@@ -581,20 +527,6 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
/* WMI Event handlers */
static
const
char
*
get_hw_id_string
(
u32
id
)
{
switch
(
id
)
{
case
AR6003_REV1_VERSION
:
return
"1.0"
;
case
AR6003_REV2_VERSION
:
return
"2.0"
;
case
AR6003_REV3_VERSION
:
return
"2.1.1"
;
default:
return
"unknown"
;
}
}
void
ath6kl_ready_event
(
void
*
devt
,
u8
*
datap
,
u32
sw_ver
,
u32
abi_ver
)
{
struct
ath6kl
*
ar
=
devt
;
...
...
@@ -617,13 +549,6 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
/* indicate to the waiting thread that the ready event was received */
set_bit
(
WMI_READY
,
&
ar
->
flag
);
wake_up
(
&
ar
->
event_wq
);
if
(
test_and_clear_bit
(
FIRST_BOOT
,
&
ar
->
flag
))
{
ath6kl_info
(
"hw %s fw %s%s
\n
"
,
get_hw_id_string
(
ar
->
wiphy
->
hw_version
),
ar
->
wiphy
->
fw_version
,
test_bit
(
TESTMODE
,
&
ar
->
flag
)
?
" testmode"
:
""
);
}
}
void
ath6kl_scan_complete_evt
(
struct
ath6kl_vif
*
vif
,
int
status
)
...
...
@@ -1077,21 +1002,11 @@ static int ath6kl_open(struct net_device *dev)
static
int
ath6kl_close
(
struct
net_device
*
dev
)
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
netif_stop_queue
(
dev
);
ath6kl_disconnect
(
vif
);
if
(
test_bit
(
WMI_READY
,
&
ar
->
flag
))
{
if
(
ath6kl_wmi_scanparams_cmd
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
0xFFFF
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
))
return
-
EIO
;
}
ath6kl_cfg80211_scan_complete_event
(
vif
,
true
);
ath6kl_cfg80211_stop
(
vif
);
clear_bit
(
WLAN_ENABLED
,
&
vif
->
flags
);
...
...
drivers/net/wireless/ath/ath6kl/sdio.c
View file @
640f5950
...
...
@@ -40,8 +40,12 @@ struct ath6kl_sdio {
struct
bus_request
bus_req
[
BUS_REQUEST_MAX_NUM
];
struct
ath6kl
*
ar
;
u8
*
dma_buffer
;
/* protects access to dma_buffer */
struct
mutex
dma_buffer_mutex
;
/* scatter request list head */
struct
list_head
scat_req
;
...
...
@@ -396,6 +400,7 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
if
(
buf_needs_bounce
(
buf
))
{
if
(
!
ar_sdio
->
dma_buffer
)
return
-
ENOMEM
;
mutex_lock
(
&
ar_sdio
->
dma_buffer_mutex
);
tbuf
=
ar_sdio
->
dma_buffer
;
memcpy
(
tbuf
,
buf
,
len
);
bounced
=
true
;
...
...
@@ -406,6 +411,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
if
((
request
&
HIF_READ
)
&&
bounced
)
memcpy
(
buf
,
tbuf
,
len
);
if
(
bounced
)
mutex_unlock
(
&
ar_sdio
->
dma_buffer_mutex
);
return
ret
;
}
...
...
@@ -799,7 +807,28 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return
ret
;
}
if
((
flags
&
MMC_PM_WAKE_SDIO_IRQ
)
&&
wow
)
{
if
(
!
(
flags
&
MMC_PM_WAKE_SDIO_IRQ
))
goto
deepsleep
;
/* sdio irq wakes up host */
if
(
ar
->
state
==
ATH6KL_STATE_SCHED_SCAN
)
{
ret
=
ath6kl_cfg80211_suspend
(
ar
,
ATH6KL_CFG_SUSPEND_SCHED_SCAN
,
NULL
);
if
(
ret
)
{
ath6kl_warn
(
"Schedule scan suspend failed: %d"
,
ret
);
return
ret
;
}
ret
=
sdio_set_host_pm_flags
(
func
,
MMC_PM_WAKE_SDIO_IRQ
);
if
(
ret
)
ath6kl_warn
(
"set sdio wake irq flag failed: %d
\n
"
,
ret
);
return
ret
;
}
if
(
wow
)
{
/*
* The host sdio controller is capable of keep power and
* sdio irq wake up at this point. It's fine to continue
...
...
@@ -816,6 +845,7 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return
ret
;
}
deepsleep:
return
ath6kl_cfg80211_suspend
(
ar
,
ATH6KL_CFG_SUSPEND_DEEPSLEEP
,
NULL
);
}
...
...
@@ -839,6 +869,8 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
case
ATH6KL_STATE_WOW
:
break
;
case
ATH6KL_STATE_SCHED_SCAN
:
break
;
}
ath6kl_cfg80211_resume
(
ar
);
...
...
@@ -846,6 +878,264 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
return
0
;
}
/* set the window address register (using 4-byte register access ). */
static
int
ath6kl_set_addrwin_reg
(
struct
ath6kl
*
ar
,
u32
reg_addr
,
u32
addr
)
{
int
status
;
u8
addr_val
[
4
];
s32
i
;
/*
* Write bytes 1,2,3 of the register to set the upper address bytes,
* the LSB is written last to initiate the access cycle
*/
for
(
i
=
1
;
i
<=
3
;
i
++
)
{
/*
* Fill the buffer with the address byte value we want to
* hit 4 times.
*/
memset
(
addr_val
,
((
u8
*
)
&
addr
)[
i
],
4
);
/*
* Hit each byte of the register address with a 4-byte
* write operation to the same address, this is a harmless
* operation.
*/
status
=
ath6kl_sdio_read_write_sync
(
ar
,
reg_addr
+
i
,
addr_val
,
4
,
HIF_WR_SYNC_BYTE_FIX
);
if
(
status
)
break
;
}
if
(
status
)
{
ath6kl_err
(
"%s: failed to write initial bytes of 0x%x "
"to window reg: 0x%X
\n
"
,
__func__
,
addr
,
reg_addr
);
return
status
;
}
/*
* Write the address register again, this time write the whole
* 4-byte value. The effect here is that the LSB write causes the
* cycle to start, the extra 3 byte write to bytes 1,2,3 has no
* effect since we are writing the same values again
*/
status
=
ath6kl_sdio_read_write_sync
(
ar
,
reg_addr
,
(
u8
*
)(
&
addr
),
4
,
HIF_WR_SYNC_BYTE_INC
);
if
(
status
)
{
ath6kl_err
(
"%s: failed to write 0x%x to window reg: 0x%X
\n
"
,
__func__
,
addr
,
reg_addr
);
return
status
;
}
return
0
;
}
static
int
ath6kl_sdio_diag_read32
(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
data
)
{
int
status
;
/* set window register to start read cycle */
status
=
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_READ_ADDR_ADDRESS
,
address
);
if
(
status
)
return
status
;
/* read the data */
status
=
ath6kl_sdio_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
data
,
sizeof
(
u32
),
HIF_RD_SYNC_BYTE_INC
);
if
(
status
)
{
ath6kl_err
(
"%s: failed to read from window data addr
\n
"
,
__func__
);
return
status
;
}
return
status
;
}
static
int
ath6kl_sdio_diag_write32
(
struct
ath6kl
*
ar
,
u32
address
,
__le32
data
)
{
int
status
;
u32
val
=
(
__force
u32
)
data
;
/* set write data */
status
=
ath6kl_sdio_read_write_sync
(
ar
,
WINDOW_DATA_ADDRESS
,
(
u8
*
)
&
val
,
sizeof
(
u32
),
HIF_WR_SYNC_BYTE_INC
);
if
(
status
)
{
ath6kl_err
(
"%s: failed to write 0x%x to window data addr
\n
"
,
__func__
,
data
);
return
status
;
}
/* set window register, which starts the write cycle */
return
ath6kl_set_addrwin_reg
(
ar
,
WINDOW_WRITE_ADDR_ADDRESS
,
address
);
}
static
int
ath6kl_sdio_bmi_credits
(
struct
ath6kl
*
ar
)
{
u32
addr
;
unsigned
long
timeout
;
int
ret
;
ar
->
bmi
.
cmd_credits
=
0
;
/* Read the counter register to get the command credits */
addr
=
COUNT_DEC_ADDRESS
+
(
HTC_MAILBOX_NUM_MAX
+
ENDPOINT1
)
*
4
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
(
time_before
(
jiffies
,
timeout
)
&&
!
ar
->
bmi
.
cmd_credits
)
{
/*
* Hit the credit counter with a 4-byte access, the first byte
* read will hit the counter and cause a decrement, while the
* remaining 3 bytes has no effect. The rationale behind this
* is to make all HIF accesses 4-byte aligned.
*/
ret
=
ath6kl_sdio_read_write_sync
(
ar
,
addr
,
(
u8
*
)
&
ar
->
bmi
.
cmd_credits
,
4
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to decrement the command credit "
"count register: %d
\n
"
,
ret
);
return
ret
;
}
/* The counter is only 8 bits.
* Ignore anything in the upper 3 bytes
*/
ar
->
bmi
.
cmd_credits
&=
0xFF
;
}
if
(
!
ar
->
bmi
.
cmd_credits
)
{
ath6kl_err
(
"bmi communication timeout
\n
"
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
int
ath6kl_bmi_get_rx_lkahd
(
struct
ath6kl
*
ar
)
{
unsigned
long
timeout
;
u32
rx_word
=
0
;
int
ret
=
0
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
((
time_before
(
jiffies
,
timeout
))
&&
!
rx_word
)
{
ret
=
ath6kl_sdio_read_write_sync
(
ar
,
RX_LOOKAHEAD_VALID_ADDRESS
,
(
u8
*
)
&
rx_word
,
sizeof
(
rx_word
),
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"unable to read RX_LOOKAHEAD_VALID
\n
"
);
return
ret
;
}
/* all we really want is one bit */
rx_word
&=
(
1
<<
ENDPOINT1
);
}
if
(
!
rx_word
)
{
ath6kl_err
(
"bmi_recv_buf FIFO empty
\n
"
);
return
-
EINVAL
;
}
return
ret
;
}
static
int
ath6kl_sdio_bmi_write
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
int
ret
;
u32
addr
;
ret
=
ath6kl_sdio_bmi_credits
(
ar
);
if
(
ret
)
return
ret
;
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
ath6kl_sdio_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_WR_SYNC_BYTE_INC
);
if
(
ret
)
ath6kl_err
(
"unable to send the bmi data to the device
\n
"
);
return
ret
;
}
static
int
ath6kl_sdio_bmi_read
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
int
ret
;
u32
addr
;
/*
* During normal bootup, small reads may be required.
* Rather than issue an HIF Read and then wait as the Target
* adds successive bytes to the FIFO, we wait here until
* we know that response data is available.
*
* This allows us to cleanly timeout on an unexpected
* Target failure rather than risk problems at the HIF level.
* In particular, this avoids SDIO timeouts and possibly garbage
* data on some host controllers. And on an interconnect
* such as Compact Flash (as well as some SDIO masters) which
* does not provide any indication on data timeout, it avoids
* a potential hang or garbage response.
*
* Synchronization is more difficult for reads larger than the
* size of the MBOX FIFO (128B), because the Target is unable
* to push the 129th byte of data until AFTER the Host posts an
* HIF Read and removes some FIFO data. So for large reads the
* Host proceeds to post an HIF Read BEFORE all the data is
* actually available to read. Fortunately, large BMI reads do
* not occur in practice -- they're supported for debug/development.
*
* So Host/Target BMI synchronization is divided into these cases:
* CASE 1: length < 4
* Should not happen
*
* CASE 2: 4 <= length <= 128
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
* response is available in the the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO
*
* For most uses, a small timeout should be sufficient and we will
* usually see a response quickly; but there may be some unusual
* (debug) cases of BMI_EXECUTE where we want an larger timeout.
* For now, we use an unbounded busy loop while waiting for
* BMI_EXECUTE.
*
* If BMI_EXECUTE ever needs to support longer-latency execution,
* especially in production, this code needs to be enhanced to sleep
* and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
* a function of Host processor speed.
*/
if
(
len
>=
4
)
{
/* NB: Currently, always true */
ret
=
ath6kl_bmi_get_rx_lkahd
(
ar
);
if
(
ret
)
return
ret
;
}
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
ath6kl_sdio_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read the bmi data from the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
void
ath6kl_sdio_stop
(
struct
ath6kl
*
ar
)
{
struct
ath6kl_sdio
*
ar_sdio
=
ath6kl_sdio_priv
(
ar
);
...
...
@@ -890,6 +1180,10 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
.
cleanup_scatter
=
ath6kl_sdio_cleanup_scatter
,
.
suspend
=
ath6kl_sdio_suspend
,
.
resume
=
ath6kl_sdio_resume
,
.
diag_read32
=
ath6kl_sdio_diag_read32
,
.
diag_write32
=
ath6kl_sdio_diag_write32
,
.
bmi_read
=
ath6kl_sdio_bmi_read
,
.
bmi_write
=
ath6kl_sdio_bmi_write
,
.
power_on
=
ath6kl_sdio_power_on
,
.
power_off
=
ath6kl_sdio_power_off
,
.
stop
=
ath6kl_sdio_stop
,
...
...
@@ -958,6 +1252,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
spin_lock_init
(
&
ar_sdio
->
lock
);
spin_lock_init
(
&
ar_sdio
->
scat_lock
);
spin_lock_init
(
&
ar_sdio
->
wr_async_lock
);
mutex_init
(
&
ar_sdio
->
dma_buffer_mutex
);
INIT_LIST_HEAD
(
&
ar_sdio
->
scat_req
);
INIT_LIST_HEAD
(
&
ar_sdio
->
bus_req_freeq
);
...
...
@@ -976,8 +1271,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
}
ar_sdio
->
ar
=
ar
;
ar
->
hif_type
=
ATH6KL_HIF_TYPE_SDIO
;
ar
->
hif_priv
=
ar_sdio
;
ar
->
hif_ops
=
&
ath6kl_sdio_ops
;
ar
->
bmi
.
max_data_size
=
256
;
ath6kl_sdio_set_mbox_info
(
ar
);
...
...
@@ -1027,13 +1324,15 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
static
const
struct
sdio_device_id
ath6kl_sdio_devices
[]
=
{
{
SDIO_DEVICE
(
MANUFACTURER_CODE
,
(
MANUFACTURER_ID_AR6003_BASE
|
0x0
))},
{
SDIO_DEVICE
(
MANUFACTURER_CODE
,
(
MANUFACTURER_ID_AR6003_BASE
|
0x1
))},
{
SDIO_DEVICE
(
MANUFACTURER_CODE
,
(
MANUFACTURER_ID_AR6004_BASE
|
0x0
))},
{
SDIO_DEVICE
(
MANUFACTURER_CODE
,
(
MANUFACTURER_ID_AR6004_BASE
|
0x1
))},
{},
};
MODULE_DEVICE_TABLE
(
sdio
,
ath6kl_sdio_devices
);
static
struct
sdio_driver
ath6kl_sdio_driver
=
{
.
name
=
"ath6kl"
,
.
name
=
"ath6kl
_sdio
"
,
.
id_table
=
ath6kl_sdio_devices
,
.
probe
=
ath6kl_sdio_probe
,
.
remove
=
ath6kl_sdio_remove
,
...
...
@@ -1063,13 +1362,19 @@ MODULE_AUTHOR("Atheros Communications, Inc.");
MODULE_DESCRIPTION
(
"Driver support for Atheros AR600x SDIO devices"
);
MODULE_LICENSE
(
"Dual BSD/GPL"
);
MODULE_FIRMWARE
(
AR6003_REV2_OTP_FILE
);
MODULE_FIRMWARE
(
AR6003_REV2_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6003_REV2_PATCH_FILE
);
MODULE_FIRMWARE
(
AR6003_REV2_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_REV2_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_REV3_OTP_FILE
);
MODULE_FIRMWARE
(
AR6003_REV3_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6003_REV3_PATCH_FILE
);
MODULE_FIRMWARE
(
AR6003_REV3_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_REV3_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_0_OTP_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_0_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_0_PATCH_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_0_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_1_1_OTP_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_1_1_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_1_1_PATCH_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_1_1_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE
);
drivers/net/wireless/ath/ath6kl/target.h
View file @
640f5950
...
...
@@ -20,7 +20,7 @@
#define AR6003_BOARD_DATA_SZ 1024
#define AR6003_BOARD_EXT_DATA_SZ 768
#define AR6004_BOARD_DATA_SZ
7168
#define AR6004_BOARD_DATA_SZ
6144
#define AR6004_BOARD_EXT_DATA_SZ 0
#define RESET_CONTROL_ADDRESS 0x00000000
...
...
@@ -334,20 +334,6 @@ struct host_interest {
(((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \
(((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0))
#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
#define AR6003_REV2_RAM_RESERVE_SIZE 6912
#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
#define AR6003_REV3_RAM_RESERVE_SIZE 512
#define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400
#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000
#define AR6004_REV1_RAM_RESERVE_SIZE 11264
#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500
struct
ath6kl_dbglog_buf
{
...
...
drivers/net/wireless/ath/ath6kl/txrx.c
View file @
640f5950
...
...
@@ -453,11 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
set_bit
(
WMI_CTRL_EP_FULL
,
&
ar
->
flag
);
spin_unlock_bh
(
&
ar
->
lock
);
ath6kl_err
(
"wmi ctrl ep is full
\n
"
);
goto
stop_adhoc_netq
;
return
action
;
}
if
(
packet
->
info
.
tx
.
tag
==
ATH6KL_CONTROL_PKT_TAG
)
goto
stop_adhoc_netq
;
return
action
;
/*
* The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
...
...
@@ -465,20 +465,18 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/
if
(
ar
->
ac_stream_pri_map
[
ar
->
ep2ac_map
[
endpoint
]]
<
ar
->
hiac_stream_active_pri
&&
ar
->
cookie_count
<=
MAX_HI_COOKIE_NUM
)
{
ar
->
cookie_count
<=
MAX_HI_COOKIE_NUM
)
/*
* Give preference to the highest priority stream by
* dropping the packets which overflowed.
*/
action
=
HTC_SEND_FULL_DROP
;
goto
stop_adhoc_netq
;
}
stop_adhoc_netq:
/* FIXME: Locking */
spin_lock_bh
(
&
ar
->
list_lock
);
list_for_each_entry
(
vif
,
&
ar
->
vif_list
,
list
)
{
if
(
vif
->
nw_type
==
ADHOC_NETWORK
)
{
if
(
vif
->
nw_type
==
ADHOC_NETWORK
||
action
!=
HTC_SEND_FULL_DROP
)
{
spin_unlock_bh
(
&
ar
->
list_lock
);
spin_lock_bh
(
&
vif
->
if_lock
);
...
...
@@ -543,7 +541,7 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
int
status
;
enum
htc_endpoint_id
eid
;
bool
wake_event
=
false
;
bool
flushing
[
MAX_NUM_VIF
]
=
{
false
};
bool
flushing
[
ATH6KL_VIF_MAX
]
=
{
false
};
u8
if_idx
;
struct
ath6kl_vif
*
vif
;
...
...
@@ -571,8 +569,6 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
if
(
!
skb
||
!
skb
->
data
)
goto
fatal
;
packet
->
buf
=
skb
->
data
;
__skb_queue_tail
(
&
skb_queue
,
skb
);
if
(
!
status
&&
(
packet
->
act_len
!=
skb
->
len
))
...
...
@@ -593,10 +589,10 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
if
(
eid
==
ar
->
ctrl_ep
)
{
if_idx
=
wmi_cmd_hdr_get_if_idx
(
(
struct
wmi_cmd_hdr
*
)
skb
->
data
);
(
struct
wmi_cmd_hdr
*
)
packet
->
buf
);
}
else
{
if_idx
=
wmi_data_hdr_get_if_idx
(
(
struct
wmi_data_hdr
*
)
skb
->
data
);
(
struct
wmi_data_hdr
*
)
packet
->
buf
);
}
vif
=
ath6kl_get_vif_by_index
(
ar
,
if_idx
);
...
...
drivers/net/wireless/ath/ath6kl/usb.c
0 → 100644
View file @
640f5950
/*
* Copyright (c) 2007-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
#include <linux/usb.h>
#include "debug.h"
#include "core.h"
/* usb device object */
struct
ath6kl_usb
{
struct
usb_device
*
udev
;
struct
usb_interface
*
interface
;
u8
*
diag_cmd_buffer
;
u8
*
diag_resp_buffer
;
struct
ath6kl
*
ar
;
};
/* diagnostic command defnitions */
#define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1
#define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2
#define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3
#define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4
#define ATH6KL_USB_CTRL_DIAG_CC_READ 0
#define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1
struct
ath6kl_usb_ctrl_diag_cmd_write
{
__le32
cmd
;
__le32
address
;
__le32
value
;
__le32
_pad
[
1
];
}
__packed
;
struct
ath6kl_usb_ctrl_diag_cmd_read
{
__le32
cmd
;
__le32
address
;
}
__packed
;
struct
ath6kl_usb_ctrl_diag_resp_read
{
__le32
value
;
}
__packed
;
#define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write))
#define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read))
static
void
ath6kl_usb_destroy
(
struct
ath6kl_usb
*
ar_usb
)
{
usb_set_intfdata
(
ar_usb
->
interface
,
NULL
);
kfree
(
ar_usb
->
diag_cmd_buffer
);
kfree
(
ar_usb
->
diag_resp_buffer
);
kfree
(
ar_usb
);
}
static
struct
ath6kl_usb
*
ath6kl_usb_create
(
struct
usb_interface
*
interface
)
{
struct
ath6kl_usb
*
ar_usb
=
NULL
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
interface
);
int
status
=
0
;
ar_usb
=
kzalloc
(
sizeof
(
struct
ath6kl_usb
),
GFP_KERNEL
);
if
(
ar_usb
==
NULL
)
goto
fail_ath6kl_usb_create
;
memset
(
ar_usb
,
0
,
sizeof
(
struct
ath6kl_usb
));
usb_set_intfdata
(
interface
,
ar_usb
);
ar_usb
->
udev
=
dev
;
ar_usb
->
interface
=
interface
;
ar_usb
->
diag_cmd_buffer
=
kzalloc
(
ATH6KL_USB_MAX_DIAG_CMD
,
GFP_KERNEL
);
if
(
ar_usb
->
diag_cmd_buffer
==
NULL
)
{
status
=
-
ENOMEM
;
goto
fail_ath6kl_usb_create
;
}
ar_usb
->
diag_resp_buffer
=
kzalloc
(
ATH6KL_USB_MAX_DIAG_RESP
,
GFP_KERNEL
);
if
(
ar_usb
->
diag_resp_buffer
==
NULL
)
{
status
=
-
ENOMEM
;
goto
fail_ath6kl_usb_create
;
}
fail_ath6kl_usb_create:
if
(
status
!=
0
)
{
ath6kl_usb_destroy
(
ar_usb
);
ar_usb
=
NULL
;
}
return
ar_usb
;
}
static
void
ath6kl_usb_device_detached
(
struct
usb_interface
*
interface
)
{
struct
ath6kl_usb
*
ar_usb
;
ar_usb
=
usb_get_intfdata
(
interface
);
if
(
ar_usb
==
NULL
)
return
;
ath6kl_stop_txrx
(
ar_usb
->
ar
);
ath6kl_core_cleanup
(
ar_usb
->
ar
);
ath6kl_usb_destroy
(
ar_usb
);
}
static
int
ath6kl_usb_submit_ctrl_out
(
struct
ath6kl_usb
*
ar_usb
,
u8
req
,
u16
value
,
u16
index
,
void
*
data
,
u32
size
)
{
u8
*
buf
=
NULL
;
int
ret
;
if
(
size
>
0
)
{
buf
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
buf
==
NULL
)
return
-
ENOMEM
;
memcpy
(
buf
,
data
,
size
);
}
/* note: if successful returns number of bytes transfered */
ret
=
usb_control_msg
(
ar_usb
->
udev
,
usb_sndctrlpipe
(
ar_usb
->
udev
,
0
),
req
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
value
,
index
,
buf
,
size
,
1000
);
if
(
ret
<
0
)
{
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"%s failed,result = %d
\n
"
,
__func__
,
ret
);
}
kfree
(
buf
);
return
0
;
}
static
int
ath6kl_usb_submit_ctrl_in
(
struct
ath6kl_usb
*
ar_usb
,
u8
req
,
u16
value
,
u16
index
,
void
*
data
,
u32
size
)
{
u8
*
buf
=
NULL
;
int
ret
;
if
(
size
>
0
)
{
buf
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
buf
==
NULL
)
return
-
ENOMEM
;
}
/* note: if successful returns number of bytes transfered */
ret
=
usb_control_msg
(
ar_usb
->
udev
,
usb_rcvctrlpipe
(
ar_usb
->
udev
,
0
),
req
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
value
,
index
,
buf
,
size
,
2
*
HZ
);
if
(
ret
<
0
)
{
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"%s failed,result = %d
\n
"
,
__func__
,
ret
);
}
memcpy
((
u8
*
)
data
,
buf
,
size
);
kfree
(
buf
);
return
0
;
}
static
int
ath6kl_usb_ctrl_msg_exchange
(
struct
ath6kl_usb
*
ar_usb
,
u8
req_val
,
u8
*
req_buf
,
u32
req_len
,
u8
resp_val
,
u8
*
resp_buf
,
u32
*
resp_len
)
{
int
ret
;
/* send command */
ret
=
ath6kl_usb_submit_ctrl_out
(
ar_usb
,
req_val
,
0
,
0
,
req_buf
,
req_len
);
if
(
ret
!=
0
)
return
ret
;
if
(
resp_buf
==
NULL
)
{
/* no expected response */
return
ret
;
}
/* get response */
ret
=
ath6kl_usb_submit_ctrl_in
(
ar_usb
,
resp_val
,
0
,
0
,
resp_buf
,
*
resp_len
);
return
ret
;
}
static
int
ath6kl_usb_diag_read32
(
struct
ath6kl
*
ar
,
u32
address
,
u32
*
data
)
{
struct
ath6kl_usb
*
ar_usb
=
ar
->
hif_priv
;
struct
ath6kl_usb_ctrl_diag_resp_read
*
resp
;
struct
ath6kl_usb_ctrl_diag_cmd_read
*
cmd
;
u32
resp_len
;
int
ret
;
cmd
=
(
struct
ath6kl_usb_ctrl_diag_cmd_read
*
)
ar_usb
->
diag_cmd_buffer
;
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
cmd
=
ATH6KL_USB_CTRL_DIAG_CC_READ
;
cmd
->
address
=
cpu_to_le32
(
address
);
resp_len
=
sizeof
(
*
resp
);
ret
=
ath6kl_usb_ctrl_msg_exchange
(
ar_usb
,
ATH6KL_USB_CONTROL_REQ_DIAG_CMD
,
(
u8
*
)
cmd
,
sizeof
(
struct
ath6kl_usb_ctrl_diag_cmd_write
),
ATH6KL_USB_CONTROL_REQ_DIAG_RESP
,
ar_usb
->
diag_resp_buffer
,
&
resp_len
);
if
(
ret
)
return
ret
;
resp
=
(
struct
ath6kl_usb_ctrl_diag_resp_read
*
)
ar_usb
->
diag_resp_buffer
;
*
data
=
le32_to_cpu
(
resp
->
value
);
return
ret
;
}
static
int
ath6kl_usb_diag_write32
(
struct
ath6kl
*
ar
,
u32
address
,
__le32
data
)
{
struct
ath6kl_usb
*
ar_usb
=
ar
->
hif_priv
;
struct
ath6kl_usb_ctrl_diag_cmd_write
*
cmd
;
cmd
=
(
struct
ath6kl_usb_ctrl_diag_cmd_write
*
)
ar_usb
->
diag_cmd_buffer
;
memset
(
cmd
,
0
,
sizeof
(
struct
ath6kl_usb_ctrl_diag_cmd_write
));
cmd
->
cmd
=
cpu_to_le32
(
ATH6KL_USB_CTRL_DIAG_CC_WRITE
);
cmd
->
address
=
cpu_to_le32
(
address
);
cmd
->
value
=
data
;
return
ath6kl_usb_ctrl_msg_exchange
(
ar_usb
,
ATH6KL_USB_CONTROL_REQ_DIAG_CMD
,
(
u8
*
)
cmd
,
sizeof
(
*
cmd
),
0
,
NULL
,
NULL
);
}
static
int
ath6kl_usb_bmi_read
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
struct
ath6kl_usb
*
ar_usb
=
ar
->
hif_priv
;
int
ret
;
/* get response */
ret
=
ath6kl_usb_submit_ctrl_in
(
ar_usb
,
ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP
,
0
,
0
,
buf
,
len
);
if
(
ret
!=
0
)
{
ath6kl_err
(
"Unable to read the bmi data from the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
ath6kl_usb_bmi_write
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
struct
ath6kl_usb
*
ar_usb
=
ar
->
hif_priv
;
int
ret
;
/* send command */
ret
=
ath6kl_usb_submit_ctrl_out
(
ar_usb
,
ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD
,
0
,
0
,
buf
,
len
);
if
(
ret
!=
0
)
{
ath6kl_err
(
"unable to send the bmi data to the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
ath6kl_usb_power_on
(
struct
ath6kl
*
ar
)
{
return
0
;
}
static
int
ath6kl_usb_power_off
(
struct
ath6kl
*
ar
)
{
return
0
;
}
static
const
struct
ath6kl_hif_ops
ath6kl_usb_ops
=
{
.
diag_read32
=
ath6kl_usb_diag_read32
,
.
diag_write32
=
ath6kl_usb_diag_write32
,
.
bmi_read
=
ath6kl_usb_bmi_read
,
.
bmi_write
=
ath6kl_usb_bmi_write
,
.
power_on
=
ath6kl_usb_power_on
,
.
power_off
=
ath6kl_usb_power_off
,
};
/* ath6kl usb driver registered functions */
static
int
ath6kl_usb_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
interface
);
struct
ath6kl
*
ar
;
struct
ath6kl_usb
*
ar_usb
=
NULL
;
int
vendor_id
,
product_id
;
int
ret
=
0
;
usb_get_dev
(
dev
);
vendor_id
=
le16_to_cpu
(
dev
->
descriptor
.
idVendor
);
product_id
=
le16_to_cpu
(
dev
->
descriptor
.
idProduct
);
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"vendor_id = %04x
\n
"
,
vendor_id
);
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"product_id = %04x
\n
"
,
product_id
);
if
(
interface
->
cur_altsetting
)
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"USB Interface %d
\n
"
,
interface
->
cur_altsetting
->
desc
.
bInterfaceNumber
);
if
(
dev
->
speed
==
USB_SPEED_HIGH
)
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"USB 2.0 Host
\n
"
);
else
ath6kl_dbg
(
ATH6KL_DBG_USB
,
"USB 1.1 Host
\n
"
);
ar_usb
=
ath6kl_usb_create
(
interface
);
if
(
ar_usb
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
err_usb_put
;
}
ar
=
ath6kl_core_alloc
(
&
ar_usb
->
udev
->
dev
);
if
(
ar
==
NULL
)
{
ath6kl_err
(
"Failed to alloc ath6kl core
\n
"
);
ret
=
-
ENOMEM
;
goto
err_usb_destroy
;
}
ar
->
hif_priv
=
ar_usb
;
ar
->
hif_type
=
ATH6KL_HIF_TYPE_USB
;
ar
->
hif_ops
=
&
ath6kl_usb_ops
;
ar
->
mbox_info
.
block_size
=
16
;
ar
->
bmi
.
max_data_size
=
252
;
ar_usb
->
ar
=
ar
;
ret
=
ath6kl_core_init
(
ar
);
if
(
ret
)
{
ath6kl_err
(
"Failed to init ath6kl core: %d
\n
"
,
ret
);
goto
err_core_free
;
}
return
ret
;
err_core_free:
ath6kl_core_free
(
ar
);
err_usb_destroy:
ath6kl_usb_destroy
(
ar_usb
);
err_usb_put:
usb_put_dev
(
dev
);
return
ret
;
}
static
void
ath6kl_usb_remove
(
struct
usb_interface
*
interface
)
{
usb_put_dev
(
interface_to_usbdev
(
interface
));
ath6kl_usb_device_detached
(
interface
);
}
/* table of devices that work with this driver */
static
struct
usb_device_id
ath6kl_usb_ids
[]
=
{
{
USB_DEVICE
(
0x0cf3
,
0x9374
)},
{
/* Terminating entry */
},
};
MODULE_DEVICE_TABLE
(
usb
,
ath6kl_usb_ids
);
static
struct
usb_driver
ath6kl_usb_driver
=
{
.
name
=
"ath6kl_usb"
,
.
probe
=
ath6kl_usb_probe
,
.
disconnect
=
ath6kl_usb_remove
,
.
id_table
=
ath6kl_usb_ids
,
};
static
int
ath6kl_usb_init
(
void
)
{
usb_register
(
&
ath6kl_usb_driver
);
return
0
;
}
static
void
ath6kl_usb_exit
(
void
)
{
usb_deregister
(
&
ath6kl_usb_driver
);
}
module_init
(
ath6kl_usb_init
);
module_exit
(
ath6kl_usb_exit
);
MODULE_AUTHOR
(
"Atheros Communications, Inc."
);
MODULE_DESCRIPTION
(
"Driver support for Atheros AR600x USB devices"
);
MODULE_LICENSE
(
"Dual BSD/GPL"
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_FIRMWARE_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_BOARD_DATA_FILE
);
MODULE_FIRMWARE
(
AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE
);
drivers/net/wireless/ath/ath6kl/wmi.c
View file @
640f5950
...
...
@@ -85,7 +85,7 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
{
struct
ath6kl_vif
*
vif
,
*
found
=
NULL
;
if
(
WARN_ON
(
if_idx
>
(
MAX_NUM_VIF
-
1
)))
if
(
WARN_ON
(
if_idx
>
(
ar
->
vif_max
-
1
)))
return
NULL
;
/* FIXME: Locking */
...
...
@@ -187,7 +187,7 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
struct
wmi_data_hdr
*
data_hdr
;
int
ret
;
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
MAX_NUM_VIF
-
1
)))
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
wmi
->
parent_dev
->
vif_max
-
1
)))
return
-
EINVAL
;
if
(
tx_meta_info
)
{
...
...
@@ -977,6 +977,13 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len,
return
0
;
}
void
ath6kl_wmi_sscan_timer
(
unsigned
long
ptr
)
{
struct
ath6kl_vif
*
vif
=
(
struct
ath6kl_vif
*
)
ptr
;
cfg80211_sched_scan_results
(
vif
->
ar
->
wiphy
);
}
static
int
ath6kl_wmi_bssinfo_event_rx
(
struct
wmi
*
wmi
,
u8
*
datap
,
int
len
,
struct
ath6kl_vif
*
vif
)
{
...
...
@@ -1066,6 +1073,21 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
return
-
ENOMEM
;
cfg80211_put_bss
(
bss
);
/*
* Firmware doesn't return any event when scheduled scan has
* finished, so we need to use a timer to find out when there are
* no more results.
*
* The timer is started from the first bss info received, otherwise
* the timer would not ever fire if the scan interval is short
* enough.
*/
if
(
ar
->
state
==
ATH6KL_STATE_SCHED_SCAN
&&
!
timer_pending
(
&
vif
->
sched_scan_timer
))
{
mod_timer
(
&
vif
->
sched_scan_timer
,
jiffies
+
msecs_to_jiffies
(
ATH6KL_SCHED_SCAN_RESULT_DELAY
));
}
return
0
;
}
...
...
@@ -1620,7 +1642,7 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
int
ret
;
u16
info1
;
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
(
MAX_NUM_VIF
-
1
))))
if
(
WARN_ON
(
skb
==
NULL
||
(
if_idx
>
(
wmi
->
parent_dev
->
vif_max
-
1
))))
return
-
EINVAL
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"wmi tx id %d len %d flag %d
\n
"
,
...
...
@@ -1682,7 +1704,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
u8
pairwise_crypto_len
,
enum
crypto_type
group_crypto
,
u8
group_crypto_len
,
int
ssid_len
,
u8
*
ssid
,
u8
*
bssid
,
u16
channel
,
u32
ctrl_flags
)
u8
*
bssid
,
u16
channel
,
u32
ctrl_flags
,
u8
nw_subtype
)
{
struct
sk_buff
*
skb
;
struct
wmi_connect_cmd
*
cc
;
...
...
@@ -1722,6 +1745,7 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
cc
->
grp_crypto_len
=
group_crypto_len
;
cc
->
ch
=
cpu_to_le16
(
channel
);
cc
->
ctrl_flags
=
cpu_to_le32
(
ctrl_flags
);
cc
->
nw_subtype
=
nw_subtype
;
if
(
bssid
!=
NULL
)
memcpy
(
cc
->
bssid
,
bssid
,
ETH_ALEN
);
...
...
@@ -1774,6 +1798,72 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
return
ret
;
}
int
ath6kl_wmi_beginscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
,
u32
no_cck
,
u32
*
rates
)
{
struct
sk_buff
*
skb
;
struct
wmi_begin_scan_cmd
*
sc
;
s8
size
;
int
i
,
band
,
ret
;
struct
ath6kl
*
ar
=
wmi
->
parent_dev
;
int
num_rates
;
size
=
sizeof
(
struct
wmi_begin_scan_cmd
);
if
((
scan_type
!=
WMI_LONG_SCAN
)
&&
(
scan_type
!=
WMI_SHORT_SCAN
))
return
-
EINVAL
;
if
(
num_chan
>
WMI_MAX_CHANNELS
)
return
-
EINVAL
;
if
(
num_chan
)
size
+=
sizeof
(
u16
)
*
(
num_chan
-
1
);
skb
=
ath6kl_wmi_get_new_buf
(
size
);
if
(
!
skb
)
return
-
ENOMEM
;
sc
=
(
struct
wmi_begin_scan_cmd
*
)
skb
->
data
;
sc
->
scan_type
=
scan_type
;
sc
->
force_fg_scan
=
cpu_to_le32
(
force_fgscan
);
sc
->
is_legacy
=
cpu_to_le32
(
is_legacy
);
sc
->
home_dwell_time
=
cpu_to_le32
(
home_dwell_time
);
sc
->
force_scan_intvl
=
cpu_to_le32
(
force_scan_interval
);
sc
->
no_cck
=
cpu_to_le32
(
no_cck
);
sc
->
num_ch
=
num_chan
;
for
(
band
=
0
;
band
<
IEEE80211_NUM_BANDS
;
band
++
)
{
struct
ieee80211_supported_band
*
sband
=
ar
->
wiphy
->
bands
[
band
];
u32
ratemask
=
rates
[
band
];
u8
*
supp_rates
=
sc
->
supp_rates
[
band
].
rates
;
num_rates
=
0
;
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
if
((
BIT
(
i
)
&
ratemask
)
==
0
)
continue
;
/* skip rate */
supp_rates
[
num_rates
++
]
=
(
u8
)
(
sband
->
bitrates
[
i
].
bitrate
/
5
);
}
sc
->
supp_rates
[
band
].
nrates
=
num_rates
;
}
for
(
i
=
0
;
i
<
num_chan
;
i
++
)
sc
->
ch_list
[
i
]
=
cpu_to_le16
(
ch_list
[
i
]);
ret
=
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_BEGIN_SCAN_CMDID
,
NO_SYNC_WMIFLAG
);
return
ret
;
}
/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
* ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
* mgmt operations using station interface.
*/
int
ath6kl_wmi_startscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
...
...
@@ -2940,7 +3030,10 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
p
=
(
struct
wmi_set_appie_cmd
*
)
skb
->
data
;
p
->
mgmt_frm_type
=
mgmt_frm_type
;
p
->
ie_len
=
ie_len
;
memcpy
(
p
->
ie_info
,
ie
,
ie_len
);
if
(
ie
!=
NULL
&&
ie_len
>
0
)
memcpy
(
p
->
ie_info
,
ie
,
ie_len
);
return
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_SET_APPIE_CMDID
,
NO_SYNC_WMIFLAG
);
}
...
...
@@ -2981,6 +3074,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
NO_SYNC_WMIFLAG
);
}
/* ath6kl_wmi_send_action_cmd is to be deprecated. Use
* ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P
* mgmt operations using station interface.
*/
int
ath6kl_wmi_send_action_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
)
{
...
...
@@ -3018,14 +3115,57 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_send_mgmt_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
,
u32
no_cck
)
{
struct
sk_buff
*
skb
;
struct
wmi_send_mgmt_cmd
*
p
;
u8
*
buf
;
if
(
wait
)
return
-
EINVAL
;
/* Offload for wait not supported */
buf
=
kmalloc
(
data_len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
)
+
data_len
);
if
(
!
skb
)
{
kfree
(
buf
);
return
-
ENOMEM
;
}
kfree
(
wmi
->
last_mgmt_tx_frame
);
memcpy
(
buf
,
data
,
data_len
);
wmi
->
last_mgmt_tx_frame
=
buf
;
wmi
->
last_mgmt_tx_frame_len
=
data_len
;
ath6kl_dbg
(
ATH6KL_DBG_WMI
,
"send_action_cmd: id=%u freq=%u wait=%u "
"len=%u
\n
"
,
id
,
freq
,
wait
,
data_len
);
p
=
(
struct
wmi_send_mgmt_cmd
*
)
skb
->
data
;
p
->
id
=
cpu_to_le32
(
id
);
p
->
freq
=
cpu_to_le32
(
freq
);
p
->
wait
=
cpu_to_le32
(
wait
);
p
->
no_cck
=
cpu_to_le32
(
no_cck
);
p
->
len
=
cpu_to_le16
(
data_len
);
memcpy
(
p
->
data
,
data
,
data_len
);
return
ath6kl_wmi_cmd_send
(
wmi
,
if_idx
,
skb
,
WMI_SEND_MGMT_CMDID
,
NO_SYNC_WMIFLAG
);
}
int
ath6kl_wmi_send_probe_response_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
freq
,
const
u8
*
dst
,
const
u8
*
data
,
u16
data_len
)
{
struct
sk_buff
*
skb
;
struct
wmi_p2p_probe_response_cmd
*
p
;
size_t
cmd_len
=
sizeof
(
*
p
)
+
data_len
;
skb
=
ath6kl_wmi_get_new_buf
(
sizeof
(
*
p
)
+
data_len
);
if
(
data_len
==
0
)
cmd_len
++
;
/* work around target minimum length requirement */
skb
=
ath6kl_wmi_get_new_buf
(
cmd_len
);
if
(
!
skb
)
return
-
ENOMEM
;
...
...
drivers/net/wireless/ath/ath6kl/wmi.h
View file @
640f5950
...
...
@@ -329,6 +329,10 @@ enum wmi_cmd_id {
WMI_SYNCHRONIZE_CMDID
,
WMI_CREATE_PSTREAM_CMDID
,
WMI_DELETE_PSTREAM_CMDID
,
/* WMI_START_SCAN_CMDID is to be deprecated. Use
* WMI_BEGIN_SCAN_CMDID instead. The new cmd supports P2P mgmt
* operations using station interface.
*/
WMI_START_SCAN_CMDID
,
WMI_SET_SCAN_PARAMS_CMDID
,
WMI_SET_BSS_FILTER_CMDID
,
...
...
@@ -542,12 +546,61 @@ enum wmi_cmd_id {
WMI_GTK_OFFLOAD_OP_CMDID
,
WMI_REMAIN_ON_CHNL_CMDID
,
WMI_CANCEL_REMAIN_ON_CHNL_CMDID
,
/* WMI_SEND_ACTION_CMDID is to be deprecated. Use
* WMI_SEND_MGMT_CMDID instead. The new cmd supports P2P mgmt
* operations using station interface.
*/
WMI_SEND_ACTION_CMDID
,
WMI_PROBE_REQ_REPORT_CMDID
,
WMI_DISABLE_11B_RATES_CMDID
,
WMI_SEND_PROBE_RESPONSE_CMDID
,
WMI_GET_P2P_INFO_CMDID
,
WMI_AP_JOIN_BSS_CMDID
,
WMI_SMPS_ENABLE_CMDID
,
WMI_SMPS_CONFIG_CMDID
,
WMI_SET_RATECTRL_PARM_CMDID
,
/* LPL specific commands*/
WMI_LPL_FORCE_ENABLE_CMDID
,
WMI_LPL_SET_POLICY_CMDID
,
WMI_LPL_GET_POLICY_CMDID
,
WMI_LPL_GET_HWSTATE_CMDID
,
WMI_LPL_SET_PARAMS_CMDID
,
WMI_LPL_GET_PARAMS_CMDID
,
WMI_SET_BUNDLE_PARAM_CMDID
,
/*GreenTx specific commands*/
WMI_GREENTX_PARAMS_CMDID
,
WMI_RTT_MEASREQ_CMDID
,
WMI_RTT_CAPREQ_CMDID
,
WMI_RTT_STATUSREQ_CMDID
,
/* WPS Commands */
WMI_WPS_START_CMDID
,
WMI_GET_WPS_STATUS_CMDID
,
/* More P2P commands */
WMI_SET_NOA_CMDID
,
WMI_GET_NOA_CMDID
,
WMI_SET_OPPPS_CMDID
,
WMI_GET_OPPPS_CMDID
,
WMI_ADD_PORT_CMDID
,
WMI_DEL_PORT_CMDID
,
/* 802.11w cmd */
WMI_SET_RSN_CAP_CMDID
,
WMI_GET_RSN_CAP_CMDID
,
WMI_SET_IGTK_CMDID
,
WMI_RX_FILTER_COALESCE_FILTER_OP_CMDID
,
WMI_RX_FILTER_SET_FRAME_TEST_LIST_CMDID
,
WMI_SEND_MGMT_CMDID
,
WMI_BEGIN_SCAN_CMDID
,
};
enum
wmi_mgmt_frame_type
{
...
...
@@ -567,6 +620,14 @@ enum network_type {
AP_NETWORK
=
0x10
,
};
enum
network_subtype
{
SUBTYPE_NONE
,
SUBTYPE_BT
,
SUBTYPE_P2PDEV
,
SUBTYPE_P2PCLIENT
,
SUBTYPE_P2PGO
,
};
enum
dot11_auth_mode
{
OPEN_AUTH
=
0x01
,
SHARED_AUTH
=
0x02
,
...
...
@@ -639,6 +700,7 @@ struct wmi_connect_cmd {
__le16
ch
;
u8
bssid
[
ETH_ALEN
];
__le32
ctrl_flags
;
u8
nw_subtype
;
}
__packed
;
/* WMI_RECONNECT_CMDID */
...
...
@@ -726,7 +788,12 @@ enum wmi_scan_type {
WMI_SHORT_SCAN
=
1
,
};
struct
wmi_start_scan_cmd
{
struct
wmi_supp_rates
{
u8
nrates
;
u8
rates
[
ATH6KL_RATE_MAXSIZE
];
};
struct
wmi_begin_scan_cmd
{
__le32
force_fg_scan
;
/* for legacy cisco AP compatibility */
...
...
@@ -738,9 +805,15 @@ struct wmi_start_scan_cmd {
/* time interval between scans (msec) */
__le32
force_scan_intvl
;
/* no CCK rates */
__le32
no_cck
;
/* enum wmi_scan_type */
u8
scan_type
;
/* Supported rates to advertise in the probe request frames */
struct
wmi_supp_rates
supp_rates
[
IEEE80211_NUM_BANDS
];
/* how many channels follow */
u8
num_ch
;
...
...
@@ -748,8 +821,31 @@ struct wmi_start_scan_cmd {
__le16
ch_list
[
1
];
}
__packed
;
/* WMI_SET_SCAN_PARAMS_CMDID */
#define WMI_SHORTSCANRATIO_DEFAULT 3
/* wmi_start_scan_cmd is to be deprecated. Use
* wmi_begin_scan_cmd instead. The new structure supports P2P mgmt
* operations using station interface.
*/
struct
wmi_start_scan_cmd
{
__le32
force_fg_scan
;
/* for legacy cisco AP compatibility */
__le32
is_legacy
;
/* max duration in the home channel(msec) */
__le32
home_dwell_time
;
/* time interval between scans (msec) */
__le32
force_scan_intvl
;
/* enum wmi_scan_type */
u8
scan_type
;
/* how many channels follow */
u8
num_ch
;
/* channels in Mhz */
__le16
ch_list
[
1
];
}
__packed
;
/*
* Warning: scan control flag value of 0xFF is used to disable
...
...
@@ -783,13 +879,6 @@ enum wmi_scan_ctrl_flags_bits {
ENABLE_SCAN_ABORT_EVENT
=
0x40
};
#define DEFAULT_SCAN_CTRL_FLAGS \
(CONNECT_SCAN_CTRL_FLAGS | \
SCAN_CONNECTED_CTRL_FLAGS | \
ACTIVE_SCAN_CTRL_FLAGS | \
ROAM_SCAN_CTRL_FLAGS | \
ENABLE_AUTO_CTRL_FLAGS)
struct
wmi_scan_params_cmd
{
/* sec */
__le16
fg_start_period
;
...
...
@@ -1818,7 +1907,7 @@ struct wmi_set_ip_cmd {
}
__packed
;
enum
ath6kl_wow_filters
{
WOW_FILTER_SSID
=
BIT
(
0
),
WOW_FILTER_SSID
=
BIT
(
1
),
WOW_FILTER_OPTION_MAGIC_PACKET
=
BIT
(
2
),
WOW_FILTER_OPTION_EAP_REQ
=
BIT
(
3
),
WOW_FILTER_OPTION_PATTERNS
=
BIT
(
4
),
...
...
@@ -1963,7 +2052,7 @@ struct wmi_tx_complete_event {
* !!! Warning !!!
* -Changing the following values needs compilation of both driver and firmware
*/
#define AP_MAX_NUM_STA
8
#define AP_MAX_NUM_STA
10
/* Spl. AID used to set DTIM flag in the beacons */
#define MCAST_AID 0xFF
...
...
@@ -2046,6 +2135,10 @@ struct wmi_remain_on_chnl_cmd {
__le32
duration
;
}
__packed
;
/* wmi_send_action_cmd is to be deprecated. Use
* wmi_send_mgmt_cmd instead. The new structure supports P2P mgmt
* operations using station interface.
*/
struct
wmi_send_action_cmd
{
__le32
id
;
__le32
freq
;
...
...
@@ -2054,6 +2147,15 @@ struct wmi_send_action_cmd {
u8
data
[
0
];
}
__packed
;
struct
wmi_send_mgmt_cmd
{
__le32
id
;
__le32
freq
;
__le32
wait
;
__le32
no_cck
;
__le16
len
;
u8
data
[
0
];
}
__packed
;
struct
wmi_tx_status_event
{
__le32
id
;
u8
ack_status
;
...
...
@@ -2242,7 +2344,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
u8
pairwise_crypto_len
,
enum
crypto_type
group_crypto
,
u8
group_crypto_len
,
int
ssid_len
,
u8
*
ssid
,
u8
*
bssid
,
u16
channel
,
u32
ctrl_flags
);
u8
*
bssid
,
u16
channel
,
u32
ctrl_flags
,
u8
nw_subtype
);
int
ath6kl_wmi_reconnect_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u8
*
bssid
,
u16
channel
);
...
...
@@ -2252,6 +2355,14 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
);
int
ath6kl_wmi_beginscan_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
enum
wmi_scan_type
scan_type
,
u32
force_fgscan
,
u32
is_legacy
,
u32
home_dwell_time
,
u32
force_scan_interval
,
s8
num_chan
,
u16
*
ch_list
,
u32
no_cck
,
u32
*
rates
);
int
ath6kl_wmi_scanparams_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u16
fg_start_sec
,
u16
fg_end_sec
,
u16
bg_sec
,
u16
minact_chdw_msec
,
u16
maxact_chdw_msec
,
...
...
@@ -2346,6 +2457,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
int
ath6kl_wmi_send_action_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
);
int
ath6kl_wmi_send_mgmt_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
id
,
u32
freq
,
u32
wait
,
const
u8
*
data
,
u16
data_len
,
u32
no_cck
);
int
ath6kl_wmi_send_probe_response_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u32
freq
,
const
u8
*
dst
,
const
u8
*
data
,
u16
data_len
);
...
...
@@ -2359,6 +2474,8 @@ int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx);
int
ath6kl_wmi_set_appie_cmd
(
struct
wmi
*
wmi
,
u8
if_idx
,
u8
mgmt_frm_type
,
const
u8
*
ie
,
u8
ie_len
);
void
ath6kl_wmi_sscan_timer
(
unsigned
long
ptr
);
struct
ath6kl_vif
*
ath6kl_get_vif_by_index
(
struct
ath6kl
*
ar
,
u8
if_idx
);
void
*
ath6kl_wmi_init
(
struct
ath6kl
*
devt
);
void
ath6kl_wmi_shutdown
(
struct
wmi
*
wmi
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment