|
@@ -35,10 +35,9 @@
|
|
#include <linux/sched.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/interrupt.h>
|
|
|
|
|
|
-#include "wl12xx.h"
|
|
|
|
|
|
+#include "wlcore.h"
|
|
#include "debug.h"
|
|
#include "debug.h"
|
|
#include "wl12xx_80211.h"
|
|
#include "wl12xx_80211.h"
|
|
-#include "reg.h"
|
|
|
|
#include "io.h"
|
|
#include "io.h"
|
|
#include "event.h"
|
|
#include "event.h"
|
|
#include "tx.h"
|
|
#include "tx.h"
|
|
@@ -50,342 +49,15 @@
|
|
#include "boot.h"
|
|
#include "boot.h"
|
|
#include "testmode.h"
|
|
#include "testmode.h"
|
|
#include "scan.h"
|
|
#include "scan.h"
|
|
|
|
+#include "hw_ops.h"
|
|
|
|
|
|
#define WL1271_BOOT_RETRIES 3
|
|
#define WL1271_BOOT_RETRIES 3
|
|
|
|
|
|
-static struct conf_drv_settings default_conf = {
|
|
|
|
- .sg = {
|
|
|
|
- .params = {
|
|
|
|
- [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
|
|
|
|
- [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
|
|
|
|
- [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
|
|
|
|
- [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
|
|
|
|
- [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
|
|
|
|
- [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
|
|
|
|
- [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
|
|
|
|
- [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
|
|
|
|
- [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
|
|
|
|
- [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
|
|
|
|
- [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
|
|
|
|
- [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
|
|
|
|
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
|
|
|
|
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
|
|
|
|
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
|
|
|
|
- [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
|
|
|
|
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
|
|
|
|
- [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
|
|
|
|
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
|
|
|
|
- /* active scan params */
|
|
|
|
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
|
|
|
|
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
|
|
|
|
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
|
|
|
|
- /* passive scan params */
|
|
|
|
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
|
|
|
|
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
|
|
|
|
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
|
|
|
|
- /* passive scan in dual antenna params */
|
|
|
|
- [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
|
|
|
|
- [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
|
|
|
|
- [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
|
|
|
|
- /* general params */
|
|
|
|
- [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
|
|
|
|
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
|
|
|
|
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
|
|
|
|
- [CONF_SG_DHCP_TIME] = 5000,
|
|
|
|
- [CONF_SG_RXT] = 1200,
|
|
|
|
- [CONF_SG_TXT] = 1000,
|
|
|
|
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
|
|
|
|
- [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
|
|
|
|
- [CONF_SG_HV3_MAX_SERVED] = 6,
|
|
|
|
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
|
|
|
|
- [CONF_SG_UPSD_TIMEOUT] = 10,
|
|
|
|
- [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
|
|
|
|
- [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
|
|
|
|
- [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
|
|
|
|
- /* AP params */
|
|
|
|
- [CONF_AP_BEACON_MISS_TX] = 3,
|
|
|
|
- [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
|
|
|
|
- [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
|
|
|
|
- [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
|
|
|
|
- [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
|
|
|
|
- [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
|
|
|
|
- /* CTS Diluting params */
|
|
|
|
- [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
|
|
|
|
- [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
|
|
|
|
- },
|
|
|
|
- .state = CONF_SG_PROTECTIVE,
|
|
|
|
- },
|
|
|
|
- .rx = {
|
|
|
|
- .rx_msdu_life_time = 512000,
|
|
|
|
- .packet_detection_threshold = 0,
|
|
|
|
- .ps_poll_timeout = 15,
|
|
|
|
- .upsd_timeout = 15,
|
|
|
|
- .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
|
|
|
|
- .rx_cca_threshold = 0,
|
|
|
|
- .irq_blk_threshold = 0xFFFF,
|
|
|
|
- .irq_pkt_threshold = 0,
|
|
|
|
- .irq_timeout = 600,
|
|
|
|
- .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
|
|
|
|
- },
|
|
|
|
- .tx = {
|
|
|
|
- .tx_energy_detection = 0,
|
|
|
|
- .sta_rc_conf = {
|
|
|
|
- .enabled_rates = 0,
|
|
|
|
- .short_retry_limit = 10,
|
|
|
|
- .long_retry_limit = 10,
|
|
|
|
- .aflags = 0,
|
|
|
|
- },
|
|
|
|
- .ac_conf_count = 4,
|
|
|
|
- .ac_conf = {
|
|
|
|
- [CONF_TX_AC_BE] = {
|
|
|
|
- .ac = CONF_TX_AC_BE,
|
|
|
|
- .cw_min = 15,
|
|
|
|
- .cw_max = 63,
|
|
|
|
- .aifsn = 3,
|
|
|
|
- .tx_op_limit = 0,
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_BK] = {
|
|
|
|
- .ac = CONF_TX_AC_BK,
|
|
|
|
- .cw_min = 15,
|
|
|
|
- .cw_max = 63,
|
|
|
|
- .aifsn = 7,
|
|
|
|
- .tx_op_limit = 0,
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_VI] = {
|
|
|
|
- .ac = CONF_TX_AC_VI,
|
|
|
|
- .cw_min = 15,
|
|
|
|
- .cw_max = 63,
|
|
|
|
- .aifsn = CONF_TX_AIFS_PIFS,
|
|
|
|
- .tx_op_limit = 3008,
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_VO] = {
|
|
|
|
- .ac = CONF_TX_AC_VO,
|
|
|
|
- .cw_min = 15,
|
|
|
|
- .cw_max = 63,
|
|
|
|
- .aifsn = CONF_TX_AIFS_PIFS,
|
|
|
|
- .tx_op_limit = 1504,
|
|
|
|
- },
|
|
|
|
- },
|
|
|
|
- .max_tx_retries = 100,
|
|
|
|
- .ap_aging_period = 300,
|
|
|
|
- .tid_conf_count = 4,
|
|
|
|
- .tid_conf = {
|
|
|
|
- [CONF_TX_AC_BE] = {
|
|
|
|
- .queue_id = CONF_TX_AC_BE,
|
|
|
|
- .channel_type = CONF_CHANNEL_TYPE_EDCF,
|
|
|
|
- .tsid = CONF_TX_AC_BE,
|
|
|
|
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
|
|
|
|
- .ack_policy = CONF_ACK_POLICY_LEGACY,
|
|
|
|
- .apsd_conf = {0, 0},
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_BK] = {
|
|
|
|
- .queue_id = CONF_TX_AC_BK,
|
|
|
|
- .channel_type = CONF_CHANNEL_TYPE_EDCF,
|
|
|
|
- .tsid = CONF_TX_AC_BK,
|
|
|
|
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
|
|
|
|
- .ack_policy = CONF_ACK_POLICY_LEGACY,
|
|
|
|
- .apsd_conf = {0, 0},
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_VI] = {
|
|
|
|
- .queue_id = CONF_TX_AC_VI,
|
|
|
|
- .channel_type = CONF_CHANNEL_TYPE_EDCF,
|
|
|
|
- .tsid = CONF_TX_AC_VI,
|
|
|
|
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
|
|
|
|
- .ack_policy = CONF_ACK_POLICY_LEGACY,
|
|
|
|
- .apsd_conf = {0, 0},
|
|
|
|
- },
|
|
|
|
- [CONF_TX_AC_VO] = {
|
|
|
|
- .queue_id = CONF_TX_AC_VO,
|
|
|
|
- .channel_type = CONF_CHANNEL_TYPE_EDCF,
|
|
|
|
- .tsid = CONF_TX_AC_VO,
|
|
|
|
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
|
|
|
|
- .ack_policy = CONF_ACK_POLICY_LEGACY,
|
|
|
|
- .apsd_conf = {0, 0},
|
|
|
|
- },
|
|
|
|
- },
|
|
|
|
- .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
|
|
|
|
- .tx_compl_timeout = 700,
|
|
|
|
- .tx_compl_threshold = 4,
|
|
|
|
- .basic_rate = CONF_HW_BIT_RATE_1MBPS,
|
|
|
|
- .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
|
|
|
|
- .tmpl_short_retry_limit = 10,
|
|
|
|
- .tmpl_long_retry_limit = 10,
|
|
|
|
- .tx_watchdog_timeout = 5000,
|
|
|
|
- },
|
|
|
|
- .conn = {
|
|
|
|
- .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
|
|
|
|
- .listen_interval = 1,
|
|
|
|
- .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM,
|
|
|
|
- .suspend_listen_interval = 3,
|
|
|
|
- .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
|
|
|
|
- .bcn_filt_ie_count = 2,
|
|
|
|
- .bcn_filt_ie = {
|
|
|
|
- [0] = {
|
|
|
|
- .ie = WLAN_EID_CHANNEL_SWITCH,
|
|
|
|
- .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
|
|
|
|
- },
|
|
|
|
- [1] = {
|
|
|
|
- .ie = WLAN_EID_HT_OPERATION,
|
|
|
|
- .rule = CONF_BCN_RULE_PASS_ON_CHANGE,
|
|
|
|
- },
|
|
|
|
- },
|
|
|
|
- .synch_fail_thold = 10,
|
|
|
|
- .bss_lose_timeout = 100,
|
|
|
|
- .beacon_rx_timeout = 10000,
|
|
|
|
- .broadcast_timeout = 20000,
|
|
|
|
- .rx_broadcast_in_ps = 1,
|
|
|
|
- .ps_poll_threshold = 10,
|
|
|
|
- .bet_enable = CONF_BET_MODE_ENABLE,
|
|
|
|
- .bet_max_consecutive = 50,
|
|
|
|
- .psm_entry_retries = 8,
|
|
|
|
- .psm_exit_retries = 16,
|
|
|
|
- .psm_entry_nullfunc_retries = 3,
|
|
|
|
- .dynamic_ps_timeout = 200,
|
|
|
|
- .forced_ps = false,
|
|
|
|
- .keep_alive_interval = 55000,
|
|
|
|
- .max_listen_interval = 20,
|
|
|
|
- },
|
|
|
|
- .itrim = {
|
|
|
|
- .enable = false,
|
|
|
|
- .timeout = 50000,
|
|
|
|
- },
|
|
|
|
- .pm_config = {
|
|
|
|
- .host_clk_settling_time = 5000,
|
|
|
|
- .host_fast_wakeup_support = false
|
|
|
|
- },
|
|
|
|
- .roam_trigger = {
|
|
|
|
- .trigger_pacing = 1,
|
|
|
|
- .avg_weight_rssi_beacon = 20,
|
|
|
|
- .avg_weight_rssi_data = 10,
|
|
|
|
- .avg_weight_snr_beacon = 20,
|
|
|
|
- .avg_weight_snr_data = 10,
|
|
|
|
- },
|
|
|
|
- .scan = {
|
|
|
|
- .min_dwell_time_active = 7500,
|
|
|
|
- .max_dwell_time_active = 30000,
|
|
|
|
- .min_dwell_time_passive = 100000,
|
|
|
|
- .max_dwell_time_passive = 100000,
|
|
|
|
- .num_probe_reqs = 2,
|
|
|
|
- .split_scan_timeout = 50000,
|
|
|
|
- },
|
|
|
|
- .sched_scan = {
|
|
|
|
- /* sched_scan requires dwell times in TU instead of TU/1000 */
|
|
|
|
- .min_dwell_time_active = 30,
|
|
|
|
- .max_dwell_time_active = 60,
|
|
|
|
- .dwell_time_passive = 100,
|
|
|
|
- .dwell_time_dfs = 150,
|
|
|
|
- .num_probe_reqs = 2,
|
|
|
|
- .rssi_threshold = -90,
|
|
|
|
- .snr_threshold = 0,
|
|
|
|
- },
|
|
|
|
- .rf = {
|
|
|
|
- .tx_per_channel_power_compensation_2 = {
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- },
|
|
|
|
- .tx_per_channel_power_compensation_5 = {
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- },
|
|
|
|
- },
|
|
|
|
- .ht = {
|
|
|
|
- .rx_ba_win_size = 8,
|
|
|
|
- .tx_ba_win_size = 64,
|
|
|
|
- .inactivity_timeout = 10000,
|
|
|
|
- .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
|
|
|
|
- },
|
|
|
|
- .mem_wl127x = {
|
|
|
|
- .num_stations = 1,
|
|
|
|
- .ssid_profiles = 1,
|
|
|
|
- .rx_block_num = 70,
|
|
|
|
- .tx_min_block_num = 40,
|
|
|
|
- .dynamic_memory = 1,
|
|
|
|
- .min_req_tx_blocks = 100,
|
|
|
|
- .min_req_rx_blocks = 22,
|
|
|
|
- .tx_min = 27,
|
|
|
|
- },
|
|
|
|
- .mem_wl128x = {
|
|
|
|
- .num_stations = 1,
|
|
|
|
- .ssid_profiles = 1,
|
|
|
|
- .rx_block_num = 40,
|
|
|
|
- .tx_min_block_num = 40,
|
|
|
|
- .dynamic_memory = 1,
|
|
|
|
- .min_req_tx_blocks = 45,
|
|
|
|
- .min_req_rx_blocks = 22,
|
|
|
|
- .tx_min = 27,
|
|
|
|
- },
|
|
|
|
- .fm_coex = {
|
|
|
|
- .enable = true,
|
|
|
|
- .swallow_period = 5,
|
|
|
|
- .n_divider_fref_set_1 = 0xff, /* default */
|
|
|
|
- .n_divider_fref_set_2 = 12,
|
|
|
|
- .m_divider_fref_set_1 = 148,
|
|
|
|
- .m_divider_fref_set_2 = 0xffff, /* default */
|
|
|
|
- .coex_pll_stabilization_time = 0xffffffff, /* default */
|
|
|
|
- .ldo_stabilization_time = 0xffff, /* default */
|
|
|
|
- .fm_disturbed_band_margin = 0xff, /* default */
|
|
|
|
- .swallow_clk_diff = 0xff, /* default */
|
|
|
|
- },
|
|
|
|
- .rx_streaming = {
|
|
|
|
- .duration = 150,
|
|
|
|
- .queues = 0x1,
|
|
|
|
- .interval = 20,
|
|
|
|
- .always = 0,
|
|
|
|
- },
|
|
|
|
- .fwlog = {
|
|
|
|
- .mode = WL12XX_FWLOG_ON_DEMAND,
|
|
|
|
- .mem_blocks = 2,
|
|
|
|
- .severity = 0,
|
|
|
|
- .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
|
|
|
|
- .output = WL12XX_FWLOG_OUTPUT_HOST,
|
|
|
|
- .threshold = 0,
|
|
|
|
- },
|
|
|
|
- .hci_io_ds = HCI_IO_DS_6MA,
|
|
|
|
- .rate = {
|
|
|
|
- .rate_retry_score = 32000,
|
|
|
|
- .per_add = 8192,
|
|
|
|
- .per_th1 = 2048,
|
|
|
|
- .per_th2 = 4096,
|
|
|
|
- .max_per = 8100,
|
|
|
|
- .inverse_curiosity_factor = 5,
|
|
|
|
- .tx_fail_low_th = 4,
|
|
|
|
- .tx_fail_high_th = 10,
|
|
|
|
- .per_alpha_shift = 4,
|
|
|
|
- .per_add_shift = 13,
|
|
|
|
- .per_beta1_shift = 10,
|
|
|
|
- .per_beta2_shift = 8,
|
|
|
|
- .rate_check_up = 2,
|
|
|
|
- .rate_check_down = 12,
|
|
|
|
- .rate_retry_policy = {
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
- 0x00, 0x00, 0x00,
|
|
|
|
- },
|
|
|
|
- },
|
|
|
|
- .hangover = {
|
|
|
|
- .recover_time = 0,
|
|
|
|
- .hangover_period = 20,
|
|
|
|
- .dynamic_mode = 1,
|
|
|
|
- .early_termination_mode = 1,
|
|
|
|
- .max_period = 20,
|
|
|
|
- .min_period = 1,
|
|
|
|
- .increase_delta = 1,
|
|
|
|
- .decrease_delta = 2,
|
|
|
|
- .quiet_time = 4,
|
|
|
|
- .increase_time = 1,
|
|
|
|
- .window_size = 16,
|
|
|
|
- },
|
|
|
|
-};
|
|
|
|
|
|
+#define WL1271_BOOT_RETRIES 3
|
|
|
|
|
|
static char *fwlog_param;
|
|
static char *fwlog_param;
|
|
static bool bug_on_recovery;
|
|
static bool bug_on_recovery;
|
|
|
|
+static bool no_recovery;
|
|
|
|
|
|
static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|
static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_vif *vif,
|
|
@@ -628,22 +300,8 @@ out:
|
|
mutex_unlock(&wl->mutex);
|
|
mutex_unlock(&wl->mutex);
|
|
}
|
|
}
|
|
|
|
|
|
-static void wl1271_conf_init(struct wl1271 *wl)
|
|
|
|
|
|
+static void wlcore_adjust_conf(struct wl1271 *wl)
|
|
{
|
|
{
|
|
-
|
|
|
|
- /*
|
|
|
|
- * This function applies the default configuration to the driver. This
|
|
|
|
- * function is invoked upon driver load (spi probe.)
|
|
|
|
- *
|
|
|
|
- * The configuration is stored in a run-time structure in order to
|
|
|
|
- * facilitate for run-time adjustment of any of the parameters. Making
|
|
|
|
- * changes to the configuration structure will apply the new values on
|
|
|
|
- * the next interface up (wl1271_op_start.)
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- /* apply driver default configuration */
|
|
|
|
- memcpy(&wl->conf, &default_conf, sizeof(default_conf));
|
|
|
|
-
|
|
|
|
/* Adjust settings according to optional module parameters */
|
|
/* Adjust settings according to optional module parameters */
|
|
if (fwlog_param) {
|
|
if (fwlog_param) {
|
|
if (!strcmp(fwlog_param, "continuous")) {
|
|
if (!strcmp(fwlog_param, "continuous")) {
|
|
@@ -666,28 +324,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- ret = wl128x_cmd_general_parms(wl);
|
|
|
|
- else
|
|
|
|
- ret = wl1271_cmd_general_parms(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return ret;
|
|
|
|
-
|
|
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- ret = wl128x_cmd_radio_parms(wl);
|
|
|
|
- else
|
|
|
|
- ret = wl1271_cmd_radio_parms(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return ret;
|
|
|
|
-
|
|
|
|
- if (wl->chip.id != CHIP_ID_1283_PG20) {
|
|
|
|
- ret = wl1271_cmd_ext_radio_parms(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Chip-specific initializations */
|
|
|
|
- ret = wl1271_chip_specific_init(wl);
|
|
|
|
|
|
+ ret = wl->ops->hw_init(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
@@ -750,7 +387,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
|
|
|
|
|
|
static void wl12xx_irq_update_links_status(struct wl1271 *wl,
|
|
static void wl12xx_irq_update_links_status(struct wl1271 *wl,
|
|
struct wl12xx_vif *wlvif,
|
|
struct wl12xx_vif *wlvif,
|
|
- struct wl12xx_fw_status *status)
|
|
|
|
|
|
+ struct wl_fw_status *status)
|
|
{
|
|
{
|
|
struct wl1271_link *lnk;
|
|
struct wl1271_link *lnk;
|
|
u32 cur_fw_ps_map;
|
|
u32 cur_fw_ps_map;
|
|
@@ -770,9 +407,10 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
|
|
|
|
|
|
for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) {
|
|
for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) {
|
|
lnk = &wl->links[hlid];
|
|
lnk = &wl->links[hlid];
|
|
- cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts;
|
|
|
|
|
|
+ cnt = status->counters.tx_lnk_free_pkts[hlid] -
|
|
|
|
+ lnk->prev_freed_pkts;
|
|
|
|
|
|
- lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid];
|
|
|
|
|
|
+ lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[hlid];
|
|
lnk->allocated_pkts -= cnt;
|
|
lnk->allocated_pkts -= cnt;
|
|
|
|
|
|
wl12xx_irq_ps_regulate_link(wl, wlvif, hlid,
|
|
wl12xx_irq_ps_regulate_link(wl, wlvif, hlid,
|
|
@@ -781,15 +419,19 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
|
|
}
|
|
}
|
|
|
|
|
|
static void wl12xx_fw_status(struct wl1271 *wl,
|
|
static void wl12xx_fw_status(struct wl1271 *wl,
|
|
- struct wl12xx_fw_status *status)
|
|
|
|
|
|
+ struct wl_fw_status *status)
|
|
{
|
|
{
|
|
struct wl12xx_vif *wlvif;
|
|
struct wl12xx_vif *wlvif;
|
|
struct timespec ts;
|
|
struct timespec ts;
|
|
u32 old_tx_blk_count = wl->tx_blocks_available;
|
|
u32 old_tx_blk_count = wl->tx_blocks_available;
|
|
int avail, freed_blocks;
|
|
int avail, freed_blocks;
|
|
int i;
|
|
int i;
|
|
|
|
+ size_t status_len;
|
|
|
|
+
|
|
|
|
+ status_len = sizeof(*status) + wl->fw_status_priv_len;
|
|
|
|
|
|
- wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
|
|
|
|
|
|
+ wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status,
|
|
|
|
+ status_len, false);
|
|
|
|
|
|
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
|
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
|
"drv_rx_counter = %d, tx_results_counter = %d)",
|
|
"drv_rx_counter = %d, tx_results_counter = %d)",
|
|
@@ -801,10 +443,10 @@ static void wl12xx_fw_status(struct wl1271 *wl,
|
|
for (i = 0; i < NUM_TX_QUEUES; i++) {
|
|
for (i = 0; i < NUM_TX_QUEUES; i++) {
|
|
/* prevent wrap-around in freed-packets counter */
|
|
/* prevent wrap-around in freed-packets counter */
|
|
wl->tx_allocated_pkts[i] -=
|
|
wl->tx_allocated_pkts[i] -=
|
|
- (status->tx_released_pkts[i] -
|
|
|
|
|
|
+ (status->counters.tx_released_pkts[i] -
|
|
wl->tx_pkts_freed[i]) & 0xff;
|
|
wl->tx_pkts_freed[i]) & 0xff;
|
|
|
|
|
|
- wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
|
|
|
|
|
|
+ wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
|
|
}
|
|
}
|
|
|
|
|
|
/* prevent wrap-around in total blocks counter */
|
|
/* prevent wrap-around in total blocks counter */
|
|
@@ -927,6 +569,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
|
|
smp_mb__after_clear_bit();
|
|
smp_mb__after_clear_bit();
|
|
|
|
|
|
wl12xx_fw_status(wl, wl->fw_status);
|
|
wl12xx_fw_status(wl, wl->fw_status);
|
|
|
|
+
|
|
|
|
+ wlcore_hw_tx_immediate_compl(wl);
|
|
|
|
+
|
|
intr = le32_to_cpu(wl->fw_status->intr);
|
|
intr = le32_to_cpu(wl->fw_status->intr);
|
|
intr &= WL1271_INTR_MASK;
|
|
intr &= WL1271_INTR_MASK;
|
|
if (!intr) {
|
|
if (!intr) {
|
|
@@ -963,9 +608,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
|
|
}
|
|
}
|
|
|
|
|
|
/* check for tx results */
|
|
/* check for tx results */
|
|
- if (wl->fw_status->tx_results_counter !=
|
|
|
|
- (wl->tx_results_count & 0xff))
|
|
|
|
- wl1271_tx_complete(wl);
|
|
|
|
|
|
+ wlcore_hw_tx_delayed_compl(wl);
|
|
|
|
|
|
/* Make sure the deferred queues don't get too long */
|
|
/* Make sure the deferred queues don't get too long */
|
|
defer_count = skb_queue_len(&wl->deferred_tx_queue) +
|
|
defer_count = skb_queue_len(&wl->deferred_tx_queue) +
|
|
@@ -1046,10 +689,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
|
|
|
|
|
|
if (plt) {
|
|
if (plt) {
|
|
fw_type = WL12XX_FW_TYPE_PLT;
|
|
fw_type = WL12XX_FW_TYPE_PLT;
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- fw_name = WL128X_PLT_FW_NAME;
|
|
|
|
- else
|
|
|
|
- fw_name = WL127X_PLT_FW_NAME;
|
|
|
|
|
|
+ fw_name = wl->plt_fw_name;
|
|
} else {
|
|
} else {
|
|
/*
|
|
/*
|
|
* we can't call wl12xx_get_vif_count() here because
|
|
* we can't call wl12xx_get_vif_count() here because
|
|
@@ -1057,16 +697,10 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
|
|
*/
|
|
*/
|
|
if (wl->last_vif_count > 1) {
|
|
if (wl->last_vif_count > 1) {
|
|
fw_type = WL12XX_FW_TYPE_MULTI;
|
|
fw_type = WL12XX_FW_TYPE_MULTI;
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- fw_name = WL128X_FW_NAME_MULTI;
|
|
|
|
- else
|
|
|
|
- fw_name = WL127X_FW_NAME_MULTI;
|
|
|
|
|
|
+ fw_name = wl->mr_fw_name;
|
|
} else {
|
|
} else {
|
|
fw_type = WL12XX_FW_TYPE_NORMAL;
|
|
fw_type = WL12XX_FW_TYPE_NORMAL;
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- fw_name = WL128X_FW_NAME_SINGLE;
|
|
|
|
- else
|
|
|
|
- fw_name = WL127X_FW_NAME_SINGLE;
|
|
|
|
|
|
+ fw_name = wl->sr_fw_name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1173,7 +807,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
|
u32 first_addr;
|
|
u32 first_addr;
|
|
u8 *block;
|
|
u8 *block;
|
|
|
|
|
|
- if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
|
|
|
|
|
|
+ if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
|
|
(wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
|
|
(wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
|
|
(wl->conf.fwlog.mem_blocks == 0))
|
|
(wl->conf.fwlog.mem_blocks == 0))
|
|
return;
|
|
return;
|
|
@@ -1239,11 +873,20 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|
wl12xx_read_fwlog_panic(wl);
|
|
wl12xx_read_fwlog_panic(wl);
|
|
|
|
|
|
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
|
|
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
|
|
- wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
|
|
|
|
|
|
+ wl->chip.fw_ver_str,
|
|
|
|
+ wlcore_read_reg(wl, REG_PC_ON_RECOVERY));
|
|
|
|
|
|
BUG_ON(bug_on_recovery &&
|
|
BUG_ON(bug_on_recovery &&
|
|
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
|
|
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
|
|
|
|
|
|
|
|
+ if (no_recovery) {
|
|
|
|
+ wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
|
|
|
|
+ clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
|
|
|
+ goto out_unlock;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BUG_ON(bug_on_recovery);
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Advance security sequence number to overcome potential progress
|
|
* Advance security sequence number to overcome potential progress
|
|
* in the firmware during recovery. This doens't hurt if the network is
|
|
* in the firmware during recovery. This doens't hurt if the network is
|
|
@@ -1290,10 +933,7 @@ out_unlock:
|
|
|
|
|
|
static void wl1271_fw_wakeup(struct wl1271 *wl)
|
|
static void wl1271_fw_wakeup(struct wl1271 *wl)
|
|
{
|
|
{
|
|
- u32 elp_reg;
|
|
|
|
-
|
|
|
|
- elp_reg = ELPCTRL_WAKE_UP;
|
|
|
|
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
|
|
|
|
|
|
+ wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
|
|
}
|
|
}
|
|
|
|
|
|
static int wl1271_setup(struct wl1271 *wl)
|
|
static int wl1271_setup(struct wl1271 *wl)
|
|
@@ -1323,7 +963,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl)
|
|
wl1271_io_reset(wl);
|
|
wl1271_io_reset(wl);
|
|
wl1271_io_init(wl);
|
|
wl1271_io_init(wl);
|
|
|
|
|
|
- wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
|
|
|
|
|
|
+ wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
|
|
|
|
|
|
/* ELP module wake up */
|
|
/* ELP module wake up */
|
|
wl1271_fw_wakeup(wl);
|
|
wl1271_fw_wakeup(wl);
|
|
@@ -1348,44 +988,18 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
|
|
* negligible, we use the same block size for all different
|
|
* negligible, we use the same block size for all different
|
|
* chip types.
|
|
* chip types.
|
|
*/
|
|
*/
|
|
- if (!wl1271_set_block_size(wl))
|
|
|
|
- wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
|
|
|
|
-
|
|
|
|
- switch (wl->chip.id) {
|
|
|
|
- case CHIP_ID_1271_PG10:
|
|
|
|
- wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
|
|
|
|
- wl->chip.id);
|
|
|
|
|
|
+ if (wl1271_set_block_size(wl))
|
|
|
|
+ wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
|
|
|
|
|
|
- ret = wl1271_setup(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- goto out;
|
|
|
|
- wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case CHIP_ID_1271_PG20:
|
|
|
|
- wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
|
|
|
|
- wl->chip.id);
|
|
|
|
-
|
|
|
|
- ret = wl1271_setup(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- goto out;
|
|
|
|
- wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
|
|
|
|
- break;
|
|
|
|
|
|
+ ret = wl->ops->identify_chip(wl);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ goto out;
|
|
|
|
|
|
- case CHIP_ID_1283_PG20:
|
|
|
|
- wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
|
|
|
|
- wl->chip.id);
|
|
|
|
|
|
+ /* TODO: make sure the lower driver has set things up correctly */
|
|
|
|
|
|
- ret = wl1271_setup(wl);
|
|
|
|
- if (ret < 0)
|
|
|
|
- goto out;
|
|
|
|
- break;
|
|
|
|
- case CHIP_ID_1283_PG10:
|
|
|
|
- default:
|
|
|
|
- wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
|
|
|
|
- ret = -ENODEV;
|
|
|
|
|
|
+ ret = wl1271_setup(wl);
|
|
|
|
+ if (ret < 0)
|
|
goto out;
|
|
goto out;
|
|
- }
|
|
|
|
|
|
|
|
ret = wl12xx_fetch_firmware(wl, plt);
|
|
ret = wl12xx_fetch_firmware(wl, plt);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -1425,7 +1039,7 @@ int wl1271_plt_start(struct wl1271 *wl)
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto power_off;
|
|
goto power_off;
|
|
|
|
|
|
- ret = wl1271_boot(wl);
|
|
|
|
|
|
+ ret = wl->ops->boot(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto power_off;
|
|
goto power_off;
|
|
|
|
|
|
@@ -1454,7 +1068,7 @@ irq_disable:
|
|
work function will not do anything.) Also, any other
|
|
work function will not do anything.) Also, any other
|
|
possible concurrent operations will fail due to the
|
|
possible concurrent operations will fail due to the
|
|
current state, hence the wl1271 struct should be safe. */
|
|
current state, hence the wl1271 struct should be safe. */
|
|
- wl1271_disable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_disable_interrupts(wl);
|
|
wl1271_flush_deferred_work(wl);
|
|
wl1271_flush_deferred_work(wl);
|
|
cancel_work_sync(&wl->netstack_work);
|
|
cancel_work_sync(&wl->netstack_work);
|
|
mutex_lock(&wl->mutex);
|
|
mutex_lock(&wl->mutex);
|
|
@@ -1481,7 +1095,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
|
|
* Otherwise, the interrupt handler might be called and exit without
|
|
* Otherwise, the interrupt handler might be called and exit without
|
|
* reading the interrupt status.
|
|
* reading the interrupt status.
|
|
*/
|
|
*/
|
|
- wl1271_disable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_disable_interrupts(wl);
|
|
mutex_lock(&wl->mutex);
|
|
mutex_lock(&wl->mutex);
|
|
if (!wl->plt) {
|
|
if (!wl->plt) {
|
|
mutex_unlock(&wl->mutex);
|
|
mutex_unlock(&wl->mutex);
|
|
@@ -1491,7 +1105,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
|
|
* may have been disabled when op_stop was called. It will,
|
|
* may have been disabled when op_stop was called. It will,
|
|
* however, balance the above call to disable_interrupts().
|
|
* however, balance the above call to disable_interrupts().
|
|
*/
|
|
*/
|
|
- wl1271_enable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_enable_interrupts(wl);
|
|
|
|
|
|
wl1271_error("cannot power down because not in PLT "
|
|
wl1271_error("cannot power down because not in PLT "
|
|
"state: %d", wl->state);
|
|
"state: %d", wl->state);
|
|
@@ -1652,14 +1266,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- mutex_lock(&wl->mutex);
|
|
|
|
-
|
|
|
|
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
|
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
|
- goto out_unlock;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
- goto out_unlock;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
wl->conf.conn.suspend_wake_up_event,
|
|
wl->conf.conn.suspend_wake_up_event,
|
|
@@ -1668,11 +1280,9 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
wl1271_error("suspend: set wake up conditions failed: %d", ret);
|
|
wl1271_error("suspend: set wake up conditions failed: %d", ret);
|
|
|
|
|
|
-
|
|
|
|
wl1271_ps_elp_sleep(wl);
|
|
wl1271_ps_elp_sleep(wl);
|
|
|
|
|
|
-out_unlock:
|
|
|
|
- mutex_unlock(&wl->mutex);
|
|
|
|
|
|
+out:
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1682,20 +1292,17 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl,
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- mutex_lock(&wl->mutex);
|
|
|
|
-
|
|
|
|
if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
|
|
if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
|
|
- goto out_unlock;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
- goto out_unlock;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
|
|
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
|
|
|
|
|
|
wl1271_ps_elp_sleep(wl);
|
|
wl1271_ps_elp_sleep(wl);
|
|
-out_unlock:
|
|
|
|
- mutex_unlock(&wl->mutex);
|
|
|
|
|
|
+out:
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1720,10 +1327,9 @@ static void wl1271_configure_resume(struct wl1271 *wl,
|
|
if ((!is_ap) && (!is_sta))
|
|
if ((!is_ap) && (!is_sta))
|
|
return;
|
|
return;
|
|
|
|
|
|
- mutex_lock(&wl->mutex);
|
|
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
ret = wl1271_ps_elp_wakeup(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
- goto out;
|
|
|
|
|
|
+ return;
|
|
|
|
|
|
if (is_sta) {
|
|
if (is_sta) {
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
@@ -1739,8 +1345,6 @@ static void wl1271_configure_resume(struct wl1271 *wl,
|
|
}
|
|
}
|
|
|
|
|
|
wl1271_ps_elp_sleep(wl);
|
|
wl1271_ps_elp_sleep(wl);
|
|
-out:
|
|
|
|
- mutex_unlock(&wl->mutex);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
@@ -1755,6 +1359,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
|
|
|
|
wl1271_tx_flush(wl);
|
|
wl1271_tx_flush(wl);
|
|
|
|
|
|
|
|
+ mutex_lock(&wl->mutex);
|
|
wl->wow_enabled = true;
|
|
wl->wow_enabled = true;
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
ret = wl1271_configure_suspend(wl, wlvif);
|
|
ret = wl1271_configure_suspend(wl, wlvif);
|
|
@@ -1763,6 +1368,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ mutex_unlock(&wl->mutex);
|
|
/* flush any remaining work */
|
|
/* flush any remaining work */
|
|
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
|
|
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
|
|
|
|
|
|
@@ -1770,7 +1376,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
* disable and re-enable interrupts in order to flush
|
|
* disable and re-enable interrupts in order to flush
|
|
* the threaded_irq
|
|
* the threaded_irq
|
|
*/
|
|
*/
|
|
- wl1271_disable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_disable_interrupts(wl);
|
|
|
|
|
|
/*
|
|
/*
|
|
* set suspended flag to avoid triggering a new threaded_irq
|
|
* set suspended flag to avoid triggering a new threaded_irq
|
|
@@ -1778,7 +1384,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
*/
|
|
*/
|
|
set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
|
|
set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
|
|
|
|
|
|
- wl1271_enable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_enable_interrupts(wl);
|
|
flush_work(&wl->tx_work);
|
|
flush_work(&wl->tx_work);
|
|
flush_delayed_work(&wl->elp_work);
|
|
flush_delayed_work(&wl->elp_work);
|
|
|
|
|
|
@@ -1810,12 +1416,15 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
|
|
wl1271_debug(DEBUG_MAC80211,
|
|
wl1271_debug(DEBUG_MAC80211,
|
|
"run postponed irq_work directly");
|
|
"run postponed irq_work directly");
|
|
wl1271_irq(0, wl);
|
|
wl1271_irq(0, wl);
|
|
- wl1271_enable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_enable_interrupts(wl);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ mutex_lock(&wl->mutex);
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
wl1271_configure_resume(wl, wlvif);
|
|
wl1271_configure_resume(wl, wlvif);
|
|
}
|
|
}
|
|
wl->wow_enabled = false;
|
|
wl->wow_enabled = false;
|
|
|
|
+ mutex_unlock(&wl->mutex);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -1851,7 +1460,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|
* Otherwise, the interrupt handler might be called and exit without
|
|
* Otherwise, the interrupt handler might be called and exit without
|
|
* reading the interrupt status.
|
|
* reading the interrupt status.
|
|
*/
|
|
*/
|
|
- wl1271_disable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_disable_interrupts(wl);
|
|
mutex_lock(&wl->mutex);
|
|
mutex_lock(&wl->mutex);
|
|
if (wl->state == WL1271_STATE_OFF) {
|
|
if (wl->state == WL1271_STATE_OFF) {
|
|
mutex_unlock(&wl->mutex);
|
|
mutex_unlock(&wl->mutex);
|
|
@@ -1861,7 +1470,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|
* may have been disabled when op_stop was called. It will,
|
|
* may have been disabled when op_stop was called. It will,
|
|
* however, balance the above call to disable_interrupts().
|
|
* however, balance the above call to disable_interrupts().
|
|
*/
|
|
*/
|
|
- wl1271_enable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_enable_interrupts(wl);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1894,7 +1503,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|
wl->tx_results_count = 0;
|
|
wl->tx_results_count = 0;
|
|
wl->tx_packets_count = 0;
|
|
wl->tx_packets_count = 0;
|
|
wl->time_offset = 0;
|
|
wl->time_offset = 0;
|
|
- wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
|
|
|
wl->ap_fw_ps_map = 0;
|
|
wl->ap_fw_ps_map = 0;
|
|
wl->ap_ps_map = 0;
|
|
wl->ap_ps_map = 0;
|
|
wl->sched_scanning = false;
|
|
wl->sched_scanning = false;
|
|
@@ -2067,7 +1675,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl)
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto power_off;
|
|
goto power_off;
|
|
|
|
|
|
- ret = wl1271_boot(wl);
|
|
|
|
|
|
+ ret = wl->ops->boot(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto power_off;
|
|
goto power_off;
|
|
|
|
|
|
@@ -2087,7 +1695,7 @@ irq_disable:
|
|
work function will not do anything.) Also, any other
|
|
work function will not do anything.) Also, any other
|
|
possible concurrent operations will fail due to the
|
|
possible concurrent operations will fail due to the
|
|
current state, hence the wl1271 struct should be safe. */
|
|
current state, hence the wl1271 struct should be safe. */
|
|
- wl1271_disable_interrupts(wl);
|
|
|
|
|
|
+ wlcore_disable_interrupts(wl);
|
|
wl1271_flush_deferred_work(wl);
|
|
wl1271_flush_deferred_work(wl);
|
|
cancel_work_sync(&wl->netstack_work);
|
|
cancel_work_sync(&wl->netstack_work);
|
|
mutex_lock(&wl->mutex);
|
|
mutex_lock(&wl->mutex);
|
|
@@ -2360,10 +1968,12 @@ deinit:
|
|
for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
|
|
for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
|
|
wl12xx_free_rate_policy(wl,
|
|
wl12xx_free_rate_policy(wl,
|
|
&wlvif->ap.ucast_rate_idx[i]);
|
|
&wlvif->ap.ucast_rate_idx[i]);
|
|
|
|
+ wl1271_free_ap_keys(wl, wlvif);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ dev_kfree_skb(wlvif->probereq);
|
|
|
|
+ wlvif->probereq = NULL;
|
|
wl12xx_tx_reset_wlvif(wl, wlvif);
|
|
wl12xx_tx_reset_wlvif(wl, wlvif);
|
|
- wl1271_free_ap_keys(wl, wlvif);
|
|
|
|
if (wl->last_wlvif == wlvif)
|
|
if (wl->last_wlvif == wlvif)
|
|
wl->last_wlvif = NULL;
|
|
wl->last_wlvif = NULL;
|
|
list_del(&wlvif->list);
|
|
list_del(&wlvif->list);
|
|
@@ -2946,6 +2556,17 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|
int ret;
|
|
int ret;
|
|
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
|
|
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * A role set to GEM cipher requires different Tx settings (namely
|
|
|
|
+ * spare blocks). Note when we are in this mode so the HW can adjust.
|
|
|
|
+ */
|
|
|
|
+ if (key_type == KEY_GEM) {
|
|
|
|
+ if (action == KEY_ADD_OR_REPLACE)
|
|
|
|
+ wlvif->is_gem = true;
|
|
|
|
+ else if (action == KEY_REMOVE)
|
|
|
|
+ wlvif->is_gem = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (is_ap) {
|
|
if (is_ap) {
|
|
struct wl1271_station *wl_sta;
|
|
struct wl1271_station *wl_sta;
|
|
u8 hlid;
|
|
u8 hlid;
|
|
@@ -2984,17 +2605,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
};
|
|
|
|
|
|
- /*
|
|
|
|
- * A STA set to GEM cipher requires 2 tx spare blocks.
|
|
|
|
- * Return to default value when GEM cipher key is removed
|
|
|
|
- */
|
|
|
|
- if (key_type == KEY_GEM) {
|
|
|
|
- if (action == KEY_ADD_OR_REPLACE)
|
|
|
|
- wl->tx_spare_blocks = 2;
|
|
|
|
- else if (action == KEY_REMOVE)
|
|
|
|
- wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
addr = sta ? sta->addr : bcast_addr;
|
|
addr = sta ? sta->addr : bcast_addr;
|
|
|
|
|
|
if (is_zero_ether_addr(addr)) {
|
|
if (is_zero_ether_addr(addr)) {
|
|
@@ -3791,8 +3401,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|
wlvif->rssi_thold = bss_conf->cqm_rssi_thold;
|
|
wlvif->rssi_thold = bss_conf->cqm_rssi_thold;
|
|
}
|
|
}
|
|
|
|
|
|
- if (changed & BSS_CHANGED_BSSID &&
|
|
|
|
- (is_ibss || bss_conf->assoc))
|
|
|
|
|
|
+ if (changed & BSS_CHANGED_BSSID)
|
|
if (!is_zero_ether_addr(bss_conf->bssid)) {
|
|
if (!is_zero_ether_addr(bss_conf->bssid)) {
|
|
ret = wl12xx_cmd_build_null_data(wl, wlvif);
|
|
ret = wl12xx_cmd_build_null_data(wl, wlvif);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -3801,9 +3410,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|
ret = wl1271_build_qos_null_data(wl, vif);
|
|
ret = wl1271_build_qos_null_data(wl, vif);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto out;
|
|
goto out;
|
|
-
|
|
|
|
- /* Need to update the BSSID (for filtering etc) */
|
|
|
|
- do_join = true;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
|
|
if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
|
|
@@ -3830,6 +3436,7 @@ sta_not_found:
|
|
int ieoffset;
|
|
int ieoffset;
|
|
wlvif->aid = bss_conf->aid;
|
|
wlvif->aid = bss_conf->aid;
|
|
wlvif->beacon_int = bss_conf->beacon_int;
|
|
wlvif->beacon_int = bss_conf->beacon_int;
|
|
|
|
+ do_join = true;
|
|
set_assoc = true;
|
|
set_assoc = true;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -4662,60 +4269,12 @@ static struct ieee80211_channel wl1271_channels[] = {
|
|
{ .hw_value = 14, .center_freq = 2484, .max_power = 25 },
|
|
{ .hw_value = 14, .center_freq = 2484, .max_power = 25 },
|
|
};
|
|
};
|
|
|
|
|
|
-/* mapping to indexes for wl1271_rates */
|
|
|
|
-static const u8 wl1271_rate_to_idx_2ghz[] = {
|
|
|
|
- /* MCS rates are used only with 11n */
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_MCS7 */
|
|
|
|
- 6, /* CONF_HW_RXTX_RATE_MCS6 */
|
|
|
|
- 5, /* CONF_HW_RXTX_RATE_MCS5 */
|
|
|
|
- 4, /* CONF_HW_RXTX_RATE_MCS4 */
|
|
|
|
- 3, /* CONF_HW_RXTX_RATE_MCS3 */
|
|
|
|
- 2, /* CONF_HW_RXTX_RATE_MCS2 */
|
|
|
|
- 1, /* CONF_HW_RXTX_RATE_MCS1 */
|
|
|
|
- 0, /* CONF_HW_RXTX_RATE_MCS0 */
|
|
|
|
-
|
|
|
|
- 11, /* CONF_HW_RXTX_RATE_54 */
|
|
|
|
- 10, /* CONF_HW_RXTX_RATE_48 */
|
|
|
|
- 9, /* CONF_HW_RXTX_RATE_36 */
|
|
|
|
- 8, /* CONF_HW_RXTX_RATE_24 */
|
|
|
|
-
|
|
|
|
- /* TI-specific rate */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */
|
|
|
|
-
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_18 */
|
|
|
|
- 6, /* CONF_HW_RXTX_RATE_12 */
|
|
|
|
- 3, /* CONF_HW_RXTX_RATE_11 */
|
|
|
|
- 5, /* CONF_HW_RXTX_RATE_9 */
|
|
|
|
- 4, /* CONF_HW_RXTX_RATE_6 */
|
|
|
|
- 2, /* CONF_HW_RXTX_RATE_5_5 */
|
|
|
|
- 1, /* CONF_HW_RXTX_RATE_2 */
|
|
|
|
- 0 /* CONF_HW_RXTX_RATE_1 */
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/* 11n STA capabilities */
|
|
|
|
-#define HW_RX_HIGHEST_RATE 72
|
|
|
|
-
|
|
|
|
-#define WL12XX_HT_CAP { \
|
|
|
|
- .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
|
|
|
|
- (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
|
|
|
|
- .ht_supported = true, \
|
|
|
|
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \
|
|
|
|
- .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \
|
|
|
|
- .mcs = { \
|
|
|
|
- .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
|
|
|
|
- .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \
|
|
|
|
- .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
|
|
|
|
- }, \
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* can't be const, mac80211 writes to this */
|
|
/* can't be const, mac80211 writes to this */
|
|
static struct ieee80211_supported_band wl1271_band_2ghz = {
|
|
static struct ieee80211_supported_band wl1271_band_2ghz = {
|
|
.channels = wl1271_channels,
|
|
.channels = wl1271_channels,
|
|
.n_channels = ARRAY_SIZE(wl1271_channels),
|
|
.n_channels = ARRAY_SIZE(wl1271_channels),
|
|
.bitrates = wl1271_rates,
|
|
.bitrates = wl1271_rates,
|
|
.n_bitrates = ARRAY_SIZE(wl1271_rates),
|
|
.n_bitrates = ARRAY_SIZE(wl1271_rates),
|
|
- .ht_cap = WL12XX_HT_CAP,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
/* 5 GHz data rates for WL1273 */
|
|
/* 5 GHz data rates for WL1273 */
|
|
@@ -4784,48 +4343,11 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
|
|
{ .hw_value = 165, .center_freq = 5825, .max_power = 25 },
|
|
{ .hw_value = 165, .center_freq = 5825, .max_power = 25 },
|
|
};
|
|
};
|
|
|
|
|
|
-/* mapping to indexes for wl1271_rates_5ghz */
|
|
|
|
-static const u8 wl1271_rate_to_idx_5ghz[] = {
|
|
|
|
- /* MCS rates are used only with 11n */
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_MCS7 */
|
|
|
|
- 6, /* CONF_HW_RXTX_RATE_MCS6 */
|
|
|
|
- 5, /* CONF_HW_RXTX_RATE_MCS5 */
|
|
|
|
- 4, /* CONF_HW_RXTX_RATE_MCS4 */
|
|
|
|
- 3, /* CONF_HW_RXTX_RATE_MCS3 */
|
|
|
|
- 2, /* CONF_HW_RXTX_RATE_MCS2 */
|
|
|
|
- 1, /* CONF_HW_RXTX_RATE_MCS1 */
|
|
|
|
- 0, /* CONF_HW_RXTX_RATE_MCS0 */
|
|
|
|
-
|
|
|
|
- 7, /* CONF_HW_RXTX_RATE_54 */
|
|
|
|
- 6, /* CONF_HW_RXTX_RATE_48 */
|
|
|
|
- 5, /* CONF_HW_RXTX_RATE_36 */
|
|
|
|
- 4, /* CONF_HW_RXTX_RATE_24 */
|
|
|
|
-
|
|
|
|
- /* TI-specific rate */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */
|
|
|
|
-
|
|
|
|
- 3, /* CONF_HW_RXTX_RATE_18 */
|
|
|
|
- 2, /* CONF_HW_RXTX_RATE_12 */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */
|
|
|
|
- 1, /* CONF_HW_RXTX_RATE_9 */
|
|
|
|
- 0, /* CONF_HW_RXTX_RATE_6 */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */
|
|
|
|
- CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
static struct ieee80211_supported_band wl1271_band_5ghz = {
|
|
static struct ieee80211_supported_band wl1271_band_5ghz = {
|
|
.channels = wl1271_channels_5ghz,
|
|
.channels = wl1271_channels_5ghz,
|
|
.n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
|
|
.n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
|
|
.bitrates = wl1271_rates_5ghz,
|
|
.bitrates = wl1271_rates_5ghz,
|
|
.n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
|
|
.n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
|
|
- .ht_cap = WL12XX_HT_CAP,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static const u8 *wl1271_band_rate_to_idx[] = {
|
|
|
|
- [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz,
|
|
|
|
- [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz
|
|
|
|
};
|
|
};
|
|
|
|
|
|
static const struct ieee80211_ops wl1271_ops = {
|
|
static const struct ieee80211_ops wl1271_ops = {
|
|
@@ -4862,18 +4384,18 @@ static const struct ieee80211_ops wl1271_ops = {
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band)
|
|
|
|
|
|
+u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band)
|
|
{
|
|
{
|
|
u8 idx;
|
|
u8 idx;
|
|
|
|
|
|
- BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *));
|
|
|
|
|
|
+ BUG_ON(band >= 2);
|
|
|
|
|
|
- if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) {
|
|
|
|
|
|
+ if (unlikely(rate >= wl->hw_tx_rate_tbl_size)) {
|
|
wl1271_error("Illegal RX rate from HW: %d", rate);
|
|
wl1271_error("Illegal RX rate from HW: %d", rate);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- idx = wl1271_band_rate_to_idx[band][rate];
|
|
|
|
|
|
+ idx = wl->band_rate_to_idx[band][rate];
|
|
if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) {
|
|
if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) {
|
|
wl1271_error("Unsupported RX rate from HW: %d", rate);
|
|
wl1271_error("Unsupported RX rate from HW: %d", rate);
|
|
return 0;
|
|
return 0;
|
|
@@ -5027,34 +4549,6 @@ static struct bin_attribute fwlog_attr = {
|
|
.read = wl1271_sysfs_read_fwlog,
|
|
.read = wl1271_sysfs_read_fwlog,
|
|
};
|
|
};
|
|
|
|
|
|
-static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
|
|
|
|
-{
|
|
|
|
- bool supported = false;
|
|
|
|
- u8 major, minor;
|
|
|
|
-
|
|
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20) {
|
|
|
|
- major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
|
|
|
|
- minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
|
|
|
|
-
|
|
|
|
- /* in wl128x we have the MAC address if the PG is >= (2, 1) */
|
|
|
|
- if (major > 2 || (major == 2 && minor >= 1))
|
|
|
|
- supported = true;
|
|
|
|
- } else {
|
|
|
|
- major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
|
|
|
|
- minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
|
|
|
|
-
|
|
|
|
- /* in wl127x we have the MAC address if the PG is >= (3, 1) */
|
|
|
|
- if (major == 3 && minor >= 1)
|
|
|
|
- supported = true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- wl1271_debug(DEBUG_PROBE,
|
|
|
|
- "PG Ver major = %d minor = %d, MAC %s present",
|
|
|
|
- major, minor, supported ? "is" : "is not");
|
|
|
|
-
|
|
|
|
- return supported;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
|
|
static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
|
|
u32 oui, u32 nic, int n)
|
|
u32 oui, u32 nic, int n)
|
|
{
|
|
{
|
|
@@ -5080,47 +4574,23 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
|
|
wl->hw->wiphy->addresses = wl->addresses;
|
|
wl->hw->wiphy->addresses = wl->addresses;
|
|
}
|
|
}
|
|
|
|
|
|
-static void wl12xx_get_fuse_mac(struct wl1271 *wl)
|
|
|
|
-{
|
|
|
|
- u32 mac1, mac2;
|
|
|
|
-
|
|
|
|
- wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
|
|
|
|
-
|
|
|
|
- mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
|
|
|
|
- mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
|
|
|
|
-
|
|
|
|
- /* these are the two parts of the BD_ADDR */
|
|
|
|
- wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
|
|
|
|
- ((mac1 & 0xff000000) >> 24);
|
|
|
|
- wl->fuse_nic_addr = mac1 & 0xffffff;
|
|
|
|
-
|
|
|
|
- wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int wl12xx_get_hw_info(struct wl1271 *wl)
|
|
static int wl12xx_get_hw_info(struct wl1271 *wl)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
- u32 die_info;
|
|
|
|
|
|
|
|
ret = wl12xx_set_power_on(wl);
|
|
ret = wl12xx_set_power_on(wl);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
|
|
|
|
|
|
+ wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B);
|
|
|
|
|
|
- if (wl->chip.id == CHIP_ID_1283_PG20)
|
|
|
|
- die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
|
|
|
|
- else
|
|
|
|
- die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
|
|
|
|
|
|
+ wl->fuse_oui_addr = 0;
|
|
|
|
+ wl->fuse_nic_addr = 0;
|
|
|
|
|
|
- wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
|
|
|
|
|
|
+ wl->hw_pg_ver = wl->ops->get_pg_ver(wl);
|
|
|
|
|
|
- if (!wl12xx_mac_in_fuse(wl)) {
|
|
|
|
- wl->fuse_oui_addr = 0;
|
|
|
|
- wl->fuse_nic_addr = 0;
|
|
|
|
- } else {
|
|
|
|
- wl12xx_get_fuse_mac(wl);
|
|
|
|
- }
|
|
|
|
|
|
+ if (wl->ops->get_mac)
|
|
|
|
+ wl->ops->get_mac(wl);
|
|
|
|
|
|
wl1271_power_off(wl);
|
|
wl1271_power_off(wl);
|
|
out:
|
|
out:
|
|
@@ -5255,8 +4725,12 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|
*/
|
|
*/
|
|
memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz,
|
|
memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz,
|
|
sizeof(wl1271_band_2ghz));
|
|
sizeof(wl1271_band_2ghz));
|
|
|
|
+ memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, &wl->ht_cap,
|
|
|
|
+ sizeof(wl->ht_cap));
|
|
memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz,
|
|
memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz,
|
|
sizeof(wl1271_band_5ghz));
|
|
sizeof(wl1271_band_5ghz));
|
|
|
|
+ memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, &wl->ht_cap,
|
|
|
|
+ sizeof(wl->ht_cap));
|
|
|
|
|
|
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
|
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
|
&wl->bands[IEEE80211_BAND_2GHZ];
|
|
&wl->bands[IEEE80211_BAND_2GHZ];
|
|
@@ -5280,14 +4754,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|
wl->hw->sta_data_size = sizeof(struct wl1271_station);
|
|
wl->hw->sta_data_size = sizeof(struct wl1271_station);
|
|
wl->hw->vif_data_size = sizeof(struct wl12xx_vif);
|
|
wl->hw->vif_data_size = sizeof(struct wl12xx_vif);
|
|
|
|
|
|
- wl->hw->max_rx_aggregation_subframes = 8;
|
|
|
|
|
|
+ wl->hw->max_rx_aggregation_subframes = wl->conf.ht.rx_ba_win_size;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
#define WL1271_DEFAULT_CHANNEL 0
|
|
#define WL1271_DEFAULT_CHANNEL 0
|
|
|
|
|
|
-static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
|
|
|
|
+struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
|
|
{
|
|
{
|
|
struct ieee80211_hw *hw;
|
|
struct ieee80211_hw *hw;
|
|
struct wl1271 *wl;
|
|
struct wl1271 *wl;
|
|
@@ -5306,6 +4780,13 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
wl = hw->priv;
|
|
wl = hw->priv;
|
|
memset(wl, 0, sizeof(*wl));
|
|
memset(wl, 0, sizeof(*wl));
|
|
|
|
|
|
|
|
+ wl->priv = kzalloc(priv_size, GFP_KERNEL);
|
|
|
|
+ if (!wl->priv) {
|
|
|
|
+ wl1271_error("could not alloc wl priv");
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ goto err_priv_alloc;
|
|
|
|
+ }
|
|
|
|
+
|
|
INIT_LIST_HEAD(&wl->wlvif_list);
|
|
INIT_LIST_HEAD(&wl->wlvif_list);
|
|
|
|
|
|
wl->hw = hw;
|
|
wl->hw = hw;
|
|
@@ -5342,7 +4823,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
wl->quirks = 0;
|
|
wl->quirks = 0;
|
|
wl->platform_quirks = 0;
|
|
wl->platform_quirks = 0;
|
|
wl->sched_scanning = false;
|
|
wl->sched_scanning = false;
|
|
- wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
|
|
|
wl->system_hlid = WL12XX_SYSTEM_HLID;
|
|
wl->system_hlid = WL12XX_SYSTEM_HLID;
|
|
wl->active_sta_count = 0;
|
|
wl->active_sta_count = 0;
|
|
wl->fwlog_size = 0;
|
|
wl->fwlog_size = 0;
|
|
@@ -5352,7 +4832,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
|
|
__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
|
|
|
|
|
|
memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
|
|
memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
|
|
- for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
|
|
|
|
|
|
+ for (i = 0; i < wl->num_tx_desc; i++)
|
|
wl->tx_frames[i] = NULL;
|
|
wl->tx_frames[i] = NULL;
|
|
|
|
|
|
spin_lock_init(&wl->wl_lock);
|
|
spin_lock_init(&wl->wl_lock);
|
|
@@ -5361,9 +4841,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
wl->fw_type = WL12XX_FW_TYPE_NONE;
|
|
wl->fw_type = WL12XX_FW_TYPE_NONE;
|
|
mutex_init(&wl->mutex);
|
|
mutex_init(&wl->mutex);
|
|
|
|
|
|
- /* Apply default driver configuration. */
|
|
|
|
- wl1271_conf_init(wl);
|
|
|
|
-
|
|
|
|
order = get_order(WL1271_AGGR_BUFFER_SIZE);
|
|
order = get_order(WL1271_AGGR_BUFFER_SIZE);
|
|
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
|
|
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
|
|
if (!wl->aggr_buf) {
|
|
if (!wl->aggr_buf) {
|
|
@@ -5384,8 +4861,17 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|
goto err_dummy_packet;
|
|
goto err_dummy_packet;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_DMA);
|
|
|
|
+ if (!wl->mbox) {
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ goto err_fwlog;
|
|
|
|
+ }
|
|
|
|
+
|
|
return hw;
|
|
return hw;
|
|
|
|
|
|
|
|
+err_fwlog:
|
|
|
|
+ free_page((unsigned long)wl->fwlog);
|
|
|
|
+
|
|
err_dummy_packet:
|
|
err_dummy_packet:
|
|
dev_kfree_skb(wl->dummy_packet);
|
|
dev_kfree_skb(wl->dummy_packet);
|
|
|
|
|
|
@@ -5397,14 +4883,18 @@ err_wq:
|
|
|
|
|
|
err_hw:
|
|
err_hw:
|
|
wl1271_debugfs_exit(wl);
|
|
wl1271_debugfs_exit(wl);
|
|
|
|
+ kfree(wl->priv);
|
|
|
|
+
|
|
|
|
+err_priv_alloc:
|
|
ieee80211_free_hw(hw);
|
|
ieee80211_free_hw(hw);
|
|
|
|
|
|
err_hw_alloc:
|
|
err_hw_alloc:
|
|
|
|
|
|
return ERR_PTR(ret);
|
|
return ERR_PTR(ret);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL_GPL(wlcore_alloc_hw);
|
|
|
|
|
|
-static int wl1271_free_hw(struct wl1271 *wl)
|
|
|
|
|
|
+int wlcore_free_hw(struct wl1271 *wl)
|
|
{
|
|
{
|
|
/* Unblock any fwlog readers */
|
|
/* Unblock any fwlog readers */
|
|
mutex_lock(&wl->mutex);
|
|
mutex_lock(&wl->mutex);
|
|
@@ -5434,10 +4924,12 @@ static int wl1271_free_hw(struct wl1271 *wl)
|
|
kfree(wl->tx_res_if);
|
|
kfree(wl->tx_res_if);
|
|
destroy_workqueue(wl->freezable_wq);
|
|
destroy_workqueue(wl->freezable_wq);
|
|
|
|
|
|
|
|
+ kfree(wl->priv);
|
|
ieee80211_free_hw(wl->hw);
|
|
ieee80211_free_hw(wl->hw);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL_GPL(wlcore_free_hw);
|
|
|
|
|
|
static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
|
static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
|
{
|
|
{
|
|
@@ -5468,22 +4960,22 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
|
return IRQ_WAKE_THREAD;
|
|
return IRQ_WAKE_THREAD;
|
|
}
|
|
}
|
|
|
|
|
|
-static int __devinit wl12xx_probe(struct platform_device *pdev)
|
|
|
|
|
|
+int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
|
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
|
- struct ieee80211_hw *hw;
|
|
|
|
- struct wl1271 *wl;
|
|
|
|
unsigned long irqflags;
|
|
unsigned long irqflags;
|
|
- int ret = -ENODEV;
|
|
|
|
|
|
+ int ret;
|
|
|
|
|
|
- hw = wl1271_alloc_hw();
|
|
|
|
- if (IS_ERR(hw)) {
|
|
|
|
- wl1271_error("can't allocate hw");
|
|
|
|
- ret = PTR_ERR(hw);
|
|
|
|
- goto out;
|
|
|
|
|
|
+ if (!wl->ops || !wl->ptable) {
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out_free_hw;
|
|
}
|
|
}
|
|
|
|
|
|
- wl = hw->priv;
|
|
|
|
|
|
+ BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS);
|
|
|
|
+
|
|
|
|
+ /* adjust some runtime configuration parameters */
|
|
|
|
+ wlcore_adjust_conf(wl);
|
|
|
|
+
|
|
wl->irq = platform_get_irq(pdev, 0);
|
|
wl->irq = platform_get_irq(pdev, 0);
|
|
wl->ref_clock = pdata->board_ref_clock;
|
|
wl->ref_clock = pdata->board_ref_clock;
|
|
wl->tcxo_clock = pdata->board_tcxo_clock;
|
|
wl->tcxo_clock = pdata->board_tcxo_clock;
|
|
@@ -5512,7 +5004,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
|
|
wl->irq_wake_enabled = true;
|
|
wl->irq_wake_enabled = true;
|
|
device_init_wakeup(wl->dev, 1);
|
|
device_init_wakeup(wl->dev, 1);
|
|
if (pdata->pwr_in_suspend)
|
|
if (pdata->pwr_in_suspend)
|
|
- hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
|
|
|
|
|
|
+ wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
|
|
|
|
|
|
}
|
|
}
|
|
disable_irq(wl->irq);
|
|
disable_irq(wl->irq);
|
|
@@ -5546,7 +5038,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
|
|
goto out_hw_pg_ver;
|
|
goto out_hw_pg_ver;
|
|
}
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
out_hw_pg_ver:
|
|
out_hw_pg_ver:
|
|
device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
|
|
device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
|
|
@@ -5558,13 +5050,14 @@ out_irq:
|
|
free_irq(wl->irq, wl);
|
|
free_irq(wl->irq, wl);
|
|
|
|
|
|
out_free_hw:
|
|
out_free_hw:
|
|
- wl1271_free_hw(wl);
|
|
|
|
|
|
+ wlcore_free_hw(wl);
|
|
|
|
|
|
out:
|
|
out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL_GPL(wlcore_probe);
|
|
|
|
|
|
-static int __devexit wl12xx_remove(struct platform_device *pdev)
|
|
|
|
|
|
+int __devexit wlcore_remove(struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct wl1271 *wl = platform_get_drvdata(pdev);
|
|
struct wl1271 *wl = platform_get_drvdata(pdev);
|
|
|
|
|
|
@@ -5574,38 +5067,11 @@ static int __devexit wl12xx_remove(struct platform_device *pdev)
|
|
}
|
|
}
|
|
wl1271_unregister_hw(wl);
|
|
wl1271_unregister_hw(wl);
|
|
free_irq(wl->irq, wl);
|
|
free_irq(wl->irq, wl);
|
|
- wl1271_free_hw(wl);
|
|
|
|
|
|
+ wlcore_free_hw(wl);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-
|
|
|
|
-static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
|
|
|
|
- { "wl12xx", 0 },
|
|
|
|
- { } /* Terminating Entry */
|
|
|
|
-};
|
|
|
|
-MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
|
|
|
|
-
|
|
|
|
-static struct platform_driver wl12xx_driver = {
|
|
|
|
- .probe = wl12xx_probe,
|
|
|
|
- .remove = __devexit_p(wl12xx_remove),
|
|
|
|
- .id_table = wl12xx_id_table,
|
|
|
|
- .driver = {
|
|
|
|
- .name = "wl12xx_driver",
|
|
|
|
- .owner = THIS_MODULE,
|
|
|
|
- }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static int __init wl12xx_init(void)
|
|
|
|
-{
|
|
|
|
- return platform_driver_register(&wl12xx_driver);
|
|
|
|
-}
|
|
|
|
-module_init(wl12xx_init);
|
|
|
|
-
|
|
|
|
-static void __exit wl12xx_exit(void)
|
|
|
|
-{
|
|
|
|
- platform_driver_unregister(&wl12xx_driver);
|
|
|
|
-}
|
|
|
|
-module_exit(wl12xx_exit);
|
|
|
|
|
|
+EXPORT_SYMBOL_GPL(wlcore_remove);
|
|
|
|
|
|
u32 wl12xx_debug_level = DEBUG_NONE;
|
|
u32 wl12xx_debug_level = DEBUG_NONE;
|
|
EXPORT_SYMBOL_GPL(wl12xx_debug_level);
|
|
EXPORT_SYMBOL_GPL(wl12xx_debug_level);
|
|
@@ -5619,6 +5085,9 @@ MODULE_PARM_DESC(fwlog,
|
|
module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
|
|
module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
|
|
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
|
|
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
|
|
|
|
|
|
|
|
+module_param(no_recovery, bool, S_IRUSR | S_IWUSR);
|
|
|
|
+MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");
|
|
|
|
+
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
|
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
|
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
|
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|