mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-30 07:38:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
7
drivers/net/wireless/ti/wl18xx/Kconfig
Normal file
7
drivers/net/wireless/ti/wl18xx/Kconfig
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
config WL18XX
|
||||
tristate "TI wl18xx support"
|
||||
depends on MAC80211
|
||||
select WLCORE
|
||||
---help---
|
||||
This module adds support for wireless adapters based on TI
|
||||
WiLink 8 chipsets.
|
||||
3
drivers/net/wireless/ti/wl18xx/Makefile
Normal file
3
drivers/net/wireless/ti/wl18xx/Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o cmd.o event.o
|
||||
|
||||
obj-$(CONFIG_WL18XX) += wl18xx.o
|
||||
196
drivers/net/wireless/ti/wl18xx/acx.c
Normal file
196
drivers/net/wireless/ti/wl18xx/acx.c
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../wlcore/cmd.h"
|
||||
#include "../wlcore/debug.h"
|
||||
#include "../wlcore/acx.h"
|
||||
|
||||
#include "acx.h"
|
||||
|
||||
int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
|
||||
u32 sdio_blk_size, u32 extra_mem_blks,
|
||||
u32 len_field_size)
|
||||
{
|
||||
struct wl18xx_acx_host_config_bitmap *bitmap_conf;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx cfg bitmap %d blk %d spare %d field %d",
|
||||
host_cfg_bitmap, sdio_blk_size, extra_mem_blks,
|
||||
len_field_size);
|
||||
|
||||
bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
|
||||
if (!bitmap_conf) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
|
||||
bitmap_conf->host_sdio_block_size = cpu_to_le32(sdio_blk_size);
|
||||
bitmap_conf->extra_mem_blocks = cpu_to_le32(extra_mem_blks);
|
||||
bitmap_conf->length_field_size = cpu_to_le32(len_field_size);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
|
||||
bitmap_conf, sizeof(*bitmap_conf));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(bitmap_conf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_acx_set_checksum_state(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_acx_checksum_state *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx checksum state");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->checksum_state = CHECKSUM_OFFLOAD_ENABLED;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_CSUM_CONFIG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to set Tx checksum state: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_acx_clear_statistics(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_acx_clear_statistics *acx;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx clear statistics");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_CLEAR_STATISTICS, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to clear firmware statistics: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide)
|
||||
{
|
||||
struct wlcore_peer_ht_operation_mode *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx peer ht operation mode hlid %d bw %d",
|
||||
hlid, wide);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->hlid = hlid;
|
||||
acx->bandwidth = wide ? WLCORE_BANDWIDTH_40MHZ : WLCORE_BANDWIDTH_20MHZ;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_OPERATION_MODE_CFG, acx,
|
||||
sizeof(*acx));
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx peer ht operation mode failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* this command is basically the same as wl1271_acx_ht_capabilities,
|
||||
* with the addition of supported rates. they should be unified in
|
||||
* the next fw api change
|
||||
*/
|
||||
int wl18xx_acx_set_peer_cap(struct wl1271 *wl,
|
||||
struct ieee80211_sta_ht_cap *ht_cap,
|
||||
bool allow_ht_operation,
|
||||
u32 rate_set, u8 hlid)
|
||||
{
|
||||
struct wlcore_acx_peer_cap *acx;
|
||||
int ret = 0;
|
||||
u32 ht_capabilites = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX,
|
||||
"acx set cap ht_supp: %d ht_cap: %d rates: 0x%x",
|
||||
ht_cap->ht_supported, ht_cap->cap, rate_set);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (allow_ht_operation && ht_cap->ht_supported) {
|
||||
/* no need to translate capabilities - use the spec values */
|
||||
ht_capabilites = ht_cap->cap;
|
||||
|
||||
/*
|
||||
* this bit is not employed by the spec but only by FW to
|
||||
* indicate peer HT support
|
||||
*/
|
||||
ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
|
||||
|
||||
/* get data from A-MPDU parameters field */
|
||||
acx->ampdu_max_length = ht_cap->ampdu_factor;
|
||||
acx->ampdu_min_spacing = ht_cap->ampdu_density;
|
||||
}
|
||||
|
||||
acx->hlid = hlid;
|
||||
acx->ht_capabilites = cpu_to_le32(ht_capabilites);
|
||||
acx->supported_rates = cpu_to_le32(rate_set);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_PEER_CAP, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ht capabilities setting failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
340
drivers/net/wireless/ti/wl18xx/acx.h
Normal file
340
drivers/net/wireless/ti/wl18xx/acx.h
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL18XX_ACX_H__
|
||||
#define __WL18XX_ACX_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
#include "../wlcore/acx.h"
|
||||
|
||||
enum {
|
||||
ACX_NS_IPV6_FILTER = 0x0050,
|
||||
ACX_PEER_HT_OPERATION_MODE_CFG = 0x0051,
|
||||
ACX_CSUM_CONFIG = 0x0052,
|
||||
ACX_SIM_CONFIG = 0x0053,
|
||||
ACX_CLEAR_STATISTICS = 0x0054,
|
||||
ACX_AUTO_RX_STREAMING = 0x0055,
|
||||
ACX_PEER_CAP = 0x0056
|
||||
};
|
||||
|
||||
/* numbers of bits the length field takes (add 1 for the actual number) */
|
||||
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
|
||||
|
||||
#define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
|
||||
WL1271_ACX_INTR_INIT_COMPLETE | \
|
||||
WL1271_ACX_INTR_EVENT_A | \
|
||||
WL1271_ACX_INTR_EVENT_B | \
|
||||
WL1271_ACX_INTR_CMD_COMPLETE | \
|
||||
WL1271_ACX_INTR_HW_AVAILABLE | \
|
||||
WL1271_ACX_INTR_DATA | \
|
||||
WL1271_ACX_SW_INTR_WATCHDOG)
|
||||
|
||||
#define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
|
||||
WL1271_ACX_INTR_EVENT_A | \
|
||||
WL1271_ACX_INTR_EVENT_B | \
|
||||
WL1271_ACX_INTR_HW_AVAILABLE | \
|
||||
WL1271_ACX_INTR_DATA | \
|
||||
WL1271_ACX_SW_INTR_WATCHDOG)
|
||||
|
||||
struct wl18xx_acx_host_config_bitmap {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 host_cfg_bitmap;
|
||||
|
||||
__le32 host_sdio_block_size;
|
||||
|
||||
/* extra mem blocks per frame in TX. */
|
||||
__le32 extra_mem_blocks;
|
||||
|
||||
/*
|
||||
* number of bits of the length field in the first TX word
|
||||
* (up to 15 - for using the entire 16 bits).
|
||||
*/
|
||||
__le32 length_field_size;
|
||||
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
CHECKSUM_OFFLOAD_DISABLED = 0,
|
||||
CHECKSUM_OFFLOAD_ENABLED = 1,
|
||||
CHECKSUM_OFFLOAD_FAKE_RX = 2,
|
||||
CHECKSUM_OFFLOAD_INVALID = 0xFF
|
||||
};
|
||||
|
||||
struct wl18xx_acx_checksum_state {
|
||||
struct acx_header header;
|
||||
|
||||
/* enum acx_checksum_state */
|
||||
u8 checksum_state;
|
||||
u8 pad[3];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct wl18xx_acx_error_stats {
|
||||
u32 error_frame;
|
||||
u32 error_null_Frame_tx_start;
|
||||
u32 error_numll_frame_cts_start;
|
||||
u32 error_bar_retry;
|
||||
u32 error_frame_cts_nul_flid;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_debug_stats {
|
||||
u32 debug1;
|
||||
u32 debug2;
|
||||
u32 debug3;
|
||||
u32 debug4;
|
||||
u32 debug5;
|
||||
u32 debug6;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_ring_stats {
|
||||
u32 prepared_descs;
|
||||
u32 tx_cmplt;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_tx_stats {
|
||||
u32 tx_prepared_descs;
|
||||
u32 tx_cmplt;
|
||||
u32 tx_template_prepared;
|
||||
u32 tx_data_prepared;
|
||||
u32 tx_template_programmed;
|
||||
u32 tx_data_programmed;
|
||||
u32 tx_burst_programmed;
|
||||
u32 tx_starts;
|
||||
u32 tx_imm_resp;
|
||||
u32 tx_start_templates;
|
||||
u32 tx_start_int_templates;
|
||||
u32 tx_start_fw_gen;
|
||||
u32 tx_start_data;
|
||||
u32 tx_start_null_frame;
|
||||
u32 tx_exch;
|
||||
u32 tx_retry_template;
|
||||
u32 tx_retry_data;
|
||||
u32 tx_exch_pending;
|
||||
u32 tx_exch_expiry;
|
||||
u32 tx_done_template;
|
||||
u32 tx_done_data;
|
||||
u32 tx_done_int_template;
|
||||
u32 tx_frame_checksum;
|
||||
u32 tx_checksum_result;
|
||||
u32 frag_called;
|
||||
u32 frag_mpdu_alloc_failed;
|
||||
u32 frag_init_called;
|
||||
u32 frag_in_process_called;
|
||||
u32 frag_tkip_called;
|
||||
u32 frag_key_not_found;
|
||||
u32 frag_need_fragmentation;
|
||||
u32 frag_bad_mblk_num;
|
||||
u32 frag_failed;
|
||||
u32 frag_cache_hit;
|
||||
u32 frag_cache_miss;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_rx_stats {
|
||||
u32 rx_beacon_early_term;
|
||||
u32 rx_out_of_mpdu_nodes;
|
||||
u32 rx_hdr_overflow;
|
||||
u32 rx_dropped_frame;
|
||||
u32 rx_done_stage;
|
||||
u32 rx_done;
|
||||
u32 rx_defrag;
|
||||
u32 rx_defrag_end;
|
||||
u32 rx_cmplt;
|
||||
u32 rx_pre_complt;
|
||||
u32 rx_cmplt_task;
|
||||
u32 rx_phy_hdr;
|
||||
u32 rx_timeout;
|
||||
u32 rx_timeout_wa;
|
||||
u32 rx_wa_density_dropped_frame;
|
||||
u32 rx_wa_ba_not_expected;
|
||||
u32 rx_frame_checksum;
|
||||
u32 rx_checksum_result;
|
||||
u32 defrag_called;
|
||||
u32 defrag_init_called;
|
||||
u32 defrag_in_process_called;
|
||||
u32 defrag_tkip_called;
|
||||
u32 defrag_need_defrag;
|
||||
u32 defrag_decrypt_failed;
|
||||
u32 decrypt_key_not_found;
|
||||
u32 defrag_need_decrypt;
|
||||
u32 rx_tkip_replays;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_isr_stats {
|
||||
u32 irqs;
|
||||
} __packed;
|
||||
|
||||
#define PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD 10
|
||||
|
||||
struct wl18xx_acx_pwr_stats {
|
||||
u32 missing_bcns_cnt;
|
||||
u32 rcvd_bcns_cnt;
|
||||
u32 connection_out_of_sync;
|
||||
u32 cont_miss_bcns_spread[PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD];
|
||||
u32 rcvd_awake_bcns_cnt;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_event_stats {
|
||||
u32 calibration;
|
||||
u32 rx_mismatch;
|
||||
u32 rx_mem_empty;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_ps_poll_stats {
|
||||
u32 ps_poll_timeouts;
|
||||
u32 upsd_timeouts;
|
||||
u32 upsd_max_ap_turn;
|
||||
u32 ps_poll_max_ap_turn;
|
||||
u32 ps_poll_utilization;
|
||||
u32 upsd_utilization;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_rx_filter_stats {
|
||||
u32 beacon_filter;
|
||||
u32 arp_filter;
|
||||
u32 mc_filter;
|
||||
u32 dup_filter;
|
||||
u32 data_filter;
|
||||
u32 ibss_filter;
|
||||
u32 protection_filter;
|
||||
u32 accum_arp_pend_requests;
|
||||
u32 max_arp_queue_dep;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_rx_rate_stats {
|
||||
u32 rx_frames_per_rates[50];
|
||||
} __packed;
|
||||
|
||||
#define AGGR_STATS_TX_AGG 16
|
||||
#define AGGR_STATS_TX_RATE 16
|
||||
#define AGGR_STATS_RX_SIZE_LEN 16
|
||||
|
||||
struct wl18xx_acx_aggr_stats {
|
||||
u32 tx_agg_vs_rate[AGGR_STATS_TX_AGG * AGGR_STATS_TX_RATE];
|
||||
u32 rx_size[AGGR_STATS_RX_SIZE_LEN];
|
||||
} __packed;
|
||||
|
||||
#define PIPE_STATS_HW_FIFO 11
|
||||
|
||||
struct wl18xx_acx_pipeline_stats {
|
||||
u32 hs_tx_stat_fifo_int;
|
||||
u32 hs_rx_stat_fifo_int;
|
||||
u32 tcp_tx_stat_fifo_int;
|
||||
u32 tcp_rx_stat_fifo_int;
|
||||
u32 enc_tx_stat_fifo_int;
|
||||
u32 enc_rx_stat_fifo_int;
|
||||
u32 rx_complete_stat_fifo_int;
|
||||
u32 pre_proc_swi;
|
||||
u32 post_proc_swi;
|
||||
u32 sec_frag_swi;
|
||||
u32 pre_to_defrag_swi;
|
||||
u32 defrag_to_csum_swi;
|
||||
u32 csum_to_rx_xfer_swi;
|
||||
u32 dec_packet_in;
|
||||
u32 dec_packet_in_fifo_full;
|
||||
u32 dec_packet_out;
|
||||
u32 cs_rx_packet_in;
|
||||
u32 cs_rx_packet_out;
|
||||
u16 pipeline_fifo_full[PIPE_STATS_HW_FIFO];
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_mem_stats {
|
||||
u32 rx_free_mem_blks;
|
||||
u32 tx_free_mem_blks;
|
||||
u32 fwlog_free_mem_blks;
|
||||
u32 fw_gen_free_mem_blks;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_statistics {
|
||||
struct acx_header header;
|
||||
|
||||
struct wl18xx_acx_error_stats error;
|
||||
struct wl18xx_acx_debug_stats debug;
|
||||
struct wl18xx_acx_tx_stats tx;
|
||||
struct wl18xx_acx_rx_stats rx;
|
||||
struct wl18xx_acx_isr_stats isr;
|
||||
struct wl18xx_acx_pwr_stats pwr;
|
||||
struct wl18xx_acx_ps_poll_stats ps_poll;
|
||||
struct wl18xx_acx_rx_filter_stats rx_filter;
|
||||
struct wl18xx_acx_rx_rate_stats rx_rate;
|
||||
struct wl18xx_acx_aggr_stats aggr_size;
|
||||
struct wl18xx_acx_pipeline_stats pipeline;
|
||||
struct wl18xx_acx_mem_stats mem;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_acx_clear_statistics {
|
||||
struct acx_header header;
|
||||
};
|
||||
|
||||
enum wlcore_bandwidth {
|
||||
WLCORE_BANDWIDTH_20MHZ,
|
||||
WLCORE_BANDWIDTH_40MHZ,
|
||||
};
|
||||
|
||||
struct wlcore_peer_ht_operation_mode {
|
||||
struct acx_header header;
|
||||
|
||||
u8 hlid;
|
||||
u8 bandwidth; /* enum wlcore_bandwidth */
|
||||
u8 padding[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* ACX_PEER_CAP
|
||||
* this struct is very similar to wl1271_acx_ht_capabilities, with the
|
||||
* addition of supported rates
|
||||
*/
|
||||
struct wlcore_acx_peer_cap {
|
||||
struct acx_header header;
|
||||
|
||||
/* bitmask of capability bits supported by the peer */
|
||||
__le32 ht_capabilites;
|
||||
|
||||
/* rates supported by the remote peer */
|
||||
__le32 supported_rates;
|
||||
|
||||
/* Indicates to which link these capabilities apply. */
|
||||
u8 hlid;
|
||||
|
||||
/*
|
||||
* This the maximum A-MPDU length supported by the AP. The FW may not
|
||||
* exceed this length when sending A-MPDUs
|
||||
*/
|
||||
u8 ampdu_max_length;
|
||||
|
||||
/* This is the minimal spacing required when sending A-MPDUs to the AP*/
|
||||
u8 ampdu_min_spacing;
|
||||
|
||||
u8 padding;
|
||||
} __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);
|
||||
int wl18xx_acx_clear_statistics(struct wl1271 *wl);
|
||||
int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide);
|
||||
int wl18xx_acx_set_peer_cap(struct wl1271 *wl,
|
||||
struct ieee80211_sta_ht_cap *ht_cap,
|
||||
bool allow_ht_operation,
|
||||
u32 rate_set, u8 hlid);
|
||||
|
||||
#endif /* __WL18XX_ACX_H__ */
|
||||
169
drivers/net/wireless/ti/wl18xx/cmd.c
Normal file
169
drivers/net/wireless/ti/wl18xx/cmd.c
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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/hw_ops.h"
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct wl18xx_cmd_channel_switch *cmd;
|
||||
u32 supported_rates;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "cmd channel switch");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
cmd->channel = ch_switch->chandef.chan->hw_value;
|
||||
cmd->switch_time = ch_switch->count;
|
||||
cmd->stop_tx = ch_switch->block_tx;
|
||||
|
||||
switch (ch_switch->chandef.chan->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
cmd->band = WLCORE_BAND_2_4GHZ;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
cmd->band = WLCORE_BAND_5GHZ;
|
||||
break;
|
||||
default:
|
||||
wl1271_error("invalid channel switch band: %d",
|
||||
ch_switch->chandef.chan->band);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES |
|
||||
wlcore_hw_sta_get_ap_rate_mask(wl, wlvif);
|
||||
if (wlvif->p2p)
|
||||
supported_rates &= ~CONF_TX_CCK_RATES;
|
||||
cmd->local_supported_rates = cpu_to_le32(supported_rates);
|
||||
cmd->channel_type = wlvif->channel_type;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send channel switch command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
|
||||
{
|
||||
struct wl18xx_cmd_smart_config_start *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x",
|
||||
group_bitmap);
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->group_id_bitmask = cpu_to_le32(group_bitmap);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send smart config start command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_cmd_smart_config_stop(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_cmd_header *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd smart config stop");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send smart config stop command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
|
||||
u8 key_len, u8 *key)
|
||||
{
|
||||
struct wl18xx_cmd_smart_config_set_group_key *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x",
|
||||
group_id);
|
||||
|
||||
if (key_len != sizeof(cmd->key)) {
|
||||
wl1271_error("invalid group key size: %d", key_len);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->group_id = cpu_to_le32(group_id);
|
||||
memcpy(cmd->key, key, key_len);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd,
|
||||
sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send smart config set group key cmd");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
69
drivers/net/wireless/ti/wl18xx/cmd.h
Normal file
69
drivers/net/wireless/ti/wl18xx/cmd.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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_CMD_H__
|
||||
#define __WL18XX_CMD_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
#include "../wlcore/acx.h"
|
||||
|
||||
struct wl18xx_cmd_channel_switch {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 role_id;
|
||||
|
||||
/* The new serving channel */
|
||||
u8 channel;
|
||||
/* Relative time of the serving channel switch in TBTT units */
|
||||
u8 switch_time;
|
||||
/* Stop the role TX, should expect it after radar detection */
|
||||
u8 stop_tx;
|
||||
|
||||
__le32 local_supported_rates;
|
||||
|
||||
u8 channel_type;
|
||||
u8 band;
|
||||
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_cmd_smart_config_start {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
__le32 group_id_bitmask;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_cmd_smart_config_set_group_key {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
__le32 group_id;
|
||||
|
||||
u8 key[16];
|
||||
} __packed;
|
||||
|
||||
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap);
|
||||
int wl18xx_cmd_smart_config_stop(struct wl1271 *wl);
|
||||
int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
|
||||
u8 key_len, u8 *key);
|
||||
#endif
|
||||
121
drivers/net/wireless/ti/wl18xx/conf.h
Normal file
121
drivers/net/wireless/ti/wl18xx/conf.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL18XX_CONF_H__
|
||||
#define __WL18XX_CONF_H__
|
||||
|
||||
#define WL18XX_CONF_MAGIC 0x10e100ca
|
||||
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0006)
|
||||
#define WL18XX_CONF_MASK 0x0000ffff
|
||||
#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
|
||||
sizeof(struct wl18xx_priv_conf))
|
||||
|
||||
#define NUM_OF_CHANNELS_11_ABG 150
|
||||
#define NUM_OF_CHANNELS_11_P 7
|
||||
#define SRF_TABLE_LEN 16
|
||||
#define PIN_MUXING_SIZE 2
|
||||
#define WL18XX_TRACE_LOSS_GAPS_TX 10
|
||||
#define WL18XX_TRACE_LOSS_GAPS_RX 18
|
||||
|
||||
struct wl18xx_mac_and_phy_params {
|
||||
u8 phy_standalone;
|
||||
u8 spare0;
|
||||
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 spare1;
|
||||
u8 per_chan_bo_mode_11_abg[13];
|
||||
u8 per_chan_bo_mode_11_p[4];
|
||||
u8 primary_clock_setting_time;
|
||||
u8 clock_valid_on_wake_up;
|
||||
u8 secondary_clock_setting_time;
|
||||
u8 board_type;
|
||||
/* enable point saturation */
|
||||
u8 psat;
|
||||
/* low/medium/high Tx power in dBm for STA-HP BG */
|
||||
s8 low_power_val;
|
||||
s8 med_power_val;
|
||||
s8 high_power_val;
|
||||
s8 per_sub_band_tx_trace_loss[WL18XX_TRACE_LOSS_GAPS_TX];
|
||||
s8 per_sub_band_rx_trace_loss[WL18XX_TRACE_LOSS_GAPS_RX];
|
||||
u8 tx_rf_margin;
|
||||
/* low/medium/high Tx power in dBm for other role */
|
||||
s8 low_power_val_2nd;
|
||||
s8 med_power_val_2nd;
|
||||
s8 high_power_val_2nd;
|
||||
|
||||
u8 padding[1];
|
||||
} __packed;
|
||||
|
||||
enum wl18xx_ht_mode {
|
||||
/* Default - use MIMO, fallback to SISO20 */
|
||||
HT_MODE_DEFAULT = 0,
|
||||
|
||||
/* Wide - use SISO40 */
|
||||
HT_MODE_WIDE = 1,
|
||||
|
||||
/* Use SISO20 */
|
||||
HT_MODE_SISO20 = 2,
|
||||
};
|
||||
|
||||
struct wl18xx_ht_settings {
|
||||
/* DEFAULT / WIDE / SISO20 */
|
||||
u8 mode;
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_priv_conf {
|
||||
/* Module params structures */
|
||||
struct wl18xx_ht_settings ht;
|
||||
|
||||
/* this structure is copied wholesale to FW */
|
||||
struct wl18xx_mac_and_phy_params phy;
|
||||
} __packed;
|
||||
|
||||
#endif /* __WL18XX_CONF_H__ */
|
||||
403
drivers/net/wireless/ti/wl18xx/debugfs.c
Normal file
403
drivers/net/wireless/ti/wl18xx/debugfs.c
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Copyright (C) 2011-2012 Texas Instruments
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../wlcore/debugfs.h"
|
||||
#include "../wlcore/wlcore.h"
|
||||
|
||||
#include "wl18xx.h"
|
||||
#include "acx.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
#define WL18XX_DEBUGFS_FWSTATS_FILE(a, b, c) \
|
||||
DEBUGFS_FWSTATS_FILE(a, b, c, wl18xx_acx_statistics)
|
||||
#define WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c) \
|
||||
DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c, wl18xx_acx_statistics)
|
||||
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug1, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug2, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug3, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug4, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug5, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug6, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(error, error_null_Frame_tx_start, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(error, error_numll_frame_cts_start, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(error, error_bar_retry, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame_cts_nul_flid, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_prepared_descs, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_cmplt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_prepared, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_prepared, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_programmed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_programmed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_burst_programmed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_starts, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_imm_resp, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_templates, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_int_templates, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_fw_gen, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_data, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_null_frame, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_template, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_data, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_pending, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_expiry, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_template, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_data, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_int_template, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_frame_checksum, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_checksum_result, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_mpdu_alloc_failed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_init_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_in_process_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_tkip_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_key_not_found, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_need_fragmentation, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_bad_mblk_num, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_failed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_hit, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_miss, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_beacon_early_term, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_out_of_mpdu_nodes, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hdr_overflow, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_dropped_frame, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_done, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag_end, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_pre_complt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt_task, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_phy_hdr, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout_wa, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_density_dropped_frame, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_ba_not_expected, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_frame_checksum, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_checksum_result, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_init_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_in_process_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_tkip_called, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_defrag, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_decrypt_failed, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, decrypt_key_not_found, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_decrypt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_tkip_replays, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pwr, missing_bcns_cnt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_bcns_cnt, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pwr, connection_out_of_sync, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pwr, cont_miss_bcns_spread,
|
||||
PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD);
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_bcns_cnt, "%u");
|
||||
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_timeouts, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_timeouts, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_max_ap_turn, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_max_ap_turn, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_utilization, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_utilization, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, beacon_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, arp_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, mc_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, dup_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, data_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, ibss_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50);
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate,
|
||||
AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE);
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, rx_size,
|
||||
AGGR_STATS_RX_SIZE_LEN);
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, hs_tx_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_tx_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_rx_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_tx_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_rx_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, rx_complete_stat_fifo_int, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_proc_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, post_proc_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, sec_frag_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_to_defrag_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, defrag_to_csum_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, csum_to_rx_xfer_swi, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in_fifo_full, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_out, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_in, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_out, "%u");
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pipeline, pipeline_fifo_full,
|
||||
PIPE_STATS_HW_FIFO);
|
||||
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(mem, rx_free_mem_blks, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(mem, tx_free_mem_blks, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(mem, fwlog_free_mem_blks, "%u");
|
||||
WL18XX_DEBUGFS_FWSTATS_FILE(mem, fw_gen_free_mem_blks, "%u");
|
||||
|
||||
static ssize_t conf_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
struct wlcore_conf_header header;
|
||||
char *buf, *pos;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = WL18XX_CONF_SIZE;
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
header.magic = cpu_to_le32(WL18XX_CONF_MAGIC);
|
||||
header.version = cpu_to_le32(WL18XX_CONF_VERSION);
|
||||
header.checksum = 0;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
pos = buf;
|
||||
memcpy(pos, &header, sizeof(header));
|
||||
pos += sizeof(header);
|
||||
memcpy(pos, &wl->conf, sizeof(wl->conf));
|
||||
pos += sizeof(wl->conf);
|
||||
memcpy(pos, &priv->conf, sizeof(priv->conf));
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations conf_ops = {
|
||||
.read = conf_read,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t clear_fw_stats_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl18xx_acx_clear_statistics(wl);
|
||||
if (ret < 0) {
|
||||
count = ret;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations clear_fw_stats_ops = {
|
||||
.write = clear_fw_stats_write,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int wl18xx_debugfs_add_files(struct wl1271 *wl,
|
||||
struct dentry *rootdir)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dentry *entry, *stats, *moddir;
|
||||
|
||||
moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir);
|
||||
if (!moddir || IS_ERR(moddir)) {
|
||||
entry = moddir;
|
||||
goto err;
|
||||
}
|
||||
|
||||
stats = debugfs_create_dir("fw_stats", moddir);
|
||||
if (!stats || IS_ERR(stats)) {
|
||||
entry = stats;
|
||||
goto err;
|
||||
}
|
||||
|
||||
DEBUGFS_ADD(clear_fw_stats, stats);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug1);
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug2);
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug3);
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug4);
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug5);
|
||||
DEBUGFS_FWSTATS_ADD(debug, debug6);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(error, error_frame);
|
||||
DEBUGFS_FWSTATS_ADD(error, error_null_Frame_tx_start);
|
||||
DEBUGFS_FWSTATS_ADD(error, error_numll_frame_cts_start);
|
||||
DEBUGFS_FWSTATS_ADD(error, error_bar_retry);
|
||||
DEBUGFS_FWSTATS_ADD(error, error_frame_cts_nul_flid);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_prepared_descs);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_cmplt);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_template_prepared);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_data_prepared);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_template_programmed);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_data_programmed);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_burst_programmed);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_starts);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_imm_resp);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_start_templates);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_start_int_templates);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_start_fw_gen);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_start_data);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_start_null_frame);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_exch);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_retry_template);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_retry_data);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_exch_pending);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_exch_expiry);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_done_template);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_done_data);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_done_int_template);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_frame_checksum);
|
||||
DEBUGFS_FWSTATS_ADD(tx, tx_checksum_result);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_called);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_mpdu_alloc_failed);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_init_called);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_in_process_called);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_tkip_called);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_key_not_found);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_need_fragmentation);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_bad_mblk_num);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_failed);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_cache_hit);
|
||||
DEBUGFS_FWSTATS_ADD(tx, frag_cache_miss);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_beacon_early_term);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_out_of_mpdu_nodes);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_hdr_overflow);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_dropped_frame);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_done);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_defrag);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_defrag_end);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_cmplt);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_pre_complt);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_cmplt_task);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_phy_hdr);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_timeout);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_timeout_wa);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_wa_density_dropped_frame);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_wa_ba_not_expected);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_frame_checksum);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_checksum_result);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_called);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_init_called);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_in_process_called);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_tkip_called);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_need_defrag);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_decrypt_failed);
|
||||
DEBUGFS_FWSTATS_ADD(rx, decrypt_key_not_found);
|
||||
DEBUGFS_FWSTATS_ADD(rx, defrag_need_decrypt);
|
||||
DEBUGFS_FWSTATS_ADD(rx, rx_tkip_replays);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(isr, irqs);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(pwr, missing_bcns_cnt);
|
||||
DEBUGFS_FWSTATS_ADD(pwr, rcvd_bcns_cnt);
|
||||
DEBUGFS_FWSTATS_ADD(pwr, connection_out_of_sync);
|
||||
DEBUGFS_FWSTATS_ADD(pwr, cont_miss_bcns_spread);
|
||||
DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_bcns_cnt);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_timeouts);
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, upsd_timeouts);
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, upsd_max_ap_turn);
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_max_ap_turn);
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_utilization);
|
||||
DEBUGFS_FWSTATS_ADD(ps_poll, upsd_utilization);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, beacon_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, arp_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, mc_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, dup_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, data_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, ibss_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, protection_filter);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, accum_arp_pend_requests);
|
||||
DEBUGFS_FWSTATS_ADD(rx_filter, max_arp_queue_dep);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(rx_rate, rx_frames_per_rates);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(aggr_size, tx_agg_vs_rate);
|
||||
DEBUGFS_FWSTATS_ADD(aggr_size, rx_size);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, hs_tx_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, tcp_tx_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, tcp_rx_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, enc_tx_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, enc_rx_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, rx_complete_stat_fifo_int);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, pre_proc_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, post_proc_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, sec_frag_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, pre_to_defrag_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, defrag_to_csum_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, csum_to_rx_xfer_swi);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in_fifo_full);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_out);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_in);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_out);
|
||||
DEBUGFS_FWSTATS_ADD(pipeline, pipeline_fifo_full);
|
||||
|
||||
DEBUGFS_FWSTATS_ADD(mem, rx_free_mem_blks);
|
||||
DEBUGFS_FWSTATS_ADD(mem, tx_free_mem_blks);
|
||||
DEBUGFS_FWSTATS_ADD(mem, fwlog_free_mem_blks);
|
||||
DEBUGFS_FWSTATS_ADD(mem, fw_gen_free_mem_blks);
|
||||
|
||||
DEBUGFS_ADD(conf, moddir);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (IS_ERR(entry))
|
||||
ret = PTR_ERR(entry);
|
||||
else
|
||||
ret = -ENOMEM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
28
drivers/net/wireless/ti/wl18xx/debugfs.h
Normal file
28
drivers/net/wireless/ti/wl18xx/debugfs.h
Normal file
|
|
@ -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__ */
|
||||
176
drivers/net/wireless/ti/wl18xx/event.c
Normal file
176
drivers/net/wireless/ti/wl18xx/event.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <net/genetlink.h>
|
||||
#include "event.h"
|
||||
#include "scan.h"
|
||||
#include "../wlcore/cmd.h"
|
||||
#include "../wlcore/debug.h"
|
||||
#include "../wlcore/vendor_cmd.h"
|
||||
|
||||
int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
|
||||
bool *timeout)
|
||||
{
|
||||
u32 local_event;
|
||||
|
||||
switch (event) {
|
||||
case WLCORE_EVENT_PEER_REMOVE_COMPLETE:
|
||||
local_event = PEER_REMOVE_COMPLETE_EVENT_ID;
|
||||
break;
|
||||
|
||||
case WLCORE_EVENT_DFS_CONFIG_COMPLETE:
|
||||
local_event = DFS_CHANNELS_CONFIG_COMPLETE_EVENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* event not implemented */
|
||||
return 0;
|
||||
}
|
||||
return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
|
||||
}
|
||||
|
||||
static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel,
|
||||
u8 sync_band)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
enum ieee80211_band band;
|
||||
int freq;
|
||||
|
||||
if (sync_band == WLCORE_BAND_5GHZ)
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
else
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
freq = ieee80211_channel_to_frequency(sync_channel, band);
|
||||
|
||||
wl1271_debug(DEBUG_EVENT,
|
||||
"SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)",
|
||||
freq, sync_channel, sync_band);
|
||||
skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, 20,
|
||||
WLCORE_VENDOR_EVENT_SC_SYNC,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) {
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
cfg80211_vendor_event(skb, GFP_KERNEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wlcore_smart_config_decode_event(struct wl1271 *wl,
|
||||
u8 ssid_len, u8 *ssid,
|
||||
u8 pwd_len, u8 *pwd)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID");
|
||||
wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len);
|
||||
|
||||
skb = cfg80211_vendor_event_alloc(wl->hw->wiphy,
|
||||
ssid_len + pwd_len + 20,
|
||||
WLCORE_VENDOR_EVENT_SC_DECODE,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) ||
|
||||
nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) {
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
cfg80211_vendor_event(skb, GFP_KERNEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl18xx_process_mailbox_events(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_event_mailbox *mbox = wl->mbox;
|
||||
u32 vector;
|
||||
|
||||
vector = le32_to_cpu(mbox->events_vector);
|
||||
wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector);
|
||||
|
||||
if (vector & SCAN_COMPLETE_EVENT_ID) {
|
||||
wl1271_debug(DEBUG_EVENT, "scan results: %d",
|
||||
mbox->number_of_scan_results);
|
||||
|
||||
if (wl->scan_wlvif)
|
||||
wl18xx_scan_completed(wl, wl->scan_wlvif);
|
||||
}
|
||||
|
||||
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
|
||||
wl1271_debug(DEBUG_EVENT,
|
||||
"PERIODIC_SCAN_REPORT_EVENT (results %d)",
|
||||
mbox->number_of_sched_scan_results);
|
||||
|
||||
wlcore_scan_sched_scan_results(wl);
|
||||
}
|
||||
|
||||
if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID)
|
||||
wlcore_event_sched_scan_completed(wl, 1);
|
||||
|
||||
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID)
|
||||
wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric);
|
||||
|
||||
if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)
|
||||
wlcore_event_ba_rx_constraint(wl,
|
||||
le16_to_cpu(mbox->rx_ba_role_id_bitmap),
|
||||
le16_to_cpu(mbox->rx_ba_allowed_bitmap));
|
||||
|
||||
if (vector & BSS_LOSS_EVENT_ID)
|
||||
wlcore_event_beacon_loss(wl,
|
||||
le16_to_cpu(mbox->bss_loss_bitmap));
|
||||
|
||||
if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID)
|
||||
wlcore_event_channel_switch(wl,
|
||||
le16_to_cpu(mbox->channel_switch_role_id_bitmap),
|
||||
true);
|
||||
|
||||
if (vector & DUMMY_PACKET_EVENT_ID)
|
||||
wlcore_event_dummy_packet(wl);
|
||||
|
||||
/*
|
||||
* "TX retries exceeded" has a different meaning according to mode.
|
||||
* In AP mode the offending station is disconnected.
|
||||
*/
|
||||
if (vector & MAX_TX_FAILURE_EVENT_ID)
|
||||
wlcore_event_max_tx_failure(wl,
|
||||
le32_to_cpu(mbox->tx_retry_exceeded_bitmap));
|
||||
|
||||
if (vector & INACTIVE_STA_EVENT_ID)
|
||||
wlcore_event_inactive_sta(wl,
|
||||
le32_to_cpu(mbox->inactive_sta_bitmap));
|
||||
|
||||
if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
|
||||
wlcore_event_roc_complete(wl);
|
||||
|
||||
if (vector & SMART_CONFIG_SYNC_EVENT_ID)
|
||||
wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel,
|
||||
mbox->sc_sync_band);
|
||||
|
||||
if (vector & SMART_CONFIG_DECODE_EVENT_ID)
|
||||
wlcore_smart_config_decode_event(wl,
|
||||
mbox->sc_ssid_len,
|
||||
mbox->sc_ssid,
|
||||
mbox->sc_pwd_len,
|
||||
mbox->sc_pwd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
99
drivers/net/wireless/ti/wl18xx/event.h
Normal file
99
drivers/net/wireless/ti/wl18xx/event.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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_EVENT_H__
|
||||
#define __WL18XX_EVENT_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
|
||||
enum {
|
||||
SCAN_COMPLETE_EVENT_ID = BIT(8),
|
||||
RADAR_DETECTED_EVENT_ID = BIT(9),
|
||||
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(10),
|
||||
BSS_LOSS_EVENT_ID = BIT(11),
|
||||
MAX_TX_FAILURE_EVENT_ID = BIT(12),
|
||||
DUMMY_PACKET_EVENT_ID = BIT(13),
|
||||
INACTIVE_STA_EVENT_ID = BIT(14),
|
||||
PEER_REMOVE_COMPLETE_EVENT_ID = BIT(15),
|
||||
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(16),
|
||||
BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(17),
|
||||
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18),
|
||||
DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19),
|
||||
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20),
|
||||
SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
|
||||
SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
|
||||
};
|
||||
|
||||
struct wl18xx_event_mailbox {
|
||||
__le32 events_vector;
|
||||
|
||||
u8 number_of_scan_results;
|
||||
u8 number_of_sched_scan_results;
|
||||
|
||||
__le16 channel_switch_role_id_bitmap;
|
||||
|
||||
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
|
||||
|
||||
/* bitmap of removed links */
|
||||
__le32 hlid_removed_bitmap;
|
||||
|
||||
/* rx ba constraint */
|
||||
__le16 rx_ba_role_id_bitmap; /* 0xfff means any role. */
|
||||
__le16 rx_ba_allowed_bitmap;
|
||||
|
||||
/* bitmap of roc completed (by role id) */
|
||||
__le16 roc_completed_bitmap;
|
||||
|
||||
/* bitmap of stations (by role id) with bss loss */
|
||||
__le16 bss_loss_bitmap;
|
||||
|
||||
/* bitmap of stations (by HLID) which exceeded max tx retries */
|
||||
__le32 tx_retry_exceeded_bitmap;
|
||||
|
||||
/* bitmap of inactive stations (by HLID) */
|
||||
__le32 inactive_sta_bitmap;
|
||||
|
||||
/* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */
|
||||
u8 rx_ba_role_id;
|
||||
u8 rx_ba_link_id;
|
||||
u8 rx_ba_win_size;
|
||||
u8 padding;
|
||||
|
||||
/* smart config */
|
||||
u8 sc_ssid_len;
|
||||
u8 sc_pwd_len;
|
||||
u8 sc_token_len;
|
||||
u8 padding1;
|
||||
u8 sc_ssid[32];
|
||||
u8 sc_pwd[32];
|
||||
u8 sc_token[32];
|
||||
|
||||
/* smart config sync channel */
|
||||
u8 sc_sync_channel;
|
||||
u8 sc_sync_band;
|
||||
u8 padding2[2];
|
||||
} __packed;
|
||||
|
||||
int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
|
||||
bool *timeout);
|
||||
int wl18xx_process_mailbox_events(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
75
drivers/net/wireless/ti/wl18xx/io.c
Normal file
75
drivers/net/wireless/ti/wl18xx/io.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
|
||||
{
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(addr % 2))
|
||||
return -EINVAL;
|
||||
|
||||
if ((addr % 4) == 0) {
|
||||
ret = wlcore_read32(wl, addr, &tmp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
tmp = (tmp & 0xffff0000) | val;
|
||||
ret = wlcore_write32(wl, addr, tmp);
|
||||
} else {
|
||||
ret = wlcore_read32(wl, addr - 2, &tmp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
tmp = (tmp & 0xffff) | (val << 16);
|
||||
ret = wlcore_write32(wl, addr - 2, tmp);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
|
||||
{
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(addr % 2))
|
||||
return -EINVAL;
|
||||
|
||||
if ((addr % 4) == 0) {
|
||||
/* address is 4-bytes aligned */
|
||||
ret = wlcore_read32(wl, addr, &val);
|
||||
if (ret >= 0 && out)
|
||||
*out = val & 0xffff;
|
||||
} else {
|
||||
ret = wlcore_read32(wl, addr - 2, &val);
|
||||
if (ret >= 0 && out)
|
||||
*out = (val & 0xffff0000) >> 16;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
28
drivers/net/wireless/ti/wl18xx/io.h
Normal file
28
drivers/net/wireless/ti/wl18xx/io.h
Normal file
|
|
@ -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__
|
||||
|
||||
int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
|
||||
int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out);
|
||||
|
||||
#endif /* __WL18XX_IO_H__ */
|
||||
2029
drivers/net/wireless/ti/wl18xx/main.c
Normal file
2029
drivers/net/wireless/ti/wl18xx/main.c
Normal file
File diff suppressed because it is too large
Load diff
248
drivers/net/wireless/ti/wl18xx/reg.h
Normal file
248
drivers/net/wireless/ti/wl18xx/reg.h
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* 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_PHY_END_MEM_ADDR 0x8093CA44
|
||||
#define WL18XX_PHY_INIT_MEM_SIZE \
|
||||
(WL18XX_PHY_END_MEM_ADDR - WL18XX_PHY_INIT_MEM_ADDR)
|
||||
|
||||
#define WL18XX_SDIO_WSPI_BASE (WL18XX_REGISTERS_BASE)
|
||||
#define WL18XX_REG_CONFIG_BASE (WL18XX_REGISTERS_BASE + 0x02000)
|
||||
#define WL18XX_WGCM_REGS_BASE (WL18XX_REGISTERS_BASE + 0x03000)
|
||||
#define WL18XX_ENC_BASE (WL18XX_REGISTERS_BASE + 0x04000)
|
||||
#define WL18XX_INTERRUPT_BASE (WL18XX_REGISTERS_BASE + 0x05000)
|
||||
#define WL18XX_UART_BASE (WL18XX_REGISTERS_BASE + 0x06000)
|
||||
#define WL18XX_WELP_BASE (WL18XX_REGISTERS_BASE + 0x07000)
|
||||
#define WL18XX_TCP_CKSM_BASE (WL18XX_REGISTERS_BASE + 0x08000)
|
||||
#define WL18XX_FIFO_BASE (WL18XX_REGISTERS_BASE + 0x09000)
|
||||
#define WL18XX_OCP_BRIDGE_BASE (WL18XX_REGISTERS_BASE + 0x0A000)
|
||||
#define WL18XX_PMAC_RX_BASE (WL18XX_REGISTERS_BASE + 0x14800)
|
||||
#define WL18XX_PMAC_ACM_BASE (WL18XX_REGISTERS_BASE + 0x14C00)
|
||||
#define WL18XX_PMAC_TX_BASE (WL18XX_REGISTERS_BASE + 0x15000)
|
||||
#define WL18XX_PMAC_CSR_BASE (WL18XX_REGISTERS_BASE + 0x15400)
|
||||
|
||||
#define WL18XX_REG_ECPU_CONTROL (WL18XX_REGISTERS_BASE + 0x02004)
|
||||
#define WL18XX_REG_INTERRUPT_NO_CLEAR (WL18XX_REGISTERS_BASE + 0x050E8)
|
||||
#define WL18XX_REG_INTERRUPT_ACK (WL18XX_REGISTERS_BASE + 0x050F0)
|
||||
#define WL18XX_REG_INTERRUPT_TRIG (WL18XX_REGISTERS_BASE + 0x5074)
|
||||
#define WL18XX_REG_INTERRUPT_TRIG_H (WL18XX_REGISTERS_BASE + 0x5078)
|
||||
#define WL18XX_REG_INTERRUPT_MASK (WL18XX_REGISTERS_BASE + 0x0050DC)
|
||||
|
||||
#define WL18XX_REG_CHIP_ID_B (WL18XX_REGISTERS_BASE + 0x01542C)
|
||||
|
||||
#define WL18XX_SLV_MEM_DATA (WL18XX_HOST_BASE + 0x0018)
|
||||
#define WL18XX_SLV_REG_DATA (WL18XX_HOST_BASE + 0x0008)
|
||||
|
||||
/* Scratch Pad registers*/
|
||||
#define WL18XX_SCR_PAD0 (WL18XX_REGISTERS_BASE + 0x0154EC)
|
||||
#define WL18XX_SCR_PAD1 (WL18XX_REGISTERS_BASE + 0x0154F0)
|
||||
#define WL18XX_SCR_PAD2 (WL18XX_REGISTERS_BASE + 0x0154F4)
|
||||
#define WL18XX_SCR_PAD3 (WL18XX_REGISTERS_BASE + 0x0154F8)
|
||||
#define WL18XX_SCR_PAD4 (WL18XX_REGISTERS_BASE + 0x0154FC)
|
||||
#define WL18XX_SCR_PAD4_SET (WL18XX_REGISTERS_BASE + 0x015504)
|
||||
#define WL18XX_SCR_PAD4_CLR (WL18XX_REGISTERS_BASE + 0x015500)
|
||||
#define WL18XX_SCR_PAD5 (WL18XX_REGISTERS_BASE + 0x015508)
|
||||
#define WL18XX_SCR_PAD5_SET (WL18XX_REGISTERS_BASE + 0x015510)
|
||||
#define WL18XX_SCR_PAD5_CLR (WL18XX_REGISTERS_BASE + 0x01550C)
|
||||
#define WL18XX_SCR_PAD6 (WL18XX_REGISTERS_BASE + 0x015514)
|
||||
#define WL18XX_SCR_PAD7 (WL18XX_REGISTERS_BASE + 0x015518)
|
||||
#define WL18XX_SCR_PAD8 (WL18XX_REGISTERS_BASE + 0x01551C)
|
||||
#define WL18XX_SCR_PAD9 (WL18XX_REGISTERS_BASE + 0x015520)
|
||||
|
||||
/* Spare registers*/
|
||||
#define WL18XX_SPARE_A1 (WL18XX_REGISTERS_BASE + 0x002194)
|
||||
#define WL18XX_SPARE_A2 (WL18XX_REGISTERS_BASE + 0x002198)
|
||||
#define WL18XX_SPARE_A3 (WL18XX_REGISTERS_BASE + 0x00219C)
|
||||
#define WL18XX_SPARE_A4 (WL18XX_REGISTERS_BASE + 0x0021A0)
|
||||
#define WL18XX_SPARE_A5 (WL18XX_REGISTERS_BASE + 0x0021A4)
|
||||
#define WL18XX_SPARE_A6 (WL18XX_REGISTERS_BASE + 0x0021A8)
|
||||
#define WL18XX_SPARE_A7 (WL18XX_REGISTERS_BASE + 0x0021AC)
|
||||
#define WL18XX_SPARE_A8 (WL18XX_REGISTERS_BASE + 0x0021B0)
|
||||
#define WL18XX_SPARE_B1 (WL18XX_REGISTERS_BASE + 0x015524)
|
||||
#define WL18XX_SPARE_B2 (WL18XX_REGISTERS_BASE + 0x015528)
|
||||
#define WL18XX_SPARE_B3 (WL18XX_REGISTERS_BASE + 0x01552C)
|
||||
#define WL18XX_SPARE_B4 (WL18XX_REGISTERS_BASE + 0x015530)
|
||||
#define WL18XX_SPARE_B5 (WL18XX_REGISTERS_BASE + 0x015534)
|
||||
#define WL18XX_SPARE_B6 (WL18XX_REGISTERS_BASE + 0x015538)
|
||||
#define WL18XX_SPARE_B7 (WL18XX_REGISTERS_BASE + 0x01553C)
|
||||
#define WL18XX_SPARE_B8 (WL18XX_REGISTERS_BASE + 0x015540)
|
||||
|
||||
#define WL18XX_REG_COMMAND_MAILBOX_PTR (WL18XX_SCR_PAD0)
|
||||
#define WL18XX_REG_EVENT_MAILBOX_PTR (WL18XX_SCR_PAD1)
|
||||
#define WL18XX_EEPROMLESS_IND (WL18XX_SCR_PAD4)
|
||||
|
||||
#define WL18XX_WELP_ARM_COMMAND (WL18XX_REGISTERS_BASE + 0x7100)
|
||||
#define WL18XX_ENABLE (WL18XX_REGISTERS_BASE + 0x01543C)
|
||||
|
||||
/* PRCM registers */
|
||||
#define PLATFORM_DETECTION 0xA0E3E0
|
||||
#define OCS_EN 0xA02080
|
||||
#define PRIMARY_CLK_DETECT 0xA020A6
|
||||
#define PLLSH_COEX_PLL_N 0xA02384
|
||||
#define PLLSH_COEX_PLL_M 0xA02382
|
||||
#define PLLSH_COEX_PLL_SWALLOW_EN 0xA0238E
|
||||
#define PLLSH_WL_PLL_SEL 0xA02398
|
||||
|
||||
#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_WL_PLL_EN_VAL1 0x7
|
||||
#define PLLSH_WL_PLL_EN_VAL2 0x2
|
||||
#define PLLSH_COEX_PLL_SWALLOW_EN_VAL1 0x2
|
||||
#define PLLSH_COEX_PLL_SWALLOW_EN_VAL2 0x11
|
||||
|
||||
#define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1
|
||||
#define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12
|
||||
|
||||
#define PLLSH_WL_PLL_SEL_WCS_PLL 0x0
|
||||
#define PLLSH_WL_PLL_SEL_COEX_PLL 0x1
|
||||
|
||||
#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C
|
||||
#define WL18XX_PG_VER_MASK 0x70
|
||||
#define WL18XX_PG_VER_OFFSET 4
|
||||
#define WL18XX_ROM_VER_MASK 0x3e00
|
||||
#define WL18XX_ROM_VER_OFFSET 9
|
||||
#define WL18XX_METAL_VER_MASK 0xC
|
||||
#define WL18XX_METAL_VER_OFFSET 2
|
||||
#define WL18XX_NEW_METAL_VER_MASK 0x180
|
||||
#define WL18XX_NEW_METAL_VER_OFFSET 7
|
||||
|
||||
#define WL18XX_PACKAGE_TYPE_OFFSET 13
|
||||
#define WL18XX_PACKAGE_TYPE_WSP 0
|
||||
|
||||
#define WL18XX_REG_FUSE_DATA_2_3 0xA02614
|
||||
#define WL18XX_RDL_VER_MASK 0x1f00
|
||||
#define WL18XX_RDL_VER_OFFSET 8
|
||||
|
||||
#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602
|
||||
#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606
|
||||
|
||||
#define WL18XX_CMD_MBOX_ADDRESS 0xB007B4
|
||||
|
||||
#define WL18XX_FW_STATUS_ADDR 0x50F8
|
||||
|
||||
#define CHIP_ID_185x_PG10 (0x06030101)
|
||||
#define CHIP_ID_185x_PG20 (0x06030111)
|
||||
|
||||
/*
|
||||
* Host Command Interrupt. Setting this bit masks
|
||||
* the interrupt that the host issues to inform
|
||||
* the FW that it has sent a command
|
||||
* to the Wlan hardware Command Mailbox.
|
||||
*/
|
||||
#define WL18XX_INTR_TRIG_CMD BIT(28)
|
||||
|
||||
/*
|
||||
* Host Event Acknowlegde Interrupt. The host
|
||||
* sets this bit to acknowledge that it received
|
||||
* the unsolicited information from the event
|
||||
* mailbox.
|
||||
*/
|
||||
#define WL18XX_INTR_TRIG_EVENT_ACK BIT(29)
|
||||
|
||||
/*
|
||||
* To boot the firmware in PLT mode we need to write this value in
|
||||
* SCR_PAD8 before starting.
|
||||
*/
|
||||
#define WL18XX_SCR_PAD8_PLT 0xBABABEBE
|
||||
|
||||
enum {
|
||||
COMPONENT_NO_SWITCH = 0x0,
|
||||
COMPONENT_2_WAY_SWITCH = 0x1,
|
||||
COMPONENT_3_WAY_SWITCH = 0x2,
|
||||
COMPONENT_MATCHING = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
FEM_NONE = 0x0,
|
||||
FEM_VENDOR_1 = 0x1,
|
||||
FEM_VENDOR_2 = 0x2,
|
||||
FEM_VENDOR_3 = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
BOARD_TYPE_EVB_18XX = 0,
|
||||
BOARD_TYPE_DVP_18XX = 1,
|
||||
BOARD_TYPE_HDK_18XX = 2,
|
||||
BOARD_TYPE_FPGA_18XX = 3,
|
||||
BOARD_TYPE_COM8_18XX = 4,
|
||||
|
||||
NUM_BOARD_TYPES,
|
||||
};
|
||||
|
||||
enum wl18xx_rdl_num {
|
||||
RDL_NONE = 0,
|
||||
RDL_1_HP = 1,
|
||||
RDL_2_SP = 2,
|
||||
RDL_3_HP = 3,
|
||||
RDL_4_SP = 4,
|
||||
RDL_5_SP = 0x11,
|
||||
RDL_6_SP = 0x12,
|
||||
RDL_7_SP = 0x13,
|
||||
RDL_8_SP = 0x14,
|
||||
|
||||
_RDL_LAST,
|
||||
RDL_MAX = _RDL_LAST - 1,
|
||||
};
|
||||
|
||||
|
||||
/* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */
|
||||
#define WL18XX_PHY_FPGA_SPARE_1 0x8093CA40
|
||||
|
||||
/* command to disable FDSP clock */
|
||||
#define MEM_FDSP_CLK_120_DISABLE 0x80000000
|
||||
|
||||
/* command to set ATPG clock toward FDSP Code RAM rather than its own clock */
|
||||
#define MEM_FDSP_CODERAM_FUNC_CLK_SEL 0xC0000000
|
||||
|
||||
/* command to re-enable FDSP clock */
|
||||
#define MEM_FDSP_CLK_120_ENABLE 0x40000000
|
||||
|
||||
#endif /* __REG_H__ */
|
||||
334
drivers/net/wireless/ti/wl18xx/scan.c
Normal file
334
drivers/net/wireless/ti/wl18xx/scan.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include "scan.h"
|
||||
#include "../wlcore/debug.h"
|
||||
|
||||
static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd,
|
||||
struct wlcore_scan_channels *cmd_channels)
|
||||
{
|
||||
memcpy(cmd->passive, cmd_channels->passive, sizeof(cmd->passive));
|
||||
memcpy(cmd->active, cmd_channels->active, sizeof(cmd->active));
|
||||
cmd->dfs = cmd_channels->dfs;
|
||||
cmd->passive_active = cmd_channels->passive_active;
|
||||
|
||||
memcpy(cmd->channels_2, cmd_channels->channels_2,
|
||||
sizeof(cmd->channels_2));
|
||||
memcpy(cmd->channels_5, cmd_channels->channels_5,
|
||||
sizeof(cmd->channels_5));
|
||||
/* channels_4 are not supported, so no need to copy them */
|
||||
}
|
||||
|
||||
static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct wl18xx_cmd_scan_params *cmd;
|
||||
struct wlcore_scan_channels *cmd_channels = NULL;
|
||||
int ret;
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
|
||||
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->scan_type = SCAN_TYPE_SEARCH;
|
||||
cmd->rssi_threshold = -127;
|
||||
cmd->snr_threshold = 0;
|
||||
|
||||
cmd->bss_type = SCAN_BSS_TYPE_ANY;
|
||||
|
||||
cmd->ssid_from_list = 0;
|
||||
cmd->filter = 0;
|
||||
cmd->add_broadcast = 0;
|
||||
|
||||
cmd->urgency = 0;
|
||||
cmd->protect = 0;
|
||||
|
||||
cmd->n_probe_reqs = wl->conf.scan.num_probe_reqs;
|
||||
cmd->terminate_after = 0;
|
||||
|
||||
/* configure channels */
|
||||
WARN_ON(req->n_ssids > 1);
|
||||
|
||||
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
|
||||
if (!cmd_channels) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
|
||||
req->n_channels, req->n_ssids,
|
||||
SCAN_TYPE_SEARCH);
|
||||
wl18xx_adjust_channels(cmd, cmd_channels);
|
||||
|
||||
/*
|
||||
* all the cycles params (except total cycles) should
|
||||
* remain 0 for normal scan
|
||||
*/
|
||||
cmd->total_cycles = 1;
|
||||
|
||||
if (req->no_cck)
|
||||
cmd->rate = WL18XX_SCAN_RATE_6;
|
||||
|
||||
cmd->tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
|
||||
if (req->n_ssids) {
|
||||
cmd->ssid_len = req->ssids[0].ssid_len;
|
||||
memcpy(cmd->ssid, req->ssids[0].ssid, cmd->ssid_len);
|
||||
}
|
||||
|
||||
/* TODO: per-band ies? */
|
||||
if (cmd->active[0]) {
|
||||
u8 band = IEEE80211_BAND_2GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
cmd->role_id, band,
|
||||
req->ssids ? req->ssids[0].ssid : NULL,
|
||||
req->ssids ? req->ssids[0].ssid_len : 0,
|
||||
req->ie,
|
||||
req->ie_len,
|
||||
NULL,
|
||||
0,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
wl1271_error("2.4GHz PROBE request template failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->active[1] || cmd->dfs) {
|
||||
u8 band = IEEE80211_BAND_5GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
cmd->role_id, band,
|
||||
req->ssids ? req->ssids[0].ssid : NULL,
|
||||
req->ssids ? req->ssids[0].ssid_len : 0,
|
||||
req->ie,
|
||||
req->ie_len,
|
||||
NULL,
|
||||
0,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
wl1271_error("5GHz PROBE request template failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("SCAN failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(cmd_channels);
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
wl->scan.failed = false;
|
||||
cancel_delayed_work(&wl->scan_complete_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
|
||||
msecs_to_jiffies(0));
|
||||
}
|
||||
|
||||
static
|
||||
int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_sched_scan_request *req,
|
||||
struct ieee80211_scan_ies *ies)
|
||||
{
|
||||
struct wl18xx_cmd_scan_params *cmd;
|
||||
struct wlcore_scan_channels *cmd_channels = NULL;
|
||||
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
|
||||
int ret;
|
||||
int filter_type;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
|
||||
|
||||
filter_type = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req);
|
||||
if (filter_type < 0)
|
||||
return filter_type;
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
|
||||
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->scan_type = SCAN_TYPE_PERIODIC;
|
||||
cmd->rssi_threshold = c->rssi_threshold;
|
||||
cmd->snr_threshold = c->snr_threshold;
|
||||
|
||||
/* don't filter on BSS type */
|
||||
cmd->bss_type = SCAN_BSS_TYPE_ANY;
|
||||
|
||||
cmd->ssid_from_list = 1;
|
||||
if (filter_type == SCAN_SSID_FILTER_LIST)
|
||||
cmd->filter = 1;
|
||||
cmd->add_broadcast = 0;
|
||||
|
||||
cmd->urgency = 0;
|
||||
cmd->protect = 0;
|
||||
|
||||
cmd->n_probe_reqs = c->num_probe_reqs;
|
||||
/* don't stop scanning automatically when something is found */
|
||||
cmd->terminate_after = 0;
|
||||
|
||||
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
|
||||
if (!cmd_channels) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* configure channels */
|
||||
wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
|
||||
req->n_channels, req->n_ssids,
|
||||
SCAN_TYPE_PERIODIC);
|
||||
wl18xx_adjust_channels(cmd, cmd_channels);
|
||||
|
||||
cmd->short_cycles_sec = 0;
|
||||
cmd->long_cycles_sec = cpu_to_le16(req->interval);
|
||||
cmd->short_cycles_count = 0;
|
||||
|
||||
cmd->total_cycles = 0;
|
||||
|
||||
cmd->tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
|
||||
/* create a PERIODIC_SCAN_REPORT_EVENT whenever we've got a match */
|
||||
cmd->report_threshold = 1;
|
||||
cmd->terminate_on_report = 0;
|
||||
|
||||
if (cmd->active[0]) {
|
||||
u8 band = IEEE80211_BAND_2GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
cmd->role_id, band,
|
||||
req->ssids ? req->ssids[0].ssid : NULL,
|
||||
req->ssids ? req->ssids[0].ssid_len : 0,
|
||||
ies->ies[band],
|
||||
ies->len[band],
|
||||
ies->common_ies,
|
||||
ies->common_ie_len,
|
||||
true);
|
||||
if (ret < 0) {
|
||||
wl1271_error("2.4GHz PROBE request template failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->active[1] || cmd->dfs) {
|
||||
u8 band = IEEE80211_BAND_5GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
cmd->role_id, band,
|
||||
req->ssids ? req->ssids[0].ssid : NULL,
|
||||
req->ssids ? req->ssids[0].ssid_len : 0,
|
||||
ies->ies[band],
|
||||
ies->len[band],
|
||||
ies->common_ies,
|
||||
ies->common_ie_len,
|
||||
true);
|
||||
if (ret < 0) {
|
||||
wl1271_error("5GHz PROBE request template failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("SCAN failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(cmd_channels);
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_sched_scan_request *req,
|
||||
struct ieee80211_scan_ies *ies)
|
||||
{
|
||||
return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies);
|
||||
}
|
||||
|
||||
static int __wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 scan_type)
|
||||
{
|
||||
struct wl18xx_cmd_scan_stop *stop;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd periodic scan stop");
|
||||
|
||||
stop = kzalloc(sizeof(*stop), GFP_KERNEL);
|
||||
if (!stop) {
|
||||
wl1271_error("failed to alloc memory to send sched scan stop");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
stop->role_id = wlvif->role_id;
|
||||
stop->scan_type = scan_type;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, stop, sizeof(*stop), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send sched scan stop command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(stop);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
__wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_PERIODIC);
|
||||
}
|
||||
int wl18xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
return wl18xx_scan_send(wl, wlvif, req);
|
||||
}
|
||||
|
||||
int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
return __wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_SEARCH);
|
||||
}
|
||||
127
drivers/net/wireless/ti/wl18xx/scan.h
Normal file
127
drivers/net/wireless/ti/wl18xx/scan.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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_SCAN_H__
|
||||
#define __WL18XX_SCAN_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
#include "../wlcore/cmd.h"
|
||||
#include "../wlcore/scan.h"
|
||||
|
||||
struct tracking_ch_params {
|
||||
struct conn_scan_ch_params channel;
|
||||
|
||||
__le32 bssid_lsb;
|
||||
__le16 bssid_msb;
|
||||
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
/* probe request rate */
|
||||
enum
|
||||
{
|
||||
WL18XX_SCAN_RATE_1 = 0,
|
||||
WL18XX_SCAN_RATE_5_5 = 1,
|
||||
WL18XX_SCAN_RATE_6 = 2,
|
||||
};
|
||||
|
||||
#define WL18XX_MAX_CHANNELS_5GHZ 32
|
||||
|
||||
struct wl18xx_cmd_scan_params {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 role_id;
|
||||
u8 scan_type;
|
||||
|
||||
s8 rssi_threshold; /* for filtering (in dBm) */
|
||||
s8 snr_threshold; /* for filtering (in dB) */
|
||||
|
||||
u8 bss_type; /* for filtering */
|
||||
u8 ssid_from_list; /* use ssid from configured ssid list */
|
||||
u8 filter; /* forward only results with matching ssids */
|
||||
|
||||
/*
|
||||
* add broadcast ssid in addition to the configured ssids.
|
||||
* the driver should add dummy entry for it (?).
|
||||
*/
|
||||
u8 add_broadcast;
|
||||
|
||||
u8 urgency;
|
||||
u8 protect; /* ??? */
|
||||
u8 n_probe_reqs; /* Number of probes requests per channel */
|
||||
u8 terminate_after; /* early terminate scan operation */
|
||||
|
||||
u8 passive[SCAN_MAX_BANDS]; /* number of passive scan channels */
|
||||
u8 active[SCAN_MAX_BANDS]; /* number of active scan channels */
|
||||
u8 dfs; /* number of dfs channels in 5ghz */
|
||||
u8 passive_active; /* number of passive before active channels 2.4ghz */
|
||||
|
||||
__le16 short_cycles_sec;
|
||||
__le16 long_cycles_sec;
|
||||
u8 short_cycles_count;
|
||||
u8 total_cycles; /* 0 - infinite */
|
||||
u8 padding[2];
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
|
||||
struct conn_scan_ch_params channels_5[WL18XX_MAX_CHANNELS_5GHZ];
|
||||
struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
|
||||
};
|
||||
struct tracking_ch_params channels_tracking[WL1271_SCAN_MAX_CHANNELS];
|
||||
} ;
|
||||
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
|
||||
u8 tag;
|
||||
u8 rate;
|
||||
|
||||
/* send SCAN_REPORT_EVENT in periodic scans after each cycle
|
||||
* if number of results >= report_threshold. Must be 0 for
|
||||
* non periodic scans
|
||||
*/
|
||||
u8 report_threshold;
|
||||
|
||||
/* Should periodic scan stop after a report event was created.
|
||||
* Must be 0 for non periodic scans.
|
||||
*/
|
||||
u8 terminate_on_report;
|
||||
|
||||
u8 padding1[3];
|
||||
} __packed;
|
||||
|
||||
struct wl18xx_cmd_scan_stop {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 role_id;
|
||||
u8 scan_type;
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
int wl18xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_scan_request *req);
|
||||
int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct cfg80211_sched_scan_request *req,
|
||||
struct ieee80211_scan_ies *ies);
|
||||
void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
#endif
|
||||
174
drivers/net/wireless/ti/wl18xx/tx.c
Normal file
174
drivers/net/wireless/ti/wl18xx/tx.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
|
||||
u8 band, struct ieee80211_tx_rate *rate)
|
||||
{
|
||||
u8 fw_rate = wl->fw_status->counters.tx_last_rate;
|
||||
|
||||
if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
|
||||
wl1271_error("last Tx rate invalid: %d", fw_rate);
|
||||
rate->idx = 0;
|
||||
rate->flags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) {
|
||||
rate->idx = fw_rate;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
rate->idx -= CONF_HW_RATE_INDEX_6MBPS;
|
||||
rate->flags = 0;
|
||||
} else {
|
||||
rate->flags = IEEE80211_TX_RC_MCS;
|
||||
rate->idx = fw_rate - CONF_HW_RATE_INDEX_MCS0;
|
||||
|
||||
/* SGI modifier is counted as a separate rate */
|
||||
if (fw_rate >= CONF_HW_RATE_INDEX_MCS7_SGI)
|
||||
(rate->idx)--;
|
||||
if (fw_rate == CONF_HW_RATE_INDEX_MCS15_SGI)
|
||||
(rate->idx)--;
|
||||
|
||||
/* this also covers the 40Mhz SGI case (= MCS15) */
|
||||
if (fw_rate == CONF_HW_RATE_INDEX_MCS7_SGI ||
|
||||
fw_rate == CONF_HW_RATE_INDEX_MCS15_SGI)
|
||||
rate->flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
|
||||
if (fw_rate > CONF_HW_RATE_INDEX_MCS7_SGI && vif) {
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
|
||||
wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
|
||||
/* adjustment needed for range 0-7 */
|
||||
rate->idx -= 8;
|
||||
rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/*
|
||||
* first pass info->control.vif while it's valid, and then fill out
|
||||
* the info->status structures
|
||||
*/
|
||||
wl18xx_get_last_tx_rate(wl, info->control.vif,
|
||||
info->band, &info->status.rates[0]);
|
||||
|
||||
info->status.rates[0].count = 1; /* no data about retries */
|
||||
info->status.ack_signal = -1;
|
||||
|
||||
if (!tx_success)
|
||||
wl->stats.retry_count++;
|
||||
|
||||
/*
|
||||
* TODO: update sequence number for encryption? seems to be
|
||||
* unsupported for now. needed for recovery with encryption.
|
||||
*/
|
||||
|
||||
/* remove private header from packet */
|
||||
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
|
||||
|
||||
/* remove TKIP header space if present */
|
||||
if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) &&
|
||||
info->control.hw_key &&
|
||||
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
||||
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen);
|
||||
skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d",
|
||||
id, skb, tx_success);
|
||||
|
||||
/* return the packet to the stack */
|
||||
skb_queue_tail(&wl->deferred_tx_queue, skb);
|
||||
queue_work(wl->freezable_wq, &wl->netstack_work);
|
||||
wl1271_free_tx_id(wl, id);
|
||||
}
|
||||
|
||||
void wl18xx_tx_immediate_complete(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_fw_status_priv *status_priv =
|
||||
(struct wl18xx_fw_status_priv *)wl->fw_status->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;
|
||||
}
|
||||
46
drivers/net/wireless/ti/wl18xx/tx.h
Normal file
46
drivers/net/wireless/ti/wl18xx/tx.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL18XX_TX_H__
|
||||
#define __WL18XX_TX_H__
|
||||
|
||||
#include "../wlcore/wlcore.h"
|
||||
|
||||
#define WL18XX_TX_HW_BLOCK_SPARE 1
|
||||
/* for special cases - namely, TKIP and GEM */
|
||||
#define WL18XX_TX_HW_EXTRA_BLOCK_SPARE 2
|
||||
#define WL18XX_TX_HW_BLOCK_SIZE 268
|
||||
|
||||
#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
|
||||
#define WL18XX_TX_STATUS_STAT_BIT_IDX 7
|
||||
|
||||
/* Indicates this TX HW frame is not padded to SDIO block size */
|
||||
#define WL18XX_TX_CTRL_NOT_PADDED BIT(7)
|
||||
|
||||
/*
|
||||
* The FW uses a special bit to indicate a wide channel should be used in
|
||||
* the rate policy.
|
||||
*/
|
||||
#define CONF_TX_RATE_USE_WIDE_CHAN BIT(31)
|
||||
|
||||
void wl18xx_tx_immediate_complete(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL12XX_TX_H__ */
|
||||
196
drivers/net/wireless/ti/wl18xx/wl18xx.h
Normal file
196
drivers/net/wireless/ti/wl18xx/wl18xx.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* This file is part of wl18xx
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL18XX_PRIV_H__
|
||||
#define __WL18XX_PRIV_H__
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
/* minimum FW required for driver */
|
||||
#define WL18XX_CHIP_VER 8
|
||||
#define WL18XX_IFTYPE_VER 8
|
||||
#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_MINOR_VER 13
|
||||
|
||||
#define WL18XX_CMD_MAX_SIZE 740
|
||||
|
||||
#define WL18XX_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
|
||||
|
||||
#define WL18XX_NUM_TX_DESCRIPTORS 32
|
||||
#define WL18XX_NUM_RX_DESCRIPTORS 32
|
||||
|
||||
#define WL18XX_NUM_MAC_ADDRESSES 2
|
||||
|
||||
#define WL18XX_RX_BA_MAX_SESSIONS 13
|
||||
|
||||
#define WL18XX_MAX_AP_STATIONS 10
|
||||
#define WL18XX_MAX_LINKS 16
|
||||
|
||||
struct wl18xx_priv {
|
||||
/* buffer for sending commands to FW */
|
||||
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
|
||||
|
||||
struct wl18xx_priv_conf conf;
|
||||
|
||||
/* Index of last released Tx desc in FW */
|
||||
u8 last_fw_rls_idx;
|
||||
|
||||
/* number of keys requiring extra spare mem-blocks */
|
||||
int extra_spare_key_count;
|
||||
};
|
||||
|
||||
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
|
||||
|
||||
struct wl18xx_fw_status_priv {
|
||||
/*
|
||||
* Index in released_tx_desc for first byte that holds
|
||||
* released tx host desc
|
||||
*/
|
||||
u8 fw_release_idx;
|
||||
|
||||
/*
|
||||
* Array of host Tx descriptors, where fw_release_idx
|
||||
* indicated the first released idx.
|
||||
*/
|
||||
u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC];
|
||||
|
||||
/* A bitmap representing the currently suspended links. The suspend
|
||||
* is short lived, for multi-channel Tx requirements.
|
||||
*/
|
||||
__le32 link_suspend_bitmap;
|
||||
|
||||
/* packet threshold for an "almost empty" AC,
|
||||
* for Tx schedulng purposes
|
||||
*/
|
||||
u8 tx_ac_threshold;
|
||||
|
||||
/* number of packets to queue up for a link in PS */
|
||||
u8 tx_ps_threshold;
|
||||
|
||||
/* number of packet to queue up for a suspended link */
|
||||
u8 tx_suspend_threshold;
|
||||
|
||||
/* Should have less than this number of packets in queue of a slow
|
||||
* link to qualify as high priority link
|
||||
*/
|
||||
u8 tx_slow_link_prio_threshold;
|
||||
|
||||
/* Should have less than this number of packets in queue of a fast
|
||||
* link to qualify as high priority link
|
||||
*/
|
||||
u8 tx_fast_link_prio_threshold;
|
||||
|
||||
/* Should have less than this number of packets in queue of a slow
|
||||
* link before we stop queuing up packets for it.
|
||||
*/
|
||||
u8 tx_slow_stop_threshold;
|
||||
|
||||
/* Should have less than this number of packets in queue of a fast
|
||||
* link before we stop queuing up packets for it.
|
||||
*/
|
||||
u8 tx_fast_stop_threshold;
|
||||
|
||||
u8 padding[3];
|
||||
};
|
||||
|
||||
struct wl18xx_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[WL18XX_MAX_LINKS];
|
||||
|
||||
/* Cumulative counter of released Voice memory blocks */
|
||||
u8 tx_voice_released_blks;
|
||||
|
||||
/* Tx rate of the last transmitted packet */
|
||||
u8 tx_last_rate;
|
||||
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
/* FW status registers */
|
||||
struct wl18xx_fw_status {
|
||||
__le32 intr;
|
||||
u8 fw_rx_counter;
|
||||
u8 drv_rx_counter;
|
||||
u8 reserved;
|
||||
u8 tx_results_counter;
|
||||
__le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS];
|
||||
|
||||
__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 wl18xx_fw_packet_counters counters;
|
||||
|
||||
__le32 log_start_addr;
|
||||
|
||||
/* Private status to be used by the lower drivers */
|
||||
struct wl18xx_fw_status_priv priv;
|
||||
} __packed;
|
||||
|
||||
#define WL18XX_PHY_VERSION_MAX_LEN 20
|
||||
|
||||
struct wl18xx_static_data_priv {
|
||||
char phy_version[WL18XX_PHY_VERSION_MAX_LEN];
|
||||
};
|
||||
|
||||
struct wl18xx_clk_cfg {
|
||||
u32 n;
|
||||
u32 m;
|
||||
u32 p;
|
||||
u32 q;
|
||||
bool swallow;
|
||||
};
|
||||
|
||||
enum {
|
||||
CLOCK_CONFIG_16_2_M = 1,
|
||||
CLOCK_CONFIG_16_368_M,
|
||||
CLOCK_CONFIG_16_8_M,
|
||||
CLOCK_CONFIG_19_2_M,
|
||||
CLOCK_CONFIG_26_M,
|
||||
CLOCK_CONFIG_32_736_M,
|
||||
CLOCK_CONFIG_33_6_M,
|
||||
CLOCK_CONFIG_38_468_M,
|
||||
CLOCK_CONFIG_52_M,
|
||||
|
||||
NUM_CLOCK_CONFIGS,
|
||||
};
|
||||
|
||||
#endif /* __WL18XX_PRIV_H__ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue