This series adds initial support for the 18xx chip family. The new
module uses wlcore for functionality common with the 12xx family.
Arik Nemtsov (28):
wl18xx: create per-chip-family private storage
wl18xx: set the number of Tx descriptors
wl18xx: set normal/GEM Tx spare block counts
wl18xx: implement hw op for calculating hw block count per packet
wl18xx: implement hw op for setting blocks in hw_tx_desc
wl18xx: implement hw op for setting frame length in tx_hw_desc
wl18xx: define HW-rate translation elements/tables
wl18xx: add fw_status private data
wl18xx: set Rx block-size alignment quirk
wl18xx: implement hw op for getting rx buffer data alignment
wl18xx: implement hw op for getting rx packet data length
wl18xx: implement immediate Tx completion
wlcore/wl18xx: add hw op for setting Tx HW checksum
wlcore/wl18xx: add hw op for Rx HW checksum
wlcore: track current channel type per vif
wl18xx: send channel type to FW on role start
wl18xx: ipmlement ap_rate_mask hw op
wlcore: support peer MIMO rates
wlcore/wl18xx: enable MIMO/wide-chan rates in AP-mode rate config
wl18xx: set HT capabilities
wl18xx: add module param for overriding HT caps
wl18xx: read FW pc on recovery
wl18xx: disable FW log functionality
wl18xx: implement hw op to read PG version
wl18xx: init Tx-released index to 0 on HW init
wl18xx: don't upload NVS to FW
wl18xx: change board type enum according to new FW
wlcore/wl12xx/18xx: split fw_status struct into two
Assaf Azulay (1):
wl18xx: change default tcp_checksum to false
Luciano Coelho (49):
wl18xx: add new module
wlcore_sdio/wl18xx: use SDIO revision number to identify wl18xx chips
wl18xx: add empty operations struct
wl18xx: add partition table
wl18xx: add register table
wl18xx: add identify chip operation
wl18xx: add some boot operations and hw-specific configurations
wl18xx: add trigger command and ack event operations
wl18xx: add hw_init operation
wl18xx: add runtime configuration parameters
wl18xx: add board type module argument
wl18xx: translate and write the board type to SCR_PAD2
wl18xx: read clock frequency and do top init accordingly
wlcore: rename wl12xx.h to wlcore_i.h
wlcore/wl12xx: move ref_clock and tcxo_clock elements to wl12xx
wlcore/wl12xx: move rx_mem_pool_addr element to wl12xx
wlcore/wl12xx: add plt_init op and move the code to wl12xx
wl18xx: add plt_init operation
wl18xx: change the low_band_component_type for HDK boards
wl18xx: add number of antennas and dc2dc type as module params
wl18xx: add module parameter to disable TCP checksum
wl18xx: derive the MAC address from the BD_ADDR in fuse ROM
wl18xx: add a module parameter to control 11a support
wlcore: add module parameter to dump SDIO reads and writes
wl18xx: copy the default configuration before checking the board_type
wl18xx: changed default board_type to HDK
wlcore: add space for private area when allocating fw_status
wl18xx: change low_band_component_type value for COM8
wlcore: reorder identify_chip and get_hw_info
wl18xx: disable MCS_13 for wl18xx PG 1.0
wlcore: update beacon and probe_resp templates when rates change
wlcore: use all AP basic rates as default
wlcore: abstract debugfs fw_stats to be handled by the lower drivers
wlcore: add debugfs macro to help print fw statistics arrays
wl12xx: implement fw status debugfs entries
wl18xx: implement fw status debugfs entries
wlcore: create private static_data area and add operation to parse it
wl18xx: print the PHY firmware version from the private static data
wlcore: print the interrupt status when recovery is triggered
wl18xx: don't use MIMO when ht_mode is set to wide
wlcore: use proper values for supported local rates
wl18xx: add module parameter to force SISO 20MHz
wl18xx: add power limit reference value to mac_and_phy settings
wl18xx: export low/high band component values as module params
wl18xx: export pwr_limit_reference_11_abg value as a module parameter
wlcore/wl12xx/wl18xx: move lower driver debugfs to a subdir
wlcore: increase aggregation buffer size by one page
wl18xx: increase tx_ba_win_size to 64
wl18xx: use new fw stats structures
drivers/net/wireless/ti/Kconfig | 1 +
drivers/net/wireless/ti/Makefile | 1 +
drivers/net/wireless/ti/wl12xx/Makefile | 2 +-
drivers/net/wireless/ti/wl12xx/acx.h | 223 +++++
drivers/net/wireless/ti/wl12xx/cmd.c | 8 +-
drivers/net/wireless/ti/wl12xx/debugfs.c | 243 ++++++
drivers/net/wireless/ti/wl12xx/debugfs.h | 28 +
drivers/net/wireless/ti/wl12xx/main.c | 164 +++-
drivers/net/wireless/ti/wl12xx/wl12xx.h | 8 +
drivers/net/wireless/ti/wl18xx/Kconfig | 6 +
drivers/net/wireless/ti/wl18xx/Makefile | 3 +
drivers/net/wireless/ti/wl18xx/acx.c | 83 ++
drivers/net/wireless/ti/wl18xx/acx.h | 241 ++++++
drivers/net/wireless/ti/wl18xx/conf.h | 53 ++
drivers/net/wireless/ti/wl18xx/debugfs.c | 309 +++++++
drivers/net/wireless/ti/wl18xx/debugfs.h | 28 +
drivers/net/wireless/ti/wl18xx/io.c | 60 ++
drivers/net/wireless/ti/wl18xx/io.h | 28 +
drivers/net/wireless/ti/wl18xx/main.c | 1282 +++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/reg.h | 241 ++++++
drivers/net/wireless/ti/wl18xx/tx.c | 126 +++
drivers/net/wireless/ti/wl18xx/tx.h | 42 +
drivers/net/wireless/ti/wl18xx/wl18xx.h | 87 ++
drivers/net/wireless/ti/wlcore/acx.c | 8 +-
drivers/net/wireless/ti/wlcore/acx.h | 227 +----
drivers/net/wireless/ti/wlcore/boot.c | 53 +-
drivers/net/wireless/ti/wlcore/boot.h | 1 +
drivers/net/wireless/ti/wlcore/cmd.c | 34 +-
drivers/net/wireless/ti/wlcore/cmd.h | 11 +-
drivers/net/wireless/ti/wlcore/conf.h | 16 +-
drivers/net/wireless/ti/wlcore/debugfs.c | 283 +------
drivers/net/wireless/ti/wlcore/debugfs.h | 87 ++
drivers/net/wireless/ti/wlcore/hw_ops.h | 48 ++
drivers/net/wireless/ti/wlcore/init.c | 3 +
drivers/net/wireless/ti/wlcore/main.c | 362 ++++----
drivers/net/wireless/ti/wlcore/rx.c | 11 +-
drivers/net/wireless/ti/wlcore/rx.h | 7 +-
drivers/net/wireless/ti/wlcore/sdio.c | 35 +-
drivers/net/wireless/ti/wlcore/tx.c | 11 +-
drivers/net/wireless/ti/wlcore/tx.h | 26 +-
drivers/net/wireless/ti/wlcore/wl12xx.h | 507 ------------
drivers/net/wireless/ti/wlcore/wlcore.h | 42 +-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 508 ++++++++++++
43 files changed, 4306 insertions(+), 1241 deletions(-)
create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.c
create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.h
create mode 100644 drivers/net/wireless/ti/wl18xx/Kconfig
create mode 100644 drivers/net/wireless/ti/wl18xx/Makefile
create mode 100644 drivers/net/wireless/ti/wl18xx/acx.c
create mode 100644 drivers/net/wireless/ti/wl18xx/acx.h
create mode 100644 drivers/net/wireless/ti/wl18xx/conf.h
create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.c
create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.h
create mode 100644 drivers/net/wireless/ti/wl18xx/io.c
create mode 100644 drivers/net/wireless/ti/wl18xx/io.h
create mode 100644 drivers/net/wireless/ti/wl18xx/main.c
create mode 100644 drivers/net/wireless/ti/wl18xx/reg.h
create mode 100644 drivers/net/wireless/ti/wl18xx/tx.c
create mode 100644 drivers/net/wireless/ti/wl18xx/tx.h
create mode 100644 drivers/net/wireless/ti/wl18xx/wl18xx.h
delete mode 100644 drivers/net/wireless/ti/wlcore/wl12xx.h
create mode 100644 drivers/net/wireless/ti/wlcore/wlcore_i.h
--
1.7.9.5
From: Luciano Coelho <[email protected]>
When the data rates change, we get BSS_CHANGED_BASIC_RATES. At this
point, we should update all the templates to match the new rates. We
were changing some of the templates, but the beacon and the probe
response templates were missing.
[Remove redundant min_rate variable - Arik]
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 173 +++++++++++++++++++--------------
1 file changed, 100 insertions(+), 73 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 9b8f6a2..f952098 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3276,8 +3276,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;
}
@@ -3382,6 +3389,87 @@ out:
return ret;
}
+static int wlcore_set_beacon_template(struct wl1271 *wl,
+ struct ieee80211_vif *vif,
+ bool is_ap)
+{
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ 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);
+ u16 tmpl_id;
+
+ if (!beacon) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_MASTER, "beacon updated");
+
+ ret = wl1271_ssid_set(vif, beacon, ieoffset);
+ if (ret < 0) {
+ dev_kfree_skb(beacon);
+ goto out;
+ }
+ min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
+ tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
+ CMD_TEMPL_BEACON;
+ ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id,
+ beacon->data,
+ beacon->len, 0,
+ min_rate);
+ if (ret < 0) {
+ dev_kfree_skb(beacon);
+ goto out;
+ }
+
+ /*
+ * In case we already have a probe-resp beacon set explicitly
+ * by usermode, don't use the beacon data.
+ */
+ if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags))
+ goto end_bcn;
+
+ /* remove TIM ie from probe response */
+ wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
+
+ /*
+ * remove p2p ie from probe response.
+ * the fw reponds to probe requests that don't include
+ * the p2p ie. probe requests with p2p ie will be passed,
+ * and will be responded by the supplicant (the spec
+ * forbids including the p2p ie when responding to probe
+ * requests that didn't include it).
+ */
+ wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
+ WLAN_OUI_TYPE_WFA_P2P, ieoffset);
+
+ hdr = (struct ieee80211_hdr *) beacon->data;
+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_PROBE_RESP);
+ if (is_ap)
+ ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif,
+ beacon->data,
+ beacon->len,
+ min_rate);
+ else
+ ret = wl1271_cmd_template_set(wl, wlvif->role_id,
+ CMD_TEMPL_PROBE_RESPONSE,
+ beacon->data,
+ beacon->len, 0,
+ min_rate);
+end_bcn:
+ 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,
@@ -3400,81 +3488,12 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
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);
- }
+
+ wl1271_ap_set_probe_resp_tmpl(wl, rate, vif);
}
if ((changed & BSS_CHANGED_BEACON)) {
- struct ieee80211_hdr *hdr;
- u32 min_rate;
- int ieoffset = offsetof(struct ieee80211_mgmt,
- u.beacon.variable);
- struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
- u16 tmpl_id;
-
- if (!beacon) {
- ret = -EINVAL;
- goto out;
- }
-
- wl1271_debug(DEBUG_MASTER, "beacon updated");
-
- ret = wl1271_ssid_set(vif, beacon, ieoffset);
- if (ret < 0) {
- dev_kfree_skb(beacon);
- goto out;
- }
- min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
- tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
- CMD_TEMPL_BEACON;
- ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id,
- beacon->data,
- beacon->len, 0,
- min_rate);
- if (ret < 0) {
- dev_kfree_skb(beacon);
- goto out;
- }
-
- /*
- * In case we already have a probe-resp beacon set explicitly
- * by usermode, don't use the beacon data.
- */
- if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags))
- goto end_bcn;
-
- /* remove TIM ie from probe response */
- wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
-
- /*
- * remove p2p ie from probe response.
- * the fw reponds to probe requests that don't include
- * the p2p ie. probe requests with p2p ie will be passed,
- * and will be responded by the supplicant (the spec
- * forbids including the p2p ie when responding to probe
- * requests that didn't include it).
- */
- wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
- WLAN_OUI_TYPE_WFA_P2P, ieoffset);
-
- hdr = (struct ieee80211_hdr *) beacon->data;
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_PROBE_RESP);
- if (is_ap)
- ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif,
- beacon->data,
- beacon->len,
- min_rate);
- else
- ret = wl1271_cmd_template_set(wl, wlvif->role_id,
- CMD_TEMPL_PROBE_RESPONSE,
- beacon->data,
- beacon->len, 0,
- min_rate);
-end_bcn:
- dev_kfree_skb(beacon);
+ ret = wlcore_set_beacon_template(wl, vif, is_ap);
if (ret < 0)
goto out;
}
@@ -3511,6 +3530,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);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add a new module parameter to disable TCP checksum offload.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 2f0cbf8..b76b6ac 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -47,6 +47,7 @@ static char *board_type_param;
static bool dc2dc_param = false;
static int n_antennas_2_param = 1;
static int n_antennas_5_param = 1;
+static bool checksum_param = true;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -865,9 +866,11 @@ static int wl18xx_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl18xx_acx_set_checksum_state(wl);
- if (ret != 0)
- return ret;
+ if (checksum_param) {
+ ret = wl18xx_acx_set_checksum_state(wl);
+ if (ret != 0)
+ return ret;
+ }
return ret;
}
@@ -879,6 +882,11 @@ static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
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;
@@ -1065,6 +1073,11 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
return -EINVAL;
}
+ if (!checksum_param) {
+ wl18xx_ops.set_rx_csum = NULL;
+ wl18xx_ops.init_vif = NULL;
+ }
+
wl18xx_conf_init(wl);
return wlcore_probe(wl, pdev);
@@ -1114,6 +1127,9 @@ MODULE_PARM_DESC(n_antennas_2, "Number of installed 2.4GHz antennas: 1 (default)
module_param_named(n_antennas_5, n_antennas_5_param, uint, S_IRUSR);
MODULE_PARM_DESC(n_antennas_5, "Number of installed 5GHz antennas: 1 (default) or 2");
+module_param_named(checksum, checksum_param, bool, S_IRUSR);
+MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to true)");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
Initialize the number of Tx-descriptors for the 18xx family.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index b298e01..68f5e09 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -325,6 +325,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->ops = &wl18xx_ops;
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
+ wl->num_tx_desc = 32;
return wlcore_probe(wl, pdev);
}
--
1.7.9.5
Implement the HW op for getting alignment state in wl18xx. The FW aligns
the Rx Ethernet payload data.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 13 +++++++++++++
drivers/net/wireless/ti/wlcore/rx.h | 3 +++
2 files changed, 16 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index a074d81..fef8726 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -27,6 +27,8 @@
#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"
@@ -447,6 +449,16 @@ wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -455,6 +467,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index e9a162a..277936e 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -102,6 +102,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,
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Different board types (ie. FPGA, HDK and DVP/EVB) require slightly
different init configuration options. Since we cannot probe the type
of board from the actual hardware, we need to pass it as an option
during module load.
This patch adds a module parameters that accepts the 3 different board
types, with DVP/EVB as the default, and uses this value where needed.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 26 ++++++++++++++++++++++++--
drivers/net/wireless/ti/wl18xx/wl18xx.h | 2 ++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 17792e2..e5ebf4a 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -42,6 +42,7 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
static char *ht_mode_param;
+static char *board_type_param;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -680,8 +681,7 @@ static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
params.secondary_clock_setting_time =
phy->secondary_clock_setting_time;
- /* TODO: hardcoded for now */
- params.board_type = BOARD_TYPE_DVP_EVB_18XX;
+ params.board_type = priv->board_type;
wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)¶ms,
@@ -964,6 +964,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
}
wl = hw->priv;
+ priv = wl->priv;
wl->ops = &wl18xx_ops;
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
@@ -979,6 +980,24 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
sizeof(wl18xx_mimo_ht_cap));
+ if (!board_type_param) {
+ board_type_param = kstrdup("dvp_evb", GFP_KERNEL);
+ priv->board_type = BOARD_TYPE_DVP_EVB_18XX;
+ } else {
+ if (!strcmp(board_type_param, "fpga"))
+ priv->board_type = BOARD_TYPE_FPGA_18XX;
+ else if (!strcmp(board_type_param, "hdk"))
+ priv->board_type = BOARD_TYPE_HDK_18XX;
+ else if (!strcmp(board_type_param, "dvp_evb"))
+ priv->board_type = BOARD_TYPE_DVP_EVB_18XX;
+ else {
+ wl1271_error("invalid board type '%s'",
+ board_type_param);
+ wlcore_free_hw(wl);
+ return -EINVAL;
+ }
+ }
+
wl18xx_conf_init(wl);
return wlcore_probe(wl, pdev);
@@ -1015,6 +1034,9 @@ module_exit(wl18xx_exit);
module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or mimo");
+module_param_named(board_type, board_type_param, charp, S_IRUSR);
+MODULE_PARM_DESC(board_type, "Board type: fpga, hdk or dvp_evb (default)");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index c9bf5c6..5bcc7f0 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -34,6 +34,8 @@ struct wl18xx_priv {
/* Index of last released Tx desc in FW */
u8 last_fw_rls_idx;
+
+ u8 board_type;
};
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
--
1.7.9.5
Implement the calc_tx_blocks op for the 18xx family.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 70683ad..055b194 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -34,6 +34,7 @@
#define WL18XX_TX_HW_BLOCK_SPARE 1
#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
+#define WL18XX_TX_HW_BLOCK_SIZE 268
static struct wl18xx_conf wl18xx_default_conf = {
.phy = {
@@ -305,11 +306,18 @@ 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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
.trigger_cmd = wl18xx_trigger_cmd,
.ack_event = wl18xx_ack_event,
+ .calc_tx_blocks = wl18xx_calc_tx_blocks,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Some of the structures were updated, other structures had a few
missing values and a few new ones were added. Change the driver
structs accordingly.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/acx.h | 156 ++++++++-----------
drivers/net/wireless/ti/wl18xx/debugfs.c | 248 +++++++++++++-----------------
2 files changed, 169 insertions(+), 235 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index c2ccf70..cb6fd85 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -71,13 +71,8 @@ struct wl18xx_acx_debug_stats {
} __packed;
struct wl18xx_acx_ring_stats {
- u32 tx_procs;
u32 prepared_descs;
- u32 tx_xfr;
- u32 tx_dma;
u32 tx_cmplt;
- u32 rx_procs;
- u32 rx_data;
} __packed;
struct wl18xx_acx_tx_stats {
@@ -98,60 +93,53 @@ struct wl18xx_acx_tx_stats {
u32 tx_retry_data;
u32 tx_exch_pending;
u32 tx_exch_expiry;
- u32 tx_exch_mismatch;
u32 tx_done_template;
u32 tx_done_data;
u32 tx_done_int_template;
- u32 tx_pre_xfr;
- u32 tx_xfr;
- u32 tx_xfr_out_of_mem;
- u32 tx_dma_programmed;
- u32 tx_dma_done;
+ 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_out_of_mem;
u32 rx_hdr_overflow;
- u32 rx_hw_stuck;
u32 rx_dropped_frame;
- u32 rx_complete_dropped_frame;
- u32 rx_alloc_frame;
- u32 rx_done_queue;
+ u32 rx_done_stage;
u32 rx_done;
u32 rx_defrag;
u32 rx_defrag_end;
- u32 rx_mic;
- u32 rx_mic_end;
- u32 rx_xfr;
- u32 rx_xfr_end;
u32 rx_cmplt;
u32 rx_pre_complt;
u32 rx_cmplt_task;
u32 rx_phy_hdr;
u32 rx_timeout;
-} __packed;
-
-struct wl18xx_acx_dma_stats {
- u32 rx_dma_errors;
- u32 tx_dma_errors;
+ 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;
} __packed;
struct wl18xx_acx_isr_stats {
u32 irqs;
} __packed;
-struct wl18xx_acx_wep_stats {
- u32 wep_add_key_count;
- u32 wep_default_key_count;
- u32 wep_key_not_found;
- u32 wep_decrypt_fail;
- u32 wep_encrypt_fail;
- u32 wep_dec_packets;
- u32 wep_dec_interrupt;
- u32 wep_enc_packets;
- u32 wep_enc_interrupts;
-} __packed;
-
#define PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD 10
struct wl18xx_acx_pwr_stats {
@@ -162,29 +150,6 @@ struct wl18xx_acx_pwr_stats {
u32 rcvd_awake_bcns_cnt;
} __packed;
-struct wl18xx_acx_mic_stats {
- u32 mic_rx_pkts;
- u32 mic_calc_failure;
-} __packed;
-
-struct wl18xx_acx_aes_stats {
- u32 aes_encrypt_fail;
- u32 aes_decrypt_fail;
- u32 aes_encrypt_packets;
- u32 aes_decrypt_packets;
- u32 aes_encrypt_interrupt;
- u32 aes_decrypt_interrupt;
-} __packed;
-
-struct wl18xx_acx_gem_stats {
- u32 gem_encrypt_fail;
- u32 gem_decrypt_fail;
- u32 gem_encrypt_packets;
- u32 gem_decrypt_packets;
- u32 gem_encrypt_interrupt;
- u32 gem_decrypt_interrupt;
-} __packed;
-
struct wl18xx_acx_event_stats {
u32 calibration;
u32 rx_mismatch;
@@ -210,31 +175,44 @@ struct wl18xx_acx_rx_filter_stats {
u32 protection_filter;
} __packed;
-struct wl18xx_acx_calibration_stats {
- u32 init_cal_total;
- u32 init_radio_bands_fail;
- u32 init_set_params;
- u32 init_tx_clpc_fail;
- u32 init_rx_iw_mm_fail;
- u32 tune_cal_total;
- u32 tune_drpw_rtrim_fail;
- u32 tune_drpw_pd_buf_fail;
- u32 tune_drpw_tx_mix_freq_fail;
- u32 tune_drpw_ta_cal;
- u32 tune_drpw_rx_if_2_gain;
- u32 tune_drpw_rx_dac;
- u32 tune_drpw_chan_tune;
- u32 tune_drpw_rx_tx_lpf;
- u32 tune_drpw_lna_tank;
- u32 tune_tx_lo_leak_fail;
- u32 tune_tx_iq_mm_fail;
- u32 tune_tx_pdet_fail;
- u32 tune_tx_ppa_fail;
- u32 tune_tx_clpc_fail;
- u32 tune_rx_ana_dc_fail;
- u32 tune_rx_dig_dc_fail; /* check if this is needed */
- u32 tune_rx_iq_mm_fail;
- u32 cal_state_fail;
+struct wl18xx_acx_rx_rate_stats {
+ u32 rx_frames_per_rates[50];
+} __packed;
+
+#define AGGR_STATS_TX_SIZE_LEN 11
+#define AGGR_STATS_RX_SIZE_LEN 11
+
+struct wl18xx_acx_aggr_stats {
+ u32 tx_size[AGGR_STATS_TX_SIZE_LEN];
+ u32 rx_size[AGGR_STATS_RX_SIZE_LEN];
+} __packed;
+
+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;
+} __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 {
@@ -244,17 +222,15 @@ struct wl18xx_acx_statistics {
struct wl18xx_acx_debug_stats debug;
struct wl18xx_acx_tx_stats tx;
struct wl18xx_acx_rx_stats rx;
- struct wl18xx_acx_dma_stats dma;
struct wl18xx_acx_isr_stats isr;
- struct wl18xx_acx_wep_stats wep;
struct wl18xx_acx_pwr_stats pwr;
- struct wl18xx_acx_aes_stats aes;
- struct wl18xx_acx_mic_stats mic;
struct wl18xx_acx_event_stats event;
struct wl18xx_acx_ps_poll_stats ps_poll;
struct wl18xx_acx_rx_filter_stats rx_filter;
- struct wl18xx_acx_calibration_stats calibration;
- struct wl18xx_acx_gem_stats gem;
+ 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;
int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c
index f4127bf..93c625b 100644
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -32,6 +32,7 @@
#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");
@@ -39,13 +40,8 @@ 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(ring, tx_procs, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(ring, prepared_descs, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_xfr, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_dma, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_cmplt, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(ring, rx_procs, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(ring, rx_data, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_prepared, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_prepared, "%u");
@@ -64,51 +60,47 @@ 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_exch_mismatch, "%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_pre_xfr, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_xfr, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_xfr_out_of_mem, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_dma_programmed, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_dma_done, "%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_out_of_mem, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hdr_overflow, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hw_stuck, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_dropped_frame, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_complete_dropped_frame, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_alloc_frame, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_done_queue, "%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_mic, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_mic_end, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_xfr, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_xfr_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(dma, rx_dma_errors, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(dma, tx_dma_errors, "%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(isr, irqs, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_add_key_count, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_default_key_count, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_key_not_found, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_decrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_encrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_dec_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_dec_interrupt, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_enc_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_enc_interrupts, "%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");
@@ -116,22 +108,6 @@ 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(mic, mic_rx_pkts, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(mic, mic_calc_failure, "%u");
-
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_interrupt, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_interrupt, "%u");
-
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_packets, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_interrupt, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_interrupt, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(event, calibration, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u");
@@ -152,30 +128,35 @@ 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(calibration, init_cal_total, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_radio_bands_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_set_params, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_tx_clpc_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_rx_iw_mm_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_cal_total, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rtrim_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_pd_buf_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_tx_mix_freq_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_ta_cal, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_if_2_gain, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_dac, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_chan_tune, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_tx_lpf, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_lna_tank, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_lo_leak_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_iq_mm_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_pdet_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_ppa_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_clpc_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_ana_dc_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_dig_dc_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_iq_mm_fail, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(calibration, cal_state_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_size,
+ AGGR_STATS_TX_SIZE_LEN);
+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(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");
int wl18xx_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
@@ -202,13 +183,8 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_FWSTATS_ADD(debug, debug5);
DEBUGFS_FWSTATS_ADD(debug, debug6);
- DEBUGFS_FWSTATS_ADD(ring, tx_procs);
DEBUGFS_FWSTATS_ADD(ring, prepared_descs);
- DEBUGFS_FWSTATS_ADD(ring, tx_xfr);
- DEBUGFS_FWSTATS_ADD(ring, tx_dma);
DEBUGFS_FWSTATS_ADD(ring, tx_cmplt);
- DEBUGFS_FWSTATS_ADD(ring, rx_procs);
- DEBUGFS_FWSTATS_ADD(ring, rx_data);
DEBUGFS_FWSTATS_ADD(tx, tx_template_prepared);
DEBUGFS_FWSTATS_ADD(tx, tx_data_prepared);
@@ -227,74 +203,53 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,
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_exch_mismatch);
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_pre_xfr);
- DEBUGFS_FWSTATS_ADD(tx, tx_xfr);
- DEBUGFS_FWSTATS_ADD(tx, tx_xfr_out_of_mem);
- DEBUGFS_FWSTATS_ADD(tx, tx_dma_programmed);
- DEBUGFS_FWSTATS_ADD(tx, tx_dma_done);
+ 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_out_of_mem);
DEBUGFS_FWSTATS_ADD(rx, rx_hdr_overflow);
- DEBUGFS_FWSTATS_ADD(rx, rx_hw_stuck);
DEBUGFS_FWSTATS_ADD(rx, rx_dropped_frame);
- DEBUGFS_FWSTATS_ADD(rx, rx_complete_dropped_frame);
- DEBUGFS_FWSTATS_ADD(rx, rx_alloc_frame);
- DEBUGFS_FWSTATS_ADD(rx, rx_done_queue);
DEBUGFS_FWSTATS_ADD(rx, rx_done);
DEBUGFS_FWSTATS_ADD(rx, rx_defrag);
DEBUGFS_FWSTATS_ADD(rx, rx_defrag_end);
- DEBUGFS_FWSTATS_ADD(rx, rx_mic);
- DEBUGFS_FWSTATS_ADD(rx, rx_mic_end);
- DEBUGFS_FWSTATS_ADD(rx, rx_xfr);
- DEBUGFS_FWSTATS_ADD(rx, rx_xfr_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(dma, rx_dma_errors);
- DEBUGFS_FWSTATS_ADD(dma, tx_dma_errors);
+ 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(isr, irqs);
- DEBUGFS_FWSTATS_ADD(wep, wep_add_key_count);
- DEBUGFS_FWSTATS_ADD(wep, wep_default_key_count);
- DEBUGFS_FWSTATS_ADD(wep, wep_key_not_found);
- DEBUGFS_FWSTATS_ADD(wep, wep_decrypt_fail);
- DEBUGFS_FWSTATS_ADD(wep, wep_encrypt_fail);
- DEBUGFS_FWSTATS_ADD(wep, wep_dec_packets);
- DEBUGFS_FWSTATS_ADD(wep, wep_dec_interrupt);
- DEBUGFS_FWSTATS_ADD(wep, wep_enc_packets);
- DEBUGFS_FWSTATS_ADD(wep, wep_enc_interrupts);
-
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(mic, mic_rx_pkts);
- DEBUGFS_FWSTATS_ADD(mic, mic_calc_failure);
-
- DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_fail);
- DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_fail);
- DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_packets);
- DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_packets);
- DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_interrupt);
- DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_interrupt);
-
- DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_fail);
- DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_fail);
- DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_packets);
- DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_packets);
- DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_interrupt);
- DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_interrupt);
-
DEBUGFS_FWSTATS_ADD(event, calibration);
DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
@@ -314,30 +269,33 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_FWSTATS_ADD(rx_filter, ibss_filter);
DEBUGFS_FWSTATS_ADD(rx_filter, protection_filter);
- DEBUGFS_FWSTATS_ADD(calibration, init_cal_total);
- DEBUGFS_FWSTATS_ADD(calibration, init_radio_bands_fail);
- DEBUGFS_FWSTATS_ADD(calibration, init_set_params);
- DEBUGFS_FWSTATS_ADD(calibration, init_tx_clpc_fail);
- DEBUGFS_FWSTATS_ADD(calibration, init_rx_iw_mm_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_cal_total);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rtrim_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_pd_buf_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_tx_mix_freq_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_ta_cal);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_if_2_gain);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_dac);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_chan_tune);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_tx_lpf);
- DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_lna_tank);
- DEBUGFS_FWSTATS_ADD(calibration, tune_tx_lo_leak_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_tx_iq_mm_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_tx_pdet_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_tx_ppa_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_tx_clpc_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_rx_ana_dc_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_rx_dig_dc_fail);
- DEBUGFS_FWSTATS_ADD(calibration, tune_rx_iq_mm_fail);
- DEBUGFS_FWSTATS_ADD(calibration, cal_state_fail);
+ DEBUGFS_FWSTATS_ADD(rx_rate, rx_frames_per_rates);
+
+ DEBUGFS_FWSTATS_ADD(aggr_size, tx_size);
+ 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(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);
return 0;
--
1.7.9.5
Read the HW PG version of the 18xx chip from FUSE.
Based on an earlier patch by Luciano Coelho <[email protected]>.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 17 +++++++++++++++--
drivers/net/wireless/ti/wl18xx/reg.h | 3 +++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ce13249..9aae0af 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -659,8 +659,6 @@ static void wl18xx_boot_soft_reset(struct wl1271 *wl)
static int wl18xx_pre_boot(struct wl1271 *wl)
{
- /* TODO: add hw_pg_ver reading */
-
wl18xx_set_clk(wl);
/* Continue the ELP wake up sequence */
@@ -946,6 +944,20 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
}
}
+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;
+}
+
static void wl18xx_conf_init(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
@@ -971,6 +983,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 1ea3393..43c480f 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -128,6 +128,9 @@
#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_CMD_MBOX_ADDRESS 0xB007B4
--
1.7.9.5
From: Luciano Coelho <[email protected]>
PLT mode needs to be initialized differently for each chip. This
patch adds an operation to init PLT and moves the existing PLT
initialization into the wl12xx driver.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 57 +++++++++++++++++++++++++++++
drivers/net/wireless/ti/wlcore/acx.c | 4 +++
drivers/net/wireless/ti/wlcore/cmd.c | 1 +
drivers/net/wireless/ti/wlcore/main.c | 59 +------------------------------
drivers/net/wireless/ti/wlcore/wlcore.h | 1 +
5 files changed, 64 insertions(+), 58 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 0266855..1d097c1 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1302,10 +1302,67 @@ static void wl12xx_set_tx_desc_csum(struct wl1271 *wl,
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 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,
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index 0fd78a0..611666e 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -86,6 +86,7 @@ out:
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)
@@ -997,6 +998,7 @@ out:
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 @@ out:
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)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 0dec465..5c47560 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -816,6 +816,7 @@ out:
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)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 414ffa8..3aadf74 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -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)
@@ -1042,14 +1002,10 @@ int wl1271_plt_start(struct wl1271 *wl)
if (ret < 0)
goto power_off;
- ret = wl->ops->boot(wl);
+ ret = wl->ops->plt_init(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)",
@@ -1062,19 +1018,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);
}
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index f62152e..1fc3c77 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -39,6 +39,7 @@ 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);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add the get_mac operation in order to fetch the BD_ADDR from fuse ROM,
so that we can derive the WLAN MAC addresses from it.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 18 ++++++++++++++++++
drivers/net/wireless/ti/wl18xx/reg.h | 3 +++
2 files changed, 21 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index df407be..52d63ff 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -975,6 +975,23 @@ static int wl18xx_plt_init(struct wl1271 *wl)
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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -994,6 +1011,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
/* HT cap appropriate for wide channels */
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index aaedf91..43863d3 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -132,6 +132,9 @@
#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
--
1.7.9.5
Enable wide-chan or MIMO rates when appropriate.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 18 ++++++++++++++++++
drivers/net/wireless/ti/wl18xx/tx.h | 6 ++++++
drivers/net/wireless/ti/wlcore/conf.h | 6 ++++++
3 files changed, 30 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index fd7a803..77840dd 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -862,6 +862,23 @@ static void wl18xx_set_rx_csum(struct wl1271 *wl,
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
+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 void wl18xx_conf_init(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
@@ -888,6 +905,7 @@ static struct wlcore_ops wl18xx_ops = {
.hw_init = wl18xx_hw_init,
.set_tx_desc_csum = wl18xx_set_tx_desc_csum,
.set_rx_csum = wl18xx_set_rx_csum,
+ .sta_get_ap_rate_mask = wl18xx_sta_get_ap_rate_mask,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wl18xx/tx.h b/drivers/net/wireless/ti/wl18xx/tx.h
index a91eb10..2417262 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.h
+++ b/drivers/net/wireless/ti/wl18xx/tx.h
@@ -31,6 +31,12 @@
#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
#define WL18XX_TX_STATUS_STAT_BIT_IDX 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__ */
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index 0798c1e..14dd361 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -443,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
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add the register table with the appropriate values for wl18xx.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 23 +++++++
drivers/net/wireless/ti/wl18xx/reg.h | 112 +++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+)
create mode 100644 drivers/net/wireless/ti/wl18xx/reg.h
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index f3a164a..88fd934 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -25,6 +25,8 @@
#include "../wlcore/wlcore.h"
#include "../wlcore/debug.h"
+#include "reg.h"
+
static struct wlcore_ops wl18xx_ops = {
};
@@ -62,6 +64,26 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
},
};
+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] = 0, /* TODO: where is the PC? */
+ [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,
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -76,6 +98,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl = hw->priv;
wl->ops = &wl18xx_ops;
wl->ptable = wl18xx_ptable;
+ wl->rtable = wl18xx_rtable;
return wlcore_probe(wl, pdev);
}
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
new file mode 100644
index 0000000..9af0c83
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -0,0 +1,112 @@
+/*
+ * 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_CMD_MBOX_ADDRESS 0xB007B4
+
+#define WL18XX_FW_STATUS_ADDR 0x50F8
+
+#define CHIP_ID_185x_PG10 (0x06030101)
+
+#endif /* __REG_H__ */
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add wl18xx-specific HW initialization operation and create acx.[ch]
files to support that.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/Makefile | 2 +-
drivers/net/wireless/ti/wl18xx/acx.c | 57 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/acx.h | 52 ++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/main.c | 32 +++++++++++++++++
drivers/net/wireless/ti/wlcore/acx.h | 2 ++
5 files changed, 144 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ti/wl18xx/acx.c
create mode 100644 drivers/net/wireless/ti/wl18xx/acx.h
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
index dd3b4c1..764d598 100644
--- a/drivers/net/wireless/ti/wl18xx/Makefile
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -1,3 +1,3 @@
-wl18xx-objs = main.o tx.o
+wl18xx-objs = main.o acx.o tx.o
obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
new file mode 100644
index 0000000..aed8d0d
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+ 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;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
new file mode 100644
index 0000000..c8eebd8
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -0,0 +1,52 @@
+/*
+ * 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"
+
+/* numbers of bits the length field takes (add 1 for the actual number) */
+#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
+
+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;
+
+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);
+
+#endif /* __WL12XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ae71131..1e0719c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -33,6 +33,7 @@
#include "reg.h"
#include "conf.h"
+#include "acx.h"
#include "tx.h"
#include "wl18xx.h"
@@ -473,6 +474,36 @@ static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
wl18xx_tx_immediate_complete(wl);
}
+static int wl18xx_hw_init(struct wl1271 *wl)
+{
+ int ret;
+ u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
+ HOST_IF_CFG_ADD_RX_ALIGNMENT;
+
+ u32 sdio_align_size = 0;
+
+ /* 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,
+ WL18XX_TX_HW_BLOCK_SPARE,
+ WL18XX_HOST_IF_LEN_SIZE_FIELD);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -485,6 +516,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 8106b2e..7a8dfba 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -828,6 +828,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,
--
1.7.9.5
From: Luciano Coelho <[email protected]>
The FW statistics differ from hardware to hardware. This commit
prepares for hardware-specific implementation of the FW statistics
debugfs entries.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/acx.c | 4 +-
drivers/net/wireless/ti/wlcore/acx.h | 224 +----------------------
drivers/net/wireless/ti/wlcore/debugfs.c | 279 +++--------------------------
drivers/net/wireless/ti/wlcore/debugfs.h | 60 +++++++
drivers/net/wireless/ti/wlcore/hw_ops.h | 9 +
drivers/net/wireless/ti/wlcore/wlcore.h | 10 ++
drivers/net/wireless/ti/wlcore/wlcore_i.h | 8 -
7 files changed, 104 insertions(+), 490 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index 611666e..6480a02 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -709,14 +709,14 @@ out:
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;
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index e513b1b..28fb35c 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -417,228 +417,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;
@@ -1284,7 +1062,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);
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index d377519..57c1eae 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -25,6 +25,7 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "wlcore.h"
#include "debug.h"
@@ -32,14 +33,15 @@
#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,
- loff_t *ppos, char *fmt, ...)
+int wl1271_format_buffer(char __user *userbuf, size_t count,
+ loff_t *ppos, char *fmt, ...)
{
va_list args;
char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
@@ -51,59 +53,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 +77,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",
@@ -1002,107 +864,10 @@ static const struct file_operations beacon_filtering_ops = {
};
static int wl1271_debugfs_add_files(struct wl1271 *wl,
- struct dentry *rootdir)
+ 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);
@@ -1144,7 +909,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;
}
@@ -1159,34 +924,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;
}
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h
index a8d3aef..e1a5bf1 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.h
+++ b/drivers/net/wireless/ti/wlcore/debugfs.h
@@ -26,8 +26,68 @@
#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_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_ADD(sub, name) \
+ DEBUGFS_ADD(sub## _ ##name, stats)
+
#endif /* WL1271_DEBUGFS_H */
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 6d3e378..1555c3e 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -149,4 +149,13 @@ wlcore_hw_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
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;
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 9ca3829..85fd3d9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -71,6 +71,7 @@ struct wlcore_ops {
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);
};
enum wlcore_partitions {
@@ -119,6 +120,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;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 0422753..45c07dc 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -132,14 +132,6 @@ 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 AP_MAX_STATIONS 8
--
1.7.9.5
Parse the peer ht_cap element containing MCS8-MCS15 rates and pass it
to the FW. Rates unsupported by the HW will be sanitized by mac80211
before reaching us.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/cmd.c | 4 +++-
drivers/net/wireless/ti/wlcore/main.c | 3 ++-
drivers/net/wireless/ti/wlcore/tx.c | 4 ++--
drivers/net/wireless/ti/wlcore/wl12xx.h | 1 +
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 8450f0e..0dec465 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1371,7 +1371,9 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
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,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 3cd2ddd..f64aeb9 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3695,7 +3695,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;
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 44e4e7b..200d091 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -428,10 +428,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;
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h
index 05e6f74..571a4ef 100644
--- a/drivers/net/wireless/ti/wlcore/wl12xx.h
+++ b/drivers/net/wireless/ti/wlcore/wl12xx.h
@@ -502,6 +502,7 @@ 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
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add the operations that allow wlcore to trigger commands to the
firmware and acknowledge when an event has been fully received.
Allocate a private buffer to hold the maximum sized cmd. Send the
entire length of the buffer each time a command is sent to signal
EOT. Remove the previous EOT mechanism.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 20 +++++++++++++++++++
drivers/net/wireless/ti/wl18xx/reg.h | 16 +++++++++++++++
drivers/net/wireless/ti/wl18xx/wl18xx.h | 33 +++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+)
create mode 100644 drivers/net/wireless/ti/wl18xx/wl18xx.h
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 12632d0..6a487c8 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -30,6 +30,7 @@
#include "reg.h"
#include "conf.h"
+#include "wl18xx.h"
static struct wl18xx_conf wl18xx_default_conf = {
.phy = {
@@ -284,9 +285,28 @@ 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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
+ .trigger_cmd = wl18xx_trigger_cmd,
+ .ack_event = wl18xx_ack_event,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 2916d69..5398799 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -113,6 +113,22 @@
#define CHIP_ID_185x_PG10 (0x06030101)
+/*
+ * 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)
+
/* TODO: maybe move elsewhere? */
#define NUM_OF_CHANNELS_11_ABG 150
#define NUM_OF_CHANNELS_11_P 7
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
new file mode 100644
index 0000000..58709bb
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -0,0 +1,33 @@
+/*
+ * 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__
+
+
+#define WL18XX_CMD_MAX_SIZE 740
+
+struct wl18xx_priv {
+ /* buffer for sending commands to FW */
+ u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
+};
+
+#endif /* __WL18XX_PRIV_H__ */
--
1.7.9.5
Define the FW pc in the 18xx register translation table. This specific
register is only valid in the boot partition, so change the momentarily
change partitions. This doesn't damage 12xx cards, where the FW pc is
accessible via boot partition as well.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 2 +-
drivers/net/wireless/ti/wlcore/main.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 5214334..82403e3 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -549,7 +549,7 @@ static const int wl18xx_rtable[REG_TABLE_LEN] = {
[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] = 0, /* TODO: where is the PC? */
+ [REG_PC_ON_RECOVERY] = WL18XX_SCR_PAD4,
[REG_CHIP_ID_B] = WL18XX_REG_CHIP_ID_B,
[REG_CMD_MBOX_ADDRESS] = WL18XX_CMD_MBOX_ADDRESS,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index c98958f..cbe94ed 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -872,9 +872,12 @@ static void wl1271_recovery_work(struct work_struct *work)
wl12xx_read_fwlog_panic(wl);
+ /* 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",
wl->chip.fw_ver_str,
wlcore_read_reg(wl, REG_PC_ON_RECOVERY));
+ wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
BUG_ON(bug_on_recovery &&
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add the wl18xx module and the probe functions. Use wlcore for the
main parts (not functional at this point due to differences in the
wl18xx initialization).
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/Kconfig | 1 +
drivers/net/wireless/ti/Makefile | 1 +
drivers/net/wireless/ti/wl18xx/Kconfig | 6 +++
drivers/net/wireless/ti/wl18xx/Makefile | 3 ++
drivers/net/wireless/ti/wl18xx/main.c | 73 +++++++++++++++++++++++++++++++
5 files changed, 84 insertions(+)
create mode 100644 drivers/net/wireless/ti/wl18xx/Kconfig
create mode 100644 drivers/net/wireless/ti/wl18xx/Makefile
create mode 100644 drivers/net/wireless/ti/wl18xx/main.c
diff --git a/drivers/net/wireless/ti/Kconfig b/drivers/net/wireless/ti/Kconfig
index 1a72932..be80011 100644
--- a/drivers/net/wireless/ti/Kconfig
+++ b/drivers/net/wireless/ti/Kconfig
@@ -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"
diff --git a/drivers/net/wireless/ti/Makefile b/drivers/net/wireless/ti/Makefile
index 0a56562..4d68239 100644
--- a/drivers/net/wireless/ti/Makefile
+++ b/drivers/net/wireless/ti/Makefile
@@ -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/
diff --git a/drivers/net/wireless/ti/wl18xx/Kconfig b/drivers/net/wireless/ti/wl18xx/Kconfig
new file mode 100644
index 0000000..1451d1f
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/Kconfig
@@ -0,0 +1,6 @@
+config WL18XX
+ tristate "TI wl18xx support"
+ select WLCORE
+ ---help---
+ This module adds support for wireless adapters based on TI
+ WiLink 8 chipsets.
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
new file mode 100644
index 0000000..d187037
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -0,0 +1,3 @@
+wl18xx-objs = main.o
+
+obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
new file mode 100644
index 0000000..cb835d9
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -0,0 +1,73 @@
+/*
+ * 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 "../wlcore/wlcore.h"
+#include "../wlcore/debug.h"
+
+int __devinit wl18xx_probe(struct platform_device *pdev)
+{
+ struct wl1271 *wl;
+ struct ieee80211_hw *hw;
+
+ hw = wlcore_alloc_hw(0);
+ if (IS_ERR(hw)) {
+ wl1271_error("can't allocate hw");
+ return PTR_ERR(hw);
+ }
+
+ wl = hw->priv;
+
+ return wlcore_probe(wl, pdev);
+}
+
+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_LICENSE("GPL v2");
+MODULE_AUTHOR("Luciano Coelho <[email protected]>");
--
1.7.9.5
Arik Nemtsov <[email protected]> writes:
> This series adds initial support for the 18xx chip family. The new
> module uses wlcore for functionality common with the 12xx family.
You do know that sending 78 patches in one patchset is very much
frowned upon? No sane person (outside of wl12xx) is going to review
all of these.
--
Kalle Valo
Add a HW op to add extra enabled rates for AP-mode data-rates. Since
the rates might depend on channel properties, reconfigure AP-mode rates
when these change.
Implement the HW op for the 18xx family, where MIMO or wide-chan rates
can be added.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 1 +
drivers/net/wireless/ti/wl18xx/main.c | 14 ++++++++++++++
drivers/net/wireless/ti/wlcore/hw_ops.h | 10 ++++++++++
drivers/net/wireless/ti/wlcore/init.c | 3 +++
drivers/net/wireless/ti/wlcore/main.c | 7 ++++++-
drivers/net/wireless/ti/wlcore/wlcore.h | 2 ++
6 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index a333653..ad760a3 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1315,6 +1315,7 @@ static struct wlcore_ops wl12xx_ops = {
.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,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 77840dd..9da94e6 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -879,6 +879,19 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
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) {
+ wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
+ return CONF_TX_RATE_USE_WIDE_CHAN;
+ } else {
+ wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
+ return CONF_TX_MIMO_RATES;
+ }
+}
+
static void wl18xx_conf_init(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
@@ -906,6 +919,7 @@ static struct wlcore_ops wl18xx_ops = {
.set_tx_desc_csum = wl18xx_set_tx_desc_csum,
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 80f3d75..6d3e378 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -139,4 +139,14 @@ wlcore_hw_set_rx_csum(struct wl1271 *wl,
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;
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index 9f89255..645abd4 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -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;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index f64aeb9..c98958f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2478,7 +2478,12 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
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
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 83c43c9..f9ec84d 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -68,6 +68,8 @@ struct wlcore_ops {
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);
};
enum wlcore_partitions {
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Implement the boot operation. Add a wl18xx-specific configuration
structure (namely to configure the mac and phy parameters).
The default hw configuration matches the DVP board.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/conf.h | 57 +++++++++++
drivers/net/wireless/ti/wl18xx/main.c | 180 ++++++++++++++++++++++++++++++++-
drivers/net/wireless/ti/wl18xx/reg.h | 75 ++++++++++++++
3 files changed, 311 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ti/wl18xx/conf.h
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
new file mode 100644
index 0000000..7cd7bf1
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -0,0 +1,57 @@
+/*
+ * 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__
+
+struct wl18xx_conf_phy {
+ 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;
+ u8 low_band_component_type;
+ u8 high_band_component;
+ u8 high_band_component_type;
+ u8 number_of_assembled_ant2_4;
+ u8 number_of_assembled_ant5;
+ u8 external_pa_dc2dc;
+ u8 tcxo_ldo_voltage;
+ u8 xtal_itrim_val;
+ u8 srf_state;
+ u8 io_configuration;
+ u8 sdio_configuration;
+ u8 settings;
+ u8 rx_profile;
+ u8 primary_clock_setting_time;
+ u8 clock_valid_on_wake_up;
+ u8 secondary_clock_setting_time;
+};
+
+struct wl18xx_conf {
+ /* TODO: move the wlcore conf here? */
+
+ struct wl18xx_conf_phy phy;
+};
+
+#endif /* __WL18XX_CONF_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index e517afd..12632d0 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -24,8 +24,40 @@
#include "../wlcore/wlcore.h"
#include "../wlcore/debug.h"
+#include "../wlcore/io.h"
+#include "../wlcore/acx.h"
+#include "../wlcore/boot.h"
#include "reg.h"
+#include "conf.h"
+
+static struct wl18xx_conf wl18xx_default_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,
+ .number_of_assembled_ant2_4 = 0x01,
+ .number_of_assembled_ant5 = 0x01,
+ .external_pa_dc2dc = 0x00,
+ .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,
+ },
+};
static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
[PART_TOP_PRCM_ELP_SOC] = {
@@ -107,8 +139,154 @@ out:
return ret;
}
+static void wl18xx_set_clk(struct wl1271 *wl)
+{
+ /*
+ * TODO: this is hardcoded just for DVP/EVB, fix according to
+ * new unified_drv.
+ */
+ wl1271_write32(wl, WL18XX_SCR_PAD2, 0xB3);
+
+ wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ wl1271_write32(wl, 0x00A02360, 0xD0078);
+ wl1271_write32(wl, 0x00A0236c, 0x12);
+ wl1271_write32(wl, 0x00A02390, 0x20118);
+}
+
+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)
+{
+ /* TODO: add hw_pg_ver reading */
+
+ 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_mac_and_phy_params params;
+
+ memset(¶ms, 0, sizeof(params));
+
+ params.phy_standalone = wl18xx_default_conf.phy.phy_standalone;
+ params.rdl = wl18xx_default_conf.phy.rdl;
+ params.enable_clpc = wl18xx_default_conf.phy.enable_clpc;
+ params.enable_tx_low_pwr_on_siso_rdl =
+ wl18xx_default_conf.phy.enable_tx_low_pwr_on_siso_rdl;
+ params.auto_detect = wl18xx_default_conf.phy.auto_detect;
+ params.dedicated_fem = wl18xx_default_conf.phy.dedicated_fem;
+ params.low_band_component = wl18xx_default_conf.phy.low_band_component;
+ params.low_band_component_type =
+ wl18xx_default_conf.phy.low_band_component_type;
+ params.high_band_component =
+ wl18xx_default_conf.phy.high_band_component;
+ params.high_band_component_type =
+ wl18xx_default_conf.phy.high_band_component_type;
+ params.number_of_assembled_ant2_4 =
+ wl18xx_default_conf.phy.number_of_assembled_ant2_4;
+ params.number_of_assembled_ant5 =
+ wl18xx_default_conf.phy.number_of_assembled_ant5;
+ params.external_pa_dc2dc = wl18xx_default_conf.phy.external_pa_dc2dc;
+ params.tcxo_ldo_voltage = wl18xx_default_conf.phy.tcxo_ldo_voltage;
+ params.xtal_itrim_val = wl18xx_default_conf.phy.xtal_itrim_val;
+ params.srf_state = wl18xx_default_conf.phy.srf_state;
+ params.io_configuration = wl18xx_default_conf.phy.io_configuration;
+ params.sdio_configuration = wl18xx_default_conf.phy.sdio_configuration;
+ params.settings = wl18xx_default_conf.phy.settings;
+ params.rx_profile = wl18xx_default_conf.phy.rx_profile;
+ params.primary_clock_setting_time =
+ wl18xx_default_conf.phy.primary_clock_setting_time;
+ params.clock_valid_on_wake_up =
+ wl18xx_default_conf.phy.clock_valid_on_wake_up;
+ params.secondary_clock_setting_time =
+ wl18xx_default_conf.phy.secondary_clock_setting_time;
+
+ /* TODO: hardcoded for now */
+ params.board_type = BOARD_TYPE_DVP_EVB_18XX;
+
+ wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
+ wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)¶ms,
+ sizeof(params), false);
+}
+
+static void wl18xx_enable_interrupts(struct wl1271 *wl)
+{
+ wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
+
+ wlcore_enable_interrupts(wl);
+ wlcore_write_reg(wl, REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+}
+
+static int wl18xx_boot(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl18xx_pre_boot(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_boot_upload_nvs(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 struct wlcore_ops wl18xx_ops = {
- .identify_chip = wl18xx_identify_chip,
+ .identify_chip = wl18xx_identify_chip,
+ .boot = wl18xx_boot,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 9af0c83..2916d69 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -102,6 +102,10 @@
#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)
#define WL18XX_CMD_MBOX_ADDRESS 0xB007B4
@@ -109,4 +113,75 @@
#define CHIP_ID_185x_PG10 (0x06030101)
+/* TODO: maybe move elsewhere? */
+#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
+
+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_FPGA_18XX = 0,
+ BOARD_TYPE_HDK_18XX = 1,
+ BOARD_TYPE_DVP_EVB_18XX = 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;
+ u8 padding[1];
+} __packed;
+
#endif /* __REG_H__ */
--
1.7.9.5
In this chip family the NVS file should not be uploaded to FW. In fact,
we encounter strange bugs (sdio errors) when trying to upload it with
certain parameters.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index a8b9cea..ddd11d0 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -755,10 +755,6 @@ static int wl18xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- ret = wlcore_boot_upload_nvs(wl);
- if (ret < 0)
- goto out;
-
wl18xx_pre_upload(wl);
ret = wlcore_boot_upload_firmware(wl);
--
1.7.9.5
The wl18xx chip passes extra information in the firmware status to the
driver. Add a private data section to handle that.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 2 +-
drivers/net/wireless/ti/wl18xx/wl18xx.h | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 7dcb832..4a5ef6e 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -478,7 +478,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
return wlcore_probe(wl, pdev);
}
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 58709bb..68ef5ba 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -30,4 +30,22 @@ struct wl18xx_priv {
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
};
+#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];
+};
+
#endif /* __WL18XX_PRIV_H__ */
--
1.7.9.5
Set an alternate HT cap allowing MIMO rates (but only 20mhz) channels,
when the module is loaded with ht_mode=mimo.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index a0bec8f..17792e2 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -41,6 +41,8 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
+static char *ht_mode_param;
+
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
@@ -936,6 +938,19 @@ static struct ieee80211_sta_ht_cap wl18xx_ht_cap = {
},
};
+/* HT cap appropriate for MIMO rates in 20mhz channel */
+static struct ieee80211_sta_ht_cap wl18xx_mimo_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, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .rx_highest = cpu_to_le16(144),
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+ },
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -960,6 +975,10 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
+ if (ht_mode_param && !strcmp(ht_mode_param, "mimo"))
+ memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
+ sizeof(wl18xx_mimo_ht_cap));
+
wl18xx_conf_init(wl);
return wlcore_probe(wl, pdev);
@@ -993,6 +1012,9 @@ static void __exit wl18xx_exit(void)
}
module_exit(wl18xx_exit);
+module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
+MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or mimo");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
Set the frame length during Tx in a way compatible with the 18xx FW.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index c85492e..0a5422c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -321,6 +321,19 @@ wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
desc->wl18xx_mem.reserved = 0;
}
+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);
+
+ 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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -328,6 +341,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
--
1.7.9.5
From: Luciano Coelho <[email protected]>
We were changing the low_band_component_type in the private
configuration structure before copying the default values to it, so
the change was overwritten and only took effect after HW recovery.
Reported-by: Dror Erez <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index d4e331f..f5ec6f6 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1072,6 +1072,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
sizeof(wl18xx_mimo_ht_cap));
+ wl18xx_conf_init(wl);
+
if (!board_type_param) {
board_type_param = kstrdup("dvp", GFP_KERNEL);
priv->board_type = BOARD_TYPE_DVP_18XX;
@@ -1100,8 +1102,6 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->enable_11a = enable_11a_param;
- wl18xx_conf_init(wl);
-
return wlcore_probe(wl, pdev);
}
--
1.7.9.5
Define the default HT capabilities of the 18xx chip family - these include
support for wide-channel.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 9da94e6..a0bec8f 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -922,6 +922,20 @@ static struct wlcore_ops wl18xx_ops = {
.ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask,
};
+/* HT cap appropriate for wide channels */
+static struct ieee80211_sta_ht_cap wl18xx_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,
+ },
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -945,6 +959,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
+ memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
wl18xx_conf_init(wl);
return wlcore_probe(wl, pdev);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
The wl18xx firmware has more information in the static_data than
wl12xx. To be able to parse that in an abstracted way, this patch
adds a priv area to the static data struct and an operation that
allows the lower driver to parse it if necessary.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/boot.c | 53 +++++++++++++++++--------------
drivers/net/wireless/ti/wlcore/boot.h | 1 +
drivers/net/wireless/ti/wlcore/hw_ops.h | 9 ++++++
drivers/net/wireless/ti/wlcore/wlcore.h | 6 ++++
4 files changed, 46 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
index 9b98230..ed718f7 100644
--- a/drivers/net/wireless/ti/wlcore/boot.c
+++ b/drivers/net/wireless/ti/wlcore/boot.c
@@ -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)
- return ret;
-
- return 0;
+ goto out;
+out:
+ return ret;
}
-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,
@@ -400,9 +407,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;
}
diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h
index 094981d..a525225 100644
--- a/drivers/net/wireless/ti/wlcore/boot.h
+++ b/drivers/net/wireless/ti/wlcore/boot.h
@@ -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 */
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 1555c3e..c590b6f 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -158,4 +158,13 @@ wlcore_debugfs_init(struct wl1271 *wl, struct dentry *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;
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 85fd3d9..1967873 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -26,6 +26,7 @@
#include "wlcore_i.h"
#include "event.h"
+#include "boot.h"
/* The maximum number of Tx descriptors in all chip families */
#define WLCORE_MAX_TX_DESCRIPTORS 32
@@ -72,6 +73,8 @@ struct wlcore_ops {
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);
};
enum wlcore_partitions {
@@ -373,6 +376,9 @@ struct wl1271 {
/* 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;
};
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Yet another temporary module parameter requested by the firmware team.
This will be replaced by the conf binary.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 6baeb26b..524f44c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -53,6 +53,7 @@ static int low_band_component = -1;
static int low_band_component_type = -1;
static int high_band_component = -1;
static int high_band_component_type = -1;
+static int pwr_limit_reference_11_abg = -1;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -1190,6 +1191,13 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
priv->conf.phy.high_band_component_type =
high_band_component_type;
+ if (pwr_limit_reference_11_abg == -1)
+ pwr_limit_reference_11_abg =
+ priv->conf.phy.pwr_limit_reference_11_abg;
+ else
+ priv->conf.phy.pwr_limit_reference_11_abg =
+ pwr_limit_reference_11_abg;
+
if (!checksum_param) {
wl18xx_ops.set_rx_csum = NULL;
wl18xx_ops.init_vif = NULL;
@@ -1270,6 +1278,10 @@ module_param(high_band_component_type, uint, S_IRUSR);
MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 "
"(default is 0x09)");
+module_param(pwr_limit_reference_11_abg, uint, 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 <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Now the firmware can support TX block ack sessions with 64 frames.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 27cd9b8..5053c05 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -408,7 +408,7 @@ static struct wlcore_conf wl18xx_conf = {
},
.ht = {
.rx_ba_win_size = 10,
- .tx_ba_win_size = 10,
+ .tx_ba_win_size = 64,
.inactivity_timeout = 10000,
.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
},
--
1.7.9.5
From: Luciano Coelho <[email protected]>
If the wl18xx module is loaded with ht_mode=wide (the default), we
shouldn't use MIMO rates when the channel type is not HT40. Fix this
by checking the ht_mode before deciding which rates to used.
Additionally, set the ht_mode parameter explicitly to "wide" as the
default.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 8262a4f..6a81edf 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -42,7 +42,7 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
-static char *ht_mode_param;
+static char *ht_mode_param = "wide";
static char *board_type_param = "hdk";
static bool dc2dc_param = false;
static int n_antennas_2_param = 1;
@@ -941,11 +941,12 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
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) {
+ 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 {
+ } else if (!strcmp(ht_mode_param, "mimo")) {
wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
/*
@@ -959,6 +960,8 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13;
return CONF_TX_MIMO_RATES;
+ } else {
+ return 0;
}
}
@@ -1106,7 +1109,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
- if (ht_mode_param && !strcmp(ht_mode_param, "mimo"))
+ if (!strcmp(ht_mode_param, "mimo"))
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
sizeof(wl18xx_mimo_ht_cap));
--
1.7.9.5
Implement the 18xx-specific way for getting the length of a Rx packet.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index fef8726..40ed53c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -458,6 +458,17 @@ wl18xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
@@ -468,6 +479,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
--
1.7.9.5
From: Luciano Coelho <[email protected]>
We use hardcoded values for the different board types. In some cases
we may need to override the defaults, so export the values as module
params. If not defined, the defaults for the specified board type
will be used.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 46 +++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ab3dd11..6baeb26b 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -49,6 +49,10 @@ static int n_antennas_2_param = 1;
static int n_antennas_5_param = 1;
static bool checksum_param = true;
static bool enable_11a_param = true;
+static int low_band_component = -1;
+static int low_band_component_type = -1;
+static int high_band_component = -1;
+static int high_band_component_type = -1;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -1160,6 +1164,32 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
goto out_free;
}
+ /*
+ * If the module param is not set, update it with the one from
+ * conf. If it is set, overwrite conf with it.
+ */
+ if (low_band_component == -1)
+ low_band_component = priv->conf.phy.low_band_component;
+ else
+ priv->conf.phy.low_band_component = low_band_component;
+ if (low_band_component_type == -1)
+ low_band_component_type =
+ priv->conf.phy.low_band_component_type;
+ else
+ priv->conf.phy.low_band_component_type =
+ low_band_component_type;
+
+ if (high_band_component == -1)
+ high_band_component = priv->conf.phy.high_band_component;
+ else
+ priv->conf.phy.high_band_component = high_band_component;
+ if (high_band_component_type == -1)
+ high_band_component_type =
+ priv->conf.phy.high_band_component_type;
+ else
+ priv->conf.phy.high_band_component_type =
+ high_band_component_type;
+
if (!checksum_param) {
wl18xx_ops.set_rx_csum = NULL;
wl18xx_ops.init_vif = NULL;
@@ -1224,6 +1254,22 @@ MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to true)");
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(low_band_component, uint, S_IRUSR);
+MODULE_PARM_DESC(low_band_component, "Low band component: u8 "
+ "(default is 0x01)");
+
+module_param(low_band_component_type, uint, 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(high_band_component, uint, S_IRUSR);
+MODULE_PARM_DESC(high_band_component, "High band component: u8, "
+ "(default is 0x01)");
+
+module_param(high_band_component_type, uint, S_IRUSR);
+MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 "
+ "(default is 0x09)");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
The firmware uses the SCR_PAD2 register to read the board type passed
from the driver. The values don't match the ones used in the mac and
phy configuration, so we need to map them before writing. This commit
adds a translation table that is used when writing the board type to
SCR_PAD2.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 16 +++++++++++-----
drivers/net/wireless/ti/wl18xx/reg.h | 9 +++++++++
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index e5ebf4a..5214334 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -44,6 +44,12 @@
static char *ht_mode_param;
static char *board_type_param;
+static const u32 wl18xx_board_type_to_scrpad2[NUM_BOARD_TYPES] = {
+ [BOARD_TYPE_FPGA_18XX] = SCR_PAD2_BOARD_TYPE_FPGA,
+ [BOARD_TYPE_HDK_18XX] = SCR_PAD2_BOARD_TYPE_HDK,
+ [BOARD_TYPE_DVP_EVB_18XX] = SCR_PAD2_BOARD_TYPE_DVP_EVB,
+};
+
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
@@ -584,11 +590,11 @@ out:
static void wl18xx_set_clk(struct wl1271 *wl)
{
- /*
- * TODO: this is hardcoded just for DVP/EVB, fix according to
- * new unified_drv.
- */
- wl1271_write32(wl, WL18XX_SCR_PAD2, 0xB3);
+ struct wl18xx_priv *priv = wl->priv;
+
+ /* write the translated board type to SCR_PAD2 */
+ wl1271_write32(wl, WL18XX_SCR_PAD2,
+ wl18xx_board_type_to_scrpad2[priv->board_type]);
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
wl1271_write32(wl, 0x00A02360, 0xD0078);
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 5398799..e0170ae 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -154,6 +154,15 @@ enum {
BOARD_TYPE_FPGA_18XX = 0,
BOARD_TYPE_HDK_18XX = 1,
BOARD_TYPE_DVP_EVB_18XX = 2,
+
+ NUM_BOARD_TYPES,
+};
+
+/* board type values used by the firmware in the SCR_PAD2 register */
+enum {
+ SCR_PAD2_BOARD_TYPE_FPGA = 0xB1,
+ SCR_PAD2_BOARD_TYPE_HDK = 0xB2,
+ SCR_PAD2_BOARD_TYPE_DVP_EVB = 0xB3,
};
struct wl18xx_mac_and_phy_params {
--
1.7.9.5
Currently (Fw .67) appears to do more harm than good.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 82403e3..0f07886 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -574,6 +574,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
wl->chip.id);
wl->sr_fw_name = WL18XX_FW_NAME;
wl->quirks |= WLCORE_QUIRK_NO_ELP |
+ WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED |
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN;
/* TODO: need to blocksize alignment for RX/TX separately? */
--
1.7.9.5
From: Luciano Coelho <[email protected]>
The wl12xx.h file now contains mostly definitions that are internal to
wlcore. Still, some things need to me moved to the public header, so
for now we keep including it in wlcore.h.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/wl12xx.h | 509 -----------------------------
drivers/net/wireless/ti/wlcore/wlcore.h | 2 +-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 509 +++++++++++++++++++++++++++++
3 files changed, 510 insertions(+), 510 deletions(-)
delete mode 100644 drivers/net/wireless/ti/wlcore/wl12xx.h
create mode 100644 drivers/net/wireless/ti/wlcore/wlcore_i.h
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h
deleted file mode 100644
index 571a4ef..0000000
--- a/drivers/net/wireless/ti/wlcore/wl12xx.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Contact: Luciano Coelho <[email protected]>
- *
- * 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_H__
-#define __WL12XX_H__
-
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <net/mac80211.h>
-
-#include "conf.h"
-#include "ini.h"
-
-#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
-#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
-
-#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
-#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
-
-#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
-#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
-
-/*
- * wl127x and wl128x are using the same NVS file name. However, the
- * ini parameters between them are different. The driver validates
- * the correct NVS size in wl1271_boot_upload_nvs().
- */
-#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
-
-#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
-#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
-#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
-
-#define WL1271_CIPHER_SUITE_GEM 0x00147201
-
-#define WL1271_BUSY_WORD_CNT 1
-#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
-
-#define WL1271_ELP_HW_STATE_ASLEEP 0
-#define WL1271_ELP_HW_STATE_IRQ 1
-
-#define WL1271_DEFAULT_BEACON_INT 100
-#define WL1271_DEFAULT_DTIM_PERIOD 1
-
-#define WL12XX_MAX_ROLES 4
-#define WL12XX_MAX_LINKS 12
-#define WL12XX_INVALID_ROLE_ID 0xff
-#define WL12XX_INVALID_LINK_ID 0xff
-
-#define WL12XX_MAX_RATE_POLICIES 16
-
-/* Defined by FW as 0. Will not be freed or allocated. */
-#define WL12XX_SYSTEM_HLID 0
-
-/*
- * When in AP-mode, we allow (at least) this number of packets
- * to be transmitted to FW for a STA in PS-mode. Only when packets are
- * present in the FW buffers it will wake the sleeping STA. We want to put
- * enough packets for the driver to transmit all of its buffered data before
- * the STA goes to sleep again. But we don't want to take too much memory
- * as it might hurt the throughput of active STAs.
- */
-#define WL1271_PS_STA_MAX_PACKETS 2
-
-#define WL1271_AP_BSS_INDEX 0
-#define WL1271_AP_DEF_BEACON_EXP 20
-
-#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
-
-enum wl1271_state {
- WL1271_STATE_OFF,
- WL1271_STATE_ON,
-};
-
-enum wl12xx_fw_type {
- WL12XX_FW_TYPE_NONE,
- WL12XX_FW_TYPE_NORMAL,
- WL12XX_FW_TYPE_MULTI,
- WL12XX_FW_TYPE_PLT,
-};
-
-struct wl1271;
-
-enum {
- FW_VER_CHIP,
- FW_VER_IF_TYPE,
- FW_VER_MAJOR,
- FW_VER_SUBTYPE,
- FW_VER_MINOR,
-
- NUM_FW_VER
-};
-
-#define FW_VER_CHIP_WL127X 6
-#define FW_VER_CHIP_WL128X 7
-
-#define FW_VER_IF_TYPE_STA 1
-#define FW_VER_IF_TYPE_AP 2
-
-#define FW_VER_MINOR_1_SPARE_STA_MIN 58
-#define FW_VER_MINOR_1_SPARE_AP_MIN 47
-
-#define FW_VER_MINOR_FWLOG_STA_MIN 70
-
-struct wl1271_chip {
- u32 id;
- char fw_ver_str[ETHTOOL_BUSINFO_LEN];
- 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
-
-struct wl_fw_packet_counters {
- /* Cumulative counter of released packets per AC */
- u8 tx_released_pkts[NUM_TX_QUEUES];
-
- /* Cumulative counter of freed packets per HLID */
- u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
-
- /* Cumulative counter of released Voice memory blocks */
- u8 tx_voice_released_blks;
-
- u8 padding[3];
-} __packed;
-
-/* FW status registers */
-struct wl_fw_status {
- __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 fw_localtime;
-
- /*
- * A bitmap (where each bit represents a single HLID)
- * to indicate if the station is in PS mode.
- */
- __le32 link_ps_bitmap;
-
- /*
- * A bitmap (where each bit represents a single HLID) to indicate
- * if the station is in Fast mode
- */
- __le32 link_fast_bitmap;
-
- /* Cumulative counter of total released mem blocks since FW-reset */
- __le32 total_released_blks;
-
- /* Size (in Memory Blocks) of TX pool */
- __le32 tx_total;
-
- struct wl_fw_packet_counters counters;
-
- __le32 log_start_addr;
-
- /* Private status to be used by the lower drivers */
- 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;
- unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)];
- bool failed;
- u8 state;
- u8 ssid[IEEE80211_MAX_SSID_LEN+1];
- size_t ssid_len;
-};
-
-struct wl1271_if_operations {
- void (*read)(struct device *child, int addr, void *buf, size_t len,
- bool fixed);
- void (*write)(struct device *child, int addr, void *buf, size_t len,
- bool fixed);
- void (*reset)(struct device *child);
- void (*init)(struct device *child);
- int (*power)(struct device *child, bool enable);
- void (*set_block_size) (struct device *child, unsigned int blksz);
-};
-
-#define MAX_NUM_KEYS 14
-#define MAX_KEY_SIZE 32
-
-struct wl1271_ap_key {
- u8 id;
- u8 key_type;
- u8 key_size;
- u8 key[MAX_KEY_SIZE];
- u8 hlid;
- u32 tx_seq_32;
- u16 tx_seq_16;
-};
-
-enum wl12xx_flags {
- WL1271_FLAG_GPIO_POWER,
- WL1271_FLAG_TX_QUEUE_STOPPED,
- WL1271_FLAG_TX_PENDING,
- WL1271_FLAG_IN_ELP,
- WL1271_FLAG_ELP_REQUESTED,
- WL1271_FLAG_IRQ_RUNNING,
- WL1271_FLAG_FW_TX_BUSY,
- WL1271_FLAG_DUMMY_PACKET_PENDING,
- WL1271_FLAG_SUSPENDED,
- WL1271_FLAG_PENDING_WORK,
- WL1271_FLAG_SOFT_GEMINI,
- WL1271_FLAG_RECOVERY_IN_PROGRESS,
- WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
- WL1271_FLAG_INTENDED_FW_RECOVERY,
-};
-
-enum wl12xx_vif_flags {
- WLVIF_FLAG_INITIALIZED,
- WLVIF_FLAG_STA_ASSOCIATED,
- WLVIF_FLAG_STA_AUTHORIZED,
- WLVIF_FLAG_IBSS_JOINED,
- WLVIF_FLAG_AP_STARTED,
- WLVIF_FLAG_IN_PS,
- WLVIF_FLAG_STA_STATE_SENT,
- WLVIF_FLAG_RX_STREAMING_STARTED,
- WLVIF_FLAG_PSPOLL_FAILURE,
- WLVIF_FLAG_CS_PROGRESS,
- WLVIF_FLAG_AP_PROBE_RESP_SET,
- WLVIF_FLAG_IN_USE,
-};
-
-struct wl1271_link {
- /* AP-mode - TX queue per AC in link */
- struct sk_buff_head tx_queue[NUM_TX_QUEUES];
-
- /* accounting for allocated / freed packets in FW */
- u8 allocated_pkts;
- u8 prev_freed_pkts;
-
- u8 addr[ETH_ALEN];
-
- /* bitmap of TIDs where RX BA sessions are active for this link */
- u8 ba_bitmap;
-};
-
-#define WL1271_MAX_RX_FILTERS 5
-#define WL1271_RX_FILTER_MAX_FIELDS 8
-
-#define WL1271_RX_FILTER_ETH_HEADER_SIZE 14
-#define WL1271_RX_FILTER_MAX_FIELDS_SIZE 95
-#define RX_FILTER_FIELD_OVERHEAD \
- (sizeof(struct wl12xx_rx_filter_field) - sizeof(u8 *))
-#define WL1271_RX_FILTER_MAX_PATTERN_SIZE \
- (WL1271_RX_FILTER_MAX_FIELDS_SIZE - RX_FILTER_FIELD_OVERHEAD)
-
-#define WL1271_RX_FILTER_FLAG_MASK BIT(0)
-#define WL1271_RX_FILTER_FLAG_IP_HEADER 0
-#define WL1271_RX_FILTER_FLAG_ETHERNET_HEADER BIT(1)
-
-enum rx_filter_action {
- FILTER_DROP = 0,
- FILTER_SIGNAL = 1,
- FILTER_FW_HANDLE = 2
-};
-
-struct wl12xx_rx_filter_field {
- __le16 offset;
- u8 len;
- u8 flags;
- u8 *pattern;
-} __packed;
-
-struct wl12xx_rx_filter {
- u8 action;
- int num_fields;
- struct wl12xx_rx_filter_field fields[WL1271_RX_FILTER_MAX_FIELDS];
-};
-
-struct wl1271_station {
- u8 hlid;
-};
-
-struct wl12xx_vif {
- struct wl1271 *wl;
- struct list_head list;
- unsigned long flags;
- u8 bss_type;
- u8 p2p; /* we are using p2p role */
- u8 role_id;
-
- /* sta/ibss specific */
- u8 dev_role_id;
- u8 dev_hlid;
-
- union {
- struct {
- u8 hlid;
- u8 ba_rx_bitmap;
-
- u8 basic_rate_idx;
- u8 ap_rate_idx;
- u8 p2p_rate_idx;
-
- bool qos;
- } sta;
- struct {
- u8 global_hlid;
- u8 bcast_hlid;
-
- /* HLIDs bitmap of associated stations */
- unsigned long sta_hlid_map[BITS_TO_LONGS(
- WL12XX_MAX_LINKS)];
-
- /* recoreded keys - set here before AP startup */
- struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS];
-
- u8 mgmt_rate_idx;
- u8 bcast_rate_idx;
- u8 ucast_rate_idx[CONF_TX_MAX_AC_COUNT];
- } ap;
- };
-
- /* the hlid of the last transmitted skb */
- int last_tx_hlid;
-
- unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
-
- u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
- u8 ssid_len;
-
- /* 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;
-
- /*
- * currently configured rate set:
- * bits 0-15 - 802.11abg rates
- * bits 16-23 - 802.11n MCS index mask
- * support only 1 stream, thus only 8 bits for the MCS rates (0-7).
- */
- u32 basic_rate;
- u32 rate_set;
-
- /* probe-req template for the current AP */
- struct sk_buff *probereq;
-
- /* Beaconing interval (needed for ad-hoc) */
- u32 beacon_int;
-
- /* Default key (for WEP) */
- u32 default_key;
-
- /* Our association ID */
- u16 aid;
-
- /* Session counter for the chipset */
- int session_counter;
-
- /* retry counter for PSM entries */
- u8 psm_entry_retry;
-
- /* in dBm */
- int power_level;
-
- int rssi_thold;
- int last_rssi_event;
-
- /* save the current encryption type for auto-arp config */
- u8 encryption_type;
- __be32 ip_addr;
-
- /* RX BA constraint value */
- bool ba_support;
- bool ba_allowed;
-
- /* Rx Streaming */
- struct work_struct rx_streaming_enable_work;
- 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)
- * should be declared in this struct.
- */
- struct {
- u8 persistent[0];
- /*
- * Security sequence number
- * bits 0-15: lower 16 bits part of sequence number
- * bits 16-47: higher 32 bits part of sequence number
- * bits 48-63: not in use
- */
- u64 tx_security_seq;
-
- /* 8 bits of the last sequence number in use */
- u8 tx_security_last_seq_lsb;
- };
-};
-
-static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif)
-{
- return (struct wl12xx_vif *)vif->drv_priv;
-}
-
-static inline
-struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
-{
- return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
-}
-
-#define wl12xx_for_each_wlvif(wl, wlvif) \
- list_for_each_entry(wlvif, &wl->wlvif_list, list)
-
-#define wl12xx_for_each_wlvif_continue(wl, wlvif) \
- list_for_each_entry_continue(wlvif, &wl->wlvif_list, list)
-
-#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \
- wl12xx_for_each_wlvif(wl, wlvif) \
- if (wlvif->bss_type == _bss_type)
-
-#define wl12xx_for_each_wlvif_sta(wl, wlvif) \
- wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS)
-
-#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
- wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
-
-int wl1271_plt_start(struct wl1271 *wl);
-int wl1271_plt_stop(struct wl1271 *wl);
-int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
-void wl12xx_queue_recovery_work(struct wl1271 *wl);
-size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
-int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
- u16 offset, u8 flags,
- u8 *pattern, u8 len);
-void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
-struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
-int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);
-void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
- u8 *buf);
-
-#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
-
-#define SESSION_COUNTER_MAX 6 /* maximum value for the session counter */
-#define SESSION_COUNTER_INVALID 7 /* used with dummy_packet */
-
-#define WL1271_DEFAULT_POWER_LEVEL 0
-
-#define WL1271_TX_QUEUE_LOW_WATERMARK 32
-#define WL1271_TX_QUEUE_HIGH_WATERMARK 256
-
-#define WL1271_DEFERRED_QUEUE_LIMIT 64
-
-/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
- on in case is has been shut down shortly before */
-#define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */
-#define WL1271_POWER_ON_SLEEP 200 /* in milliseconds */
-
-/* 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
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index f9ec84d..8f724da 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -24,7 +24,7 @@
#include <linux/platform_device.h>
-#include "wl12xx.h"
+#include "wlcore_i.h"
#include "event.h"
/* The maximum number of Tx descriptors in all chip families */
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
new file mode 100644
index 0000000..819c97c
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -0,0 +1,509 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <[email protected]>
+ *
+ * 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 __WLCORE_I_H__
+#define __WLCORE_I_H__
+
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <net/mac80211.h>
+
+#include "conf.h"
+#include "ini.h"
+
+#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
+#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
+
+#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
+#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
+
+#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
+#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
+
+/*
+ * wl127x and wl128x are using the same NVS file name. However, the
+ * ini parameters between them are different. The driver validates
+ * the correct NVS size in wl1271_boot_upload_nvs().
+ */
+#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
+
+#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
+#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
+
+#define WL1271_CIPHER_SUITE_GEM 0x00147201
+
+#define WL1271_BUSY_WORD_CNT 1
+#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
+
+#define WL1271_ELP_HW_STATE_ASLEEP 0
+#define WL1271_ELP_HW_STATE_IRQ 1
+
+#define WL1271_DEFAULT_BEACON_INT 100
+#define WL1271_DEFAULT_DTIM_PERIOD 1
+
+#define WL12XX_MAX_ROLES 4
+#define WL12XX_MAX_LINKS 12
+#define WL12XX_INVALID_ROLE_ID 0xff
+#define WL12XX_INVALID_LINK_ID 0xff
+
+#define WL12XX_MAX_RATE_POLICIES 16
+
+/* Defined by FW as 0. Will not be freed or allocated. */
+#define WL12XX_SYSTEM_HLID 0
+
+/*
+ * When in AP-mode, we allow (at least) this number of packets
+ * to be transmitted to FW for a STA in PS-mode. Only when packets are
+ * present in the FW buffers it will wake the sleeping STA. We want to put
+ * enough packets for the driver to transmit all of its buffered data before
+ * the STA goes to sleep again. But we don't want to take too much memory
+ * as it might hurt the throughput of active STAs.
+ */
+#define WL1271_PS_STA_MAX_PACKETS 2
+
+#define WL1271_AP_BSS_INDEX 0
+#define WL1271_AP_DEF_BEACON_EXP 20
+
+#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
+
+enum wl1271_state {
+ WL1271_STATE_OFF,
+ WL1271_STATE_ON,
+};
+
+enum wl12xx_fw_type {
+ WL12XX_FW_TYPE_NONE,
+ WL12XX_FW_TYPE_NORMAL,
+ WL12XX_FW_TYPE_MULTI,
+ WL12XX_FW_TYPE_PLT,
+};
+
+struct wl1271;
+
+enum {
+ FW_VER_CHIP,
+ FW_VER_IF_TYPE,
+ FW_VER_MAJOR,
+ FW_VER_SUBTYPE,
+ FW_VER_MINOR,
+
+ NUM_FW_VER
+};
+
+#define FW_VER_CHIP_WL127X 6
+#define FW_VER_CHIP_WL128X 7
+
+#define FW_VER_IF_TYPE_STA 1
+#define FW_VER_IF_TYPE_AP 2
+
+#define FW_VER_MINOR_1_SPARE_STA_MIN 58
+#define FW_VER_MINOR_1_SPARE_AP_MIN 47
+
+#define FW_VER_MINOR_FWLOG_STA_MIN 70
+
+struct wl1271_chip {
+ u32 id;
+ char fw_ver_str[ETHTOOL_BUSINFO_LEN];
+ 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
+
+struct wl_fw_packet_counters {
+ /* Cumulative counter of released packets per AC */
+ u8 tx_released_pkts[NUM_TX_QUEUES];
+
+ /* Cumulative counter of freed packets per HLID */
+ u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
+
+ /* Cumulative counter of released Voice memory blocks */
+ u8 tx_voice_released_blks;
+
+ u8 padding[3];
+} __packed;
+
+/* FW status registers */
+struct wl_fw_status {
+ __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 fw_localtime;
+
+ /*
+ * A bitmap (where each bit represents a single HLID)
+ * to indicate if the station is in PS mode.
+ */
+ __le32 link_ps_bitmap;
+
+ /*
+ * A bitmap (where each bit represents a single HLID) to indicate
+ * if the station is in Fast mode
+ */
+ __le32 link_fast_bitmap;
+
+ /* Cumulative counter of total released mem blocks since FW-reset */
+ __le32 total_released_blks;
+
+ /* Size (in Memory Blocks) of TX pool */
+ __le32 tx_total;
+
+ struct wl_fw_packet_counters counters;
+
+ __le32 log_start_addr;
+
+ /* Private status to be used by the lower drivers */
+ 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;
+ unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)];
+ bool failed;
+ u8 state;
+ u8 ssid[IEEE80211_MAX_SSID_LEN+1];
+ size_t ssid_len;
+};
+
+struct wl1271_if_operations {
+ void (*read)(struct device *child, int addr, void *buf, size_t len,
+ bool fixed);
+ void (*write)(struct device *child, int addr, void *buf, size_t len,
+ bool fixed);
+ void (*reset)(struct device *child);
+ void (*init)(struct device *child);
+ int (*power)(struct device *child, bool enable);
+ void (*set_block_size) (struct device *child, unsigned int blksz);
+};
+
+#define MAX_NUM_KEYS 14
+#define MAX_KEY_SIZE 32
+
+struct wl1271_ap_key {
+ u8 id;
+ u8 key_type;
+ u8 key_size;
+ u8 key[MAX_KEY_SIZE];
+ u8 hlid;
+ u32 tx_seq_32;
+ u16 tx_seq_16;
+};
+
+enum wl12xx_flags {
+ WL1271_FLAG_GPIO_POWER,
+ WL1271_FLAG_TX_QUEUE_STOPPED,
+ WL1271_FLAG_TX_PENDING,
+ WL1271_FLAG_IN_ELP,
+ WL1271_FLAG_ELP_REQUESTED,
+ WL1271_FLAG_IRQ_RUNNING,
+ WL1271_FLAG_FW_TX_BUSY,
+ WL1271_FLAG_DUMMY_PACKET_PENDING,
+ WL1271_FLAG_SUSPENDED,
+ WL1271_FLAG_PENDING_WORK,
+ WL1271_FLAG_SOFT_GEMINI,
+ WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
+ WL1271_FLAG_INTENDED_FW_RECOVERY,
+};
+
+enum wl12xx_vif_flags {
+ WLVIF_FLAG_INITIALIZED,
+ WLVIF_FLAG_STA_ASSOCIATED,
+ WLVIF_FLAG_STA_AUTHORIZED,
+ WLVIF_FLAG_IBSS_JOINED,
+ WLVIF_FLAG_AP_STARTED,
+ WLVIF_FLAG_IN_PS,
+ WLVIF_FLAG_STA_STATE_SENT,
+ WLVIF_FLAG_RX_STREAMING_STARTED,
+ WLVIF_FLAG_PSPOLL_FAILURE,
+ WLVIF_FLAG_CS_PROGRESS,
+ WLVIF_FLAG_AP_PROBE_RESP_SET,
+ WLVIF_FLAG_IN_USE,
+};
+
+struct wl1271_link {
+ /* AP-mode - TX queue per AC in link */
+ struct sk_buff_head tx_queue[NUM_TX_QUEUES];
+
+ /* accounting for allocated / freed packets in FW */
+ u8 allocated_pkts;
+ u8 prev_freed_pkts;
+
+ u8 addr[ETH_ALEN];
+
+ /* bitmap of TIDs where RX BA sessions are active for this link */
+ u8 ba_bitmap;
+};
+
+#define WL1271_MAX_RX_FILTERS 5
+#define WL1271_RX_FILTER_MAX_FIELDS 8
+
+#define WL1271_RX_FILTER_ETH_HEADER_SIZE 14
+#define WL1271_RX_FILTER_MAX_FIELDS_SIZE 95
+#define RX_FILTER_FIELD_OVERHEAD \
+ (sizeof(struct wl12xx_rx_filter_field) - sizeof(u8 *))
+#define WL1271_RX_FILTER_MAX_PATTERN_SIZE \
+ (WL1271_RX_FILTER_MAX_FIELDS_SIZE - RX_FILTER_FIELD_OVERHEAD)
+
+#define WL1271_RX_FILTER_FLAG_MASK BIT(0)
+#define WL1271_RX_FILTER_FLAG_IP_HEADER 0
+#define WL1271_RX_FILTER_FLAG_ETHERNET_HEADER BIT(1)
+
+enum rx_filter_action {
+ FILTER_DROP = 0,
+ FILTER_SIGNAL = 1,
+ FILTER_FW_HANDLE = 2
+};
+
+struct wl12xx_rx_filter_field {
+ __le16 offset;
+ u8 len;
+ u8 flags;
+ u8 *pattern;
+} __packed;
+
+struct wl12xx_rx_filter {
+ u8 action;
+ int num_fields;
+ struct wl12xx_rx_filter_field fields[WL1271_RX_FILTER_MAX_FIELDS];
+};
+
+struct wl1271_station {
+ u8 hlid;
+};
+
+struct wl12xx_vif {
+ struct wl1271 *wl;
+ struct list_head list;
+ unsigned long flags;
+ u8 bss_type;
+ u8 p2p; /* we are using p2p role */
+ u8 role_id;
+
+ /* sta/ibss specific */
+ u8 dev_role_id;
+ u8 dev_hlid;
+
+ union {
+ struct {
+ u8 hlid;
+ u8 ba_rx_bitmap;
+
+ u8 basic_rate_idx;
+ u8 ap_rate_idx;
+ u8 p2p_rate_idx;
+
+ bool qos;
+ } sta;
+ struct {
+ u8 global_hlid;
+ u8 bcast_hlid;
+
+ /* HLIDs bitmap of associated stations */
+ unsigned long sta_hlid_map[BITS_TO_LONGS(
+ WL12XX_MAX_LINKS)];
+
+ /* recoreded keys - set here before AP startup */
+ struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS];
+
+ u8 mgmt_rate_idx;
+ u8 bcast_rate_idx;
+ u8 ucast_rate_idx[CONF_TX_MAX_AC_COUNT];
+ } ap;
+ };
+
+ /* the hlid of the last transmitted skb */
+ int last_tx_hlid;
+
+ unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+
+ u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
+ u8 ssid_len;
+
+ /* 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;
+
+ /*
+ * currently configured rate set:
+ * bits 0-15 - 802.11abg rates
+ * bits 16-23 - 802.11n MCS index mask
+ * support only 1 stream, thus only 8 bits for the MCS rates (0-7).
+ */
+ u32 basic_rate;
+ u32 rate_set;
+
+ /* probe-req template for the current AP */
+ struct sk_buff *probereq;
+
+ /* Beaconing interval (needed for ad-hoc) */
+ u32 beacon_int;
+
+ /* Default key (for WEP) */
+ u32 default_key;
+
+ /* Our association ID */
+ u16 aid;
+
+ /* Session counter for the chipset */
+ int session_counter;
+
+ /* retry counter for PSM entries */
+ u8 psm_entry_retry;
+
+ /* in dBm */
+ int power_level;
+
+ int rssi_thold;
+ int last_rssi_event;
+
+ /* save the current encryption type for auto-arp config */
+ u8 encryption_type;
+ __be32 ip_addr;
+
+ /* RX BA constraint value */
+ bool ba_support;
+ bool ba_allowed;
+
+ /* Rx Streaming */
+ struct work_struct rx_streaming_enable_work;
+ 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)
+ * should be declared in this struct.
+ */
+ struct {
+ u8 persistent[0];
+ /*
+ * Security sequence number
+ * bits 0-15: lower 16 bits part of sequence number
+ * bits 16-47: higher 32 bits part of sequence number
+ * bits 48-63: not in use
+ */
+ u64 tx_security_seq;
+
+ /* 8 bits of the last sequence number in use */
+ u8 tx_security_last_seq_lsb;
+ };
+};
+
+static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif)
+{
+ return (struct wl12xx_vif *)vif->drv_priv;
+}
+
+static inline
+struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
+{
+ return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
+}
+
+#define wl12xx_for_each_wlvif(wl, wlvif) \
+ list_for_each_entry(wlvif, &wl->wlvif_list, list)
+
+#define wl12xx_for_each_wlvif_continue(wl, wlvif) \
+ list_for_each_entry_continue(wlvif, &wl->wlvif_list, list)
+
+#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \
+ wl12xx_for_each_wlvif(wl, wlvif) \
+ if (wlvif->bss_type == _bss_type)
+
+#define wl12xx_for_each_wlvif_sta(wl, wlvif) \
+ wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS)
+
+#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
+ wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
+
+int wl1271_plt_start(struct wl1271 *wl);
+int wl1271_plt_stop(struct wl1271 *wl);
+int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
+void wl12xx_queue_recovery_work(struct wl1271 *wl);
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
+int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
+ u16 offset, u8 flags,
+ u8 *pattern, u8 len);
+void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
+struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
+int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);
+void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
+ u8 *buf);
+
+#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
+
+#define SESSION_COUNTER_MAX 6 /* maximum value for the session counter */
+#define SESSION_COUNTER_INVALID 7 /* used with dummy_packet */
+
+#define WL1271_DEFAULT_POWER_LEVEL 0
+
+#define WL1271_TX_QUEUE_LOW_WATERMARK 32
+#define WL1271_TX_QUEUE_HIGH_WATERMARK 256
+
+#define WL1271_DEFERRED_QUEUE_LIMIT 64
+
+/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
+ on in case is has been shut down shortly before */
+#define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */
+#define WL1271_POWER_ON_SLEEP 200 /* in milliseconds */
+
+/* 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 /* __WLCORE_I_H__ */
--
1.7.9.5
The 18xx FW sends Rx blocks with aligned length.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 4a5ef6e..a074d81 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -243,7 +243,8 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)",
wl->chip.id);
wl->sr_fw_name = WL18XX_FW_NAME;
- wl->quirks |= WLCORE_QUIRK_NO_ELP;
+ wl->quirks |= WLCORE_QUIRK_NO_ELP |
+ WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN;
/* TODO: need to blocksize alignment for RX/TX separately? */
break;
--
1.7.9.5
On Thu, May 10, 2012 at 1:15 PM, Kalle Valo <[email protected]> wrote:
> Arik Nemtsov <[email protected]> writes:
>
>> On Thu, May 10, 2012 at 12:50 PM, Kalle Valo <[email protected]> wrote:
>>> Arik Nemtsov <[email protected]> writes:
>>>
>>>> This series adds initial support for the 18xx chip family. The new
>>>> module uses wlcore for functionality common with the 12xx family.
>>>
>>> You do know that sending 78 patches in one patchset is very much
>>> frowned upon? No sane person (outside of wl12xx) is going to review
>>> all of these.
>>
>> Yea I don't like it as well, but it took this amount of patches to get
>> the card up and running. Posting some skeleton code seems kind of
>> useless.
>
> You can always submit patches in smaller (10-15 patches) chunks.
We'll try to better split stuff in the future.
Arik
From: Luciano Coelho <[email protected]>
There are some problems with MCS_13 in PG 1.0 hardware. So we disable
it when PG 1.0 is detected.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 6047a6d..afa2334 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -588,6 +588,9 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED |
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN;
+ /* PG 1.0 has some problems with MCS_13, so disable it */
+ wl->ht_cap.mcs.rx_mask[1] &= ~BIT(5);
+
/* TODO: need to blocksize alignment for RX/TX separately? */
break;
default:
@@ -914,6 +917,10 @@ static void wl18xx_set_rx_csum(struct wl1271 *wl,
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)
{
@@ -940,6 +947,17 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
return CONF_TX_RATE_USE_WIDE_CHAN;
} else {
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;
}
}
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Only wl127x chips use the rx_mem_pool_addr values, which need to be
given to the firmware as part of the RX path. Move this from core to
the wl12xx driver.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 2 +-
drivers/net/wireless/ti/wl12xx/wl12xx.h | 5 +++++
drivers/net/wireless/ti/wlcore/wlcore.h | 3 ---
drivers/net/wireless/ti/wlcore/wlcore_i.h | 5 -----
4 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 962d85d..0266855 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -596,7 +596,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 wl1271_rx_mem_pool_addr rx_mem_addr;
+ struct wl127x_rx_mem_pool_addr rx_mem_addr;
/*
* Choose the block we want to read
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 0d81c1e..de11324 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -24,6 +24,11 @@
#include "conf.h"
+struct wl127x_rx_mem_pool_addr {
+ u32 addr;
+ u32 addr_extra;
+};
+
struct wl12xx_priv {
struct wl12xx_priv_conf conf;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 89abbce..f62152e 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -213,9 +213,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;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 819c97c..53263a9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -194,11 +194,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;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
In some cases it may be useful to force narrow-band SISO channels.
Add a new value to the ht_mode module parameter to force the device to
operate in SISO 20MHz.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 38 +++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 6a81edf..0795598 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1055,7 +1055,7 @@ static struct wlcore_ops wl18xx_ops = {
};
/* HT cap appropriate for wide channels */
-static struct ieee80211_sta_ht_cap wl18xx_ht_cap = {
+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,
@@ -1068,6 +1068,19 @@ static struct ieee80211_sta_ht_cap wl18xx_ht_cap = {
},
};
+/* 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 = {
.cap = IEEE80211_HT_CAP_SGI_20,
@@ -1108,10 +1121,20 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
- memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
- if (!strcmp(ht_mode_param, "mimo"))
+
+ if (!strcmp(ht_mode_param, "wide")) {
+ memcpy(&wl->ht_cap, &wl18xx_siso40_ht_cap,
+ sizeof(wl18xx_siso40_ht_cap));
+ } else if (!strcmp(ht_mode_param, "mimo")) {
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
sizeof(wl18xx_mimo_ht_cap));
+ } else if (!strcmp(ht_mode_param, "siso20")) {
+ memcpy(&wl->ht_cap, &wl18xx_siso20_ht_cap,
+ sizeof(wl18xx_siso20_ht_cap));
+ } else {
+ wl1271_error("invalid ht_mode '%s'", ht_mode_param);
+ goto out_free;
+ }
wl18xx_conf_init(wl);
@@ -1131,8 +1154,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
priv->conf.phy.low_band_component_type = 0x06;
} else {
wl1271_error("invalid board type '%s'", board_type_param);
- wlcore_free_hw(wl);
- return -EINVAL;
+ goto out_free;
}
if (!checksum_param) {
@@ -1143,6 +1165,10 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->enable_11a = enable_11a_param;
return wlcore_probe(wl, pdev);
+
+out_free:
+ wlcore_free_hw(wl);
+ return -EINVAL;
}
static const struct platform_device_id wl18xx_id_table[] __devinitconst = {
@@ -1174,7 +1200,7 @@ static void __exit wl18xx_exit(void)
module_exit(wl18xx_exit);
module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
-MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or mimo");
+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 "
--
1.7.9.5
Add more board types and remove a now unneeded write to SCR_PAD2 setting
the board type.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 43 +++++++++++++--------------------
drivers/net/wireless/ti/wl18xx/reg.h | 15 ++++--------
2 files changed, 22 insertions(+), 36 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ddd11d0..f892d37 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -45,12 +45,6 @@
static char *ht_mode_param;
static char *board_type_param;
-static const u32 wl18xx_board_type_to_scrpad2[NUM_BOARD_TYPES] = {
- [BOARD_TYPE_FPGA_18XX] = SCR_PAD2_BOARD_TYPE_FPGA,
- [BOARD_TYPE_HDK_18XX] = SCR_PAD2_BOARD_TYPE_HDK,
- [BOARD_TYPE_DVP_EVB_18XX] = SCR_PAD2_BOARD_TYPE_DVP_EVB,
-};
-
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
@@ -604,13 +598,8 @@ out:
static void wl18xx_set_clk(struct wl1271 *wl)
{
- struct wl18xx_priv *priv = wl->priv;
u32 clk_freq;
- /* write the translated board type to SCR_PAD2 */
- wl1271_write32(wl, WL18XX_SCR_PAD2,
- wl18xx_board_type_to_scrpad2[priv->board_type]);
-
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
/* TODO: PG2: apparently we need to read the clk type */
@@ -1046,21 +1035,22 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
sizeof(wl18xx_mimo_ht_cap));
if (!board_type_param) {
- board_type_param = kstrdup("dvp_evb", GFP_KERNEL);
- priv->board_type = BOARD_TYPE_DVP_EVB_18XX;
+ board_type_param = kstrdup("dvp", GFP_KERNEL);
+ priv->board_type = BOARD_TYPE_DVP_18XX;
+ } else if (!strcmp(board_type_param, "fpga")) {
+ priv->board_type = BOARD_TYPE_FPGA_18XX;
+ } else if (!strcmp(board_type_param, "hdk")) {
+ priv->board_type = BOARD_TYPE_HDK_18XX;
+ } else if (!strcmp(board_type_param, "dvp")) {
+ priv->board_type = BOARD_TYPE_DVP_18XX;
+ } else if (!strcmp(board_type_param, "evb")) {
+ priv->board_type = BOARD_TYPE_EVB_18XX;
+ } else if (!strcmp(board_type_param, "com8")) {
+ priv->board_type = BOARD_TYPE_COM8_18XX;
} else {
- if (!strcmp(board_type_param, "fpga"))
- priv->board_type = BOARD_TYPE_FPGA_18XX;
- else if (!strcmp(board_type_param, "hdk"))
- priv->board_type = BOARD_TYPE_HDK_18XX;
- else if (!strcmp(board_type_param, "dvp_evb"))
- priv->board_type = BOARD_TYPE_DVP_EVB_18XX;
- else {
- wl1271_error("invalid board type '%s'",
- board_type_param);
- wlcore_free_hw(wl);
- return -EINVAL;
- }
+ wl1271_error("invalid board type '%s'", board_type_param);
+ wlcore_free_hw(wl);
+ return -EINVAL;
}
wl18xx_conf_init(wl);
@@ -1100,7 +1090,8 @@ module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or mimo");
module_param_named(board_type, board_type_param, charp, S_IRUSR);
-MODULE_PARM_DESC(board_type, "Board type: fpga, hdk or dvp_evb (default)");
+MODULE_PARM_DESC(board_type, "Board type: fpga, hdk, evb, com8 or "
+ "dvp (default)");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 43c480f..1674c1a 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -176,20 +176,15 @@ enum {
};
enum {
- BOARD_TYPE_FPGA_18XX = 0,
- BOARD_TYPE_HDK_18XX = 1,
- BOARD_TYPE_DVP_EVB_18XX = 2,
+ 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,
};
-/* board type values used by the firmware in the SCR_PAD2 register */
-enum {
- SCR_PAD2_BOARD_TYPE_FPGA = 0xB1,
- SCR_PAD2_BOARD_TYPE_HDK = 0xB2,
- SCR_PAD2_BOARD_TYPE_DVP_EVB = 0xB3,
-};
-
struct wl18xx_mac_and_phy_params {
u8 phy_standalone;
u8 rdl;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
In wl18xx we don't have an NVS yet, so we need to control whether 11a
is supported with a module parameter for now. 11a support is enabled
by default and can be changed by setting enable_11a to false when
loading the module.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 52d63ff..d4e331f 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -48,6 +48,7 @@ static bool dc2dc_param = false;
static int n_antennas_2_param = 1;
static int n_antennas_5_param = 1;
static bool checksum_param = true;
+static bool enable_11a_param = true;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -1097,6 +1098,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl18xx_ops.init_vif = NULL;
}
+ wl->enable_11a = enable_11a_param;
+
wl18xx_conf_init(wl);
return wlcore_probe(wl, pdev);
@@ -1149,6 +1152,9 @@ MODULE_PARM_DESC(n_antennas_5, "Number of installed 5GHz antennas: 1 (default) o
module_param_named(checksum, checksum_param, bool, S_IRUSR);
MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to true)");
+module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR);
+MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
Hi Kalle,
On Thu, 2012-05-10 at 12:50 +0300, Kalle Valo wrote:
> Arik Nemtsov <[email protected]> writes:
>
> > This series adds initial support for the 18xx chip family. The new
> > module uses wlcore for functionality common with the 12xx family.
>
> You do know that sending 78 patches in one patchset is very much
> frowned upon? No sane person (outside of wl12xx) is going to review
> all of these.
Yes, I totally agree with you. I have been trying to send all this
stuff in smaller batches that would be much easier to review and manage
upstream. We wanted to squash many of them, clean things up a bit more
and so on, but we diverged so much from the mainline (we had close to
100 patches dragging in our internal trees) that all the rebases and
even small squashes or moving patches around became a horrible
nightmare.
As you know, I've been on sick leave for a while, so all this work would
have dragged even longer if Arik and the rest of the team didn't take an
action to get it out.
To conclude, even though I don't like the way this was done, now it's
done and sending this series again in smaller batches would just make
things worse, because not only there would still be a huge bunch of
patches in total, most of them would actually be duplicate or just
slightly modified.
So, unless you or someone else really disagrees, I'll apply these to the
wl12xx.git tree.
And then I'll go find Arik to remove some of his fingernails, especially
the one on his right hand pinky so he can't hit ENTER so quickly after
typing git send-email. :P
--
Cheers,
Luca.
Add the 18xx variant to the HW Tx descriptor union and set the 18xx
specific values during Tx.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 10 ++++++++++
drivers/net/wireless/ti/wlcore/tx.h | 14 ++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 055b194..c85492e 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -26,6 +26,7 @@
#include "../wlcore/debug.h"
#include "../wlcore/io.h"
#include "../wlcore/acx.h"
+#include "../wlcore/tx.h"
#include "../wlcore/boot.h"
#include "reg.h"
@@ -312,12 +313,21 @@ static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
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;
+ desc->wl18xx_mem.reserved = 0;
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index 2fd6e5d..e440c31 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -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;
+
+ /*
+ * always zero
+ */
+ u8 reserved;
+} __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;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
With 4 pages (16Kb), we can't fit 10 frames in the aggregation buffer
during iperf. This is the optimal for the firmware. Thus, increase
the buffer size by one page.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 45c07dc..83c9869 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.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,
--
1.7.9.5
Some chip families are capable of checksumming certain classes of Tx
packets in HW. Indicate this fact in the netdev features and perform the
HW checksum by protocol type for the 18xx family.
Fix the location of the skb network header when we move it so we can
rely on it when setting the checksum.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 8 ++++++++
drivers/net/wireless/ti/wl18xx/acx.c | 26 ++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/acx.h | 16 ++++++++++++++++
drivers/net/wireless/ti/wl18xx/main.c | 31 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wlcore/acx.h | 1 +
drivers/net/wireless/ti/wlcore/hw_ops.h | 11 +++++++++++
drivers/net/wireless/ti/wlcore/tx.c | 3 ++-
drivers/net/wireless/ti/wlcore/tx.h | 11 ++++++++++-
drivers/net/wireless/ti/wlcore/wlcore.h | 3 +++
9 files changed, 108 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d7dd3de..8141447 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1288,6 +1288,13 @@ 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 struct wlcore_ops wl12xx_ops = {
.identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw,
@@ -1306,6 +1313,7 @@ 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,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index aed8d0d..3379db2 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -55,3 +55,29 @@ out:
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;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index c8eebd8..544db6e 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -45,8 +45,24 @@ struct wl18xx_acx_host_config_bitmap {
} __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;
+
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);
#endif /* __WL12XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 1e0719c..c47f52c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/ip.h>
#include "../wlcore/wlcore.h"
#include "../wlcore/debug.h"
@@ -501,9 +502,38 @@ static int wl18xx_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ 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 (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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -517,6 +547,7 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 7a8dfba..e513b1b 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -1245,6 +1245,7 @@ enum {
ACX_CONFIG_HANGOVER = 0x0042,
ACX_FEATURE_CFG = 0x0043,
ACX_PROTECTION_CFG = 0x0044,
+ ACX_CHECKSUM_CONFIG = 0x0045,
};
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 9384b4d..4573249 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -119,4 +119,15 @@ 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);
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index b4e02ef..44e4e7b 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -270,6 +270,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 */
@@ -332,9 +333,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);
}
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index 2207274..e24c436 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -130,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 {
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 0b3f0b5..c062d30 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -61,6 +61,9 @@ 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);
};
enum wlcore_partitions {
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add a macro to make it easy to print arrays from the FW statistics
array in debugfs. At the same time, increase the buffer size so
arrays fit more easily.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/debugfs.c | 1 -
drivers/net/wireless/ti/wlcore/debugfs.h | 27 +++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 57c1eae..fc44262 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -39,7 +39,6 @@
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
/* debugfs macros idea from mac80211 */
-#define DEBUGFS_FORMAT_BUFFER_SIZE 100
int wl1271_format_buffer(char __user *userbuf, size_t count,
loff_t *ppos, char *fmt, ...)
{
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h
index e1a5bf1..f7381dd 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.h
+++ b/drivers/net/wireless/ti/wlcore/debugfs.h
@@ -34,6 +34,8 @@ 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) \
@@ -86,6 +88,31 @@ static const struct file_operations sub## _ ##name## _ops = { \
.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)
--
1.7.9.5
The number of RX packet descriptors may vary from chip to chip and
in different firmware versions. Unfortunately, the array that
contains the actual descriptors is in the middle of the fw_status
structure. To manage this, we split the struct into two so we can
calculate the offset of what comes after the array and access the last
elements more easily.
[Changed the STATUS_LEN macro to be placement agnostic - Arik]
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 4 +-
drivers/net/wireless/ti/wl18xx/main.c | 1 +
drivers/net/wireless/ti/wl18xx/tx.c | 2 +-
drivers/net/wireless/ti/wlcore/main.c | 64 ++++++++++++++++-------------
drivers/net/wireless/ti/wlcore/rx.c | 10 ++---
drivers/net/wireless/ti/wlcore/rx.h | 4 +-
drivers/net/wireless/ti/wlcore/wlcore.h | 5 ++-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 18 ++++++--
8 files changed, 66 insertions(+), 42 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 1d097c1..82e0c6a 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1156,7 +1156,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);
@@ -1414,6 +1415,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
wl->ptable = wl12xx_ptable;
wl->rtable = wl12xx_rtable;
wl->num_tx_desc = 16;
+ wl->num_rx_desc = 8;
wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index b76b6ac..df407be 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1041,6 +1041,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = 32;
+ wl->num_rx_desc = 16;
wl->normal_tx_spare = WL18XX_TX_HW_BLOCK_SPARE;
wl->gem_tx_spare = WL18XX_TX_HW_GEM_BLOCK_SPARE;
wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
index 4e12f56..4de00b9 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -94,7 +94,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
void wl18xx_tx_immediate_complete(struct wl1271 *wl)
{
struct wl18xx_fw_status_priv *status_priv =
- (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
+ (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
struct wl18xx_priv *priv = wl->priv;
u8 i;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 3aadf74..3e3dce9 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -347,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;
@@ -379,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;
@@ -388,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;
@@ -434,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
@@ -453,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)
@@ -528,11 +530,11 @@ 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 = le32_to_cpu(wl->fw_status_1->intr);
intr &= WL1271_INTR_MASK;
if (!intr) {
done = true;
@@ -551,7 +553,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);
@@ -786,8 +788,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
wl12xx_cmd_stop_fwlog(wl);
/* 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;
@@ -901,13 +903,18 @@ 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), 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;
}
@@ -1745,8 +1752,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);
@@ -5180,7 +5188,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);
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index e2c5df6..406eed2 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -200,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;
@@ -224,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) {
@@ -264,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);
}
}
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index 277936e..9be7801 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -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
@@ -139,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,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 1fc3c77..9ca3829 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -269,7 +269,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 */
@@ -337,6 +338,8 @@ struct wl1271 {
/* number of TX descriptors the HW supports. */
u32 num_tx_desc;
+ /* number of RX descriptors the HW supports. */
+ u32 num_rx_desc;
/* spare Tx blocks for normal/GEM operating modes */
u32 normal_tx_spare;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 53263a9..0422753 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -141,7 +141,6 @@ struct wl1271_stats {
};
#define NUM_TX_QUEUES 4
-#define NUM_RX_PKT_DESC 8
#define AP_MAX_STATIONS 8
@@ -159,13 +158,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;
/*
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add identify_chip operation to detect the chip ID for wl185x and set
the correct firmware name.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 34 ++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 88fd934..e517afd 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -27,9 +27,6 @@
#include "reg.h"
-static struct wlcore_ops wl18xx_ops = {
-};
-
static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
[PART_TOP_PRCM_ELP_SOC] = {
.mem = { .start = 0x00A02000, .size = 0x00010000 },
@@ -84,6 +81,36 @@ static const int wl18xx_rtable[REG_TABLE_LEN] = {
[REG_RAW_FW_STATUS_ADDR] = WL18XX_FW_STATUS_ADDR,
};
+/* 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_PG10:
+ wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)",
+ wl->chip.id);
+ wl->sr_fw_name = WL18XX_FW_NAME;
+ wl->quirks |= WLCORE_QUIRK_NO_ELP;
+
+ /* TODO: need to blocksize alignment for RX/TX separately? */
+ break;
+ default:
+ wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
+ ret = -ENODEV;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static struct wlcore_ops wl18xx_ops = {
+ .identify_chip = wl18xx_identify_chip,
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -133,3 +160,4 @@ module_exit(wl18xx_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
+MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Only wl12xx needs to get the ref_clock anc tcxo_clock values from the
platform data. Move these elements from the wl1271 structure to
wl12xx's private data.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/cmd.c | 8 ++-
drivers/net/wireless/ti/wl12xx/main.c | 88 +++++++++++++++++++++++++-----
drivers/net/wireless/ti/wl12xx/wl12xx.h | 3 +
drivers/net/wireless/ti/wlcore/debugfs.c | 3 +-
drivers/net/wireless/ti/wlcore/main.c | 2 -
drivers/net/wireless/ti/wlcore/wlcore.h | 3 -
6 files changed, 82 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
index 8ffaeb5..50ba748 100644
--- a/drivers/net/wireless/ti/wl12xx/cmd.c
+++ b/drivers/net/wireless/ti/wl12xx/cmd.c
@@ -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) {
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index ad760a3..962d85d 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -40,6 +40,9 @@
#include "cmd.h"
#include "acx.h"
+static char *fref_param;
+static char *tcxo_param;
+
static struct wlcore_conf wl12xx_conf = {
.sg = {
.params = {
@@ -773,6 +776,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 +786,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 +812,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 +831,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 +841,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 +856,26 @@ config_mcs_pll:
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_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 +945,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 +977,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);
@@ -1333,6 +1340,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;
@@ -1344,6 +1352,7 @@ 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;
@@ -1357,6 +1366,48 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
memcpy(&wl->ht_cap, &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);
}
@@ -1388,6 +1439,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 <[email protected]>");
MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 74cd332..0d81c1e 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -26,6 +26,9 @@
struct wl12xx_priv {
struct wl12xx_priv_conf conf;
+
+ int ref_clock;
+ int tcxo_clock;
};
#endif /* __WL12XX_PRIV_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index d5aea1f..d377519 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -535,8 +535,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);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index cbe94ed..414ffa8 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5294,8 +5294,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;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 8f724da..89abbce 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -130,7 +130,6 @@ struct wl1271 {
void (*set_power)(bool enable);
int irq;
- int ref_clock;
spinlock_t wl_lock;
@@ -288,8 +287,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)
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Since the most common board we're using now is an HDK board, change
the default board_type to hdk.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index f5ec6f6..aa227a1 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -43,7 +43,7 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
static char *ht_mode_param;
-static char *board_type_param;
+static char *board_type_param = "hdk";
static bool dc2dc_param = false;
static int n_antennas_2_param = 1;
static int n_antennas_5_param = 1;
@@ -1074,10 +1074,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl18xx_conf_init(wl);
- if (!board_type_param) {
- board_type_param = kstrdup("dvp", GFP_KERNEL);
- priv->board_type = BOARD_TYPE_DVP_18XX;
- } else if (!strcmp(board_type_param, "fpga")) {
+ if (!strcmp(board_type_param, "fpga")) {
priv->board_type = BOARD_TYPE_FPGA_18XX;
} else if (!strcmp(board_type_param, "hdk")) {
priv->board_type = BOARD_TYPE_HDK_18XX;
@@ -1137,8 +1134,8 @@ module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or mimo");
module_param_named(board_type, board_type_param, charp, S_IRUSR);
-MODULE_PARM_DESC(board_type, "Board type: fpga, hdk, evb, com8 or "
- "dvp (default)");
+MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
+ "dvp");
module_param_named(dc2dc, dc2dc_param, bool, S_IRUSR);
MODULE_PARM_DESC(dc2dc, "External DC2DC: boolean (defaults to false)");
--
1.7.9.5
From: Luciano Coelho <[email protected]>
With more recent PHY firmware versions (>8.1.0.0.116), we need to use
the correct value for the pwr_limit_reference_11_abg parameter when
setting the mac_and_phy options.
For now we use a hardcoded 0xc8 as the value. This will be moved to
the configuration binary when it gets implemented.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/conf.h | 1 +
drivers/net/wireless/ti/wl18xx/main.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index a6058fb..ffad302 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -43,6 +43,7 @@ struct wl18xx_conf_phy {
u8 primary_clock_setting_time;
u8 clock_valid_on_wake_up;
u8 secondary_clock_setting_time;
+ u8 pwr_limit_reference_11_abg;
};
struct wl18xx_priv_conf {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 0795598..ab3dd11 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -501,6 +501,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
.enable_clpc = 0x00,
.enable_tx_low_pwr_on_siso_rdl = 0x00,
.rx_profile = 0x00,
+ .pwr_limit_reference_11_abg = 0xc8,
},
};
@@ -726,6 +727,8 @@ static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
phy->clock_valid_on_wake_up;
params.secondary_clock_setting_time =
phy->secondary_clock_setting_time;
+ params.pwr_limit_reference_11_abg =
+ phy->pwr_limit_reference_11_abg;
params.board_type = priv->board_type;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Sometimes we get a BSS_CHANGED_BEACON_ENABLED event before the basic
rates have been properly set. To avoid problems with the firmware not
expecting to receive frames at rates that are not set during
CMD_START_ROLE, we now start with all basic rates by default.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index f952098..1d9c11c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1845,6 +1845,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;
@@ -1854,13 +1857,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;
/*
--
1.7.9.5
Implement immediate Tx completion for the 18xx family. Move 18xx
specific Tx code to new tx.c/h files and create helper header files
for definitions.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/Makefile | 2 +-
drivers/net/wireless/ti/wl18xx/main.c | 11 ++-
drivers/net/wireless/ti/wl18xx/tx.c | 126 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/tx.h | 36 +++++++++
drivers/net/wireless/ti/wl18xx/wl18xx.h | 3 +
drivers/net/wireless/ti/wlcore/tx.c | 4 +-
drivers/net/wireless/ti/wlcore/tx.h | 1 +
7 files changed, 178 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/wireless/ti/wl18xx/tx.c
create mode 100644 drivers/net/wireless/ti/wl18xx/tx.h
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
index d187037..dd3b4c1 100644
--- a/drivers/net/wireless/ti/wl18xx/Makefile
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -1,3 +1,3 @@
-wl18xx-objs = main.o
+wl18xx-objs = main.o tx.o
obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 40ed53c..ae71131 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -33,11 +33,9 @@
#include "reg.h"
#include "conf.h"
+#include "tx.h"
#include "wl18xx.h"
-#define WL18XX_TX_HW_BLOCK_SPARE 1
-#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
-#define WL18XX_TX_HW_BLOCK_SIZE 268
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -470,6 +468,11 @@ static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
return data_len - sizeof(*desc);
}
+static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
+{
+ wl18xx_tx_immediate_complete(wl);
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -480,6 +483,8 @@ static struct wlcore_ops wl18xx_ops = {
.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,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
new file mode 100644
index 0000000..4e12f56
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -0,0 +1,126 @@
+/*
+ * 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 (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->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;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/tx.h b/drivers/net/wireless/ti/wl18xx/tx.h
new file mode 100644
index 0000000..a91eb10
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/tx.h
@@ -0,0 +1,36 @@
+/*
+ * 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
+#define WL18XX_TX_HW_GEM_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
+
+void wl18xx_tx_immediate_complete(struct wl1271 *wl);
+
+#endif /* __WL12XX_TX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 68ef5ba..d24f9c0 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -28,6 +28,9 @@
struct wl18xx_priv {
/* buffer for sending commands to FW */
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
+
+ /* Index of last released Tx desc in FW */
+ u8 last_fw_rls_idx;
};
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 6893bc2..b4e02ef 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -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)
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index e440c31..2207274 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -237,6 +237,7 @@ 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);
/* from main.c */
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
--
1.7.9.5
Translate the NL80211 channel type to a FW-specific channel type and send
it to the FW as part of the role-start command. For wl12xx this has no
effect - this element is treated as padding.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/cmd.c | 19 +++++++++++++++++++
drivers/net/wireless/ti/wlcore/cmd.h | 11 ++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 5b128a9..8450f0e 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -291,6 +291,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 +424,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);
@@ -519,6 +537,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 */
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index a46ae07..2aafe3d 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -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 {
--
1.7.9.5
Some chip families can checksum certain classes of Rx packets in FW.
Implement the Rx-checksum feature as a HW-op. For the 18xx chip-family,
set Rx-checsum according to indication from FW.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 1 +
drivers/net/wireless/ti/wl18xx/main.c | 11 +++++++++++
drivers/net/wireless/ti/wlcore/hw_ops.h | 9 +++++++++
drivers/net/wireless/ti/wlcore/rx.c | 1 +
drivers/net/wireless/ti/wlcore/wlcore.h | 4 ++++
5 files changed, 26 insertions(+)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 8141447..a333653 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1314,6 +1314,7 @@ static struct wlcore_ops wl12xx_ops = {
.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,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index c47f52c..90fccb7 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -39,6 +39,8 @@
#include "wl18xx.h"
+#define WL18XX_RX_CHECKSUM_MASK 0x40
+
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
@@ -534,6 +536,14 @@ static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
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;
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -548,6 +558,7 @@ static struct wlcore_ops wl18xx_ops = {
.tx_delayed_compl = NULL,
.hw_init = wl18xx_hw_init,
.set_tx_desc_csum = wl18xx_set_tx_desc_csum,
+ .set_rx_csum = wl18xx_set_rx_csum,
};
int __devinit wl18xx_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 4573249..80f3d75 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -130,4 +130,13 @@ wlcore_hw_set_tx_desc_csum(struct wl1271 *wl,
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);
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 1f1d948..e2c5df6 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -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,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index c062d30..2922d8a 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -33,6 +33,7 @@
/* 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);
@@ -64,6 +65,9 @@ struct wlcore_ops {
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);
};
enum wlcore_partitions {
--
1.7.9.5
Define HW-rate conversion tables for the 18xx chip. Initialize
the appropriate wlcore elements with these tables and values to allow
conversion of HW-rates.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 115 +++++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wlcore/conf.h | 10 ++-
2 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 0a5422c..7dcb832 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -37,6 +37,118 @@
#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
#define WL18XX_TX_HW_BLOCK_SIZE 268
+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 wl18xx_conf wl18xx_default_conf = {
.phy = {
.phy_standalone = 0x00,
@@ -363,6 +475,9 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->num_tx_desc = 32;
wl->normal_tx_spare = WL18XX_TX_HW_BLOCK_SPARE;
wl->gem_tx_spare = WL18XX_TX_HW_GEM_BLOCK_SPARE;
+ 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;
return wlcore_probe(wl, pdev);
}
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index fef0db4..0798c1e 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -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 {
--
1.7.9.5
On Thu, May 10, 2012 at 12:50 PM, Kalle Valo <[email protected]> wrote:
> Arik Nemtsov <[email protected]> writes:
>
>> This series adds initial support for the 18xx chip family. The new
>> module uses wlcore for functionality common with the 12xx family.
>
> You do know that sending 78 patches in one patchset is very much
> frowned upon? No sane person (outside of wl12xx) is going to review
> all of these.
Yea I don't like it as well, but it took this amount of patches to get
the card up and running. Posting some skeleton code seems kind of
useless.
Arik
This ensures the index is 0 on FW recovery and prevents spurious error
prints - "WARNING illegal id in tx completion".
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 9aae0af..a8b9cea 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -850,11 +850,15 @@ static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
static int wl18xx_hw_init(struct wl1271 *wl)
{
int ret;
+ struct wl18xx_priv *priv = wl->priv;
u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
HOST_IF_CFG_ADD_RX_ALIGNMENT;
u32 sdio_align_size = 0;
+ /* (re)init private structures. Relevant on recovery as well. */
+ priv->last_fw_rls_idx = 0;
+
/* Enable Tx SDIO padding */
if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) {
host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
In some cases we may want to dump all the SDIO data in order to get
detailed information for debugging the communication with the
firmware.
Add printks to dump the data and a module parameter to enable/disable
it.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/sdio.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 1082e39..c67ec48 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -33,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"
@@ -46,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;
@@ -77,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",
@@ -106,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",
@@ -380,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 <[email protected]>");
MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
--
1.7.9.5
From: Luciano Coelho <[email protected]>
We need to specify the number of 2.4GHz and 5GHz antennas and whether
the board has an internal or external DC2DC. Add some module
parameters that allow changing that.
In the future this will come from the "NVS" file.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/conf.h | 3 ---
drivers/net/wireless/ti/wl18xx/main.c | 21 +++++++++++++++------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index d2b097e..a6058fb 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -33,9 +33,6 @@ struct wl18xx_conf_phy {
u8 low_band_component_type;
u8 high_band_component;
u8 high_band_component_type;
- u8 number_of_assembled_ant2_4;
- u8 number_of_assembled_ant5;
- u8 external_pa_dc2dc;
u8 tcxo_ldo_voltage;
u8 xtal_itrim_val;
u8 srf_state;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index f14141b..2f0cbf8 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -44,6 +44,9 @@
static char *ht_mode_param;
static char *board_type_param;
+static bool dc2dc_param = false;
+static int n_antennas_2_param = 1;
+static int n_antennas_5_param = 1;
static const u8 wl18xx_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
@@ -487,9 +490,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
.low_band_component_type = 0x05,
.high_band_component = COMPONENT_2_WAY_SWITCH,
.high_band_component_type = 0x09,
- .number_of_assembled_ant2_4 = 0x01,
- .number_of_assembled_ant5 = 0x01,
- .external_pa_dc2dc = 0x00,
.tcxo_ldo_voltage = 0x00,
.xtal_itrim_val = 0x04,
.srf_state = 0x00,
@@ -704,10 +704,10 @@ static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
params.high_band_component_type =
phy->high_band_component_type;
params.number_of_assembled_ant2_4 =
- phy->number_of_assembled_ant2_4;
+ n_antennas_2_param;
params.number_of_assembled_ant5 =
- phy->number_of_assembled_ant5;
- params.external_pa_dc2dc = phy->external_pa_dc2dc;
+ n_antennas_5_param;
+ params.external_pa_dc2dc = dc2dc_param;
params.tcxo_ldo_voltage = phy->tcxo_ldo_voltage;
params.xtal_itrim_val = phy->xtal_itrim_val;
params.srf_state = phy->srf_state;
@@ -1105,6 +1105,15 @@ module_param_named(board_type, board_type_param, charp, S_IRUSR);
MODULE_PARM_DESC(board_type, "Board type: fpga, hdk, evb, com8 or "
"dvp (default)");
+module_param_named(dc2dc, dc2dc_param, bool, S_IRUSR);
+MODULE_PARM_DESC(dc2dc, "External DC2DC: boolean (defaults to false)");
+
+module_param_named(n_antennas_2, n_antennas_2_param, uint, 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, uint, S_IRUSR);
+MODULE_PARM_DESC(n_antennas_5, "Number of installed 5GHz antennas: 1 (default) or 2");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
In some cases it may be useful for debugging to check what is the
status of the interrupt register when a hardware recovery happens.
Print the contents of REG_INTERRUPT_NO_CLEAR (aka. HINT_STS_RAW) when
recovery starts.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 1d9c11c..ebbedbf 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -836,9 +836,11 @@ static void wl1271_recovery_work(struct work_struct *work)
/* 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",
+ 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 &&
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Currently, all HDK boards use low_band_component_type 0x06. In the
future this may change, but for now, we hardcode this value when the
board_type is set to HDK.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 5940829..f14141b 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1051,6 +1051,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
priv->board_type = BOARD_TYPE_FPGA_18XX;
} else if (!strcmp(board_type_param, "hdk")) {
priv->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->board_type = BOARD_TYPE_DVP_18XX;
} else if (!strcmp(board_type_param, "evb")) {
--
1.7.9.5
Arik Nemtsov <[email protected]> writes:
> On Thu, May 10, 2012 at 12:50 PM, Kalle Valo <[email protected]> wrote:
>> Arik Nemtsov <[email protected]> writes:
>>
>>> This series adds initial support for the 18xx chip family. The new
>>> module uses wlcore for functionality common with the 12xx family.
>>
>> You do know that sending 78 patches in one patchset is very much
>> frowned upon? No sane person (outside of wl12xx) is going to review
>> all of these.
>
> Yea I don't like it as well, but it took this amount of patches to get
> the card up and running. Posting some skeleton code seems kind of
> useless.
You can always submit patches in smaller (10-15 patches) chunks.
--
Kalle Valo
From: Luciano Coelho <[email protected]>
We were setting all the rates bits when starting the AP role. Instead
of doing this, we should set only the rates we really support
(eg. MIMO rates or wide-channel rates). This commit changes that so
that we always use the default rates (basic rates + MCS0-7) and add
the values returned by the ap_get_mimo_wide_rate_mask operation.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/cmd.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 5c47560..5b14446 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -36,6 +36,7 @@
#include "cmd.h"
#include "event.h"
#include "tx.h"
+#include "hw_ops.h"
#define WL1271_CMD_FAST_POLL_COUNT 50
@@ -500,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);
@@ -550,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:
--
1.7.9.5
From: Assaf Azulay <[email protected]>
as tcp check sum is going to be removed from firmware, and as
there is a problem with getting dns in security when checksum is
enabled, it was decided to disable it by default.
for none security modes it can be enabled by module paramenter.
Signed-off-by: Assaf Azulay <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 5053c05..dda9c18 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -47,7 +47,7 @@ static char *board_type_param = "hdk";
static bool dc2dc_param = false;
static int n_antennas_2_param = 1;
static int n_antennas_5_param = 1;
-static bool checksum_param = true;
+static bool checksum_param = false;
static bool enable_11a_param = true;
static int low_band_component = -1;
static int low_band_component_type = -1;
@@ -1252,7 +1252,7 @@ module_param_named(n_antennas_5, n_antennas_5_param, uint, S_IRUSR);
MODULE_PARM_DESC(n_antennas_5, "Number of installed 5GHz antennas: 1 (default) or 2");
module_param_named(checksum, checksum_param, bool, S_IRUSR);
-MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to true)");
+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)");
--
1.7.9.5
From: Luciano Coelho <[email protected]>
The wl18xx firmware writes the PHY firmware version in the static
data. Add an operation to parse the static data and print the PHY
firmware version when booting.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 13 +++++++++++++
drivers/net/wireless/ti/wl18xx/wl18xx.h | 6 ++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 24673e3..8262a4f 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1016,6 +1016,17 @@ static int wl18xx_debugfs_init(struct wl1271 *wl, struct dentry *rootdir)
return wl18xx_debugfs_add_files(wl, rootdir);
}
+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 struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -1037,6 +1048,7 @@ static struct wlcore_ops wl18xx_ops = {
.ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask,
.get_mac = wl18xx_get_mac,
.debugfs_init = wl18xx_debugfs_init,
+ .handle_static_data = wl18xx_handle_static_data,
};
/* HT cap appropriate for wide channels */
@@ -1092,6 +1104,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
if (ht_mode_param && !strcmp(ht_mode_param, "mimo"))
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 75abb5b..34e202b 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -56,6 +56,12 @@ struct wl18xx_fw_status_priv {
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;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
We don't have any chip-specific operations yet, but now wlcore has
defined an operations structure and requires the pointer to be set.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index cb835d9..3fa9298 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -25,6 +25,9 @@
#include "../wlcore/wlcore.h"
#include "../wlcore/debug.h"
+static struct wlcore_ops wl18xx_ops = {
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -37,6 +40,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
}
wl = hw->priv;
+ wl->ops = &wl18xx_ops;
return wlcore_probe(wl, pdev);
}
--
1.7.9.5
From: Luciano Coelho <[email protected]>
At least in PG1, the wl18xx chips use the same SDIO vendor/device ID,
so it's not possible to figure out which driver is to be used. As a
workaround, we can check the SDIO revision number, because wl18xx uses
3.00 and wl12xx does not.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/sdio.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 0a72347..1082e39 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -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>
@@ -196,6 +197,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 +238,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;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Now wlcore requires the lower drivers to set the correct
configuration. Move the existing private configuration to the proper
place and add all generic configuration parameters.
The important changes are in Tx interrupt pacing and Rx BA window size.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/conf.h | 4 +-
drivers/net/wireless/ti/wl18xx/main.c | 381 +++++++++++++++++++++++++++++--
drivers/net/wireless/ti/wl18xx/wl18xx.h | 3 +
3 files changed, 360 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index 7cd7bf1..d2b097e 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -48,9 +48,7 @@ struct wl18xx_conf_phy {
u8 secondary_clock_setting_time;
};
-struct wl18xx_conf {
- /* TODO: move the wlcore conf here? */
-
+struct wl18xx_priv_conf {
struct wl18xx_conf_phy phy;
};
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 90fccb7..fd7a803 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -153,7 +153,324 @@ enum wl18xx_hw_rates {
WL18XX_CONF_HW_RXTX_RATE_MAX,
};
-static struct wl18xx_conf wl18xx_default_conf = {
+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 = 2,
+ .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,
+ },
+ },
+ .synch_fail_thold = 10,
+ .bss_lose_timeout = 100,
+ .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 = 40,
+ .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 = false
+ },
+ .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 = 10,
+ .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 = 148,
+ .m_divider_fref_set_2 = 0xffff, /* 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,
@@ -323,42 +640,43 @@ static void wl18xx_pre_upload(struct wl1271 *wl)
static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
{
+ struct wl18xx_priv *priv = wl->priv;
+ struct wl18xx_conf_phy *phy = &priv->conf.phy;
struct wl18xx_mac_and_phy_params params;
memset(¶ms, 0, sizeof(params));
- params.phy_standalone = wl18xx_default_conf.phy.phy_standalone;
- params.rdl = wl18xx_default_conf.phy.rdl;
- params.enable_clpc = wl18xx_default_conf.phy.enable_clpc;
+ params.phy_standalone = phy->phy_standalone;
+ params.rdl = phy->rdl;
+ params.enable_clpc = phy->enable_clpc;
params.enable_tx_low_pwr_on_siso_rdl =
- wl18xx_default_conf.phy.enable_tx_low_pwr_on_siso_rdl;
- params.auto_detect = wl18xx_default_conf.phy.auto_detect;
- params.dedicated_fem = wl18xx_default_conf.phy.dedicated_fem;
- params.low_band_component = wl18xx_default_conf.phy.low_band_component;
+ phy->enable_tx_low_pwr_on_siso_rdl;
+ params.auto_detect = phy->auto_detect;
+ params.dedicated_fem = phy->dedicated_fem;
+ params.low_band_component = phy->low_band_component;
params.low_band_component_type =
- wl18xx_default_conf.phy.low_band_component_type;
- params.high_band_component =
- wl18xx_default_conf.phy.high_band_component;
+ phy->low_band_component_type;
+ params.high_band_component = phy->high_band_component;
params.high_band_component_type =
- wl18xx_default_conf.phy.high_band_component_type;
+ phy->high_band_component_type;
params.number_of_assembled_ant2_4 =
- wl18xx_default_conf.phy.number_of_assembled_ant2_4;
+ phy->number_of_assembled_ant2_4;
params.number_of_assembled_ant5 =
- wl18xx_default_conf.phy.number_of_assembled_ant5;
- params.external_pa_dc2dc = wl18xx_default_conf.phy.external_pa_dc2dc;
- params.tcxo_ldo_voltage = wl18xx_default_conf.phy.tcxo_ldo_voltage;
- params.xtal_itrim_val = wl18xx_default_conf.phy.xtal_itrim_val;
- params.srf_state = wl18xx_default_conf.phy.srf_state;
- params.io_configuration = wl18xx_default_conf.phy.io_configuration;
- params.sdio_configuration = wl18xx_default_conf.phy.sdio_configuration;
- params.settings = wl18xx_default_conf.phy.settings;
- params.rx_profile = wl18xx_default_conf.phy.rx_profile;
+ phy->number_of_assembled_ant5;
+ params.external_pa_dc2dc = phy->external_pa_dc2dc;
+ params.tcxo_ldo_voltage = phy->tcxo_ldo_voltage;
+ params.xtal_itrim_val = phy->xtal_itrim_val;
+ params.srf_state = phy->srf_state;
+ params.io_configuration = phy->io_configuration;
+ params.sdio_configuration = phy->sdio_configuration;
+ params.settings = phy->settings;
+ params.rx_profile = phy->rx_profile;
params.primary_clock_setting_time =
- wl18xx_default_conf.phy.primary_clock_setting_time;
+ phy->primary_clock_setting_time;
params.clock_valid_on_wake_up =
- wl18xx_default_conf.phy.clock_valid_on_wake_up;
+ phy->clock_valid_on_wake_up;
params.secondary_clock_setting_time =
- wl18xx_default_conf.phy.secondary_clock_setting_time;
+ phy->secondary_clock_setting_time;
/* TODO: hardcoded for now */
params.board_type = BOARD_TYPE_DVP_EVB_18XX;
@@ -544,6 +862,17 @@ static void wl18xx_set_rx_csum(struct wl1271 *wl,
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
+static void wl18xx_conf_init(struct wl1271 *wl)
+{
+ struct wl18xx_priv *priv = wl->priv;
+
+ /* 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));
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -584,6 +913,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
+ wl18xx_conf_init(wl);
+
return wlcore_probe(wl, pdev);
}
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index d24f9c0..c9bf5c6 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -22,6 +22,7 @@
#ifndef __WL18XX_PRIV_H__
#define __WL18XX_PRIV_H__
+#include "conf.h"
#define WL18XX_CMD_MAX_SIZE 740
@@ -29,6 +30,8 @@ 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;
};
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Define and add the partition table in the wlcore struct.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 35 +++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 3fa9298..f3a164a 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -28,6 +28,40 @@
static struct wlcore_ops wl18xx_ops = {
};
+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] = {
+ /* TODO: use the phy_conf struct size here */
+ .mem = { .start = 0x80926000, .size = 252 },
+ .reg = { .start = 0x00000000, .size = 0x00000000 },
+ .mem2 = { .start = 0x00000000, .size = 0x00000000 },
+ .mem3 = { .start = 0x00000000, .size = 0x00000000 },
+ },
+};
+
int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@@ -41,6 +75,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl = hw->priv;
wl->ops = &wl18xx_ops;
+ wl->ptable = wl18xx_ptable;
return wlcore_probe(wl, pdev);
}
--
1.7.9.5
Initialize the Tx spare block counts for all operating modes in the 18xx
card.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 68f5e09..70683ad 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -32,6 +32,9 @@
#include "conf.h"
#include "wl18xx.h"
+#define WL18XX_TX_HW_BLOCK_SPARE 1
+#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2
+
static struct wl18xx_conf wl18xx_default_conf = {
.phy = {
.phy_standalone = 0x00,
@@ -326,6 +329,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = 32;
+ wl->normal_tx_spare = WL18XX_TX_HW_BLOCK_SPARE;
+ wl->gem_tx_spare = WL18XX_TX_HW_GEM_BLOCK_SPARE;
return wlcore_probe(wl, pdev);
}
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Add the correct FW name for PLT (which is the same as the normal
firmware) and implement the plt_init operation.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 10 ++++++++++
drivers/net/wireless/ti/wl18xx/reg.h | 6 ++++++
2 files changed, 16 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index f892d37..5940829 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -580,6 +580,8 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
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;
@@ -958,9 +960,17 @@ static void wl18xx_conf_init(struct wl1271 *wl)
memcpy(&priv->conf, &wl18xx_default_priv_conf, sizeof(priv->conf));
}
+static int wl18xx_plt_init(struct wl1271 *wl)
+{
+ wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
+
+ return wl->ops->boot(wl);
+}
+
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,
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 1674c1a..aaedf91 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -154,6 +154,12 @@
*/
#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
+
/* TODO: maybe move elsewhere? */
#define NUM_OF_CHANNELS_11_ABG 150
#define NUM_OF_CHANNELS_11_P 7
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Instead of using hardcoded values for a single frequency, we need to
read the frequency and use the appropriate values for it in the top
initialization.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/Makefile | 2 +-
drivers/net/wireless/ti/wl18xx/io.c | 60 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/io.h | 28 +++++++++++++++
drivers/net/wireless/ti/wl18xx/main.c | 51 ++++++++++++++++++++++++--
drivers/net/wireless/ti/wl18xx/reg.h | 22 ++++++++++++
drivers/net/wireless/ti/wl18xx/wl18xx.h | 22 ++++++++++++
6 files changed, 181 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/wireless/ti/wl18xx/io.c
create mode 100644 drivers/net/wireless/ti/wl18xx/io.h
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
index 764d598..abd881f 100644
--- a/drivers/net/wireless/ti/wl18xx/Makefile
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -1,3 +1,3 @@
-wl18xx-objs = main.o acx.o tx.o
+wl18xx-objs = main.o acx.o tx.o io.o
obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c
new file mode 100644
index 0000000..598c057
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/io.c
@@ -0,0 +1,60 @@
+/*
+ * 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;
+ }
+}
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h
new file mode 100644
index 0000000..be4e126
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/io.h
@@ -0,0 +1,28 @@
+/*
+ * 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__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 0f07886..ce13249 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -37,6 +37,7 @@
#include "acx.h"
#include "tx.h"
#include "wl18xx.h"
+#include "io.h"
#define WL18XX_RX_CHECKSUM_MASK 0x40
@@ -561,6 +562,18 @@ static const int wl18xx_rtable[REG_TABLE_LEN] = {
[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"
@@ -592,15 +605,47 @@ out:
static void wl18xx_set_clk(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
+ u32 clk_freq;
/* write the translated board type to SCR_PAD2 */
wl1271_write32(wl, WL18XX_SCR_PAD2,
wl18xx_board_type_to_scrpad2[priv->board_type]);
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
- wl1271_write32(wl, 0x00A02360, 0xD0078);
- wl1271_write32(wl, 0x00A0236c, 0x12);
- wl1271_write32(wl, 0x00A02390, 0x20118);
+
+ /* 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)
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index e0170ae..1ea3393 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -107,6 +107,28 @@
#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_CMD_MBOX_ADDRESS 0xB007B4
#define WL18XX_FW_STATUS_ADDR 0x50F8
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 5bcc7f0..75abb5b 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -56,4 +56,26 @@ struct wl18xx_fw_status_priv {
u8 padding[2];
};
+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__ */
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Like HDK, COM8 uses 0x06 for the low_band_component_type as well.
Hardcode the value for COM8 until this configuration can be done in
the external configuration binary (to be implemented).
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index aa227a1..6047a6d 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1086,6 +1086,8 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
priv->board_type = BOARD_TYPE_EVB_18XX;
} else if (!strcmp(board_type_param, "com8")) {
priv->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);
wlcore_free_hw(wl);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Instead of adding more files from the lower drivers into the same
directory in debugfs as wlcore, we now add a subdirectory for the
lower driver. This makes things a bit easier, because we can quickly
see where the debugfs entry is implemented and what is specific to the
lower driver.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/debugfs.c | 10 ++++++++--
drivers/net/wireless/ti/wl12xx/main.c | 7 +------
drivers/net/wireless/ti/wl18xx/debugfs.c | 10 ++++++++--
drivers/net/wireless/ti/wl18xx/main.c | 7 +------
4 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c
index 311703d..0521cbf 100644
--- a/drivers/net/wireless/ti/wl12xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl12xx/debugfs.c
@@ -126,9 +126,15 @@ int wl12xx_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
int ret = 0;
- struct dentry *entry, *stats;
+ struct dentry *entry, *stats, *moddir;
- stats = debugfs_create_dir("wl12xx_fw_stats", rootdir);
+ 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;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 2ac8407..ba5afa4 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1360,11 +1360,6 @@ out:
return ret;
}
-static int wl12xx_debugfs_init(struct wl1271 *wl, struct dentry *rootdir)
-{
- return wl12xx_debugfs_add_files(wl, rootdir);
-}
-
static struct wlcore_ops wl12xx_ops = {
.identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw,
@@ -1387,7 +1382,7 @@ static struct wlcore_ops wl12xx_ops = {
.set_tx_desc_csum = wl12xx_set_tx_desc_csum,
.set_rx_csum = NULL,
.ap_get_mimo_wide_rate_mask = NULL,
- .debugfs_init = wl12xx_debugfs_init,
+ .debugfs_init = wl12xx_debugfs_add_files,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c
index 8354dfc..f4127bf 100644
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -181,9 +181,15 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
int ret = 0;
- struct dentry *entry, *stats;
+ struct dentry *entry, *stats, *moddir;
- stats = debugfs_create_dir("wl18xx_fw_stats", rootdir);
+ 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;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 524f44c..27cd9b8 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1022,11 +1022,6 @@ static void wl18xx_get_mac(struct wl1271 *wl)
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
}
-static int wl18xx_debugfs_init(struct wl1271 *wl, struct dentry *rootdir)
-{
- return wl18xx_debugfs_add_files(wl, rootdir);
-}
-
static int wl18xx_handle_static_data(struct wl1271 *wl,
struct wl1271_static_data *static_data)
{
@@ -1058,7 +1053,7 @@ static struct wlcore_ops wl18xx_ops = {
.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_init,
+ .debugfs_init = wl18xx_debugfs_add_files,
.handle_static_data = wl18xx_handle_static_data,
};
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Implement the operations that are necessary to fetch the
wl12xx-specific FW statistics. Re-add some of the code removed from
wlcore.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/Makefile | 2 +-
drivers/net/wireless/ti/wl12xx/acx.h | 223 ++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl12xx/debugfs.c | 236 ++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl12xx/debugfs.h | 28 ++++
drivers/net/wireless/ti/wl12xx/main.c | 8 +
5 files changed, 496 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.c
create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.h
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile
index 87f64b1..da509aa 100644
--- a/drivers/net/wireless/ti/wl12xx/Makefile
+++ b/drivers/net/wireless/ti/wl12xx/Makefile
@@ -1,3 +1,3 @@
-wl12xx-objs = main.o cmd.o acx.o
+wl12xx-objs = main.o cmd.o acx.o debugfs.o
obj-$(CONFIG_WL12XX) += wl12xx.o
diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h
index d1f5aba..1be0f2d 100644
--- a/drivers/net/wireless/ti/wl12xx/acx.h
+++ b/drivers/net/wireless/ti/wl12xx/acx.h
@@ -24,6 +24,7 @@
#define __WL12XX_ACX_H__
#include "../wlcore/wlcore.h"
+#include "../wlcore/acx.h"
struct wl1271_acx_host_config_bitmap {
struct acx_header header;
@@ -31,6 +32,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__ */
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c
new file mode 100644
index 0000000..9cc79d8
--- /dev/null
+++ b/drivers/net/wireless/ti/wl12xx/debugfs.c
@@ -0,0 +1,236 @@
+/*
+ * 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"
+
+#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;
+
+ stats = debugfs_create_dir("wl12xx_fw_stats", 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);
+
+ return 0;
+
+err:
+ if (IS_ERR(entry))
+ ret = PTR_ERR(entry);
+ else
+ ret = -ENOMEM;
+
+ return ret;
+}
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.h b/drivers/net/wireless/ti/wl12xx/debugfs.h
new file mode 100644
index 0000000..96898e2
--- /dev/null
+++ b/drivers/net/wireless/ti/wl12xx/debugfs.h
@@ -0,0 +1,28 @@
+/*
+ * 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__ */
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 82e0c6a..2ac8407 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -39,6 +39,7 @@
#include "reg.h"
#include "cmd.h"
#include "acx.h"
+#include "debugfs.h"
static char *fref_param;
static char *tcxo_param;
@@ -1359,6 +1360,11 @@ out:
return ret;
}
+static int wl12xx_debugfs_init(struct wl1271 *wl, struct dentry *rootdir)
+{
+ return wl12xx_debugfs_add_files(wl, rootdir);
+}
+
static struct wlcore_ops wl12xx_ops = {
.identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw,
@@ -1381,6 +1387,7 @@ static struct wlcore_ops wl12xx_ops = {
.set_tx_desc_csum = wl12xx_set_tx_desc_csum,
.set_rx_csum = NULL,
.ap_get_mimo_wide_rate_mask = NULL,
+ .debugfs_init = wl12xx_debugfs_init,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
@@ -1422,6 +1429,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
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;
+ wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
memcpy(&wl->ht_cap, &wl12xx_ht_cap, sizeof(wl12xx_ht_cap));
wl12xx_conf_init(wl);
--
1.7.9.5
From: Luciano Coelho <[email protected]>
We can do get the HW information and identify the chip already at
probe time. This makes it easier to mangle with the parameters during
identify chip before registering the hardware with mac80211.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 2c78057..9b8f6a2 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -962,10 +962,6 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
if (wl1271_set_block_size(wl))
wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
- ret = wl->ops->identify_chip(wl);
- if (ret < 0)
- goto out;
-
/* TODO: make sure the lower driver has set things up correctly */
ret = wl1271_setup(wl);
@@ -4871,12 +4867,6 @@ 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) {
/* NOTE: The wl->nvs->nvs element must be first, in
@@ -5281,6 +5271,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;
--
1.7.9.5
From: Luciano Coelho <[email protected]>
Implement the operations that are necessary to fetch the
wl18xx-specific FW statistics and export them in debugfs.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/debugfs.c | 1 +
drivers/net/wireless/ti/wl18xx/Makefile | 2 +-
drivers/net/wireless/ti/wl18xx/acx.h | 199 ++++++++++++++++-
drivers/net/wireless/ti/wl18xx/debugfs.c | 345 ++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/debugfs.h | 28 +++
drivers/net/wireless/ti/wl18xx/main.c | 9 +-
6 files changed, 581 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.c
create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.h
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c
index 9cc79d8..311703d 100644
--- a/drivers/net/wireless/ti/wl12xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl12xx/debugfs.c
@@ -25,6 +25,7 @@
#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)
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
index abd881f..67c0987 100644
--- a/drivers/net/wireless/ti/wl18xx/Makefile
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -1,3 +1,3 @@
-wl18xx-objs = main.o acx.o tx.o io.o
+wl18xx-objs = main.o acx.o tx.o io.o debugfs.o
obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index 544db6e..c2ccf70 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -23,6 +23,7 @@
#define __WL18XX_ACX_H__
#include "../wlcore/wlcore.h"
+#include "../wlcore/acx.h"
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
@@ -60,9 +61,205 @@ struct wl18xx_acx_checksum_state {
u8 pad[3];
} __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 tx_procs;
+ u32 prepared_descs;
+ u32 tx_xfr;
+ u32 tx_dma;
+ u32 tx_cmplt;
+ u32 rx_procs;
+ u32 rx_data;
+} __packed;
+
+struct wl18xx_acx_tx_stats {
+ 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_exch_mismatch;
+ u32 tx_done_template;
+ u32 tx_done_data;
+ u32 tx_done_int_template;
+ u32 tx_pre_xfr;
+ u32 tx_xfr;
+ u32 tx_xfr_out_of_mem;
+ u32 tx_dma_programmed;
+ u32 tx_dma_done;
+} __packed;
+
+struct wl18xx_acx_rx_stats {
+ u32 rx_out_of_mem;
+ u32 rx_hdr_overflow;
+ u32 rx_hw_stuck;
+ u32 rx_dropped_frame;
+ u32 rx_complete_dropped_frame;
+ u32 rx_alloc_frame;
+ u32 rx_done_queue;
+ u32 rx_done;
+ u32 rx_defrag;
+ u32 rx_defrag_end;
+ u32 rx_mic;
+ u32 rx_mic_end;
+ u32 rx_xfr;
+ u32 rx_xfr_end;
+ u32 rx_cmplt;
+ u32 rx_pre_complt;
+ u32 rx_cmplt_task;
+ u32 rx_phy_hdr;
+ u32 rx_timeout;
+} __packed;
+
+struct wl18xx_acx_dma_stats {
+ u32 rx_dma_errors;
+ u32 tx_dma_errors;
+} __packed;
+
+struct wl18xx_acx_isr_stats {
+ u32 irqs;
+} __packed;
+
+struct wl18xx_acx_wep_stats {
+ u32 wep_add_key_count;
+ u32 wep_default_key_count;
+ u32 wep_key_not_found;
+ u32 wep_decrypt_fail;
+ u32 wep_encrypt_fail;
+ u32 wep_dec_packets;
+ u32 wep_dec_interrupt;
+ u32 wep_enc_packets;
+ u32 wep_enc_interrupts;
+} __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_mic_stats {
+ u32 mic_rx_pkts;
+ u32 mic_calc_failure;
+} __packed;
+
+struct wl18xx_acx_aes_stats {
+ u32 aes_encrypt_fail;
+ u32 aes_decrypt_fail;
+ u32 aes_encrypt_packets;
+ u32 aes_decrypt_packets;
+ u32 aes_encrypt_interrupt;
+ u32 aes_decrypt_interrupt;
+} __packed;
+
+struct wl18xx_acx_gem_stats {
+ u32 gem_encrypt_fail;
+ u32 gem_decrypt_fail;
+ u32 gem_encrypt_packets;
+ u32 gem_decrypt_packets;
+ u32 gem_encrypt_interrupt;
+ u32 gem_decrypt_interrupt;
+} __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;
+} __packed;
+
+struct wl18xx_acx_calibration_stats {
+ u32 init_cal_total;
+ u32 init_radio_bands_fail;
+ u32 init_set_params;
+ u32 init_tx_clpc_fail;
+ u32 init_rx_iw_mm_fail;
+ u32 tune_cal_total;
+ u32 tune_drpw_rtrim_fail;
+ u32 tune_drpw_pd_buf_fail;
+ u32 tune_drpw_tx_mix_freq_fail;
+ u32 tune_drpw_ta_cal;
+ u32 tune_drpw_rx_if_2_gain;
+ u32 tune_drpw_rx_dac;
+ u32 tune_drpw_chan_tune;
+ u32 tune_drpw_rx_tx_lpf;
+ u32 tune_drpw_lna_tank;
+ u32 tune_tx_lo_leak_fail;
+ u32 tune_tx_iq_mm_fail;
+ u32 tune_tx_pdet_fail;
+ u32 tune_tx_ppa_fail;
+ u32 tune_tx_clpc_fail;
+ u32 tune_rx_ana_dc_fail;
+ u32 tune_rx_dig_dc_fail; /* check if this is needed */
+ u32 tune_rx_iq_mm_fail;
+ u32 cal_state_fail;
+} __packed;
+
+struct wl18xx_acx_statistics {
+ struct acx_header header;
+
+ struct wl18xx_acx_ring_stats ring;
+ struct wl18xx_acx_debug_stats debug;
+ struct wl18xx_acx_tx_stats tx;
+ struct wl18xx_acx_rx_stats rx;
+ struct wl18xx_acx_dma_stats dma;
+ struct wl18xx_acx_isr_stats isr;
+ struct wl18xx_acx_wep_stats wep;
+ struct wl18xx_acx_pwr_stats pwr;
+ struct wl18xx_acx_aes_stats aes;
+ struct wl18xx_acx_mic_stats mic;
+ struct wl18xx_acx_event_stats event;
+ struct wl18xx_acx_ps_poll_stats ps_poll;
+ struct wl18xx_acx_rx_filter_stats rx_filter;
+ struct wl18xx_acx_calibration_stats calibration;
+ struct wl18xx_acx_gem_stats gem;
+} __packed;
+
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);
-#endif /* __WL12XX_ACX_H__ */
+#endif /* __WL18XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c
new file mode 100644
index 0000000..8354dfc
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -0,0 +1,345 @@
+/*
+ * 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(ring, tx_procs, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, prepared_descs, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_xfr, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_dma, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, tx_cmplt, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, rx_procs, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(ring, rx_data, "%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_exch_mismatch, "%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_pre_xfr, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_xfr, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_xfr_out_of_mem, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_dma_programmed, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_dma_done, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_out_of_mem, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hdr_overflow, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hw_stuck, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_dropped_frame, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_complete_dropped_frame, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_alloc_frame, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_done_queue, "%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_mic, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_mic_end, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_xfr, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_xfr_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(dma, rx_dma_errors, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(dma, tx_dma_errors, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_add_key_count, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_default_key_count, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_key_not_found, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_decrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_encrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_dec_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_dec_interrupt, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_enc_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(wep, wep_enc_interrupts, "%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(mic, mic_rx_pkts, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(mic, mic_calc_failure, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_encrypt_interrupt, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(aes, aes_decrypt_interrupt, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_packets, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_encrypt_interrupt, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(gem, gem_decrypt_interrupt, "%u");
+
+WL18XX_DEBUGFS_FWSTATS_FILE(event, calibration, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%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(calibration, init_cal_total, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_radio_bands_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_set_params, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_tx_clpc_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, init_rx_iw_mm_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_cal_total, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rtrim_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_pd_buf_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_tx_mix_freq_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_ta_cal, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_if_2_gain, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_dac, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_chan_tune, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_rx_tx_lpf, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_drpw_lna_tank, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_lo_leak_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_iq_mm_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_pdet_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_ppa_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_tx_clpc_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_ana_dc_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_dig_dc_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, tune_rx_iq_mm_fail, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE(calibration, cal_state_fail, "%u");
+
+int wl18xx_debugfs_add_files(struct wl1271 *wl,
+ struct dentry *rootdir)
+{
+ int ret = 0;
+ struct dentry *entry, *stats;
+
+ stats = debugfs_create_dir("wl18xx_fw_stats", rootdir);
+ if (!stats || IS_ERR(stats)) {
+ entry = stats;
+ goto err;
+ }
+
+ 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(ring, tx_procs);
+ DEBUGFS_FWSTATS_ADD(ring, prepared_descs);
+ DEBUGFS_FWSTATS_ADD(ring, tx_xfr);
+ DEBUGFS_FWSTATS_ADD(ring, tx_dma);
+ DEBUGFS_FWSTATS_ADD(ring, tx_cmplt);
+ DEBUGFS_FWSTATS_ADD(ring, rx_procs);
+ DEBUGFS_FWSTATS_ADD(ring, rx_data);
+
+ 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_exch_mismatch);
+ 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_pre_xfr);
+ DEBUGFS_FWSTATS_ADD(tx, tx_xfr);
+ DEBUGFS_FWSTATS_ADD(tx, tx_xfr_out_of_mem);
+ DEBUGFS_FWSTATS_ADD(tx, tx_dma_programmed);
+ DEBUGFS_FWSTATS_ADD(tx, tx_dma_done);
+
+ DEBUGFS_FWSTATS_ADD(rx, rx_out_of_mem);
+ DEBUGFS_FWSTATS_ADD(rx, rx_hdr_overflow);
+ DEBUGFS_FWSTATS_ADD(rx, rx_hw_stuck);
+ DEBUGFS_FWSTATS_ADD(rx, rx_dropped_frame);
+ DEBUGFS_FWSTATS_ADD(rx, rx_complete_dropped_frame);
+ DEBUGFS_FWSTATS_ADD(rx, rx_alloc_frame);
+ DEBUGFS_FWSTATS_ADD(rx, rx_done_queue);
+ DEBUGFS_FWSTATS_ADD(rx, rx_done);
+ DEBUGFS_FWSTATS_ADD(rx, rx_defrag);
+ DEBUGFS_FWSTATS_ADD(rx, rx_defrag_end);
+ DEBUGFS_FWSTATS_ADD(rx, rx_mic);
+ DEBUGFS_FWSTATS_ADD(rx, rx_mic_end);
+ DEBUGFS_FWSTATS_ADD(rx, rx_xfr);
+ DEBUGFS_FWSTATS_ADD(rx, rx_xfr_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(dma, rx_dma_errors);
+ DEBUGFS_FWSTATS_ADD(dma, tx_dma_errors);
+
+ DEBUGFS_FWSTATS_ADD(isr, irqs);
+
+ DEBUGFS_FWSTATS_ADD(wep, wep_add_key_count);
+ DEBUGFS_FWSTATS_ADD(wep, wep_default_key_count);
+ DEBUGFS_FWSTATS_ADD(wep, wep_key_not_found);
+ DEBUGFS_FWSTATS_ADD(wep, wep_decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(wep, wep_encrypt_fail);
+ DEBUGFS_FWSTATS_ADD(wep, wep_dec_packets);
+ DEBUGFS_FWSTATS_ADD(wep, wep_dec_interrupt);
+ DEBUGFS_FWSTATS_ADD(wep, wep_enc_packets);
+ DEBUGFS_FWSTATS_ADD(wep, wep_enc_interrupts);
+
+ 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(mic, mic_rx_pkts);
+ DEBUGFS_FWSTATS_ADD(mic, mic_calc_failure);
+
+ DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, aes_encrypt_interrupt);
+ DEBUGFS_FWSTATS_ADD(aes, aes_decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_fail);
+ DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_packets);
+ DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_packets);
+ DEBUGFS_FWSTATS_ADD(gem, gem_encrypt_interrupt);
+ DEBUGFS_FWSTATS_ADD(gem, gem_decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_ADD(event, calibration);
+ DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
+ DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
+
+ 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(calibration, init_cal_total);
+ DEBUGFS_FWSTATS_ADD(calibration, init_radio_bands_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, init_set_params);
+ DEBUGFS_FWSTATS_ADD(calibration, init_tx_clpc_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, init_rx_iw_mm_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_cal_total);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rtrim_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_pd_buf_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_tx_mix_freq_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_ta_cal);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_if_2_gain);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_dac);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_chan_tune);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_rx_tx_lpf);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_drpw_lna_tank);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_tx_lo_leak_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_tx_iq_mm_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_tx_pdet_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_tx_ppa_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_tx_clpc_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_rx_ana_dc_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_rx_dig_dc_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, tune_rx_iq_mm_fail);
+ DEBUGFS_FWSTATS_ADD(calibration, cal_state_fail);
+
+ return 0;
+
+err:
+ if (IS_ERR(entry))
+ ret = PTR_ERR(entry);
+ else
+ ret = -ENOMEM;
+
+ return ret;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.h b/drivers/net/wireless/ti/wl18xx/debugfs.h
new file mode 100644
index 0000000..ed679be
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.h
@@ -0,0 +1,28 @@
+/*
+ * 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__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index afa2334..24673e3 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -38,7 +38,7 @@
#include "tx.h"
#include "wl18xx.h"
#include "io.h"
-
+#include "debugfs.h"
#define WL18XX_RX_CHECKSUM_MASK 0x40
@@ -1011,6 +1011,11 @@ static void wl18xx_get_mac(struct wl1271 *wl)
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
}
+static int wl18xx_debugfs_init(struct wl1271 *wl, struct dentry *rootdir)
+{
+ return wl18xx_debugfs_add_files(wl, rootdir);
+}
+
static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot,
@@ -1031,6 +1036,7 @@ static struct wlcore_ops wl18xx_ops = {
.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_init,
};
/* HT cap appropriate for wide channels */
@@ -1085,6 +1091,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
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);
memcpy(&wl->ht_cap, &wl18xx_ht_cap, sizeof(wl18xx_ht_cap));
if (ht_mode_param && !strcmp(ht_mode_param, "mimo"))
memcpy(&wl->ht_cap, &wl18xx_mimo_ht_cap,
--
1.7.9.5
From: Luciano Coelho <[email protected]>
When allocating the fw_status structure, the space for the
lower-driver private area was missing. This was causing an illegal
write outside the allocated area, which was causing random oopses
around the kernel.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 3e3dce9..2c78057 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -904,7 +904,8 @@ static void wl1271_fw_wakeup(struct wl1271 *wl)
static int wl1271_setup(struct wl1271 *wl)
{
wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
- sizeof(*wl->fw_status_2), GFP_KERNEL);
+ sizeof(*wl->fw_status_2) +
+ wl->fw_status_priv_len, GFP_KERNEL);
if (!wl->fw_status_1)
return -ENOMEM;
--
1.7.9.5
Hi Luca,
Luciano Coelho <[email protected]> writes:
> On Thu, 2012-05-10 at 12:50 +0300, Kalle Valo wrote:
>> Arik Nemtsov <[email protected]> writes:
>>
>> > This series adds initial support for the 18xx chip family. The new
>> > module uses wlcore for functionality common with the 12xx family.
>>
>> You do know that sending 78 patches in one patchset is very much
>> frowned upon? No sane person (outside of wl12xx) is going to review
>> all of these.
>
[...]
> So, unless you or someone else really disagrees, I'll apply these to the
> wl12xx.git tree.
I don't like this method of sending patches with the "take it or leave it"
attitude, because there's really no way to give any feedback to a series
of 78 patches. But I'm not going to go berserk either if you take the
patch bomb, it's really up to you.
But I can promise you that I will complain everytime I see a patch bomb
like this, and I will get louder after each iteration. And as you know,
I have a really loud voice :)
> And then I'll go find Arik to remove some of his fingernails, especially
> the one on his right hand pinky so he can't hit ENTER so quickly after
> typing git send-email. :P
Please still try to be gentle ;)
--
Kalle Valo
Make use of the wlcore provided private storage in the 18xx low-level
driver.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 6a487c8..b298e01 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -313,8 +313,9 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
struct ieee80211_hw *hw;
+ struct wl18xx_priv *priv;
- hw = wlcore_alloc_hw(0);
+ hw = wlcore_alloc_hw(sizeof(*priv));
if (IS_ERR(hw)) {
wl1271_error("can't allocate hw");
return PTR_ERR(hw);
--
1.7.9.5
Track the current 802.11 channel type, defaulting to a NO_HT channel.
Update the channel type element when changed by mac80211.
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 9 ++++++++-
drivers/net/wireless/ti/wlcore/wl12xx.h | 1 +
drivers/net/wireless/ti/wlcore/wlcore.h | 3 +++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 45fe911..3cd2ddd 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1766,6 +1766,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;
@@ -1918,6 +1919,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);
@@ -2468,11 +2470,13 @@ 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) {
/*
@@ -2592,6 +2596,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)
@@ -3703,6 +3708,7 @@ sta_not_found:
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;
@@ -5116,6 +5122,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;
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h
index f12bdf7..05e6f74 100644
--- a/drivers/net/wireless/ti/wlcore/wl12xx.h
+++ b/drivers/net/wireless/ti/wlcore/wl12xx.h
@@ -367,6 +367,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;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 2922d8a..83c43c9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -362,6 +362,9 @@ struct wl1271 {
/* RX Data filter rule state - enabled/disabled */
bool rx_filter_enabled[WL1271_MAX_RX_FILTERS];
+
+ /* the current channel type */
+ enum nl80211_channel_type channel_type;
};
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
--
1.7.9.5
On Thu, 2012-05-10 at 12:13 +0300, Arik Nemtsov wrote:
> This series adds initial support for the 18xx chip family. The new
> module uses wlcore for functionality common with the 12xx family.
>
> Arik Nemtsov (28):
> wl18xx: create per-chip-family private storage
> wl18xx: set the number of Tx descriptors
> wl18xx: set normal/GEM Tx spare block counts
> wl18xx: implement hw op for calculating hw block count per packet
> wl18xx: implement hw op for setting blocks in hw_tx_desc
> wl18xx: implement hw op for setting frame length in tx_hw_desc
> wl18xx: define HW-rate translation elements/tables
> wl18xx: add fw_status private data
> wl18xx: set Rx block-size alignment quirk
> wl18xx: implement hw op for getting rx buffer data alignment
> wl18xx: implement hw op for getting rx packet data length
> wl18xx: implement immediate Tx completion
> wlcore/wl18xx: add hw op for setting Tx HW checksum
> wlcore/wl18xx: add hw op for Rx HW checksum
> wlcore: track current channel type per vif
> wl18xx: send channel type to FW on role start
> wl18xx: ipmlement ap_rate_mask hw op
> wlcore: support peer MIMO rates
> wlcore/wl18xx: enable MIMO/wide-chan rates in AP-mode rate config
> wl18xx: set HT capabilities
> wl18xx: add module param for overriding HT caps
> wl18xx: read FW pc on recovery
> wl18xx: disable FW log functionality
> wl18xx: implement hw op to read PG version
> wl18xx: init Tx-released index to 0 on HW init
> wl18xx: don't upload NVS to FW
> wl18xx: change board type enum according to new FW
> wlcore/wl12xx/18xx: split fw_status struct into two
>
> Assaf Azulay (1):
> wl18xx: change default tcp_checksum to false
>
> Luciano Coelho (49):
> wl18xx: add new module
> wlcore_sdio/wl18xx: use SDIO revision number to identify wl18xx chips
> wl18xx: add empty operations struct
> wl18xx: add partition table
> wl18xx: add register table
> wl18xx: add identify chip operation
> wl18xx: add some boot operations and hw-specific configurations
> wl18xx: add trigger command and ack event operations
> wl18xx: add hw_init operation
> wl18xx: add runtime configuration parameters
> wl18xx: add board type module argument
> wl18xx: translate and write the board type to SCR_PAD2
> wl18xx: read clock frequency and do top init accordingly
> wlcore: rename wl12xx.h to wlcore_i.h
> wlcore/wl12xx: move ref_clock and tcxo_clock elements to wl12xx
> wlcore/wl12xx: move rx_mem_pool_addr element to wl12xx
> wlcore/wl12xx: add plt_init op and move the code to wl12xx
> wl18xx: add plt_init operation
> wl18xx: change the low_band_component_type for HDK boards
> wl18xx: add number of antennas and dc2dc type as module params
> wl18xx: add module parameter to disable TCP checksum
> wl18xx: derive the MAC address from the BD_ADDR in fuse ROM
> wl18xx: add a module parameter to control 11a support
> wlcore: add module parameter to dump SDIO reads and writes
> wl18xx: copy the default configuration before checking the board_type
> wl18xx: changed default board_type to HDK
> wlcore: add space for private area when allocating fw_status
> wl18xx: change low_band_component_type value for COM8
> wlcore: reorder identify_chip and get_hw_info
> wl18xx: disable MCS_13 for wl18xx PG 1.0
> wlcore: update beacon and probe_resp templates when rates change
> wlcore: use all AP basic rates as default
> wlcore: abstract debugfs fw_stats to be handled by the lower drivers
> wlcore: add debugfs macro to help print fw statistics arrays
> wl12xx: implement fw status debugfs entries
> wl18xx: implement fw status debugfs entries
> wlcore: create private static_data area and add operation to parse it
> wl18xx: print the PHY firmware version from the private static data
> wlcore: print the interrupt status when recovery is triggered
> wl18xx: don't use MIMO when ht_mode is set to wide
> wlcore: use proper values for supported local rates
> wl18xx: add module parameter to force SISO 20MHz
> wl18xx: add power limit reference value to mac_and_phy settings
> wl18xx: export low/high band component values as module params
> wl18xx: export pwr_limit_reference_11_abg value as a module parameter
> wlcore/wl12xx/wl18xx: move lower driver debugfs to a subdir
> wlcore: increase aggregation buffer size by one page
> wl18xx: increase tx_ba_win_size to 64
> wl18xx: use new fw stats structures
Applied and pushed this whole series to wl12xx/master.
--
Cheers,
Luca.