diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_boot.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_boot.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_io.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 63 |
7 files changed, 79 insertions, 11 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 75887e74205b..6f1b6b5640c0 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -388,6 +388,8 @@ struct wl1271 { size_t fw_len; struct wl1271_nvs_file *nvs; + s8 hw_pg_ver; + u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; u8 bss_type; @@ -479,7 +481,7 @@ struct wl1271 { struct wl1271_stats stats; struct wl1271_debugfs debugfs; - u32 buffer_32; + __le32 buffer_32; u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index acb1d9e6b7d2..1a36d8a2196e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -441,11 +441,23 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) return 0; } +static void wl1271_boot_hw_version(struct wl1271 *wl) +{ + u32 fuse; + + fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); + fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; + + wl->hw_pg_ver = (s8)fuse; +} + int wl1271_boot(struct wl1271 *wl) { int ret = 0; u32 tmp, clk, pause; + wl1271_boot_hw_version(wl); + if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 95ecc5241959..f829699d597e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h @@ -55,6 +55,9 @@ struct wl1271_static_data { #define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_PULL 0x0cb4 +#define REG_FUSE_DATA_2_1 0x050a +#define PG_VER_MASK 0x3c +#define PG_VER_OFFSET 2 #define CMD_MBOX_ADDRESS 0x407B4 diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 62c11af1d8e2..19393e236e2c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -516,7 +516,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) ps_params->ps_mode = ps_mode; ps_params->send_null_data = send; ps_params->retries = 5; - ps_params->hang_over_period = 128; + ps_params->hang_over_period = 1; ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 00f78b7aa384..f2820b42a943 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -129,7 +129,7 @@ enum cmd_templ { /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_CMD_TEMPL_MAX_SIZE 252 -#define WL1271_EVENT_TIMEOUT 100 +#define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { __le16 id; diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index d8837ef0bb40..bc806c74c63a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -74,12 +74,12 @@ static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) wl1271_raw_read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32), false); - return wl->buffer_32; + return le32_to_cpu(wl->buffer_32); } static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) { - wl->buffer_32 = val; + wl->buffer_32 = cpu_to_le32(val); wl1271_raw_write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32), false); } diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 62e544041d0d..5bb9e3fff961 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1140,10 +1140,25 @@ out: return ret; } -static int wl1271_join(struct wl1271 *wl) +static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; + /* + * One of the side effects of the JOIN command is that is clears + * WPA/WPA2 keys from the chipset. Performing a JOIN while associated + * to a WPA/WPA2 access point will therefore kill the data-path. + * Currently there is no supported scenario for JOIN during + * association - if it becomes a supported scenario, the WPA/WPA2 keys + * must be handled somehow. + * + */ + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + wl1271_info("JOIN while associated."); + + if (set_assoc) + set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) goto out; @@ -1190,7 +1205,6 @@ static int wl1271_unjoin(struct wl1271 *wl) goto out; clear_bit(WL1271_FLAG_JOINED, &wl->flags); - wl->channel = 0; memset(wl->bssid, 0, ETH_ALEN); /* stop filterting packets based on bssid */ @@ -1250,7 +1264,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) goto out; /* if the channel changes while joined, join again */ - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & IEEE80211_CONF_CHANGE_CHANNEL && + ((wl->band != conf->channel->band) || + (wl->channel != channel))) { wl->band = conf->channel->band; wl->channel = channel; @@ -1270,7 +1286,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) "failed %d", ret); if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { - ret = wl1271_join(wl); + ret = wl1271_join(wl, false); if (ret < 0) wl1271_warning("cmd join to update channel " "failed %d", ret); @@ -1647,6 +1663,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; bool do_join = false; + bool set_assoc = false; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1756,7 +1773,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->assoc) { u32 rates; wl->aid = bss_conf->aid; - set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + set_assoc = true; /* * use basic rates from AP, and determine lowest rate @@ -1856,7 +1873,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } if (do_join) { - ret = wl1271_join(wl); + ret = wl1271_join(wl, set_assoc); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out_sleep; @@ -2228,6 +2245,29 @@ static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, wl1271_sysfs_show_bt_coex_state, wl1271_sysfs_store_bt_coex_state); +static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + + /* FIXME: what's the maximum length of buf? page size?*/ + len = 500; + + mutex_lock(&wl->mutex); + if (wl->hw_pg_ver >= 0) + len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); + else + len = snprintf(buf, len, "n/a\n"); + mutex_unlock(&wl->mutex); + + return len; +} + +static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, + wl1271_sysfs_show_hw_pg_ver, NULL); + int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -2347,6 +2387,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->vif = NULL; wl->flags = 0; wl->sg_enabled = true; + wl->hw_pg_ver = -1; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; @@ -2376,8 +2417,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void) goto err_platform; } + /* Create sysfs file to get HW PG version */ + ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + if (ret < 0) { + wl1271_error("failed to create sysfs file hw_pg_ver"); + goto err_bt_coex_state; + } + return hw; +err_bt_coex_state: + device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); + err_platform: platform_device_unregister(wl->plat_dev); |