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
bf34e683
Commit
bf34e683
authored
Jun 08, 2012
by
Luciano Coelho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wl12xx-next' into for-linville
parents
2eb278e0
3e3947ff
Changes
46
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
4818 additions
and
956 deletions
+4818
-956
drivers/net/wireless/ti/Kconfig
drivers/net/wireless/ti/Kconfig
+1
-0
drivers/net/wireless/ti/Makefile
drivers/net/wireless/ti/Makefile
+1
-0
drivers/net/wireless/ti/wl12xx/Makefile
drivers/net/wireless/ti/wl12xx/Makefile
+1
-1
drivers/net/wireless/ti/wl12xx/acx.h
drivers/net/wireless/ti/wl12xx/acx.h
+237
-0
drivers/net/wireless/ti/wl12xx/cmd.c
drivers/net/wireless/ti/wl12xx/cmd.c
+5
-3
drivers/net/wireless/ti/wl12xx/debugfs.c
drivers/net/wireless/ti/wl12xx/debugfs.c
+243
-0
drivers/net/wireless/ti/wl12xx/debugfs.h
drivers/net/wireless/ti/wl12xx/debugfs.h
+28
-0
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl12xx/main.c
+199
-43
drivers/net/wireless/ti/wl12xx/wl12xx.h
drivers/net/wireless/ti/wl12xx/wl12xx.h
+8
-0
drivers/net/wireless/ti/wl18xx/Kconfig
drivers/net/wireless/ti/wl18xx/Kconfig
+7
-0
drivers/net/wireless/ti/wl18xx/Makefile
drivers/net/wireless/ti/wl18xx/Makefile
+3
-0
drivers/net/wireless/ti/wl18xx/acx.c
drivers/net/wireless/ti/wl18xx/acx.c
+111
-0
drivers/net/wireless/ti/wl18xx/acx.h
drivers/net/wireless/ti/wl18xx/acx.h
+291
-0
drivers/net/wireless/ti/wl18xx/conf.h
drivers/net/wireless/ti/wl18xx/conf.h
+92
-0
drivers/net/wireless/ti/wl18xx/debugfs.c
drivers/net/wireless/ti/wl18xx/debugfs.c
+403
-0
drivers/net/wireless/ti/wl18xx/debugfs.h
drivers/net/wireless/ti/wl18xx/debugfs.h
+28
-0
drivers/net/wireless/ti/wl18xx/io.c
drivers/net/wireless/ti/wl18xx/io.c
+60
-0
drivers/net/wireless/ti/wl18xx/io.h
drivers/net/wireless/ti/wl18xx/io.h
+28
-0
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
+1462
-0
drivers/net/wireless/ti/wl18xx/reg.h
drivers/net/wireless/ti/wl18xx/reg.h
+191
-0
drivers/net/wireless/ti/wl18xx/tx.c
drivers/net/wireless/ti/wl18xx/tx.c
+127
-0
drivers/net/wireless/ti/wl18xx/tx.h
drivers/net/wireless/ti/wl18xx/tx.h
+46
-0
drivers/net/wireless/ti/wl18xx/wl18xx.h
drivers/net/wireless/ti/wl18xx/wl18xx.h
+88
-0
drivers/net/wireless/ti/wlcore/acx.c
drivers/net/wireless/ti/wlcore/acx.c
+6
-2
drivers/net/wireless/ti/wlcore/acx.h
drivers/net/wireless/ti/wlcore/acx.h
+16
-238
drivers/net/wireless/ti/wlcore/boot.c
drivers/net/wireless/ti/wlcore/boot.c
+33
-24
drivers/net/wireless/ti/wlcore/boot.h
drivers/net/wireless/ti/wlcore/boot.h
+1
-0
drivers/net/wireless/ti/wlcore/cmd.c
drivers/net/wireless/ti/wlcore/cmd.c
+51
-11
drivers/net/wireless/ti/wlcore/cmd.h
drivers/net/wireless/ti/wlcore/cmd.h
+11
-2
drivers/net/wireless/ti/wlcore/conf.h
drivers/net/wireless/ti/wlcore/conf.h
+67
-26
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.c
+129
-261
drivers/net/wireless/ti/wlcore/debugfs.h
drivers/net/wireless/ti/wlcore/debugfs.h
+87
-0
drivers/net/wireless/ti/wlcore/event.c
drivers/net/wireless/ti/wlcore/event.c
+21
-3
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/hw_ops.h
+78
-0
drivers/net/wireless/ti/wlcore/init.c
drivers/net/wireless/ti/wlcore/init.c
+3
-0
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/main.c
+267
-237
drivers/net/wireless/ti/wlcore/ps.c
drivers/net/wireless/ti/wlcore/ps.c
+17
-4
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.c
+6
-5
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/rx.h
+4
-3
drivers/net/wireless/ti/wlcore/scan.c
drivers/net/wireless/ti/wlcore/scan.c
+43
-9
drivers/net/wireless/ti/wlcore/scan.h
drivers/net/wireless/ti/wlcore/scan.h
+13
-6
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/sdio.c
+34
-1
drivers/net/wireless/ti/wlcore/tx.c
drivers/net/wireless/ti/wlcore/tx.c
+147
-38
drivers/net/wireless/ti/wlcore/tx.h
drivers/net/wireless/ti/wlcore/tx.h
+47
-2
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/ti/wlcore/wlcore.h
+56
-14
drivers/net/wireless/ti/wlcore/wlcore_i.h
drivers/net/wireless/ti/wlcore/wlcore_i.h
+21
-23
No files found.
drivers/net/wireless/ti/Kconfig
View file @
bf34e683
...
...
@@ -8,6 +8,7 @@ menuconfig WL_TI
if WL_TI
source "drivers/net/wireless/ti/wl1251/Kconfig"
source "drivers/net/wireless/ti/wl12xx/Kconfig"
source "drivers/net/wireless/ti/wl18xx/Kconfig"
# keep last for automatic dependencies
source "drivers/net/wireless/ti/wlcore/Kconfig"
...
...
drivers/net/wireless/ti/Makefile
View file @
bf34e683
...
...
@@ -2,3 +2,4 @@ obj-$(CONFIG_WLCORE) += wlcore/
obj-$(CONFIG_WL12XX)
+=
wl12xx/
obj-$(CONFIG_WL12XX_PLATFORM_DATA)
+=
wlcore/
obj-$(CONFIG_WL1251)
+=
wl1251/
obj-$(CONFIG_WL18XX)
+=
wl18xx/
drivers/net/wireless/ti/wl12xx/Makefile
View file @
bf34e683
wl12xx-objs
=
main.o cmd.o acx.o
wl12xx-objs
=
main.o cmd.o acx.o
debugfs.o
obj-$(CONFIG_WL12XX)
+=
wl12xx.o
drivers/net/wireless/ti/wl12xx/acx.h
View file @
bf34e683
...
...
@@ -24,6 +24,21 @@
#define __WL12XX_ACX_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/acx.h"
#define WL12XX_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL12XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
struct
wl1271_acx_host_config_bitmap
{
struct
acx_header
header
;
...
...
@@ -31,6 +46,228 @@ struct wl1271_acx_host_config_bitmap {
__le32
host_cfg_bitmap
;
}
__packed
;
struct
wl12xx_acx_tx_statistics
{
__le32
internal_desc_overflow
;
}
__packed
;
struct
wl12xx_acx_rx_statistics
{
__le32
out_of_mem
;
__le32
hdr_overflow
;
__le32
hw_stuck
;
__le32
dropped
;
__le32
fcs_err
;
__le32
xfr_hint_trig
;
__le32
path_reset
;
__le32
reset_counter
;
}
__packed
;
struct
wl12xx_acx_dma_statistics
{
__le32
rx_requested
;
__le32
rx_errors
;
__le32
tx_requested
;
__le32
tx_errors
;
}
__packed
;
struct
wl12xx_acx_isr_statistics
{
/* host command complete */
__le32
cmd_cmplt
;
/* fiqisr() */
__le32
fiqs
;
/* (INT_STS_ND & INT_TRIG_RX_HEADER) */
__le32
rx_headers
;
/* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
__le32
rx_completes
;
/* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
__le32
rx_mem_overflow
;
/* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
__le32
rx_rdys
;
/* irqisr() */
__le32
irqs
;
/* (INT_STS_ND & INT_TRIG_TX_PROC) */
__le32
tx_procs
;
/* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
__le32
decrypt_done
;
/* (INT_STS_ND & INT_TRIG_DMA0) */
__le32
dma0_done
;
/* (INT_STS_ND & INT_TRIG_DMA1) */
__le32
dma1_done
;
/* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
__le32
tx_exch_complete
;
/* (INT_STS_ND & INT_TRIG_COMMAND) */
__le32
commands
;
/* (INT_STS_ND & INT_TRIG_RX_PROC) */
__le32
rx_procs
;
/* (INT_STS_ND & INT_TRIG_PM_802) */
__le32
hw_pm_mode_changes
;
/* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
__le32
host_acknowledges
;
/* (INT_STS_ND & INT_TRIG_PM_PCI) */
__le32
pci_pm
;
/* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
__le32
wakeups
;
/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
__le32
low_rssi
;
}
__packed
;
struct
wl12xx_acx_wep_statistics
{
/* WEP address keys configured */
__le32
addr_key_count
;
/* default keys configured */
__le32
default_key_count
;
__le32
reserved
;
/* number of times that WEP key not found on lookup */
__le32
key_not_found
;
/* number of times that WEP key decryption failed */
__le32
decrypt_fail
;
/* WEP packets decrypted */
__le32
packets
;
/* WEP decrypt interrupts */
__le32
interrupt
;
}
__packed
;
#define ACX_MISSED_BEACONS_SPREAD 10
struct
wl12xx_acx_pwr_statistics
{
/* the amount of enters into power save mode (both PD & ELP) */
__le32
ps_enter
;
/* the amount of enters into ELP mode */
__le32
elp_enter
;
/* the amount of missing beacon interrupts to the host */
__le32
missing_bcns
;
/* the amount of wake on host-access times */
__le32
wake_on_host
;
/* the amount of wake on timer-expire */
__le32
wake_on_timer_exp
;
/* the number of packets that were transmitted with PS bit set */
__le32
tx_with_ps
;
/* the number of packets that were transmitted with PS bit clear */
__le32
tx_without_ps
;
/* the number of received beacons */
__le32
rcvd_beacons
;
/* the number of entering into PowerOn (power save off) */
__le32
power_save_off
;
/* the number of entries into power save mode */
__le16
enable_ps
;
/*
* the number of exits from power save, not including failed PS
* transitions
*/
__le16
disable_ps
;
/*
* the number of times the TSF counter was adjusted because
* of drift
*/
__le32
fix_tsf_ps
;
/* Gives statistics about the spread continuous missed beacons.
* The 16 LSB are dedicated for the PS mode.
* The 16 MSB are dedicated for the PS mode.
* cont_miss_bcns_spread[0] - single missed beacon.
* cont_miss_bcns_spread[1] - two continuous missed beacons.
* cont_miss_bcns_spread[2] - three continuous missed beacons.
* ...
* cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
*/
__le32
cont_miss_bcns_spread
[
ACX_MISSED_BEACONS_SPREAD
];
/* the number of beacons in awake mode */
__le32
rcvd_awake_beacons
;
}
__packed
;
struct
wl12xx_acx_mic_statistics
{
__le32
rx_pkts
;
__le32
calc_failure
;
}
__packed
;
struct
wl12xx_acx_aes_statistics
{
__le32
encrypt_fail
;
__le32
decrypt_fail
;
__le32
encrypt_packets
;
__le32
decrypt_packets
;
__le32
encrypt_interrupt
;
__le32
decrypt_interrupt
;
}
__packed
;
struct
wl12xx_acx_event_statistics
{
__le32
heart_beat
;
__le32
calibration
;
__le32
rx_mismatch
;
__le32
rx_mem_empty
;
__le32
rx_pool
;
__le32
oom_late
;
__le32
phy_transmit_error
;
__le32
tx_stuck
;
}
__packed
;
struct
wl12xx_acx_ps_statistics
{
__le32
pspoll_timeouts
;
__le32
upsd_timeouts
;
__le32
upsd_max_sptime
;
__le32
upsd_max_apturn
;
__le32
pspoll_max_apturn
;
__le32
pspoll_utilization
;
__le32
upsd_utilization
;
}
__packed
;
struct
wl12xx_acx_rxpipe_statistics
{
__le32
rx_prep_beacon_drop
;
__le32
descr_host_int_trig_rx_data
;
__le32
beacon_buffer_thres_host_int_trig_rx_data
;
__le32
missed_beacon_host_int_trig_rx_data
;
__le32
tx_xfr_host_int_trig_rx_data
;
}
__packed
;
struct
wl12xx_acx_statistics
{
struct
acx_header
header
;
struct
wl12xx_acx_tx_statistics
tx
;
struct
wl12xx_acx_rx_statistics
rx
;
struct
wl12xx_acx_dma_statistics
dma
;
struct
wl12xx_acx_isr_statistics
isr
;
struct
wl12xx_acx_wep_statistics
wep
;
struct
wl12xx_acx_pwr_statistics
pwr
;
struct
wl12xx_acx_aes_statistics
aes
;
struct
wl12xx_acx_mic_statistics
mic
;
struct
wl12xx_acx_event_statistics
event
;
struct
wl12xx_acx_ps_statistics
ps
;
struct
wl12xx_acx_rxpipe_statistics
rxpipe
;
}
__packed
;
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
);
#endif
/* __WL12XX_ACX_H__ */
drivers/net/wireless/ti/wl12xx/cmd.c
View file @
bf34e683
...
...
@@ -65,6 +65,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
struct
wl1271_general_parms_cmd
*
gen_parms
;
struct
wl1271_ini_general_params
*
gp
=
&
((
struct
wl1271_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
bool
answer
=
false
;
int
ret
;
...
...
@@ -88,7 +89,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
answer
=
true
;
/* Override the REF CLK from the NVS with the one from platform data */
gen_parms
->
general_params
.
ref_clock
=
wl
->
ref_clock
;
gen_parms
->
general_params
.
ref_clock
=
priv
->
ref_clock
;
ret
=
wl1271_cmd_test
(
wl
,
gen_parms
,
sizeof
(
*
gen_parms
),
answer
);
if
(
ret
<
0
)
{
...
...
@@ -118,6 +119,7 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
struct
wl128x_general_parms_cmd
*
gen_parms
;
struct
wl128x_ini_general_params
*
gp
=
&
((
struct
wl128x_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
bool
answer
=
false
;
int
ret
;
...
...
@@ -141,8 +143,8 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
answer
=
true
;
/* Replace REF and TCXO CLKs with the ones from platform data */
gen_parms
->
general_params
.
ref_clock
=
wl
->
ref_clock
;
gen_parms
->
general_params
.
tcxo_ref_clock
=
wl
->
tcxo_clock
;
gen_parms
->
general_params
.
ref_clock
=
priv
->
ref_clock
;
gen_parms
->
general_params
.
tcxo_ref_clock
=
priv
->
tcxo_clock
;
ret
=
wl1271_cmd_test
(
wl
,
gen_parms
,
sizeof
(
*
gen_parms
),
answer
);
if
(
ret
<
0
)
{
...
...
drivers/net/wireless/ti/wl12xx/debugfs.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl12xx
*
* Copyright (C) 2009 Nokia Corporation
* Copyright (C) 2011-2012 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/debugfs.h"
#include "../wlcore/wlcore.h"
#include "wl12xx.h"
#include "acx.h"
#include "debugfs.h"
#define WL12XX_DEBUGFS_FWSTATS_FILE(a, b, c) \
DEBUGFS_FWSTATS_FILE(a, b, c, wl12xx_acx_statistics)
WL12XX_DEBUGFS_FWSTATS_FILE
(
tx
,
internal_desc_overflow
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
out_of_mem
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
hdr_overflow
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
hw_stuck
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
dropped
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
fcs_err
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
xfr_hint_trig
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
path_reset
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rx
,
reset_counter
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
dma
,
rx_requested
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
dma
,
rx_errors
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
dma
,
tx_requested
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
dma
,
tx_errors
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
cmd_cmplt
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
fiqs
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
rx_headers
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
rx_mem_overflow
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
rx_rdys
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
irqs
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
tx_procs
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
decrypt_done
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
dma0_done
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
dma1_done
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
tx_exch_complete
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
commands
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
rx_procs
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
hw_pm_mode_changes
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
host_acknowledges
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
pci_pm
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
wakeups
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
isr
,
low_rssi
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
addr_key_count
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
default_key_count
,
"%u"
);
/* skipping wep.reserved */
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
key_not_found
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
decrypt_fail
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
packets
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
wep
,
interrupt
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
ps_enter
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
elp_enter
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
missing_bcns
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
wake_on_host
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
wake_on_timer_exp
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
tx_with_ps
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
tx_without_ps
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_beacons
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
power_save_off
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
enable_ps
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
disable_ps
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
fix_tsf_ps
,
"%u"
);
/* skipping cont_miss_bcns_spread for now */
WL12XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_awake_beacons
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
mic
,
rx_pkts
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
mic
,
calc_failure
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_fail
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_fail
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_packets
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_packets
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_interrupt
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_interrupt
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
heart_beat
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
calibration
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
rx_mismatch
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
rx_mem_empty
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
rx_pool
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
oom_late
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
phy_transmit_error
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
event
,
tx_stuck
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_timeouts
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_timeouts
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_max_sptime
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_max_apturn
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_max_apturn
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_utilization
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_utilization
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rxpipe
,
rx_prep_beacon_drop
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rxpipe
,
descr_host_int_trig_rx_data
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rxpipe
,
beacon_buffer_thres_host_int_trig_rx_data
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rxpipe
,
missed_beacon_host_int_trig_rx_data
,
"%u"
);
WL12XX_DEBUGFS_FWSTATS_FILE
(
rxpipe
,
tx_xfr_host_int_trig_rx_data
,
"%u"
);
int
wl12xx_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
int
ret
=
0
;
struct
dentry
*
entry
,
*
stats
,
*
moddir
;
moddir
=
debugfs_create_dir
(
KBUILD_MODNAME
,
rootdir
);
if
(
!
moddir
||
IS_ERR
(
moddir
))
{
entry
=
moddir
;
goto
err
;
}
stats
=
debugfs_create_dir
(
"fw_stats"
,
moddir
);
if
(
!
stats
||
IS_ERR
(
stats
))
{
entry
=
stats
;
goto
err
;
}
DEBUGFS_FWSTATS_ADD
(
tx
,
internal_desc_overflow
);
DEBUGFS_FWSTATS_ADD
(
rx
,
out_of_mem
);
DEBUGFS_FWSTATS_ADD
(
rx
,
hdr_overflow
);
DEBUGFS_FWSTATS_ADD
(
rx
,
hw_stuck
);
DEBUGFS_FWSTATS_ADD
(
rx
,
dropped
);
DEBUGFS_FWSTATS_ADD
(
rx
,
fcs_err
);
DEBUGFS_FWSTATS_ADD
(
rx
,
xfr_hint_trig
);
DEBUGFS_FWSTATS_ADD
(
rx
,
path_reset
);
DEBUGFS_FWSTATS_ADD
(
rx
,
reset_counter
);
DEBUGFS_FWSTATS_ADD
(
dma
,
rx_requested
);
DEBUGFS_FWSTATS_ADD
(
dma
,
rx_errors
);
DEBUGFS_FWSTATS_ADD
(
dma
,
tx_requested
);
DEBUGFS_FWSTATS_ADD
(
dma
,
tx_errors
);
DEBUGFS_FWSTATS_ADD
(
isr
,
cmd_cmplt
);
DEBUGFS_FWSTATS_ADD
(
isr
,
fiqs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_headers
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_mem_overflow
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_rdys
);
DEBUGFS_FWSTATS_ADD
(
isr
,
irqs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
tx_procs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
decrypt_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
dma0_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
dma1_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
tx_exch_complete
);
DEBUGFS_FWSTATS_ADD
(
isr
,
commands
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_procs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
hw_pm_mode_changes
);
DEBUGFS_FWSTATS_ADD
(
isr
,
host_acknowledges
);
DEBUGFS_FWSTATS_ADD
(
isr
,
pci_pm
);
DEBUGFS_FWSTATS_ADD
(
isr
,
wakeups
);
DEBUGFS_FWSTATS_ADD
(
isr
,
low_rssi
);
DEBUGFS_FWSTATS_ADD
(
wep
,
addr_key_count
);
DEBUGFS_FWSTATS_ADD
(
wep
,
default_key_count
);
/* skipping wep.reserved */
DEBUGFS_FWSTATS_ADD
(
wep
,
key_not_found
);
DEBUGFS_FWSTATS_ADD
(
wep
,
decrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
wep
,
packets
);
DEBUGFS_FWSTATS_ADD
(
wep
,
interrupt
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
ps_enter
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
elp_enter
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
missing_bcns
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
wake_on_host
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
wake_on_timer_exp
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
tx_with_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
tx_without_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_beacons
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
power_save_off
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
enable_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
disable_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
fix_tsf_ps
);
/* skipping cont_miss_bcns_spread for now */
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_awake_beacons
);
DEBUGFS_FWSTATS_ADD
(
mic
,
rx_pkts
);
DEBUGFS_FWSTATS_ADD
(
mic
,
calc_failure
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_packets
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_packets
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_interrupt
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_interrupt
);
DEBUGFS_FWSTATS_ADD
(
event
,
heart_beat
);
DEBUGFS_FWSTATS_ADD
(
event
,
calibration
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_mismatch
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_mem_empty
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_pool
);
DEBUGFS_FWSTATS_ADD
(
event
,
oom_late
);
DEBUGFS_FWSTATS_ADD
(
event
,
phy_transmit_error
);
DEBUGFS_FWSTATS_ADD
(
event
,
tx_stuck
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_max_sptime
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_max_apturn
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_max_apturn
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_utilization
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_utilization
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
rx_prep_beacon_drop
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
descr_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
beacon_buffer_thres_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
missed_beacon_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
tx_xfr_host_int_trig_rx_data
);
return
0
;
err:
if
(
IS_ERR
(
entry
))
ret
=
PTR_ERR
(
entry
);
else
ret
=
-
ENOMEM
;
return
ret
;
}
drivers/net/wireless/ti/wl12xx/debugfs.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_DEBUGFS_H__
#define __WL12XX_DEBUGFS_H__
int
wl12xx_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
);
#endif
/* __WL12XX_DEBUGFS_H__ */
drivers/net/wireless/ti/wl12xx/main.c
View file @
bf34e683
...
...
@@ -39,6 +39,10 @@
#include "reg.h"
#include "cmd.h"
#include "acx.h"
#include "debugfs.h"
static
char
*
fref_param
;
static
char
*
tcxo_param
;
static
struct
wlcore_conf
wl12xx_conf
=
{
.
sg
=
{
...
...
@@ -212,7 +216,7 @@ static struct wlcore_conf wl12xx_conf = {
.
suspend_wake_up_event
=
CONF_WAKE_UP_EVENT_N_DTIM
,
.
suspend_listen_interval
=
3
,
.
bcn_filt_mode
=
CONF_BCN_FILT_MODE_ENABLED
,
.
bcn_filt_ie_count
=
2
,
.
bcn_filt_ie_count
=
3
,
.
bcn_filt_ie
=
{
[
0
]
=
{
.
ie
=
WLAN_EID_CHANNEL_SWITCH
,
...
...
@@ -222,9 +226,13 @@ static struct wlcore_conf wl12xx_conf = {
.
ie
=
WLAN_EID_HT_OPERATION
,
.
rule
=
CONF_BCN_RULE_PASS_ON_CHANGE
,
},
[
2
]
=
{
.
ie
=
WLAN_EID_ERP_INFO
,
.
rule
=
CONF_BCN_RULE_PASS_ON_CHANGE
,
},
},
.
synch_fail_thold
=
1
0
,
.
bss_lose_timeout
=
1
00
,
.
synch_fail_thold
=
1
2
,
.
bss_lose_timeout
=
4
00
,
.
beacon_rx_timeout
=
10000
,
.
broadcast_timeout
=
20000
,
.
rx_broadcast_in_ps
=
1
,
...
...
@@ -234,7 +242,7 @@ static struct wlcore_conf wl12xx_conf = {
.
psm_entry_retries
=
8
,
.
psm_exit_retries
=
16
,
.
psm_entry_nullfunc_retries
=
3
,
.
dynamic_ps_timeout
=
4
0
,
.
dynamic_ps_timeout
=
20
0
,
.
forced_ps
=
false
,
.
keep_alive_interval
=
55000
,
.
max_listen_interval
=
20
,
...
...
@@ -245,7 +253,7 @@ static struct wlcore_conf wl12xx_conf = {
},
.
pm_config
=
{
.
host_clk_settling_time
=
5000
,
.
host_fast_wakeup_support
=
false
.
host_fast_wakeup_support
=
CONF_FAST_WAKEUP_DISABLE
,
},
.
roam_trigger
=
{
.
trigger_pacing
=
1
,
...
...
@@ -305,8 +313,8 @@ static struct wlcore_conf wl12xx_conf = {
.
swallow_period
=
5
,
.
n_divider_fref_set_1
=
0xff
,
/* default */
.
n_divider_fref_set_2
=
12
,
.
m_divider_fref_set_1
=
148
,
.
m_divider_fref_set_2
=
0xffff
,
/* default */
.
m_divider_fref_set_1
=
0xffff
,
.
m_divider_fref_set_2
=
148
,
/* default */
.
coex_pll_stabilization_time
=
0xffffffff
,
/* default */
.
ldo_stabilization_time
=
0xffff
,
/* default */
.
fm_disturbed_band_margin
=
0xff
,
/* default */
...
...
@@ -593,7 +601,7 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
struct
wl1271_acx_mem_map
*
wl_mem_map
=
wl
->
target_mem_map
;
struct
wl127
1
_rx_mem_pool_addr
rx_mem_addr
;
struct
wl127
x
_rx_mem_pool_addr
rx_mem_addr
;
/*
* Choose the block we want to read
...
...
@@ -621,10 +629,8 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
wl1271_warning
(
"chip id 0x%x (1271 PG10) support is obsolete"
,
wl
->
chip
.
id
);
/* clear the alignment quirk, since we don't support it */
wl
->
quirks
&=
~
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
;
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
memcpy
(
&
wl
->
conf
.
mem
,
&
wl12xx_default_priv_conf
.
mem_wl127x
,
...
...
@@ -639,10 +645,8 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
/* clear the alignment quirk, since we don't support it */
wl
->
quirks
&=
~
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
;
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
wl
->
plt_fw_name
=
WL127X_PLT_FW_NAME
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
...
...
@@ -660,6 +664,11 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
wl
->
plt_fw_name
=
WL128X_PLT_FW_NAME
;
wl
->
sr_fw_name
=
WL128X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL128X_FW_NAME_MULTI
;
/* wl128x requires TX blocksize alignment */
wl
->
quirks
|=
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
break
;
case
CHIP_ID_1283_PG10
:
default:
...
...
@@ -773,6 +782,7 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
u16
spare_reg
;
u16
pll_config
;
u8
input_freq
;
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
/* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg
=
wl12xx_top_reg_read
(
wl
,
WL_SPARE_REG
);
...
...
@@ -782,8 +792,8 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
wl12xx_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
/* Handle special cases of the TCXO clock */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_8
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_33_6
)
if
(
priv
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_8
||
priv
->
tcxo_clock
==
WL12XX_TCXOCLOCK_33_6
)
return
wl128x_manually_configure_mcs_pll
(
wl
);
/* Set the input frequency according to the selected clock source */
...
...
@@ -808,11 +818,12 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
*/
static
int
wl128x_boot_clk
(
struct
wl1271
*
wl
,
int
*
selected_clock
)
{
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
u16
sys_clk_cfg
;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if
(
wl
->
ref_clock
==
WL12XX_REFCLOCK_26_XTAL
||
wl
->
ref_clock
==
WL12XX_REFCLOCK_38_XTAL
)
{
if
(
priv
->
ref_clock
==
WL12XX_REFCLOCK_26_XTAL
||
priv
->
ref_clock
==
WL12XX_REFCLOCK_38_XTAL
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
...
...
@@ -826,8 +837,8 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
goto
fref_clk
;
/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_368
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_32_736
)
{
if
(
priv
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_368
||
priv
->
tcxo_clock
==
WL12XX_TCXOCLOCK_32_736
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
...
...
@@ -836,14 +847,14 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
/* TCXO clock is selected */
if
(
!
wl128x_is_tcxo_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
tcxo_clock
;
*
selected_clock
=
priv
->
tcxo_clock
;
goto
config_mcs_pll
;
fref_clk:
/* FREF clock is selected */
if
(
!
wl128x_is_fref_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
ref_clock
;
*
selected_clock
=
priv
->
ref_clock
;
config_mcs_pll:
return
wl128x_configure_mcs_pll
(
wl
,
*
selected_clock
);
...
...
@@ -851,25 +862,27 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
static
int
wl127x_boot_clk
(
struct
wl1271
*
wl
)
{
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
u32
pause
;
u32
clk
;
if
(
WL127X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
)
<
3
)
wl
->
quirks
|=
WLCORE_QUIRK_END_OF_TRANSACTION
;
if
(
wl
->
ref_clock
==
CONF_REF_CLK_19_2_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_M_XTAL
)
if
(
priv
->
ref_clock
==
CONF_REF_CLK_19_2_E
||
priv
->
ref_clock
==
CONF_REF_CLK_38_4_E
||
priv
->
ref_clock
==
CONF_REF_CLK_38_4_M_XTAL
)
/* ref clk: 19.2/38.4/38.4-XTAL */
clk
=
0x3
;
else
if
(
wl
->
ref_clock
==
CONF_REF_CLK_26_E
||
wl
->
ref_clock
==
CONF_REF_CLK_52_E
)
else
if
(
priv
->
ref_clock
==
CONF_REF_CLK_26_E
||
priv
->
ref_clock
==
CONF_REF_CLK_26_M_XTAL
||
priv
->
ref_clock
==
CONF_REF_CLK_52_E
)
/* ref clk: 26/52 */
clk
=
0x5
;
else
return
-
EINVAL
;
if
(
wl
->
ref_clock
!=
CONF_REF_CLK_19_2_E
)
{
if
(
priv
->
ref_clock
!=
CONF_REF_CLK_19_2_E
)
{
u16
val
;
/* Set clock type (open drain) */
val
=
wl12xx_top_reg_read
(
wl
,
OCP_REG_CLK_TYPE
);
...
...
@@ -939,6 +952,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
static
int
wl12xx_pre_boot
(
struct
wl1271
*
wl
)
{
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
int
ret
=
0
;
u32
clk
;
int
selected_clock
=
-
1
;
...
...
@@ -970,7 +984,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
clk
|=
((
selected_clock
&
0x3
)
<<
1
)
<<
4
;
else
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
clk
|=
(
priv
->
ref_clock
<<
1
)
<<
4
;
wl1271_write32
(
wl
,
WL12XX_DRPW_SCRATCH_START
,
clk
);
...
...
@@ -989,7 +1003,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
static
void
wl12xx_pre_upload
(
struct
wl1271
*
wl
)
{
u32
tmp
;
u32
tmp
,
polarity
;
/* write firmware's last address (ie. it's length) to
* ACX_EEPROMLESS_IND_REG */
...
...
@@ -1009,23 +1023,23 @@ static void wl12xx_pre_upload(struct wl1271 *wl)
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
wl12xx_top_reg_write
(
wl
,
SDIO_IO_DS
,
HCI_IO_DS_6MA
);
}
static
void
wl12xx_enable_interrupts
(
struct
wl1271
*
wl
)
{
u32
polarity
;
/* polarity must be set before the firmware is loaded */
polarity
=
wl12xx_top_reg_read
(
wl
,
OCP_REG_POLARITY
);
/* We use HIGH polarity, so unset the LOW bit */
polarity
&=
~
POLARITY_LOW
;
wl12xx_top_reg_write
(
wl
,
OCP_REG_POLARITY
,
polarity
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
}
static
void
wl12xx_enable_interrupts
(
struct
wl1271
*
wl
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL12XX_ACX_ALL_EVENTS_VECTOR
);
wlcore_enable_interrupts
(
wl
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
(
WL12
71
_INTR_MASK
));
WL1271_ACX_INTR_ALL
&
~
(
WL12
XX
_INTR_MASK
));
wl1271_write32
(
wl
,
WL12XX_HI_CFG
,
HI_CFG_DEF_VAL
);
}
...
...
@@ -1149,7 +1163,8 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
static
void
wl12xx_tx_delayed_compl
(
struct
wl1271
*
wl
)
{
if
(
wl
->
fw_status
->
tx_results_counter
==
(
wl
->
tx_results_count
&
0xff
))
if
(
wl
->
fw_status_1
->
tx_results_counter
==
(
wl
->
tx_results_count
&
0xff
))
return
;
wl1271_tx_complete
(
wl
);
...
...
@@ -1288,10 +1303,90 @@ static void wl12xx_get_mac(struct wl1271 *wl)
wl12xx_get_fuse_mac
(
wl
);
}
static
void
wl12xx_set_tx_desc_csum
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
)
{
desc
->
wl12xx_reserved
=
0
;
}
static
int
wl12xx_plt_init
(
struct
wl1271
*
wl
)
{
int
ret
;
ret
=
wl
->
ops
->
boot
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl
->
ops
->
hw_init
(
wl
);
if
(
ret
<
0
)
goto
out_irq_disable
;
ret
=
wl1271_acx_init_mem_config
(
wl
);
if
(
ret
<
0
)
goto
out_irq_disable
;
ret
=
wl12xx_acx_mem_cfg
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Enable data path */
ret
=
wl1271_cmd_data_path
(
wl
,
1
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Configure for CAM power saving (ie. always active) */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_CAM
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* configure PM */
ret
=
wl1271_acx_pm_config
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
goto
out
;
out_free_memmap:
kfree
(
wl
->
target_mem_map
);
wl
->
target_mem_map
=
NULL
;
out_irq_disable:
mutex_unlock
(
&
wl
->
mutex
);
/* Unlocking the mutex in the middle of handling is
inherently unsafe. In this case we deem it safe to do,
because we need to let any possibly pending IRQ out of
the system (and while we are WL1271_STATE_OFF the IRQ
work function will not do anything.) Also, any other
possible concurrent operations will fail due to the
current state, hence the wl1271 struct should be safe. */
wlcore_disable_interrupts
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
out:
return
ret
;
}
static
int
wl12xx_get_spare_blocks
(
struct
wl1271
*
wl
,
bool
is_gem
)
{
if
(
is_gem
)
return
WL12XX_TX_HW_BLOCK_GEM_SPARE
;
return
WL12XX_TX_HW_BLOCK_SPARE_DEFAULT
;
}
static
int
wl12xx_set_key
(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
)
{
return
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
}
static
struct
wlcore_ops
wl12xx_ops
=
{
.
identify_chip
=
wl12xx_identify_chip
,
.
identify_fw
=
wl12xx_identify_fw
,
.
boot
=
wl12xx_boot
,
.
plt_init
=
wl12xx_plt_init
,
.
trigger_cmd
=
wl12xx_trigger_cmd
,
.
ack_event
=
wl12xx_ack_event
,
.
calc_tx_blocks
=
wl12xx_calc_tx_blocks
,
...
...
@@ -1306,6 +1401,13 @@ static struct wlcore_ops wl12xx_ops = {
.
sta_get_ap_rate_mask
=
wl12xx_sta_get_ap_rate_mask
,
.
get_pg_ver
=
wl12xx_get_pg_ver
,
.
get_mac
=
wl12xx_get_mac
,
.
set_tx_desc_csum
=
wl12xx_set_tx_desc_csum
,
.
set_rx_csum
=
NULL
,
.
ap_get_mimo_wide_rate_mask
=
NULL
,
.
debugfs_init
=
wl12xx_debugfs_add_files
,
.
get_spare_blocks
=
wl12xx_get_spare_blocks
,
.
set_key
=
wl12xx_set_key
,
.
pre_pkt_send
=
NULL
,
};
static
struct
ieee80211_sta_ht_cap
wl12xx_ht_cap
=
{
...
...
@@ -1323,6 +1425,7 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
static
int
__devinit
wl12xx_probe
(
struct
platform_device
*
pdev
)
{
struct
wl12xx_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
wl1271
*
wl
;
struct
ieee80211_hw
*
hw
;
struct
wl12xx_priv
*
priv
;
...
...
@@ -1334,19 +1437,65 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
}
wl
=
hw
->
priv
;
priv
=
wl
->
priv
;
wl
->
ops
=
&
wl12xx_ops
;
wl
->
ptable
=
wl12xx_ptable
;
wl
->
rtable
=
wl12xx_rtable
;
wl
->
num_tx_desc
=
16
;
wl
->
normal_tx_spare
=
WL12XX_TX_HW_BLOCK_SPARE_DEFAULT
;
wl
->
gem_tx_spare
=
WL12XX_TX_HW_BLOCK_GEM_SPARE
;
wl
->
num_rx_desc
=
8
;
wl
->
band_rate_to_idx
=
wl12xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL12XX_CONF_HW_RXTX_RATE_MAX
;
wl
->
hw_min_ht_rate
=
WL12XX_CONF_HW_RXTX_RATE_MCS0
;
wl
->
fw_status_priv_len
=
0
;
memcpy
(
&
wl
->
ht_cap
,
&
wl12xx_ht_cap
,
sizeof
(
wl12xx_ht_cap
));
wl
->
stats
.
fw_stats_len
=
sizeof
(
struct
wl12xx_acx_statistics
);
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
],
&
wl12xx_ht_cap
,
sizeof
(
wl12xx_ht_cap
));
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_5GHZ
],
&
wl12xx_ht_cap
,
sizeof
(
wl12xx_ht_cap
));
wl12xx_conf_init
(
wl
);
if
(
!
fref_param
)
{
priv
->
ref_clock
=
pdata
->
board_ref_clock
;
}
else
{
if
(
!
strcmp
(
fref_param
,
"19.2"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_19
;
else
if
(
!
strcmp
(
fref_param
,
"26"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_26
;
else
if
(
!
strcmp
(
fref_param
,
"26x"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_26_XTAL
;
else
if
(
!
strcmp
(
fref_param
,
"38.4"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_38
;
else
if
(
!
strcmp
(
fref_param
,
"38.4x"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_38_XTAL
;
else
if
(
!
strcmp
(
fref_param
,
"52"
))
priv
->
ref_clock
=
WL12XX_REFCLOCK_52
;
else
wl1271_error
(
"Invalid fref parameter %s"
,
fref_param
);
}
if
(
!
tcxo_param
)
{
priv
->
tcxo_clock
=
pdata
->
board_tcxo_clock
;
}
else
{
if
(
!
strcmp
(
tcxo_param
,
"19.2"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_19_2
;
else
if
(
!
strcmp
(
tcxo_param
,
"26"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_26
;
else
if
(
!
strcmp
(
tcxo_param
,
"38.4"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_38_4
;
else
if
(
!
strcmp
(
tcxo_param
,
"52"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_52
;
else
if
(
!
strcmp
(
tcxo_param
,
"16.368"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_16_368
;
else
if
(
!
strcmp
(
tcxo_param
,
"32.736"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_32_736
;
else
if
(
!
strcmp
(
tcxo_param
,
"16.8"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_16_8
;
else
if
(
!
strcmp
(
tcxo_param
,
"33.6"
))
priv
->
tcxo_clock
=
WL12XX_TCXOCLOCK_33_6
;
else
wl1271_error
(
"Invalid tcxo parameter %s"
,
tcxo_param
);
}
return
wlcore_probe
(
wl
,
pdev
);
}
...
...
@@ -1378,6 +1527,13 @@ static void __exit wl12xx_exit(void)
}
module_exit
(
wl12xx_exit
);
module_param_named
(
fref
,
fref_param
,
charp
,
0
);
MODULE_PARM_DESC
(
fref
,
"FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"
);
module_param_named
(
tcxo
,
tcxo_param
,
charp
,
0
);
MODULE_PARM_DESC
(
tcxo
,
"TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_FIRMWARE
(
WL127X_FW_NAME_SINGLE
);
...
...
drivers/net/wireless/ti/wl12xx/wl12xx.h
View file @
bf34e683
...
...
@@ -24,8 +24,16 @@
#include "conf.h"
struct
wl127x_rx_mem_pool_addr
{
u32
addr
;
u32
addr_extra
;
};
struct
wl12xx_priv
{
struct
wl12xx_priv_conf
conf
;
int
ref_clock
;
int
tcxo_clock
;
};
#endif
/* __WL12XX_PRIV_H__ */
drivers/net/wireless/ti/wl18xx/Kconfig
0 → 100644
View file @
bf34e683
config WL18XX
tristate "TI wl18xx support"
depends on MAC80211
select WLCORE
---help---
This module adds support for wireless adapters based on TI
WiLink 8 chipsets.
drivers/net/wireless/ti/wl18xx/Makefile
0 → 100644
View file @
bf34e683
wl18xx-objs
=
main.o acx.o tx.o io.o debugfs.o
obj-$(CONFIG_WL18XX)
+=
wl18xx.o
drivers/net/wireless/ti/wl18xx/acx.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "../wlcore/acx.h"
#include "acx.h"
int
wl18xx_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
,
u32
sdio_blk_size
,
u32
extra_mem_blks
,
u32
len_field_size
)
{
struct
wl18xx_acx_host_config_bitmap
*
bitmap_conf
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx cfg bitmap %d blk %d spare %d field %d"
,
host_cfg_bitmap
,
sdio_blk_size
,
extra_mem_blks
,
len_field_size
);
bitmap_conf
=
kzalloc
(
sizeof
(
*
bitmap_conf
),
GFP_KERNEL
);
if
(
!
bitmap_conf
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
bitmap_conf
->
host_cfg_bitmap
=
cpu_to_le32
(
host_cfg_bitmap
);
bitmap_conf
->
host_sdio_block_size
=
cpu_to_le32
(
sdio_blk_size
);
bitmap_conf
->
extra_mem_blocks
=
cpu_to_le32
(
extra_mem_blks
);
bitmap_conf
->
length_field_size
=
cpu_to_le32
(
len_field_size
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_HOST_IF_CFG_BITMAP
,
bitmap_conf
,
sizeof
(
*
bitmap_conf
));
if
(
ret
<
0
)
{
wl1271_warning
(
"wl1271 bitmap config opt failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
bitmap_conf
);
return
ret
;
}
int
wl18xx_acx_set_checksum_state
(
struct
wl1271
*
wl
)
{
struct
wl18xx_acx_checksum_state
*
acx
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx checksum state"
);
acx
=
kzalloc
(
sizeof
(
*
acx
),
GFP_KERNEL
);
if
(
!
acx
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
acx
->
checksum_state
=
CHECKSUM_OFFLOAD_ENABLED
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_CHECKSUM_CONFIG
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"failed to set Tx checksum state: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
acx
);
return
ret
;
}
int
wl18xx_acx_clear_statistics
(
struct
wl1271
*
wl
)
{
struct
wl18xx_acx_clear_statistics
*
acx
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_ACX
,
"acx clear statistics"
);
acx
=
kzalloc
(
sizeof
(
*
acx
),
GFP_KERNEL
);
if
(
!
acx
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ret
=
wl1271_cmd_configure
(
wl
,
ACX_CLEAR_STATISTICS
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"failed to clear firmware statistics: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
acx
);
return
ret
;
}
drivers/net/wireless/ti/wl18xx/acx.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_ACX_H__
#define __WL18XX_ACX_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/acx.h"
enum
{
ACX_CLEAR_STATISTICS
=
0x0047
,
};
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
struct
wl18xx_acx_host_config_bitmap
{
struct
acx_header
header
;
__le32
host_cfg_bitmap
;
__le32
host_sdio_block_size
;
/* extra mem blocks per frame in TX. */
__le32
extra_mem_blocks
;
/*
* number of bits of the length field in the first TX word
* (up to 15 - for using the entire 16 bits).
*/
__le32
length_field_size
;
}
__packed
;
enum
{
CHECKSUM_OFFLOAD_DISABLED
=
0
,
CHECKSUM_OFFLOAD_ENABLED
=
1
,
CHECKSUM_OFFLOAD_FAKE_RX
=
2
,
CHECKSUM_OFFLOAD_INVALID
=
0xFF
};
struct
wl18xx_acx_checksum_state
{
struct
acx_header
header
;
/* enum acx_checksum_state */
u8
checksum_state
;
u8
pad
[
3
];
}
__packed
;
struct
wl18xx_acx_error_stats
{
u32
error_frame
;
u32
error_null_Frame_tx_start
;
u32
error_numll_frame_cts_start
;
u32
error_bar_retry
;
u32
error_frame_cts_nul_flid
;
}
__packed
;
struct
wl18xx_acx_debug_stats
{
u32
debug1
;
u32
debug2
;
u32
debug3
;
u32
debug4
;
u32
debug5
;
u32
debug6
;
}
__packed
;
struct
wl18xx_acx_ring_stats
{
u32
prepared_descs
;
u32
tx_cmplt
;
}
__packed
;
struct
wl18xx_acx_tx_stats
{
u32
tx_prepared_descs
;
u32
tx_cmplt
;
u32
tx_template_prepared
;
u32
tx_data_prepared
;
u32
tx_template_programmed
;
u32
tx_data_programmed
;
u32
tx_burst_programmed
;
u32
tx_starts
;
u32
tx_imm_resp
;
u32
tx_start_templates
;
u32
tx_start_int_templates
;
u32
tx_start_fw_gen
;
u32
tx_start_data
;
u32
tx_start_null_frame
;
u32
tx_exch
;
u32
tx_retry_template
;
u32
tx_retry_data
;
u32
tx_exch_pending
;
u32
tx_exch_expiry
;
u32
tx_done_template
;
u32
tx_done_data
;
u32
tx_done_int_template
;
u32
tx_frame_checksum
;
u32
tx_checksum_result
;
u32
frag_called
;
u32
frag_mpdu_alloc_failed
;
u32
frag_init_called
;
u32
frag_in_process_called
;
u32
frag_tkip_called
;
u32
frag_key_not_found
;
u32
frag_need_fragmentation
;
u32
frag_bad_mblk_num
;
u32
frag_failed
;
u32
frag_cache_hit
;
u32
frag_cache_miss
;
}
__packed
;
struct
wl18xx_acx_rx_stats
{
u32
rx_beacon_early_term
;
u32
rx_out_of_mpdu_nodes
;
u32
rx_hdr_overflow
;
u32
rx_dropped_frame
;
u32
rx_done_stage
;
u32
rx_done
;
u32
rx_defrag
;
u32
rx_defrag_end
;
u32
rx_cmplt
;
u32
rx_pre_complt
;
u32
rx_cmplt_task
;
u32
rx_phy_hdr
;
u32
rx_timeout
;
u32
rx_timeout_wa
;
u32
rx_wa_density_dropped_frame
;
u32
rx_wa_ba_not_expected
;
u32
rx_frame_checksum
;
u32
rx_checksum_result
;
u32
defrag_called
;
u32
defrag_init_called
;
u32
defrag_in_process_called
;
u32
defrag_tkip_called
;
u32
defrag_need_defrag
;
u32
defrag_decrypt_failed
;
u32
decrypt_key_not_found
;
u32
defrag_need_decrypt
;
u32
rx_tkip_replays
;
}
__packed
;
struct
wl18xx_acx_isr_stats
{
u32
irqs
;
}
__packed
;
#define PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD 10
struct
wl18xx_acx_pwr_stats
{
u32
missing_bcns_cnt
;
u32
rcvd_bcns_cnt
;
u32
connection_out_of_sync
;
u32
cont_miss_bcns_spread
[
PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD
];
u32
rcvd_awake_bcns_cnt
;
}
__packed
;
struct
wl18xx_acx_event_stats
{
u32
calibration
;
u32
rx_mismatch
;
u32
rx_mem_empty
;
}
__packed
;
struct
wl18xx_acx_ps_poll_stats
{
u32
ps_poll_timeouts
;
u32
upsd_timeouts
;
u32
upsd_max_ap_turn
;
u32
ps_poll_max_ap_turn
;
u32
ps_poll_utilization
;
u32
upsd_utilization
;
}
__packed
;
struct
wl18xx_acx_rx_filter_stats
{
u32
beacon_filter
;
u32
arp_filter
;
u32
mc_filter
;
u32
dup_filter
;
u32
data_filter
;
u32
ibss_filter
;
u32
protection_filter
;
u32
accum_arp_pend_requests
;
u32
max_arp_queue_dep
;
}
__packed
;
struct
wl18xx_acx_rx_rate_stats
{
u32
rx_frames_per_rates
[
50
];
}
__packed
;
#define AGGR_STATS_TX_AGG 16
#define AGGR_STATS_TX_RATE 16
#define AGGR_STATS_RX_SIZE_LEN 16
struct
wl18xx_acx_aggr_stats
{
u32
tx_agg_vs_rate
[
AGGR_STATS_TX_AGG
*
AGGR_STATS_TX_RATE
];
u32
rx_size
[
AGGR_STATS_RX_SIZE_LEN
];
}
__packed
;
#define PIPE_STATS_HW_FIFO 11
struct
wl18xx_acx_pipeline_stats
{
u32
hs_tx_stat_fifo_int
;
u32
hs_rx_stat_fifo_int
;
u32
tcp_tx_stat_fifo_int
;
u32
tcp_rx_stat_fifo_int
;
u32
enc_tx_stat_fifo_int
;
u32
enc_rx_stat_fifo_int
;
u32
rx_complete_stat_fifo_int
;
u32
pre_proc_swi
;
u32
post_proc_swi
;
u32
sec_frag_swi
;
u32
pre_to_defrag_swi
;
u32
defrag_to_csum_swi
;
u32
csum_to_rx_xfer_swi
;
u32
dec_packet_in
;
u32
dec_packet_in_fifo_full
;
u32
dec_packet_out
;
u32
cs_rx_packet_in
;
u32
cs_rx_packet_out
;
u16
pipeline_fifo_full
[
PIPE_STATS_HW_FIFO
];
}
__packed
;
struct
wl18xx_acx_mem_stats
{
u32
rx_free_mem_blks
;
u32
tx_free_mem_blks
;
u32
fwlog_free_mem_blks
;
u32
fw_gen_free_mem_blks
;
}
__packed
;
struct
wl18xx_acx_statistics
{
struct
acx_header
header
;
struct
wl18xx_acx_error_stats
error
;
struct
wl18xx_acx_debug_stats
debug
;
struct
wl18xx_acx_tx_stats
tx
;
struct
wl18xx_acx_rx_stats
rx
;
struct
wl18xx_acx_isr_stats
isr
;
struct
wl18xx_acx_pwr_stats
pwr
;
struct
wl18xx_acx_ps_poll_stats
ps_poll
;
struct
wl18xx_acx_rx_filter_stats
rx_filter
;
struct
wl18xx_acx_rx_rate_stats
rx_rate
;
struct
wl18xx_acx_aggr_stats
aggr_size
;
struct
wl18xx_acx_pipeline_stats
pipeline
;
struct
wl18xx_acx_mem_stats
mem
;
}
__packed
;
struct
wl18xx_acx_clear_statistics
{
struct
acx_header
header
;
};
int
wl18xx_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
,
u32
sdio_blk_size
,
u32
extra_mem_blks
,
u32
len_field_size
);
int
wl18xx_acx_set_checksum_state
(
struct
wl1271
*
wl
);
int
wl18xx_acx_clear_statistics
(
struct
wl1271
*
wl
);
#endif
/* __WL18XX_ACX_H__ */
drivers/net/wireless/ti/wl18xx/conf.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_CONF_H__
#define __WL18XX_CONF_H__
#define WL18XX_CONF_MAGIC 0x10e100ca
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0002)
#define WL18XX_CONF_MASK 0x0000ffff
#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
sizeof(struct wl18xx_priv_conf))
#define NUM_OF_CHANNELS_11_ABG 150
#define NUM_OF_CHANNELS_11_P 7
#define WL18XX_NUM_OF_SUB_BANDS 9
#define SRF_TABLE_LEN 16
#define PIN_MUXING_SIZE 2
struct
wl18xx_mac_and_phy_params
{
u8
phy_standalone
;
u8
rdl
;
u8
enable_clpc
;
u8
enable_tx_low_pwr_on_siso_rdl
;
u8
auto_detect
;
u8
dedicated_fem
;
u8
low_band_component
;
/* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */
u8
low_band_component_type
;
u8
high_band_component
;
/* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */
u8
high_band_component_type
;
u8
number_of_assembled_ant2_4
;
u8
number_of_assembled_ant5
;
u8
pin_muxing_platform_options
[
PIN_MUXING_SIZE
];
u8
external_pa_dc2dc
;
u8
tcxo_ldo_voltage
;
u8
xtal_itrim_val
;
u8
srf_state
;
u8
srf1
[
SRF_TABLE_LEN
];
u8
srf2
[
SRF_TABLE_LEN
];
u8
srf3
[
SRF_TABLE_LEN
];
u8
io_configuration
;
u8
sdio_configuration
;
u8
settings
;
u8
rx_profile
;
u8
per_chan_pwr_limit_arr_11abg
[
NUM_OF_CHANNELS_11_ABG
];
u8
pwr_limit_reference_11_abg
;
u8
per_chan_pwr_limit_arr_11p
[
NUM_OF_CHANNELS_11_P
];
u8
pwr_limit_reference_11p
;
u8
per_sub_band_tx_trace_loss
[
WL18XX_NUM_OF_SUB_BANDS
];
u8
per_sub_band_rx_trace_loss
[
WL18XX_NUM_OF_SUB_BANDS
];
u8
primary_clock_setting_time
;
u8
clock_valid_on_wake_up
;
u8
secondary_clock_setting_time
;
u8
board_type
;
/* enable point saturation */
u8
psat
;
/* low/medium/high Tx power in dBm */
s8
low_power_val
;
s8
med_power_val
;
s8
high_power_val
;
u8
padding
[
1
];
}
__packed
;
struct
wl18xx_priv_conf
{
/* this structure is copied wholesale to FW */
struct
wl18xx_mac_and_phy_params
phy
;
}
__packed
;
#endif
/* __WL18XX_CONF_H__ */
drivers/net/wireless/ti/wl18xx/debugfs.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2009 Nokia Corporation
* Copyright (C) 2011-2012 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/debugfs.h"
#include "../wlcore/wlcore.h"
#include "wl18xx.h"
#include "acx.h"
#include "debugfs.h"
#define WL18XX_DEBUGFS_FWSTATS_FILE(a, b, c) \
DEBUGFS_FWSTATS_FILE(a, b, c, wl18xx_acx_statistics)
#define WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c) \
DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c, wl18xx_acx_statistics)
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug1
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug2
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug3
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug4
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug5
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
debug
,
debug6
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
error
,
error_frame
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
error
,
error_null_Frame_tx_start
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
error
,
error_numll_frame_cts_start
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
error
,
error_bar_retry
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
error
,
error_frame_cts_nul_flid
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_prepared_descs
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_cmplt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_template_prepared
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_data_prepared
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_template_programmed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_data_programmed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_burst_programmed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_starts
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_imm_resp
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_start_templates
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_start_int_templates
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_start_fw_gen
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_start_data
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_start_null_frame
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_exch
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_retry_template
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_retry_data
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_exch_pending
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_exch_expiry
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_done_template
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_done_data
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_done_int_template
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_frame_checksum
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
tx_checksum_result
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_mpdu_alloc_failed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_init_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_in_process_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_tkip_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_key_not_found
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_need_fragmentation
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_bad_mblk_num
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_failed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_cache_hit
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
tx
,
frag_cache_miss
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_beacon_early_term
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_out_of_mpdu_nodes
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_hdr_overflow
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_dropped_frame
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_done
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_defrag
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_defrag_end
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_cmplt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_pre_complt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_cmplt_task
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_phy_hdr
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_timeout
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_timeout_wa
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_wa_density_dropped_frame
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_wa_ba_not_expected
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_frame_checksum
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_checksum_result
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_init_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_in_process_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_tkip_called
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_need_defrag
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_decrypt_failed
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
decrypt_key_not_found
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
defrag_need_decrypt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx
,
rx_tkip_replays
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
isr
,
irqs
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
missing_bcns_cnt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_bcns_cnt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
connection_out_of_sync
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY
(
pwr
,
cont_miss_bcns_spread
,
PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_awake_bcns_cnt
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
ps_poll_timeouts
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
upsd_timeouts
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
upsd_max_ap_turn
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
ps_poll_max_ap_turn
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
ps_poll_utilization
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
ps_poll
,
upsd_utilization
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
beacon_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
arp_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
mc_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
dup_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
data_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
ibss_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
protection_filter
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
accum_arp_pend_requests
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_filter
,
max_arp_queue_dep
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
rx_rate
,
rx_frames_per_rates
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY
(
aggr_size
,
tx_agg_vs_rate
,
AGGR_STATS_TX_AGG
*
AGGR_STATS_TX_RATE
);
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY
(
aggr_size
,
rx_size
,
AGGR_STATS_RX_SIZE_LEN
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
hs_tx_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
tcp_tx_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
tcp_rx_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
enc_tx_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
enc_rx_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
rx_complete_stat_fifo_int
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
pre_proc_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
post_proc_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
sec_frag_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
pre_to_defrag_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
defrag_to_csum_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
csum_to_rx_xfer_swi
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
dec_packet_in
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
dec_packet_in_fifo_full
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
dec_packet_out
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
cs_rx_packet_in
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
pipeline
,
cs_rx_packet_out
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY
(
pipeline
,
pipeline_fifo_full
,
PIPE_STATS_HW_FIFO
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
mem
,
rx_free_mem_blks
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
mem
,
tx_free_mem_blks
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
mem
,
fwlog_free_mem_blks
,
"%u"
);
WL18XX_DEBUGFS_FWSTATS_FILE
(
mem
,
fw_gen_free_mem_blks
,
"%u"
);
static
ssize_t
conf_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
struct
wlcore_conf_header
header
;
char
*
buf
,
*
pos
;
size_t
len
;
int
ret
;
len
=
WL18XX_CONF_SIZE
;
buf
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
header
.
magic
=
cpu_to_le32
(
WL18XX_CONF_MAGIC
);
header
.
version
=
cpu_to_le32
(
WL18XX_CONF_VERSION
);
header
.
checksum
=
0
;
mutex_lock
(
&
wl
->
mutex
);
pos
=
buf
;
memcpy
(
pos
,
&
header
,
sizeof
(
header
));
pos
+=
sizeof
(
header
);
memcpy
(
pos
,
&
wl
->
conf
,
sizeof
(
wl
->
conf
));
pos
+=
sizeof
(
wl
->
conf
);
memcpy
(
pos
,
&
priv
->
conf
,
sizeof
(
priv
->
conf
));
mutex_unlock
(
&
wl
->
mutex
);
ret
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
len
);
kfree
(
buf
);
return
ret
;
}
static
const
struct
file_operations
conf_ops
=
{
.
read
=
conf_read
,
.
open
=
simple_open
,
.
llseek
=
default_llseek
,
};
static
ssize_t
clear_fw_stats_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
int
ret
;
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
goto
out
;
ret
=
wl18xx_acx_clear_statistics
(
wl
);
if
(
ret
<
0
)
{
count
=
ret
;
goto
out
;
}
out:
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
const
struct
file_operations
clear_fw_stats_ops
=
{
.
write
=
clear_fw_stats_write
,
.
open
=
simple_open
,
.
llseek
=
default_llseek
,
};
int
wl18xx_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
int
ret
=
0
;
struct
dentry
*
entry
,
*
stats
,
*
moddir
;
moddir
=
debugfs_create_dir
(
KBUILD_MODNAME
,
rootdir
);
if
(
!
moddir
||
IS_ERR
(
moddir
))
{
entry
=
moddir
;
goto
err
;
}
stats
=
debugfs_create_dir
(
"fw_stats"
,
moddir
);
if
(
!
stats
||
IS_ERR
(
stats
))
{
entry
=
stats
;
goto
err
;
}
DEBUGFS_ADD
(
clear_fw_stats
,
stats
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug1
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug2
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug3
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug4
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug5
);
DEBUGFS_FWSTATS_ADD
(
debug
,
debug6
);
DEBUGFS_FWSTATS_ADD
(
error
,
error_frame
);
DEBUGFS_FWSTATS_ADD
(
error
,
error_null_Frame_tx_start
);
DEBUGFS_FWSTATS_ADD
(
error
,
error_numll_frame_cts_start
);
DEBUGFS_FWSTATS_ADD
(
error
,
error_bar_retry
);
DEBUGFS_FWSTATS_ADD
(
error
,
error_frame_cts_nul_flid
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_prepared_descs
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_cmplt
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_template_prepared
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_data_prepared
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_template_programmed
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_data_programmed
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_burst_programmed
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_starts
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_imm_resp
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_start_templates
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_start_int_templates
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_start_fw_gen
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_start_data
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_start_null_frame
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_exch
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_retry_template
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_retry_data
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_exch_pending
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_exch_expiry
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_done_template
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_done_data
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_done_int_template
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_frame_checksum
);
DEBUGFS_FWSTATS_ADD
(
tx
,
tx_checksum_result
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_called
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_mpdu_alloc_failed
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_init_called
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_in_process_called
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_tkip_called
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_key_not_found
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_need_fragmentation
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_bad_mblk_num
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_failed
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_cache_hit
);
DEBUGFS_FWSTATS_ADD
(
tx
,
frag_cache_miss
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_beacon_early_term
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_out_of_mpdu_nodes
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_hdr_overflow
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_dropped_frame
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_done
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_defrag
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_defrag_end
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_cmplt
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_pre_complt
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_cmplt_task
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_phy_hdr
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_timeout
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_timeout_wa
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_wa_density_dropped_frame
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_wa_ba_not_expected
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_frame_checksum
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_checksum_result
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_called
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_init_called
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_in_process_called
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_tkip_called
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_need_defrag
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_decrypt_failed
);
DEBUGFS_FWSTATS_ADD
(
rx
,
decrypt_key_not_found
);
DEBUGFS_FWSTATS_ADD
(
rx
,
defrag_need_decrypt
);
DEBUGFS_FWSTATS_ADD
(
rx
,
rx_tkip_replays
);
DEBUGFS_FWSTATS_ADD
(
isr
,
irqs
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
missing_bcns_cnt
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_bcns_cnt
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
connection_out_of_sync
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
cont_miss_bcns_spread
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_awake_bcns_cnt
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
ps_poll_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
upsd_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
upsd_max_ap_turn
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
ps_poll_max_ap_turn
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
ps_poll_utilization
);
DEBUGFS_FWSTATS_ADD
(
ps_poll
,
upsd_utilization
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
beacon_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
arp_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
mc_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
dup_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
data_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
ibss_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
protection_filter
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
accum_arp_pend_requests
);
DEBUGFS_FWSTATS_ADD
(
rx_filter
,
max_arp_queue_dep
);
DEBUGFS_FWSTATS_ADD
(
rx_rate
,
rx_frames_per_rates
);
DEBUGFS_FWSTATS_ADD
(
aggr_size
,
tx_agg_vs_rate
);
DEBUGFS_FWSTATS_ADD
(
aggr_size
,
rx_size
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
hs_tx_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
tcp_tx_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
tcp_rx_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
enc_tx_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
enc_rx_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
rx_complete_stat_fifo_int
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
pre_proc_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
post_proc_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
sec_frag_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
pre_to_defrag_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
defrag_to_csum_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
csum_to_rx_xfer_swi
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
dec_packet_in
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
dec_packet_in_fifo_full
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
dec_packet_out
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
cs_rx_packet_in
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
cs_rx_packet_out
);
DEBUGFS_FWSTATS_ADD
(
pipeline
,
pipeline_fifo_full
);
DEBUGFS_FWSTATS_ADD
(
mem
,
rx_free_mem_blks
);
DEBUGFS_FWSTATS_ADD
(
mem
,
tx_free_mem_blks
);
DEBUGFS_FWSTATS_ADD
(
mem
,
fwlog_free_mem_blks
);
DEBUGFS_FWSTATS_ADD
(
mem
,
fw_gen_free_mem_blks
);
DEBUGFS_ADD
(
conf
,
moddir
);
return
0
;
err:
if
(
IS_ERR
(
entry
))
ret
=
PTR_ERR
(
entry
);
else
ret
=
-
ENOMEM
;
return
ret
;
}
drivers/net/wireless/ti/wl18xx/debugfs.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_DEBUGFS_H__
#define __WL18XX_DEBUGFS_H__
int
wl18xx_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
);
#endif
/* __WL18XX_DEBUGFS_H__ */
drivers/net/wireless/ti/wl18xx/io.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/wlcore.h"
#include "../wlcore/io.h"
#include "io.h"
void
wl18xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
)
{
u32
tmp
;
if
(
WARN_ON
(
addr
%
2
))
return
;
if
((
addr
%
4
)
==
0
)
{
tmp
=
wl1271_read32
(
wl
,
addr
);
tmp
=
(
tmp
&
0xffff0000
)
|
val
;
wl1271_write32
(
wl
,
addr
,
tmp
);
}
else
{
tmp
=
wl1271_read32
(
wl
,
addr
-
2
);
tmp
=
(
tmp
&
0xffff
)
|
(
val
<<
16
);
wl1271_write32
(
wl
,
addr
-
2
,
tmp
);
}
}
u16
wl18xx_top_reg_read
(
struct
wl1271
*
wl
,
int
addr
)
{
u32
val
;
if
(
WARN_ON
(
addr
%
2
))
return
0
;
if
((
addr
%
4
)
==
0
)
{
/* address is 4-bytes aligned */
val
=
wl1271_read32
(
wl
,
addr
);
return
val
&
0xffff
;
}
else
{
val
=
wl1271_read32
(
wl
,
addr
-
2
);
return
(
val
&
0xffff0000
)
>>
16
;
}
}
drivers/net/wireless/ti/wl18xx/io.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__
void
wl18xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
);
u16
wl18xx_top_reg_read
(
struct
wl1271
*
wl
,
int
addr
);
#endif
/* __WL18XX_IO_H__ */
drivers/net/wireless/ti/wl18xx/main.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ip.h>
#include <linux/firmware.h>
#include "../wlcore/wlcore.h"
#include "../wlcore/debug.h"
#include "../wlcore/io.h"
#include "../wlcore/acx.h"
#include "../wlcore/tx.h"
#include "../wlcore/rx.h"
#include "../wlcore/io.h"
#include "../wlcore/boot.h"
#include "reg.h"
#include "conf.h"
#include "acx.h"
#include "tx.h"
#include "wl18xx.h"
#include "io.h"
#include "debugfs.h"
#define WL18XX_RX_CHECKSUM_MASK 0x40
static
char
*
ht_mode_param
=
"wide"
;
static
char
*
board_type_param
=
"hdk"
;
static
bool
checksum_param
=
false
;
static
bool
enable_11a_param
=
true
;
/* phy paramters */
static
int
dc2dc_param
=
-
1
;
static
int
n_antennas_2_param
=
-
1
;
static
int
n_antennas_5_param
=
-
1
;
static
int
low_band_component_param
=
-
1
;
static
int
low_band_component_type_param
=
-
1
;
static
int
high_band_component_param
=
-
1
;
static
int
high_band_component_type_param
=
-
1
;
static
int
pwr_limit_reference_11_abg_param
=
-
1
;
static
const
u8
wl18xx_rate_to_idx_2ghz
[]
=
{
/* MCS rates are used only with 11n */
15
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
14
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
13
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
12
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
11
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
10
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
9
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
8
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
7
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
6
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
5
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
4
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
3
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
2
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
1
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
0
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
11
,
/* WL18XX_CONF_HW_RXTX_RATE_54 */
10
,
/* WL18XX_CONF_HW_RXTX_RATE_48 */
9
,
/* WL18XX_CONF_HW_RXTX_RATE_36 */
8
,
/* WL18XX_CONF_HW_RXTX_RATE_24 */
/* TI-specific rate */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_22 */
7
,
/* WL18XX_CONF_HW_RXTX_RATE_18 */
6
,
/* WL18XX_CONF_HW_RXTX_RATE_12 */
3
,
/* WL18XX_CONF_HW_RXTX_RATE_11 */
5
,
/* WL18XX_CONF_HW_RXTX_RATE_9 */
4
,
/* WL18XX_CONF_HW_RXTX_RATE_6 */
2
,
/* WL18XX_CONF_HW_RXTX_RATE_5_5 */
1
,
/* WL18XX_CONF_HW_RXTX_RATE_2 */
0
/* WL18XX_CONF_HW_RXTX_RATE_1 */
};
static
const
u8
wl18xx_rate_to_idx_5ghz
[]
=
{
/* MCS rates are used only with 11n */
15
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
14
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
13
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
12
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
11
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
10
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
9
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
8
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
7
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
6
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
5
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
4
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
3
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
2
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
1
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
0
,
/* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
7
,
/* WL18XX_CONF_HW_RXTX_RATE_54 */
6
,
/* WL18XX_CONF_HW_RXTX_RATE_48 */
5
,
/* WL18XX_CONF_HW_RXTX_RATE_36 */
4
,
/* WL18XX_CONF_HW_RXTX_RATE_24 */
/* TI-specific rate */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_22 */
3
,
/* WL18XX_CONF_HW_RXTX_RATE_18 */
2
,
/* WL18XX_CONF_HW_RXTX_RATE_12 */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_11 */
1
,
/* WL18XX_CONF_HW_RXTX_RATE_9 */
0
,
/* WL18XX_CONF_HW_RXTX_RATE_6 */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_5_5 */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_2 */
CONF_HW_RXTX_RATE_UNSUPPORTED
,
/* WL18XX_CONF_HW_RXTX_RATE_1 */
};
static
const
u8
*
wl18xx_band_rate_to_idx
[]
=
{
[
IEEE80211_BAND_2GHZ
]
=
wl18xx_rate_to_idx_2ghz
,
[
IEEE80211_BAND_5GHZ
]
=
wl18xx_rate_to_idx_5ghz
};
enum
wl18xx_hw_rates
{
WL18XX_CONF_HW_RXTX_RATE_MCS15
=
0
,
WL18XX_CONF_HW_RXTX_RATE_MCS14
,
WL18XX_CONF_HW_RXTX_RATE_MCS13
,
WL18XX_CONF_HW_RXTX_RATE_MCS12
,
WL18XX_CONF_HW_RXTX_RATE_MCS11
,
WL18XX_CONF_HW_RXTX_RATE_MCS10
,
WL18XX_CONF_HW_RXTX_RATE_MCS9
,
WL18XX_CONF_HW_RXTX_RATE_MCS8
,
WL18XX_CONF_HW_RXTX_RATE_MCS7
,
WL18XX_CONF_HW_RXTX_RATE_MCS6
,
WL18XX_CONF_HW_RXTX_RATE_MCS5
,
WL18XX_CONF_HW_RXTX_RATE_MCS4
,
WL18XX_CONF_HW_RXTX_RATE_MCS3
,
WL18XX_CONF_HW_RXTX_RATE_MCS2
,
WL18XX_CONF_HW_RXTX_RATE_MCS1
,
WL18XX_CONF_HW_RXTX_RATE_MCS0
,
WL18XX_CONF_HW_RXTX_RATE_54
,
WL18XX_CONF_HW_RXTX_RATE_48
,
WL18XX_CONF_HW_RXTX_RATE_36
,
WL18XX_CONF_HW_RXTX_RATE_24
,
WL18XX_CONF_HW_RXTX_RATE_22
,
WL18XX_CONF_HW_RXTX_RATE_18
,
WL18XX_CONF_HW_RXTX_RATE_12
,
WL18XX_CONF_HW_RXTX_RATE_11
,
WL18XX_CONF_HW_RXTX_RATE_9
,
WL18XX_CONF_HW_RXTX_RATE_6
,
WL18XX_CONF_HW_RXTX_RATE_5_5
,
WL18XX_CONF_HW_RXTX_RATE_2
,
WL18XX_CONF_HW_RXTX_RATE_1
,
WL18XX_CONF_HW_RXTX_RATE_MAX
,
};
static
struct
wlcore_conf
wl18xx_conf
=
{
.
sg
=
{
.
params
=
{
[
CONF_SG_ACL_BT_MASTER_MIN_BR
]
=
10
,
[
CONF_SG_ACL_BT_MASTER_MAX_BR
]
=
180
,
[
CONF_SG_ACL_BT_SLAVE_MIN_BR
]
=
10
,
[
CONF_SG_ACL_BT_SLAVE_MAX_BR
]
=
180
,
[
CONF_SG_ACL_BT_MASTER_MIN_EDR
]
=
10
,
[
CONF_SG_ACL_BT_MASTER_MAX_EDR
]
=
80
,
[
CONF_SG_ACL_BT_SLAVE_MIN_EDR
]
=
10
,
[
CONF_SG_ACL_BT_SLAVE_MAX_EDR
]
=
80
,
[
CONF_SG_ACL_WLAN_PS_MASTER_BR
]
=
8
,
[
CONF_SG_ACL_WLAN_PS_SLAVE_BR
]
=
8
,
[
CONF_SG_ACL_WLAN_PS_MASTER_EDR
]
=
20
,
[
CONF_SG_ACL_WLAN_PS_SLAVE_EDR
]
=
20
,
[
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR
]
=
20
,
[
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR
]
=
35
,
[
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR
]
=
16
,
[
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR
]
=
35
,
[
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR
]
=
32
,
[
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR
]
=
50
,
[
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR
]
=
28
,
[
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR
]
=
50
,
[
CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR
]
=
10
,
[
CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR
]
=
20
,
[
CONF_SG_ACL_PASSIVE_SCAN_BT_BR
]
=
75
,
[
CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR
]
=
15
,
[
CONF_SG_ACL_PASSIVE_SCAN_BT_EDR
]
=
27
,
[
CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR
]
=
17
,
/* active scan params */
[
CONF_SG_AUTO_SCAN_PROBE_REQ
]
=
170
,
[
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3
]
=
50
,
[
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP
]
=
100
,
/* passive scan params */
[
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR
]
=
800
,
[
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR
]
=
200
,
[
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3
]
=
200
,
/* passive scan in dual antenna params */
[
CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN
]
=
0
,
[
CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN
]
=
0
,
[
CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN
]
=
0
,
/* general params */
[
CONF_SG_STA_FORCE_PS_IN_BT_SCO
]
=
1
,
[
CONF_SG_ANTENNA_CONFIGURATION
]
=
0
,
[
CONF_SG_BEACON_MISS_PERCENT
]
=
60
,
[
CONF_SG_DHCP_TIME
]
=
5000
,
[
CONF_SG_RXT
]
=
1200
,
[
CONF_SG_TXT
]
=
1000
,
[
CONF_SG_ADAPTIVE_RXT_TXT
]
=
1
,
[
CONF_SG_GENERAL_USAGE_BIT_MAP
]
=
3
,
[
CONF_SG_HV3_MAX_SERVED
]
=
6
,
[
CONF_SG_PS_POLL_TIMEOUT
]
=
10
,
[
CONF_SG_UPSD_TIMEOUT
]
=
10
,
[
CONF_SG_CONSECUTIVE_CTS_THRESHOLD
]
=
2
,
[
CONF_SG_STA_RX_WINDOW_AFTER_DTIM
]
=
5
,
[
CONF_SG_STA_CONNECTION_PROTECTION_TIME
]
=
30
,
/* AP params */
[
CONF_AP_BEACON_MISS_TX
]
=
3
,
[
CONF_AP_RX_WINDOW_AFTER_BEACON
]
=
10
,
[
CONF_AP_BEACON_WINDOW_INTERVAL
]
=
2
,
[
CONF_AP_CONNECTION_PROTECTION_TIME
]
=
0
,
[
CONF_AP_BT_ACL_VAL_BT_SERVE_TIME
]
=
25
,
[
CONF_AP_BT_ACL_VAL_WL_SERVE_TIME
]
=
25
,
/* CTS Diluting params */
[
CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH
]
=
0
,
[
CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER
]
=
0
,
},
.
state
=
CONF_SG_PROTECTIVE
,
},
.
rx
=
{
.
rx_msdu_life_time
=
512000
,
.
packet_detection_threshold
=
0
,
.
ps_poll_timeout
=
15
,
.
upsd_timeout
=
15
,
.
rts_threshold
=
IEEE80211_MAX_RTS_THRESHOLD
,
.
rx_cca_threshold
=
0
,
.
irq_blk_threshold
=
0xFFFF
,
.
irq_pkt_threshold
=
0
,
.
irq_timeout
=
600
,
.
queue_type
=
CONF_RX_QUEUE_TYPE_LOW_PRIORITY
,
},
.
tx
=
{
.
tx_energy_detection
=
0
,
.
sta_rc_conf
=
{
.
enabled_rates
=
0
,
.
short_retry_limit
=
10
,
.
long_retry_limit
=
10
,
.
aflags
=
0
,
},
.
ac_conf_count
=
4
,
.
ac_conf
=
{
[
CONF_TX_AC_BE
]
=
{
.
ac
=
CONF_TX_AC_BE
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
3
,
.
tx_op_limit
=
0
,
},
[
CONF_TX_AC_BK
]
=
{
.
ac
=
CONF_TX_AC_BK
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
7
,
.
tx_op_limit
=
0
,
},
[
CONF_TX_AC_VI
]
=
{
.
ac
=
CONF_TX_AC_VI
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
CONF_TX_AIFS_PIFS
,
.
tx_op_limit
=
3008
,
},
[
CONF_TX_AC_VO
]
=
{
.
ac
=
CONF_TX_AC_VO
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
CONF_TX_AIFS_PIFS
,
.
tx_op_limit
=
1504
,
},
},
.
max_tx_retries
=
100
,
.
ap_aging_period
=
300
,
.
tid_conf_count
=
4
,
.
tid_conf
=
{
[
CONF_TX_AC_BE
]
=
{
.
queue_id
=
CONF_TX_AC_BE
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_BE
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
CONF_TX_AC_BK
]
=
{
.
queue_id
=
CONF_TX_AC_BK
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_BK
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
CONF_TX_AC_VI
]
=
{
.
queue_id
=
CONF_TX_AC_VI
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_VI
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
CONF_TX_AC_VO
]
=
{
.
queue_id
=
CONF_TX_AC_VO
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_VO
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
},
.
frag_threshold
=
IEEE80211_MAX_FRAG_THRESHOLD
,
.
tx_compl_timeout
=
350
,
.
tx_compl_threshold
=
10
,
.
basic_rate
=
CONF_HW_BIT_RATE_1MBPS
,
.
basic_rate_5
=
CONF_HW_BIT_RATE_6MBPS
,
.
tmpl_short_retry_limit
=
10
,
.
tmpl_long_retry_limit
=
10
,
.
tx_watchdog_timeout
=
5000
,
},
.
conn
=
{
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
listen_interval
=
1
,
.
suspend_wake_up_event
=
CONF_WAKE_UP_EVENT_N_DTIM
,
.
suspend_listen_interval
=
3
,
.
bcn_filt_mode
=
CONF_BCN_FILT_MODE_ENABLED
,
.
bcn_filt_ie_count
=
3
,
.
bcn_filt_ie
=
{
[
0
]
=
{
.
ie
=
WLAN_EID_CHANNEL_SWITCH
,
.
rule
=
CONF_BCN_RULE_PASS_ON_APPEARANCE
,
},
[
1
]
=
{
.
ie
=
WLAN_EID_HT_OPERATION
,
.
rule
=
CONF_BCN_RULE_PASS_ON_CHANGE
,
},
[
2
]
=
{
.
ie
=
WLAN_EID_ERP_INFO
,
.
rule
=
CONF_BCN_RULE_PASS_ON_CHANGE
,
},
},
.
synch_fail_thold
=
12
,
.
bss_lose_timeout
=
400
,
.
beacon_rx_timeout
=
10000
,
.
broadcast_timeout
=
20000
,
.
rx_broadcast_in_ps
=
1
,
.
ps_poll_threshold
=
10
,
.
bet_enable
=
CONF_BET_MODE_ENABLE
,
.
bet_max_consecutive
=
50
,
.
psm_entry_retries
=
8
,
.
psm_exit_retries
=
16
,
.
psm_entry_nullfunc_retries
=
3
,
.
dynamic_ps_timeout
=
200
,
.
forced_ps
=
false
,
.
keep_alive_interval
=
55000
,
.
max_listen_interval
=
20
,
},
.
itrim
=
{
.
enable
=
false
,
.
timeout
=
50000
,
},
.
pm_config
=
{
.
host_clk_settling_time
=
5000
,
.
host_fast_wakeup_support
=
CONF_FAST_WAKEUP_DISABLE
,
},
.
roam_trigger
=
{
.
trigger_pacing
=
1
,
.
avg_weight_rssi_beacon
=
20
,
.
avg_weight_rssi_data
=
10
,
.
avg_weight_snr_beacon
=
20
,
.
avg_weight_snr_data
=
10
,
},
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
100000
,
.
max_dwell_time_passive
=
100000
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
},
.
sched_scan
=
{
/*
* Values are in TU/1000 but since sched scan FW command
* params are in TUs rounding up may occur.
*/
.
base_dwell_time
=
7500
,
.
max_dwell_time_delta
=
22500
,
/* based on 250bits per probe @1Mbps */
.
dwell_time_delta_per_probe
=
2000
,
/* based on 250bits per probe @6Mbps (plus a bit more) */
.
dwell_time_delta_per_probe_5
=
350
,
.
dwell_time_passive
=
100000
,
.
dwell_time_dfs
=
150000
,
.
num_probe_reqs
=
2
,
.
rssi_threshold
=
-
90
,
.
snr_threshold
=
0
,
},
.
ht
=
{
.
rx_ba_win_size
=
10
,
.
tx_ba_win_size
=
64
,
.
inactivity_timeout
=
10000
,
.
tx_ba_tid_bitmap
=
CONF_TX_BA_ENABLED_TID_BITMAP
,
},
.
mem
=
{
.
num_stations
=
1
,
.
ssid_profiles
=
1
,
.
rx_block_num
=
40
,
.
tx_min_block_num
=
40
,
.
dynamic_memory
=
1
,
.
min_req_tx_blocks
=
45
,
.
min_req_rx_blocks
=
22
,
.
tx_min
=
27
,
},
.
fm_coex
=
{
.
enable
=
true
,
.
swallow_period
=
5
,
.
n_divider_fref_set_1
=
0xff
,
/* default */
.
n_divider_fref_set_2
=
12
,
.
m_divider_fref_set_1
=
0xffff
,
.
m_divider_fref_set_2
=
148
,
/* default */
.
coex_pll_stabilization_time
=
0xffffffff
,
/* default */
.
ldo_stabilization_time
=
0xffff
,
/* default */
.
fm_disturbed_band_margin
=
0xff
,
/* default */
.
swallow_clk_diff
=
0xff
,
/* default */
},
.
rx_streaming
=
{
.
duration
=
150
,
.
queues
=
0x1
,
.
interval
=
20
,
.
always
=
0
,
},
.
fwlog
=
{
.
mode
=
WL12XX_FWLOG_ON_DEMAND
,
.
mem_blocks
=
2
,
.
severity
=
0
,
.
timestamp
=
WL12XX_FWLOG_TIMESTAMP_DISABLED
,
.
output
=
WL12XX_FWLOG_OUTPUT_HOST
,
.
threshold
=
0
,
},
.
rate
=
{
.
rate_retry_score
=
32000
,
.
per_add
=
8192
,
.
per_th1
=
2048
,
.
per_th2
=
4096
,
.
max_per
=
8100
,
.
inverse_curiosity_factor
=
5
,
.
tx_fail_low_th
=
4
,
.
tx_fail_high_th
=
10
,
.
per_alpha_shift
=
4
,
.
per_add_shift
=
13
,
.
per_beta1_shift
=
10
,
.
per_beta2_shift
=
8
,
.
rate_check_up
=
2
,
.
rate_check_down
=
12
,
.
rate_retry_policy
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
},
},
.
hangover
=
{
.
recover_time
=
0
,
.
hangover_period
=
20
,
.
dynamic_mode
=
1
,
.
early_termination_mode
=
1
,
.
max_period
=
20
,
.
min_period
=
1
,
.
increase_delta
=
1
,
.
decrease_delta
=
2
,
.
quiet_time
=
4
,
.
increase_time
=
1
,
.
window_size
=
16
,
},
};
static
struct
wl18xx_priv_conf
wl18xx_default_priv_conf
=
{
.
phy
=
{
.
phy_standalone
=
0x00
,
.
primary_clock_setting_time
=
0x05
,
.
clock_valid_on_wake_up
=
0x00
,
.
secondary_clock_setting_time
=
0x05
,
.
rdl
=
0x01
,
.
auto_detect
=
0x00
,
.
dedicated_fem
=
FEM_NONE
,
.
low_band_component
=
COMPONENT_2_WAY_SWITCH
,
.
low_band_component_type
=
0x05
,
.
high_band_component
=
COMPONENT_2_WAY_SWITCH
,
.
high_band_component_type
=
0x09
,
.
tcxo_ldo_voltage
=
0x00
,
.
xtal_itrim_val
=
0x04
,
.
srf_state
=
0x00
,
.
io_configuration
=
0x01
,
.
sdio_configuration
=
0x00
,
.
settings
=
0x00
,
.
enable_clpc
=
0x00
,
.
enable_tx_low_pwr_on_siso_rdl
=
0x00
,
.
rx_profile
=
0x00
,
.
pwr_limit_reference_11_abg
=
0xc8
,
.
psat
=
0
,
.
low_power_val
=
0x00
,
.
med_power_val
=
0x0a
,
.
high_power_val
=
0x1e
,
.
external_pa_dc2dc
=
0
,
.
number_of_assembled_ant2_4
=
1
,
.
number_of_assembled_ant5
=
1
,
},
};
static
const
struct
wlcore_partition_set
wl18xx_ptable
[
PART_TABLE_LEN
]
=
{
[
PART_TOP_PRCM_ELP_SOC
]
=
{
.
mem
=
{
.
start
=
0x00A02000
,
.
size
=
0x00010000
},
.
reg
=
{
.
start
=
0x00807000
,
.
size
=
0x00005000
},
.
mem2
=
{
.
start
=
0x00800000
,
.
size
=
0x0000B000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
[
PART_DOWN
]
=
{
.
mem
=
{
.
start
=
0x00000000
,
.
size
=
0x00014000
},
.
reg
=
{
.
start
=
0x00810000
,
.
size
=
0x0000BFFF
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
[
PART_BOOT
]
=
{
.
mem
=
{
.
start
=
0x00700000
,
.
size
=
0x0000030c
},
.
reg
=
{
.
start
=
0x00802000
,
.
size
=
0x00014578
},
.
mem2
=
{
.
start
=
0x00B00404
,
.
size
=
0x00001000
},
.
mem3
=
{
.
start
=
0x00C00000
,
.
size
=
0x00000400
},
},
[
PART_WORK
]
=
{
.
mem
=
{
.
start
=
0x00800000
,
.
size
=
0x000050FC
},
.
reg
=
{
.
start
=
0x00B00404
,
.
size
=
0x00001000
},
.
mem2
=
{
.
start
=
0x00C00000
,
.
size
=
0x00000400
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
[
PART_PHY_INIT
]
=
{
.
mem
=
{
.
start
=
0x80926000
,
.
size
=
sizeof
(
struct
wl18xx_mac_and_phy_params
)
},
.
reg
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
};
static
const
int
wl18xx_rtable
[
REG_TABLE_LEN
]
=
{
[
REG_ECPU_CONTROL
]
=
WL18XX_REG_ECPU_CONTROL
,
[
REG_INTERRUPT_NO_CLEAR
]
=
WL18XX_REG_INTERRUPT_NO_CLEAR
,
[
REG_INTERRUPT_ACK
]
=
WL18XX_REG_INTERRUPT_ACK
,
[
REG_COMMAND_MAILBOX_PTR
]
=
WL18XX_REG_COMMAND_MAILBOX_PTR
,
[
REG_EVENT_MAILBOX_PTR
]
=
WL18XX_REG_EVENT_MAILBOX_PTR
,
[
REG_INTERRUPT_TRIG
]
=
WL18XX_REG_INTERRUPT_TRIG_H
,
[
REG_INTERRUPT_MASK
]
=
WL18XX_REG_INTERRUPT_MASK
,
[
REG_PC_ON_RECOVERY
]
=
WL18XX_SCR_PAD4
,
[
REG_CHIP_ID_B
]
=
WL18XX_REG_CHIP_ID_B
,
[
REG_CMD_MBOX_ADDRESS
]
=
WL18XX_CMD_MBOX_ADDRESS
,
/* data access memory addresses, used with partition translation */
[
REG_SLV_MEM_DATA
]
=
WL18XX_SLV_MEM_DATA
,
[
REG_SLV_REG_DATA
]
=
WL18XX_SLV_REG_DATA
,
/* raw data access memory addresses */
[
REG_RAW_FW_STATUS_ADDR
]
=
WL18XX_FW_STATUS_ADDR
,
};
static
const
struct
wl18xx_clk_cfg
wl18xx_clk_table
[
NUM_CLOCK_CONFIGS
]
=
{
[
CLOCK_CONFIG_16_2_M
]
=
{
7
,
104
,
801
,
4
,
true
},
[
CLOCK_CONFIG_16_368_M
]
=
{
9
,
132
,
3751
,
4
,
true
},
[
CLOCK_CONFIG_16_8_M
]
=
{
7
,
100
,
0
,
0
,
false
},
[
CLOCK_CONFIG_19_2_M
]
=
{
8
,
100
,
0
,
0
,
false
},
[
CLOCK_CONFIG_26_M
]
=
{
13
,
120
,
0
,
0
,
false
},
[
CLOCK_CONFIG_32_736_M
]
=
{
9
,
132
,
3751
,
4
,
true
},
[
CLOCK_CONFIG_33_6_M
]
=
{
7
,
100
,
0
,
0
,
false
},
[
CLOCK_CONFIG_38_468_M
]
=
{
8
,
100
,
0
,
0
,
false
},
[
CLOCK_CONFIG_52_M
]
=
{
13
,
120
,
0
,
0
,
false
},
};
/* TODO: maybe move to a new header file? */
#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin"
static
int
wl18xx_identify_chip
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
switch
(
wl
->
chip
.
id
)
{
case
CHIP_ID_185x_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (185x PG20)"
,
wl
->
chip
.
id
);
wl
->
sr_fw_name
=
WL18XX_FW_NAME
;
/* wl18xx uses the same firmware for PLT */
wl
->
plt_fw_name
=
WL18XX_FW_NAME
;
wl
->
quirks
|=
WLCORE_QUIRK_NO_ELP
|
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_PAD_LAST_FRAME
;
break
;
case
CHIP_ID_185x_PG10
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (185x PG10)"
,
wl
->
chip
.
id
);
wl
->
sr_fw_name
=
WL18XX_FW_NAME
;
/* wl18xx uses the same firmware for PLT */
wl
->
plt_fw_name
=
WL18XX_FW_NAME
;
wl
->
quirks
|=
WLCORE_QUIRK_NO_ELP
|
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED
|
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
/* PG 1.0 has some problems with MCS_13, so disable it */
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
].
mcs
.
rx_mask
[
1
]
&=
~
BIT
(
5
);
break
;
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
goto
out
;
}
out:
return
ret
;
}
static
void
wl18xx_set_clk
(
struct
wl1271
*
wl
)
{
u32
clk_freq
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
/* TODO: PG2: apparently we need to read the clk type */
clk_freq
=
wl18xx_top_reg_read
(
wl
,
PRIMARY_CLK_DETECT
);
wl1271_debug
(
DEBUG_BOOT
,
"clock freq %d (%d, %d, %d, %d, %s)"
,
clk_freq
,
wl18xx_clk_table
[
clk_freq
].
n
,
wl18xx_clk_table
[
clk_freq
].
m
,
wl18xx_clk_table
[
clk_freq
].
p
,
wl18xx_clk_table
[
clk_freq
].
q
,
wl18xx_clk_table
[
clk_freq
].
swallow
?
"swallow"
:
"spit"
);
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_N
,
wl18xx_clk_table
[
clk_freq
].
n
);
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_M
,
wl18xx_clk_table
[
clk_freq
].
m
);
if
(
wl18xx_clk_table
[
clk_freq
].
swallow
)
{
/* first the 16 lower bits */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
q
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK
);
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
q
>>
16
)
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK
);
/* first the 16 lower bits */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
p
&
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK
);
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
p
>>
16
)
&
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK
);
}
else
{
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_SWALLOW_EN
,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2
);
}
}
static
void
wl18xx_boot_soft_reset
(
struct
wl1271
*
wl
)
{
/* disable Rx/Tx */
wl1271_write32
(
wl
,
WL18XX_ENABLE
,
0x0
);
/* disable auto calibration on start*/
wl1271_write32
(
wl
,
WL18XX_SPARE_A2
,
0xffff
);
}
static
int
wl18xx_pre_boot
(
struct
wl1271
*
wl
)
{
wl18xx_set_clk
(
wl
);
/* Continue the ELP wake up sequence */
wl1271_write32
(
wl
,
WL18XX_WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
udelay
(
500
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
/* Disable interrupts */
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
wl18xx_boot_soft_reset
(
wl
);
return
0
;
}
static
void
wl18xx_pre_upload
(
struct
wl1271
*
wl
)
{
u32
tmp
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
/* TODO: check if this is all needed */
wl1271_write32
(
wl
,
WL18XX_EEPROMLESS_IND
,
WL18XX_EEPROMLESS_IND
);
tmp
=
wlcore_read_reg
(
wl
,
REG_CHIP_ID_B
);
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x"
,
tmp
);
tmp
=
wl1271_read32
(
wl
,
WL18XX_SCR_PAD2
);
}
static
void
wl18xx_set_mac_and_phy
(
struct
wl1271
*
wl
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
size_t
len
;
/* the parameters struct is smaller for PG1 */
if
(
wl
->
chip
.
id
==
CHIP_ID_185x_PG10
)
len
=
offsetof
(
struct
wl18xx_mac_and_phy_params
,
psat
)
+
1
;
else
len
=
sizeof
(
struct
wl18xx_mac_and_phy_params
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_PHY_INIT
]);
wl1271_write
(
wl
,
WL18XX_PHY_INIT_MEM_ADDR
,
(
u8
*
)
&
priv
->
conf
.
phy
,
len
,
false
);
}
static
void
wl18xx_enable_interrupts
(
struct
wl1271
*
wl
)
{
u32
event_mask
,
intr_mask
;
if
(
wl
->
chip
.
id
==
CHIP_ID_185x_PG10
)
{
event_mask
=
WL18XX_ACX_EVENTS_VECTOR_PG1
;
intr_mask
=
WL18XX_INTR_MASK_PG1
;
}
else
{
event_mask
=
WL18XX_ACX_EVENTS_VECTOR_PG2
;
intr_mask
=
WL18XX_INTR_MASK_PG2
;
}
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
event_mask
);
wlcore_enable_interrupts
(
wl
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
intr_mask
);
}
static
int
wl18xx_boot
(
struct
wl1271
*
wl
)
{
int
ret
;
ret
=
wl18xx_pre_boot
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl18xx_pre_upload
(
wl
);
ret
=
wlcore_boot_upload_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl18xx_set_mac_and_phy
(
wl
);
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl18xx_enable_interrupts
(
wl
);
out:
return
ret
;
}
static
void
wl18xx_trigger_cmd
(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
memcpy
(
priv
->
cmd_buf
,
buf
,
len
);
memset
(
priv
->
cmd_buf
+
len
,
0
,
WL18XX_CMD_MAX_SIZE
-
len
);
wl1271_write
(
wl
,
cmd_box_addr
,
priv
->
cmd_buf
,
WL18XX_CMD_MAX_SIZE
,
false
);
}
static
void
wl18xx_ack_event
(
struct
wl1271
*
wl
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL18XX_INTR_TRIG_EVENT_ACK
);
}
static
u32
wl18xx_calc_tx_blocks
(
struct
wl1271
*
wl
,
u32
len
,
u32
spare_blks
)
{
u32
blk_size
=
WL18XX_TX_HW_BLOCK_SIZE
;
return
(
len
+
blk_size
-
1
)
/
blk_size
+
spare_blks
;
}
static
void
wl18xx_set_tx_desc_blocks
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
u32
blks
,
u32
spare_blks
)
{
desc
->
wl18xx_mem
.
total_mem_blocks
=
blks
;
}
static
void
wl18xx_set_tx_desc_data_len
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
)
{
desc
->
length
=
cpu_to_le16
(
skb
->
len
);
/* if only the last frame is to be padded, we unset this bit on Tx */
if
(
wl
->
quirks
&
WLCORE_QUIRK_TX_PAD_LAST_FRAME
)
desc
->
wl18xx_mem
.
ctrl
=
WL18XX_TX_CTRL_NOT_PADDED
;
else
desc
->
wl18xx_mem
.
ctrl
=
0
;
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: hlid: %d "
"len: %d life: %d mem: %d"
,
desc
->
hlid
,
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
wl18xx_mem
.
total_mem_blocks
);
}
static
enum
wl_rx_buf_align
wl18xx_get_rx_buf_align
(
struct
wl1271
*
wl
,
u32
rx_desc
)
{
if
(
rx_desc
&
RX_BUF_PADDED_PAYLOAD
)
return
WLCORE_RX_BUF_PADDED
;
return
WLCORE_RX_BUF_ALIGNED
;
}
static
u32
wl18xx_get_rx_packet_len
(
struct
wl1271
*
wl
,
void
*
rx_data
,
u32
data_len
)
{
struct
wl1271_rx_descriptor
*
desc
=
rx_data
;
/* invalid packet */
if
(
data_len
<
sizeof
(
*
desc
))
return
0
;
return
data_len
-
sizeof
(
*
desc
);
}
static
void
wl18xx_tx_immediate_completion
(
struct
wl1271
*
wl
)
{
wl18xx_tx_immediate_complete
(
wl
);
}
static
int
wl18xx_set_host_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
extra_mem_blk
)
{
int
ret
;
u32
sdio_align_size
=
0
;
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
|
HOST_IF_CFG_ADD_RX_ALIGNMENT
;
/* Enable Tx SDIO padding */
if
(
wl
->
quirks
&
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
)
{
host_cfg_bitmap
|=
HOST_IF_CFG_TX_PAD_TO_SDIO_BLK
;
sdio_align_size
=
WL12XX_BUS_BLOCK_SIZE
;
}
/* Enable Rx SDIO padding */
if
(
wl
->
quirks
&
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
)
{
host_cfg_bitmap
|=
HOST_IF_CFG_RX_PAD_TO_SDIO_BLK
;
sdio_align_size
=
WL12XX_BUS_BLOCK_SIZE
;
}
ret
=
wl18xx_acx_host_if_cfg_bitmap
(
wl
,
host_cfg_bitmap
,
sdio_align_size
,
extra_mem_blk
,
WL18XX_HOST_IF_LEN_SIZE_FIELD
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl18xx_hw_init
(
struct
wl1271
*
wl
)
{
int
ret
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
/* (re)init private structures. Relevant on recovery as well. */
priv
->
last_fw_rls_idx
=
0
;
priv
->
extra_spare_vif_count
=
0
;
/* set the default amount of spare blocks in the bitmap */
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_BLOCK_SPARE
);
if
(
ret
<
0
)
return
ret
;
if
(
checksum_param
)
{
ret
=
wl18xx_acx_set_checksum_state
(
wl
);
if
(
ret
!=
0
)
return
ret
;
}
return
ret
;
}
static
void
wl18xx_set_tx_desc_csum
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
)
{
u32
ip_hdr_offset
;
struct
iphdr
*
ip_hdr
;
if
(
!
checksum_param
)
{
desc
->
wl18xx_checksum_data
=
0
;
return
;
}
if
(
skb
->
ip_summed
!=
CHECKSUM_PARTIAL
)
{
desc
->
wl18xx_checksum_data
=
0
;
return
;
}
ip_hdr_offset
=
skb_network_header
(
skb
)
-
skb_mac_header
(
skb
);
if
(
WARN_ON
(
ip_hdr_offset
>=
(
1
<<
7
)))
{
desc
->
wl18xx_checksum_data
=
0
;
return
;
}
desc
->
wl18xx_checksum_data
=
ip_hdr_offset
<<
1
;
/* FW is interested only in the LSB of the protocol TCP=0 UDP=1 */
ip_hdr
=
(
void
*
)
skb_network_header
(
skb
);
desc
->
wl18xx_checksum_data
|=
(
ip_hdr
->
protocol
&
0x01
);
}
static
void
wl18xx_set_rx_csum
(
struct
wl1271
*
wl
,
struct
wl1271_rx_descriptor
*
desc
,
struct
sk_buff
*
skb
)
{
if
(
desc
->
status
&
WL18XX_RX_CHECKSUM_MASK
)
skb
->
ip_summed
=
CHECKSUM_UNNECESSARY
;
}
/*
* TODO: instead of having these two functions to get the rate mask,
* we should modify the wlvif->rate_set instead
*/
static
u32
wl18xx_sta_get_ap_rate_mask
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
u32
hw_rate_set
=
wlvif
->
rate_set
;
if
(
wlvif
->
channel_type
==
NL80211_CHAN_HT40MINUS
||
wlvif
->
channel_type
==
NL80211_CHAN_HT40PLUS
)
{
wl1271_debug
(
DEBUG_ACX
,
"using wide channel rate mask"
);
hw_rate_set
|=
CONF_TX_RATE_USE_WIDE_CHAN
;
/* we don't support MIMO in wide-channel mode */
hw_rate_set
&=
~
CONF_TX_MIMO_RATES
;
}
return
hw_rate_set
;
}
static
u32
wl18xx_ap_get_mimo_wide_rate_mask
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
if
((
wlvif
->
channel_type
==
NL80211_CHAN_HT40MINUS
||
wlvif
->
channel_type
==
NL80211_CHAN_HT40PLUS
)
&&
!
strcmp
(
ht_mode_param
,
"wide"
))
{
wl1271_debug
(
DEBUG_ACX
,
"using wide channel rate mask"
);
return
CONF_TX_RATE_USE_WIDE_CHAN
;
}
else
if
(
!
strcmp
(
ht_mode_param
,
"mimo"
))
{
wl1271_debug
(
DEBUG_ACX
,
"using MIMO rate mask"
);
/*
* PG 1.0 has some problems with MCS_13, so disable it
*
* TODO: instead of hacking this in here, we should
* make it more general and change a bit in the
* wlvif->rate_set instead.
*/
if
(
wl
->
chip
.
id
==
CHIP_ID_185x_PG10
)
return
CONF_TX_MIMO_RATES
&
~
CONF_HW_BIT_RATE_MCS_13
;
return
CONF_TX_MIMO_RATES
;
}
else
{
return
0
;
}
}
static
s8
wl18xx_get_pg_ver
(
struct
wl1271
*
wl
)
{
u32
fuse
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
fuse
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_DATA_1_3
);
fuse
=
(
fuse
&
WL18XX_PG_VER_MASK
)
>>
WL18XX_PG_VER_OFFSET
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
return
(
s8
)
fuse
;
}
#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
static
int
wl18xx_conf_init
(
struct
wl1271
*
wl
,
struct
device
*
dev
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
struct
wlcore_conf_file
*
conf_file
;
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL18XX_CONF_FILE_NAME
,
dev
);
if
(
ret
<
0
)
{
wl1271_error
(
"could not get configuration binary %s: %d"
,
WL18XX_CONF_FILE_NAME
,
ret
);
goto
out_fallback
;
}
if
(
fw
->
size
!=
WL18XX_CONF_SIZE
)
{
wl1271_error
(
"configuration binary file size is wrong, "
"expected %d got %d"
,
WL18XX_CONF_SIZE
,
fw
->
size
);
ret
=
-
EINVAL
;
goto
out
;
}
conf_file
=
(
struct
wlcore_conf_file
*
)
fw
->
data
;
if
(
conf_file
->
header
.
magic
!=
cpu_to_le32
(
WL18XX_CONF_MAGIC
))
{
wl1271_error
(
"configuration binary file magic number mismatch, "
"expected 0x%0x got 0x%0x"
,
WL18XX_CONF_MAGIC
,
conf_file
->
header
.
magic
);
ret
=
-
EINVAL
;
goto
out
;
}
if
(
conf_file
->
header
.
version
!=
cpu_to_le32
(
WL18XX_CONF_VERSION
))
{
wl1271_error
(
"configuration binary file version not supported, "
"expected 0x%08x got 0x%08x"
,
WL18XX_CONF_VERSION
,
conf_file
->
header
.
version
);
ret
=
-
EINVAL
;
goto
out
;
}
memcpy
(
&
wl
->
conf
,
&
conf_file
->
core
,
sizeof
(
wl18xx_conf
));
memcpy
(
&
priv
->
conf
,
&
conf_file
->
priv
,
sizeof
(
priv
->
conf
));
goto
out
;
out_fallback:
wl1271_warning
(
"falling back to default config"
);
/* apply driver default configuration */
memcpy
(
&
wl
->
conf
,
&
wl18xx_conf
,
sizeof
(
wl18xx_conf
));
/* apply default private configuration */
memcpy
(
&
priv
->
conf
,
&
wl18xx_default_priv_conf
,
sizeof
(
priv
->
conf
));
/* For now we just fallback */
return
0
;
out:
release_firmware
(
fw
);
return
ret
;
}
static
int
wl18xx_plt_init
(
struct
wl1271
*
wl
)
{
wl1271_write32
(
wl
,
WL18XX_SCR_PAD8
,
WL18XX_SCR_PAD8_PLT
);
return
wl
->
ops
->
boot
(
wl
);
}
static
void
wl18xx_get_mac
(
struct
wl1271
*
wl
)
{
u32
mac1
,
mac2
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
mac1
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_BD_ADDR_1
);
mac2
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_BD_ADDR_2
);
/* these are the two parts of the BD_ADDR */
wl
->
fuse_oui_addr
=
((
mac2
&
0xffff
)
<<
8
)
+
((
mac1
&
0xff000000
)
>>
24
);
wl
->
fuse_nic_addr
=
(
mac1
&
0xffffff
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DOWN
]);
}
static
int
wl18xx_handle_static_data
(
struct
wl1271
*
wl
,
struct
wl1271_static_data
*
static_data
)
{
struct
wl18xx_static_data_priv
*
static_data_priv
=
(
struct
wl18xx_static_data_priv
*
)
static_data
->
priv
;
wl1271_info
(
"PHY firmware version: %s"
,
static_data_priv
->
phy_version
);
return
0
;
}
static
int
wl18xx_get_spare_blocks
(
struct
wl1271
*
wl
,
bool
is_gem
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
/* If we have VIFs requiring extra spare, indulge them */
if
(
priv
->
extra_spare_vif_count
)
return
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
;
return
WL18XX_TX_HW_BLOCK_SPARE
;
}
static
int
wl18xx_set_key
(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
bool
change_spare
=
false
;
int
ret
;
/*
* when adding the first or removing the last GEM/TKIP interface,
* we have to adjust the number of spare blocks.
*/
change_spare
=
(
key_conf
->
cipher
==
WL1271_CIPHER_SUITE_GEM
||
key_conf
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
&&
((
priv
->
extra_spare_vif_count
==
0
&&
cmd
==
SET_KEY
)
||
(
priv
->
extra_spare_vif_count
==
1
&&
cmd
==
DISABLE_KEY
));
/* no need to change spare - just regular set_key */
if
(
!
change_spare
)
return
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
/*
* stop the queues and flush to ensure the next packets are
* in sync with FW spare block accounting
*/
wlcore_stop_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_SPARE_BLK
);
wl1271_tx_flush
(
wl
);
ret
=
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
if
(
ret
<
0
)
goto
out
;
/* key is now set, change the spare blocks */
if
(
cmd
==
SET_KEY
)
{
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
);
if
(
ret
<
0
)
goto
out
;
priv
->
extra_spare_vif_count
++
;
}
else
{
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_BLOCK_SPARE
);
if
(
ret
<
0
)
goto
out
;
priv
->
extra_spare_vif_count
--
;
}
out:
wlcore_wake_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_SPARE_BLK
);
return
ret
;
}
static
u32
wl18xx_pre_pkt_send
(
struct
wl1271
*
wl
,
u32
buf_offset
,
u32
last_len
)
{
if
(
wl
->
quirks
&
WLCORE_QUIRK_TX_PAD_LAST_FRAME
)
{
struct
wl1271_tx_hw_descr
*
last_desc
;
/* get the last TX HW descriptor written to the aggr buf */
last_desc
=
(
struct
wl1271_tx_hw_descr
*
)(
wl
->
aggr_buf
+
buf_offset
-
last_len
);
/* the last frame is padded up to an SDIO block */
last_desc
->
wl18xx_mem
.
ctrl
&=
~
WL18XX_TX_CTRL_NOT_PADDED
;
return
ALIGN
(
buf_offset
,
WL12XX_BUS_BLOCK_SIZE
);
}
/* no modifications */
return
buf_offset
;
}
static
struct
wlcore_ops
wl18xx_ops
=
{
.
identify_chip
=
wl18xx_identify_chip
,
.
boot
=
wl18xx_boot
,
.
plt_init
=
wl18xx_plt_init
,
.
trigger_cmd
=
wl18xx_trigger_cmd
,
.
ack_event
=
wl18xx_ack_event
,
.
calc_tx_blocks
=
wl18xx_calc_tx_blocks
,
.
set_tx_desc_blocks
=
wl18xx_set_tx_desc_blocks
,
.
set_tx_desc_data_len
=
wl18xx_set_tx_desc_data_len
,
.
get_rx_buf_align
=
wl18xx_get_rx_buf_align
,
.
get_rx_packet_len
=
wl18xx_get_rx_packet_len
,
.
tx_immediate_compl
=
wl18xx_tx_immediate_completion
,
.
tx_delayed_compl
=
NULL
,
.
hw_init
=
wl18xx_hw_init
,
.
set_tx_desc_csum
=
wl18xx_set_tx_desc_csum
,
.
get_pg_ver
=
wl18xx_get_pg_ver
,
.
set_rx_csum
=
wl18xx_set_rx_csum
,
.
sta_get_ap_rate_mask
=
wl18xx_sta_get_ap_rate_mask
,
.
ap_get_mimo_wide_rate_mask
=
wl18xx_ap_get_mimo_wide_rate_mask
,
.
get_mac
=
wl18xx_get_mac
,
.
debugfs_init
=
wl18xx_debugfs_add_files
,
.
handle_static_data
=
wl18xx_handle_static_data
,
.
get_spare_blocks
=
wl18xx_get_spare_blocks
,
.
set_key
=
wl18xx_set_key
,
.
pre_pkt_send
=
wl18xx_pre_pkt_send
,
};
/* HT cap appropriate for wide channels */
static
struct
ieee80211_sta_ht_cap
wl18xx_siso40_ht_cap
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_DSSSCCK40
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
mcs
=
{
.
rx_mask
=
{
0xff
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
},
.
rx_highest
=
cpu_to_le16
(
150
),
.
tx_params
=
IEEE80211_HT_MCS_TX_DEFINED
,
},
};
/* HT cap appropriate for SISO 20 */
static
struct
ieee80211_sta_ht_cap
wl18xx_siso20_ht_cap
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
mcs
=
{
.
rx_mask
=
{
0xff
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
},
.
rx_highest
=
cpu_to_le16
(
72
),
.
tx_params
=
IEEE80211_HT_MCS_TX_DEFINED
,
},
};
/* HT cap appropriate for MIMO rates in 20mhz channel */
static
struct
ieee80211_sta_ht_cap
wl18xx_mimo_ht_cap_2ghz
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
mcs
=
{
.
rx_mask
=
{
0xff
,
0xff
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
},
.
rx_highest
=
cpu_to_le16
(
144
),
.
tx_params
=
IEEE80211_HT_MCS_TX_DEFINED
,
},
};
static
struct
ieee80211_sta_ht_cap
wl18xx_mimo_ht_cap_5ghz
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
mcs
=
{
.
rx_mask
=
{
0xff
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
},
.
rx_highest
=
cpu_to_le16
(
72
),
.
tx_params
=
IEEE80211_HT_MCS_TX_DEFINED
,
},
};
static
int
__devinit
wl18xx_probe
(
struct
platform_device
*
pdev
)
{
struct
wl1271
*
wl
;
struct
ieee80211_hw
*
hw
;
struct
wl18xx_priv
*
priv
;
int
ret
;
hw
=
wlcore_alloc_hw
(
sizeof
(
*
priv
));
if
(
IS_ERR
(
hw
))
{
wl1271_error
(
"can't allocate hw"
);
ret
=
PTR_ERR
(
hw
);
goto
out
;
}
wl
=
hw
->
priv
;
priv
=
wl
->
priv
;
wl
->
ops
=
&
wl18xx_ops
;
wl
->
ptable
=
wl18xx_ptable
;
wl
->
rtable
=
wl18xx_rtable
;
wl
->
num_tx_desc
=
32
;
wl
->
num_rx_desc
=
16
;
wl
->
band_rate_to_idx
=
wl18xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL18XX_CONF_HW_RXTX_RATE_MAX
;
wl
->
hw_min_ht_rate
=
WL18XX_CONF_HW_RXTX_RATE_MCS0
;
wl
->
fw_status_priv_len
=
sizeof
(
struct
wl18xx_fw_status_priv
);
wl
->
stats
.
fw_stats_len
=
sizeof
(
struct
wl18xx_acx_statistics
);
wl
->
static_data_priv_len
=
sizeof
(
struct
wl18xx_static_data_priv
);
if
(
!
strcmp
(
ht_mode_param
,
"wide"
))
{
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
],
&
wl18xx_siso40_ht_cap
,
sizeof
(
wl18xx_siso40_ht_cap
));
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_5GHZ
],
&
wl18xx_siso40_ht_cap
,
sizeof
(
wl18xx_siso40_ht_cap
));
}
else
if
(
!
strcmp
(
ht_mode_param
,
"mimo"
))
{
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
],
&
wl18xx_mimo_ht_cap_2ghz
,
sizeof
(
wl18xx_mimo_ht_cap_2ghz
));
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_5GHZ
],
&
wl18xx_mimo_ht_cap_5ghz
,
sizeof
(
wl18xx_mimo_ht_cap_5ghz
));
}
else
if
(
!
strcmp
(
ht_mode_param
,
"siso20"
))
{
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
],
&
wl18xx_siso20_ht_cap
,
sizeof
(
wl18xx_siso20_ht_cap
));
memcpy
(
&
wl
->
ht_cap
[
IEEE80211_BAND_5GHZ
],
&
wl18xx_siso20_ht_cap
,
sizeof
(
wl18xx_siso20_ht_cap
));
}
else
{
wl1271_error
(
"invalid ht_mode '%s'"
,
ht_mode_param
);
ret
=
-
EINVAL
;
goto
out_free
;
}
ret
=
wl18xx_conf_init
(
wl
,
&
pdev
->
dev
);
if
(
ret
<
0
)
goto
out_free
;
if
(
!
strcmp
(
board_type_param
,
"fpga"
))
{
priv
->
conf
.
phy
.
board_type
=
BOARD_TYPE_FPGA_18XX
;
}
else
if
(
!
strcmp
(
board_type_param
,
"hdk"
))
{
priv
->
conf
.
phy
.
board_type
=
BOARD_TYPE_HDK_18XX
;
/* HACK! Just for now we hardcode HDK to 0x06 */
priv
->
conf
.
phy
.
low_band_component_type
=
0x06
;
}
else
if
(
!
strcmp
(
board_type_param
,
"dvp"
))
{
priv
->
conf
.
phy
.
board_type
=
BOARD_TYPE_DVP_18XX
;
}
else
if
(
!
strcmp
(
board_type_param
,
"evb"
))
{
priv
->
conf
.
phy
.
board_type
=
BOARD_TYPE_EVB_18XX
;
}
else
if
(
!
strcmp
(
board_type_param
,
"com8"
))
{
priv
->
conf
.
phy
.
board_type
=
BOARD_TYPE_COM8_18XX
;
/* HACK! Just for now we hardcode COM8 to 0x06 */
priv
->
conf
.
phy
.
low_band_component_type
=
0x06
;
}
else
{
wl1271_error
(
"invalid board type '%s'"
,
board_type_param
);
ret
=
-
EINVAL
;
goto
out_free
;
}
/* If the module param is set, update it in conf */
if
(
low_band_component_param
!=
-
1
)
priv
->
conf
.
phy
.
low_band_component
=
low_band_component_param
;
if
(
low_band_component_type_param
!=
-
1
)
priv
->
conf
.
phy
.
low_band_component_type
=
low_band_component_type_param
;
if
(
high_band_component_param
!=
-
1
)
priv
->
conf
.
phy
.
high_band_component
=
high_band_component_param
;
if
(
high_band_component_type_param
!=
-
1
)
priv
->
conf
.
phy
.
high_band_component_type
=
high_band_component_type_param
;
if
(
pwr_limit_reference_11_abg_param
!=
-
1
)
priv
->
conf
.
phy
.
pwr_limit_reference_11_abg
=
pwr_limit_reference_11_abg_param
;
if
(
n_antennas_2_param
!=
-
1
)
priv
->
conf
.
phy
.
number_of_assembled_ant2_4
=
n_antennas_2_param
;
if
(
n_antennas_5_param
!=
-
1
)
priv
->
conf
.
phy
.
number_of_assembled_ant5
=
n_antennas_5_param
;
if
(
dc2dc_param
!=
-
1
)
priv
->
conf
.
phy
.
external_pa_dc2dc
=
dc2dc_param
;
if
(
!
checksum_param
)
{
wl18xx_ops
.
set_rx_csum
=
NULL
;
wl18xx_ops
.
init_vif
=
NULL
;
}
wl
->
enable_11a
=
enable_11a_param
;
return
wlcore_probe
(
wl
,
pdev
);
out_free:
wlcore_free_hw
(
wl
);
out:
return
ret
;
}
static
const
struct
platform_device_id
wl18xx_id_table
[]
__devinitconst
=
{
{
"wl18xx"
,
0
},
{
}
/* Terminating Entry */
};
MODULE_DEVICE_TABLE
(
platform
,
wl18xx_id_table
);
static
struct
platform_driver
wl18xx_driver
=
{
.
probe
=
wl18xx_probe
,
.
remove
=
__devexit_p
(
wlcore_remove
),
.
id_table
=
wl18xx_id_table
,
.
driver
=
{
.
name
=
"wl18xx_driver"
,
.
owner
=
THIS_MODULE
,
}
};
static
int
__init
wl18xx_init
(
void
)
{
return
platform_driver_register
(
&
wl18xx_driver
);
}
module_init
(
wl18xx_init
);
static
void
__exit
wl18xx_exit
(
void
)
{
platform_driver_unregister
(
&
wl18xx_driver
);
}
module_exit
(
wl18xx_exit
);
module_param_named
(
ht_mode
,
ht_mode_param
,
charp
,
S_IRUSR
);
MODULE_PARM_DESC
(
ht_mode
,
"Force HT mode: wide (default), mimo or siso20"
);
module_param_named
(
board_type
,
board_type_param
,
charp
,
S_IRUSR
);
MODULE_PARM_DESC
(
board_type
,
"Board type: fpga, hdk (default), evb, com8 or "
"dvp"
);
module_param_named
(
checksum
,
checksum_param
,
bool
,
S_IRUSR
);
MODULE_PARM_DESC
(
checksum
,
"Enable TCP checksum: boolean (defaults to false)"
);
module_param_named
(
enable_11a
,
enable_11a_param
,
bool
,
S_IRUSR
);
MODULE_PARM_DESC
(
enable_11a
,
"Enable 11a (5GHz): boolean (defaults to true)"
);
module_param_named
(
dc2dc
,
dc2dc_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
dc2dc
,
"External DC2DC: u8 (defaults to 0)"
);
module_param_named
(
n_antennas_2
,
n_antennas_2_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
n_antennas_2
,
"Number of installed 2.4GHz antennas: 1 (default) or 2"
);
module_param_named
(
n_antennas_5
,
n_antennas_5_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
n_antennas_5
,
"Number of installed 5GHz antennas: 1 (default) or 2"
);
module_param_named
(
low_band_component
,
low_band_component_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
low_band_component
,
"Low band component: u8 "
"(default is 0x01)"
);
module_param_named
(
low_band_component_type
,
low_band_component_type_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
low_band_component_type
,
"Low band component type: u8 "
"(default is 0x05 or 0x06 depending on the board_type)"
);
module_param_named
(
high_band_component
,
high_band_component_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
high_band_component
,
"High band component: u8, "
"(default is 0x01)"
);
module_param_named
(
high_band_component_type
,
high_band_component_type_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
high_band_component_type
,
"High band component type: u8 "
"(default is 0x09)"
);
module_param_named
(
pwr_limit_reference_11_abg
,
pwr_limit_reference_11_abg_param
,
int
,
S_IRUSR
);
MODULE_PARM_DESC
(
pwr_limit_reference_11_abg
,
"Power limit reference: u8 "
"(default is 0xc8)"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_FIRMWARE
(
WL18XX_FW_NAME
);
drivers/net/wireless/ti/wl18xx/reg.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wlcore
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __REG_H__
#define __REG_H__
#define WL18XX_REGISTERS_BASE 0x00800000
#define WL18XX_CODE_BASE 0x00000000
#define WL18XX_DATA_BASE 0x00400000
#define WL18XX_DOUBLE_BUFFER_BASE 0x00600000
#define WL18XX_MCU_KEY_SEARCH_BASE 0x00700000
#define WL18XX_PHY_BASE 0x00900000
#define WL18XX_TOP_OCP_BASE 0x00A00000
#define WL18XX_PACKET_RAM_BASE 0x00B00000
#define WL18XX_HOST_BASE 0x00C00000
#define WL18XX_REGISTERS_DOWN_SIZE 0x0000B000
#define WL18XX_REG_BOOT_PART_START 0x00802000
#define WL18XX_REG_BOOT_PART_SIZE 0x00014578
#define WL18XX_PHY_INIT_MEM_ADDR 0x80926000
#define WL18XX_SDIO_WSPI_BASE (WL18XX_REGISTERS_BASE)
#define WL18XX_REG_CONFIG_BASE (WL18XX_REGISTERS_BASE + 0x02000)
#define WL18XX_WGCM_REGS_BASE (WL18XX_REGISTERS_BASE + 0x03000)
#define WL18XX_ENC_BASE (WL18XX_REGISTERS_BASE + 0x04000)
#define WL18XX_INTERRUPT_BASE (WL18XX_REGISTERS_BASE + 0x05000)
#define WL18XX_UART_BASE (WL18XX_REGISTERS_BASE + 0x06000)
#define WL18XX_WELP_BASE (WL18XX_REGISTERS_BASE + 0x07000)
#define WL18XX_TCP_CKSM_BASE (WL18XX_REGISTERS_BASE + 0x08000)
#define WL18XX_FIFO_BASE (WL18XX_REGISTERS_BASE + 0x09000)
#define WL18XX_OCP_BRIDGE_BASE (WL18XX_REGISTERS_BASE + 0x0A000)
#define WL18XX_PMAC_RX_BASE (WL18XX_REGISTERS_BASE + 0x14800)
#define WL18XX_PMAC_ACM_BASE (WL18XX_REGISTERS_BASE + 0x14C00)
#define WL18XX_PMAC_TX_BASE (WL18XX_REGISTERS_BASE + 0x15000)
#define WL18XX_PMAC_CSR_BASE (WL18XX_REGISTERS_BASE + 0x15400)
#define WL18XX_REG_ECPU_CONTROL (WL18XX_REGISTERS_BASE + 0x02004)
#define WL18XX_REG_INTERRUPT_NO_CLEAR (WL18XX_REGISTERS_BASE + 0x050E8)
#define WL18XX_REG_INTERRUPT_ACK (WL18XX_REGISTERS_BASE + 0x050F0)
#define WL18XX_REG_INTERRUPT_TRIG (WL18XX_REGISTERS_BASE + 0x5074)
#define WL18XX_REG_INTERRUPT_TRIG_H (WL18XX_REGISTERS_BASE + 0x5078)
#define WL18XX_REG_INTERRUPT_MASK (WL18XX_REGISTERS_BASE + 0x0050DC)
#define WL18XX_REG_CHIP_ID_B (WL18XX_REGISTERS_BASE + 0x01542C)
#define WL18XX_SLV_MEM_DATA (WL18XX_HOST_BASE + 0x0018)
#define WL18XX_SLV_REG_DATA (WL18XX_HOST_BASE + 0x0008)
/* Scratch Pad registers*/
#define WL18XX_SCR_PAD0 (WL18XX_REGISTERS_BASE + 0x0154EC)
#define WL18XX_SCR_PAD1 (WL18XX_REGISTERS_BASE + 0x0154F0)
#define WL18XX_SCR_PAD2 (WL18XX_REGISTERS_BASE + 0x0154F4)
#define WL18XX_SCR_PAD3 (WL18XX_REGISTERS_BASE + 0x0154F8)
#define WL18XX_SCR_PAD4 (WL18XX_REGISTERS_BASE + 0x0154FC)
#define WL18XX_SCR_PAD4_SET (WL18XX_REGISTERS_BASE + 0x015504)
#define WL18XX_SCR_PAD4_CLR (WL18XX_REGISTERS_BASE + 0x015500)
#define WL18XX_SCR_PAD5 (WL18XX_REGISTERS_BASE + 0x015508)
#define WL18XX_SCR_PAD5_SET (WL18XX_REGISTERS_BASE + 0x015510)
#define WL18XX_SCR_PAD5_CLR (WL18XX_REGISTERS_BASE + 0x01550C)
#define WL18XX_SCR_PAD6 (WL18XX_REGISTERS_BASE + 0x015514)
#define WL18XX_SCR_PAD7 (WL18XX_REGISTERS_BASE + 0x015518)
#define WL18XX_SCR_PAD8 (WL18XX_REGISTERS_BASE + 0x01551C)
#define WL18XX_SCR_PAD9 (WL18XX_REGISTERS_BASE + 0x015520)
/* Spare registers*/
#define WL18XX_SPARE_A1 (WL18XX_REGISTERS_BASE + 0x002194)
#define WL18XX_SPARE_A2 (WL18XX_REGISTERS_BASE + 0x002198)
#define WL18XX_SPARE_A3 (WL18XX_REGISTERS_BASE + 0x00219C)
#define WL18XX_SPARE_A4 (WL18XX_REGISTERS_BASE + 0x0021A0)
#define WL18XX_SPARE_A5 (WL18XX_REGISTERS_BASE + 0x0021A4)
#define WL18XX_SPARE_A6 (WL18XX_REGISTERS_BASE + 0x0021A8)
#define WL18XX_SPARE_A7 (WL18XX_REGISTERS_BASE + 0x0021AC)
#define WL18XX_SPARE_A8 (WL18XX_REGISTERS_BASE + 0x0021B0)
#define WL18XX_SPARE_B1 (WL18XX_REGISTERS_BASE + 0x015524)
#define WL18XX_SPARE_B2 (WL18XX_REGISTERS_BASE + 0x015528)
#define WL18XX_SPARE_B3 (WL18XX_REGISTERS_BASE + 0x01552C)
#define WL18XX_SPARE_B4 (WL18XX_REGISTERS_BASE + 0x015530)
#define WL18XX_SPARE_B5 (WL18XX_REGISTERS_BASE + 0x015534)
#define WL18XX_SPARE_B6 (WL18XX_REGISTERS_BASE + 0x015538)
#define WL18XX_SPARE_B7 (WL18XX_REGISTERS_BASE + 0x01553C)
#define WL18XX_SPARE_B8 (WL18XX_REGISTERS_BASE + 0x015540)
#define WL18XX_REG_COMMAND_MAILBOX_PTR (WL18XX_SCR_PAD0)
#define WL18XX_REG_EVENT_MAILBOX_PTR (WL18XX_SCR_PAD1)
#define WL18XX_EEPROMLESS_IND (WL18XX_SCR_PAD4)
#define WL18XX_WELP_ARM_COMMAND (WL18XX_REGISTERS_BASE + 0x7100)
#define WL18XX_ENABLE (WL18XX_REGISTERS_BASE + 0x01543C)
/* PRCM registers */
#define PLATFORM_DETECTION 0xA0E3E0
#define OCS_EN 0xA02080
#define PRIMARY_CLK_DETECT 0xA020A6
#define PLLSH_WCS_PLL_N 0xA02362
#define PLLSH_WCS_PLL_M 0xA02360
#define PLLSH_WCS_PLL_Q_FACTOR_CFG_1 0xA02364
#define PLLSH_WCS_PLL_Q_FACTOR_CFG_2 0xA02366
#define PLLSH_WCS_PLL_P_FACTOR_CFG_1 0xA02368
#define PLLSH_WCS_PLL_P_FACTOR_CFG_2 0xA0236A
#define PLLSH_WCS_PLL_SWALLOW_EN 0xA0236C
#define PLLSH_WL_PLL_EN 0xA02392
#define PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK 0xFFFF
#define PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK 0x007F
#define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK 0xFFFF
#define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK 0x000F
#define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1
#define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12
#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C
#define WL18XX_PG_VER_MASK 0x70
#define WL18XX_PG_VER_OFFSET 4
#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602
#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606
#define WL18XX_CMD_MBOX_ADDRESS 0xB007B4
#define WL18XX_FW_STATUS_ADDR 0x50F8
#define CHIP_ID_185x_PG10 (0x06030101)
#define CHIP_ID_185x_PG20 (0x06030111)
/*
* Host Command Interrupt. Setting this bit masks
* the interrupt that the host issues to inform
* the FW that it has sent a command
* to the Wlan hardware Command Mailbox.
*/
#define WL18XX_INTR_TRIG_CMD BIT(28)
/*
* Host Event Acknowlegde Interrupt. The host
* sets this bit to acknowledge that it received
* the unsolicited information from the event
* mailbox.
*/
#define WL18XX_INTR_TRIG_EVENT_ACK BIT(29)
/*
* To boot the firmware in PLT mode we need to write this value in
* SCR_PAD8 before starting.
*/
#define WL18XX_SCR_PAD8_PLT 0xBABABEBE
enum
{
COMPONENT_NO_SWITCH
=
0x0
,
COMPONENT_2_WAY_SWITCH
=
0x1
,
COMPONENT_3_WAY_SWITCH
=
0x2
,
COMPONENT_MATCHING
=
0x3
,
};
enum
{
FEM_NONE
=
0x0
,
FEM_VENDOR_1
=
0x1
,
FEM_VENDOR_2
=
0x2
,
FEM_VENDOR_3
=
0x3
,
};
enum
{
BOARD_TYPE_EVB_18XX
=
0
,
BOARD_TYPE_DVP_18XX
=
1
,
BOARD_TYPE_HDK_18XX
=
2
,
BOARD_TYPE_FPGA_18XX
=
3
,
BOARD_TYPE_COM8_18XX
=
4
,
NUM_BOARD_TYPES
,
};
#endif
/* __REG_H__ */
drivers/net/wireless/ti/wl18xx/tx.c
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/wlcore.h"
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "../wlcore/acx.h"
#include "../wlcore/tx.h"
#include "wl18xx.h"
#include "tx.h"
static
void
wl18xx_tx_complete_packet
(
struct
wl1271
*
wl
,
u8
tx_stat_byte
)
{
struct
ieee80211_tx_info
*
info
;
struct
sk_buff
*
skb
;
int
id
=
tx_stat_byte
&
WL18XX_TX_STATUS_DESC_ID_MASK
;
bool
tx_success
;
/* check for id legality */
if
(
unlikely
(
id
>=
wl
->
num_tx_desc
||
wl
->
tx_frames
[
id
]
==
NULL
))
{
wl1271_warning
(
"illegal id in tx completion: %d"
,
id
);
return
;
}
/* a zero bit indicates Tx success */
tx_success
=
!
(
tx_stat_byte
&
BIT
(
WL18XX_TX_STATUS_STAT_BIT_IDX
));
skb
=
wl
->
tx_frames
[
id
];
info
=
IEEE80211_SKB_CB
(
skb
);
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
wl1271_free_tx_id
(
wl
,
id
);
return
;
}
/* update the TX status info */
if
(
tx_success
&&
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
info
->
flags
|=
IEEE80211_TX_STAT_ACK
;
/* no real data about Tx completion */
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
info
->
status
.
rates
[
0
].
flags
=
0
;
info
->
status
.
ack_signal
=
-
1
;
if
(
!
tx_success
)
wl
->
stats
.
retry_count
++
;
/*
* TODO: update sequence number for encryption? seems to be
* unsupported for now. needed for recovery with encryption.
*/
/* remove private header from packet */
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
/* remove TKIP header space if present */
if
((
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
&&
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_EXTRA_SPACE_TKIP
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_EXTRA_SPACE_TKIP
);
}
wl1271_debug
(
DEBUG_TX
,
"tx status id %u skb 0x%p success %d"
,
id
,
skb
,
tx_success
);
/* return the packet to the stack */
skb_queue_tail
(
&
wl
->
deferred_tx_queue
,
skb
);
queue_work
(
wl
->
freezable_wq
,
&
wl
->
netstack_work
);
wl1271_free_tx_id
(
wl
,
id
);
}
void
wl18xx_tx_immediate_complete
(
struct
wl1271
*
wl
)
{
struct
wl18xx_fw_status_priv
*
status_priv
=
(
struct
wl18xx_fw_status_priv
*
)
wl
->
fw_status_2
->
priv
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
u8
i
;
/* nothing to do here */
if
(
priv
->
last_fw_rls_idx
==
status_priv
->
fw_release_idx
)
return
;
/* freed Tx descriptors */
wl1271_debug
(
DEBUG_TX
,
"last released desc = %d, current idx = %d"
,
priv
->
last_fw_rls_idx
,
status_priv
->
fw_release_idx
);
if
(
status_priv
->
fw_release_idx
>=
WL18XX_FW_MAX_TX_STATUS_DESC
)
{
wl1271_error
(
"invalid desc release index %d"
,
status_priv
->
fw_release_idx
);
WARN_ON
(
1
);
return
;
}
for
(
i
=
priv
->
last_fw_rls_idx
;
i
!=
status_priv
->
fw_release_idx
;
i
=
(
i
+
1
)
%
WL18XX_FW_MAX_TX_STATUS_DESC
)
{
wl18xx_tx_complete_packet
(
wl
,
status_priv
->
released_tx_desc
[
i
]);
wl
->
tx_results_count
++
;
}
priv
->
last_fw_rls_idx
=
status_priv
->
fw_release_idx
;
}
drivers/net/wireless/ti/wl18xx/tx.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_TX_H__
#define __WL18XX_TX_H__
#include "../wlcore/wlcore.h"
#define WL18XX_TX_HW_BLOCK_SPARE 1
/* for special cases - namely, TKIP and GEM */
#define WL18XX_TX_HW_EXTRA_BLOCK_SPARE 2
#define WL18XX_TX_HW_BLOCK_SIZE 268
#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
#define WL18XX_TX_STATUS_STAT_BIT_IDX 7
/* Indicates this TX HW frame is not padded to SDIO block size */
#define WL18XX_TX_CTRL_NOT_PADDED BIT(7)
/*
* The FW uses a special bit to indicate a wide channel should be used in
* the rate policy.
*/
#define CONF_TX_RATE_USE_WIDE_CHAN BIT(31)
void
wl18xx_tx_immediate_complete
(
struct
wl1271
*
wl
);
#endif
/* __WL12XX_TX_H__ */
drivers/net/wireless/ti/wl18xx/wl18xx.h
0 → 100644
View file @
bf34e683
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_PRIV_H__
#define __WL18XX_PRIV_H__
#include "conf.h"
#define WL18XX_CMD_MAX_SIZE 740
struct
wl18xx_priv
{
/* buffer for sending commands to FW */
u8
cmd_buf
[
WL18XX_CMD_MAX_SIZE
];
struct
wl18xx_priv_conf
conf
;
/* Index of last released Tx desc in FW */
u8
last_fw_rls_idx
;
/* number of VIFs requiring extra spare mem-blocks */
int
extra_spare_vif_count
;
};
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
struct
wl18xx_fw_status_priv
{
/*
* Index in released_tx_desc for first byte that holds
* released tx host desc
*/
u8
fw_release_idx
;
/*
* Array of host Tx descriptors, where fw_release_idx
* indicated the first released idx.
*/
u8
released_tx_desc
[
WL18XX_FW_MAX_TX_STATUS_DESC
];
u8
padding
[
2
];
};
#define WL18XX_PHY_VERSION_MAX_LEN 20
struct
wl18xx_static_data_priv
{
char
phy_version
[
WL18XX_PHY_VERSION_MAX_LEN
];
};
struct
wl18xx_clk_cfg
{
u32
n
;
u32
m
;
u32
p
;
u32
q
;
bool
swallow
;
};
enum
{
CLOCK_CONFIG_16_2_M
=
1
,
CLOCK_CONFIG_16_368_M
,
CLOCK_CONFIG_16_8_M
,
CLOCK_CONFIG_19_2_M
,
CLOCK_CONFIG_26_M
,
CLOCK_CONFIG_32_736_M
,
CLOCK_CONFIG_33_6_M
,
CLOCK_CONFIG_38_468_M
,
CLOCK_CONFIG_52_M
,
NUM_CLOCK_CONFIGS
,
};
#endif
/* __WL18XX_PRIV_H__ */
drivers/net/wireless/ti/wlcore/acx.c
View file @
bf34e683
...
...
@@ -86,6 +86,7 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
kfree
(
auth
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl1271_acx_sleep_auth
);
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
power
)
...
...
@@ -708,14 +709,14 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
}
int
wl1271_acx_statistics
(
struct
wl1271
*
wl
,
struct
acx_statistics
*
stats
)
int
wl1271_acx_statistics
(
struct
wl1271
*
wl
,
void
*
stats
)
{
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx statistics"
);
ret
=
wl1271_cmd_interrogate
(
wl
,
ACX_STATISTICS
,
stats
,
sizeof
(
*
stats
)
);
wl
->
stats
.
fw_stats_len
);
if
(
ret
<
0
)
{
wl1271_warning
(
"acx statistics failed: %d"
,
ret
);
return
-
ENOMEM
;
...
...
@@ -997,6 +998,7 @@ int wl12xx_acx_mem_cfg(struct wl1271 *wl)
kfree
(
mem_conf
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl12xx_acx_mem_cfg
);
int
wl1271_acx_init_mem_config
(
struct
wl1271
*
wl
)
{
...
...
@@ -1027,6 +1029,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl)
return
0
;
}
EXPORT_SYMBOL_GPL
(
wl1271_acx_init_mem_config
);
int
wl1271_acx_init_rx_interrupt
(
struct
wl1271
*
wl
)
{
...
...
@@ -1150,6 +1153,7 @@ int wl1271_acx_pm_config(struct wl1271 *wl)
kfree
(
acx
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl1271_acx_pm_config
);
int
wl1271_acx_keep_alive_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
)
...
...
drivers/net/wireless/ti/wlcore/acx.h
View file @
bf34e683
...
...
@@ -51,21 +51,18 @@
#define WL1271_ACX_INTR_TRACE_A BIT(7)
/* Trace message on MBOX #B */
#define WL1271_ACX_INTR_TRACE_B BIT(8)
/* SW FW Initiated interrupt Watchdog timer expiration */
#define WL1271_ACX_SW_INTR_WATCHDOG BIT(9)
#define WL1271_ACX_INTR_ALL 0xFFFFFFFF
#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
/* all possible interrupts - only appropriate ones will be masked in */
#define WLCORE_ALL_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
WL1271_ACX_INTR_DATA | \
WL1271_ACX_SW_INTR_WATCHDOG)
/* Target's information element */
struct
acx_header
{
...
...
@@ -417,228 +414,6 @@ struct acx_ctsprotect {
u8
padding
[
2
];
}
__packed
;
struct
acx_tx_statistics
{
__le32
internal_desc_overflow
;
}
__packed
;
struct
acx_rx_statistics
{
__le32
out_of_mem
;
__le32
hdr_overflow
;
__le32
hw_stuck
;
__le32
dropped
;
__le32
fcs_err
;
__le32
xfr_hint_trig
;
__le32
path_reset
;
__le32
reset_counter
;
}
__packed
;
struct
acx_dma_statistics
{
__le32
rx_requested
;
__le32
rx_errors
;
__le32
tx_requested
;
__le32
tx_errors
;
}
__packed
;
struct
acx_isr_statistics
{
/* host command complete */
__le32
cmd_cmplt
;
/* fiqisr() */
__le32
fiqs
;
/* (INT_STS_ND & INT_TRIG_RX_HEADER) */
__le32
rx_headers
;
/* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
__le32
rx_completes
;
/* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
__le32
rx_mem_overflow
;
/* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
__le32
rx_rdys
;
/* irqisr() */
__le32
irqs
;
/* (INT_STS_ND & INT_TRIG_TX_PROC) */
__le32
tx_procs
;
/* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
__le32
decrypt_done
;
/* (INT_STS_ND & INT_TRIG_DMA0) */
__le32
dma0_done
;
/* (INT_STS_ND & INT_TRIG_DMA1) */
__le32
dma1_done
;
/* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
__le32
tx_exch_complete
;
/* (INT_STS_ND & INT_TRIG_COMMAND) */
__le32
commands
;
/* (INT_STS_ND & INT_TRIG_RX_PROC) */
__le32
rx_procs
;
/* (INT_STS_ND & INT_TRIG_PM_802) */
__le32
hw_pm_mode_changes
;
/* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
__le32
host_acknowledges
;
/* (INT_STS_ND & INT_TRIG_PM_PCI) */
__le32
pci_pm
;
/* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
__le32
wakeups
;
/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
__le32
low_rssi
;
}
__packed
;
struct
acx_wep_statistics
{
/* WEP address keys configured */
__le32
addr_key_count
;
/* default keys configured */
__le32
default_key_count
;
__le32
reserved
;
/* number of times that WEP key not found on lookup */
__le32
key_not_found
;
/* number of times that WEP key decryption failed */
__le32
decrypt_fail
;
/* WEP packets decrypted */
__le32
packets
;
/* WEP decrypt interrupts */
__le32
interrupt
;
}
__packed
;
#define ACX_MISSED_BEACONS_SPREAD 10
struct
acx_pwr_statistics
{
/* the amount of enters into power save mode (both PD & ELP) */
__le32
ps_enter
;
/* the amount of enters into ELP mode */
__le32
elp_enter
;
/* the amount of missing beacon interrupts to the host */
__le32
missing_bcns
;
/* the amount of wake on host-access times */
__le32
wake_on_host
;
/* the amount of wake on timer-expire */
__le32
wake_on_timer_exp
;
/* the number of packets that were transmitted with PS bit set */
__le32
tx_with_ps
;
/* the number of packets that were transmitted with PS bit clear */
__le32
tx_without_ps
;
/* the number of received beacons */
__le32
rcvd_beacons
;
/* the number of entering into PowerOn (power save off) */
__le32
power_save_off
;
/* the number of entries into power save mode */
__le16
enable_ps
;
/*
* the number of exits from power save, not including failed PS
* transitions
*/
__le16
disable_ps
;
/*
* the number of times the TSF counter was adjusted because
* of drift
*/
__le32
fix_tsf_ps
;
/* Gives statistics about the spread continuous missed beacons.
* The 16 LSB are dedicated for the PS mode.
* The 16 MSB are dedicated for the PS mode.
* cont_miss_bcns_spread[0] - single missed beacon.
* cont_miss_bcns_spread[1] - two continuous missed beacons.
* cont_miss_bcns_spread[2] - three continuous missed beacons.
* ...
* cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
*/
__le32
cont_miss_bcns_spread
[
ACX_MISSED_BEACONS_SPREAD
];
/* the number of beacons in awake mode */
__le32
rcvd_awake_beacons
;
}
__packed
;
struct
acx_mic_statistics
{
__le32
rx_pkts
;
__le32
calc_failure
;
}
__packed
;
struct
acx_aes_statistics
{
__le32
encrypt_fail
;
__le32
decrypt_fail
;
__le32
encrypt_packets
;
__le32
decrypt_packets
;
__le32
encrypt_interrupt
;
__le32
decrypt_interrupt
;
}
__packed
;
struct
acx_event_statistics
{
__le32
heart_beat
;
__le32
calibration
;
__le32
rx_mismatch
;
__le32
rx_mem_empty
;
__le32
rx_pool
;
__le32
oom_late
;
__le32
phy_transmit_error
;
__le32
tx_stuck
;
}
__packed
;
struct
acx_ps_statistics
{
__le32
pspoll_timeouts
;
__le32
upsd_timeouts
;
__le32
upsd_max_sptime
;
__le32
upsd_max_apturn
;
__le32
pspoll_max_apturn
;
__le32
pspoll_utilization
;
__le32
upsd_utilization
;
}
__packed
;
struct
acx_rxpipe_statistics
{
__le32
rx_prep_beacon_drop
;
__le32
descr_host_int_trig_rx_data
;
__le32
beacon_buffer_thres_host_int_trig_rx_data
;
__le32
missed_beacon_host_int_trig_rx_data
;
__le32
tx_xfr_host_int_trig_rx_data
;
}
__packed
;
struct
acx_statistics
{
struct
acx_header
header
;
struct
acx_tx_statistics
tx
;
struct
acx_rx_statistics
rx
;
struct
acx_dma_statistics
dma
;
struct
acx_isr_statistics
isr
;
struct
acx_wep_statistics
wep
;
struct
acx_pwr_statistics
pwr
;
struct
acx_aes_statistics
aes
;
struct
acx_mic_statistics
mic
;
struct
acx_event_statistics
event
;
struct
acx_ps_statistics
ps
;
struct
acx_rxpipe_statistics
rxpipe
;
}
__packed
;
struct
acx_rate_class
{
__le32
enabled_rates
;
u8
short_retry_limit
;
...
...
@@ -828,6 +603,8 @@ struct wl1271_acx_keep_alive_config {
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
#define HOST_IF_CFG_RX_PAD_TO_SDIO_BLK BIT(4)
#define HOST_IF_CFG_ADD_RX_ALIGNMENT BIT(6)
enum
{
WL1271_ACX_TRIG_TYPE_LEVEL
=
0
,
...
...
@@ -946,7 +723,7 @@ struct wl1271_acx_ht_information {
u8
padding
[
2
];
}
__packed
;
#define RX_BA_MAX_SESSIONS
2
#define RX_BA_MAX_SESSIONS
3
struct
wl1271_acx_ba_initiator_policy
{
struct
acx_header
header
;
...
...
@@ -1243,6 +1020,7 @@ enum {
ACX_CONFIG_HANGOVER
=
0x0042
,
ACX_FEATURE_CFG
=
0x0043
,
ACX_PROTECTION_CFG
=
0x0044
,
ACX_CHECKSUM_CONFIG
=
0x0045
,
};
...
...
@@ -1281,7 +1059,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum
acx_preamble_type
preamble
);
int
wl1271_acx_cts_protect
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_ctsprotect_type
ctsprotect
);
int
wl1271_acx_statistics
(
struct
wl1271
*
wl
,
struct
acx_statistics
*
stats
);
int
wl1271_acx_statistics
(
struct
wl1271
*
wl
,
void
*
stats
);
int
wl1271_acx_sta_rate_policies
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_ap_rate_policy
(
struct
wl1271
*
wl
,
struct
conf_tx_rate_class
*
c
,
u8
idx
);
...
...
drivers/net/wireless/ti/wlcore/boot.c
View file @
bf34e683
...
...
@@ -45,10 +45,17 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
wlcore_write_reg
(
wl
,
REG_ECPU_CONTROL
,
cpu_ctrl
);
}
static
int
wlcore_parse_fw_ver
(
struct
wl1271
*
wl
)
static
int
wlcore_boot_parse_fw_ver
(
struct
wl1271
*
wl
,
struct
wl1271_static_data
*
static_data
)
{
int
ret
;
strncpy
(
wl
->
chip
.
fw_ver_str
,
static_data
->
fw_version
,
sizeof
(
wl
->
chip
.
fw_ver_str
));
/* make sure the string is NULL-terminated */
wl
->
chip
.
fw_ver_str
[
sizeof
(
wl
->
chip
.
fw_ver_str
)
-
1
]
=
'\0'
;
ret
=
sscanf
(
wl
->
chip
.
fw_ver_str
+
4
,
"%u.%u.%u.%u.%u"
,
&
wl
->
chip
.
fw_ver
[
0
],
&
wl
->
chip
.
fw_ver
[
1
],
&
wl
->
chip
.
fw_ver
[
2
],
&
wl
->
chip
.
fw_ver
[
3
],
...
...
@@ -57,43 +64,43 @@ static int wlcore_parse_fw_ver(struct wl1271 *wl)
if
(
ret
!=
5
)
{
wl1271_warning
(
"fw version incorrect value"
);
memset
(
wl
->
chip
.
fw_ver
,
0
,
sizeof
(
wl
->
chip
.
fw_ver
));
return
-
EINVAL
;
ret
=
-
EINVAL
;
goto
out
;
}
ret
=
wlcore_identify_fw
(
wl
);
if
(
ret
<
0
)
goto
out
;
out:
return
ret
;
return
0
;
}
static
int
wlcore_boot_
fw_version
(
struct
wl1271
*
wl
)
static
int
wlcore_boot_
static_data
(
struct
wl1271
*
wl
)
{
struct
wl1271_static_data
*
static_data
;
size_t
len
=
sizeof
(
*
static_data
)
+
wl
->
static_data_priv_len
;
int
ret
;
static_data
=
kmalloc
(
sizeof
(
*
static_data
),
GFP_KERNEL
|
GFP_DMA
);
static_data
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
!
static_data
)
{
wl1271_error
(
"Couldn't allocate memory for static data!"
)
;
return
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
out
;
}
wl1271_read
(
wl
,
wl
->
cmd_box_addr
,
static_data
,
sizeof
(
*
static_data
),
false
);
wl1271_read
(
wl
,
wl
->
cmd_box_addr
,
static_data
,
len
,
false
);
strncpy
(
wl
->
chip
.
fw_ver_str
,
static_data
->
fw_version
,
sizeof
(
wl
->
chip
.
fw_ver_str
));
kfree
(
static_data
);
/* make sure the string is NULL-terminated */
wl
->
chip
.
fw_ver_str
[
sizeof
(
wl
->
chip
.
fw_ver_str
)
-
1
]
=
'\0'
;
ret
=
wlcore_boot_parse_fw_ver
(
wl
,
static_data
);
if
(
ret
<
0
)
goto
out_free
;
ret
=
wlcore_
parse_fw_ver
(
wl
);
ret
=
wlcore_
handle_static_data
(
wl
,
static_data
);
if
(
ret
<
0
)
return
ret
;
goto
out_free
;
return
0
;
out_free:
kfree
(
static_data
);
out:
return
ret
;
}
static
int
wl1271_boot_upload_firmware_chunk
(
struct
wl1271
*
wl
,
void
*
buf
,
...
...
@@ -204,8 +211,10 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
u32
dest_addr
,
val
;
u8
*
nvs_ptr
,
*
nvs_aligned
;
if
(
wl
->
nvs
==
NULL
)
if
(
wl
->
nvs
==
NULL
)
{
wl1271_error
(
"NVS file is needed during boot"
);
return
-
ENODEV
;
}
if
(
wl
->
quirks
&
WLCORE_QUIRK_LEGACY_NVS
)
{
struct
wl1271_nvs_file
*
nvs
=
...
...
@@ -400,9 +409,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
wl1271_debug
(
DEBUG_MAILBOX
,
"MBOX ptrs: 0x%x 0x%x"
,
wl
->
mbox_ptr
[
0
],
wl
->
mbox_ptr
[
1
]);
ret
=
wlcore_boot_
fw_version
(
wl
);
ret
=
wlcore_boot_
static_data
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"
couldn't boot firmware
"
);
wl1271_error
(
"
error getting static data
"
);
return
ret
;
}
...
...
drivers/net/wireless/ti/wlcore/boot.h
View file @
bf34e683
...
...
@@ -40,6 +40,7 @@ struct wl1271_static_data {
u8
fw_version
[
WL1271_FW_VERSION_MAX_LEN
];
u32
hw_version
;
u8
tx_power_table
[
WL1271_NO_SUBBANDS
][
WL1271_NO_POWER_LEVELS
];
u8
priv
[
0
];
};
/* number of times we try to read the INIT interrupt */
...
...
drivers/net/wireless/ti/wlcore/cmd.c
View file @
bf34e683
...
...
@@ -36,6 +36,7 @@
#include "cmd.h"
#include "event.h"
#include "tx.h"
#include "hw_ops.h"
#define WL1271_CMD_FAST_POLL_COUNT 50
...
...
@@ -291,6 +292,23 @@ static int wl12xx_get_new_session_id(struct wl1271 *wl,
return
wlvif
->
session_counter
;
}
static
u8
wlcore_get_native_channel_type
(
u8
nl_channel_type
)
{
switch
(
nl_channel_type
)
{
case
NL80211_CHAN_NO_HT
:
return
WLCORE_CHAN_NO_HT
;
case
NL80211_CHAN_HT20
:
return
WLCORE_CHAN_HT20
;
case
NL80211_CHAN_HT40MINUS
:
return
WLCORE_CHAN_HT40MINUS
;
case
NL80211_CHAN_HT40PLUS
:
return
WLCORE_CHAN_HT40PLUS
;
default:
WARN_ON
(
1
);
return
WLCORE_CHAN_NO_HT
;
}
}
static
int
wl12xx_cmd_role_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
...
...
@@ -407,6 +425,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
memcpy
(
cmd
->
sta
.
ssid
,
wlvif
->
ssid
,
wlvif
->
ssid_len
);
memcpy
(
cmd
->
sta
.
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wlvif
->
rate_set
);
cmd
->
channel_type
=
wlcore_get_native_channel_type
(
wlvif
->
channel_type
);
if
(
wlvif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
...
...
@@ -482,6 +501,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
struct
wl12xx_cmd_role_start
*
cmd
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
ieee80211_bss_conf
*
bss_conf
=
&
vif
->
bss_conf
;
u32
supported_rates
;
int
ret
;
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ap %d"
,
wlvif
->
role_id
);
...
...
@@ -519,6 +539,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
/* FIXME: Change when adding DFS */
cmd
->
ap
.
reset_tsf
=
1
;
/* By default reset AP TSF */
cmd
->
channel
=
wlvif
->
channel
;
cmd
->
channel_type
=
wlcore_get_native_channel_type
(
wlvif
->
channel_type
);
if
(
!
bss_conf
->
hidden_ssid
)
{
/* take the SSID from the beacon for backward compatibility */
...
...
@@ -531,7 +552,13 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
memcpy
(
cmd
->
ap
.
ssid
,
bss_conf
->
ssid
,
bss_conf
->
ssid_len
);
}
cmd
->
ap
.
local_rates
=
cpu_to_le32
(
0xffffffff
);
supported_rates
=
CONF_TX_AP_ENABLED_RATES
|
CONF_TX_MCS_RATES
|
wlcore_hw_ap_get_mimo_wide_rate_mask
(
wl
,
wlvif
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ap with supported_rates 0x%08x"
,
supported_rates
);
cmd
->
ap
.
local_rates
=
cpu_to_le32
(
supported_rates
);
switch
(
wlvif
->
band
)
{
case
IEEE80211_BAND_2GHZ
:
...
...
@@ -797,6 +824,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
kfree
(
cmd
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl1271_cmd_data_path
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
,
u16
auto_ps_timeout
)
...
...
@@ -1018,7 +1046,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
,
extra
;
int
ret
,
extra
=
0
;
u16
fc
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
sk_buff
*
skb
;
...
...
@@ -1057,6 +1085,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif)
/* encryption space */
switch
(
wlvif
->
encryption_type
)
{
case
KEY_TKIP
:
if
(
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
extra
=
WL1271_EXTRA_SPACE_TKIP
;
break
;
case
KEY_AES
:
...
...
@@ -1346,13 +1375,18 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
for
(
i
=
0
;
i
<
NUM_ACCESS_CATEGORIES_COPY
;
i
++
)
if
(
sta
->
wme
&&
(
sta
->
uapsd_queues
&
BIT
(
i
)))
cmd
->
psd_type
[
i
]
=
WL1271_PSD_UPSD_TRIGGER
;
cmd
->
psd_type
[
NUM_ACCESS_CATEGORIES_COPY
-
1
-
i
]
=
WL1271_PSD_UPSD_TRIGGER
;
else
cmd
->
psd_type
[
i
]
=
WL1271_PSD_LEGACY
;
cmd
->
psd_type
[
NUM_ACCESS_CATEGORIES_COPY
-
1
-
i
]
=
WL1271_PSD_LEGACY
;
sta_rates
=
sta
->
supp_rates
[
wlvif
->
band
];
if
(
sta
->
ht_cap
.
ht_supported
)
sta_rates
|=
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
;
sta_rates
|=
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
)
|
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
1
]
<<
HW_MIMO_RATES_OFFSET
);
cmd
->
supported_rates
=
cpu_to_le32
(
wl1271_tx_enabled_rates_get
(
wl
,
sta_rates
,
...
...
@@ -1573,20 +1607,26 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
)
{
int
ret
=
0
;
bool
is_first_roc
;
if
(
WARN_ON
(
test_bit
(
role_id
,
wl
->
roc_map
)))
return
0
;
is_first_roc
=
(
find_first_bit
(
wl
->
roc_map
,
WL12XX_MAX_ROLES
)
>=
WL12XX_MAX_ROLES
);
ret
=
wl12xx_cmd_roc
(
wl
,
wlvif
,
role_id
);
if
(
ret
<
0
)
goto
out
;
if
(
is_first_roc
)
{
ret
=
wl1271_cmd_wait_for_event
(
wl
,
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
);
if
(
ret
<
0
)
{
wl1271_error
(
"cmd roc event completion error"
);
goto
out
;
}
}
__set_bit
(
role_id
,
wl
->
roc_map
);
out:
...
...
drivers/net/wireless/ti/wlcore/cmd.h
View file @
bf34e683
...
...
@@ -192,7 +192,7 @@ enum cmd_templ {
#define WL1271_COMMAND_TIMEOUT 2000
#define WL1271_CMD_TEMPL_DFLT_SIZE 252
#define WL1271_CMD_TEMPL_MAX_SIZE 512
#define WL1271_EVENT_TIMEOUT
75
0
#define WL1271_EVENT_TIMEOUT
100
0
struct
wl1271_cmd_header
{
__le16
id
;
...
...
@@ -266,13 +266,22 @@ enum wlcore_band {
WLCORE_BAND_MAX_RADIO
=
0x7F
,
};
enum
wlcore_channel_type
{
WLCORE_CHAN_NO_HT
,
WLCORE_CHAN_HT20
,
WLCORE_CHAN_HT40MINUS
,
WLCORE_CHAN_HT40PLUS
};
struct
wl12xx_cmd_role_start
{
struct
wl1271_cmd_header
header
;
u8
role_id
;
u8
band
;
u8
channel
;
u8
padding
;
/* enum wlcore_channel_type */
u8
channel_type
;
union
{
struct
{
...
...
drivers/net/wireless/ti/wlcore/conf.h
View file @
bf34e683
...
...
@@ -45,7 +45,15 @@ enum {
CONF_HW_BIT_RATE_MCS_4
=
BIT
(
17
),
CONF_HW_BIT_RATE_MCS_5
=
BIT
(
18
),
CONF_HW_BIT_RATE_MCS_6
=
BIT
(
19
),
CONF_HW_BIT_RATE_MCS_7
=
BIT
(
20
)
CONF_HW_BIT_RATE_MCS_7
=
BIT
(
20
),
CONF_HW_BIT_RATE_MCS_8
=
BIT
(
21
),
CONF_HW_BIT_RATE_MCS_9
=
BIT
(
22
),
CONF_HW_BIT_RATE_MCS_10
=
BIT
(
23
),
CONF_HW_BIT_RATE_MCS_11
=
BIT
(
24
),
CONF_HW_BIT_RATE_MCS_12
=
BIT
(
25
),
CONF_HW_BIT_RATE_MCS_13
=
BIT
(
26
),
CONF_HW_BIT_RATE_MCS_14
=
BIT
(
27
),
CONF_HW_BIT_RATE_MCS_15
=
BIT
(
28
),
};
enum
{
...
...
@@ -310,7 +318,7 @@ enum {
struct
conf_sg_settings
{
u32
params
[
CONF_SG_PARAMS_MAX
];
u8
state
;
};
}
__packed
;
enum
conf_rx_queue_type
{
CONF_RX_QUEUE_TYPE_LOW_PRIORITY
,
/* All except the high priority */
...
...
@@ -394,7 +402,7 @@ struct conf_rx_settings {
* Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY,
*/
u8
queue_type
;
};
}
__packed
;
#define CONF_TX_MAX_RATE_CLASSES 10
...
...
@@ -435,6 +443,12 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \
CONF_HW_BIT_RATE_MCS_7)
#define CONF_TX_MIMO_RATES (CONF_HW_BIT_RATE_MCS_8 | \
CONF_HW_BIT_RATE_MCS_9 | CONF_HW_BIT_RATE_MCS_10 | \
CONF_HW_BIT_RATE_MCS_11 | CONF_HW_BIT_RATE_MCS_12 | \
CONF_HW_BIT_RATE_MCS_13 | CONF_HW_BIT_RATE_MCS_14 | \
CONF_HW_BIT_RATE_MCS_15)
/*
* Default rates for management traffic when operating in AP mode. This
* should be configured according to the basic rate set of the AP
...
...
@@ -487,7 +501,7 @@ struct conf_tx_rate_class {
* the policy (0 - long preamble, 1 - short preamble.
*/
u8
aflags
;
};
}
__packed
;
#define CONF_TX_MAX_AC_COUNT 4
...
...
@@ -504,7 +518,7 @@ enum conf_tx_ac {
CONF_TX_AC_VI
=
2
,
/* video */
CONF_TX_AC_VO
=
3
,
/* voice */
CONF_TX_AC_CTS2SELF
=
4
,
/* fictitious AC, follows AC_VO */
CONF_TX_AC_ANY_TID
=
0x
1
f
CONF_TX_AC_ANY_TID
=
0x
f
f
};
struct
conf_tx_ac_category
{
...
...
@@ -544,7 +558,7 @@ struct conf_tx_ac_category {
* Range: u16
*/
u16
tx_op_limit
;
};
}
__packed
;
#define CONF_TX_MAX_TID_COUNT 8
...
...
@@ -578,7 +592,7 @@ struct conf_tx_tid {
u8
ps_scheme
;
u8
ack_policy
;
u32
apsd_conf
[
2
];
};
}
__packed
;
struct
conf_tx_settings
{
/*
...
...
@@ -664,7 +678,7 @@ struct conf_tx_settings {
/* Time in ms for Tx watchdog timer to expire */
u32
tx_watchdog_timeout
;
};
}
__packed
;
enum
{
CONF_WAKE_UP_EVENT_BEACON
=
0x01
,
/* Wake on every Beacon*/
...
...
@@ -711,7 +725,7 @@ struct conf_bcn_filt_rule {
* Version for the vendor specifie IE (221)
*/
u8
version
[
CONF_BCN_IE_VER_LEN
];
};
}
__packed
;
#define CONF_MAX_RSSI_SNR_TRIGGERS 8
...
...
@@ -762,7 +776,7 @@ struct conf_sig_weights {
* Range: u8
*/
u8
snr_pkt_avg_weight
;
};
}
__packed
;
enum
conf_bcn_filt_mode
{
CONF_BCN_FILT_MODE_DISABLED
=
0
,
...
...
@@ -810,7 +824,7 @@ struct conf_conn_settings {
*
* Range: CONF_BCN_FILT_MODE_*
*/
enum
conf_bcn_filt_mode
bcn_filt_mode
;
u8
bcn_filt_mode
;
/*
* Configure Beacon filter pass-thru rules.
...
...
@@ -937,7 +951,7 @@ struct conf_conn_settings {
* Range: u16
*/
u8
max_listen_interval
;
};
}
__packed
;
enum
{
CONF_REF_CLK_19_2_E
,
...
...
@@ -965,6 +979,11 @@ struct conf_itrim_settings {
/* moderation timeout in microsecs from the last TX */
u32
timeout
;
}
__packed
;
enum
conf_fast_wakeup
{
CONF_FAST_WAKEUP_ENABLE
,
CONF_FAST_WAKEUP_DISABLE
,
};
struct
conf_pm_config_settings
{
...
...
@@ -978,10 +997,10 @@ struct conf_pm_config_settings {
/*
* Host fast wakeup support
*
* Range:
true, false
* Range:
enum conf_fast_wakeup
*/
bool
host_fast_wakeup_support
;
};
u8
host_fast_wakeup_support
;
}
__packed
;
struct
conf_roam_trigger_settings
{
/*
...
...
@@ -1018,7 +1037,7 @@ struct conf_roam_trigger_settings {
* Range: 0 - 255
*/
u8
avg_weight_snr_data
;
};
}
__packed
;
struct
conf_scan_settings
{
/*
...
...
@@ -1064,7 +1083,7 @@ struct conf_scan_settings {
* Range: u32 Microsecs
*/
u32
split_scan_timeout
;
};
}
__packed
;
struct
conf_sched_scan_settings
{
/*
...
...
@@ -1102,7 +1121,7 @@ struct conf_sched_scan_settings {
/* SNR threshold to be used for filtering */
s8
snr_threshold
;
};
}
__packed
;
struct
conf_ht_setting
{
u8
rx_ba_win_size
;
...
...
@@ -1111,7 +1130,7 @@ struct conf_ht_setting {
/* bitmap of enabled TIDs for TX BA sessions */
u8
tx_ba_tid_bitmap
;
};
}
__packed
;
struct
conf_memory_settings
{
/* Number of stations supported in IBSS mode */
...
...
@@ -1151,7 +1170,7 @@ struct conf_memory_settings {
* Range: 0-120
*/
u8
tx_min
;
};
}
__packed
;
struct
conf_fm_coex
{
u8
enable
;
...
...
@@ -1164,7 +1183,7 @@ struct conf_fm_coex {
u16
ldo_stabilization_time
;
u8
fm_disturbed_band_margin
;
u8
swallow_clk_diff
;
};
}
__packed
;
struct
conf_rx_streaming_settings
{
/*
...
...
@@ -1193,7 +1212,7 @@ struct conf_rx_streaming_settings {
* enable rx streaming also when there is no coex activity
*/
u8
always
;
};
}
__packed
;
struct
conf_fwlog
{
/* Continuous or on-demand */
...
...
@@ -1217,7 +1236,7 @@ struct conf_fwlog {
/* Regulates the frequency of log messages */
u8
threshold
;
};
}
__packed
;
#define ACX_RATE_MGMT_NUM_OF_RATES 13
struct
conf_rate_policy_settings
{
...
...
@@ -1236,7 +1255,7 @@ struct conf_rate_policy_settings {
u8
rate_check_up
;
u8
rate_check_down
;
u8
rate_retry_policy
[
ACX_RATE_MGMT_NUM_OF_RATES
];
};
}
__packed
;
struct
conf_hangover_settings
{
u32
recover_time
;
...
...
@@ -1250,7 +1269,23 @@ struct conf_hangover_settings {
u8
quiet_time
;
u8
increase_time
;
u8
window_size
;
};
}
__packed
;
/*
* The conf version consists of 4 bytes. The two MSB are the wlcore
* version, the two LSB are the lower driver's private conf
* version.
*/
#define WLCORE_CONF_VERSION (0x0001 << 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
struct
wlcore_conf_header
{
__le32
magic
;
__le32
version
;
__le32
checksum
;
}
__packed
;
struct
wlcore_conf
{
struct
conf_sg_settings
sg
;
...
...
@@ -1269,6 +1304,12 @@ struct wlcore_conf {
struct
conf_fwlog
fwlog
;
struct
conf_rate_policy_settings
rate
;
struct
conf_hangover_settings
hangover
;
};
}
__packed
;
struct
wlcore_conf_file
{
struct
wlcore_conf_header
header
;
struct
wlcore_conf
core
;
u8
priv
[
0
];
}
__packed
;
#endif
drivers/net/wireless/ti/wlcore/debugfs.c
View file @
bf34e683
...
...
@@ -25,6 +25,7 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/module.h>
#include "wlcore.h"
#include "debug.h"
...
...
@@ -32,13 +33,13 @@
#include "ps.h"
#include "io.h"
#include "tx.h"
#include "hw_ops.h"
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
/* debugfs macros idea from mac80211 */
#define DEBUGFS_FORMAT_BUFFER_SIZE 100
static
int
wl1271_format_buffer
(
char
__user
*
userbuf
,
size_t
count
,
int
wl1271_format_buffer
(
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
,
char
*
fmt
,
...)
{
va_list
args
;
...
...
@@ -51,59 +52,9 @@ static int wl1271_format_buffer(char __user *userbuf, size_t count,
return
simple_read_from_buffer
(
userbuf
,
count
,
ppos
,
buf
,
res
);
}
EXPORT_SYMBOL_GPL
(
wl1271_format_buffer
);
#define DEBUGFS_READONLY_FILE(name, fmt, value...) \
static ssize_t name## _read(struct file *file, char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
return wl1271_format_buffer(userbuf, count, ppos, \
fmt "\n", ##value); \
} \
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
};
#define DEBUGFS_ADD(name, parent) \
entry = debugfs_create_file(#name, 0400, parent, \
wl, &name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
do { \
entry = debugfs_create_file(#name, 0400, parent, \
wl, &prefix## _## name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
} while (0);
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
\
wl1271_debugfs_update_stats(wl); \
\
return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \
wl->stats.fw_stats->sub.name); \
} \
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
};
#define DEBUGFS_FWSTATS_ADD(sub, name) \
DEBUGFS_ADD(sub## _ ##name, stats)
static
void
wl1271_debugfs_update_stats
(
struct
wl1271
*
wl
)
void
wl1271_debugfs_update_stats
(
struct
wl1271
*
wl
)
{
int
ret
;
...
...
@@ -125,97 +76,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
out:
mutex_unlock
(
&
wl
->
mutex
);
}
DEBUGFS_FWSTATS_FILE
(
tx
,
internal_desc_overflow
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
out_of_mem
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
hdr_overflow
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
hw_stuck
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
dropped
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
fcs_err
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
xfr_hint_trig
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
path_reset
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rx
,
reset_counter
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
dma
,
rx_requested
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
dma
,
rx_errors
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
dma
,
tx_requested
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
dma
,
tx_errors
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
cmd_cmplt
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
fiqs
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
rx_headers
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
rx_mem_overflow
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
rx_rdys
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
irqs
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
tx_procs
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
decrypt_done
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
dma0_done
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
dma1_done
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
tx_exch_complete
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
commands
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
rx_procs
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
hw_pm_mode_changes
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
host_acknowledges
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
pci_pm
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
wakeups
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
isr
,
low_rssi
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
wep
,
addr_key_count
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
wep
,
default_key_count
,
"%u"
);
/* skipping wep.reserved */
DEBUGFS_FWSTATS_FILE
(
wep
,
key_not_found
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
wep
,
decrypt_fail
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
wep
,
packets
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
wep
,
interrupt
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
ps_enter
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
elp_enter
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
missing_bcns
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
wake_on_host
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
wake_on_timer_exp
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
tx_with_ps
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
tx_without_ps
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_beacons
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
power_save_off
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
enable_ps
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
disable_ps
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
pwr
,
fix_tsf_ps
,
"%u"
);
/* skipping cont_miss_bcns_spread for now */
DEBUGFS_FWSTATS_FILE
(
pwr
,
rcvd_awake_beacons
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
mic
,
rx_pkts
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
mic
,
calc_failure
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_fail
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_fail
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_packets
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_packets
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
encrypt_interrupt
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
aes
,
decrypt_interrupt
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
heart_beat
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
calibration
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
rx_mismatch
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
rx_mem_empty
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
rx_pool
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
oom_late
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
phy_transmit_error
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
event
,
tx_stuck
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_timeouts
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_timeouts
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_max_sptime
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_max_apturn
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_max_apturn
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
pspoll_utilization
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
ps
,
upsd_utilization
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rxpipe
,
rx_prep_beacon_drop
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rxpipe
,
descr_host_int_trig_rx_data
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rxpipe
,
beacon_buffer_thres_host_int_trig_rx_data
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rxpipe
,
missed_beacon_host_int_trig_rx_data
,
"%u"
);
DEBUGFS_FWSTATS_FILE
(
rxpipe
,
tx_xfr_host_int_trig_rx_data
,
"%u"
);
EXPORT_SYMBOL_GPL
(
wl1271_debugfs_update_stats
);
DEBUGFS_READONLY_FILE
(
retry_count
,
"%u"
,
wl
->
stats
.
retry_count
);
DEBUGFS_READONLY_FILE
(
excessive_retries
,
"%u"
,
...
...
@@ -241,6 +102,89 @@ static const struct file_operations tx_queue_len_ops = {
.
llseek
=
default_llseek
,
};
static
void
chip_op_handler
(
struct
wl1271
*
wl
,
unsigned
long
value
,
void
*
arg
)
{
int
ret
;
int
(
*
chip_op
)
(
struct
wl1271
*
wl
);
if
(
!
arg
)
{
wl1271_warning
(
"debugfs chip_op_handler with no callback"
);
return
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
return
;
chip_op
=
arg
;
chip_op
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
}
static
inline
void
no_write_handler
(
struct
wl1271
*
wl
,
unsigned
long
value
,
unsigned
long
param
)
{
}
#define WL12XX_CONF_DEBUGFS(param, conf_sub_struct, \
min_val, max_val, write_handler_locked, \
write_handler_arg) \
static ssize_t param##_read(struct file *file, \
char __user *user_buf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
return wl1271_format_buffer(user_buf, count, \
ppos, "%d\n", \
wl->conf.conf_sub_struct.param); \
} \
\
static ssize_t param##_write(struct file *file, \
const char __user *user_buf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
unsigned long value; \
int ret; \
\
ret = kstrtoul_from_user(user_buf, count, 10, &value); \
if (ret < 0) { \
wl1271_warning("illegal value for " #param); \
return -EINVAL; \
} \
\
if (value < min_val || value > max_val) { \
wl1271_warning(#param " is not in valid range"); \
return -ERANGE; \
} \
\
mutex_lock(&wl->mutex); \
wl->conf.conf_sub_struct.param = value; \
\
write_handler_locked(wl, value, write_handler_arg); \
\
mutex_unlock(&wl->mutex); \
return count; \
} \
\
static const struct file_operations param##_ops = { \
.read = param##_read, \
.write = param##_write, \
.open = simple_open, \
.llseek = default_llseek, \
};
WL12XX_CONF_DEBUGFS
(
irq_pkt_threshold
,
rx
,
0
,
65535
,
chip_op_handler
,
wl1271_acx_init_rx_interrupt
)
WL12XX_CONF_DEBUGFS
(
irq_blk_threshold
,
rx
,
0
,
65535
,
chip_op_handler
,
wl1271_acx_init_rx_interrupt
)
WL12XX_CONF_DEBUGFS
(
irq_timeout
,
rx
,
0
,
100
,
chip_op_handler
,
wl1271_acx_init_rx_interrupt
)
static
ssize_t
gpio_power_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -535,8 +479,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_LHEX
(
ap_ps_map
);
DRIVER_STATE_PRINT_HEX
(
quirks
);
DRIVER_STATE_PRINT_HEX
(
irq
);
DRIVER_STATE_PRINT_HEX
(
ref_clock
);
DRIVER_STATE_PRINT_HEX
(
tcxo_clock
);
/* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
DRIVER_STATE_PRINT_HEX
(
hw_pg_ver
);
DRIVER_STATE_PRINT_HEX
(
platform_quirks
);
DRIVER_STATE_PRINT_HEX
(
chip
.
id
);
...
...
@@ -647,7 +590,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT
(
last_rssi_event
);
VIF_STATE_PRINT_INT
(
ba_support
);
VIF_STATE_PRINT_INT
(
ba_allowed
);
VIF_STATE_PRINT_INT
(
is_gem
);
VIF_STATE_PRINT_LLHEX
(
tx_security_seq
);
VIF_STATE_PRINT_INT
(
tx_security_last_seq_lsb
);
}
...
...
@@ -1002,108 +944,30 @@ static const struct file_operations beacon_filtering_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
fw_stats_raw_read
(
struct
file
*
file
,
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
wl1271_debugfs_update_stats
(
wl
);
return
simple_read_from_buffer
(
userbuf
,
count
,
ppos
,
wl
->
stats
.
fw_stats
,
wl
->
stats
.
fw_stats_len
);
}
static
const
struct
file_operations
fw_stats_raw_ops
=
{
.
read
=
fw_stats_raw_read
,
.
open
=
simple_open
,
.
llseek
=
default_llseek
,
};
static
int
wl1271_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
int
ret
=
0
;
struct
dentry
*
entry
,
*
stats
,
*
streaming
;
stats
=
debugfs_create_dir
(
"fw-statistics"
,
rootdir
);
if
(
!
stats
||
IS_ERR
(
stats
))
{
entry
=
stats
;
goto
err
;
}
DEBUGFS_FWSTATS_ADD
(
tx
,
internal_desc_overflow
);
DEBUGFS_FWSTATS_ADD
(
rx
,
out_of_mem
);
DEBUGFS_FWSTATS_ADD
(
rx
,
hdr_overflow
);
DEBUGFS_FWSTATS_ADD
(
rx
,
hw_stuck
);
DEBUGFS_FWSTATS_ADD
(
rx
,
dropped
);
DEBUGFS_FWSTATS_ADD
(
rx
,
fcs_err
);
DEBUGFS_FWSTATS_ADD
(
rx
,
xfr_hint_trig
);
DEBUGFS_FWSTATS_ADD
(
rx
,
path_reset
);
DEBUGFS_FWSTATS_ADD
(
rx
,
reset_counter
);
DEBUGFS_FWSTATS_ADD
(
dma
,
rx_requested
);
DEBUGFS_FWSTATS_ADD
(
dma
,
rx_errors
);
DEBUGFS_FWSTATS_ADD
(
dma
,
tx_requested
);
DEBUGFS_FWSTATS_ADD
(
dma
,
tx_errors
);
DEBUGFS_FWSTATS_ADD
(
isr
,
cmd_cmplt
);
DEBUGFS_FWSTATS_ADD
(
isr
,
fiqs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_headers
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_mem_overflow
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_rdys
);
DEBUGFS_FWSTATS_ADD
(
isr
,
irqs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
tx_procs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
decrypt_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
dma0_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
dma1_done
);
DEBUGFS_FWSTATS_ADD
(
isr
,
tx_exch_complete
);
DEBUGFS_FWSTATS_ADD
(
isr
,
commands
);
DEBUGFS_FWSTATS_ADD
(
isr
,
rx_procs
);
DEBUGFS_FWSTATS_ADD
(
isr
,
hw_pm_mode_changes
);
DEBUGFS_FWSTATS_ADD
(
isr
,
host_acknowledges
);
DEBUGFS_FWSTATS_ADD
(
isr
,
pci_pm
);
DEBUGFS_FWSTATS_ADD
(
isr
,
wakeups
);
DEBUGFS_FWSTATS_ADD
(
isr
,
low_rssi
);
DEBUGFS_FWSTATS_ADD
(
wep
,
addr_key_count
);
DEBUGFS_FWSTATS_ADD
(
wep
,
default_key_count
);
/* skipping wep.reserved */
DEBUGFS_FWSTATS_ADD
(
wep
,
key_not_found
);
DEBUGFS_FWSTATS_ADD
(
wep
,
decrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
wep
,
packets
);
DEBUGFS_FWSTATS_ADD
(
wep
,
interrupt
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
ps_enter
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
elp_enter
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
missing_bcns
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
wake_on_host
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
wake_on_timer_exp
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
tx_with_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
tx_without_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_beacons
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
power_save_off
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
enable_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
disable_ps
);
DEBUGFS_FWSTATS_ADD
(
pwr
,
fix_tsf_ps
);
/* skipping cont_miss_bcns_spread for now */
DEBUGFS_FWSTATS_ADD
(
pwr
,
rcvd_awake_beacons
);
DEBUGFS_FWSTATS_ADD
(
mic
,
rx_pkts
);
DEBUGFS_FWSTATS_ADD
(
mic
,
calc_failure
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_fail
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_packets
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_packets
);
DEBUGFS_FWSTATS_ADD
(
aes
,
encrypt_interrupt
);
DEBUGFS_FWSTATS_ADD
(
aes
,
decrypt_interrupt
);
DEBUGFS_FWSTATS_ADD
(
event
,
heart_beat
);
DEBUGFS_FWSTATS_ADD
(
event
,
calibration
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_mismatch
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_mem_empty
);
DEBUGFS_FWSTATS_ADD
(
event
,
rx_pool
);
DEBUGFS_FWSTATS_ADD
(
event
,
oom_late
);
DEBUGFS_FWSTATS_ADD
(
event
,
phy_transmit_error
);
DEBUGFS_FWSTATS_ADD
(
event
,
tx_stuck
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_timeouts
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_max_sptime
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_max_apturn
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_max_apturn
);
DEBUGFS_FWSTATS_ADD
(
ps
,
pspoll_utilization
);
DEBUGFS_FWSTATS_ADD
(
ps
,
upsd_utilization
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
rx_prep_beacon_drop
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
descr_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
beacon_buffer_thres_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
missed_beacon_host_int_trig_rx_data
);
DEBUGFS_FWSTATS_ADD
(
rxpipe
,
tx_xfr_host_int_trig_rx_data
);
struct
dentry
*
entry
,
*
streaming
;
DEBUGFS_ADD
(
tx_queue_len
,
rootdir
);
DEBUGFS_ADD
(
retry_count
,
rootdir
);
...
...
@@ -1120,6 +984,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD
(
dynamic_ps_timeout
,
rootdir
);
DEBUGFS_ADD
(
forced_ps
,
rootdir
);
DEBUGFS_ADD
(
split_scan_timeout
,
rootdir
);
DEBUGFS_ADD
(
irq_pkt_threshold
,
rootdir
);
DEBUGFS_ADD
(
irq_blk_threshold
,
rootdir
);
DEBUGFS_ADD
(
irq_timeout
,
rootdir
);
DEBUGFS_ADD
(
fw_stats_raw
,
rootdir
);
streaming
=
debugfs_create_dir
(
"rx_streaming"
,
rootdir
);
if
(
!
streaming
||
IS_ERR
(
streaming
))
...
...
@@ -1145,7 +1013,7 @@ void wl1271_debugfs_reset(struct wl1271 *wl)
if
(
!
wl
->
stats
.
fw_stats
)
return
;
memset
(
wl
->
stats
.
fw_stats
,
0
,
sizeof
(
*
wl
->
stats
.
fw_stats
)
);
memset
(
wl
->
stats
.
fw_stats
,
0
,
wl
->
stats
.
fw_stats_len
);
wl
->
stats
.
retry_count
=
0
;
wl
->
stats
.
excessive_retries
=
0
;
}
...
...
@@ -1160,34 +1028,34 @@ int wl1271_debugfs_init(struct wl1271 *wl)
if
(
IS_ERR
(
rootdir
))
{
ret
=
PTR_ERR
(
rootdir
);
goto
err
;
goto
out
;
}
wl
->
stats
.
fw_stats
=
kzalloc
(
sizeof
(
*
wl
->
stats
.
fw_stats
),
GFP_KERNEL
);
wl
->
stats
.
fw_stats
=
kzalloc
(
wl
->
stats
.
fw_stats_len
,
GFP_KERNEL
);
if
(
!
wl
->
stats
.
fw_stats
)
{
ret
=
-
ENOMEM
;
goto
err_fw
;
goto
out_remove
;
}
wl
->
stats
.
fw_stats_update
=
jiffies
;
ret
=
wl1271_debugfs_add_files
(
wl
,
rootdir
);
if
(
ret
<
0
)
goto
out_exit
;
ret
=
wlcore_debugfs_init
(
wl
,
rootdir
);
if
(
ret
<
0
)
goto
err_file
;
goto
out_exit
;
return
0
;
goto
out
;
err_file:
kfree
(
wl
->
stats
.
fw_stats
);
wl
->
stats
.
fw_stats
=
NULL
;
out_exit:
wl1271_debugfs_exit
(
wl
);
err_fw
:
out_remove
:
debugfs_remove_recursive
(
rootdir
);
err
:
out
:
return
ret
;
}
...
...
drivers/net/wireless/ti/wlcore/debugfs.h
View file @
bf34e683
...
...
@@ -26,8 +26,95 @@
#include "wlcore.h"
int
wl1271_format_buffer
(
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
,
char
*
fmt
,
...);
int
wl1271_debugfs_init
(
struct
wl1271
*
wl
);
void
wl1271_debugfs_exit
(
struct
wl1271
*
wl
);
void
wl1271_debugfs_reset
(
struct
wl1271
*
wl
);
void
wl1271_debugfs_update_stats
(
struct
wl1271
*
wl
);
#define DEBUGFS_FORMAT_BUFFER_SIZE 256
#define DEBUGFS_READONLY_FILE(name, fmt, value...) \
static ssize_t name## _read(struct file *file, char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
return wl1271_format_buffer(userbuf, count, ppos, \
fmt "\n", ##value); \
} \
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
};
#define DEBUGFS_ADD(name, parent) \
do { \
entry = debugfs_create_file(#name, 0400, parent, \
wl, &name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
} while (0);
#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
do { \
entry = debugfs_create_file(#name, 0400, parent, \
wl, &prefix## _## name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
} while (0);
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
struct struct_type *stats = wl->stats.fw_stats; \
\
wl1271_debugfs_update_stats(wl); \
\
return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \
stats->sub.name); \
} \
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
};
#define DEBUGFS_FWSTATS_FILE_ARRAY(sub, name, len, struct_type) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct wl1271 *wl = file->private_data; \
struct struct_type *stats = wl->stats.fw_stats; \
char buf[DEBUGFS_FORMAT_BUFFER_SIZE] = ""; \
int res, i; \
\
wl1271_debugfs_update_stats(wl); \
\
for (i = 0; i < len; i++) \
res = snprintf(buf, sizeof(buf), "%s[%d] = %d\n", \
buf, i, stats->sub.name[i]); \
\
return wl1271_format_buffer(userbuf, count, ppos, "%s", buf); \
} \
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
};
#define DEBUGFS_FWSTATS_ADD(sub, name) \
DEBUGFS_ADD(sub## _ ##name, stats)
#endif
/* WL1271_DEBUGFS_H */
drivers/net/wireless/ti/wlcore/event.c
View file @
bf34e683
...
...
@@ -148,15 +148,33 @@ static int wl1271_event_process(struct wl1271 *wl)
int
delay
=
wl
->
conf
.
conn
.
synch_fail_thold
*
wl
->
conf
.
conn
.
bss_lose_timeout
;
wl1271_info
(
"Beacon loss detected."
);
cancel_delayed_work_sync
(
&
wl
->
connection_loss_work
);
/*
* if the work is already queued, it should take place. We
* don't want to delay the connection loss indication
* any more.
*/
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
connection_loss_work
,
msecs_to_jiffies
(
delay
));
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_cqm_rssi_notify
(
vif
,
NL80211_CQM_RSSI_BEACON_LOSS_EVENT
,
GFP_KERNEL
);
}
}
if
(
vector
&
REGAINED_BSS_EVENT_ID
)
{
/* TODO: check for multi-role */
wl1271_info
(
"Beacon regained."
);
cancel_delayed_work_sync
(
&
wl
->
connection_loss_work
);
cancel_delayed_work
(
&
wl
->
connection_loss_work
);
/* sanity check - we can't lose and gain the beacon together */
WARN
(
vector
&
BSS_LOSE_EVENT_ID
,
"Concurrent beacon loss and gain from FW"
);
}
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
{
...
...
drivers/net/wireless/ti/wlcore/hw_ops.h
View file @
bf34e683
...
...
@@ -119,4 +119,82 @@ static inline int wlcore_identify_fw(struct wl1271 *wl)
return
0
;
}
static
inline
void
wlcore_hw_set_tx_desc_csum
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
)
{
if
(
!
wl
->
ops
->
set_tx_desc_csum
)
BUG_ON
(
1
);
wl
->
ops
->
set_tx_desc_csum
(
wl
,
desc
,
skb
);
}
static
inline
void
wlcore_hw_set_rx_csum
(
struct
wl1271
*
wl
,
struct
wl1271_rx_descriptor
*
desc
,
struct
sk_buff
*
skb
)
{
if
(
wl
->
ops
->
set_rx_csum
)
wl
->
ops
->
set_rx_csum
(
wl
,
desc
,
skb
);
}
static
inline
u32
wlcore_hw_ap_get_mimo_wide_rate_mask
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
if
(
wl
->
ops
->
ap_get_mimo_wide_rate_mask
)
return
wl
->
ops
->
ap_get_mimo_wide_rate_mask
(
wl
,
wlvif
);
return
0
;
}
static
inline
int
wlcore_debugfs_init
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
if
(
wl
->
ops
->
debugfs_init
)
return
wl
->
ops
->
debugfs_init
(
wl
,
rootdir
);
return
0
;
}
static
inline
int
wlcore_handle_static_data
(
struct
wl1271
*
wl
,
void
*
static_data
)
{
if
(
wl
->
ops
->
handle_static_data
)
return
wl
->
ops
->
handle_static_data
(
wl
,
static_data
);
return
0
;
}
static
inline
int
wlcore_hw_get_spare_blocks
(
struct
wl1271
*
wl
,
bool
is_gem
)
{
if
(
!
wl
->
ops
->
get_spare_blocks
)
BUG_ON
(
1
);
return
wl
->
ops
->
get_spare_blocks
(
wl
,
is_gem
);
}
static
inline
int
wlcore_hw_set_key
(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
)
{
if
(
!
wl
->
ops
->
set_key
)
BUG_ON
(
1
);
return
wl
->
ops
->
set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
}
static
inline
u32
wlcore_hw_pre_pkt_send
(
struct
wl1271
*
wl
,
u32
buf_offset
,
u32
last_len
)
{
if
(
wl
->
ops
->
pre_pkt_send
)
return
wl
->
ops
->
pre_pkt_send
(
wl
,
buf_offset
,
last_len
);
return
buf_offset
;
}
#endif
drivers/net/wireless/ti/wlcore/init.c
View file @
bf34e683
...
...
@@ -460,6 +460,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
/* unconditionally enable HT rates */
supported_rates
|=
CONF_TX_MCS_RATES
;
/* get extra MIMO or wide-chan rates where the HW supports it */
supported_rates
|=
wlcore_hw_ap_get_mimo_wide_rate_mask
(
wl
,
wlvif
);
/* configure unicast TX rate classes */
for
(
i
=
0
;
i
<
wl
->
conf
.
tx
.
ac_conf_count
;
i
++
)
{
rc
.
enabled_rates
=
supported_rates
;
...
...
drivers/net/wireless/ti/wlcore/main.c
View file @
bf34e683
...
...
@@ -320,46 +320,6 @@ static void wlcore_adjust_conf(struct wl1271 *wl)
}
}
static
int
wl1271_plt_init
(
struct
wl1271
*
wl
)
{
int
ret
;
ret
=
wl
->
ops
->
hw_init
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_init_mem_config
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_acx_mem_cfg
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Enable data path */
ret
=
wl1271_cmd_data_path
(
wl
,
1
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Configure for CAM power saving (ie. always active) */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_CAM
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* configure PM */
ret
=
wl1271_acx_pm_config
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
return
0
;
out_free_memmap:
kfree
(
wl
->
target_mem_map
);
wl
->
target_mem_map
=
NULL
;
return
ret
;
}
static
void
wl12xx_irq_ps_regulate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
,
u8
tx_pkts
)
...
...
@@ -387,7 +347,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
static
void
wl12xx_irq_update_links_status
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
wl_fw_status
*
status
)
struct
wl_fw_status
_2
*
status
)
{
struct
wl1271_link
*
lnk
;
u32
cur_fw_ps_map
;
...
...
@@ -419,7 +379,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
}
static
void
wl12xx_fw_status
(
struct
wl1271
*
wl
,
struct
wl_fw_status
*
status
)
struct
wl_fw_status_1
*
status_1
,
struct
wl_fw_status_2
*
status_2
)
{
struct
wl12xx_vif
*
wlvif
;
struct
timespec
ts
;
...
...
@@ -428,37 +389,38 @@ static void wl12xx_fw_status(struct wl1271 *wl,
int
i
;
size_t
status_len
;
status_len
=
sizeof
(
*
status
)
+
wl
->
fw_status_priv_len
;
status_len
=
WLCORE_FW_STATUS_1_LEN
(
wl
->
num_rx_desc
)
+
sizeof
(
*
status_2
)
+
wl
->
fw_status_priv_len
;
wlcore_raw_read_data
(
wl
,
REG_RAW_FW_STATUS_ADDR
,
status
,
wlcore_raw_read_data
(
wl
,
REG_RAW_FW_STATUS_ADDR
,
status
_1
,
status_len
,
false
);
wl1271_debug
(
DEBUG_IRQ
,
"intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)"
,
status
->
intr
,
status
->
fw_rx_counter
,
status
->
drv_rx_counter
,
status
->
tx_results_counter
);
status
_1
->
intr
,
status
_1
->
fw_rx_counter
,
status
_1
->
drv_rx_counter
,
status
_1
->
tx_results_counter
);
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
/* prevent wrap-around in freed-packets counter */
wl
->
tx_allocated_pkts
[
i
]
-=
(
status
->
counters
.
tx_released_pkts
[
i
]
-
(
status
_2
->
counters
.
tx_released_pkts
[
i
]
-
wl
->
tx_pkts_freed
[
i
])
&
0xff
;
wl
->
tx_pkts_freed
[
i
]
=
status
->
counters
.
tx_released_pkts
[
i
];
wl
->
tx_pkts_freed
[
i
]
=
status
_2
->
counters
.
tx_released_pkts
[
i
];
}
/* prevent wrap-around in total blocks counter */
if
(
likely
(
wl
->
tx_blocks_freed
<=
le32_to_cpu
(
status
->
total_released_blks
)))
freed_blocks
=
le32_to_cpu
(
status
->
total_released_blks
)
-
le32_to_cpu
(
status
_2
->
total_released_blks
)))
freed_blocks
=
le32_to_cpu
(
status
_2
->
total_released_blks
)
-
wl
->
tx_blocks_freed
;
else
freed_blocks
=
0x100000000LL
-
wl
->
tx_blocks_freed
+
le32_to_cpu
(
status
->
total_released_blks
);
le32_to_cpu
(
status
_2
->
total_released_blks
);
wl
->
tx_blocks_freed
=
le32_to_cpu
(
status
->
total_released_blks
);
wl
->
tx_blocks_freed
=
le32_to_cpu
(
status
_2
->
total_released_blks
);
wl
->
tx_allocated_blocks
-=
freed_blocks
;
...
...
@@ -474,7 +436,7 @@ static void wl12xx_fw_status(struct wl1271 *wl,
cancel_delayed_work
(
&
wl
->
tx_watchdog_work
);
}
avail
=
le32_to_cpu
(
status
->
tx_total
)
-
wl
->
tx_allocated_blocks
;
avail
=
le32_to_cpu
(
status
_2
->
tx_total
)
-
wl
->
tx_allocated_blocks
;
/*
* The FW might change the total number of TX memblocks before
...
...
@@ -493,13 +455,13 @@ static void wl12xx_fw_status(struct wl1271 *wl,
/* for AP update num of allocated TX blocks per link and ps status */
wl12xx_for_each_wlvif_ap
(
wl
,
wlvif
)
{
wl12xx_irq_update_links_status
(
wl
,
wlvif
,
status
);
wl12xx_irq_update_links_status
(
wl
,
wlvif
,
status
_2
);
}
/* update the host-chipset time offset */
getnstimeofday
(
&
ts
);
wl
->
time_offset
=
(
timespec_to_ns
(
&
ts
)
>>
10
)
-
(
s64
)
le32_to_cpu
(
status
->
fw_localtime
);
(
s64
)
le32_to_cpu
(
status
_2
->
fw_localtime
);
}
static
void
wl1271_flush_deferred_work
(
struct
wl1271
*
wl
)
...
...
@@ -568,20 +530,30 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
clear_bit
(
WL1271_FLAG_IRQ_RUNNING
,
&
wl
->
flags
);
smp_mb__after_clear_bit
();
wl12xx_fw_status
(
wl
,
wl
->
fw_status
);
wl12xx_fw_status
(
wl
,
wl
->
fw_status
_1
,
wl
->
fw_status_2
);
wlcore_hw_tx_immediate_compl
(
wl
);
intr
=
le32_to_cpu
(
wl
->
fw_status
->
intr
);
intr
&=
WL
1271
_INTR_MASK
;
intr
=
le32_to_cpu
(
wl
->
fw_status
_1
->
intr
);
intr
&=
WL
CORE_ALL
_INTR_MASK
;
if
(
!
intr
)
{
done
=
true
;
continue
;
}
if
(
unlikely
(
intr
&
WL1271_ACX_INTR_WATCHDOG
))
{
wl1271_error
(
"watchdog interrupt received! "
wl1271_error
(
"HW watchdog interrupt received! starting recovery."
);
wl
->
watchdog_recovery
=
true
;
wl12xx_queue_recovery_work
(
wl
);
/* restarting the chip. ignore any other interrupt. */
goto
out
;
}
if
(
unlikely
(
intr
&
WL1271_ACX_SW_INTR_WATCHDOG
))
{
wl1271_error
(
"SW watchdog interrupt received! "
"starting recovery."
);
wl
->
watchdog_recovery
=
true
;
wl12xx_queue_recovery_work
(
wl
);
/* restarting the chip. ignore any other interrupt. */
...
...
@@ -591,7 +563,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if
(
likely
(
intr
&
WL1271_ACX_INTR_DATA
))
{
wl1271_debug
(
DEBUG_IRQ
,
"WL1271_ACX_INTR_DATA"
);
wl12xx_rx
(
wl
,
wl
->
fw_status
);
wl12xx_rx
(
wl
,
wl
->
fw_status
_1
);
/* Check if any tx blocks were freed */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
...
...
@@ -743,7 +715,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
return
ret
;
}
static
int
wl1271_fetch_nvs
(
struct
wl1271
*
wl
)
static
void
wl1271_fetch_nvs
(
struct
wl1271
*
wl
)
{
const
struct
firmware
*
fw
;
int
ret
;
...
...
@@ -751,16 +723,15 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
ret
=
request_firmware
(
&
fw
,
WL12XX_NVS_NAME
,
wl
->
dev
);
if
(
ret
<
0
)
{
wl1271_
error
(
"could not get nvs file %s: %d"
,
WL12XX_NVS_NAME
,
ret
);
return
ret
;
wl1271_
debug
(
DEBUG_BOOT
,
"could not get nvs file %s: %d"
,
WL12XX_NVS_NAME
,
ret
);
return
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
fw
->
size
,
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
wl1271_error
(
"could not allocate memory for the nvs file"
);
ret
=
-
ENOMEM
;
goto
out
;
}
...
...
@@ -768,8 +739,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
out:
release_firmware
(
fw
);
return
ret
;
}
void
wl12xx_queue_recovery_work
(
struct
wl1271
*
wl
)
...
...
@@ -820,14 +789,16 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
/*
* Make sure the chip is awake and the logger isn't active.
*
This might fail if the firmware
hanged.
*
Do not send a stop fwlog command if the fw is
hanged.
*/
if
(
!
wl1271_ps_elp_wakeup
(
wl
))
if
(
!
wl1271_ps_elp_wakeup
(
wl
)
&&
!
wl
->
watchdog_recovery
)
wl12xx_cmd_stop_fwlog
(
wl
);
else
goto
out
;
/* Read the first memory block address */
wl12xx_fw_status
(
wl
,
wl
->
fw_status
);
first_addr
=
le32_to_cpu
(
wl
->
fw_status
->
log_start_addr
);
wl12xx_fw_status
(
wl
,
wl
->
fw_status
_1
,
wl
->
fw_status_2
);
first_addr
=
le32_to_cpu
(
wl
->
fw_status
_2
->
log_start_addr
);
if
(
!
first_addr
)
goto
out
;
...
...
@@ -872,9 +843,14 @@ static void wl1271_recovery_work(struct work_struct *work)
wl12xx_read_fwlog_panic
(
wl
);
wl1271_info
(
"Hardware recovery in progress. FW ver: %s pc: 0x%x"
,
/* change partitions momentarily so we can read the FW pc */
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
wl1271_info
(
"Hardware recovery in progress. FW ver: %s pc: 0x%x "
"hint_sts: 0x%08x"
,
wl
->
chip
.
fw_ver_str
,
wlcore_read_reg
(
wl
,
REG_PC_ON_RECOVERY
));
wlcore_read_reg
(
wl
,
REG_PC_ON_RECOVERY
),
wlcore_read_reg
(
wl
,
REG_INTERRUPT_NO_CLEAR
));
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
BUG_ON
(
bug_on_recovery
&&
!
test_bit
(
WL1271_FLAG_INTENDED_FW_RECOVERY
,
&
wl
->
flags
));
...
...
@@ -885,8 +861,6 @@ static void wl1271_recovery_work(struct work_struct *work)
goto
out_unlock
;
}
BUG_ON
(
bug_on_recovery
);
/*
* Advance security sequence number to overcome potential progress
* in the firmware during recovery. This doens't hurt if the network is
...
...
@@ -900,7 +874,7 @@ static void wl1271_recovery_work(struct work_struct *work)
}
/* Prevent spurious TX during FW restart */
ieee80211_stop_queues
(
wl
->
hw
);
wlcore_stop_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_FW_RESTART
);
if
(
wl
->
sched_scanning
)
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
...
...
@@ -914,6 +888,7 @@ static void wl1271_recovery_work(struct work_struct *work)
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
__wl1271_op_remove_interface
(
wl
,
vif
,
false
);
}
wl
->
watchdog_recovery
=
false
;
mutex_unlock
(
&
wl
->
mutex
);
wl1271_op_stop
(
wl
->
hw
);
...
...
@@ -925,9 +900,10 @@ static void wl1271_recovery_work(struct work_struct *work)
* Its safe to enable TX now - the queues are stopped after a request
* to restart the HW.
*/
ieee80211_wake_queues
(
wl
->
hw
);
wlcore_wake_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_FW_RESTART
);
return
;
out_unlock:
wl
->
watchdog_recovery
=
false
;
mutex_unlock
(
&
wl
->
mutex
);
}
...
...
@@ -938,13 +914,19 @@ static void wl1271_fw_wakeup(struct wl1271 *wl)
static
int
wl1271_setup
(
struct
wl1271
*
wl
)
{
wl
->
fw_status
=
kmalloc
(
sizeof
(
*
wl
->
fw_status
),
GFP_KERNEL
);
if
(
!
wl
->
fw_status
)
wl
->
fw_status_1
=
kmalloc
(
WLCORE_FW_STATUS_1_LEN
(
wl
->
num_rx_desc
)
+
sizeof
(
*
wl
->
fw_status_2
)
+
wl
->
fw_status_priv_len
,
GFP_KERNEL
);
if
(
!
wl
->
fw_status_1
)
return
-
ENOMEM
;
wl
->
fw_status_2
=
(
struct
wl_fw_status_2
*
)
(((
u8
*
)
wl
->
fw_status_1
)
+
WLCORE_FW_STATUS_1_LEN
(
wl
->
num_rx_desc
));
wl
->
tx_res_if
=
kmalloc
(
sizeof
(
*
wl
->
tx_res_if
),
GFP_KERNEL
);
if
(
!
wl
->
tx_res_if
)
{
kfree
(
wl
->
fw_status
);
kfree
(
wl
->
fw_status
_1
);
return
-
ENOMEM
;
}
...
...
@@ -987,13 +969,12 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
* simplify the code and since the performance impact is
* negligible, we use the same block size for all different
* chip types.
*
* Check if the bus supports blocksize alignment and, if it
* doesn't, make sure we don't have the quirk.
*/
if
(
wl1271_set_block_size
(
wl
))
wl
->
quirks
|=
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
ret
=
wl
->
ops
->
identify_chip
(
wl
);
if
(
ret
<
0
)
goto
out
;
if
(
!
wl1271_set_block_size
(
wl
))
wl
->
quirks
&=
~
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
/* TODO: make sure the lower driver has set things up correctly */
...
...
@@ -1005,13 +986,6 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
if
(
ret
<
0
)
goto
out
;
/* No NVS from netlink, try to get it from the filesystem */
if
(
wl
->
nvs
==
NULL
)
{
ret
=
wl1271_fetch_nvs
(
wl
);
if
(
ret
<
0
)
goto
out
;
}
out:
return
ret
;
}
...
...
@@ -1039,14 +1013,10 @@ int wl1271_plt_start(struct wl1271 *wl)
if
(
ret
<
0
)
goto
power_off
;
ret
=
wl
->
ops
->
boo
t
(
wl
);
ret
=
wl
->
ops
->
plt_ini
t
(
wl
);
if
(
ret
<
0
)
goto
power_off
;
ret
=
wl1271_plt_init
(
wl
);
if
(
ret
<
0
)
goto
irq_disable
;
wl
->
plt
=
true
;
wl
->
state
=
WL1271_STATE_ON
;
wl1271_notice
(
"firmware booted in PLT mode (%s)"
,
...
...
@@ -1059,19 +1029,6 @@ int wl1271_plt_start(struct wl1271 *wl)
goto
out
;
irq_disable:
mutex_unlock
(
&
wl
->
mutex
);
/* Unlocking the mutex in the middle of handling is
inherently unsafe. In this case we deem it safe to do,
because we need to let any possibly pending IRQ out of
the system (and while we are WL1271_STATE_OFF the IRQ
work function will not do anything.) Also, any other
possible concurrent operations will fail due to the
current state, hence the wl1271 struct should be safe. */
wlcore_disable_interrupts
(
wl
);
wl1271_flush_deferred_work
(
wl
);
cancel_work_sync
(
&
wl
->
netstack_work
);
mutex_lock
(
&
wl
->
mutex
);
power_off:
wl1271_power_off
(
wl
);
}
...
...
@@ -1154,9 +1111,16 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
/* queue the packet */
/*
* drop the packet if the link is invalid or the queue is stopped
* for any reason but watermark. Watermark is a "soft"-stop so we
* allow these packets through.
*/
if
(
hlid
==
WL12XX_INVALID_LINK_ID
||
(
wlvif
&&
!
test_bit
(
hlid
,
wlvif
->
links_map
)))
{
(
wlvif
&&
!
test_bit
(
hlid
,
wlvif
->
links_map
))
||
(
wlcore_is_queue_stopped
(
wl
,
q
)
&&
!
wlcore_is_queue_stopped_by_reason
(
wl
,
q
,
WLCORE_QUEUE_STOP_REASON_WATERMARK
)))
{
wl1271_debug
(
DEBUG_TX
,
"DROP skb hlid %d q %d"
,
hlid
,
q
);
ieee80211_free_txskb
(
hw
,
skb
);
goto
out
;
...
...
@@ -1174,8 +1138,8 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
*/
if
(
wl
->
tx_queue_count
[
q
]
>=
WL1271_TX_QUEUE_HIGH_WATERMARK
)
{
wl1271_debug
(
DEBUG_TX
,
"op_tx: stopping queues for q %d"
,
q
);
ieee80211_stop_queue
(
wl
->
hw
,
mapping
);
set_bit
(
q
,
&
wl
->
stopped_queues_map
);
wlcore_stop_queue_locked
(
wl
,
q
,
WLCORE_QUEUE_STOP_REASON_WATERMARK
);
}
/*
...
...
@@ -1758,7 +1722,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync
(
&
wl
->
connection_loss_work
);
/* let's notify MAC80211 about the remaining pending TX frames */
wl12xx_tx_reset
(
wl
,
true
);
wl12xx_tx_reset
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
wl1271_power_off
(
wl
);
...
...
@@ -1767,6 +1731,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl
->
rx_counter
=
0
;
wl
->
power_level
=
WL1271_DEFAULT_POWER_LEVEL
;
wl
->
channel_type
=
NL80211_CHAN_NO_HT
;
wl
->
tx_blocks_available
=
0
;
wl
->
tx_allocated_blocks
=
0
;
wl
->
tx_results_count
=
0
;
...
...
@@ -1799,8 +1764,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debugfs_reset
(
wl
);
kfree
(
wl
->
fw_status
);
wl
->
fw_status
=
NULL
;
kfree
(
wl
->
fw_status_1
);
wl
->
fw_status_1
=
NULL
;
wl
->
fw_status_2
=
NULL
;
kfree
(
wl
->
tx_res_if
);
wl
->
tx_res_if
=
NULL
;
kfree
(
wl
->
target_mem_map
);
...
...
@@ -1894,6 +1860,9 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wl12xx_allocate_rate_policy
(
wl
,
&
wlvif
->
sta
.
basic_rate_idx
);
wl12xx_allocate_rate_policy
(
wl
,
&
wlvif
->
sta
.
ap_rate_idx
);
wl12xx_allocate_rate_policy
(
wl
,
&
wlvif
->
sta
.
p2p_rate_idx
);
wlvif
->
basic_rate_set
=
CONF_TX_RATE_MASK_BASIC
;
wlvif
->
basic_rate
=
CONF_TX_RATE_MASK_BASIC
;
wlvif
->
rate_set
=
CONF_TX_RATE_MASK_BASIC
;
}
else
{
/* init ap data */
wlvif
->
ap
.
bcast_hlid
=
WL12XX_INVALID_LINK_ID
;
...
...
@@ -1903,13 +1872,19 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
for
(
i
=
0
;
i
<
CONF_TX_MAX_AC_COUNT
;
i
++
)
wl12xx_allocate_rate_policy
(
wl
,
&
wlvif
->
ap
.
ucast_rate_idx
[
i
]);
wlvif
->
basic_rate_set
=
CONF_TX_AP_ENABLED_RATES
;
/*
* TODO: check if basic_rate shouldn't be
* wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
* instead (the same thing for STA above).
*/
wlvif
->
basic_rate
=
CONF_TX_AP_ENABLED_RATES
;
/* TODO: this seems to be used only for STA, check it */
wlvif
->
rate_set
=
CONF_TX_AP_ENABLED_RATES
;
}
wlvif
->
bitrate_masks
[
IEEE80211_BAND_2GHZ
]
=
wl
->
conf
.
tx
.
basic_rate
;
wlvif
->
bitrate_masks
[
IEEE80211_BAND_5GHZ
]
=
wl
->
conf
.
tx
.
basic_rate_5
;
wlvif
->
basic_rate_set
=
CONF_TX_RATE_MASK_BASIC
;
wlvif
->
basic_rate
=
CONF_TX_RATE_MASK_BASIC
;
wlvif
->
rate_set
=
CONF_TX_RATE_MASK_BASIC
;
wlvif
->
beacon_int
=
WL1271_DEFAULT_BEACON_INT
;
/*
...
...
@@ -1919,6 +1894,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wlvif
->
band
=
wl
->
band
;
wlvif
->
channel
=
wl
->
channel
;
wlvif
->
power_level
=
wl
->
power_level
;
wlvif
->
channel_type
=
wl
->
channel_type
;
INIT_WORK
(
&
wlvif
->
rx_streaming_enable_work
,
wl1271_rx_streaming_enable_work
);
...
...
@@ -2444,7 +2420,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}
else
{
/* The current firmware only supports sched_scan in idle */
if
(
wl
->
sched_scanning
)
{
wl1271_scan_sched_scan_stop
(
wl
);
wl1271_scan_sched_scan_stop
(
wl
,
wlvif
);
ieee80211_sched_scan_stopped
(
wl
->
hw
);
}
...
...
@@ -2469,13 +2445,20 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
/* if the channel changes while joined, join again */
if
(
changed
&
IEEE80211_CONF_CHANGE_CHANNEL
&&
((
wlvif
->
band
!=
conf
->
channel
->
band
)
||
(
wlvif
->
channel
!=
channel
)))
{
(
wlvif
->
channel
!=
channel
)
||
(
wlvif
->
channel_type
!=
conf
->
channel_type
)))
{
/* send all pending packets */
wl1271_tx_work_locked
(
wl
);
wlvif
->
band
=
conf
->
channel
->
band
;
wlvif
->
channel
=
channel
;
wlvif
->
channel_type
=
conf
->
channel_type
;
if
(
!
is_ap
)
{
if
(
is_ap
)
{
ret
=
wl1271_init_ap_rates
(
wl
,
wlvif
);
if
(
ret
<
0
)
wl1271_error
(
"AP rate policy change failed %d"
,
ret
);
}
else
{
/*
* FIXME: the mac80211 should really provide a fixed
* rate to use here. for now, just use the smallest
...
...
@@ -2583,8 +2566,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
* frames, such as the deauth. To make sure those frames reach the air,
* wait here until the TX queue is fully flushed.
*/
if
((
changed
&
IEEE80211_CONF_CHANGE_IDLE
)
&&
(
conf
->
flags
&
IEEE80211_CONF_IDLE
))
if
((
changed
&
IEEE80211_CONF_CHANGE_CHANNEL
)
||
((
changed
&
IEEE80211_CONF_CHANGE_IDLE
)
&&
(
conf
->
flags
&
IEEE80211_CONF_IDLE
)))
wl1271_tx_flush
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
...
...
@@ -2593,6 +2577,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if
(
changed
&
IEEE80211_CONF_CHANGE_CHANNEL
)
{
wl
->
band
=
conf
->
channel
->
band
;
wl
->
channel
=
channel
;
wl
->
channel_type
=
conf
->
channel_type
;
}
if
(
changed
&
IEEE80211_CONF_CHANGE_POWER
)
...
...
@@ -2825,17 +2810,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int
ret
;
bool
is_ap
=
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
);
/*
* A role set to GEM cipher requires different Tx settings (namely
* spare blocks). Note when we are in this mode so the HW can adjust.
*/
if
(
key_type
==
KEY_GEM
)
{
if
(
action
==
KEY_ADD_OR_REPLACE
)
wlvif
->
is_gem
=
true
;
else
if
(
action
==
KEY_REMOVE
)
wlvif
->
is_gem
=
false
;
}
if
(
is_ap
)
{
struct
wl1271_station
*
wl_sta
;
u8
hlid
;
...
...
@@ -2913,12 +2887,21 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
0
;
}
static
int
wl
1271
_op_set_key
(
struct
ieee80211_hw
*
hw
,
enum
set_key_cmd
cmd
,
static
int
wl
core
_op_set_key
(
struct
ieee80211_hw
*
hw
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
return
wlcore_hw_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
}
int
wlcore_set_key
(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
int
ret
;
u32
tx_seq_32
=
0
;
...
...
@@ -3029,6 +3012,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wlcore_set_key
);
static
int
wl1271_op_hw_scan
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
...
...
@@ -3167,6 +3151,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw,
struct
ieee80211_vif
*
vif
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
int
ret
;
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271_op_sched_scan_stop"
);
...
...
@@ -3180,7 +3165,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw,
if
(
ret
<
0
)
goto
out
;
wl1271_scan_sched_scan_stop
(
wl
);
wl1271_scan_sched_scan_stop
(
wl
,
wlvif
);
wl1271_ps_elp_sleep
(
wl
);
out:
...
...
@@ -3316,8 +3301,15 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates,
skb
->
data
,
skb
->
len
,
0
,
rates
);
dev_kfree_skb
(
skb
);
if
(
ret
<
0
)
goto
out
;
wl1271_debug
(
DEBUG_AP
,
"probe response updated"
);
set_bit
(
WLVIF_FLAG_AP_PROBE_RESP_SET
,
&
wlvif
->
flags
);
out:
return
ret
;
}
...
...
@@ -3422,33 +3414,14 @@ static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
return
ret
;
}
static
int
wl
1271_bss_beacon_info_changed
(
struct
wl1271
*
wl
,
static
int
wl
core_set_beacon_template
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_bss_conf
*
bss_conf
,
u32
changed
)
bool
is_ap
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
bool
is_ap
=
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
);
int
ret
=
0
;
if
((
changed
&
BSS_CHANGED_BEACON_INT
))
{
wl1271_debug
(
DEBUG_MASTER
,
"beacon interval updated: %d"
,
bss_conf
->
beacon_int
);
wlvif
->
beacon_int
=
bss_conf
->
beacon_int
;
}
if
((
changed
&
BSS_CHANGED_AP_PROBE_RESP
)
&&
is_ap
)
{
u32
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
if
(
!
wl1271_ap_set_probe_resp_tmpl
(
wl
,
rate
,
vif
))
{
wl1271_debug
(
DEBUG_AP
,
"probe response updated"
);
set_bit
(
WLVIF_FLAG_AP_PROBE_RESP_SET
,
&
wlvif
->
flags
);
}
}
if
((
changed
&
BSS_CHANGED_BEACON
))
{
struct
ieee80211_hdr
*
hdr
;
u32
min_rate
;
int
ret
;
int
ieoffset
=
offsetof
(
struct
ieee80211_mgmt
,
u
.
beacon
.
variable
);
struct
sk_buff
*
beacon
=
ieee80211_beacon_get
(
wl
->
hw
,
vif
);
...
...
@@ -3517,6 +3490,37 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
dev_kfree_skb
(
beacon
);
if
(
ret
<
0
)
goto
out
;
out:
return
ret
;
}
static
int
wl1271_bss_beacon_info_changed
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_bss_conf
*
bss_conf
,
u32
changed
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
bool
is_ap
=
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
);
int
ret
=
0
;
if
((
changed
&
BSS_CHANGED_BEACON_INT
))
{
wl1271_debug
(
DEBUG_MASTER
,
"beacon interval updated: %d"
,
bss_conf
->
beacon_int
);
wlvif
->
beacon_int
=
bss_conf
->
beacon_int
;
}
if
((
changed
&
BSS_CHANGED_AP_PROBE_RESP
)
&&
is_ap
)
{
u32
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
wl1271_ap_set_probe_resp_tmpl
(
wl
,
rate
,
vif
);
}
if
((
changed
&
BSS_CHANGED_BEACON
))
{
ret
=
wlcore_set_beacon_template
(
wl
,
vif
,
is_ap
);
if
(
ret
<
0
)
goto
out
;
}
out:
...
...
@@ -3551,6 +3555,14 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
ret
=
wl1271_ap_init_templates
(
wl
,
vif
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_ap_set_probe_resp_tmpl
(
wl
,
wlvif
->
basic_rate
,
vif
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_set_beacon_template
(
wl
,
vif
,
true
);
if
(
ret
<
0
)
goto
out
;
}
ret
=
wl1271_bss_beacon_info_changed
(
wl
,
vif
,
bss_conf
,
changed
);
...
...
@@ -3691,7 +3703,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
sta_rate_set
=
sta
->
supp_rates
[
wl
->
hw
->
conf
.
channel
->
band
];
if
(
sta
->
ht_cap
.
ht_supported
)
sta_rate_set
|=
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
);
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
)
|
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
1
]
<<
HW_MIMO_RATES_OFFSET
);
sta_ht_cap
=
sta
->
ht_cap
;
sta_exists
=
true
;
...
...
@@ -3704,13 +3717,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
u32
rates
;
int
ieoffset
;
wlvif
->
aid
=
bss_conf
->
aid
;
wlvif
->
channel_type
=
bss_conf
->
channel_type
;
wlvif
->
beacon_int
=
bss_conf
->
beacon_int
;
do_join
=
true
;
set_assoc
=
true
;
/* Cancel connection_loss_work */
cancel_delayed_work_sync
(
&
wl
->
connection_loss_work
);
/*
* use basic rates from AP, and determine lowest rate
* to use with control frames.
...
...
@@ -3960,6 +3971,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 bss info changed 0x%x"
,
(
int
)
changed
);
/*
* make sure to cancel pending disconnections if our association
* state changed
*/
if
(
!
is_ap
&&
(
changed
&
BSS_CHANGED_ASSOC
))
cancel_delayed_work_sync
(
&
wl
->
connection_loss_work
);
if
(
is_ap
&&
(
changed
&
BSS_CHANGED_BEACON_ENABLED
)
&&
!
bss_conf
->
enable_beacon
)
wl1271_tx_flush
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
...
...
@@ -4636,7 +4658,7 @@ static const struct ieee80211_ops wl1271_ops = {
.
prepare_multicast
=
wl1271_op_prepare_multicast
,
.
configure_filter
=
wl1271_op_configure_filter
,
.
tx
=
wl1271_op_tx
,
.
set_key
=
wl
1271
_op_set_key
,
.
set_key
=
wl
core
_op_set_key
,
.
hw_scan
=
wl1271_op_hw_scan
,
.
cancel_hw_scan
=
wl1271_op_cancel_hw_scan
,
.
sched_scan_start
=
wl1271_op_sched_scan_start
,
...
...
@@ -4905,14 +4927,8 @@ static int wl1271_register_hw(struct wl1271 *wl)
if
(
wl
->
mac80211_registered
)
return
0
;
ret
=
wl12xx_get_hw_info
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't get hw info"
);
goto
out
;
}
ret
=
wl1271_fetch_nvs
(
wl
);
if
(
ret
==
0
)
{
wl1271_fetch_nvs
(
wl
);
if
(
wl
->
nvs
!=
NULL
)
{
/* NOTE: The wl->nvs->nvs element must be first, in
* order to simplify the casting, we assume it is at
* the beginning of the wl->nvs structure.
...
...
@@ -4970,9 +4986,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
WL1271_CIPHER_SUITE_GEM
,
};
/* The tx descriptor buffer and the TKIP space. */
wl
->
hw
->
extra_tx_headroom
=
WL1271_EXTRA_SPACE_TKIP
+
sizeof
(
struct
wl1271_tx_hw_descr
);
/* The tx descriptor buffer */
wl
->
hw
->
extra_tx_headroom
=
sizeof
(
struct
wl1271_tx_hw_descr
);
if
(
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
wl
->
hw
->
extra_tx_headroom
+=
WL1271_EXTRA_SPACE_TKIP
;
/* unit us */
/* FIXME: find a proper value */
...
...
@@ -5025,12 +5043,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
*/
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_2GHZ
],
&
wl1271_band_2ghz
,
sizeof
(
wl1271_band_2ghz
));
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_2GHZ
].
ht_cap
,
&
wl
->
ht_cap
,
sizeof
(
wl
->
ht_cap
));
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_2GHZ
].
ht_cap
,
&
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
],
sizeof
(
*
wl
->
ht_cap
));
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_5GHZ
],
&
wl1271_band_5ghz
,
sizeof
(
wl1271_band_5ghz
));
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_5GHZ
].
ht_cap
,
&
wl
->
ht_cap
,
sizeof
(
wl
->
ht_cap
));
memcpy
(
&
wl
->
bands
[
IEEE80211_BAND_5GHZ
].
ht_cap
,
&
wl
->
ht_cap
[
IEEE80211_BAND_5GHZ
],
sizeof
(
*
wl
->
ht_cap
));
wl
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
]
=
&
wl
->
bands
[
IEEE80211_BAND_2GHZ
];
...
...
@@ -5117,6 +5137,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
wl
->
rx_counter
=
0
;
wl
->
power_level
=
WL1271_DEFAULT_POWER_LEVEL
;
wl
->
band
=
IEEE80211_BAND_2GHZ
;
wl
->
channel_type
=
NL80211_CHAN_NO_HT
;
wl
->
flags
=
0
;
wl
->
sg_enabled
=
true
;
wl
->
hw_pg_ver
=
-
1
;
...
...
@@ -5142,6 +5163,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
wl
->
state
=
WL1271_STATE_OFF
;
wl
->
fw_type
=
WL12XX_FW_TYPE_NONE
;
mutex_init
(
&
wl
->
mutex
);
mutex_init
(
&
wl
->
flush_mutex
);
order
=
get_order
(
WL1271_AGGR_BUFFER_SIZE
);
wl
->
aggr_buf
=
(
u8
*
)
__get_free_pages
(
GFP_KERNEL
,
order
);
...
...
@@ -5222,7 +5244,7 @@ int wlcore_free_hw(struct wl1271 *wl)
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
kfree
(
wl
->
fw_status
);
kfree
(
wl
->
fw_status
_1
);
kfree
(
wl
->
tx_res_if
);
destroy_workqueue
(
wl
->
freezable_wq
);
...
...
@@ -5279,8 +5301,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
wlcore_adjust_conf
(
wl
);
wl
->
irq
=
platform_get_irq
(
pdev
,
0
);
wl
->
ref_clock
=
pdata
->
board_ref_clock
;
wl
->
tcxo_clock
=
pdata
->
board_tcxo_clock
;
wl
->
platform_quirks
=
pdata
->
platform_quirks
;
wl
->
set_power
=
pdata
->
set_power
;
wl
->
dev
=
&
pdev
->
dev
;
...
...
@@ -5316,6 +5336,16 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
}
disable_irq
(
wl
->
irq
);
ret
=
wl12xx_get_hw_info
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't get hw info"
);
goto
out
;
}
ret
=
wl
->
ops
->
identify_chip
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
goto
out_irq
;
...
...
drivers/net/wireless/ti/wlcore/ps.c
View file @
bf34e683
...
...
@@ -28,6 +28,8 @@
#define WL1271_WAKEUP_TIMEOUT 500
#define ELP_ENTRY_DELAY 5
void
wl1271_elp_work
(
struct
work_struct
*
work
)
{
struct
delayed_work
*
dwork
;
...
...
@@ -72,6 +74,7 @@ void wl1271_elp_work(struct work_struct *work)
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
)
{
struct
wl12xx_vif
*
wlvif
;
u32
timeout
;
if
(
wl
->
quirks
&
WLCORE_QUIRK_NO_ELP
)
return
;
...
...
@@ -89,8 +92,13 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
return
;
}
if
(
wl
->
conf
.
conn
.
forced_ps
)
timeout
=
ELP_ENTRY_DELAY
;
else
timeout
=
wl
->
conf
.
conn
.
dynamic_ps_timeout
;
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
elp_work
,
msecs_to_jiffies
(
wl
->
conf
.
conn
.
dynamic_ps_
timeout
));
msecs_to_jiffies
(
timeout
));
}
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
)
...
...
@@ -185,8 +193,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
set_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
);
/* enable beacon early termination. Not relevant for 5GHz */
if
(
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
{
/*
* enable beacon early termination.
* Not relevant for 5GHz and for high rates.
*/
if
((
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
&&
(
wlvif
->
basic_rate
<
CONF_HW_BIT_RATE_9MBPS
))
{
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
true
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -196,7 +208,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
/* disable beacon early termination */
if
(
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
{
if
((
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
&&
(
wlvif
->
basic_rate
<
CONF_HW_BIT_RATE_9MBPS
))
{
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
false
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/net/wireless/ti/wlcore/rx.c
View file @
bf34e683
...
...
@@ -186,6 +186,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
is_data
=
1
;
wl1271_rx_status
(
wl
,
desc
,
IEEE80211_SKB_RXCB
(
skb
),
beacon
);
wlcore_hw_set_rx_csum
(
wl
,
desc
,
skb
);
seq_num
=
(
le16_to_cpu
(
hdr
->
seq_ctrl
)
&
IEEE80211_SCTL_SEQ
)
>>
4
;
wl1271_debug
(
DEBUG_RX
,
"rx skb 0x%p: %d B %s seq %d hlid %d"
,
skb
,
...
...
@@ -199,12 +200,12 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return
is_data
;
}
void
wl12xx_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status
*
status
)
void
wl12xx_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status
_1
*
status
)
{
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
u32
buf_size
;
u32
fw_rx_counter
=
status
->
fw_rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
u32
drv_rx_counter
=
wl
->
rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
u32
fw_rx_counter
=
status
->
fw_rx_counter
%
wl
->
num_rx_desc
;
u32
drv_rx_counter
=
wl
->
rx_counter
%
wl
->
num_rx_desc
;
u32
rx_counter
;
u32
pkt_len
,
align_pkt_len
;
u32
pkt_offset
,
des
;
...
...
@@ -223,7 +224,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
break
;
buf_size
+=
align_pkt_len
;
rx_counter
++
;
rx_counter
&=
NUM_RX_PKT_DESC_MOD_MASK
;
rx_counter
%=
wl
->
num_rx_desc
;
}
if
(
buf_size
==
0
)
{
...
...
@@ -263,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
wl
->
rx_counter
++
;
drv_rx_counter
++
;
drv_rx_counter
&=
NUM_RX_PKT_DESC_MOD_MASK
;
drv_rx_counter
%=
wl
->
num_rx_desc
;
pkt_offset
+=
wlcore_rx_get_align_buf_size
(
wl
,
pkt_len
);
}
}
...
...
drivers/net/wireless/ti/wlcore/rx.h
View file @
bf34e683
...
...
@@ -38,8 +38,6 @@
#define RX_DESC_PACKETID_SHIFT 11
#define RX_MAX_PACKET_ID 3
#define NUM_RX_PKT_DESC_MOD_MASK 7
#define RX_DESC_VALID_FCS 0x0001
#define RX_DESC_MATCH_RXADDR1 0x0002
#define RX_DESC_MCAST 0x0004
...
...
@@ -102,6 +100,9 @@
/* If set, the start of IP payload is not 4 bytes aligned */
#define RX_BUF_UNALIGNED_PAYLOAD BIT(20)
/* If set, the buffer was padded by the FW to be 4 bytes aligned */
#define RX_BUF_PADDED_PAYLOAD BIT(30)
/* Describes the alignment state of a Rx buffer */
enum
wl_rx_buf_align
{
WLCORE_RX_BUF_ALIGNED
,
...
...
@@ -136,7 +137,7 @@ struct wl1271_rx_descriptor {
u8
reserved
;
}
__packed
;
void
wl12xx_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status
*
status
);
void
wl12xx_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status
_1
*
status
);
u8
wl1271_rate_to_idx
(
int
rate
,
enum
ieee80211_band
band
);
int
wl1271_rx_filter_enable
(
struct
wl1271
*
wl
,
int
index
,
bool
enable
,
...
...
drivers/net/wireless/ti/wlcore/scan.c
View file @
bf34e683
...
...
@@ -411,7 +411,8 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
struct
cfg80211_sched_scan_request
*
req
,
struct
conn_scan_ch_params
*
channels
,
u32
band
,
bool
radar
,
bool
passive
,
int
start
,
int
max_channels
)
int
start
,
int
max_channels
,
u8
*
n_pactive_ch
)
{
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
j
;
...
...
@@ -479,6 +480,23 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
channels
[
j
].
tx_power_att
=
req
->
channels
[
i
]
->
max_power
;
channels
[
j
].
channel
=
req
->
channels
[
i
]
->
hw_value
;
if
((
band
==
IEEE80211_BAND_2GHZ
)
&&
(
channels
[
j
].
channel
>=
12
)
&&
(
channels
[
j
].
channel
<=
14
)
&&
(
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
)
&&
!
force_passive
)
{
/* pactive channels treated as DFS */
channels
[
j
].
flags
=
SCAN_CHANNEL_FLAGS_DFS
;
/*
* n_pactive_ch is counted down from the end of
* the passive channel list
*/
(
*
n_pactive_ch
)
++
;
wl1271_debug
(
DEBUG_SCAN
,
"n_pactive_ch = %d"
,
*
n_pactive_ch
);
}
j
++
;
}
}
...
...
@@ -491,38 +509,47 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
struct
cfg80211_sched_scan_request
*
req
,
struct
wl1271_cmd_sched_scan_config
*
cfg
)
{
u8
n_pactive_ch
=
0
;
cfg
->
passive
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels_2
,
IEEE80211_BAND_2GHZ
,
false
,
true
,
0
,
MAX_CHANNELS_2GHZ
);
MAX_CHANNELS_2GHZ
,
&
n_pactive_ch
);
cfg
->
active
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels_2
,
IEEE80211_BAND_2GHZ
,
false
,
false
,
cfg
->
passive
[
0
],
MAX_CHANNELS_2GHZ
);
MAX_CHANNELS_2GHZ
,
&
n_pactive_ch
);
cfg
->
passive
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels_5
,
IEEE80211_BAND_5GHZ
,
false
,
true
,
0
,
MAX_CHANNELS_5GHZ
);
MAX_CHANNELS_5GHZ
,
&
n_pactive_ch
);
cfg
->
dfs
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels_5
,
IEEE80211_BAND_5GHZ
,
true
,
true
,
cfg
->
passive
[
1
],
MAX_CHANNELS_5GHZ
);
MAX_CHANNELS_5GHZ
,
&
n_pactive_ch
);
cfg
->
active
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels_5
,
IEEE80211_BAND_5GHZ
,
false
,
false
,
cfg
->
passive
[
1
]
+
cfg
->
dfs
,
MAX_CHANNELS_5GHZ
);
MAX_CHANNELS_5GHZ
,
&
n_pactive_ch
);
/* 802.11j channels are not supported yet */
cfg
->
passive
[
2
]
=
0
;
cfg
->
active
[
2
]
=
0
;
cfg
->
n_pactive_ch
=
n_pactive_ch
;
wl1271_debug
(
DEBUG_SCAN
,
" 2.4GHz: active %d passive %d"
,
cfg
->
active
[
0
],
cfg
->
passive
[
0
]);
wl1271_debug
(
DEBUG_SCAN
,
" 5GHz: active %d passive %d"
,
...
...
@@ -537,6 +564,7 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
/* Returns the scan type to be used or a negative value on error */
static
int
wl12xx_scan_sched_scan_ssid_list
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
)
{
struct
wl1271_cmd_sched_scan_ssid_list
*
cmd
=
NULL
;
...
...
@@ -565,6 +593,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
goto
out
;
}
cmd
->
role_id
=
wlvif
->
dev_role_id
;
if
(
!
n_match_ssids
)
{
/* No filter, with ssids */
type
=
SCAN_SSID_FILTER_DISABLED
;
...
...
@@ -603,7 +632,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
continue
;
for
(
j
=
0
;
j
<
cmd
->
n_ssids
;
j
++
)
if
(
!
memcmp
(
req
->
ssids
[
i
].
ssid
,
if
((
req
->
ssids
[
i
].
ssid_len
==
req
->
ssids
[
j
].
ssid_len
)
&&
!
memcmp
(
req
->
ssids
[
i
].
ssid
,
cmd
->
ssids
[
j
].
ssid
,
req
->
ssids
[
i
].
ssid_len
))
{
cmd
->
ssids
[
j
].
type
=
...
...
@@ -652,6 +683,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
if
(
!
cfg
)
return
-
ENOMEM
;
cfg
->
role_id
=
wlvif
->
dev_role_id
;
cfg
->
rssi_threshold
=
c
->
rssi_threshold
;
cfg
->
snr_threshold
=
c
->
snr_threshold
;
cfg
->
n_probe_reqs
=
c
->
num_probe_reqs
;
...
...
@@ -669,7 +701,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
cfg
->
intervals
[
i
]
=
cpu_to_le32
(
req
->
interval
);
cfg
->
ssid_len
=
0
;
ret
=
wl12xx_scan_sched_scan_ssid_list
(
wl
,
req
);
ret
=
wl12xx_scan_sched_scan_ssid_list
(
wl
,
wlvif
,
req
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -741,6 +773,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if
(
!
start
)
return
-
ENOMEM
;
start
->
role_id
=
wlvif
->
dev_role_id
;
start
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_START_PERIODIC_SCAN
,
start
,
...
...
@@ -762,7 +795,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl)
ieee80211_sched_scan_results
(
wl
->
hw
);
}
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
)
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_cmd_sched_scan_stop
*
stop
;
int
ret
=
0
;
...
...
@@ -776,6 +809,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl)
return
;
}
stop
->
role_id
=
wlvif
->
dev_role_id
;
stop
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_PERIODIC_SCAN
,
stop
,
...
...
drivers/net/wireless/ti/wlcore/scan.h
View file @
bf34e683
...
...
@@ -40,7 +40,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
);
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl1271_scan_sched_scan_results
(
struct
wl1271
*
wl
);
#define WL1271_SCAN_MAX_CHANNELS 24
...
...
@@ -142,7 +142,8 @@ enum {
SCAN_BSS_TYPE_ANY
,
};
#define SCAN_CHANNEL_FLAGS_DFS BIT(0)
#define SCAN_CHANNEL_FLAGS_DFS BIT(0)
/* channel is passive until an
activity is detected on it */
#define SCAN_CHANNEL_FLAGS_DFS_ENABLED BIT(1)
struct
conn_scan_ch_params
{
...
...
@@ -185,7 +186,10 @@ struct wl1271_cmd_sched_scan_config {
u8
dfs
;
u8
padding
[
3
];
u8
n_pactive_ch
;
/* number of pactive (passive until fw detects energy)
channels in BG band */
u8
role_id
;
u8
padding
[
1
];
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
MAX_CHANNELS_5GHZ
];
...
...
@@ -212,21 +216,24 @@ struct wl1271_cmd_sched_scan_ssid_list {
u8
n_ssids
;
struct
wl1271_ssid
ssids
[
SCHED_SCAN_MAX_SSIDS
];
u8
padding
[
3
];
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_start
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
padding
[
3
];
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_stop
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
padding
[
3
];
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
...
...
drivers/net/wireless/ti/wlcore/sdio.c
View file @
bf34e683
...
...
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
...
...
@@ -32,6 +33,7 @@
#include <linux/gpio.h>
#include <linux/wl12xx.h>
#include <linux/pm_runtime.h>
#include <linux/printk.h>
#include "wlcore.h"
#include "wl12xx_80211.h"
...
...
@@ -45,6 +47,8 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
static
bool
dump
=
false
;
struct
wl12xx_sdio_glue
{
struct
device
*
dev
;
struct
platform_device
*
core
;
...
...
@@ -76,6 +80,13 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
sdio_claim_host
(
func
);
if
(
unlikely
(
dump
))
{
printk
(
KERN_DEBUG
"wlcore_sdio: READ from 0x%04x
\n
"
,
addr
);
print_hex_dump
(
KERN_DEBUG
,
"wlcore_sdio: READ "
,
DUMP_PREFIX_OFFSET
,
16
,
1
,
buf
,
len
,
false
);
}
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG
))
{
((
u8
*
)
buf
)[
0
]
=
sdio_f0_readb
(
func
,
addr
,
&
ret
);
dev_dbg
(
child
->
parent
,
"sdio read 52 addr 0x%x, byte 0x%02x
\n
"
,
...
...
@@ -105,6 +116,13 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
sdio_claim_host
(
func
);
if
(
unlikely
(
dump
))
{
printk
(
KERN_DEBUG
"wlcore_sdio: WRITE to 0x%04x
\n
"
,
addr
);
print_hex_dump
(
KERN_DEBUG
,
"wlcore_sdio: WRITE "
,
DUMP_PREFIX_OFFSET
,
16
,
1
,
buf
,
len
,
false
);
}
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG
))
{
sdio_f0_writeb
(
func
,
((
u8
*
)
buf
)[
0
],
addr
,
&
ret
);
dev_dbg
(
child
->
parent
,
"sdio write 52 addr 0x%x, byte 0x%02x
\n
"
,
...
...
@@ -196,6 +214,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
struct
resource
res
[
1
];
mmc_pm_flag_t
mmcflags
;
int
ret
=
-
ENOMEM
;
const
char
*
chip_family
;
/* We are only able to handle the wlan function */
if
(
func
->
num
!=
0x02
)
...
...
@@ -236,7 +255,18 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle
(
&
func
->
dev
);
glue
->
core
=
platform_device_alloc
(
"wl12xx"
,
-
1
);
/*
* Due to a hardware bug, we can't differentiate wl18xx from
* wl12xx, because both report the same device ID. The only
* way to differentiate is by checking the SDIO revision,
* which is 3.00 on the wl18xx chips.
*/
if
(
func
->
card
->
cccr
.
sdio_vsn
==
SDIO_SDIO_REV_3_00
)
chip_family
=
"wl18xx"
;
else
chip_family
=
"wl12xx"
;
glue
->
core
=
platform_device_alloc
(
chip_family
,
-
1
);
if
(
!
glue
->
core
)
{
dev_err
(
glue
->
dev
,
"can't allocate platform_device"
);
ret
=
-
ENOMEM
;
...
...
@@ -367,6 +397,9 @@ static void __exit wl1271_exit(void)
module_init
(
wl1271_init
);
module_exit
(
wl1271_exit
);
module_param
(
dump
,
bool
,
S_IRUSR
|
S_IWUSR
);
MODULE_PARM_DESC
(
dump
,
"Enable sdio read/write dumps."
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
...
...
drivers/net/wireless/ti/wlcore/tx.c
View file @
bf34e683
...
...
@@ -72,7 +72,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
return
id
;
}
static
void
wl1271_free_tx_id
(
struct
wl1271
*
wl
,
int
id
)
void
wl1271_free_tx_id
(
struct
wl1271
*
wl
,
int
id
)
{
if
(
__test_and_clear_bit
(
id
,
wl
->
tx_frames_map
))
{
if
(
unlikely
(
wl
->
tx_frames_cnt
==
wl
->
num_tx_desc
))
...
...
@@ -82,6 +82,7 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
wl
->
tx_frames_cnt
--
;
}
}
EXPORT_SYMBOL
(
wl1271_free_tx_id
);
static
void
wl1271_tx_ap_update_inconnection_sta
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
...
...
@@ -127,6 +128,7 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
{
return
wl
->
dummy_packet
==
skb
;
}
EXPORT_SYMBOL
(
wl12xx_is_dummy_packet
);
u8
wl12xx_tx_get_hlid_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
...
...
@@ -146,10 +148,10 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
wl
->
system_hlid
;
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
ieee80211_is_mgmt
(
hdr
->
frame_control
))
return
wlvif
->
ap
.
global_hlid
;
else
if
(
is_multicast_ether_addr
(
ieee80211_get_DA
(
hdr
)))
return
wlvif
->
ap
.
bcast_hlid
;
else
return
wlvif
->
ap
.
global_hlid
;
}
}
...
...
@@ -176,37 +178,34 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
unsigned
int
wlcore_calc_packet_alignment
(
struct
wl1271
*
wl
,
unsigned
int
packet_length
)
{
if
(
wl
->
quirks
&
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
)
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
else
if
((
wl
->
quirks
&
WLCORE_QUIRK_TX_PAD_LAST_FRAME
)
||
!
(
wl
->
quirks
&
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
))
return
ALIGN
(
packet_length
,
WL1271_TX_ALIGN_TO
);
else
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
}
EXPORT_SYMBOL
(
wlcore_calc_packet_alignment
);
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
,
u8
hlid
)
u8
hlid
,
bool
is_gem
)
{
struct
wl1271_tx_hw_descr
*
desc
;
u32
total_len
=
skb
->
len
+
sizeof
(
struct
wl1271_tx_hw_descr
)
+
extra
;
u32
total_blocks
;
int
id
,
ret
=
-
EBUSY
,
ac
;
u32
spare_blocks
=
wl
->
normal_tx_spare
;
bool
is_dummy
=
false
;
u32
spare_blocks
;
if
(
buf_offset
+
total_len
>
WL1271_AGGR_BUFFER_SIZE
)
return
-
EAGAIN
;
spare_blocks
=
wlcore_hw_get_spare_blocks
(
wl
,
is_gem
);
/* allocate free identifier for the packet */
id
=
wl1271_alloc_tx_id
(
wl
,
skb
);
if
(
id
<
0
)
return
id
;
if
(
unlikely
(
wl12xx_is_dummy_packet
(
wl
,
skb
)))
is_dummy
=
true
;
else
if
(
wlvif
->
is_gem
)
spare_blocks
=
wl
->
gem_tx_spare
;
total_blocks
=
wlcore_hw_calc_tx_blocks
(
wl
,
total_len
,
spare_blocks
);
if
(
total_blocks
<=
wl
->
tx_blocks_available
)
{
...
...
@@ -228,7 +227,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
wl
->
tx_allocated_pkts
[
ac
]
++
;
if
(
!
is_dummy
&&
wlvif
&&
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
)
&&
wlvif
&&
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
&&
test_bit
(
hlid
,
wlvif
->
ap
.
sta_hlid_map
))
wl
->
links
[
hlid
].
allocated_pkts
++
;
...
...
@@ -268,6 +267,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if
(
extra
)
{
int
hdrlen
=
ieee80211_hdrlen
(
frame_control
);
memmove
(
frame_start
,
hdr
,
hdrlen
);
skb_set_network_header
(
skb
,
skb_network_offset
(
skb
)
+
extra
);
}
/* configure packet life time */
...
...
@@ -330,9 +330,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ieee80211_has_protected
(
frame_control
))
tx_attr
|=
TX_HW_ATTR_HOST_ENCRYPT
;
desc
->
reserved
=
0
;
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
wlcore_hw_set_tx_desc_csum
(
wl
,
desc
,
skb
);
wlcore_hw_set_tx_desc_data_len
(
wl
,
desc
,
skb
);
}
...
...
@@ -346,6 +346,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32
total_len
;
u8
hlid
;
bool
is_dummy
;
bool
is_gem
=
false
;
if
(
!
skb
)
return
-
EINVAL
;
...
...
@@ -355,7 +356,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
/* TODO: handle dummy packets on multi-vifs */
is_dummy
=
wl12xx_is_dummy_packet
(
wl
,
skb
);
if
(
info
->
control
.
hw_key
&&
if
((
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
&&
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
extra
=
WL1271_EXTRA_SPACE_TKIP
;
...
...
@@ -373,6 +375,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
wlvif
->
default_key
=
idx
;
}
is_gem
=
(
cipher
==
WL1271_CIPHER_SUITE_GEM
);
}
hlid
=
wl12xx_tx_get_hlid
(
wl
,
wlvif
,
skb
);
if
(
hlid
==
WL12XX_INVALID_LINK_ID
)
{
...
...
@@ -380,7 +384,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
-
EINVAL
;
}
ret
=
wl1271_tx_allocate
(
wl
,
wlvif
,
skb
,
extra
,
buf_offset
,
hlid
);
ret
=
wl1271_tx_allocate
(
wl
,
wlvif
,
skb
,
extra
,
buf_offset
,
hlid
,
is_gem
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -425,10 +430,10 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
rate_set
>>=
1
;
}
/* MCS rates indication are on bits 16 -
23
*/
/* MCS rates indication are on bits 16 -
31
*/
rate_set
>>=
HW_HT_RATES_OFFSET
-
band
->
n_bitrates
;
for
(
bit
=
0
;
bit
<
8
;
bit
++
)
{
for
(
bit
=
0
;
bit
<
16
;
bit
++
)
{
if
(
rate_set
&
0x1
)
enabled_rates
|=
(
CONF_HW_BIT_RATE_MCS_0
<<
bit
);
rate_set
>>=
1
;
...
...
@@ -439,18 +444,15 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
void
wl1271_handle_tx_low_watermark
(
struct
wl1271
*
wl
)
{
unsigned
long
flags
;
int
i
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
if
(
test_bit
(
i
,
&
wl
->
stopped_queues_map
)
&&
if
(
wlcore_is_queue_stopped_by_reason
(
wl
,
i
,
WLCORE_QUEUE_STOP_REASON_WATERMARK
)
&&
wl
->
tx_queue_count
[
i
]
<=
WL1271_TX_QUEUE_LOW_WATERMARK
)
{
/* firmware buffer has space, restart queues */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
ieee80211_wake_queue
(
wl
->
hw
,
wl1271_tx_get_mac80211_queue
(
i
));
clear_bit
(
i
,
&
wl
->
stopped_queues_map
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
wlcore_wake_queue
(
wl
,
i
,
WLCORE_QUEUE_STOP_REASON_WATERMARK
);
}
}
}
...
...
@@ -661,7 +663,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
struct
wl12xx_vif
*
wlvif
;
struct
sk_buff
*
skb
;
struct
wl1271_tx_hw_descr
*
desc
;
u32
buf_offset
=
0
;
u32
buf_offset
=
0
,
last_len
=
0
;
bool
sent_packets
=
false
;
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
int
ret
;
...
...
@@ -685,6 +687,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Flush buffer and try again.
*/
wl1271_skb_queue_head
(
wl
,
wlvif
,
skb
);
buf_offset
=
wlcore_hw_pre_pkt_send
(
wl
,
buf_offset
,
last_len
);
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
sent_packets
=
true
;
...
...
@@ -710,7 +715,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
ieee80211_free_txskb
(
wl
->
hw
,
skb
);
goto
out_ack
;
}
buf_offset
+=
ret
;
last_len
=
ret
;
buf_offset
+=
last_len
;
wl
->
tx_packets_count
++
;
if
(
has_data
)
{
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb
->
data
;
...
...
@@ -720,6 +726,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
out_ack:
if
(
buf_offset
)
{
buf_offset
=
wlcore_hw_pre_pkt_send
(
wl
,
buf_offset
,
last_len
);
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
sent_packets
=
true
;
...
...
@@ -849,7 +856,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
/* remove TKIP header space if present */
if
(
info
->
control
.
hw_key
&&
if
((
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
&&
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_EXTRA_SPACE_TKIP
,
skb
->
data
,
...
...
@@ -958,7 +966,7 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
}
/* caller must hold wl->mutex and TX must be stopped */
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
)
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
)
{
int
i
;
struct
sk_buff
*
skb
;
...
...
@@ -973,14 +981,11 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
wl
->
tx_queue_count
[
i
]
=
0
;
}
wl
->
stopped_queues_map
=
0
;
/*
* Make sure the driver is at a consistent state, in case this
* function is called from a context other than interface removal.
* This call will always wake the TX queues.
*/
if
(
reset_tx_queues
)
wl1271_handle_tx_low_watermark
(
wl
);
for
(
i
=
0
;
i
<
wl
->
num_tx_desc
;
i
++
)
{
...
...
@@ -998,7 +1003,8 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
*/
info
=
IEEE80211_SKB_CB
(
skb
);
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
if
(
info
->
control
.
hw_key
&&
if
((
wl
->
quirks
&
WLCORE_QUIRK_TKIP_HEADER_SPACE
)
&&
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
...
...
@@ -1024,6 +1030,11 @@ void wl1271_tx_flush(struct wl1271 *wl)
int
i
;
timeout
=
jiffies
+
usecs_to_jiffies
(
WL1271_TX_FLUSH_TIMEOUT
);
/* only one flush should be in progress, for consistent queue state */
mutex_lock
(
&
wl
->
flush_mutex
);
wlcore_stop_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_FLUSH
);
while
(
!
time_after
(
jiffies
,
timeout
))
{
mutex_lock
(
&
wl
->
mutex
);
wl1271_debug
(
DEBUG_TX
,
"flushing tx buffer: %d %d"
,
...
...
@@ -1032,7 +1043,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
if
((
wl
->
tx_frames_cnt
==
0
)
&&
(
wl1271_tx_total_queue_count
(
wl
)
==
0
))
{
mutex_unlock
(
&
wl
->
mutex
);
return
;
goto
out
;
}
mutex_unlock
(
&
wl
->
mutex
);
msleep
(
1
);
...
...
@@ -1045,7 +1056,12 @@ void wl1271_tx_flush(struct wl1271 *wl)
for
(
i
=
0
;
i
<
WL12XX_MAX_LINKS
;
i
++
)
wl1271_tx_reset_link_queues
(
wl
,
i
);
mutex_unlock
(
&
wl
->
mutex
);
out:
wlcore_wake_queues
(
wl
,
WLCORE_QUEUE_STOP_REASON_FLUSH
);
mutex_unlock
(
&
wl
->
flush_mutex
);
}
EXPORT_SYMBOL_GPL
(
wl1271_tx_flush
);
u32
wl1271_tx_min_rate_get
(
struct
wl1271
*
wl
,
u32
rate_set
)
{
...
...
@@ -1054,3 +1070,96 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
return
BIT
(
__ffs
(
rate_set
));
}
void
wlcore_stop_queue_locked
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
)
{
bool
stopped
=
!!
wl
->
queue_stop_reasons
[
queue
];
/* queue should not be stopped for this reason */
WARN_ON
(
test_and_set_bit
(
reason
,
&
wl
->
queue_stop_reasons
[
queue
]));
if
(
stopped
)
return
;
ieee80211_stop_queue
(
wl
->
hw
,
wl1271_tx_get_mac80211_queue
(
queue
));
}
void
wlcore_stop_queue
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wlcore_stop_queue_locked
(
wl
,
queue
,
reason
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
void
wlcore_wake_queue
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
/* queue should not be clear for this reason */
WARN_ON
(
!
test_and_clear_bit
(
reason
,
&
wl
->
queue_stop_reasons
[
queue
]));
if
(
wl
->
queue_stop_reasons
[
queue
])
goto
out
;
ieee80211_wake_queue
(
wl
->
hw
,
wl1271_tx_get_mac80211_queue
(
queue
));
out:
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
void
wlcore_stop_queues
(
struct
wl1271
*
wl
,
enum
wlcore_queue_stop_reason
reason
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
wlcore_stop_queue
(
wl
,
i
,
reason
);
}
EXPORT_SYMBOL_GPL
(
wlcore_stop_queues
);
void
wlcore_wake_queues
(
struct
wl1271
*
wl
,
enum
wlcore_queue_stop_reason
reason
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
wlcore_wake_queue
(
wl
,
i
,
reason
);
}
EXPORT_SYMBOL_GPL
(
wlcore_wake_queues
);
void
wlcore_reset_stopped_queues
(
struct
wl1271
*
wl
)
{
int
i
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
if
(
!
wl
->
queue_stop_reasons
[
i
])
continue
;
wl
->
queue_stop_reasons
[
i
]
=
0
;
ieee80211_wake_queue
(
wl
->
hw
,
wl1271_tx_get_mac80211_queue
(
i
));
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
bool
wlcore_is_queue_stopped_by_reason
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
)
{
return
test_bit
(
reason
,
&
wl
->
queue_stop_reasons
[
queue
]);
}
bool
wlcore_is_queue_stopped
(
struct
wl1271
*
wl
,
u8
queue
)
{
return
!!
wl
->
queue_stop_reasons
[
queue
];
}
drivers/net/wireless/ti/wlcore/tx.h
View file @
bf34e683
...
...
@@ -85,6 +85,19 @@ struct wl128x_tx_mem {
u8
extra_bytes
;
}
__packed
;
struct
wl18xx_tx_mem
{
/*
* Total number of memory blocks allocated by the host for
* this packet.
*/
u8
total_mem_blocks
;
/*
* control bits
*/
u8
ctrl
;
}
__packed
;
/*
* On wl128x based devices, when TX packets are aggregated, each packet
* size must be aligned to the SDIO block size. The maximum block size
...
...
@@ -100,6 +113,7 @@ struct wl1271_tx_hw_descr {
union
{
struct
wl127x_tx_mem
wl127x_mem
;
struct
wl128x_tx_mem
wl128x_mem
;
struct
wl18xx_tx_mem
wl18xx_mem
;
}
__packed
;
/* Device time (in us) when the packet arrived to the driver */
__le32
start_time
;
...
...
@@ -116,7 +130,16 @@ struct wl1271_tx_hw_descr {
u8
tid
;
/* host link ID (HLID) */
u8
hlid
;
u8
reserved
;
union
{
u8
wl12xx_reserved
;
/*
* bit 0 -> 0 = udp, 1 = tcp
* bit 1:7 -> IP header offset
*/
u8
wl18xx_checksum_data
;
}
__packed
;
}
__packed
;
enum
wl1271_tx_hw_res_status
{
...
...
@@ -161,6 +184,13 @@ struct wl1271_tx_hw_res_if {
struct
wl1271_tx_hw_res_descr
tx_results_queue
[
TX_HW_RESULT_QUEUE_LEN
];
}
__packed
;
enum
wlcore_queue_stop_reason
{
WLCORE_QUEUE_STOP_REASON_WATERMARK
,
WLCORE_QUEUE_STOP_REASON_FW_RESTART
,
WLCORE_QUEUE_STOP_REASON_FLUSH
,
WLCORE_QUEUE_STOP_REASON_SPARE_BLK
,
/* 18xx specific */
};
static
inline
int
wl1271_tx_get_queue
(
int
queue
)
{
switch
(
queue
)
{
...
...
@@ -207,7 +237,7 @@ void wl1271_tx_work(struct work_struct *work);
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
);
void
wl1271_tx_complete
(
struct
wl1271
*
wl
);
void
wl12xx_tx_reset_wlvif
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
);
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
);
void
wl1271_tx_flush
(
struct
wl1271
*
wl
);
u8
wlcore_rate_to_idx
(
struct
wl1271
*
wl
,
u8
rate
,
enum
ieee80211_band
band
);
u32
wl1271_tx_enabled_rates_get
(
struct
wl1271
*
wl
,
u32
rate_set
,
...
...
@@ -223,6 +253,21 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
void
wl12xx_rearm_rx_streaming
(
struct
wl1271
*
wl
,
unsigned
long
*
active_hlids
);
unsigned
int
wlcore_calc_packet_alignment
(
struct
wl1271
*
wl
,
unsigned
int
packet_length
);
void
wl1271_free_tx_id
(
struct
wl1271
*
wl
,
int
id
);
void
wlcore_stop_queue_locked
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
);
void
wlcore_stop_queue
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
);
void
wlcore_wake_queue
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
);
void
wlcore_stop_queues
(
struct
wl1271
*
wl
,
enum
wlcore_queue_stop_reason
reason
);
void
wlcore_wake_queues
(
struct
wl1271
*
wl
,
enum
wlcore_queue_stop_reason
reason
);
void
wlcore_reset_stopped_queues
(
struct
wl1271
*
wl
);
bool
wlcore_is_queue_stopped_by_reason
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
);
bool
wlcore_is_queue_stopped
(
struct
wl1271
*
wl
,
u8
queue
);
/* from main.c */
void
wl1271_free_sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
);
...
...
drivers/net/wireless/ti/wlcore/wlcore.h
View file @
bf34e683
...
...
@@ -24,8 +24,9 @@
#include <linux/platform_device.h>
#include "wl
12xx
.h"
#include "wl
core_i
.h"
#include "event.h"
#include "boot.h"
/* The maximum number of Tx descriptors in all chip families */
#define WLCORE_MAX_TX_DESCRIPTORS 32
...
...
@@ -33,11 +34,13 @@
/* forward declaration */
struct
wl1271_tx_hw_descr
;
enum
wl_rx_buf_align
;
struct
wl1271_rx_descriptor
;
struct
wlcore_ops
{
int
(
*
identify_chip
)(
struct
wl1271
*
wl
);
int
(
*
identify_fw
)(
struct
wl1271
*
wl
);
int
(
*
boot
)(
struct
wl1271
*
wl
);
int
(
*
plt_init
)(
struct
wl1271
*
wl
);
void
(
*
trigger_cmd
)(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
);
void
(
*
ack_event
)(
struct
wl1271
*
wl
);
...
...
@@ -61,6 +64,23 @@ struct wlcore_ops {
struct
wl12xx_vif
*
wlvif
);
s8
(
*
get_pg_ver
)(
struct
wl1271
*
wl
);
void
(
*
get_mac
)(
struct
wl1271
*
wl
);
void
(
*
set_tx_desc_csum
)(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
);
void
(
*
set_rx_csum
)(
struct
wl1271
*
wl
,
struct
wl1271_rx_descriptor
*
desc
,
struct
sk_buff
*
skb
);
u32
(
*
ap_get_mimo_wide_rate_mask
)(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
(
*
debugfs_init
)(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
);
int
(
*
handle_static_data
)(
struct
wl1271
*
wl
,
struct
wl1271_static_data
*
static_data
);
int
(
*
get_spare_blocks
)(
struct
wl1271
*
wl
,
bool
is_gem
);
int
(
*
set_key
)(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
);
u32
(
*
pre_pkt_send
)(
struct
wl1271
*
wl
,
u32
buf_offset
,
u32
last_len
);
};
enum
wlcore_partitions
{
...
...
@@ -109,6 +129,15 @@ enum wlcore_registers {
REG_TABLE_LEN
,
};
struct
wl1271_stats
{
void
*
fw_stats
;
unsigned
long
fw_stats_update
;
size_t
fw_stats_len
;
unsigned
int
retry_count
;
unsigned
int
excessive_retries
;
};
struct
wl1271
{
struct
ieee80211_hw
*
hw
;
bool
mac80211_registered
;
...
...
@@ -121,7 +150,6 @@ struct wl1271 {
void
(
*
set_power
)(
bool
enable
);
int
irq
;
int
ref_clock
;
spinlock_t
wl_lock
;
...
...
@@ -186,7 +214,7 @@ struct wl1271 {
/* Frames scheduled for transmission, not handled yet */
int
tx_queue_count
[
NUM_TX_QUEUES
];
long
stopped_queues_map
;
unsigned
long
queue_stop_reasons
[
NUM_TX_QUEUES
]
;
/* Frames received, not handled yet by mac80211 */
struct
sk_buff_head
deferred_rx_queue
;
...
...
@@ -205,9 +233,6 @@ struct wl1271 {
/* FW Rx counter */
u32
rx_counter
;
/* Rx memory pool address */
struct
wl1271_rx_mem_pool_addr
rx_mem_pool_addr
;
/* Intermediate buffer, used for packet aggregation */
u8
*
aggr_buf
;
...
...
@@ -228,6 +253,7 @@ struct wl1271 {
/* Hardware recovery work */
struct
work_struct
recovery_work
;
bool
watchdog_recovery
;
/* Pointer that holds DMA-friendly block for the mailbox */
struct
event_mailbox
*
mbox
;
...
...
@@ -263,7 +289,8 @@ struct wl1271 {
u32
buffer_cmd
;
u32
buffer_busyword
[
WL1271_BUSY_WORD_CNT
];
struct
wl_fw_status
*
fw_status
;
struct
wl_fw_status_1
*
fw_status_1
;
struct
wl_fw_status_2
*
fw_status_2
;
struct
wl1271_tx_hw_res_if
*
tx_res_if
;
/* Current chipset configuration */
...
...
@@ -279,8 +306,6 @@ struct wl1271 {
/* bands supported by this instance of wl12xx */
struct
ieee80211_supported_band
bands
[
IEEE80211_NUM_BANDS
];
int
tcxo_clock
;
/*
* wowlan trigger was configured during suspend.
* (currently, only "ANY" trigger is supported)
...
...
@@ -333,10 +358,8 @@ struct wl1271 {
/* number of TX descriptors the HW supports. */
u32
num_tx_desc
;
/* spare Tx blocks for normal/GEM operating modes */
u32
normal_tx_spare
;
u32
gem_tx_spare
;
/* number of RX descriptors the HW supports. */
u32
num_rx_desc
;
/* translate HW Tx rates to standard rate-indices */
const
u8
**
band_rate_to_idx
;
...
...
@@ -348,19 +371,32 @@ struct wl1271 {
u8
hw_min_ht_rate
;
/* HW HT (11n) capabilities */
struct
ieee80211_sta_ht_cap
ht_cap
;
struct
ieee80211_sta_ht_cap
ht_cap
[
IEEE80211_NUM_BANDS
]
;
/* size of the private FW status data */
size_t
fw_status_priv_len
;
/* RX Data filter rule state - enabled/disabled */
bool
rx_filter_enabled
[
WL1271_MAX_RX_FILTERS
];
/* size of the private static data */
size_t
static_data_priv_len
;
/* the current channel type */
enum
nl80211_channel_type
channel_type
;
/* mutex for protecting the tx_flush function */
struct
mutex
flush_mutex
;
};
int
__devinit
wlcore_probe
(
struct
wl1271
*
wl
,
struct
platform_device
*
pdev
);
int
__devexit
wlcore_remove
(
struct
platform_device
*
pdev
);
struct
ieee80211_hw
*
wlcore_alloc_hw
(
size_t
priv_size
);
int
wlcore_free_hw
(
struct
wl1271
*
wl
);
int
wlcore_set_key
(
struct
wl1271
*
wl
,
enum
set_key_cmd
cmd
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key_conf
);
/* Firmware image load chunk size */
#define CHUNK_SIZE 16384
...
...
@@ -385,6 +421,12 @@ int wlcore_free_hw(struct wl1271 *wl);
/* Some firmwares may not support ELP */
#define WLCORE_QUIRK_NO_ELP BIT(6)
/* pad only the last frame in the aggregate buffer */
#define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7)
/* extra header space is required for TKIP */
#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8)
/* TODO: move to the lower drivers when all usages are abstracted */
#define CHIP_ID_1271_PG10 (0x4030101)
#define CHIP_ID_1271_PG20 (0x4030111)
...
...
drivers/net/wireless/ti/wlcore/wl
12xx
.h
→
drivers/net/wireless/ti/wlcore/wl
core_i
.h
View file @
bf34e683
...
...
@@ -22,8 +22,8 @@
*
*/
#ifndef __WL
12XX
_H__
#define __WL
12XX
_H__
#ifndef __WL
CORE_I
_H__
#define __WL
CORE_I
_H__
#include <linux/mutex.h>
#include <linux/completion.h>
...
...
@@ -89,7 +89,7 @@
#define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_DEF_BEACON_EXP 20
#define WL1271_AGGR_BUFFER_SIZE (
4
* PAGE_SIZE)
#define WL1271_AGGR_BUFFER_SIZE (
5
* PAGE_SIZE)
enum
wl1271_state
{
WL1271_STATE_OFF
,
...
...
@@ -132,16 +132,7 @@ struct wl1271_chip {
unsigned
int
fw_ver
[
NUM_FW_VER
];
};
struct
wl1271_stats
{
struct
acx_statistics
*
fw_stats
;
unsigned
long
fw_stats_update
;
unsigned
int
retry_count
;
unsigned
int
excessive_retries
;
};
#define NUM_TX_QUEUES 4
#define NUM_RX_PKT_DESC 8
#define AP_MAX_STATIONS 8
...
...
@@ -159,13 +150,26 @@ struct wl_fw_packet_counters {
}
__packed
;
/* FW status registers */
struct
wl_fw_status
{
struct
wl_fw_status
_1
{
__le32
intr
;
u8
fw_rx_counter
;
u8
drv_rx_counter
;
u8
reserved
;
u8
tx_results_counter
;
__le32
rx_pkt_descs
[
NUM_RX_PKT_DESC
];
__le32
rx_pkt_descs
[
0
];
}
__packed
;
/*
* Each HW arch has a different number of Rx descriptors.
* The length of the status depends on it, since it holds an array
* of descriptors.
*/
#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \
(sizeof(struct wl_fw_status_1) + \
(sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \
num_rx_desc)
struct
wl_fw_status_2
{
__le32
fw_localtime
;
/*
...
...
@@ -194,11 +198,6 @@ struct wl_fw_status {
u8
priv
[
0
];
}
__packed
;
struct
wl1271_rx_mem_pool_addr
{
u32
addr
;
u32
addr_extra
;
};
#define WL1271_MAX_CHANNELS 64
struct
wl1271_scan
{
struct
cfg80211_scan_request
*
req
;
...
...
@@ -367,6 +366,7 @@ struct wl12xx_vif {
/* The current band */
enum
ieee80211_band
band
;
int
channel
;
enum
nl80211_channel_type
channel_type
;
u32
bitrate_masks
[
IEEE80211_NUM_BANDS
];
u32
basic_rate_set
;
...
...
@@ -417,9 +417,6 @@ struct wl12xx_vif {
struct
work_struct
rx_streaming_disable_work
;
struct
timer_list
rx_streaming_timer
;
/* does the current role use GEM for encryption (AP or STA) */
bool
is_gem
;
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
...
...
@@ -501,7 +498,8 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
/* Macros to handle wl1271.sta_rate_set */
#define HW_BG_RATES_MASK 0xffff
#define HW_HT_RATES_OFFSET 16
#define HW_MIMO_RATES_OFFSET 24
#define WL12XX_HW_BLOCK_SIZE 256
#endif
#endif
/* __WLCORE_I_H__ */
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