Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

Conflicts:
	drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
This commit is contained in:
John W. Linville 2012-06-29 12:42:14 -04:00
commit 8732baafc3
167 changed files with 6612 additions and 7042 deletions

View File

@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com>
M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
M: Kan Yan <kanyan@broadcom.com>
L: linux-wireless@vger.kernel.org
L: brcm80211-dev-list@broadcom.com
S: Supported
F: drivers/net/wireless/brcm80211/

View File

@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = {
static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
{ BCMA_CORE_INVALID, "Invalid" },
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
{ BCMA_CORE_ILINE20, "ILine 20" },

View File

@ -53,6 +53,11 @@
#define DEFAULT_BG_SCAN_PERIOD 60
struct ath6kl_cfg80211_match_probe_ssid {
struct cfg80211_ssid ssid;
u8 flag;
};
static struct ieee80211_rate ath6kl_rates[] = {
RATETAB_ENT(10, 0x1, 0),
RATETAB_ENT(20, 0x2, 0),
@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->nw_type = vif->next_mode;
/* enable enhanced bmiss detection if applicable */
ath6kl_cfg80211_sta_bmiss_enhance(vif, true);
if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
nw_subtype = SUBTYPE_P2PCLIENT;
@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
}
}
/*
* Send a disconnect command to target when a disconnect event is
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
* request from host) to make the firmware stop trying to connect even
* after giving disconnect event. There will be one more disconnect
* event for this disconnect command with reason code DISCONNECT_CMD
* which will be notified to cfg80211.
*/
if (reason != DISCONNECT_CMD) {
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
return;
}
clear_bit(CONNECT_PEND, &vif->flags);
if (vif->sme_state == SME_CONNECTING) {
@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
} else if (vif->sme_state == SME_CONNECTED) {
cfg80211_disconnected(vif->ndev, reason,
cfg80211_disconnected(vif->ndev, proto_reason,
NULL, 0, GFP_KERNEL);
}
vif->sme_state = SME_DISCONNECTED;
/*
* Send a disconnect command to target when a disconnect event is
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
* request from host) to make the firmware stop trying to connect even
* after giving disconnect event. There will be one more disconnect
* event for this disconnect command with reason code DISCONNECT_CMD
* which won't be notified to cfg80211.
*/
if (reason != DISCONNECT_CMD)
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
}
static int ath6kl_set_probed_ssids(struct ath6kl *ar,
struct ath6kl_vif *vif,
struct cfg80211_ssid *ssids, int n_ssids)
struct cfg80211_ssid *ssids, int n_ssids,
struct cfg80211_match_set *match_set,
int n_match_ssid)
{
u8 i;
u8 i, j, index_to_add, ssid_found = false;
struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS];
if (n_ssids > MAX_PROBED_SSID_INDEX)
memset(ssid_list, 0, sizeof(ssid_list));
if (n_ssids > MAX_PROBED_SSIDS ||
n_match_ssid > MAX_PROBED_SSIDS)
return -EINVAL;
for (i = 0; i < n_ssids; i++) {
memcpy(ssid_list[i].ssid.ssid,
ssids[i].ssid,
ssids[i].ssid_len);
ssid_list[i].ssid.ssid_len = ssids[i].ssid_len;
if (ssids[i].ssid_len)
ssid_list[i].flag = SPECIFIC_SSID_FLAG;
else
ssid_list[i].flag = ANY_SSID_FLAG;
if (n_match_ssid == 0)
ssid_list[i].flag |= MATCH_SSID_FLAG;
}
index_to_add = i;
for (i = 0; i < n_match_ssid; i++) {
ssid_found = false;
for (j = 0; j < n_ssids; j++) {
if ((match_set[i].ssid.ssid_len ==
ssid_list[j].ssid.ssid_len) &&
(!memcmp(ssid_list[j].ssid.ssid,
match_set[i].ssid.ssid,
match_set[i].ssid.ssid_len))) {
ssid_list[j].flag |= MATCH_SSID_FLAG;
ssid_found = true;
break;
}
}
if (ssid_found)
continue;
if (index_to_add >= MAX_PROBED_SSIDS)
continue;
ssid_list[index_to_add].ssid.ssid_len =
match_set[i].ssid.ssid_len;
memcpy(ssid_list[index_to_add].ssid.ssid,
match_set[i].ssid.ssid,
match_set[i].ssid.ssid_len);
ssid_list[index_to_add].flag |= MATCH_SSID_FLAG;
index_to_add++;
}
for (i = 0; i < index_to_add; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
ssids[i].ssid_len ?
SPECIFIC_SSID_FLAG : ANY_SSID_FLAG,
ssids[i].ssid_len,
ssids[i].ssid);
ssid_list[i].flag,
ssid_list[i].ssid.ssid_len,
ssid_list[i].ssid.ssid);
}
/* Make sure no old entries are left behind */
for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) {
for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
DISABLE_SSID_FLAG, 0, NULL);
}
@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
request->n_ssids);
request->n_ssids, NULL, 0);
if (ret < 0)
return ret;
@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
ath6kl_err("failed to set Probe Request appie for scan");
ath6kl_err("failed to set Probe Request appie for scan\n");
return ret;
}
@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
}
}
/* need to clean up enhanced bmiss detection fw state */
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
set_iface_type:
switch (type) {
case NL80211_IFTYPE_STATION:
@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
return -EINVAL;
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, false);
if (ret)
@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
ar->state = ATH6KL_STATE_ON;
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, true);
if (ret)
@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
bool ht_enable)
{
struct ath6kl_htcap *htcap = &vif->htcap;
struct ath6kl_htcap *htcap = &vif->htcap[band];
if (htcap->ht_enable == ht_enable)
return 0;
@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
return 0;
}
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
{
int err;
if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
return;
if (vif->nw_type != INFRA_NETWORK)
return;
if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
vif->ar->fw_capabilities))
return;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
enable ? "enable" : "disable");
err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
vif->fw_vif_idx, enable);
if (err)
ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
enable ? "enable" : "disable", err);
}
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
u8 *rsn_capab)
{
@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
/* TODO:
* info->interval
* info->dtim_period
*/
ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
info->dtim_period);
/* ignore error, just print a warning and continue normally */
if (ret)
ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);
if (info->beacon.head == NULL)
return -EINVAL;
mgmt = (struct ieee80211_mgmt *) info->beacon.head;
@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
ath6kl_cfg80211_scan_complete_event(vif, true);
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
request->n_ssids);
request->n_ssids,
request->match_sets,
request->n_match_sets);
if (ret < 0)
return ret;
if (!request->n_match_sets) {
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
ALL_BSS_FILTER, 0);
if (ret < 0)
return ret;
} else {
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
MATCHED_SSID_FILTER, 0);
if (ret < 0)
return ret;
}
/* fw uses seconds, also make sure that it's >0 */
interval = max_t(u16, 1, request->interval / 1000);
@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
ret);
return ret;
}
@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
return 0;
}
static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
struct net_device *dev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
mask);
}
static const struct ieee80211_txrx_stypes
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.mgmt_frame_register = ath6kl_mgmt_frame_register,
.sched_scan_start = ath6kl_cfg80211_sscan_start,
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
};
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
vif->bg_scan_period = 0;
vif->htcap.ht_enable = true;
vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
}
/* max num of ssids that can be probed during scanning */
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
/* max num of ssids that can be matched after scan */
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
ar->fw_capabilities))
wiphy->max_match_sets = MAX_PROBED_SSIDS;
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
switch (ar->hw.cap) {
case WMI_11AN_CAP:
@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.cap = 0;
ath6kl_band_5ghz.ht_cap.ht_supported = false;
}
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
} else {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
}
if (band_2gig)
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
if (band_5gig)
@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->wowlan.pattern_min_len = 1;
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;
wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME |

View File

@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
struct ath6kl *ath6kl_cfg80211_create(void);
void ath6kl_cfg80211_destroy(struct ath6kl *ar);
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
#endif /* ATH6KL_CFG80211_H */

View File

@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
/* Firmware has support to override rsn cap of rsn ie */
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
/*
* Multicast support in WOW and host awake mode.
* Allow all multicast in host awake mode.
* Apply multicast filter in WOW mode.
*/
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
/* Firmware supports enhanced bmiss detection */
ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
/*
* FW supports matching of ssid in schedule scan
*/
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
u8 data[0];
};
enum ath6kl_hw_flags {
ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
@ -196,7 +215,7 @@ struct ath6kl_fw_ie {
#define AGGR_NUM_OF_FREE_NETBUFS 16
#define AGGR_RX_TIMEOUT 400 /* in ms */
#define AGGR_RX_TIMEOUT 100 /* in ms */
#define WMI_TIMEOUT (2 * HZ)
@ -245,7 +264,6 @@ struct skb_hold_q {
struct rxtid {
bool aggr;
bool progress;
bool timer_mon;
u16 win_sz;
u16 seq_next;
@ -254,9 +272,15 @@ struct rxtid {
struct sk_buff_head q;
/*
* FIXME: No clue what this should protect. Apparently it should
* protect some of the fields above but they are also accessed
* without taking the lock.
* lock mainly protects seq_next and hold_q. Movement of seq_next
* needs to be protected between aggr_timeout() and
* aggr_process_recv_frm(). hold_q will be holding the pending
* reorder frames and it's access should also be protected.
* Some of the other fields like hold_q_sz, win_sz and aggr are
* initialized/reset when receiving addba/delba req, also while
* deleting aggr state all the pending buffers are flushed before
* resetting these fields, so there should not be any race in accessing
* these fields.
*/
spinlock_t lock;
};
@ -541,7 +565,7 @@ struct ath6kl_vif {
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
struct aggr_info *aggr_cntxt;
struct ath6kl_htcap htcap;
struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];
struct timer_list disconnect_timer;
struct timer_list sched_scan_timer;
@ -684,6 +708,8 @@ struct ath6kl {
u32 testscript_addr;
enum wmi_phy_cap cap;
u32 flags;
struct ath6kl_hw_fw {
const char *dir;
const char *otp;

View File

@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
}
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx 0x%p hdr x%x len %d mbox 0x%x\n",
"htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n",
packet, packet->info.rx.exp_hdr,
padded_len, dev->ar->mbox_info.htc_addr);

View File

@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.reserved_ram_size = 6912,
.refclk_hz = 26000000,
.uarttx_pin = 8,
.flags = 0,
/* hw2.0 needs override address hardcoded */
.app_start_override_addr = 0x944C00,
@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.refclk_hz = 26000000,
.uarttx_pin = 8,
.testscript_addr = 0x57ef74,
.flags = 0,
.fw = {
.dir = AR6003_HW_2_1_1_FW_DIR,
@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900,
.refclk_hz = 26000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_0_FW_DIR,
@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400,
.refclk_hz = 40000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_1_FW_DIR,
@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00,
.refclk_hz = 40000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_2_FW_DIR,
@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
}
switch (ie_id) {
case ATH6KL_FW_IE_FW_VERSION:
strlcpy(ar->wiphy->fw_version, data,
sizeof(ar->wiphy->fw_version));
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found fw version %s\n",
ar->wiphy->fw_version);
break;
case ATH6KL_FW_IE_OTP_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
ie_len);
@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->hw.reserved_ram_size);
break;
case ATH6KL_FW_IE_CAPABILITIES:
if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
break;
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found firmware capabilities ie (%zd B)\n",
ie_len);
@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
index = i / 8;
bit = i % 8;
if (index == ie_len)
break;
if (data[index] & (1 << bit))
__set_bit(i, ar->fw_capabilities);
}
@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar)
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
ath6kl_err("temporary war to avoid sdio crc error\n");
param = 0x28;
address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
status = ath6kl_bmi_reg_write(ar, address, param);
if (status)
return status;
param = 0x20;
address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
cfg80211_scan_done(vif->scan_req, true);
vif->scan_req = NULL;
}
/* need to clean up enhanced bmiss detection fw state */
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
}
void ath6kl_stop_txrx(struct ath6kl *ar)

View File

@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
struct ath6kl *ar = devt;
memcpy(ar->mac_addr, datap, ETH_ALEN);
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
__func__, ar->mac_addr);
ath6kl_dbg(ATH6KL_DBG_BOOT,
"ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n",
ar->mac_addr, sw_ver, abi_ver, cap);
ar->version.wlan_ver = sw_ver;
ar->version.abi_ver = abi_ver;
ar->hw.cap = cap;
snprintf(ar->wiphy->fw_version,
sizeof(ar->wiphy->fw_version),
"%u.%u.%u.%u",
(ar->version.wlan_ver & 0xf0000000) >> 28,
(ar->version.wlan_ver & 0x0f000000) >> 24,
(ar->version.wlan_ver & 0x00ff0000) >> 16,
(ar->version.wlan_ver & 0x0000ffff));
if (strlen(ar->wiphy->fw_version) == 0) {
snprintf(ar->wiphy->fw_version,
sizeof(ar->wiphy->fw_version),
"%u.%u.%u.%u",
(ar->version.wlan_ver & 0xf0000000) >> 28,
(ar->version.wlan_ver & 0x0f000000) >> 24,
(ar->version.wlan_ver & 0x00ff0000) >> 16,
(ar->version.wlan_ver & 0x0000ffff));
}
/* indicate to the waiting thread that the ready event was received */
set_bit(WMI_READY, &ar->flag);
@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
else
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
vif->ar->fw_capabilities)) {
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
}
if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on = false;

View File

@ -45,6 +45,7 @@
#define LPO_CAL_ENABLE_S 20
#define LPO_CAL_ENABLE 0x00100000
#define GPIO_PIN9_ADDRESS 0x0000004c
#define GPIO_PIN10_ADDRESS 0x00000050
#define GPIO_PIN11_ADDRESS 0x00000054
#define GPIO_PIN12_ADDRESS 0x00000058

View File

@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid];
spin_lock_bh(&rxtid->lock);
idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
/*
@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
seq_end = seq_no ? seq_no : rxtid->seq_next;
idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
spin_lock_bh(&rxtid->lock);
do {
node = &rxtid->hold_q[idx];
if ((order == 1) && (!node->skb))
@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
((end > extended_end) && (cur > extended_end) &&
(cur < end))) {
aggr_deque_frms(agg_conn, tid, 0, 0);
spin_lock_bh(&rxtid->lock);
if (cur >= rxtid->hold_q_sz - 1)
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
else
rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
(rxtid->hold_q_sz - 2 - cur);
spin_unlock_bh(&rxtid->lock);
} else {
/*
* Dequeue only those frames that are outside the
@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
aggr_deque_frms(agg_conn, tid, 0, 1);
if (agg_conn->timer_scheduled)
rxtid->progress = true;
else
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
if (rxtid->hold_q[idx].skb) {
/*
* There is a frame in the queue and no
* timer so start a timer to ensure that
* the frame doesn't remain stuck
* forever.
*/
agg_conn->timer_scheduled = true;
mod_timer(&agg_conn->timer,
(jiffies +
HZ * (AGGR_RX_TIMEOUT) / 1000));
rxtid->progress = false;
rxtid->timer_mon = true;
break;
}
return is_queued;
spin_lock_bh(&rxtid->lock);
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
if (rxtid->hold_q[idx].skb) {
/*
* There is a frame in the queue and no
* timer so start a timer to ensure that
* the frame doesn't remain stuck
* forever.
*/
agg_conn->timer_scheduled = true;
mod_timer(&agg_conn->timer,
(jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
rxtid->timer_mon = true;
break;
}
}
spin_unlock_bh(&rxtid->lock);
return is_queued;
}
@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i];
stats = &aggr_conn->stat[i];
if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
if (!rxtid->aggr || !rxtid->timer_mon)
continue;
stats->num_timeouts++;
@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i];
if (rxtid->aggr && rxtid->hold_q) {
spin_lock_bh(&rxtid->lock);
for (j = 0; j < rxtid->hold_q_sz; j++) {
if (rxtid->hold_q[j].skb) {
aggr_conn->timer_scheduled = true;
rxtid->timer_mon = true;
rxtid->progress = false;
break;
}
}
spin_unlock_bh(&rxtid->lock);
if (j >= rxtid->hold_q_sz)
rxtid->timer_mon = false;
@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
aggr_deque_frms(aggr_conn, tid, 0, 0);
rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false;
rxtid->win_sz = 0;
rxtid->seq_next = 0;
@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
for (i = 0; i < NUM_OF_TIDS; i++) {
rxtid = &aggr_conn->rx_tid[i];
rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false;
skb_queue_head_init(&rxtid->q);
spin_lock_init(&rxtid->lock);

View File

@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
memcpy(cmd->info.bssid, bssid, ETH_ALEN);
cmd->roam_ctrl = WMI_FORCE_ROAM;
@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
{
struct sk_buff *skb;
struct set_dtim_cmd *cmd;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct set_dtim_cmd *) skb->data;
cmd->dtim_period = cpu_to_le32(dtim_period);
return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
{
struct sk_buff *skb;
@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
cmd->info.roam_mode = mode;
cmd->roam_ctrl = WMI_SET_ROAM_MODE;
@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
struct wmi_probed_ssid_cmd *cmd;
int ret;
if (index > MAX_PROBED_SSID_INDEX)
if (index >= MAX_PROBED_SSIDS)
return -EINVAL;
if (ssid_len > sizeof(cmd->ssid))
@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
spin_unlock_bh(&wmi->lock);
}
static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates64_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[1];
mcsrate <<= 8;
mcsrate |= mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 28;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates32_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 20;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 32 bit: 2.4:%x 5:%x\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct ath6kl *ar = wmi->parent_dev;
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
}
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode)
{
@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
return ret;
}
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
{
struct sk_buff *skb;
struct wmi_sta_bmiss_enhance_cmd *cmd;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
cmd->enable = enhance ? 1 : 0;
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_STA_BMISS_ENHANCE_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
s32 ath6kl_wmi_get_rate(s8 rate_index)
{
if (rate_index == RATE_AUTO)

View File

@ -624,6 +624,10 @@ enum wmi_cmd_id {
WMI_SEND_MGMT_CMDID,
WMI_BEGIN_SCAN_CMDID,
WMI_SET_BLACK_LIST,
WMI_SET_MCASTRATE,
WMI_STA_BMISS_ENHANCE_CMDID,
};
enum wmi_mgmt_frame_type {
@ -960,6 +964,9 @@ enum wmi_bss_filter {
/* beacons matching probed ssid */
PROBED_SSID_FILTER,
/* beacons matching matched ssid */
MATCHED_SSID_FILTER,
/* marker only */
LAST_BSS_FILTER,
};
@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd {
} __packed;
/* WMI_SET_PROBED_SSID_CMDID */
#define MAX_PROBED_SSID_INDEX 9
#define MAX_PROBED_SSIDS 16
enum wmi_ssid_flag {
/* disables entry */
@ -989,10 +996,13 @@ enum wmi_ssid_flag {
/* probes for any ssid */
ANY_SSID_FLAG = 0x02,
/* match for ssid */
MATCH_SSID_FLAG = 0x08,
};
struct wmi_probed_ssid_cmd {
/* 0 to MAX_PROBED_SSID_INDEX */
/* 0 to MAX_PROBED_SSIDS - 1 */
u8 entry_index;
/* see, enum wmi_ssid_flg */
@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd {
__le16 num_beacons;
};
/* WMI_STA_ENHANCE_BMISS_CMDID */
struct wmi_sta_bmiss_enhance_cmd {
u8 enable;
} __packed;
/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
REC_POWER = 0x01,
@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd {
__le16 ps_fail_event_policy;
} __packed;
/*
* Ratemask for below modes should be passed
* to WMI_SET_TX_SELECT_RATES_CMDID.
* AR6003 has 32 bit mask for each modes.
* First 12 bits for legacy rates, 13 to 20
* bits for HT 20 rates and 21 to 28 bits for
* HT 40 rates
*/
enum wmi_mode_phy {
WMI_RATES_MODE_11A = 0,
WMI_RATES_MODE_11G,
WMI_RATES_MODE_11B,
WMI_RATES_MODE_11GONLY,
WMI_RATES_MODE_11A_HT20,
WMI_RATES_MODE_11G_HT20,
WMI_RATES_MODE_11A_HT40,
WMI_RATES_MODE_11G_HT40,
WMI_RATES_MODE_MAX
};
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates32_cmd {
__le32 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates64_cmd {
__le64 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_DISC_TIMEOUT_CMDID */
struct wmi_disc_timeout_cmd {
/* seconds */
@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd {
u8 roam_ctrl;
} __packed;
struct set_dtim_cmd {
__le32 dtim_period;
} __packed;
/* BSS INFO HDR version 2.0 */
struct wmi_bss_info_hdr2 {
__le16 ch; /* frequency in MHz */
@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1);
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode);
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask);
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_wow_mode wow_mode,
u32 filter, u16 host_req_delay);
@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
u8 *filter, bool add_filter);
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
/* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);

View File

@ -104,11 +104,6 @@ static const struct ani_cck_level_entry cck_level_table[] = {
#define ATH9K_ANI_CCK_DEF_LEVEL \
2 /* default level - matches the INI settings */
static bool use_new_ani(struct ath_hw *ah)
{
return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
}
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
struct ath9k_mib_stats *stats)
{
@ -122,8 +117,6 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
static void ath9k_ani_restart(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
u32 ofdm_base = 0, cck_base = 0;
if (!DO_ANI(ah))
return;
@ -131,18 +124,10 @@ static void ath9k_ani_restart(struct ath_hw *ah)
aniState = &ah->curchan->ani;
aniState->listenTime = 0;
if (!use_new_ani(ah)) {
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
}
ath_dbg(common, ANI, "Writing ofdmbase=%u cckbase=%u\n",
ofdm_base, cck_base);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_1, 0);
REG_WRITE(ah, AR_PHY_ERR_2, 0);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
@ -154,129 +139,23 @@ static void ath9k_ani_restart(struct ath_hw *ah)
aniState->cckPhyErrCount = 0;
}
static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
struct ar5416AniState *aniState;
int32_t rssi;
aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel + 1)) {
return;
}
}
if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
aniState->spurImmunityLevel + 1)) {
return;
}
}
if (ah->opmode == NL80211_IFTYPE_AP) {
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel + 1);
}
return;
}
rssi = BEACON_RSSI(ah);
if (rssi > aniState->rssiThrHigh) {
if (!aniState->ofdmWeakSigDetectOff) {
if (ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
false)) {
ath9k_hw_ani_control(ah,
ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
return;
}
}
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel + 1);
return;
}
} else if (rssi > aniState->rssiThrLow) {
if (aniState->ofdmWeakSigDetectOff)
ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
true);
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel + 1);
return;
} else {
if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
!conf_is_ht(conf)) {
if (!aniState->ofdmWeakSigDetectOff)
ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
false);
if (aniState->firstepLevel > 0)
ath9k_hw_ani_control(ah,
ATH9K_ANI_FIRSTEP_LEVEL, 0);
return;
}
}
}
static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
struct ar5416AniState *aniState;
int32_t rssi;
aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel + 1)) {
return;
}
}
if (ah->opmode == NL80211_IFTYPE_AP) {
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel + 1);
}
return;
}
rssi = BEACON_RSSI(ah);
if (rssi > aniState->rssiThrLow) {
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel + 1);
} else {
if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
!conf_is_ht(conf)) {
if (aniState->firstepLevel > 0)
ath9k_hw_ani_control(ah,
ATH9K_ANI_FIRSTEP_LEVEL, 0);
}
}
}
/* Adjust the OFDM Noise Immunity Level */
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
bool scan)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
aniState->noiseFloor = BEACON_RSSI(ah);
bool weak_sig;
ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
aniState->ofdmNoiseImmunityLevel,
immunityLevel, aniState->noiseFloor,
immunityLevel, BEACON_RSSI(ah),
aniState->rssiThrLow, aniState->rssiThrHigh);
if (aniState->update_ani)
aniState->ofdmNoiseImmunityLevel =
(immunityLevel > ATH9K_ANI_OFDM_DEF_LEVEL) ?
immunityLevel : ATH9K_ANI_OFDM_DEF_LEVEL;
if (!scan)
aniState->ofdmNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@ -292,12 +171,22 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
ATH9K_ANI_FIRSTEP_LEVEL,
entry_ofdm->fir_step_level);
if ((aniState->noiseFloor >= aniState->rssiThrHigh) &&
(!aniState->ofdmWeakSigDetectOff !=
entry_ofdm->ofdm_weak_signal_on)) {
weak_sig = entry_ofdm->ofdm_weak_signal_on;
if (ah->opmode == NL80211_IFTYPE_STATION &&
BEACON_RSSI(ah) <= aniState->rssiThrHigh)
weak_sig = true;
if (aniState->ofdmWeakSigDetect != weak_sig)
ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
entry_ofdm->ofdm_weak_signal_on);
if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
} else {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
}
}
@ -308,43 +197,35 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
if (!DO_ANI(ah))
return;
if (!use_new_ani(ah)) {
ath9k_hw_ani_ofdm_err_trigger_old(ah);
return;
}
aniState = &ah->curchan->ani;
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
}
/*
* Set the ANI settings to match an CCK level.
*/
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
bool scan)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
aniState->noiseFloor = BEACON_RSSI(ah);
ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
aniState->cckNoiseImmunityLevel, immunityLevel,
aniState->noiseFloor, aniState->rssiThrLow,
BEACON_RSSI(ah), aniState->rssiThrLow,
aniState->rssiThrHigh);
if ((ah->opmode == NL80211_IFTYPE_STATION ||
ah->opmode == NL80211_IFTYPE_ADHOC) &&
aniState->noiseFloor <= aniState->rssiThrLow &&
if (ah->opmode == NL80211_IFTYPE_STATION &&
BEACON_RSSI(ah) <= aniState->rssiThrLow &&
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
if (aniState->update_ani)
aniState->cckNoiseImmunityLevel =
(immunityLevel > ATH9K_ANI_CCK_DEF_LEVEL) ?
immunityLevel : ATH9K_ANI_CCK_DEF_LEVEL;
if (!scan)
aniState->cckNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@ -359,7 +240,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
return;
if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
if (aniState->mrcCCK != entry_cck->mrc_cck_on)
ath9k_hw_ani_control(ah,
ATH9K_ANI_MRC_CCK,
entry_cck->mrc_cck_on);
@ -372,68 +253,11 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
if (!DO_ANI(ah))
return;
if (!use_new_ani(ah)) {
ath9k_hw_ani_cck_err_trigger_old(ah);
return;
}
aniState = &ah->curchan->ani;
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
}
static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
int32_t rssi;
aniState = &ah->curchan->ani;
if (ah->opmode == NL80211_IFTYPE_AP) {
if (aniState->firstepLevel > 0) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel - 1))
return;
}
} else {
rssi = BEACON_RSSI(ah);
if (rssi > aniState->rssiThrHigh) {
/* XXX: Handle me */
} else if (rssi > aniState->rssiThrLow) {
if (aniState->ofdmWeakSigDetectOff) {
if (ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
true))
return;
}
if (aniState->firstepLevel > 0) {
if (ath9k_hw_ani_control(ah,
ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel - 1))
return;
}
} else {
if (aniState->firstepLevel > 0) {
if (ath9k_hw_ani_control(ah,
ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel - 1))
return;
}
}
}
if (aniState->spurImmunityLevel > 0) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
aniState->spurImmunityLevel - 1))
return;
}
if (aniState->noiseImmunityLevel > 0) {
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel - 1);
return;
}
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
false);
}
/*
@ -446,87 +270,18 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
aniState = &ah->curchan->ani;
if (!use_new_ani(ah)) {
ath9k_hw_ani_lower_immunity_old(ah);
return;
}
/* lower OFDM noise immunity */
if (aniState->ofdmNoiseImmunityLevel > 0 &&
(aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
false);
return;
}
/* lower CCK noise immunity */
if (aniState->cckNoiseImmunityLevel > 0)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
}
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
{
struct ar5416AniState *aniState;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
if (!DO_ANI(ah))
return;
aniState = &ah->curchan->ani;
if (ah->opmode != NL80211_IFTYPE_STATION
&& ah->opmode != NL80211_IFTYPE_ADHOC) {
ath_dbg(common, ANI, "Reset ANI state opmode %u\n", ah->opmode);
ah->stats.ast_ani_reset++;
if (ah->opmode == NL80211_IFTYPE_AP) {
/*
* ath9k_hw_ani_control() will only process items set on
* ah->ani_function
*/
if (IS_CHAN_2GHZ(chan))
ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
ATH9K_ANI_FIRSTEP_LEVEL);
else
ah->ani_function = 0;
}
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
!ATH9K_ANI_USE_OFDM_WEAK_SIG);
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
ATH9K_ANI_CCK_WEAK_SIG_THR);
ath9k_ani_restart(ah);
return;
}
if (aniState->noiseImmunityLevel != 0)
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel);
if (aniState->spurImmunityLevel != 0)
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
aniState->spurImmunityLevel);
if (aniState->ofdmWeakSigDetectOff)
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
!aniState->ofdmWeakSigDetectOff);
if (aniState->cckWeakSigThreshold)
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
aniState->cckWeakSigThreshold);
if (aniState->firstepLevel != 0)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel);
ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
false);
}
/*
@ -539,13 +294,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
int ofdm_nil, cck_nil;
if (!DO_ANI(ah))
return;
if (!use_new_ani(ah))
return ath9k_ani_reset_old(ah, is_scanning);
BUG_ON(aniState == NULL);
ah->stats.ast_ani_reset++;
@ -563,6 +316,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
/* always allow mode (on/off) to be controlled */
ah->ani_function |= ATH9K_ANI_MODE;
ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
aniState->ofdmNoiseImmunityLevel);
cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
aniState->cckNoiseImmunityLevel);
if (is_scanning ||
(ah->opmode != NL80211_IFTYPE_STATION &&
ah->opmode != NL80211_IFTYPE_ADHOC)) {
@ -585,9 +343,8 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
aniState->update_ani = false;
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
}
} else {
/*
@ -601,13 +358,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
is_scanning,
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
aniState->update_ani = true;
ath9k_hw_set_ofdm_nil(ah,
aniState->ofdmNoiseImmunityLevel);
ath9k_hw_set_cck_nil(ah,
aniState->cckNoiseImmunityLevel);
}
ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
/*
* enable phy counters if hw supports or if not, enable phy
@ -627,9 +380,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416AniState *aniState = &ah->curchan->ani;
u32 ofdm_base = 0;
u32 cck_base = 0;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
u32 phyCnt1, phyCnt2;
int32_t listenTime;
@ -642,11 +392,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
return false;
}
if (!use_new_ani(ah)) {
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
}
aniState->listenTime += listenTime;
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@ -654,35 +399,12 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
if (phyCnt1 < ofdm_base) {
ath_dbg(common, ANI,
"phyCnt1 0x%x, resetting counter value to 0x%x\n",
phyCnt1, ofdm_base);
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
AR_PHY_ERR_OFDM_TIMING);
}
if (phyCnt2 < cck_base) {
ath_dbg(common, ANI,
"phyCnt2 0x%x, resetting counter value to 0x%x\n",
phyCnt2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
AR_PHY_ERR_CCK_TIMING);
}
return false;
}
ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
aniState->ofdmPhyErrCount = phyCnt1;
ofdmPhyErrCnt = phyCnt1 - ofdm_base;
ah->stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = phyCnt2;
cckPhyErrCnt = phyCnt2 - cck_base;
ah->stats.ast_ani_cckerrs +=
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
return true;
}
@ -716,21 +438,10 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
if (aniState->listenTime > ah->aniperiod) {
if (cckPhyErrRate < ah->config.cck_trig_low &&
((ofdmPhyErrRate < ah->config.ofdm_trig_low &&
aniState->ofdmNoiseImmunityLevel <
ATH9K_ANI_OFDM_DEF_LEVEL) ||
(ofdmPhyErrRate < ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI &&
aniState->ofdmNoiseImmunityLevel >=
ATH9K_ANI_OFDM_DEF_LEVEL))) {
ofdmPhyErrRate < ah->config.ofdm_trig_low) {
ath9k_hw_ani_lower_immunity(ah);
aniState->ofdmsTurn = !aniState->ofdmsTurn;
} else if ((ofdmPhyErrRate > ah->config.ofdm_trig_high &&
aniState->ofdmNoiseImmunityLevel >=
ATH9K_ANI_OFDM_DEF_LEVEL) ||
(ofdmPhyErrRate >
ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI &&
aniState->ofdmNoiseImmunityLevel <
ATH9K_ANI_OFDM_DEF_LEVEL)) {
} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
ath9k_hw_ani_ofdm_err_trigger(ah);
aniState->ofdmsTurn = false;
} else if (cckPhyErrRate > ah->config.cck_trig_high) {
@ -778,49 +489,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
/*
* Process a MIB interrupt. We may potentially be invoked because
* any of the MIB counters overflow/trigger so don't assume we're
* here because a PHY error counter triggered.
*/
void ath9k_hw_proc_mib_event(struct ath_hw *ah)
{
u32 phyCnt1, phyCnt2;
/* Reset these counters regardless */
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
/* Clear the mib counters and save them in the stats */
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
if (!DO_ANI(ah)) {
/*
* We must always clear the interrupt cause by
* resetting the phy error regs.
*/
REG_WRITE(ah, AR_PHY_ERR_1, 0);
REG_WRITE(ah, AR_PHY_ERR_2, 0);
return;
}
/* NB: these are not reset-on-read */
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
if (!use_new_ani(ah))
ath9k_hw_ani_read_counters(ah);
/* NB: always restart to insure the h/w counters are reset */
ath9k_ani_restart(ah);
}
}
EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
void ath9k_hw_ani_setup(struct ath_hw *ah)
{
int i;
@ -845,66 +513,37 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ath_dbg(common, ANI, "Initialize ANI\n");
if (use_new_ani(ah)) {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
} else {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
}
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
struct ath9k_channel *chan = &ah->channels[i];
struct ar5416AniState *ani = &chan->ani;
if (use_new_ani(ah)) {
ani->spurImmunityLevel =
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
if (AR_SREV_9300_20_OR_LATER(ah))
ani->mrcCCKOff =
!ATH9K_ANI_ENABLE_MRC_CCK;
else
ani->mrcCCKOff = true;
ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
ani->ofdmsTurn = true;
} else {
ani->spurImmunityLevel =
ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
ani->cckWeakSigThreshold =
ATH9K_ANI_CCK_WEAK_SIG_THR;
}
ani->ofdmsTurn = true;
ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
ani->ofdmWeakSigDetectOff =
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
ani->update_ani = false;
}
/*
* since we expect some ongoing maintenance on the tables, let's sanity
* check here default level should not modify INI setting.
*/
if (use_new_ani(ah)) {
ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
} else {
ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
}
ah->aniperiod = ATH9K_ANI_PERIOD;
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;

View File

@ -24,42 +24,34 @@
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
/* units are errors per second */
#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
/* units are errors per second */
#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
#define ATH9K_ANI_OFDM_TRIG_LOW 400
#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
/* units are errors per second */
#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
#define ATH9K_ANI_CCK_TRIG_HIGH 600
/* units are errors per second */
#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
#define ATH9K_ANI_CCK_TRIG_LOW 300
#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
#define ATH9K_ANI_USE_OFDM_WEAK_SIG true
#define ATH9K_ANI_CCK_WEAK_SIG_THR false
#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
#define ATH9K_ANI_SPUR_IMMUNE_LVL 3
#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
#define ATH9K_ANI_FIRSTEP_LVL 2
#define ATH9K_ANI_RSSI_THR_HIGH 40
#define ATH9K_ANI_RSSI_THR_LOW 7
#define ATH9K_ANI_PERIOD_OLD 100
#define ATH9K_ANI_PERIOD_NEW 300
#define ATH9K_ANI_PERIOD 300
/* in ms */
#define ATH9K_ANI_POLLINTERVAL_OLD 100
#define ATH9K_ANI_POLLINTERVAL_NEW 1000
#define ATH9K_ANI_POLLINTERVAL 1000
#define HAL_NOISE_IMMUNE_MAX 4
#define HAL_SPUR_IMMUNE_MAX 7
@ -70,8 +62,6 @@
#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
#define ATH9K_ANI_ENABLE_MRC_CCK true
/* values here are relative to the INI */
enum ath9k_ani_cmd {
@ -119,16 +109,14 @@ struct ar5416AniState {
u8 ofdmNoiseImmunityLevel;
u8 cckNoiseImmunityLevel;
bool ofdmsTurn;
u8 mrcCCKOff;
u8 mrcCCK;
u8 spurImmunityLevel;
u8 firstepLevel;
u8 ofdmWeakSigDetectOff;
u8 ofdmWeakSigDetect;
u8 cckWeakSigThreshold;
bool update_ani;
u32 listenTime;
int32_t rssiThrLow;
int32_t rssiThrHigh;
u32 noiseFloor;
u32 ofdmPhyErrCount;
u32 cckPhyErrCount;
int16_t pktRssi[2];

View File

@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
return pll;
}
static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
switch (cmd & ah->ani_function) {
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
u32 level = param;
if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(ah->totalSizeDesired));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
AR_PHY_DESIRED_SZ_TOT_DES,
ah->totalSizeDesired[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_LOW,
ah->coarse_low[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_HIGH,
ah->coarse_high[level]);
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRPWR,
ah->firpwr[level]);
if (level > aniState->noiseImmunityLevel)
ah->stats.ast_ani_niup++;
else if (level < aniState->noiseImmunityLevel)
ah->stats.ast_ani_nidown++;
aniState->noiseImmunityLevel = level;
break;
}
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
u32 on = param ? 1 : 0;
if (on)
REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
else
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) {
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on;
}
break;
}
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
static const int weakSigThrCck[] = { 8, 6 };
u32 high = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
weakSigThrCck[high]);
if (high != aniState->cckWeakSigThreshold) {
if (high)
ah->stats.ast_ani_cckhigh++;
else
ah->stats.ast_ani_ccklow++;
aniState->cckWeakSigThreshold = high;
}
break;
}
case ATH9K_ANI_FIRSTEP_LEVEL:{
static const int firstep[] = { 0, 4, 8 };
u32 level = param;
if (level >= ARRAY_SIZE(firstep)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(firstep));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRSTEP,
firstep[level]);
if (level > aniState->firstepLevel)
ah->stats.ast_ani_stepup++;
else if (level < aniState->firstepLevel)
ah->stats.ast_ani_stepdown++;
aniState->firstepLevel = level;
break;
}
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
u32 level = param;
if (level >= ARRAY_SIZE(cycpwrThr1)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(cycpwrThr1));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
AR_PHY_TIMING5_CYCPWR_THR1,
cycpwrThr1[level]);
if (level > aniState->spurImmunityLevel)
ah->stats.ast_ani_spurup++;
else if (level < aniState->spurImmunityLevel)
ah->stats.ast_ani_spurdown++;
aniState->spurImmunityLevel = level;
break;
}
case ATH9K_ANI_PRESENT:
break;
default:
ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
return false;
}
ath_dbg(common, ANI, "ANI parameters:\n");
ath_dbg(common, ANI,
"noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
aniState->noiseImmunityLevel,
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff);
ath_dbg(common, ANI,
"cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
aniState->cckWeakSigThreshold,
aniState->firstepLevel,
aniState->listenTime);
ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
}
static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) {
if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel,
!aniState->ofdmWeakSigDetectOff ?
aniState->ofdmWeakSigDetect ?
"on" : "off",
on ? "on" : "off");
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on;
aniState->ofdmWeakSigDetect = on;
}
break;
}
@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
ATH9K_ANI_FIRSTEP_LVL_NEW,
ATH9K_ANI_FIRSTEP_LVL,
value,
aniState->iniDef.firstep);
ath_dbg(common, ANI,
@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
ATH9K_ANI_FIRSTEP_LVL_NEW,
ATH9K_ANI_FIRSTEP_LVL,
value2,
aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel)
@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
ATH9K_ANI_SPUR_IMMUNE_LVL,
value,
aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI,
@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
ATH9K_ANI_SPUR_IMMUNE_LVL,
value2,
aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel)
@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->mrcCCK ? "on" : "off",
aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_TIMING5_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = true; /* not available on pre AR9003 */
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCK = false; /* not available on pre AR9003 */
}
static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->do_getnf = ar5008_hw_do_getnf;
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
if (modparam_force_new_ani) {
priv_ops->ani_control = ar5008_hw_ani_control_new;
priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
} else
priv_ops->ani_control = ar5008_hw_ani_control_old;
priv_ops->ani_control = ar5008_hw_ani_control_new;
priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;

View File

@ -21,10 +21,6 @@
#include "ar9002_initvals.h"
#include "ar9002_phy.h"
int modparam_force_new_ani;
module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002");
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@ -767,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah)
{
/* disable all MCI messages */
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
/* wait pending HW messages to flush out */
@ -1019,9 +1015,14 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
return;
if (mci->is_2g) {
ar9003_mci_send_2g5g_status(ah, true);
if (!force) {
ar9003_mci_send_2g5g_status(ah, true);
REG_SET_BIT(ah, AR_MCI_TX_CTRL,
ar9003_mci_send_lna_transfer(ah, true);
udelay(5);
}
REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
@ -1029,6 +1030,11 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
ar9003_mci_osla_setup(ah, true);
} else {
if (!force) {
ar9003_mci_send_lna_take(ah, true);
udelay(5);
}
REG_SET_BIT(ah, AR_MCI_TX_CTRL,
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
@ -1255,6 +1261,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
ar9003_mci_send_lna_take(ah, true);
udelay(50);
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
mci->is_2g = false;
mci->update_2g5g = true;

View File

@ -173,7 +173,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
int cur_bb_spur, negative = 0, cck_spur_freq;
int i;
int range, max_spur_cnts, synth_freq;
u8 *spur_fbin_ptr = NULL;
u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan));
/*
* Need to verify range +/- 10 MHz in control channel, otherwise spur
@ -181,8 +181,6 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
*/
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
IS_CHAN_2GHZ(chan));
if (spur_fbin_ptr[0] == 0) /* No spur */
return;
max_spur_cnts = 5;
@ -825,18 +823,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) {
if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel,
!aniState->ofdmWeakSigDetectOff ?
aniState->ofdmWeakSigDetect ?
"on" : "off",
on ? "on" : "off");
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on;
aniState->ofdmWeakSigDetect = on;
}
break;
}
@ -855,7 +853,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@ -870,7 +868,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@ -886,7 +884,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
ATH9K_ANI_FIRSTEP_LVL_NEW,
ATH9K_ANI_FIRSTEP_LVL,
value,
aniState->iniDef.firstep);
ath_dbg(common, ANI,
@ -894,7 +892,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
ATH9K_ANI_FIRSTEP_LVL_NEW,
ATH9K_ANI_FIRSTEP_LVL,
value2,
aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel)
@ -919,7 +917,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@ -935,7 +933,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@ -950,7 +948,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
ATH9K_ANI_SPUR_IMMUNE_LVL,
value,
aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI,
@ -958,7 +956,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
ATH9K_ANI_SPUR_IMMUNE_LVL,
value2,
aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel)
@ -979,16 +977,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
AR_PHY_MRC_CCK_ENABLE, is_on);
REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
AR_PHY_MRC_CCK_MUX_REG, is_on);
if (!is_on != aniState->mrcCCKOff) {
if (is_on != aniState->mrcCCK) {
ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
chan->channel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->mrcCCK ? "on" : "off",
is_on ? "on" : "off");
if (is_on)
ah->stats.ast_ani_ccklow++;
else
ah->stats.ast_ani_cckhigh++;
aniState->mrcCCKOff = !is_on;
aniState->mrcCCK = is_on;
}
break;
}
@ -1002,9 +1000,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->mrcCCK ? "on" : "off",
aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@ -1111,10 +1109,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCK = true;
}
static void ar9003_hw_set_radar_params(struct ath_hw *ah,

View File

@ -337,12 +337,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
};
static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
/* Addr allmodes */
{0x0000a398, 0x00000000},
{0x0000a39c, 0x6f7f0301},
{0x0000a3a0, 0xca9228ee},
};
#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
static const u32 ar9331_1p1_xtal_25M[][2] = {
/* Addr allmodes */
@ -783,17 +778,7 @@ static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
};
static const u32 ar9331_1p1_mac_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
};
#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
static const u32 ar9331_1p1_soc_preamble[][2] = {
/* Addr allmodes */
@ -1112,38 +1097,4 @@ static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
{0x00000000},
};
static const u32 ar9331_1p1_chansel_xtal_25M[] = {
0x0101479e,
0x0101d027,
0x010258af,
0x0102e138,
0x010369c0,
0x0103f249,
0x01047ad1,
0x0105035a,
0x01058be2,
0x0106146b,
0x01069cf3,
0x0107257c,
0x0107ae04,
0x0108f5b2,
};
static const u32 ar9331_1p1_chansel_xtal_40M[] = {
0x00a0ccbe,
0x00a12213,
0x00a17769,
0x00a1ccbe,
0x00a22213,
0x00a27769,
0x00a2ccbe,
0x00a32213,
0x00a37769,
0x00a3ccbe,
0x00a42213,
0x00a47769,
0x00a4ccbe,
0x00a5998b,
};
#endif /* INITVALS_9330_1P1_H */

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011 Atheros Communications Inc.
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -17,8 +18,8 @@
#ifndef INITVALS_9330_1P2_H
#define INITVALS_9330_1P2_H
static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
@ -102,8 +103,14 @@ static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
};
#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2
#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2
static const u32 ar9331_1p2_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
@ -147,191 +154,6 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
};
static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
};
static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
/* Addr allmodes */
{0x0000a398, 0x00000000},
{0x0000a39c, 0x6f7f0301},
{0x0000a3a0, 0xca9228ee},
};
static const u32 ar9331_1p2_xtal_25M[][2] = {
/* Addr allmodes */
{0x00007038, 0x000002f8},
{0x00008244, 0x0010f3d7},
{0x0000824c, 0x0001e7ae},
{0x0001609c, 0x0f508f29},
};
static const u32 ar9331_1p2_radio_core[][2] = {
/* Addr allmodes */
{0x00016000, 0x36db6db6},
@ -397,684 +219,24 @@ static const u32 ar9331_1p2_radio_core[][2] = {
{0x000163d4, 0x00000000},
};
static const u32 ar9331_1p2_soc_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
};
#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
/* Addr allmodes */
{0x0000a000, 0x00060005},
{0x0000a004, 0x00810080},
{0x0000a008, 0x00830082},
{0x0000a00c, 0x00850084},
{0x0000a010, 0x01820181},
{0x0000a014, 0x01840183},
{0x0000a018, 0x01880185},
{0x0000a01c, 0x018a0189},
{0x0000a020, 0x02850284},
{0x0000a024, 0x02890288},
{0x0000a028, 0x028b028a},
{0x0000a02c, 0x03850384},
{0x0000a030, 0x03890388},
{0x0000a034, 0x038b038a},
{0x0000a038, 0x038d038c},
{0x0000a03c, 0x03910390},
{0x0000a040, 0x03930392},
{0x0000a044, 0x03950394},
{0x0000a048, 0x00000396},
{0x0000a04c, 0x00000000},
{0x0000a050, 0x00000000},
{0x0000a054, 0x00000000},
{0x0000a058, 0x00000000},
{0x0000a05c, 0x00000000},
{0x0000a060, 0x00000000},
{0x0000a064, 0x00000000},
{0x0000a068, 0x00000000},
{0x0000a06c, 0x00000000},
{0x0000a070, 0x00000000},
{0x0000a074, 0x00000000},
{0x0000a078, 0x00000000},
{0x0000a07c, 0x00000000},
{0x0000a080, 0x28282828},
{0x0000a084, 0x28282828},
{0x0000a088, 0x28282828},
{0x0000a08c, 0x28282828},
{0x0000a090, 0x28282828},
{0x0000a094, 0x24242428},
{0x0000a098, 0x171e1e1e},
{0x0000a09c, 0x02020b0b},
{0x0000a0a0, 0x02020202},
{0x0000a0a4, 0x00000000},
{0x0000a0a8, 0x00000000},
{0x0000a0ac, 0x00000000},
{0x0000a0b0, 0x00000000},
{0x0000a0b4, 0x00000000},
{0x0000a0b8, 0x00000000},
{0x0000a0bc, 0x00000000},
{0x0000a0c0, 0x22072208},
{0x0000a0c4, 0x22052206},
{0x0000a0c8, 0x22032204},
{0x0000a0cc, 0x22012202},
{0x0000a0d0, 0x221f2200},
{0x0000a0d4, 0x221d221e},
{0x0000a0d8, 0x33023303},
{0x0000a0dc, 0x33003301},
{0x0000a0e0, 0x331e331f},
{0x0000a0e4, 0x4402331d},
{0x0000a0e8, 0x44004401},
{0x0000a0ec, 0x441e441f},
{0x0000a0f0, 0x55025503},
{0x0000a0f4, 0x55005501},
{0x0000a0f8, 0x551e551f},
{0x0000a0fc, 0x6602551d},
{0x0000a100, 0x66006601},
{0x0000a104, 0x661e661f},
{0x0000a108, 0x7703661d},
{0x0000a10c, 0x77017702},
{0x0000a110, 0x00007700},
{0x0000a114, 0x00000000},
{0x0000a118, 0x00000000},
{0x0000a11c, 0x00000000},
{0x0000a120, 0x00000000},
{0x0000a124, 0x00000000},
{0x0000a128, 0x00000000},
{0x0000a12c, 0x00000000},
{0x0000a130, 0x00000000},
{0x0000a134, 0x00000000},
{0x0000a138, 0x00000000},
{0x0000a13c, 0x00000000},
{0x0000a140, 0x001f0000},
{0x0000a144, 0x111f1100},
{0x0000a148, 0x111d111e},
{0x0000a14c, 0x111b111c},
{0x0000a150, 0x22032204},
{0x0000a154, 0x22012202},
{0x0000a158, 0x221f2200},
{0x0000a15c, 0x221d221e},
{0x0000a160, 0x33013302},
{0x0000a164, 0x331f3300},
{0x0000a168, 0x4402331e},
{0x0000a16c, 0x44004401},
{0x0000a170, 0x441e441f},
{0x0000a174, 0x55015502},
{0x0000a178, 0x551f5500},
{0x0000a17c, 0x6602551e},
{0x0000a180, 0x66006601},
{0x0000a184, 0x661e661f},
{0x0000a188, 0x7703661d},
{0x0000a18c, 0x77017702},
{0x0000a190, 0x00007700},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
{0x0000a1a0, 0x00000000},
{0x0000a1a4, 0x00000000},
{0x0000a1a8, 0x00000000},
{0x0000a1ac, 0x00000000},
{0x0000a1b0, 0x00000000},
{0x0000a1b4, 0x00000000},
{0x0000a1b8, 0x00000000},
{0x0000a1bc, 0x00000000},
{0x0000a1c0, 0x00000000},
{0x0000a1c4, 0x00000000},
{0x0000a1c8, 0x00000000},
{0x0000a1cc, 0x00000000},
{0x0000a1d0, 0x00000000},
{0x0000a1d4, 0x00000000},
{0x0000a1d8, 0x00000000},
{0x0000a1dc, 0x00000000},
{0x0000a1e0, 0x00000000},
{0x0000a1e4, 0x00000000},
{0x0000a1e8, 0x00000000},
{0x0000a1ec, 0x00000000},
{0x0000a1f0, 0x00000396},
{0x0000a1f4, 0x00000396},
{0x0000a1f8, 0x00000396},
{0x0000a1fc, 0x00000296},
};
#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
static const u32 ar9331_1p2_baseband_core[][2] = {
/* Addr allmodes */
{0x00009800, 0xafe68e30},
{0x00009804, 0xfd14e000},
{0x00009808, 0x9c0a8f6b},
{0x0000980c, 0x04800000},
{0x00009814, 0x9280c00a},
{0x00009818, 0x00000000},
{0x0000981c, 0x00020028},
{0x00009834, 0x5f3ca3de},
{0x00009838, 0x0108ecff},
{0x0000983c, 0x14750600},
{0x00009880, 0x201fff00},
{0x00009884, 0x00001042},
{0x000098a4, 0x00200400},
{0x000098b0, 0x32840bbe},
{0x000098d0, 0x004b6a8e},
{0x000098d4, 0x00000820},
{0x000098dc, 0x00000000},
{0x000098f0, 0x00000000},
{0x000098f4, 0x00000000},
{0x00009c04, 0x00000000},
{0x00009c08, 0x03200000},
{0x00009c0c, 0x00000000},
{0x00009c10, 0x00000000},
{0x00009c14, 0x00046384},
{0x00009c18, 0x05b6b440},
{0x00009c1c, 0x00b6b440},
{0x00009d00, 0xc080a333},
{0x00009d04, 0x40206c10},
{0x00009d08, 0x009c4060},
{0x00009d0c, 0x1883800a},
{0x00009d10, 0x01834061},
{0x00009d14, 0x00c00400},
{0x00009d18, 0x00000000},
{0x00009e08, 0x0038233c},
{0x00009e24, 0x9927b515},
{0x00009e28, 0x12ef0200},
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009fc0, 0x803e4788},
{0x00009fc4, 0x0001efb5},
{0x00009fcc, 0x40000014},
{0x0000a20c, 0x00000000},
{0x0000a220, 0x00000000},
{0x0000a224, 0x00000000},
{0x0000a228, 0x10002310},
{0x0000a23c, 0x00000000},
{0x0000a244, 0x0c000000},
{0x0000a2a0, 0x00000001},
{0x0000a2c0, 0x00000001},
{0x0000a2c8, 0x00000000},
{0x0000a2cc, 0x18c43433},
{0x0000a2d4, 0x00000000},
{0x0000a2dc, 0x00000000},
{0x0000a2e0, 0x00000000},
{0x0000a2e4, 0x00000000},
{0x0000a2e8, 0x00000000},
{0x0000a2ec, 0x00000000},
{0x0000a2f0, 0x00000000},
{0x0000a2f4, 0x00000000},
{0x0000a2f8, 0x00000000},
{0x0000a344, 0x00000000},
{0x0000a34c, 0x00000000},
{0x0000a350, 0x0000a000},
{0x0000a364, 0x00000000},
{0x0000a370, 0x00000000},
{0x0000a390, 0x00000001},
{0x0000a394, 0x00000444},
{0x0000a398, 0x001f0e0f},
{0x0000a39c, 0x0075393f},
{0x0000a3a0, 0xb79f6427},
{0x0000a3a4, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa},
{0x0000a3ac, 0x3c466478},
{0x0000a3c0, 0x20202020},
{0x0000a3c4, 0x22222220},
{0x0000a3c8, 0x20200020},
{0x0000a3cc, 0x20202020},
{0x0000a3d0, 0x20202020},
{0x0000a3d4, 0x20202020},
{0x0000a3d8, 0x20202020},
{0x0000a3dc, 0x20202020},
{0x0000a3e0, 0x20202020},
{0x0000a3e4, 0x20202020},
{0x0000a3e8, 0x20202020},
{0x0000a3ec, 0x20202020},
{0x0000a3f0, 0x00000000},
{0x0000a3f4, 0x00000006},
{0x0000a3f8, 0x0cdbd380},
{0x0000a3fc, 0x000f0f01},
{0x0000a400, 0x8fa91f01},
{0x0000a404, 0x00000000},
{0x0000a408, 0x0e79e5c6},
{0x0000a40c, 0x00820820},
{0x0000a414, 0x1ce739ce},
{0x0000a418, 0x2d001dce},
{0x0000a41c, 0x1ce739ce},
{0x0000a420, 0x000001ce},
{0x0000a424, 0x1ce739ce},
{0x0000a428, 0x000001ce},
{0x0000a42c, 0x1ce739ce},
{0x0000a430, 0x1ce739ce},
{0x0000a434, 0x00000000},
{0x0000a438, 0x00001801},
{0x0000a43c, 0x00000000},
{0x0000a440, 0x00000000},
{0x0000a444, 0x00000000},
{0x0000a448, 0x04000000},
{0x0000a44c, 0x00000001},
{0x0000a450, 0x00010000},
{0x0000a458, 0x00000000},
{0x0000a640, 0x00000000},
{0x0000a644, 0x3fad9d74},
{0x0000a648, 0x0048060a},
{0x0000a64c, 0x00003c37},
{0x0000a670, 0x03020100},
{0x0000a674, 0x09080504},
{0x0000a678, 0x0d0c0b0a},
{0x0000a67c, 0x13121110},
{0x0000a680, 0x31301514},
{0x0000a684, 0x35343332},
{0x0000a688, 0x00000036},
{0x0000a690, 0x00000838},
{0x0000a7c0, 0x00000000},
{0x0000a7c4, 0xfffffffc},
{0x0000a7c8, 0x00000000},
{0x0000a7cc, 0x00000000},
{0x0000a7d0, 0x00000000},
{0x0000a7d4, 0x00000004},
{0x0000a7dc, 0x00000001},
};
#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
};
#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core
static const u32 ar9331_1p2_mac_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
};
#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
static const u32 ar9331_1p2_soc_preamble[][2] = {
/* Addr allmodes */
{0x00007020, 0x00000000},
{0x00007034, 0x00000002},
{0x00007038, 0x000002f8},
};
#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
static const u32 ar9331_1p2_xtal_40M[][2] = {
/* Addr allmodes */
{0x00007038, 0x000004c2},
{0x00008244, 0x0010f400},
{0x0000824c, 0x0001e800},
{0x0001609c, 0x0b283f31},
};
#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
static const u32 ar9331_1p2_mac_core[][2] = {
/* Addr allmodes */
{0x00000008, 0x00000000},
{0x00000030, 0x00020085},
{0x00000034, 0x00000005},
{0x00000040, 0x00000000},
{0x00000044, 0x00000000},
{0x00000048, 0x00000008},
{0x0000004c, 0x00000010},
{0x00000050, 0x00000000},
{0x00001040, 0x002ffc0f},
{0x00001044, 0x002ffc0f},
{0x00001048, 0x002ffc0f},
{0x0000104c, 0x002ffc0f},
{0x00001050, 0x002ffc0f},
{0x00001054, 0x002ffc0f},
{0x00001058, 0x002ffc0f},
{0x0000105c, 0x002ffc0f},
{0x00001060, 0x002ffc0f},
{0x00001064, 0x002ffc0f},
{0x000010f0, 0x00000100},
{0x00001270, 0x00000000},
{0x000012b0, 0x00000000},
{0x000012f0, 0x00000000},
{0x0000143c, 0x00000000},
{0x0000147c, 0x00000000},
{0x00008000, 0x00000000},
{0x00008004, 0x00000000},
{0x00008008, 0x00000000},
{0x0000800c, 0x00000000},
{0x00008018, 0x00000000},
{0x00008020, 0x00000000},
{0x00008038, 0x00000000},
{0x0000803c, 0x00000000},
{0x00008040, 0x00000000},
{0x00008044, 0x00000000},
{0x00008048, 0x00000000},
{0x0000804c, 0xffffffff},
{0x00008054, 0x00000000},
{0x00008058, 0x00000000},
{0x0000805c, 0x000fc78f},
{0x00008060, 0x0000000f},
{0x00008064, 0x00000000},
{0x00008070, 0x00000310},
{0x00008074, 0x00000020},
{0x00008078, 0x00000000},
{0x0000809c, 0x0000000f},
{0x000080a0, 0x00000000},
{0x000080a4, 0x02ff0000},
{0x000080a8, 0x0e070605},
{0x000080ac, 0x0000000d},
{0x000080b0, 0x00000000},
{0x000080b4, 0x00000000},
{0x000080b8, 0x00000000},
{0x000080bc, 0x00000000},
{0x000080c0, 0x2a800000},
{0x000080c4, 0x06900168},
{0x000080c8, 0x13881c20},
{0x000080cc, 0x01f40000},
{0x000080d0, 0x00252500},
{0x000080d4, 0x00a00000},
{0x000080d8, 0x00400000},
{0x000080dc, 0x00000000},
{0x000080e0, 0xffffffff},
{0x000080e4, 0x0000ffff},
{0x000080e8, 0x3f3f3f3f},
{0x000080ec, 0x00000000},
{0x000080f0, 0x00000000},
{0x000080f4, 0x00000000},
{0x000080fc, 0x00020000},
{0x00008100, 0x00000000},
{0x00008108, 0x00000052},
{0x0000810c, 0x00000000},
{0x00008110, 0x00000000},
{0x00008114, 0x000007ff},
{0x00008118, 0x000000aa},
{0x0000811c, 0x00003210},
{0x00008124, 0x00000000},
{0x00008128, 0x00000000},
{0x0000812c, 0x00000000},
{0x00008130, 0x00000000},
{0x00008134, 0x00000000},
{0x00008138, 0x00000000},
{0x0000813c, 0x0000ffff},
{0x00008144, 0xffffffff},
{0x00008168, 0x00000000},
{0x0000816c, 0x00000000},
{0x00008170, 0x18486200},
{0x00008174, 0x33332210},
{0x00008178, 0x00000000},
{0x0000817c, 0x00020000},
{0x000081c0, 0x00000000},
{0x000081c4, 0x33332210},
{0x000081c8, 0x00000000},
{0x000081cc, 0x00000000},
{0x000081d4, 0x00000000},
{0x000081ec, 0x00000000},
{0x000081f0, 0x00000000},
{0x000081f4, 0x00000000},
{0x000081f8, 0x00000000},
{0x000081fc, 0x00000000},
{0x00008240, 0x00100000},
{0x00008248, 0x00000800},
{0x00008250, 0x00000000},
{0x00008254, 0x00000000},
{0x00008258, 0x00000000},
{0x0000825c, 0x40000000},
{0x00008260, 0x00080922},
{0x00008264, 0x9d400010},
{0x00008268, 0xffffffff},
{0x0000826c, 0x0000ffff},
{0x00008270, 0x00000000},
{0x00008274, 0x40000000},
{0x00008278, 0x003e4180},
{0x0000827c, 0x00000004},
{0x00008284, 0x0000002c},
{0x00008288, 0x0000002c},
{0x0000828c, 0x000000ff},
{0x00008294, 0x00000000},
{0x00008298, 0x00000000},
{0x0000829c, 0x00000000},
{0x00008300, 0x00000140},
{0x00008314, 0x00000000},
{0x0000831c, 0x0000010d},
{0x00008328, 0x00000000},
{0x0000832c, 0x00000007},
{0x00008330, 0x00000302},
{0x00008334, 0x00000700},
{0x00008338, 0x00ff0000},
{0x0000833c, 0x02400000},
{0x00008340, 0x000107ff},
{0x00008344, 0xaa48105b},
{0x00008348, 0x008f0000},
{0x0000835c, 0x00000000},
{0x00008360, 0xffffffff},
{0x00008364, 0xffffffff},
{0x00008368, 0x00000000},
{0x00008370, 0x00000000},
{0x00008374, 0x000000ff},
{0x00008378, 0x00000000},
{0x0000837c, 0x00000000},
{0x00008380, 0xffffffff},
{0x00008384, 0xffffffff},
{0x00008390, 0xffffffff},
{0x00008394, 0xffffffff},
{0x00008398, 0x00000000},
{0x0000839c, 0x00000000},
{0x000083a0, 0x00000000},
{0x000083a4, 0x0000fa14},
{0x000083a8, 0x000f0c00},
{0x000083ac, 0x33332210},
{0x000083b0, 0x33332210},
{0x000083b4, 0x33332210},
{0x000083b8, 0x33332210},
{0x000083bc, 0x00000000},
{0x000083c0, 0x00000000},
{0x000083c4, 0x00000000},
{0x000083c8, 0x00000000},
{0x000083cc, 0x00000200},
{0x000083d0, 0x000301ff},
};
#define ar9331_1p2_mac_core ar9331_1p1_mac_core
static const u32 ar9331_common_rx_gain_1p2[][2] = {
/* Addr allmodes */
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
{0x0000a00c, 0x00810080},
{0x0000a010, 0x01800082},
{0x0000a014, 0x01820181},
{0x0000a018, 0x01840183},
{0x0000a01c, 0x01880185},
{0x0000a020, 0x018a0189},
{0x0000a024, 0x02850284},
{0x0000a028, 0x02890288},
{0x0000a02c, 0x03850384},
{0x0000a030, 0x03890388},
{0x0000a034, 0x038b038a},
{0x0000a038, 0x038d038c},
{0x0000a03c, 0x03910390},
{0x0000a040, 0x03930392},
{0x0000a044, 0x03950394},
{0x0000a048, 0x00000396},
{0x0000a04c, 0x00000000},
{0x0000a050, 0x00000000},
{0x0000a054, 0x00000000},
{0x0000a058, 0x00000000},
{0x0000a05c, 0x00000000},
{0x0000a060, 0x00000000},
{0x0000a064, 0x00000000},
{0x0000a068, 0x00000000},
{0x0000a06c, 0x00000000},
{0x0000a070, 0x00000000},
{0x0000a074, 0x00000000},
{0x0000a078, 0x00000000},
{0x0000a07c, 0x00000000},
{0x0000a080, 0x28282828},
{0x0000a084, 0x28282828},
{0x0000a088, 0x28282828},
{0x0000a08c, 0x28282828},
{0x0000a090, 0x28282828},
{0x0000a094, 0x21212128},
{0x0000a098, 0x171c1c1c},
{0x0000a09c, 0x02020212},
{0x0000a0a0, 0x00000202},
{0x0000a0a4, 0x00000000},
{0x0000a0a8, 0x00000000},
{0x0000a0ac, 0x00000000},
{0x0000a0b0, 0x00000000},
{0x0000a0b4, 0x00000000},
{0x0000a0b8, 0x00000000},
{0x0000a0bc, 0x00000000},
{0x0000a0c0, 0x001f0000},
{0x0000a0c4, 0x111f1100},
{0x0000a0c8, 0x111d111e},
{0x0000a0cc, 0x111b111c},
{0x0000a0d0, 0x22032204},
{0x0000a0d4, 0x22012202},
{0x0000a0d8, 0x221f2200},
{0x0000a0dc, 0x221d221e},
{0x0000a0e0, 0x33013302},
{0x0000a0e4, 0x331f3300},
{0x0000a0e8, 0x4402331e},
{0x0000a0ec, 0x44004401},
{0x0000a0f0, 0x441e441f},
{0x0000a0f4, 0x55015502},
{0x0000a0f8, 0x551f5500},
{0x0000a0fc, 0x6602551e},
{0x0000a100, 0x66006601},
{0x0000a104, 0x661e661f},
{0x0000a108, 0x7703661d},
{0x0000a10c, 0x77017702},
{0x0000a110, 0x00007700},
{0x0000a114, 0x00000000},
{0x0000a118, 0x00000000},
{0x0000a11c, 0x00000000},
{0x0000a120, 0x00000000},
{0x0000a124, 0x00000000},
{0x0000a128, 0x00000000},
{0x0000a12c, 0x00000000},
{0x0000a130, 0x00000000},
{0x0000a134, 0x00000000},
{0x0000a138, 0x00000000},
{0x0000a13c, 0x00000000},
{0x0000a140, 0x001f0000},
{0x0000a144, 0x111f1100},
{0x0000a148, 0x111d111e},
{0x0000a14c, 0x111b111c},
{0x0000a150, 0x22032204},
{0x0000a154, 0x22012202},
{0x0000a158, 0x221f2200},
{0x0000a15c, 0x221d221e},
{0x0000a160, 0x33013302},
{0x0000a164, 0x331f3300},
{0x0000a168, 0x4402331e},
{0x0000a16c, 0x44004401},
{0x0000a170, 0x441e441f},
{0x0000a174, 0x55015502},
{0x0000a178, 0x551f5500},
{0x0000a17c, 0x6602551e},
{0x0000a180, 0x66006601},
{0x0000a184, 0x661e661f},
{0x0000a188, 0x7703661d},
{0x0000a18c, 0x77017702},
{0x0000a190, 0x00007700},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
{0x0000a1a0, 0x00000000},
{0x0000a1a4, 0x00000000},
{0x0000a1a8, 0x00000000},
{0x0000a1ac, 0x00000000},
{0x0000a1b0, 0x00000000},
{0x0000a1b4, 0x00000000},
{0x0000a1b8, 0x00000000},
{0x0000a1bc, 0x00000000},
{0x0000a1c0, 0x00000000},
{0x0000a1c4, 0x00000000},
{0x0000a1c8, 0x00000000},
{0x0000a1cc, 0x00000000},
{0x0000a1d0, 0x00000000},
{0x0000a1d4, 0x00000000},
{0x0000a1d8, 0x00000000},
{0x0000a1dc, 0x00000000},
{0x0000a1e0, 0x00000000},
{0x0000a1e4, 0x00000000},
{0x0000a1e8, 0x00000000},
{0x0000a1ec, 0x00000000},
{0x0000a1f0, 0x00000396},
{0x0000a1f4, 0x00000396},
{0x0000a1f8, 0x00000396},
{0x0000a1fc, 0x00000296},
};
#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1
#endif /* INITVALS_9330_1P2_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -61,7 +62,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
{0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
@ -1007,7 +1008,7 @@ static const u32 ar9462_2p0_radio_core[][2] = {
static const u32 ar9462_2p0_soc_preamble[][2] = {
/* Addr allmodes */
{0x000040a4 ,0x00a0c1c9},
{0x000040a4, 0x00a0c1c9},
{0x00007020, 0x00000000},
{0x00007034, 0x00000002},
{0x00007038, 0x000004c2},

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -19,18 +20,7 @@
/* AR9580 1.0 */
static const u32 ar9580_1p0_modes_fast_clock[][3] = {
/* Addr 5G_HT20 5G_HT40 */
{0x00001030, 0x00000268, 0x000004d0},
{0x00001070, 0x0000018c, 0x00000318},
{0x000010b0, 0x00000fd0, 0x00001fa0},
{0x00008014, 0x044c044c, 0x08980898},
{0x0000801c, 0x148ec02b, 0x148ec057},
{0x00008318, 0x000044c0, 0x00008980},
{0x00009e00, 0x0372131c, 0x0372131c},
{0x0000a230, 0x0000000b, 0x00000016},
{0x0000a254, 0x00000898, 0x00001130},
};
#define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
static const u32 ar9580_1p0_radio_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@ -208,17 +198,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
{0x0000c420, 0x00000000},
};
static const u32 ar9580_1p0_mac_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
};
#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@ -326,111 +306,7 @@ static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
#define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table
static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@ -538,12 +414,7 @@ static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
/* Addr allmodes */
{0x0000a398, 0x00000000},
{0x0000a39c, 0x6f7f0301},
{0x0000a3a0, 0xca9228ee},
};
#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
static const u32 ar9580_1p0_mac_core[][2] = {
/* Addr allmodes */
@ -808,376 +679,11 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = {
/* Addr allmodes */
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
{0x0000a00c, 0x00810080},
{0x0000a010, 0x00830082},
{0x0000a014, 0x01810180},
{0x0000a018, 0x01830182},
{0x0000a01c, 0x01850184},
{0x0000a020, 0x01890188},
{0x0000a024, 0x018b018a},
{0x0000a028, 0x018d018c},
{0x0000a02c, 0x03820190},
{0x0000a030, 0x03840383},
{0x0000a034, 0x03880385},
{0x0000a038, 0x038a0389},
{0x0000a03c, 0x038c038b},
{0x0000a040, 0x0390038d},
{0x0000a044, 0x03920391},
{0x0000a048, 0x03940393},
{0x0000a04c, 0x03960395},
{0x0000a050, 0x00000000},
{0x0000a054, 0x00000000},
{0x0000a058, 0x00000000},
{0x0000a05c, 0x00000000},
{0x0000a060, 0x00000000},
{0x0000a064, 0x00000000},
{0x0000a068, 0x00000000},
{0x0000a06c, 0x00000000},
{0x0000a070, 0x00000000},
{0x0000a074, 0x00000000},
{0x0000a078, 0x00000000},
{0x0000a07c, 0x00000000},
{0x0000a080, 0x29292929},
{0x0000a084, 0x29292929},
{0x0000a088, 0x29292929},
{0x0000a08c, 0x29292929},
{0x0000a090, 0x22292929},
{0x0000a094, 0x1d1d2222},
{0x0000a098, 0x0c111117},
{0x0000a09c, 0x00030303},
{0x0000a0a0, 0x00000000},
{0x0000a0a4, 0x00000000},
{0x0000a0a8, 0x00000000},
{0x0000a0ac, 0x00000000},
{0x0000a0b0, 0x00000000},
{0x0000a0b4, 0x00000000},
{0x0000a0b8, 0x00000000},
{0x0000a0bc, 0x00000000},
{0x0000a0c0, 0x001f0000},
{0x0000a0c4, 0x01000101},
{0x0000a0c8, 0x011e011f},
{0x0000a0cc, 0x011c011d},
{0x0000a0d0, 0x02030204},
{0x0000a0d4, 0x02010202},
{0x0000a0d8, 0x021f0200},
{0x0000a0dc, 0x0302021e},
{0x0000a0e0, 0x03000301},
{0x0000a0e4, 0x031e031f},
{0x0000a0e8, 0x0402031d},
{0x0000a0ec, 0x04000401},
{0x0000a0f0, 0x041e041f},
{0x0000a0f4, 0x0502041d},
{0x0000a0f8, 0x05000501},
{0x0000a0fc, 0x051e051f},
{0x0000a100, 0x06010602},
{0x0000a104, 0x061f0600},
{0x0000a108, 0x061d061e},
{0x0000a10c, 0x07020703},
{0x0000a110, 0x07000701},
{0x0000a114, 0x00000000},
{0x0000a118, 0x00000000},
{0x0000a11c, 0x00000000},
{0x0000a120, 0x00000000},
{0x0000a124, 0x00000000},
{0x0000a128, 0x00000000},
{0x0000a12c, 0x00000000},
{0x0000a130, 0x00000000},
{0x0000a134, 0x00000000},
{0x0000a138, 0x00000000},
{0x0000a13c, 0x00000000},
{0x0000a140, 0x001f0000},
{0x0000a144, 0x01000101},
{0x0000a148, 0x011e011f},
{0x0000a14c, 0x011c011d},
{0x0000a150, 0x02030204},
{0x0000a154, 0x02010202},
{0x0000a158, 0x021f0200},
{0x0000a15c, 0x0302021e},
{0x0000a160, 0x03000301},
{0x0000a164, 0x031e031f},
{0x0000a168, 0x0402031d},
{0x0000a16c, 0x04000401},
{0x0000a170, 0x041e041f},
{0x0000a174, 0x0502041d},
{0x0000a178, 0x05000501},
{0x0000a17c, 0x051e051f},
{0x0000a180, 0x06010602},
{0x0000a184, 0x061f0600},
{0x0000a188, 0x061d061e},
{0x0000a18c, 0x07020703},
{0x0000a190, 0x07000701},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
{0x0000a1a0, 0x00000000},
{0x0000a1a4, 0x00000000},
{0x0000a1a8, 0x00000000},
{0x0000a1ac, 0x00000000},
{0x0000a1b0, 0x00000000},
{0x0000a1b4, 0x00000000},
{0x0000a1b8, 0x00000000},
{0x0000a1bc, 0x00000000},
{0x0000a1c0, 0x00000000},
{0x0000a1c4, 0x00000000},
{0x0000a1c8, 0x00000000},
{0x0000a1cc, 0x00000000},
{0x0000a1d0, 0x00000000},
{0x0000a1d4, 0x00000000},
{0x0000a1d8, 0x00000000},
{0x0000a1dc, 0x00000000},
{0x0000a1e0, 0x00000000},
{0x0000a1e4, 0x00000000},
{0x0000a1e8, 0x00000000},
{0x0000a1ec, 0x00000000},
{0x0000a1f0, 0x00000396},
{0x0000a1f4, 0x00000396},
{0x0000a1f8, 0x00000396},
{0x0000a1fc, 0x00000196},
{0x0000b000, 0x00010000},
{0x0000b004, 0x00030002},
{0x0000b008, 0x00050004},
{0x0000b00c, 0x00810080},
{0x0000b010, 0x00830082},
{0x0000b014, 0x01810180},
{0x0000b018, 0x01830182},
{0x0000b01c, 0x01850184},
{0x0000b020, 0x02810280},
{0x0000b024, 0x02830282},
{0x0000b028, 0x02850284},
{0x0000b02c, 0x02890288},
{0x0000b030, 0x028b028a},
{0x0000b034, 0x0388028c},
{0x0000b038, 0x038a0389},
{0x0000b03c, 0x038c038b},
{0x0000b040, 0x0390038d},
{0x0000b044, 0x03920391},
{0x0000b048, 0x03940393},
{0x0000b04c, 0x03960395},
{0x0000b050, 0x00000000},
{0x0000b054, 0x00000000},
{0x0000b058, 0x00000000},
{0x0000b05c, 0x00000000},
{0x0000b060, 0x00000000},
{0x0000b064, 0x00000000},
{0x0000b068, 0x00000000},
{0x0000b06c, 0x00000000},
{0x0000b070, 0x00000000},
{0x0000b074, 0x00000000},
{0x0000b078, 0x00000000},
{0x0000b07c, 0x00000000},
{0x0000b080, 0x32323232},
{0x0000b084, 0x2f2f3232},
{0x0000b088, 0x23282a2d},
{0x0000b08c, 0x1c1e2123},
{0x0000b090, 0x14171919},
{0x0000b094, 0x0e0e1214},
{0x0000b098, 0x03050707},
{0x0000b09c, 0x00030303},
{0x0000b0a0, 0x00000000},
{0x0000b0a4, 0x00000000},
{0x0000b0a8, 0x00000000},
{0x0000b0ac, 0x00000000},
{0x0000b0b0, 0x00000000},
{0x0000b0b4, 0x00000000},
{0x0000b0b8, 0x00000000},
{0x0000b0bc, 0x00000000},
{0x0000b0c0, 0x003f0020},
{0x0000b0c4, 0x00400041},
{0x0000b0c8, 0x0140005f},
{0x0000b0cc, 0x0160015f},
{0x0000b0d0, 0x017e017f},
{0x0000b0d4, 0x02410242},
{0x0000b0d8, 0x025f0240},
{0x0000b0dc, 0x027f0260},
{0x0000b0e0, 0x0341027e},
{0x0000b0e4, 0x035f0340},
{0x0000b0e8, 0x037f0360},
{0x0000b0ec, 0x04400441},
{0x0000b0f0, 0x0460045f},
{0x0000b0f4, 0x0541047f},
{0x0000b0f8, 0x055f0540},
{0x0000b0fc, 0x057f0560},
{0x0000b100, 0x06400641},
{0x0000b104, 0x0660065f},
{0x0000b108, 0x067e067f},
{0x0000b10c, 0x07410742},
{0x0000b110, 0x075f0740},
{0x0000b114, 0x077f0760},
{0x0000b118, 0x07800781},
{0x0000b11c, 0x07a0079f},
{0x0000b120, 0x07c107bf},
{0x0000b124, 0x000007c0},
{0x0000b128, 0x00000000},
{0x0000b12c, 0x00000000},
{0x0000b130, 0x00000000},
{0x0000b134, 0x00000000},
{0x0000b138, 0x00000000},
{0x0000b13c, 0x00000000},
{0x0000b140, 0x003f0020},
{0x0000b144, 0x00400041},
{0x0000b148, 0x0140005f},
{0x0000b14c, 0x0160015f},
{0x0000b150, 0x017e017f},
{0x0000b154, 0x02410242},
{0x0000b158, 0x025f0240},
{0x0000b15c, 0x027f0260},
{0x0000b160, 0x0341027e},
{0x0000b164, 0x035f0340},
{0x0000b168, 0x037f0360},
{0x0000b16c, 0x04400441},
{0x0000b170, 0x0460045f},
{0x0000b174, 0x0541047f},
{0x0000b178, 0x055f0540},
{0x0000b17c, 0x057f0560},
{0x0000b180, 0x06400641},
{0x0000b184, 0x0660065f},
{0x0000b188, 0x067e067f},
{0x0000b18c, 0x07410742},
{0x0000b190, 0x075f0740},
{0x0000b194, 0x077f0760},
{0x0000b198, 0x07800781},
{0x0000b19c, 0x07a0079f},
{0x0000b1a0, 0x07c107bf},
{0x0000b1a4, 0x000007c0},
{0x0000b1a8, 0x00000000},
{0x0000b1ac, 0x00000000},
{0x0000b1b0, 0x00000000},
{0x0000b1b4, 0x00000000},
{0x0000b1b8, 0x00000000},
{0x0000b1bc, 0x00000000},
{0x0000b1c0, 0x00000000},
{0x0000b1c4, 0x00000000},
{0x0000b1c8, 0x00000000},
{0x0000b1cc, 0x00000000},
{0x0000b1d0, 0x00000000},
{0x0000b1d4, 0x00000000},
{0x0000b1d8, 0x00000000},
{0x0000b1dc, 0x00000000},
{0x0000b1e0, 0x00000000},
{0x0000b1e4, 0x00000000},
{0x0000b1e8, 0x00000000},
{0x0000b1ec, 0x00000000},
{0x0000b1f0, 0x00000396},
{0x0000b1f4, 0x00000396},
{0x0000b1f8, 0x00000396},
{0x0000b1fc, 0x00000196},
};
#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
static const u32 ar9580_1p0_soc_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
};
#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
{0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
{0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
{0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
{0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
{0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
{0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
{0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
{0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
{0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
{0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
{0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
{0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
{0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
{0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
{0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
{0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
{0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
{0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
{0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
{0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
{0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
{0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
{0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
{0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
{0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
{0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
{0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
{0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
{0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
{0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
{0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
{0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
{0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
{0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
{0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
{0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
{0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
{0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
{0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
{0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
{0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
{0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
{0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
{0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
{0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
{0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
{0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
{0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
{0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
{0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
{0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
{0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
{0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
{0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
{0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
{0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
{0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
{0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
{0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
{0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
static const u32 ar9580_1p0_soc_preamble[][2] = {
/* Addr allmodes */
@ -1189,265 +695,7 @@ static const u32 ar9580_1p0_soc_preamble[][2] = {
{0x00007048, 0x00000008},
};
static const u32 ar9580_1p0_rx_gain_table[][2] = {
/* Addr allmodes */
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
{0x0000a00c, 0x00810080},
{0x0000a010, 0x00830082},
{0x0000a014, 0x01810180},
{0x0000a018, 0x01830182},
{0x0000a01c, 0x01850184},
{0x0000a020, 0x01890188},
{0x0000a024, 0x018b018a},
{0x0000a028, 0x018d018c},
{0x0000a02c, 0x01910190},
{0x0000a030, 0x01930192},
{0x0000a034, 0x01950194},
{0x0000a038, 0x038a0196},
{0x0000a03c, 0x038c038b},
{0x0000a040, 0x0390038d},
{0x0000a044, 0x03920391},
{0x0000a048, 0x03940393},
{0x0000a04c, 0x03960395},
{0x0000a050, 0x00000000},
{0x0000a054, 0x00000000},
{0x0000a058, 0x00000000},
{0x0000a05c, 0x00000000},
{0x0000a060, 0x00000000},
{0x0000a064, 0x00000000},
{0x0000a068, 0x00000000},
{0x0000a06c, 0x00000000},
{0x0000a070, 0x00000000},
{0x0000a074, 0x00000000},
{0x0000a078, 0x00000000},
{0x0000a07c, 0x00000000},
{0x0000a080, 0x22222229},
{0x0000a084, 0x1d1d1d1d},
{0x0000a088, 0x1d1d1d1d},
{0x0000a08c, 0x1d1d1d1d},
{0x0000a090, 0x171d1d1d},
{0x0000a094, 0x11111717},
{0x0000a098, 0x00030311},
{0x0000a09c, 0x00000000},
{0x0000a0a0, 0x00000000},
{0x0000a0a4, 0x00000000},
{0x0000a0a8, 0x00000000},
{0x0000a0ac, 0x00000000},
{0x0000a0b0, 0x00000000},
{0x0000a0b4, 0x00000000},
{0x0000a0b8, 0x00000000},
{0x0000a0bc, 0x00000000},
{0x0000a0c0, 0x001f0000},
{0x0000a0c4, 0x01000101},
{0x0000a0c8, 0x011e011f},
{0x0000a0cc, 0x011c011d},
{0x0000a0d0, 0x02030204},
{0x0000a0d4, 0x02010202},
{0x0000a0d8, 0x021f0200},
{0x0000a0dc, 0x0302021e},
{0x0000a0e0, 0x03000301},
{0x0000a0e4, 0x031e031f},
{0x0000a0e8, 0x0402031d},
{0x0000a0ec, 0x04000401},
{0x0000a0f0, 0x041e041f},
{0x0000a0f4, 0x0502041d},
{0x0000a0f8, 0x05000501},
{0x0000a0fc, 0x051e051f},
{0x0000a100, 0x06010602},
{0x0000a104, 0x061f0600},
{0x0000a108, 0x061d061e},
{0x0000a10c, 0x07020703},
{0x0000a110, 0x07000701},
{0x0000a114, 0x00000000},
{0x0000a118, 0x00000000},
{0x0000a11c, 0x00000000},
{0x0000a120, 0x00000000},
{0x0000a124, 0x00000000},
{0x0000a128, 0x00000000},
{0x0000a12c, 0x00000000},
{0x0000a130, 0x00000000},
{0x0000a134, 0x00000000},
{0x0000a138, 0x00000000},
{0x0000a13c, 0x00000000},
{0x0000a140, 0x001f0000},
{0x0000a144, 0x01000101},
{0x0000a148, 0x011e011f},
{0x0000a14c, 0x011c011d},
{0x0000a150, 0x02030204},
{0x0000a154, 0x02010202},
{0x0000a158, 0x021f0200},
{0x0000a15c, 0x0302021e},
{0x0000a160, 0x03000301},
{0x0000a164, 0x031e031f},
{0x0000a168, 0x0402031d},
{0x0000a16c, 0x04000401},
{0x0000a170, 0x041e041f},
{0x0000a174, 0x0502041d},
{0x0000a178, 0x05000501},
{0x0000a17c, 0x051e051f},
{0x0000a180, 0x06010602},
{0x0000a184, 0x061f0600},
{0x0000a188, 0x061d061e},
{0x0000a18c, 0x07020703},
{0x0000a190, 0x07000701},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
{0x0000a1a0, 0x00000000},
{0x0000a1a4, 0x00000000},
{0x0000a1a8, 0x00000000},
{0x0000a1ac, 0x00000000},
{0x0000a1b0, 0x00000000},
{0x0000a1b4, 0x00000000},
{0x0000a1b8, 0x00000000},
{0x0000a1bc, 0x00000000},
{0x0000a1c0, 0x00000000},
{0x0000a1c4, 0x00000000},
{0x0000a1c8, 0x00000000},
{0x0000a1cc, 0x00000000},
{0x0000a1d0, 0x00000000},
{0x0000a1d4, 0x00000000},
{0x0000a1d8, 0x00000000},
{0x0000a1dc, 0x00000000},
{0x0000a1e0, 0x00000000},
{0x0000a1e4, 0x00000000},
{0x0000a1e8, 0x00000000},
{0x0000a1ec, 0x00000000},
{0x0000a1f0, 0x00000396},
{0x0000a1f4, 0x00000396},
{0x0000a1f8, 0x00000396},
{0x0000a1fc, 0x00000196},
{0x0000b000, 0x00010000},
{0x0000b004, 0x00030002},
{0x0000b008, 0x00050004},
{0x0000b00c, 0x00810080},
{0x0000b010, 0x00830082},
{0x0000b014, 0x01810180},
{0x0000b018, 0x01830182},
{0x0000b01c, 0x01850184},
{0x0000b020, 0x02810280},
{0x0000b024, 0x02830282},
{0x0000b028, 0x02850284},
{0x0000b02c, 0x02890288},
{0x0000b030, 0x028b028a},
{0x0000b034, 0x0388028c},
{0x0000b038, 0x038a0389},
{0x0000b03c, 0x038c038b},
{0x0000b040, 0x0390038d},
{0x0000b044, 0x03920391},
{0x0000b048, 0x03940393},
{0x0000b04c, 0x03960395},
{0x0000b050, 0x00000000},
{0x0000b054, 0x00000000},
{0x0000b058, 0x00000000},
{0x0000b05c, 0x00000000},
{0x0000b060, 0x00000000},
{0x0000b064, 0x00000000},
{0x0000b068, 0x00000000},
{0x0000b06c, 0x00000000},
{0x0000b070, 0x00000000},
{0x0000b074, 0x00000000},
{0x0000b078, 0x00000000},
{0x0000b07c, 0x00000000},
{0x0000b080, 0x2a2d2f32},
{0x0000b084, 0x21232328},
{0x0000b088, 0x19191c1e},
{0x0000b08c, 0x12141417},
{0x0000b090, 0x07070e0e},
{0x0000b094, 0x03030305},
{0x0000b098, 0x00000003},
{0x0000b09c, 0x00000000},
{0x0000b0a0, 0x00000000},
{0x0000b0a4, 0x00000000},
{0x0000b0a8, 0x00000000},
{0x0000b0ac, 0x00000000},
{0x0000b0b0, 0x00000000},
{0x0000b0b4, 0x00000000},
{0x0000b0b8, 0x00000000},
{0x0000b0bc, 0x00000000},
{0x0000b0c0, 0x003f0020},
{0x0000b0c4, 0x00400041},
{0x0000b0c8, 0x0140005f},
{0x0000b0cc, 0x0160015f},
{0x0000b0d0, 0x017e017f},
{0x0000b0d4, 0x02410242},
{0x0000b0d8, 0x025f0240},
{0x0000b0dc, 0x027f0260},
{0x0000b0e0, 0x0341027e},
{0x0000b0e4, 0x035f0340},
{0x0000b0e8, 0x037f0360},
{0x0000b0ec, 0x04400441},
{0x0000b0f0, 0x0460045f},
{0x0000b0f4, 0x0541047f},
{0x0000b0f8, 0x055f0540},
{0x0000b0fc, 0x057f0560},
{0x0000b100, 0x06400641},
{0x0000b104, 0x0660065f},
{0x0000b108, 0x067e067f},
{0x0000b10c, 0x07410742},
{0x0000b110, 0x075f0740},
{0x0000b114, 0x077f0760},
{0x0000b118, 0x07800781},
{0x0000b11c, 0x07a0079f},
{0x0000b120, 0x07c107bf},
{0x0000b124, 0x000007c0},
{0x0000b128, 0x00000000},
{0x0000b12c, 0x00000000},
{0x0000b130, 0x00000000},
{0x0000b134, 0x00000000},
{0x0000b138, 0x00000000},
{0x0000b13c, 0x00000000},
{0x0000b140, 0x003f0020},
{0x0000b144, 0x00400041},
{0x0000b148, 0x0140005f},
{0x0000b14c, 0x0160015f},
{0x0000b150, 0x017e017f},
{0x0000b154, 0x02410242},
{0x0000b158, 0x025f0240},
{0x0000b15c, 0x027f0260},
{0x0000b160, 0x0341027e},
{0x0000b164, 0x035f0340},
{0x0000b168, 0x037f0360},
{0x0000b16c, 0x04400441},
{0x0000b170, 0x0460045f},
{0x0000b174, 0x0541047f},
{0x0000b178, 0x055f0540},
{0x0000b17c, 0x057f0560},
{0x0000b180, 0x06400641},
{0x0000b184, 0x0660065f},
{0x0000b188, 0x067e067f},
{0x0000b18c, 0x07410742},
{0x0000b190, 0x075f0740},
{0x0000b194, 0x077f0760},
{0x0000b198, 0x07800781},
{0x0000b19c, 0x07a0079f},
{0x0000b1a0, 0x07c107bf},
{0x0000b1a4, 0x000007c0},
{0x0000b1a8, 0x00000000},
{0x0000b1ac, 0x00000000},
{0x0000b1b0, 0x00000000},
{0x0000b1b4, 0x00000000},
{0x0000b1b8, 0x00000000},
{0x0000b1bc, 0x00000000},
{0x0000b1c0, 0x00000000},
{0x0000b1c4, 0x00000000},
{0x0000b1c8, 0x00000000},
{0x0000b1cc, 0x00000000},
{0x0000b1d0, 0x00000000},
{0x0000b1d4, 0x00000000},
{0x0000b1d8, 0x00000000},
{0x0000b1dc, 0x00000000},
{0x0000b1e0, 0x00000000},
{0x0000b1e4, 0x00000000},
{0x0000b1e8, 0x00000000},
{0x0000b1ec, 0x00000000},
{0x0000b1f0, 0x00000396},
{0x0000b1f4, 0x00000396},
{0x0000b1f8, 0x00000396},
{0x0000b1fc, 0x00000196},
};
#define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0
static const u32 ar9580_1p0_radio_core[][2] = {
/* Addr allmodes */

View File

@ -722,6 +722,7 @@ extern int ath9k_modparam_nohwcrypt;
extern int led_blink;
extern bool is_ath9k_unloaded;
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);

View File

@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
sc->debug.stats.istats.txok++;
if (status & ATH9K_INT_TXURN)
sc->debug.stats.istats.txurn++;
if (status & ATH9K_INT_MIB)
sc->debug.stats.istats.mib++;
if (status & ATH9K_INT_RXPHY)
sc->debug.stats.istats.rxphyerr++;
if (status & ATH9K_INT_RXKCM)

View File

@ -416,7 +416,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
txq = sc->tx.txq_map[WME_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
if (AR_SREV_9462(ah)) {
if (ath9k_hw_mci_is_enabled(ah)) {
sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
INIT_LIST_HEAD(&sc->btcoex.mci.info);

View File

@ -453,7 +453,6 @@ struct ath9k_htc_priv {
u8 num_sta_assoc_vif;
u8 num_ap_vif;
u16 op_flags;
u16 curtxpow;
u16 txpowlimit;
u16 nvifs;
@ -461,6 +460,7 @@ struct ath9k_htc_priv {
bool rearm_ani;
bool reconfig_beacon;
unsigned int rxfilter;
unsigned long op_flags;
struct ath9k_hw_cal_data caldata;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
#ifdef CONFIG_MAC80211_LEDS
void ath9k_init_leds(struct ath9k_htc_priv *priv);

View File

@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
if (priv->op_flags & OP_TSF_RESET) {
if (test_bit(OP_TSF_RESET, &priv->op_flags)) {
ath9k_hw_reset_tsf(priv->ah);
priv->op_flags &= ~OP_TSF_RESET;
clear_bit(OP_TSF_RESET, &priv->op_flags);
} else {
/*
* Pull nexttbtt forward to reflect the current TSF.
@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
} while (nexttbtt < tsftu);
}
if (priv->op_flags & OP_ENABLE_BEACON)
if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG,
@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
if (priv->op_flags & OP_ENABLE_BEACON)
if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG,
@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
vif = priv->cur_beacon_conf.bslot[slot];
avp = (struct ath9k_htc_vif *)vif->drv_priv;
if (unlikely(priv->op_flags & OP_SCANNING)) {
if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) {
spin_unlock_bh(&priv->beacon_lock);
return;
}

View File

@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
if (time_after(jiffies, btcoex->bt_priority_time +
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
clear_bit(OP_BT_SCAN, &priv->op_flags);
/* Detect if colocated bt started scanning */
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT scan detected\n");
priv->op_flags |= (OP_BT_SCAN |
OP_BT_PRIORITY_DETECTED);
set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
set_bit(OP_BT_SCAN, &priv->op_flags);
} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT priority traffic detected\n");
priv->op_flags |= OP_BT_PRIORITY_DETECTED;
set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
}
btcoex->bt_priority_cnt = 0;
@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work)
struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(priv->ah);
u32 timer_period;
bool is_btscan;
int ret;
ath_detect_bt_priority(priv);
is_btscan = !!(priv->op_flags & OP_BT_SCAN);
ret = ath9k_htc_update_cap_target(priv,
!!(priv->op_flags & OP_BT_PRIORITY_DETECTED));
test_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags));
if (ret) {
ath_err(common, "Unable to set BTCOEX parameters\n");
return;
}
ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
btcoex->bt_stomp_type);
ath9k_hw_btcoex_bt_stomp(priv->ah, test_bit(OP_BT_SCAN, &priv->op_flags) ?
ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type);
ath9k_hw_btcoex_enable(priv->ah);
timer_period = is_btscan ? btcoex->btscan_no_stomp :
btcoex->btcoex_no_stomp;
timer_period = test_bit(OP_BT_SCAN, &priv->op_flags) ?
btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp;
ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
msecs_to_jiffies(timer_period));
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
struct ath_hw *ah = priv->ah;
struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(ah);
bool is_btscan = priv->op_flags & OP_BT_SCAN;
ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
test_bit(OP_BT_SCAN, &priv->op_flags))
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
ath9k_hw_btcoex_enable(priv->ah);
}
@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies;
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
clear_bit(OP_BT_SCAN, &priv->op_flags);
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
}
@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
wiphy_rfkill_start_polling(priv->hw->wiphy);
}
void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
int ret;
u8 cmd_rsp;
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
/* Reset the HW */
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (ret) {
ath_err(common,
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
ret, ah->curchan->channel);
}
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
&priv->curtxpow);
/* Start RX */
WMI_CMD(WMI_START_RECV_CMDID);
ath9k_host_rx_init(priv);
/* Start TX */
htc_start(priv->htc);
spin_lock_bh(&priv->tx.tx_lock);
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
spin_unlock_bh(&priv->tx.tx_lock);
ieee80211_wake_queues(hw);
WMI_CMD(WMI_ENABLE_INTR_CMDID);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
}
void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
int ret;
u8 cmd_rsp;
ath9k_htc_ps_wakeup(priv);
/* Disable LED */
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
/* Stop TX */
ieee80211_stop_queues(hw);
ath9k_htc_tx_drain(priv);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
/* Stop RX */
WMI_CMD(WMI_STOP_RECV_CMDID);
/* Clear the WMI event queue */
ath9k_wmi_event_drain(priv);
/*
* The MIB counters have to be disabled here,
* since the target doesn't do it.
*/
ath9k_hw_disable_mib_counters(ah);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
/* Reset the HW */
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (ret) {
ath_err(common,
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
ret, ah->curchan->channel);
}
/* Disable the PHY */
ath9k_hw_phy_disable(ah);
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
}

View File

@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
struct ath_common *common;
int i, ret = 0, csz = 0;
priv->op_flags |= OP_INVALID;
set_bit(OP_INVALID, &priv->op_flags);
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
if (!ah)
@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->queues = 4;
hw->channel_change_time = 5000;
hw->max_listen_interval = 10;
hw->max_listen_interval = 1;
hw->vif_data_size = sizeof(struct ath9k_htc_vif);
hw->sta_data_size = sizeof(struct ath9k_htc_sta);

View File

@ -75,14 +75,19 @@ unlock:
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
{
bool reset;
mutex_lock(&priv->htc_pm_lock);
if (--priv->ps_usecount != 0)
goto unlock;
if (priv->ps_idle)
if (priv->ps_idle) {
ath9k_hw_setrxabort(priv->ah, true);
ath9k_hw_stopdmarecv(priv->ah, &reset);
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
else if (priv->ps_enabled)
} else if (priv->ps_enabled) {
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
}
unlock:
mutex_unlock(&priv->htc_pm_lock);
@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
int ret;
if (priv->op_flags & OP_INVALID)
if (test_bit(OP_INVALID, &priv->op_flags))
return -EIO;
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
htc_start(priv->htc);
if (!(priv->op_flags & OP_SCANNING) &&
if (!test_bit(OP_SCANNING, &priv->op_flags) &&
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
ath9k_htc_vif_reconfig(priv);
@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
common->ani.shortcal_timer = timestamp;
common->ani.checkani_timer = timestamp;
priv->op_flags |= OP_ANI_RUNNING;
set_bit(OP_ANI_RUNNING, &priv->op_flags);
ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
{
cancel_delayed_work_sync(&priv->ani_work);
priv->op_flags &= ~OP_ANI_RUNNING;
clear_bit(OP_ANI_RUNNING, &priv->op_flags);
}
void ath9k_htc_ani_work(struct work_struct *work)
@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ath_dbg(common, CONFIG,
"Failed to update capability in target\n");
priv->op_flags &= ~OP_INVALID;
clear_bit(OP_INVALID, &priv->op_flags);
htc_start(priv->htc);
spin_lock_bh(&priv->tx.tx_lock);
@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
if (priv->op_flags & OP_INVALID) {
if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(common, ANY, "Device not present\n");
mutex_unlock(&priv->mutex);
return;
@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
priv->op_flags |= OP_INVALID;
set_bit(OP_INVALID, &priv->op_flags);
ath_dbg(common, CONFIG, "Driver halt\n");
mutex_unlock(&priv->mutex);
@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv);
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
!(priv->op_flags & OP_ANI_RUNNING)) {
!test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
ath9k_hw_set_tsfadjust(priv->ah, 1);
ath9k_htc_start_ani(priv);
}
@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ieee80211_conf *conf = &hw->conf;
bool chip_reset = false;
int ret = 0;
mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv);
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
bool enable_radio = false;
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
mutex_lock(&priv->htc_pm_lock);
if (!idle && priv->ps_idle)
enable_radio = true;
priv->ps_idle = idle;
mutex_unlock(&priv->htc_pm_lock);
if (enable_radio) {
ath_dbg(common, CONFIG, "not-idle: enabling radio\n");
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
ath9k_htc_radio_enable(hw);
}
priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
if (priv->ps_idle)
chip_reset = true;
mutex_unlock(&priv->htc_pm_lock);
}
/*
@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
ath9k_htc_remove_monitor_interface(priv);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
mutex_unlock(&priv->mutex);
return -EINVAL;
ret = -EINVAL;
goto out;
}
}
@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
priv->txpowlimit, &priv->curtxpow);
}
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
mutex_lock(&priv->htc_pm_lock);
if (!priv->ps_idle) {
mutex_unlock(&priv->htc_pm_lock);
goto out;
}
mutex_unlock(&priv->htc_pm_lock);
ath_dbg(common, CONFIG, "idle: disabling radio\n");
ath9k_htc_radio_disable(hw);
}
out:
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
return 0;
return ret;
}
#define SUPPORTED_FILTERS \
@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
if (priv->op_flags & OP_INVALID) {
if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(ath9k_hw_common(priv->ah), ANY,
"Unable to configure filter on invalid state\n");
mutex_unlock(&priv->mutex);
@ -1516,7 +1506,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
bss_conf->bssid);
ath9k_htc_set_tsfadjust(priv, vif);
priv->op_flags |= OP_ENABLE_BEACON;
set_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif);
}
@ -1529,7 +1519,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG,
"Beacon disabled for BSS: %pM\n",
bss_conf->bssid);
priv->op_flags &= ~OP_ENABLE_BEACON;
clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif);
}
}
@ -1542,7 +1532,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
(priv->nvifs == 1) &&
(priv->num_ap_vif == 1) &&
(vif->type == NL80211_IFTYPE_AP)) {
priv->op_flags |= OP_TSF_RESET;
set_bit(OP_TSF_RESET, &priv->op_flags);
}
ath_dbg(common, CONFIG,
"Beacon interval changed for BSS: %pM\n",
@ -1654,7 +1644,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock);
priv->op_flags |= OP_SCANNING;
set_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock);
cancel_work_sync(&priv->ps_work);
ath9k_htc_stop_ani(priv);
@ -1667,7 +1657,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock);
priv->op_flags &= ~OP_SCANNING;
clear_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock);
ath9k_htc_ps_wakeup(priv);
ath9k_htc_vif_reconfig(priv);

View File

@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
{
ath9k_hw_rxena(priv->ah);
ath9k_htc_opmode_init(priv);
ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING));
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
}

View File

@ -1019,16 +1019,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah);
void ar9003_hw_attach_ops(struct ath_hw *ah);
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
/*
* ANI work can be shared between all families but a next
* generation implementation of ANI will be used only for AR9003 only
* for now as the other families still need to be tested with the same
* next generation ANI. Feel free to start testing it though for the
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
*/
extern int modparam_force_new_ani;
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
@ -1038,7 +1030,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
}
static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
{
return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
return ah->common.btcoex_enabled &&
(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
}
void ath9k_hw_btcoex_enable(struct ath_hw *ah);

View File

@ -407,6 +407,7 @@ void ath_ani_calibrate(unsigned long data)
longcal ? "long" : "", shortcal ? "short" : "",
aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
ath9k_debug_samp_bb_mac(sc);
ath9k_ps_restore(sc);
set_timer:
@ -415,7 +416,6 @@ set_timer:
* The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration.
*/
ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval,

View File

@ -19,7 +19,7 @@
#include "ath9k.h"
#include "btcoex.h"
static u8 parse_mpdudensity(u8 mpdudensity)
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
{
/*
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
@ -150,8 +150,10 @@ static void __ath_cancel_work(struct ath_softc *sc)
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
cancel_work_sync(&sc->mci_work);
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
cancel_work_sync(&sc->mci_work);
#endif
}
@ -320,6 +322,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct ath_node *an;
u8 density;
an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS
@ -334,7 +337,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
an->mpdudensity = density;
}
}
@ -516,24 +520,6 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_hw_set_interrupts(ah);
}
if (status & ATH9K_INT_MIB) {
/*
* Disable interrupts until we service the MIB
* interrupt; otherwise it will continue to
* fire.
*/
ath9k_hw_disable_interrupts(ah);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
* the interrupt.
*/
spin_lock(&common->cc_lock);
ath9k_hw_proc_mib_event(ah);
spin_unlock(&common->cc_lock);
ath9k_hw_enable_interrupts(ah);
}
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
if (status & ATH9K_INT_TIM_TIMER) {
if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
@ -959,14 +945,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
/*
* Enable MIB interrupts when there are hardware phy counters.
*/
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
if (ah->config.enable_ani)
ah->imask |= ATH9K_INT_MIB;
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
ah->imask |= ATH9K_INT_TSFOOR;
} else {
ah->imask &= ~ATH9K_INT_MIB;
else
ah->imask &= ~ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(ah);

View File

@ -233,8 +233,21 @@ static void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *entry = NULL;
entry = ath_mci_find_profile(mci, info);
if (entry)
if (entry) {
/*
* Two MCI interrupts are generated while connecting to
* headset and A2DP profile, but only one MCI interrupt
* is generated with last added profile type while disconnecting
* both profiles.
* So while adding second profile type decrement
* the first one.
*/
if (entry->type != info->type) {
DEC_PROF(mci, entry);
INC_PROF(mci, info);
}
memcpy(entry, info, 10);
}
if (info->start) {
if (!entry && !ath_mci_add_profile(common, mci, info))
@ -335,7 +348,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
seq_num = *((u32 *)(rx_payload + 12));
ath_dbg(common, MCI,
"BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%d\n",
"BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%u\n",
profile_status.is_link, profile_status.conn_handle,
profile_status.is_critical, seq_num);

View File

@ -2162,10 +2162,6 @@ enum {
#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
#define AR_BTCOEX_WL_WEIGHTS0 0x18b0
#define AR_BTCOEX_WL_WEIGHTS1 0x18b4
#define AR_BTCOEX_WL_WEIGHTS2 0x18b8
#define AR_BTCOEX_WL_WEIGHTS3 0x18bc
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
#define AR_BTCOEX_WL_LNA 0x1940
#define AR_BTCOEX_RFGAIN_CTRL 0x1944

View File

@ -1165,6 +1165,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
{
struct ath_atx_tid *txtid;
struct ath_node *an;
u8 density;
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
@ -1172,6 +1173,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
return -EAGAIN;
/* update ampdu factor/density, they may have changed. This may happen
* in HT IBSS when a beacon with HT-info is received after the station
* has already been added.
*/
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
an->mpdudensity = density;
}
txtid->state |= AGGR_ADDBA_PROGRESS;
txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next;

View File

@ -44,6 +44,7 @@
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
@ -52,6 +53,7 @@
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);

View File

@ -36,6 +36,13 @@ struct dngl_stats {
unsigned long multicast; /* multicast packets received */
};
struct brcmf_bus_dcmd {
char *name;
char *param;
int param_len;
struct list_head list;
};
/* interface structure between common and bus layer */
struct brcmf_bus {
u8 type; /* bus type */
@ -50,6 +57,7 @@ struct brcmf_bus {
unsigned long tx_realloc; /* Tx packets realloced for headroom */
struct dngl_stats dstats; /* Stats for dongle-based data */
u8 align; /* bus alignment requirement */
struct list_head dcmd_list;
/* interface functions pointers */
/* Stop bus module: clear pending frames, disable data flow */

View File

@ -800,13 +800,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
"event_msgs" + '\0' + bitvec */
char buf[128], *ptr;
u32 dongle_align = drvr->bus_if->align;
u32 glom = 0;
u32 roaming = 1;
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
int i;
struct brcmf_bus_dcmd *cmdlst;
struct list_head *cur, *q;
mutex_lock(&drvr->proto_block);
@ -827,17 +827,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
/* Print fw version info */
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
/* Match Host and Dongle rx alignment */
brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* disable glom option per default */
brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* Setup timeout if Beacons are lost and roam is off to report
link down */
brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
@ -874,6 +863,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
0, true);
}
/* set bus specific command if there is any */
list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) {
cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
cmdlst->param_len, iovbuf,
sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
}
list_del(cur);
kfree(cmdlst);
}
mutex_unlock(&drvr->proto_block);
return 0;

View File

@ -1020,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
return ret;
fail:

View File

@ -31,6 +31,8 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/bcma/bcma.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@ -48,6 +50,9 @@
#define CBUF_LEN (128)
/* Device console log buffer state */
#define CONSOLE_BUFFER_MAX 2024
struct rte_log_le {
__le32 buf; /* Can't be pointer on (64-bit) hosts */
__le32 buf_size;
@ -281,7 +286,7 @@ struct rte_console {
* Shared structure between dongle and the host.
* The structure contains pointers to trap or assert information.
*/
#define SDPCM_SHARED_VERSION 0x0002
#define SDPCM_SHARED_VERSION 0x0003
#define SDPCM_SHARED_VERSION_MASK 0x00FF
#define SDPCM_SHARED_ASSERT_BUILT 0x0100
#define SDPCM_SHARED_ASSERT 0x0200
@ -428,6 +433,29 @@ struct brcmf_console {
u8 *buf; /* Log buffer (host copy) */
uint last; /* Last buffer read index */
};
struct brcmf_trap_info {
__le32 type;
__le32 epc;
__le32 cpsr;
__le32 spsr;
__le32 r0; /* a1 */
__le32 r1; /* a2 */
__le32 r2; /* a3 */
__le32 r3; /* a4 */
__le32 r4; /* v1 */
__le32 r5; /* v2 */
__le32 r6; /* v3 */
__le32 r7; /* v4 */
__le32 r8; /* v5 */
__le32 r9; /* sb/v6 */
__le32 r10; /* sl/v7 */
__le32 r11; /* fp/v8 */
__le32 r12; /* ip */
__le32 r13; /* sp */
__le32 r14; /* lr */
__le32 pc; /* r15 */
};
#endif /* DEBUG */
struct sdpcm_shared {
@ -439,6 +467,7 @@ struct sdpcm_shared {
u32 console_addr; /* Address of struct rte_console */
u32 msgtrace_addr;
u8 tag[32];
u32 brpt_addr;
};
struct sdpcm_shared_le {
@ -450,6 +479,7 @@ struct sdpcm_shared_le {
__le32 console_addr; /* Address of struct rte_console */
__le32 msgtrace_addr;
u8 tag[32];
__le32 brpt_addr;
};
@ -2953,13 +2983,311 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
}
#ifdef DEBUG
static inline bool brcmf_sdio_valid_shared_address(u32 addr)
{
return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
}
static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
struct sdpcm_shared *sh)
{
u32 addr;
int rv;
u32 shaddr = 0;
struct sdpcm_shared_le sh_le;
__le32 addr_le;
shaddr = bus->ramsize - 4;
/*
* Read last word in socram to determine
* address of sdpcm_shared structure
*/
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
(u8 *)&addr_le, 4);
if (rv < 0)
return rv;
addr = le32_to_cpu(addr_le);
brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
/*
* Check if addr is valid.
* NVRAM length at the end of memory should have been overwritten.
*/
if (!brcmf_sdio_valid_shared_address(addr)) {
brcmf_dbg(ERROR, "invalid sdpcm_shared address 0x%08X\n",
addr);
return -EINVAL;
}
/* Read hndrte_shared structure */
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
sizeof(struct sdpcm_shared_le));
if (rv < 0)
return rv;
/* Endianness */
sh->flags = le32_to_cpu(sh_le.flags);
sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
sh->assert_line = le32_to_cpu(sh_le.assert_line);
sh->console_addr = le32_to_cpu(sh_le.console_addr);
sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
brcmf_dbg(ERROR,
"sdpcm_shared version mismatch: dhd %d dongle %d\n",
SDPCM_SHARED_VERSION,
sh->flags & SDPCM_SHARED_VERSION_MASK);
return -EPROTO;
}
return 0;
}
static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
struct sdpcm_shared *sh, char __user *data,
size_t count)
{
u32 addr, console_ptr, console_size, console_index;
char *conbuf = NULL;
__le32 sh_val;
int rv;
loff_t pos = 0;
int nbytes = 0;
/* obtain console information from device memory */
addr = sh->console_addr + offsetof(struct rte_console, log_le);
rv = brcmf_sdbrcm_membytes(bus, false, addr,
(u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_ptr = le32_to_cpu(sh_val);
addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
rv = brcmf_sdbrcm_membytes(bus, false, addr,
(u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_size = le32_to_cpu(sh_val);
addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
rv = brcmf_sdbrcm_membytes(bus, false, addr,
(u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_index = le32_to_cpu(sh_val);
/* allocate buffer for console data */
if (console_size <= CONSOLE_BUFFER_MAX)
conbuf = vzalloc(console_size+1);
if (!conbuf)
return -ENOMEM;
/* obtain the console data from device */
conbuf[console_size] = '\0';
rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
console_size);
if (rv < 0)
goto done;
rv = simple_read_from_buffer(data, count, &pos,
conbuf + console_index,
console_size - console_index);
if (rv < 0)
goto done;
nbytes = rv;
if (console_index > 0) {
pos = 0;
rv = simple_read_from_buffer(data+nbytes, count, &pos,
conbuf, console_index - 1);
if (rv < 0)
goto done;
rv += nbytes;
}
done:
vfree(conbuf);
return rv;
}
static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
char __user *data, size_t count)
{
int error, res;
char buf[350];
struct brcmf_trap_info tr;
int nbytes;
loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
return 0;
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
if (nbytes < 0)
return nbytes;
res = scnprintf(buf, sizeof(buf),
"dongle trap info: type 0x%x @ epc 0x%08x\n"
" cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
" lr 0x%08x pc 0x%08x offset 0x%x\n"
" r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
" r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
le32_to_cpu(tr.pc), sh->trap_addr,
le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res);
if (error < 0)
return error;
nbytes += error;
return nbytes;
}
static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
struct sdpcm_shared *sh, char __user *data,
size_t count)
{
int error = 0;
char buf[200];
char file[80] = "?";
char expr[80] = "<???>";
int res;
loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
brcmf_dbg(INFO, "firmware not built with -assert\n");
return 0;
} else if ((sh->flags & SDPCM_SHARED_ASSERT) == 0) {
brcmf_dbg(INFO, "no assert in dongle\n");
return 0;
}
if (sh->assert_file_addr != 0) {
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
(u8 *)file, 80);
if (error < 0)
return error;
}
if (sh->assert_exp_addr != 0) {
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr,
(u8 *)expr, 80);
if (error < 0)
return error;
}
res = scnprintf(buf, sizeof(buf),
"dongle assert: %s:%d: assert(%s)\n",
file, sh->assert_line, expr);
return simple_read_from_buffer(data, count, &pos, buf, res);
}
static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
{
int error;
struct sdpcm_shared sh;
down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
up(&bus->sdsem);
if (error < 0)
return error;
if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0)
brcmf_dbg(INFO, "firmware not built with -assert\n");
else if (sh.flags & SDPCM_SHARED_ASSERT)
brcmf_dbg(ERROR, "assertion in dongle\n");
if (sh.flags & SDPCM_SHARED_TRAP)
brcmf_dbg(ERROR, "firmware trap in dongle\n");
return 0;
}
static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
size_t count, loff_t *ppos)
{
int error = 0;
struct sdpcm_shared sh;
int nbytes = 0;
loff_t pos = *ppos;
if (pos != 0)
return 0;
down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
if (error < 0)
goto done;
error = brcmf_sdio_assert_info(bus, &sh, data, count);
if (error < 0)
goto done;
nbytes = error;
error = brcmf_sdio_trap_info(bus, &sh, data, count);
if (error < 0)
goto done;
error += nbytes;
*ppos += error;
done:
up(&bus->sdsem);
return error;
}
static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
{
struct brcmf_sdio *bus = f->private_data;
int res;
res = brcmf_sdbrcm_died_dump(bus, data, count, ppos);
if (res > 0)
*ppos += res;
return (ssize_t)res;
}
static const struct file_operations brcmf_sdio_forensic_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = brcmf_sdio_forensic_read
};
static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
{
struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr;
struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);
if (IS_ERR_OR_NULL(dentry))
return;
debugfs_create_file("forensics", S_IRUGO, dentry, bus,
&brcmf_sdio_forensic_ops);
brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
}
#else
static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
{
return 0;
}
static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
{
}
@ -2991,11 +3319,13 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
rxlen, msglen);
} else if (timeleft == 0) {
brcmf_dbg(ERROR, "resumed on timeout\n");
brcmf_sdbrcm_checkdied(bus);
} else if (pending) {
brcmf_dbg(CTL, "cancelled\n");
return -ERESTARTSYS;
} else {
brcmf_dbg(CTL, "resumed for unknown reason?\n");
brcmf_sdbrcm_checkdied(bus);
}
if (rxlen)
@ -3006,45 +3336,10 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len)
{
int bcmerror = 0;
brcmf_dbg(TRACE, "Enter\n");
/* Basic sanity checks */
if (bus->sdiodev->bus_if->drvr_up) {
bcmerror = -EISCONN;
goto err;
}
if (!len) {
bcmerror = -EOVERFLOW;
goto err;
}
/* Free the old ones and replace with passed variables */
kfree(bus->vars);
bus->vars = kmalloc(len, GFP_ATOMIC);
bus->varsz = bus->vars ? len : 0;
if (bus->vars == NULL) {
bcmerror = -ENOMEM;
goto err;
}
/* Copy the passed variables, which should include the
terminating double-null */
memcpy(bus->vars, arg, bus->varsz);
err:
return bcmerror;
}
static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
{
int bcmerror = 0;
u32 varsize;
u32 varaddr;
u8 *vbuffer;
u32 varsizew;
__le32 varsizew_le;
#ifdef DEBUG
@ -3053,56 +3348,44 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
/* Even if there are no vars are to be written, we still
need to set the ramsize. */
varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
varaddr = (bus->ramsize - 4) - varsize;
varaddr = (bus->ramsize - 4) - bus->varsz;
if (bus->vars) {
vbuffer = kzalloc(varsize, GFP_ATOMIC);
if (!vbuffer)
return -ENOMEM;
memcpy(vbuffer, bus->vars, bus->varsz);
/* Write the vars list */
bcmerror =
brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr,
bus->vars, bus->varsz);
#ifdef DEBUG
/* Verify NVRAM bytes */
brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize);
nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
if (!nvram_ularray) {
kfree(vbuffer);
brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n",
bus->varsz);
nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
if (!nvram_ularray)
return -ENOMEM;
}
/* Upload image to verify downloaded contents. */
memset(nvram_ularray, 0xaa, varsize);
memset(nvram_ularray, 0xaa, bus->varsz);
/* Read the vars list to temp buffer for comparison */
bcmerror =
brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
varsize);
bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
nvram_ularray, bus->varsz);
if (bcmerror) {
brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n",
bcmerror, varsize, varaddr);
bcmerror, bus->varsz, varaddr);
}
/* Compare the org NVRAM with the one read from RAM */
if (memcmp(vbuffer, nvram_ularray, varsize))
if (memcmp(bus->vars, nvram_ularray, bus->varsz))
brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n");
else
brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n");
kfree(nvram_ularray);
#endif /* DEBUG */
kfree(vbuffer);
}
/* adjust to the user specified RAM */
brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
varaddr, varsize);
varsize = ((bus->ramsize - 4) - varaddr);
varaddr, bus->varsz);
/*
* Determine the length token:
@ -3113,13 +3396,13 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
varsizew = 0;
varsizew_le = cpu_to_le32(0);
} else {
varsizew = varsize / 4;
varsizew = bus->varsz / 4;
varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
varsizew_le = cpu_to_le32(varsizew);
}
brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
varsize, varsizew);
bus->varsz, varsizew);
/* Write the length token to the last word */
bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
@ -3243,13 +3526,21 @@ err:
* by two NULs.
*/
static uint brcmf_process_nvram_vars(char *varbuf, uint len)
static int brcmf_process_nvram_vars(struct brcmf_sdio *bus)
{
char *varbuf;
char *dp;
bool findNewline;
int column;
uint buf_len, n;
int ret = 0;
uint buf_len, n, len;
len = bus->firmware->size;
varbuf = vmalloc(len);
if (!varbuf)
return -ENOMEM;
memcpy(varbuf, bus->firmware->data, len);
dp = varbuf;
findNewline = false;
@ -3278,56 +3569,44 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len)
column++;
}
buf_len = dp - varbuf;
while (dp < varbuf + n)
*dp++ = 0;
return buf_len;
kfree(bus->vars);
/* roundup needed for download to device */
bus->varsz = roundup(buf_len + 1, 4);
bus->vars = kmalloc(bus->varsz, GFP_KERNEL);
if (bus->vars == NULL) {
bus->varsz = 0;
ret = -ENOMEM;
goto err;
}
/* copy the processed variables and add null termination */
memcpy(bus->vars, varbuf, buf_len);
bus->vars[buf_len] = 0;
err:
vfree(varbuf);
return ret;
}
static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
{
uint len;
char *memblock = NULL;
char *bufp;
int ret;
if (bus->sdiodev->bus_if->drvr_up)
return -EISCONN;
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
&bus->sdiodev->func[2]->dev);
if (ret) {
brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
return ret;
}
bus->fw_ptr = 0;
memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
if (memblock == NULL) {
ret = -ENOMEM;
goto err;
}
len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
if (len > 0 && len < MEMBLOCK) {
bufp = memblock;
bufp[len] = 0;
len = brcmf_process_nvram_vars(bufp, len);
bufp += len;
*bufp++ = 0;
if (len)
ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
if (ret)
brcmf_dbg(ERROR, "error downloading vars: %d\n", ret);
} else {
brcmf_dbg(ERROR, "error reading nvram file: %d\n", len);
ret = -EIO;
}
err:
kfree(memblock);
ret = brcmf_process_nvram_vars(bus);
release_firmware(bus->firmware);
bus->fw_ptr = 0;
return ret;
}
@ -3606,6 +3885,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
return true;
if (chipid == BCM4330_CHIP_ID)
return true;
if (chipid == BCM4334_CHIP_ID)
return true;
return false;
}
@ -3817,6 +4098,7 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
{
brcmf_dbg(TRACE, "Enter\n");
if (bus) {
/* De-register interrupt handler */
brcmf_sdio_intr_unregister(bus->sdiodev);
@ -3838,6 +4120,10 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
{
int ret;
struct brcmf_sdio *bus;
struct brcmf_bus_dcmd *dlst;
u32 dngl_txglom;
u32 dngl_txglomalign;
u8 idx;
brcmf_dbg(TRACE, "Enter\n");
@ -3923,6 +4209,26 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n");
/* sdio bus core specific dcmd */
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL);
if (dlst) {
if (bus->ci->c_inf[idx].rev < 12) {
/* for sdio core rev < 12, disable txgloming */
dngl_txglom = 0;
dlst->name = "bus:txglom";
dlst->param = (char *)&dngl_txglom;
dlst->param_len = sizeof(u32);
} else {
/* otherwise, set txglomalign */
dngl_txglomalign = bus->sdiodev->bus_if->align;
dlst->name = "bus:txglomalign";
dlst->param = (char *)&dngl_txglomalign;
dlst->param_len = sizeof(u32);
}
list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list);
}
/* if firmware path present try to download and bring up bus */
ret = brcmf_bus_start(bus->sdiodev->dev);
if (ret != 0) {

View File

@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].cib = 0x03004211;
ci->ramsize = 0x48000;
break;
case BCM4334_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x29004211;
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = 0x18002000;
ci->c_inf[1].wrapbase = 0x18102000;
ci->c_inf[1].cib = 0x0d004211;
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
ci->c_inf[2].base = 0x18004000;
ci->c_inf[2].wrapbase = 0x18104000;
ci->c_inf[2].cib = 0x13080401;
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
ci->c_inf[3].base = 0x18003000;
ci->c_inf[3].wrapbase = 0x18103000;
ci->c_inf[3].cib = 0x07004211;
ci->ramsize = 0x80000;
break;
default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit);
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
u16 chspec);
@ -49,5 +46,6 @@ extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
u16 chanspec,
u8 local_constraint_qdbm);
extern void brcms_c_regd_init(struct brcms_c_info *wlc);
#endif /* _WLC_CHANNEL_H */

View File

@ -1050,6 +1050,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
goto fail;
}
brcms_c_regd_init(wl->wlc);
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
if (WARN_ON(!is_valid_ether_addr(perm)))
goto fail;

View File

@ -18,6 +18,7 @@
#include <linux/pci_ids.h>
#include <linux/if_ether.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <brcm_hw_ids.h>
#include <aiutils.h>
@ -3139,20 +3140,6 @@ void brcms_c_reset(struct brcms_c_info *wlc)
brcms_b_reset(wlc->hw);
}
/* Return the channel the driver should initialize during brcms_c_init.
* the channel may have to be changed from the currently configured channel
* if other configurations are in conflict (bandlocked, 11n mode disabled,
* invalid channel for current country, etc.)
*/
static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
{
u16 chanspec =
1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
WL_CHANSPEC_BAND_2G;
return chanspec;
}
void brcms_c_init_scb(struct scb *scb)
{
int i;
@ -5129,6 +5116,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
/* make interface operational */
int brcms_c_up(struct brcms_c_info *wlc)
{
struct ieee80211_channel *ch;
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/* HW is turned off so don't try to access it */
@ -5195,8 +5184,9 @@ int brcms_c_up(struct brcms_c_info *wlc)
wlc->pub->up = true;
if (wlc->bandinit_pending) {
ch = wlc->pub->ieee_hw->conf.channel;
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
wlc->bandinit_pending = false;
brcms_c_enable_mac(wlc);
}
@ -5397,11 +5387,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
else
return -EINVAL;
/* Legacy or bust when no OFDM is supported by regulatory */
if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
return -EINVAL;
/* update configuration value */
if (config)
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
@ -8201,19 +8186,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
{
struct bcma_device *core = wlc->hw->d11core;
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
u16 chanspec;
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/*
* This will happen if a big-hammer was executed. In
* that case, we want to go back to the channel that
* we were on and not new channel
*/
if (wlc->pub->associated)
chanspec = wlc->home_chanspec;
else
chanspec = brcms_c_init_chanspec(wlc);
chanspec = ch20mhz_chspec(ch->hw_value);
brcms_b_init(wlc->hw, chanspec);

View File

@ -37,5 +37,6 @@
#define BCM4329_CHIP_ID 0x4329
#define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331
#define BCM4334_CHIP_ID 0x4334
#endif /* _BRCM_HW_IDS_H_ */

View File

@ -4717,10 +4717,11 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
struct il_tx_queue *txq = &il->txq[cnt];
struct il_queue *q = &txq->q;
unsigned long timeout;
unsigned long now = jiffies;
int ret;
if (q->read_ptr == q->write_ptr) {
txq->time_stamp = jiffies;
txq->time_stamp = now;
return 0;
}
@ -4728,9 +4729,9 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
txq->time_stamp +
msecs_to_jiffies(il->cfg->wd_timeout);
if (time_after(jiffies, timeout)) {
if (time_after(now, timeout)) {
IL_ERR("Queue %d stuck for %u ms.\n", q->id,
il->cfg->wd_timeout);
jiffies_to_msecs(now - txq->time_stamp));
ret = il_force_reset(il, false);
return (ret == -EAGAIN) ? 0 : 1;
}

View File

@ -269,7 +269,7 @@ void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 15)
/* bt coex */

View File

@ -568,7 +568,6 @@ enum iwl_scan_type {
*
* @tx_chains_num: Number of TX chains
* @rx_chains_num: Number of RX chains
* @sku: sku read from EEPROM
* @ct_kill_threshold: temperature threshold - in hw dependent unit
* @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
* relevant for 1000, 6000 and up
@ -579,7 +578,6 @@ struct iwl_hw_params {
u8 tx_chains_num;
u8 rx_chains_num;
bool use_rts_for_aggregation;
u16 sku;
u32 ct_kill_threshold;
u32 ct_kill_exit_threshold;

View File

@ -250,17 +250,6 @@ struct iwl_lib_ops iwl2030_lib = {
*/
/* NIC configuration for 5000 series */
static void iwl5000_nic_config(struct iwl_priv *priv)
{
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
*/
iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
}
static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.min_nrg_cck = 100,
.auto_corr_min_ofdm = 90,
@ -433,14 +422,12 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.set_channel_switch = iwl5000_hw_channel_switch,
.nic_config = iwl5000_nic_config,
.temperature = iwlagn_temperature,
};
struct iwl_lib_ops iwl5150_lib = {
.set_hw_params = iwl5150_hw_set_hw_params,
.set_channel_switch = iwl5000_hw_channel_switch,
.nic_config = iwl5000_nic_config,
.temperature = iwl5150_temperature,
};

View File

@ -160,7 +160,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
IWL_PAN_SCD_MULTICAST_MSK;
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",

View File

@ -164,7 +164,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
*/
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@ -649,7 +649,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE))
if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n");
@ -1048,8 +1048,18 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
err = -EBUSY;
goto out;
/* mac80211 should not scan while ROC or ROC while scanning */
if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
err = -EBUSY;
goto out;
}
iwl_scan_cancel_timeout(priv, 100);
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
err = -EBUSY;
goto out;
}
}
priv->hw_roc_channel = channel;
@ -1413,13 +1423,11 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
}
static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p)
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_context *tmp;
struct iwl_rxon_context *ctx, *tmp;
enum nl80211_iftype newviftype = newtype;
u32 interface_modes;
int err;
@ -1430,6 +1438,18 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
ctx = iwl_rxon_ctx_from_vif(vif);
/*
* To simplify this code, only support changes on the
* BSS context. The PAN context is usually reassigned
* by creating/removing P2P interfaces anyway.
*/
if (ctx->ctxid != IWL_RXON_CTX_BSS) {
err = -EBUSY;
goto out;
}
if (!ctx->vif || !iwl_is_ready_rf(priv)) {
/*
* Huh? But wait ... this can maybe happen when
@ -1439,32 +1459,19 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
goto out;
}
/* Check if the switch is supported in the same context */
interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
if (!(interface_modes & BIT(newtype))) {
err = -EBUSY;
goto out;
}
/*
* Refuse a change that should be done by moving from the PAN
* context to the BSS context instead, if the BSS context is
* available and can support the new interface type.
*/
if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
(bss_ctx->interface_modes & BIT(newtype) ||
bss_ctx->exclusive_interface_modes & BIT(newtype))) {
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
err = -EBUSY;
goto out;
}
if (ctx->exclusive_interface_modes & BIT(newtype)) {
for_each_context(priv, tmp) {
if (ctx == tmp)
continue;
if (!tmp->vif)
if (!tmp->is_active)
continue;
/*

View File

@ -51,11 +51,13 @@
#include "iwl-op-mode.h"
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-prph.h"
#include "dev.h"
#include "calib.h"
#include "agn.h"
/******************************************************************************
*
* module boiler plate
@ -1185,9 +1187,6 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
priv->hw_params.use_rts_for_aggregation =
priv->cfg->ht_params->use_rts_for_aggregation;
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
priv->hw_params.sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
/* Device-specific setup */
priv->lib->set_hw_params(priv);
}
@ -1232,20 +1231,20 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
u16 radio_cfg;
priv->hw_params.sku = priv->eeprom_data->sku;
priv->eeprom_data->sku = priv->eeprom_data->sku;
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE &&
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
!priv->cfg->ht_params) {
IWL_ERR(priv, "Invalid 11n configuration\n");
return -EINVAL;
}
if (!priv->hw_params.sku) {
if (!priv->eeprom_data->sku) {
IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL;
}
IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku);
IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
radio_cfg = priv->eeprom_data->radio_cfg;
@ -1352,6 +1351,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
trans_cfg.command_names = iwl_dvm_cmd_strings;
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
priv->cfg->base_params->num_of_queues);
ucode_flags = fw->ucode_capa.flags;
#ifndef CONFIG_IWLWIFI_P2P
@ -1448,7 +1450,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
************************/
iwl_set_hw_params(priv);
if (!(priv->hw_params.sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
/*
@ -2073,7 +2075,16 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
priv->lib->nic_config(priv);
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
*/
iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
if (priv->lib->nic_config)
priv->lib->nic_config(priv);
}
static void iwl_wimax_active(struct iwl_op_mode *op_mode)

View File

@ -51,6 +51,9 @@
#define IWL_CHANNEL_TUNE_TIME 5
#define MAX_SCAN_CHANNEL 50
/* For reset radio, need minimal dwell time only */
#define IWL_RADIO_RESET_DWELL_TIME 5
static int iwl_send_scan_abort(struct iwl_priv *priv)
{
int ret;
@ -469,45 +472,39 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv,
return 0;
}
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
struct ieee80211_vif *vif,
enum ieee80211_band band,
struct iwl_scan_channel *scan_ch)
static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv,
struct ieee80211_vif *vif,
enum ieee80211_band band,
struct iwl_scan_channel *scan_ch)
{
const struct ieee80211_supported_band *sband;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added = 0;
u16 channel = 0;
u16 channel;
sband = iwl_get_hw_mode(priv, band);
if (!sband) {
IWL_ERR(priv, "invalid band\n");
return added;
return 0;
}
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
channel = iwl_get_single_channel_number(priv, band);
if (channel) {
scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
scan_ch->active_dwell =
cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
scan_ch->passive_dwell =
cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
added++;
} else
IWL_ERR(priv, "no valid channel found\n");
return added;
return 1;
}
IWL_ERR(priv, "no valid channel found\n");
return 0;
}
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
@ -723,6 +720,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
switch (priv->scan_type) {
case IWL_SCAN_RADIO_RESET:
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
/*
* Override quiet time as firmware checks that active
* dwell is >= quiet; since we use passive scan it'll
* not actually be used.
*/
scan->quiet_time = cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
break;
case IWL_SCAN_NORMAL:
if (priv->scan_request->n_ssids) {
@ -896,7 +899,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
switch (priv->scan_type) {
case IWL_SCAN_RADIO_RESET:
scan->channel_count =
iwl_get_single_channel_for_scan(priv, vif, band,
iwl_get_channel_for_reset_scan(priv, vif, band,
(void *)&scan->data[cmd_len]);
break;
case IWL_SCAN_NORMAL:

View File

@ -853,6 +853,9 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
EEPROM_RADIO_CONFIG);
data->sku = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_SKU_CAP);
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
data->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_VERSION);

View File

@ -121,13 +121,12 @@ EXPORT_SYMBOL_GPL(iwl_notification_wait_notify);
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
{
unsigned long flags;
struct iwl_notification_wait *wait_entry;
spin_lock_irqsave(&notif_wait->notif_wait_lock, flags);
spin_lock(&notif_wait->notif_wait_lock);
list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&notif_wait->notif_wait_lock, flags);
spin_unlock(&notif_wait->notif_wait_lock);
wake_up_all(&notif_wait->notif_waitq);
}

View File

@ -111,22 +111,25 @@ struct iwl_cfg;
* May sleep
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
* HCMD the this Rx responds to.
* Must be atomic.
* Must be atomic and called with BH disabled.
* @queue_full: notifies that a HW queue is full.
* Must be atomic
* Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more.
* Must be atomic
* Must be atomic and called with BH disabled.
* @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
* the radio is killed. Must be atomic.
* @free_skb: allows the transport layer to free skbs that haven't been
* reclaimed by the op_mode. This can happen when the driver is freed and
* there are Tx packets pending in the transport layer.
* Must be atomic
* @nic_error: error notification. Must be atomic
* @cmd_queue_full: Called when the command queue gets full. Must be atomic.
* @nic_error: error notification. Must be atomic and must be called with BH
* disabled.
* @cmd_queue_full: Called when the command queue gets full. Must be atomic and
* called with BH disabled.
* @nic_config: configure NIC, called before firmware is started.
* May sleep
* @wimax_active: invoked when WiMax becomes active. Must be atomic.
* @wimax_active: invoked when WiMax becomes active. Must be atomic and called
* with BH disabled.
*/
struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@ -165,7 +168,6 @@ struct iwl_op_mode {
static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
{
might_sleep();
op_mode->ops->stop(op_mode);
}

View File

@ -867,24 +867,23 @@ void iwl_disable_ict(struct iwl_trans *trans)
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
}
/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
static irqreturn_t iwl_isr(int irq, void *data)
{
struct iwl_trans *trans = data;
struct iwl_trans_pcie *trans_pcie;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 inta, inta_mask;
unsigned long flags;
#ifdef CONFIG_IWLWIFI_DEBUG
u32 inta_fh;
#endif
lockdep_assert_held(&trans_pcie->irq_lock);
if (!trans)
return IRQ_NONE;
trace_iwlwifi_dev_irq(trans->dev);
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
@ -907,7 +906,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* Hardware disappeared. It might have already raised
* an interrupt */
IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
return IRQ_HANDLED;
}
#ifdef CONFIG_IWLWIFI_DEBUG
@ -926,18 +925,13 @@ static irqreturn_t iwl_isr(int irq, void *data)
!trans_pcie->inta)
iwl_enable_interrupts(trans);
unplugged:
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
return IRQ_HANDLED;
none:
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if disabled by irq and no schedules tasklet. */
if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta)
iwl_enable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
return IRQ_NONE;
}
@ -963,15 +957,19 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
/* dram interrupt table not set yet,
* use legacy interrupt.
*/
if (!trans_pcie->use_ict)
return iwl_isr(irq, data);
if (unlikely(!trans_pcie->use_ict)) {
irqreturn_t ret = iwl_isr(irq, data);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
return ret;
}
trace_iwlwifi_dev_irq(trans->dev);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.

View File

@ -296,6 +296,7 @@ static void iwlagn_free_dma_ptr(struct iwl_trans *trans,
static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
{
struct iwl_tx_queue *txq = (void *)data;
struct iwl_queue *q = &txq->q;
struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
u32 scd_sram_addr = trans_pcie->scd_base_addr +
@ -346,6 +347,14 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
}
for (i = q->read_ptr; i != q->write_ptr;
i = iwl_queue_inc_wrap(i, q->n_bd)) {
struct iwl_tx_cmd *tx_cmd =
(struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
get_unaligned_le32(&tx_cmd->scratch));
}
iwl_op_mode_nic_error(trans->op_mode);
}
@ -1037,15 +1046,12 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
/*
* Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under the irq lock and with MAC access
*/
static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
{
struct iwl_trans_pcie __maybe_unused *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
lockdep_assert_held(&trans_pcie->irq_lock);
iwl_write_prph(trans, SCD_TXFACT, mask);
}
@ -1053,12 +1059,9 @@ static void iwl_tx_start(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 a;
unsigned long flags;
int i, chan;
u32 reg_val;
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
/* make sure all queue are not stopped/used */
memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
@ -1109,8 +1112,6 @@ static void iwl_tx_start(struct iwl_trans *trans)
iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG,
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
/* Enable L1-Active */
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
@ -2017,7 +2018,9 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
if (!trans->op_mode)
return -EAGAIN;
local_bh_disable();
iwl_op_mode_nic_error(trans->op_mode);
local_bh_enable();
return count;
}

View File

@ -678,8 +678,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
continue;
if (data2->idle || !data2->started ||
!hwsim_ps_rx_ok(data2, skb) ||
!data->channel || !data2->channel ||
!hwsim_ps_rx_ok(data2, skb) || !data2->channel ||
data->channel->center_freq != data2->channel->center_freq ||
!(data->group & data2->group))
continue;
@ -1486,7 +1485,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
struct mac80211_hwsim_data *data2;
struct ieee80211_tx_info *txi;
struct hwsim_tx_rate *tx_attempts;
struct sk_buff __user *ret_skb;
unsigned long ret_skb_ptr;
struct sk_buff *skb, *tmp;
struct mac_address *src;
unsigned int hwsim_flags;
@ -1504,8 +1503,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
ret_skb = (struct sk_buff __user *)
(unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
ret_skb_ptr = nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
data2 = get_hwsim_data_ref_from_addr(src);
@ -1514,7 +1512,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
/* look for the skb matching the cookie passed back from user */
skb_queue_walk_safe(&data2->pending, skb, tmp) {
if (skb == ret_skb) {
if ((unsigned long)skb == ret_skb_ptr) {
skb_unlink(skb, &data2->pending);
found = true;
break;

View File

@ -170,7 +170,9 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
if (!priv->sec_info.wep_enabled)
return 0;
if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
priv->wep_key_curr_index = key_index;
} else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
wiphy_err(wiphy, "set default Tx key index\n");
return -EFAULT;
}
@ -187,9 +189,25 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
struct key_params *params)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
struct mwifiex_wep_key *wep_key;
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
(params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
if (params->key && params->key_len) {
wep_key = &priv->wep_key[key_index];
memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
memcpy(wep_key->key_material, params->key,
params->key_len);
wep_key->key_index = key_index;
wep_key->key_length = params->key_len;
priv->sec_info.wep_enabled = 1;
}
return 0;
}
if (mwifiex_set_encode(priv, params->key, params->key_len,
key_index, peer_mac, 0)) {
wiphy_err(wiphy, "crypto keys added\n");
@ -242,13 +260,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
flag = 1;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
max_pwr = ch->max_power;
max_pwr = ch->max_reg_power;
no_of_parsed_chan = 1;
continue;
}
if (ch->hw_value == next_chan + 1 &&
ch->max_power == max_pwr) {
ch->max_reg_power == max_pwr) {
next_chan++;
no_of_parsed_chan++;
} else {
@ -259,7 +277,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
no_of_triplet++;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
max_pwr = ch->max_power;
max_pwr = ch->max_reg_power;
no_of_parsed_chan = 1;
}
}
@ -384,13 +402,13 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
cfp.freq = chan->center_freq;
cfp.channel = ieee80211_frequency_to_channel(chan->center_freq);
if (mwifiex_bss_set_channel(priv, &cfp))
return -EFAULT;
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
if (mwifiex_bss_set_channel(priv, &cfp))
return -EFAULT;
return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
else
return mwifiex_uap_set_channel(priv, cfp.channel);
}
return 0;
}
/*
@ -961,12 +979,25 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
return -EINVAL;
}
bss_cfg->channel =
(u8)ieee80211_frequency_to_channel(params->channel->center_freq);
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
if (mwifiex_set_rf_channel(priv, params->channel,
params->channel_type)) {
kfree(bss_cfg);
wiphy_err(wiphy, "Failed to set band config information!\n");
return -1;
}
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
kfree(bss_cfg);
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
return -1;
}
mwifiex_set_ht_params(priv, bss_cfg, params);
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
HostCmd_ACT_GEN_SET, 0, NULL)) {
wiphy_err(wiphy, "Failed to stop the BSS\n");
@ -990,6 +1021,16 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
return -1;
}
if (priv->sec_info.wep_enabled)
priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
else
priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL,
HostCmd_ACT_GEN_SET, 0,
&priv->curr_pkt_filter))
return -1;
return 0;
}
@ -1381,7 +1422,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
priv->user_scan_cfg->chan_list[i].scan_time = 0;
}
if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg))
if (mwifiex_scan_networks(priv, priv->user_scan_cfg))
return -EFAULT;
if (request->ie && request->ie_len) {
@ -1702,7 +1743,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY;
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);

View File

@ -578,6 +578,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
} else {
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
queue_work(adapter->workqueue, &adapter->main_work);
}
return ret;
@ -1102,7 +1103,8 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
&resp->params.opt_hs_cfg;
uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) {
if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
adapter->iface_type == MWIFIEX_SDIO) {
mwifiex_hs_activated_event(priv, true);
return 0;
} else {
@ -1114,6 +1116,9 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
}
if (conditions != HOST_SLEEP_CFG_CANCEL) {
adapter->is_hs_configured = true;
if (adapter->iface_type == MWIFIEX_USB ||
adapter->iface_type == MWIFIEX_PCIE)
mwifiex_hs_activated_event(priv, true);
} else {
adapter->is_hs_configured = false;
if (adapter->hs_activated)

View File

@ -124,6 +124,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48)
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59)
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65)
@ -162,6 +163,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
IEEE80211_HT_CAP_SM_PS)
#define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR
/* dev_cap bitmap
* BIT
* 0-16 reserved
@ -219,6 +226,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_RF_REG_ACCESS 0x001b
#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad
#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
#define HostCmd_CMD_RF_TX_PWR 0x001e
#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
#define HostCmd_CMD_MAC_CONTROL 0x0028
#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
@ -869,6 +877,13 @@ struct host_cmd_ds_txpwr_cfg {
__le32 mode;
} __packed;
struct host_cmd_ds_rf_tx_pwr {
__le16 action;
__le16 cur_level;
u8 max_power;
u8 min_power;
} __packed;
struct mwifiex_bcn_param {
u8 bssid[ETH_ALEN];
u8 rssi;
@ -1195,6 +1210,13 @@ struct host_cmd_tlv_passphrase {
u8 passphrase[0];
} __packed;
struct host_cmd_tlv_wep_key {
struct host_cmd_tlv tlv;
u8 key_index;
u8 is_default;
u8 key[1];
};
struct host_cmd_tlv_auth_type {
struct host_cmd_tlv tlv;
u8 auth_type;
@ -1347,6 +1369,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_tx_rate_query tx_rate;
struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
struct host_cmd_ds_txpwr_cfg txp_cfg;
struct host_cmd_ds_rf_tx_pwr txp;
struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
struct host_cmd_ds_802_11_scan scan;

View File

@ -225,29 +225,46 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
struct cfg80211_ap_settings *params)
{
struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
struct ieee_types_header *ie = NULL;
struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL;
struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK;
u16 mask;
u16 mask, ie_len = 0;
const u8 *vendor_ie;
int ret = 0;
if (params->beacon.tail && params->beacon.tail_len) {
ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail,
params->beacon.tail_len);
if (ie) {
rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!rsn_ie)
return -ENOMEM;
gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!gen_ie)
return -ENOMEM;
gen_ie->ie_index = cpu_to_le16(rsn_idx);
mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP |
MGMT_MASK_ASSOC_RESP;
gen_ie->mgmt_subtype_mask = cpu_to_le16(mask);
rsn_ie->ie_index = cpu_to_le16(rsn_idx);
mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP |
MGMT_MASK_ASSOC_RESP;
rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask);
rsn_ie->ie_length = cpu_to_le16(ie->len + 2);
memcpy(rsn_ie->ie_buffer, ie, ie->len + 2);
rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
params->beacon.tail,
params->beacon.tail_len);
if (rsn_ie) {
memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
ie_len = rsn_ie->len + 2;
gen_ie->ie_length = cpu_to_le16(ie_len);
}
if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx,
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WPA,
params->beacon.tail,
params->beacon.tail_len);
if (vendor_ie) {
wpa_ie = (struct ieee_types_header *)vendor_ie;
memcpy(gen_ie->ie_buffer + ie_len,
wpa_ie, wpa_ie->len + 2);
ie_len += wpa_ie->len + 2;
gen_ie->ie_length = cpu_to_le16(ie_len);
}
if (rsn_ie || wpa_ie) {
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx,
NULL, NULL,
NULL, NULL)) {
ret = -1;
@ -320,7 +337,7 @@ done:
kfree(beacon_ie);
kfree(pr_ie);
kfree(ar_ie);
kfree(rsn_ie);
kfree(gen_ie);
return ret;
}

View File

@ -103,6 +103,7 @@ static void scan_delay_timer_fn(unsigned long data)
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
adapter->scan_delay_cnt++;
}
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
} else {
/*
* Tx data queue is empty. Get scan command from scan_pending_q

View File

@ -21,6 +21,7 @@
#define _MWIFIEX_IOCTL_H_
#include <net/mac80211.h>
#include <net/lib80211.h>
enum {
MWIFIEX_SCAN_TYPE_UNCHANGED = 0,
@ -71,6 +72,13 @@ struct wpa_param {
u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN];
};
struct wep_key {
u8 key_index;
u8 is_default;
u16 length;
u8 key[WLAN_KEY_LEN_WEP104];
};
#define KEY_MGMT_ON_HOST 0x03
#define MWIFIEX_AUTH_MODE_AUTO 0xFF
#define BAND_CONFIG_MANUAL 0x00
@ -90,6 +98,8 @@ struct mwifiex_uap_bss_param {
u16 key_mgmt;
u16 key_mgmt_operation;
struct wpa_param wpa_cfg;
struct wep_key wep_cfg[NUM_WEP_KEYS];
struct ieee80211_ht_cap ht_cap;
};
enum {

View File

@ -190,7 +190,8 @@ process_start:
adapter->tx_lock_flag)
break;
if (adapter->scan_processing || adapter->data_sent ||
if ((adapter->scan_processing &&
!adapter->scan_delay_cnt) || adapter->data_sent ||
mwifiex_wmm_lists_empty(adapter)) {
if (adapter->cmd_sent || adapter->curr_cmd ||
(!is_command_pending(adapter)))

View File

@ -840,6 +840,9 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
int mwifiex_set_secure_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_config,
struct cfg80211_ap_settings *params);
void mwifiex_set_ht_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
/*
* This function checks if the queuing is RA based or not.
@ -946,8 +949,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct cfg80211_ssid *req_ssid);
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
struct mwifiex_user_scan_cfg *scan_req);
int mwifiex_scan_networks(struct mwifiex_private *priv,
const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
@ -990,7 +993,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
int mwifiex_main_process(struct mwifiex_adapter *);
int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
int mwifiex_get_bss_info(struct mwifiex_private *,

View File

@ -1294,8 +1294,8 @@ mwifiex_radio_type_to_band(u8 radio_type)
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table.
*/
static int mwifiex_scan_networks(struct mwifiex_private *priv,
const struct mwifiex_user_scan_cfg *user_scan_in)
int mwifiex_scan_networks(struct mwifiex_private *priv,
const struct mwifiex_user_scan_cfg *user_scan_in)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@ -1360,6 +1360,7 @@ static int mwifiex_scan_networks(struct mwifiex_private *priv,
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
queue_work(adapter->workqueue, &adapter->main_work);
} else {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
@ -1375,26 +1376,6 @@ static int mwifiex_scan_networks(struct mwifiex_private *priv,
return ret;
}
/*
* Sends IOCTL request to start a scan with user configurations.
*
* This function allocates the IOCTL request buffer, fills it
* with requisite parameters and calls the IOCTL handler.
*
* Upon completion, it also generates a wireless event to notify
* applications.
*/
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
struct mwifiex_user_scan_cfg *scan_req)
{
int status;
status = mwifiex_scan_networks(priv, scan_req);
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
return status;
}
/*
* This function prepares a scan command to be sent to the firmware.
*

View File

@ -259,6 +259,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
return 0;
}
/*
* This function prepares command to get RF Tx power.
*/
static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, void *data_buf)
{
struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
+ S_DS_GEN);
cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR);
txp->action = cpu_to_le16(cmd_action);
return 0;
}
/*
* This function prepares command to set Host Sleep configuration.
*
@ -1049,6 +1066,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,
data_buf);
break;
case HostCmd_CMD_RF_TX_PWR:
ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
data_buf);
break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
(uint16_t)cmd_oid, data_buf);
@ -1277,7 +1298,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
priv->data_rate = 0;
/* get tx power */
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG,
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_RF_TX_PWR,
HostCmd_ACT_GEN_GET, 0, NULL);
if (ret)
return -1;

View File

@ -450,6 +450,30 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
return 0;
}
/*
* This function handles the command response of get RF Tx power.
*/
static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp)
{
struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
u16 action = le16_to_cpu(txp->action);
priv->tx_power_level = le16_to_cpu(txp->cur_level);
if (action == HostCmd_ACT_GEN_GET) {
priv->max_tx_power_level = txp->max_power;
priv->min_tx_power_level = txp->min_power;
}
dev_dbg(priv->adapter->dev,
"Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
priv->tx_power_level, priv->max_tx_power_level,
priv->min_tx_power_level);
return 0;
}
/*
* This function handles the command response of set/get MAC address.
*
@ -841,6 +865,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_TXPWR_CFG:
ret = mwifiex_ret_tx_power_cfg(priv, resp);
break;
case HostCmd_CMD_RF_TX_PWR:
ret = mwifiex_ret_rf_tx_power(priv, resp);
break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
break;

View File

@ -66,9 +66,6 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
dev_dbg(adapter->dev, "cmd pending\n");
atomic_inc(&adapter->cmd_pending);
/* Status pending, wake up main process */
queue_work(adapter->workqueue, &adapter->main_work);
/* Wait for completion */
wait_event_interruptible(adapter->cmd_wait_q.wait,
*(cmd_queued->condition));

View File

@ -26,6 +26,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_config,
struct cfg80211_ap_settings *params) {
int i;
struct mwifiex_wep_key wep_key;
if (!params->privacy) {
bss_config->protocol = PROTOCOL_NO_SECURITY;
@ -65,7 +66,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
}
if (params->crypto.wpa_versions &
NL80211_WPA_VERSION_2) {
bss_config->protocol = PROTOCOL_WPA2;
bss_config->protocol |= PROTOCOL_WPA2;
bss_config->key_mgmt = KEY_MGMT_EAP;
}
break;
@ -77,7 +78,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
}
if (params->crypto.wpa_versions &
NL80211_WPA_VERSION_2) {
bss_config->protocol = PROTOCOL_WPA2;
bss_config->protocol |= PROTOCOL_WPA2;
bss_config->key_mgmt = KEY_MGMT_PSK;
}
break;
@ -91,10 +92,19 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
case WLAN_CIPHER_SUITE_WEP104:
break;
case WLAN_CIPHER_SUITE_TKIP:
bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP;
if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
bss_config->wpa_cfg.pairwise_cipher_wpa |=
CIPHER_TKIP;
if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
CIPHER_TKIP;
break;
case WLAN_CIPHER_SUITE_CCMP:
bss_config->wpa_cfg.pairwise_cipher_wpa2 =
if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
bss_config->wpa_cfg.pairwise_cipher_wpa |=
CIPHER_AES_CCMP;
if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
CIPHER_AES_CCMP;
default:
break;
@ -104,6 +114,27 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
switch (params->crypto.cipher_group) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
if (priv->sec_info.wep_enabled) {
bss_config->protocol = PROTOCOL_STATIC_WEP;
bss_config->key_mgmt = KEY_MGMT_NONE;
bss_config->wpa_cfg.length = 0;
for (i = 0; i < NUM_WEP_KEYS; i++) {
wep_key = priv->wep_key[i];
bss_config->wep_cfg[i].key_index = i;
if (priv->wep_key_curr_index == i)
bss_config->wep_cfg[i].is_default = 1;
else
bss_config->wep_cfg[i].is_default = 0;
bss_config->wep_cfg[i].length =
wep_key.key_length;
memcpy(&bss_config->wep_cfg[i].key,
&wep_key.key_material,
wep_key.key_length);
}
}
break;
case WLAN_CIPHER_SUITE_TKIP:
bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
@ -118,6 +149,33 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
return 0;
}
/* This function updates 11n related parameters from IE and sets them into
* bss_config structure.
*/
void
mwifiex_set_ht_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params)
{
const u8 *ht_ie;
if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
return;
ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
params->beacon.tail_len);
if (ht_ie) {
memcpy(&bss_cfg->ht_cap, ht_ie + 2,
sizeof(struct ieee80211_ht_cap));
} else {
memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
}
return;
}
/* This function initializes some of mwifiex_uap_bss_param variables.
* This helps FW in ignoring invalid values. These values may or may not
* be get updated to valid ones at later stage.
@ -134,6 +192,120 @@ void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
config->retry_limit = 0x7F;
}
/* This function parses BSS related parameters from structure
* and prepares TLVs specific to WPA/WPA2 security.
* These TLVs are appended to command buffer.
*/
static void
mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
{
struct host_cmd_tlv_pwk_cipher *pwk_cipher;
struct host_cmd_tlv_gwk_cipher *gwk_cipher;
struct host_cmd_tlv_passphrase *passphrase;
struct host_cmd_tlv_akmp *tlv_akmp;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
u16 cmd_size = *param_size;
u8 *tlv = *tlv_buf;
tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
tlv_akmp->tlv.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
sizeof(struct host_cmd_tlv));
tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
cmd_size += sizeof(struct host_cmd_tlv_akmp);
tlv += sizeof(struct host_cmd_tlv_akmp);
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
pwk_cipher->tlv.len =
cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
sizeof(struct host_cmd_tlv));
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
}
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
pwk_cipher->tlv.len =
cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
sizeof(struct host_cmd_tlv));
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
}
if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
gwk_cipher->tlv.len =
cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
sizeof(struct host_cmd_tlv));
gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
}
if (bss_cfg->wpa_cfg.length) {
passphrase = (struct host_cmd_tlv_passphrase *)tlv;
passphrase->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
passphrase->tlv.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
bss_cfg->wpa_cfg.length);
cmd_size += sizeof(struct host_cmd_tlv) +
bss_cfg->wpa_cfg.length;
tlv += sizeof(struct host_cmd_tlv) + bss_cfg->wpa_cfg.length;
}
*param_size = cmd_size;
*tlv_buf = tlv;
return;
}
/* This function parses BSS related parameters from structure
* and prepares TLVs specific to WEP encryption.
* These TLVs are appended to command buffer.
*/
static void
mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
{
struct host_cmd_tlv_wep_key *wep_key;
u16 cmd_size = *param_size;
int i;
u8 *tlv = *tlv_buf;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (bss_cfg->wep_cfg[i].length &&
(bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
wep_key = (struct host_cmd_tlv_wep_key *)tlv;
wep_key->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
wep_key->tlv.len =
cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
bss_cfg->wep_cfg[i].length);
cmd_size += sizeof(struct host_cmd_tlv) + 2 +
bss_cfg->wep_cfg[i].length;
tlv += sizeof(struct host_cmd_tlv) + 2 +
bss_cfg->wep_cfg[i].length;
}
}
*param_size = cmd_size;
*tlv_buf = tlv;
return;
}
/* This function parses BSS related parameters from structure
* and prepares TLVs. These TLVs are appended to command buffer.
*/
@ -148,12 +320,9 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
struct host_cmd_tlv_frag_threshold *frag_threshold;
struct host_cmd_tlv_rts_threshold *rts_threshold;
struct host_cmd_tlv_retry_limit *retry_limit;
struct host_cmd_tlv_pwk_cipher *pwk_cipher;
struct host_cmd_tlv_gwk_cipher *gwk_cipher;
struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
struct host_cmd_tlv_auth_type *auth_type;
struct host_cmd_tlv_passphrase *passphrase;
struct host_cmd_tlv_akmp *tlv_akmp;
struct mwifiex_ie_types_htcap *htcap;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
u16 cmd_size = *param_size;
@ -243,70 +412,11 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
}
if ((bss_cfg->protocol & PROTOCOL_WPA) ||
(bss_cfg->protocol & PROTOCOL_WPA2) ||
(bss_cfg->protocol & PROTOCOL_EAP)) {
tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
tlv_akmp->tlv.len =
cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
sizeof(struct host_cmd_tlv));
tlv_akmp->key_mgmt_operation =
cpu_to_le16(bss_cfg->key_mgmt_operation);
tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
cmd_size += sizeof(struct host_cmd_tlv_akmp);
tlv += sizeof(struct host_cmd_tlv_akmp);
(bss_cfg->protocol & PROTOCOL_EAP))
mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
else
mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa &
VALID_CIPHER_BITMAP) {
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
pwk_cipher->tlv.type =
cpu_to_le16(TLV_TYPE_PWK_CIPHER);
pwk_cipher->tlv.len = cpu_to_le16(
sizeof(struct host_cmd_tlv_pwk_cipher) -
sizeof(struct host_cmd_tlv));
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
pwk_cipher->cipher =
bss_cfg->wpa_cfg.pairwise_cipher_wpa;
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
}
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 &
VALID_CIPHER_BITMAP) {
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
pwk_cipher->tlv.len = cpu_to_le16(
sizeof(struct host_cmd_tlv_pwk_cipher) -
sizeof(struct host_cmd_tlv));
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
pwk_cipher->cipher =
bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
}
if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
gwk_cipher->tlv.len = cpu_to_le16(
sizeof(struct host_cmd_tlv_gwk_cipher) -
sizeof(struct host_cmd_tlv));
gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
}
if (bss_cfg->wpa_cfg.length) {
passphrase = (struct host_cmd_tlv_passphrase *)tlv;
passphrase->tlv.type =
cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
passphrase->tlv.len =
cpu_to_le16(bss_cfg->wpa_cfg.length);
memcpy(passphrase->passphrase,
bss_cfg->wpa_cfg.passphrase,
bss_cfg->wpa_cfg.length);
cmd_size += sizeof(struct host_cmd_tlv) +
bss_cfg->wpa_cfg.length;
tlv += sizeof(struct host_cmd_tlv) +
bss_cfg->wpa_cfg.length;
}
}
if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
(bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
auth_type = (struct host_cmd_tlv_auth_type *)tlv;
@ -330,6 +440,25 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
}
if (bss_cfg->ht_cap.cap_info) {
htcap = (struct mwifiex_ie_types_htcap *)tlv;
htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
htcap->header.len =
cpu_to_le16(sizeof(struct ieee80211_ht_cap));
htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
htcap->ht_cap.ampdu_params_info =
bss_cfg->ht_cap.ampdu_params_info;
memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
sizeof(struct ieee80211_mcs_info));
htcap->ht_cap.extended_ht_cap_info =
bss_cfg->ht_cap.extended_ht_cap_info;
htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
htcap->ht_cap.antenna_selection_info =
bss_cfg->ht_cap.antenna_selection_info;
cmd_size += sizeof(struct mwifiex_ie_types_htcap);
tlv += sizeof(struct mwifiex_ie_types_htcap);
}
*param_size = cmd_size;
return 0;
@ -421,33 +550,3 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
return 0;
}
/* This function sets the RF channel for AP.
*
* This function populates channel information in AP config structure
* and sends command to configure channel information in AP.
*/
int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel)
{
struct mwifiex_uap_bss_param *bss_cfg;
struct wiphy *wiphy = priv->wdev->wiphy;
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
if (!bss_cfg)
return -ENOMEM;
mwifiex_set_sys_config_invalid_data(bss_cfg);
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
bss_cfg->channel = channel;
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
HostCmd_ACT_GEN_SET,
UAP_BSS_PARAMS_I, bss_cfg)) {
wiphy_err(wiphy, "Failed to set the uAP channel\n");
kfree(bss_cfg);
return -1;
}
kfree(bss_cfg);
return 0;
}

View File

@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
rt2800pci driver.
Supported chips: RT5390
config RT2800PCI_RT3290
bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
default y
---help---
This adds support for rt3290 wireless chipset family to the
rt2800pci driver.
Supported chips: RT3290
endif
config RT2500USB

View File

@ -68,6 +68,7 @@
#define RF3320 0x000b
#define RF3322 0x000c
#define RF3053 0x000d
#define RF3290 0x3290
#define RF5360 0x5360
#define RF5370 0x5370
#define RF5372 0x5372
@ -117,6 +118,12 @@
* Registers.
*/
/*
* MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number.
*/
#define MAC_CSR0_3290 0x0000
/*
* E2PROM_CSR: PCI EEPROM control register.
* RELOAD: Write 1 to reload eeprom content.
@ -132,6 +139,150 @@
#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040)
#define E2PROM_CSR_RELOAD FIELD32(0x00000080)
/*
* CMB_CTRL_CFG
*/
#define CMB_CTRL 0x0020
#define AUX_OPT_BIT0 FIELD32(0x00000001)
#define AUX_OPT_BIT1 FIELD32(0x00000002)
#define AUX_OPT_BIT2 FIELD32(0x00000004)
#define AUX_OPT_BIT3 FIELD32(0x00000008)
#define AUX_OPT_BIT4 FIELD32(0x00000010)
#define AUX_OPT_BIT5 FIELD32(0x00000020)
#define AUX_OPT_BIT6 FIELD32(0x00000040)
#define AUX_OPT_BIT7 FIELD32(0x00000080)
#define AUX_OPT_BIT8 FIELD32(0x00000100)
#define AUX_OPT_BIT9 FIELD32(0x00000200)
#define AUX_OPT_BIT10 FIELD32(0x00000400)
#define AUX_OPT_BIT11 FIELD32(0x00000800)
#define AUX_OPT_BIT12 FIELD32(0x00001000)
#define AUX_OPT_BIT13 FIELD32(0x00002000)
#define AUX_OPT_BIT14 FIELD32(0x00004000)
#define AUX_OPT_BIT15 FIELD32(0x00008000)
#define LDO25_LEVEL FIELD32(0x00030000)
#define LDO25_LARGEA FIELD32(0x00040000)
#define LDO25_FRC_ON FIELD32(0x00080000)
#define CMB_RSV FIELD32(0x00300000)
#define XTAL_RDY FIELD32(0x00400000)
#define PLL_LD FIELD32(0x00800000)
#define LDO_CORE_LEVEL FIELD32(0x0F000000)
#define LDO_BGSEL FIELD32(0x30000000)
#define LDO3_EN FIELD32(0x40000000)
#define LDO0_EN FIELD32(0x80000000)
/*
* EFUSE_CSR_3290: RT3290 EEPROM
*/
#define EFUSE_CTRL_3290 0x0024
/*
* EFUSE_DATA3 of 3290
*/
#define EFUSE_DATA3_3290 0x0028
/*
* EFUSE_DATA2 of 3290
*/
#define EFUSE_DATA2_3290 0x002c
/*
* EFUSE_DATA1 of 3290
*/
#define EFUSE_DATA1_3290 0x0030
/*
* EFUSE_DATA0 of 3290
*/
#define EFUSE_DATA0_3290 0x0034
/*
* OSC_CTRL_CFG
* Ring oscillator configuration
*/
#define OSC_CTRL 0x0038
#define OSC_REF_CYCLE FIELD32(0x00001fff)
#define OSC_RSV FIELD32(0x0000e000)
#define OSC_CAL_CNT FIELD32(0x0fff0000)
#define OSC_CAL_ACK FIELD32(0x10000000)
#define OSC_CLK_32K_VLD FIELD32(0x20000000)
#define OSC_CAL_REQ FIELD32(0x40000000)
#define OSC_ROSC_EN FIELD32(0x80000000)
/*
* COEX_CFG_0
*/
#define COEX_CFG0 0x0040
#define COEX_CFG_ANT FIELD32(0xff000000)
/*
* COEX_CFG_1
*/
#define COEX_CFG1 0x0044
/*
* COEX_CFG_2
*/
#define COEX_CFG2 0x0048
#define BT_COEX_CFG1 FIELD32(0xff000000)
#define BT_COEX_CFG0 FIELD32(0x00ff0000)
#define WL_COEX_CFG1 FIELD32(0x0000ff00)
#define WL_COEX_CFG0 FIELD32(0x000000ff)
/*
* PLL_CTRL_CFG
* PLL configuration register
*/
#define PLL_CTRL 0x0050
#define PLL_RESERVED_INPUT1 FIELD32(0x000000ff)
#define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00)
#define PLL_CONTROL FIELD32(0x00070000)
#define PLL_LPF_R1 FIELD32(0x00080000)
#define PLL_LPF_C1_CTRL FIELD32(0x00300000)
#define PLL_LPF_C2_CTRL FIELD32(0x00c00000)
#define PLL_CP_CURRENT_CTRL FIELD32(0x03000000)
#define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000)
#define PLL_LOCK_CTRL FIELD32(0x70000000)
#define PLL_VBGBK_EN FIELD32(0x80000000)
/*
* WLAN_CTRL_CFG
* RT3290 wlan configuration
*/
#define WLAN_FUN_CTRL 0x0080
#define WLAN_EN FIELD32(0x00000001)
#define WLAN_CLK_EN FIELD32(0x00000002)
#define WLAN_RSV1 FIELD32(0x00000004)
#define WLAN_RESET FIELD32(0x00000008)
#define PCIE_APP0_CLK_REQ FIELD32(0x00000010)
#define FRC_WL_ANT_SET FIELD32(0x00000020)
#define INV_TR_SW0 FIELD32(0x00000040)
#define WLAN_GPIO_IN_BIT0 FIELD32(0x00000100)
#define WLAN_GPIO_IN_BIT1 FIELD32(0x00000200)
#define WLAN_GPIO_IN_BIT2 FIELD32(0x00000400)
#define WLAN_GPIO_IN_BIT3 FIELD32(0x00000800)
#define WLAN_GPIO_IN_BIT4 FIELD32(0x00001000)
#define WLAN_GPIO_IN_BIT5 FIELD32(0x00002000)
#define WLAN_GPIO_IN_BIT6 FIELD32(0x00004000)
#define WLAN_GPIO_IN_BIT7 FIELD32(0x00008000)
#define WLAN_GPIO_IN_BIT_ALL FIELD32(0x0000ff00)
#define WLAN_GPIO_OUT_BIT0 FIELD32(0x00010000)
#define WLAN_GPIO_OUT_BIT1 FIELD32(0x00020000)
#define WLAN_GPIO_OUT_BIT2 FIELD32(0x00040000)
#define WLAN_GPIO_OUT_BIT3 FIELD32(0x00050000)
#define WLAN_GPIO_OUT_BIT4 FIELD32(0x00100000)
#define WLAN_GPIO_OUT_BIT5 FIELD32(0x00200000)
#define WLAN_GPIO_OUT_BIT6 FIELD32(0x00400000)
#define WLAN_GPIO_OUT_BIT7 FIELD32(0x00800000)
#define WLAN_GPIO_OUT_BIT_ALL FIELD32(0x00ff0000)
#define WLAN_GPIO_OUT_OE_BIT0 FIELD32(0x01000000)
#define WLAN_GPIO_OUT_OE_BIT1 FIELD32(0x02000000)
#define WLAN_GPIO_OUT_OE_BIT2 FIELD32(0x04000000)
#define WLAN_GPIO_OUT_OE_BIT3 FIELD32(0x08000000)
#define WLAN_GPIO_OUT_OE_BIT4 FIELD32(0x10000000)
#define WLAN_GPIO_OUT_OE_BIT5 FIELD32(0x20000000)
#define WLAN_GPIO_OUT_OE_BIT6 FIELD32(0x40000000)
#define WLAN_GPIO_OUT_OE_BIT7 FIELD32(0x80000000)
#define WLAN_GPIO_OUT_OE_BIT_ALL FIELD32(0xff000000)
/*
* AUX_CTRL: Aux/PCI-E related configuration
*/
@ -1763,9 +1914,11 @@ struct mac_iveiv_entry {
/*
* BBP 3: RX Antenna
*/
#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ANTENNA FIELD8(0x18)
#define BBP3_HT40_MINUS FIELD8(0x20)
#define BBP3_ADC_MODE_SWITCH FIELD8(0x40)
#define BBP3_ADC_INIT_MODE FIELD8(0x80)
/*
* BBP 4: Bandwidth
@ -1774,6 +1927,14 @@ struct mac_iveiv_entry {
#define BBP4_BANDWIDTH FIELD8(0x18)
#define BBP4_MAC_IF_CTRL FIELD8(0x40)
/*
* BBP 47: Bandwidth
*/
#define BBP47_TSSI_REPORT_SEL FIELD8(0x03)
#define BBP47_TSSI_UPDATE_REQ FIELD8(0x04)
#define BBP47_TSSI_TSSI_MODE FIELD8(0x18)
#define BBP47_TSSI_ADC6 FIELD8(0x80)
/*
* BBP 109
*/
@ -1916,6 +2077,16 @@ struct mac_iveiv_entry {
#define RFCSR27_R3 FIELD8(0x30)
#define RFCSR27_R4 FIELD8(0x40)
/*
* RFCSR 29:
*/
#define RFCSR29_ADC6_TEST FIELD8(0x01)
#define RFCSR29_ADC6_INT_TEST FIELD8(0x02)
#define RFCSR29_RSSI_RESET FIELD8(0x04)
#define RFCSR29_RSSI_ON FIELD8(0x08)
#define RFCSR29_RSSI_RIP_CTRL FIELD8(0x30)
#define RFCSR29_RSSI_GAIN FIELD8(0xc0)
/*
* RFCSR 30:
*/

View File

@ -354,16 +354,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
* of 4kb. Certain USB chipsets however require different firmware,
* which Ralink only provides attached to the original firmware
* file. Thus for USB devices, firmware files have a length
* which is a multiple of 4kb.
* which is a multiple of 4kb. The firmware for rt3290 chip also
* have a length which is a multiple of 4kb.
*/
if (rt2x00_is_usb(rt2x00dev)) {
if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))
fw_len = 4096;
multiple = true;
} else {
else
fw_len = 8192;
multiple = true;
}
multiple = true;
/*
* Validate the firmware length
*/
@ -415,7 +414,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
return -EBUSY;
if (rt2x00_is_pci(rt2x00dev)) {
if (rt2x00_rt(rt2x00dev, RT3572) ||
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
@ -851,8 +851,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
} else {
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
}
}
EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
@ -1935,9 +1940,54 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
#define RT3290_POWER_BOUND 0x27
#define RT3290_FREQ_OFFSET_BOUND 0x5f
#define RT5390_POWER_BOUND 0x27
#define RT5390_FREQ_OFFSET_BOUND 0x5f
static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
struct channel_info *info)
{
u8 rfcsr;
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
if (info->default_power1 > RT3290_POWER_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
RT3290_FREQ_OFFSET_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
if (rf->channel <= 14) {
if (rf->channel == 6)
rt2800_bbp_write(rt2x00dev, 68, 0x0c);
else
rt2800_bbp_write(rt2x00dev, 68, 0x0b);
if (rf->channel >= 1 && rf->channel <= 6)
rt2800_bbp_write(rt2x00dev, 59, 0x0f);
else if (rf->channel >= 7 && rf->channel <= 11)
rt2800_bbp_write(rt2x00dev, 59, 0x0e);
else if (rf->channel >= 12 && rf->channel <= 14)
rt2800_bbp_write(rt2x00dev, 59, 0x0d);
}
}
static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@ -2036,15 +2086,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
}
}
}
rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
@ -2054,7 +2095,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
unsigned int tx_pin;
u8 bbp;
u8 bbp, rfcsr;
if (rf->channel <= 14) {
info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
@ -2075,6 +2116,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
case RF3052:
rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
break;
case RF3290:
rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
break;
case RF5360:
case RF5370:
case RF5372:
@ -2086,6 +2130,22 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
}
if (rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) ||
rt2x00_rf(rt2x00dev, RF5390) ||
rt2x00_rf(rt2x00dev, RF5392)) {
rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}
/*
* Change BBP settings
*/
@ -2566,6 +2626,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
break;
case RF3290:
case RF5360:
case RF5370:
case RF5372:
@ -2701,6 +2762,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3390) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
@ -2797,10 +2859,54 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
}
rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
rt2x00_set_field32(&reg, LDO0_EN, 1);
rt2x00_set_field32(&reg, LDO_BGSEL, 3);
rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
}
rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
rt2x00_set_field32(&reg, PLL_CONTROL, 1);
rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
}
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3390)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_register_write(rt2x00dev, TX_SW_CFG0,
0x00000404);
else
rt2800_register_write(rt2x00dev, TX_SW_CFG0,
0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
@ -3209,14 +3315,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_wait_bbp_ready(rt2x00dev)))
return -EACCES;
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_bbp_read(rt2x00dev, 4, &value);
rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
rt2800_bbp_write(rt2x00dev, 4, value);
}
if (rt2800_is_305x_soc(rt2x00dev) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
@ -3225,20 +3333,26 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 65, 0x2c);
rt2800_bbp_write(rt2x00dev, 66, 0x38);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 68, 0x0b);
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
rt2800_bbp_write(rt2x00dev, 69, 0x16);
rt2800_bbp_write(rt2x00dev, 73, 0x12);
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
} else if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
rt2800_bbp_write(rt2x00dev, 73, 0x13);
rt2800_bbp_write(rt2x00dev, 75, 0x46);
rt2800_bbp_write(rt2x00dev, 76, 0x28);
rt2800_bbp_write(rt2x00dev, 77, 0x59);
if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 77, 0x58);
else
rt2800_bbp_write(rt2x00dev, 77, 0x59);
} else {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
rt2800_bbp_write(rt2x00dev, 73, 0x10);
@ -3263,23 +3377,33 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 81, 0x37);
}
if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_bbp_write(rt2x00dev, 74, 0x0b);
rt2800_bbp_write(rt2x00dev, 79, 0x18);
rt2800_bbp_write(rt2x00dev, 80, 0x09);
rt2800_bbp_write(rt2x00dev, 81, 0x33);
}
rt2800_bbp_write(rt2x00dev, 82, 0x62);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 83, 0x7a);
else
rt2800_bbp_write(rt2x00dev, 83, 0x6a);
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
rt2800_bbp_write(rt2x00dev, 84, 0x19);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
else if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 84, 0x9a);
else
rt2800_bbp_write(rt2x00dev, 84, 0x99);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 86, 0x38);
else
rt2800_bbp_write(rt2x00dev, 86, 0x00);
@ -3289,8 +3413,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 91, 0x04);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 92, 0x02);
else
rt2800_bbp_write(rt2x00dev, 92, 0x00);
@ -3304,6 +3429,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
@ -3312,27 +3438,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
else
rt2800_bbp_write(rt2x00dev, 103, 0x00);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 104, 0x92);
if (rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 105, 0x01);
else if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 105, 0x1c);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c);
else
rt2800_bbp_write(rt2x00dev, 105, 0x05);
if (rt2x00_rt(rt2x00dev, RT5390))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 106, 0x03);
else if (rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 106, 0x12);
else
rt2800_bbp_write(rt2x00dev, 106, 0x35);
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 128, 0x12);
if (rt2x00_rt(rt2x00dev, RT5392)) {
@ -3357,6 +3488,29 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 138, value);
}
if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_bbp_write(rt2x00dev, 67, 0x24);
rt2800_bbp_write(rt2x00dev, 143, 0x04);
rt2800_bbp_write(rt2x00dev, 142, 0x99);
rt2800_bbp_write(rt2x00dev, 150, 0x30);
rt2800_bbp_write(rt2x00dev, 151, 0x2e);
rt2800_bbp_write(rt2x00dev, 152, 0x20);
rt2800_bbp_write(rt2x00dev, 153, 0x34);
rt2800_bbp_write(rt2x00dev, 154, 0x40);
rt2800_bbp_write(rt2x00dev, 155, 0x3b);
rt2800_bbp_write(rt2x00dev, 253, 0x04);
rt2800_bbp_read(rt2x00dev, 47, &value);
rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
rt2800_bbp_write(rt2x00dev, 47, value);
/* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
rt2800_bbp_read(rt2x00dev, 3, &value);
rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
rt2800_bbp_write(rt2x00dev, 3, value);
}
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
int ant, div_mode;
@ -3489,6 +3643,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_rt(rt2x00dev, RT3070) &&
!rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3290) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
!rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
@ -3499,8 +3654,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
/*
* Init RF calibration.
*/
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
@ -3538,6 +3694,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
} else if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
} else if (rt2x00_rt(rt2x00dev, RT3390)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
@ -3946,6 +4149,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
}
if (rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
}
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
@ -4052,9 +4261,14 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
u16 efuse_ctrl_reg;
rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
if (rt2x00_rt(rt2x00dev, RT3290))
efuse_ctrl_reg = EFUSE_CTRL_3290;
else
efuse_ctrl_reg = EFUSE_CTRL;
rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
}
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@ -4062,27 +4276,44 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
{
u32 reg;
u16 efuse_ctrl_reg;
u16 efuse_data0_reg;
u16 efuse_data1_reg;
u16 efuse_data2_reg;
u16 efuse_data3_reg;
if (rt2x00_rt(rt2x00dev, RT3290)) {
efuse_ctrl_reg = EFUSE_CTRL_3290;
efuse_data0_reg = EFUSE_DATA0_3290;
efuse_data1_reg = EFUSE_DATA1_3290;
efuse_data2_reg = EFUSE_DATA2_3290;
efuse_data3_reg = EFUSE_DATA3_3290;
} else {
efuse_ctrl_reg = EFUSE_CTRL;
efuse_data0_reg = EFUSE_DATA0;
efuse_data1_reg = EFUSE_DATA1;
efuse_data2_reg = EFUSE_DATA2;
efuse_data3_reg = EFUSE_DATA3;
}
mutex_lock(&rt2x00dev->csr_mutex);
rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
/* Wait until the EEPROM has been loaded */
rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
/* Apparently the data is read from end to start */
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
/* The returned value is in CPU order, but eeprom is le */
*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
mutex_unlock(&rt2x00dev->csr_mutex);
@ -4244,9 +4475,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
* RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
* RT53xx: defined in "EEPROM_CHIP_ID" field
*/
rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
else
rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 ||
rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
else
value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
@ -4261,6 +4497,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RT3070:
case RT3071:
case RT3090:
case RT3290:
case RT3390:
case RT3572:
case RT5390:
@ -4281,6 +4518,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF3021:
case RF3022:
case RF3052:
case RF3290:
case RF3320:
case RF5360:
case RF5370:
@ -4597,6 +4835,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF2020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
rt2x00_rf(rt2x00dev, RF3022) ||
rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3320) ||
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
@ -4685,6 +4924,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
case RF3022:
case RF3320:
case RF3052:
case RF3290:
case RF5360:
case RF5370:
case RF5372:

View File

@ -280,7 +280,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
*/
static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
return FIRMWARE_RT2860;
/*
* Chip rt3290 use specific 4KB firmware named rt3290.bin.
*/
if (rt2x00_rt(rt2x00dev, RT3290))
return FIRMWARE_RT3290;
else
return FIRMWARE_RT2860;
}
static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
@ -974,6 +980,66 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
return rt2800_validate_eeprom(rt2x00dev);
}
static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
int i, count;
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
if ((rt2x00_get_field32(reg, WLAN_EN) == 1))
return 0;
rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
rt2x00_set_field32(&reg, WLAN_EN, 1);
rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
udelay(REGISTER_BUSY_DELAY);
count = 0;
do {
/*
* Check PLL_LD & XTAL_RDY.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
if ((rt2x00_get_field32(reg, PLL_LD) == 1) &&
(rt2x00_get_field32(reg, XTAL_RDY) == 1))
break;
udelay(REGISTER_BUSY_DELAY);
}
if (i >= REGISTER_BUSY_COUNT) {
if (count >= 10)
return -EIO;
rt2800_register_write(rt2x00dev, 0x58, 0x018);
udelay(REGISTER_BUSY_DELAY);
rt2800_register_write(rt2x00dev, 0x58, 0x418);
udelay(REGISTER_BUSY_DELAY);
rt2800_register_write(rt2x00dev, 0x58, 0x618);
udelay(REGISTER_BUSY_DELAY);
count++;
} else {
count = 0;
}
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
rt2x00_set_field32(&reg, WLAN_RESET, 1);
rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
udelay(10);
rt2x00_set_field32(&reg, WLAN_RESET, 0);
rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
udelay(10);
rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);
} while (count != 0);
return 0;
}
static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
@ -996,6 +1062,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval)
return retval;
/*
* In probe phase call rt2800_enable_wlan_rt3290 to enable wlan
* clk for rt3290. That avoid the MCU fail in start phase.
*/
if (rt2x00_rt(rt2x00dev, RT3290)) {
retval = rt2800_enable_wlan_rt3290(rt2x00dev);
if (retval)
return retval;
}
/*
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
@ -1175,6 +1252,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
{ PCI_DEVICE(0x1432, 0x7768) },
{ PCI_DEVICE(0x1462, 0x891a) },
{ PCI_DEVICE(0x1a3b, 0x1059) },
#ifdef CONFIG_RT2800PCI_RT3290
{ PCI_DEVICE(0x1814, 0x3290) },
#endif
#ifdef CONFIG_RT2800PCI_RT33XX
{ PCI_DEVICE(0x1814, 0x3390) },
#endif

View File

@ -47,6 +47,7 @@
* 8051 firmware image.
*/
#define FIRMWARE_RT2860 "rt2860.bin"
#define FIRMWARE_RT3290 "rt3290.bin"
#define FIRMWARE_IMAGE_BASE 0x2000
/*

View File

@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0411, 0x015d) },
{ USB_DEVICE(0x0411, 0x016f) },
{ USB_DEVICE(0x0411, 0x01a2) },
{ USB_DEVICE(0x0411, 0x01ee) },
/* Corega */
{ USB_DEVICE(0x07aa, 0x002f) },
{ USB_DEVICE(0x07aa, 0x003c) },

View File

@ -187,6 +187,7 @@ struct rt2x00_chip {
#define RT3070 0x3070
#define RT3071 0x3071
#define RT3090 0x3090 /* 2.4GHz PCIe */
#define RT3290 0x3290
#define RT3390 0x3390
#define RT3572 0x3572
#define RT3593 0x3593

View File

@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
u16 chip;
retval = pci_enable_device(pci_dev);
if (retval) {
@ -305,6 +306,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
if (retval)
goto exit_free_device;
/*
* Because rt3290 chip use different efuse offset to read efuse data.
* So before read efuse it need to indicate it is the
* rt3290 or not.
*/
pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
rt2x00dev->chip.rt = chip;
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_reg;

View File

@ -47,6 +47,8 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = {
{ PCI_DEVICE(0x1799, 0x6001) },
{ PCI_DEVICE(0x1799, 0x6020) },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) },
{ PCI_DEVICE(0x1186, 0x3301) },
{ PCI_DEVICE(0x1432, 0x7106) },
{ }
};

View File

@ -128,7 +128,7 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
u32 us_config;
struct rtl_priv *rtlpriv = rtl_priv(hw);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
"EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
ul_entry_idx, ul_key_id, ul_enc_alg,
ul_default_key, mac_addr);
@ -342,7 +342,8 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
/* Remove from HW Security CAM */
memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
pr_info("&&&&&&&&&del entry %d\n", i);
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
"del CAM entry %d\n", i);
}
}
return;

View File

@ -1273,17 +1273,18 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
*after reset, release previous pending packet,
*and force the tx idx to the first one
*/
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
if (rtlpci->tx_ring[i].desc) {
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i];
while (skb_queue_len(&ring->queue)) {
struct rtl_tx_desc *entry =
&ring->desc[ring->idx];
struct sk_buff *skb =
__skb_dequeue(&ring->queue);
struct rtl_tx_desc *entry;
struct sk_buff *skb;
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock,
flags);
entry = &ring->desc[ring->idx];
skb = __skb_dequeue(&ring->queue);
pci_unmap_single(rtlpci->pdev,
rtlpriv->cfg->ops->
get_desc((u8 *)
@ -1291,15 +1292,15 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
true,
HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE);
kfree_skb(skb);
ring->idx = (ring->idx + 1) % ring->entries;
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
flags);
kfree_skb(skb);
}
ring->idx = 0;
}
}
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
return 0;
}

View File

@ -1247,6 +1247,9 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
/* Read HT 40 OFDM TX power */
ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index];
ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index];
} else {
ofdmpowerLevel[0] = 0;
ofdmpowerLevel[1] = 0;
}
}

View File

@ -29,7 +29,6 @@
#include "../wifi.h"
#include "../core.h"
#include "../pci.h"
#include "../base.h"
#include "../pci.h"
#include "reg.h"

View File

@ -277,15 +277,6 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
join->rx_config_options = wl->rx_config;
join->rx_filter_options = wl->rx_filter;
/*
* FIXME: disable temporarily all filters because after commit
* 9cef8737 "mac80211: fix managed mode BSSID handling" broke
* association. The filter logic needs to be implemented properly
* and once that is done, this hack can be removed.
*/
join->rx_config_options = 0;
join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;

View File

@ -334,6 +334,12 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
if (ret < 0)
goto out;
/*
* Join command applies filters, and if we are not associated,
* BSSID filter must be disabled for association to work.
*/
if (is_zero_ether_addr(wl->bssid))
wl->rx_config &= ~CFG_BSSID_FILTER_EN;
ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
dtim_period);
@ -348,33 +354,6 @@ out:
return ret;
}
static void wl1251_filter_work(struct work_struct *work)
{
struct wl1251 *wl =
container_of(work, struct wl1251, filter_work);
int ret;
mutex_lock(&wl->mutex);
if (wl->state == WL1251_STATE_OFF)
goto out;
ret = wl1251_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
wl->dtim_period);
if (ret < 0)
goto out_sleep;
out_sleep:
wl1251_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
}
static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1251 *wl = hw->priv;
@ -478,7 +457,6 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->filter_work);
cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
@ -681,13 +659,15 @@ out:
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_CONTROL | \
FIF_OTHER_BSS)
FIF_OTHER_BSS | \
FIF_PROBE_REQ)
static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *total,u64 multicast)
{
struct wl1251 *wl = hw->priv;
int ret;
wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
@ -698,7 +678,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
/* no filters which we support changed */
return;
/* FIXME: wl->rx_config and wl->rx_filter are not protected */
mutex_lock(&wl->mutex);
wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
@ -721,15 +701,25 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
}
if (*total & FIF_CONTROL)
wl->rx_filter |= CFG_RX_CTL_EN;
if (*total & FIF_OTHER_BSS)
wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
if (*total & FIF_OTHER_BSS || is_zero_ether_addr(wl->bssid))
wl->rx_config &= ~CFG_BSSID_FILTER_EN;
if (*total & FIF_PROBE_REQ)
wl->rx_filter |= CFG_RX_PREQ_EN;
/*
* FIXME: workqueues need to be properly cancelled on stop(), for
* now let's just disable changing the filter settings. They will
* be updated any on config().
*/
/* schedule_work(&wl->filter_work); */
if (wl->state == WL1251_STATE_OFF)
goto out;
ret = wl1251_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
/* send filters to firmware */
wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
wl1251_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
}
/* HW encryption */
@ -1390,7 +1380,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
skb_queue_head_init(&wl->tx_queue);
INIT_WORK(&wl->filter_work, wl1251_filter_work);
INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->scanning = false;

View File

@ -315,7 +315,6 @@ struct wl1251 {
bool tx_queue_stopped;
struct work_struct tx_work;
struct work_struct filter_work;
/* Pending TX frames */
struct sk_buff *tx_frames[16];

View File

@ -174,7 +174,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
struct wl1271_radio_parms_cmd *radio_parms;
struct wl1271_ini_general_params *gp = &nvs->general_params;
int ret;
int ret, fem_idx;
if (!wl->nvs)
return -ENODEV;
@ -185,11 +185,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl1271_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_2[fem_idx].params,
sizeof(struct wl1271_ini_fem_params_2));
/* 5GHz parameters */
@ -197,7 +199,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
&nvs->stat_radio_params_5,
sizeof(struct wl1271_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_5[fem_idx].params,
sizeof(struct wl1271_ini_fem_params_5));
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
@ -216,7 +218,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
struct wl128x_radio_parms_cmd *radio_parms;
struct wl128x_ini_general_params *gp = &nvs->general_params;
int ret;
int ret, fem_idx;
if (!wl->nvs)
return -ENODEV;
@ -227,11 +229,13 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl128x_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_2[fem_idx].params,
sizeof(struct wl128x_ini_fem_params_2));
/* 5GHz parameters */
@ -239,7 +243,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
&nvs->stat_radio_params_5,
sizeof(struct wl128x_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_5[fem_idx].params,
sizeof(struct wl128x_ini_fem_params_5));
radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;

View File

@ -246,6 +246,7 @@ static struct wlcore_conf wl12xx_conf = {
.forced_ps = false,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
.sta_sleep_auth = WL1271_PSM_ILLEGAL,
},
.itrim = {
.enable = false,
@ -597,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = {
#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
int ret;
if (wl->chip.id != CHIP_ID_1283_PG20) {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
struct wl127x_rx_mem_pool_addr rx_mem_addr;
@ -615,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
wl1271_write(wl, WL1271_SLV_REG_DATA,
&rx_mem_addr, sizeof(rx_mem_addr), false);
ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr,
sizeof(rx_mem_addr), false);
if (ret < 0)
return ret;
}
return 0;
}
static int wl12xx_identify_chip(struct wl1271 *wl)
@ -681,64 +688,95 @@ out:
return ret;
}
static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr,
u16 val)
{
int ret;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
if (ret < 0)
goto out;
/* write value to OCP_POR_WDATA */
wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val);
ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val);
if (ret < 0)
goto out;
/* write 1 to OCP_CMD */
wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
if (ret < 0)
goto out;
out:
return ret;
}
static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr,
u16 *out)
{
u32 val;
int timeout = OCP_CMD_LOOP;
int ret;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
if (ret < 0)
return ret;
/* write 2 to OCP_CMD */
wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
if (ret < 0)
return ret;
/* poll for data ready */
do {
val = wl1271_read32(wl, WL12XX_OCP_DATA_READ);
ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val);
if (ret < 0)
return ret;
} while (!(val & OCP_READY_MASK) && --timeout);
if (!timeout) {
wl1271_warning("Top register access timed out.");
return 0xffff;
return -ETIMEDOUT;
}
/* check data status and return if OK */
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
return val & 0xffff;
else {
if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) {
wl1271_warning("Top register access returned error.");
return 0xffff;
return -EIO;
}
if (out)
*out = val & 0xffff;
return 0;
}
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
{
u16 spare_reg;
int ret;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
if (ret < 0)
return ret;
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= (BIT(3) | BIT(5) | BIT(6));
wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
if (ret < 0)
return ret;
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
if (ret < 0)
return ret;
/* Delay execution for 15msec, to let the HW settle */
mdelay(15);
@ -749,8 +787,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{
u16 tcxo_detection;
int ret;
ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection);
if (ret < 0)
return false;
tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
if (tcxo_detection & TCXO_DET_FAILED)
return false;
@ -760,8 +802,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
static bool wl128x_is_fref_valid(struct wl1271 *wl)
{
u16 fref_detection;
int ret;
ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection);
if (ret < 0)
return false;
fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
if (fref_detection & FREF_CLK_DETECT_FAIL)
return false;
@ -770,11 +816,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl)
static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
{
wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
int ret;
return 0;
ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
if (ret < 0)
goto out;
ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
if (ret < 0)
goto out;
ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG,
MCS_PLL_CONFIG_REG_VAL);
out:
return ret;
}
static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
@ -783,13 +839,19 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
u16 pll_config;
u8 input_freq;
struct wl12xx_priv *priv = wl->priv;
int ret;
/* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
if (ret < 0)
return ret;
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= BIT(2);
wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
if (ret < 0)
return ret;
/* Handle special cases of the TCXO clock */
if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
@ -799,14 +861,17 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
/* Set the input frequency according to the selected clock source */
input_freq = (clk & 1) + 1;
pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG);
ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config);
if (ret < 0)
return ret;
if (pll_config == 0xFFFF)
return -EFAULT;
pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
pll_config |= MCS_PLL_ENABLE_HP;
wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
return 0;
return ret;
}
/*
@ -820,6 +885,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{
struct wl12xx_priv *priv = wl->priv;
u16 sys_clk_cfg;
int ret;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
@ -830,7 +896,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
}
/* Query the HW, to determine which clock source we should use */
sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG);
ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg);
if (ret < 0)
return ret;
if (sys_clk_cfg == 0xFFFF)
return -EINVAL;
if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
@ -865,6 +934,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
struct wl12xx_priv *priv = wl->priv;
u32 pause;
u32 clk;
int ret;
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
@ -885,48 +955,74 @@ static int wl127x_boot_clk(struct wl1271 *wl)
if (priv->ref_clock != CONF_REF_CLK_19_2_E) {
u16 val;
/* Set clock type (open drain) */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE);
ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val);
if (ret < 0)
goto out;
val &= FREF_CLK_TYPE_BITS;
wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
if (ret < 0)
goto out;
/* Set clock pull mode (no pull) */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL);
ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val);
if (ret < 0)
goto out;
val |= NO_PULL;
wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
if (ret < 0)
goto out;
} else {
u16 val;
/* Set clock polarity */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY);
ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val);
if (ret < 0)
goto out;
val &= FREF_CLK_POLARITY_BITS;
val |= CLK_REQ_OUTN_SEL;
wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
if (ret < 0)
goto out;
}
wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk);
if (ret < 0)
goto out;
pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
pause &= ~(WU_COUNTER_PAUSE_VAL);
pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
return 0;
out:
return ret;
}
static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
unsigned long timeout;
u32 boot_data;
int ret = 0;
/* perform soft reset */
wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
if (ret < 0)
goto out;
/* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
while (1) {
boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break;
@ -942,12 +1038,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
}
/* disable Rx/Tx */
wl1271_write32(wl, WL12XX_ENABLE, 0x0);
ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0);
if (ret < 0)
goto out;
/* disable auto calibration on start*/
wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff);
return 0;
out:
return ret;
}
static int wl12xx_pre_boot(struct wl1271 *wl)
@ -968,16 +1067,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
}
/* Continue the ELP wake up sequence */
wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
if (ret < 0)
goto out;
udelay(500);
wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
if (ret < 0)
goto out;
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
to be used by DRPw FW. The RTRIM value will be added by the FW
before taking DRPw out of reset */
clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
@ -986,12 +1092,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
else
clk |= (priv->ref_clock << 1) << 4;
wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
if (ret < 0)
goto out;
wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
if (ret < 0)
goto out;
/* Disable interrupts */
wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
if (ret < 0)
goto out;
ret = wl1271_boot_soft_reset(wl);
if (ret < 0)
@ -1001,47 +1113,72 @@ out:
return ret;
}
static void wl12xx_pre_upload(struct wl1271 *wl)
static int wl12xx_pre_upload(struct wl1271 *wl)
{
u32 tmp, polarity;
u32 tmp;
u16 polarity;
int ret;
/* write firmware's last address (ie. it's length) to
* ACX_EEPROMLESS_IND_REG */
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
if (ret < 0)
goto out;
tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
/* 6. read the EEPROM parameters */
tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp);
if (ret < 0)
goto out;
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
if (wl->chip.id == CHIP_ID_1283_PG20)
wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
if (ret < 0)
goto out;
}
/* polarity must be set before the firmware is loaded */
polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY);
ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity);
if (ret < 0)
goto out;
/* We use HIGH polarity, so unset the LOW bit */
polarity &= ~POLARITY_LOW;
wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
out:
return ret;
}
static void wl12xx_enable_interrupts(struct wl1271 *wl)
static int wl12xx_enable_interrupts(struct wl1271 *wl)
{
wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR);
int ret;
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL12XX_ACX_ALL_EVENTS_VECTOR);
if (ret < 0)
goto out;
wlcore_enable_interrupts(wl);
wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
if (ret < 0)
goto out;
wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
out:
return ret;
}
static int wl12xx_boot(struct wl1271 *wl)
@ -1056,7 +1193,9 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
wl12xx_pre_upload(wl);
ret = wl12xx_pre_upload(wl);
if (ret < 0)
goto out;
ret = wlcore_boot_upload_firmware(wl);
if (ret < 0)
@ -1066,22 +1205,30 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
wl12xx_enable_interrupts(wl);
ret = wl12xx_enable_interrupts(wl);
out:
return ret;
}
static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len)
{
wl1271_write(wl, cmd_box_addr, buf, len, false);
wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
int ret;
ret = wlcore_write(wl, cmd_box_addr, buf, len, false);
if (ret < 0)
return ret;
ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
return ret;
}
static void wl12xx_ack_event(struct wl1271 *wl)
static int wl12xx_ack_event(struct wl1271 *wl)
{
wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
WL12XX_INTR_TRIG_EVENT_ACK);
}
static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
@ -1161,13 +1308,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
return data_len - sizeof(*desc) - desc->pad_len;
}
static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
{
if (wl->fw_status_1->tx_results_counter ==
(wl->tx_results_count & 0xff))
return;
return 0;
wl1271_tx_complete(wl);
return wlcore_tx_complete(wl);
}
static int wl12xx_hw_init(struct wl1271 *wl)
@ -1268,39 +1415,58 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
return supported;
}
static void wl12xx_get_fuse_mac(struct wl1271 *wl)
static int wl12xx_get_fuse_mac(struct wl1271 *wl)
{
u32 mac1, mac2;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
if (ret < 0)
goto out;
mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1);
if (ret < 0)
goto out;
ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2);
if (ret < 0)
goto out;
/* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
((mac1 & 0xff000000) >> 24);
wl->fuse_nic_addr = mac1 & 0xffffff;
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
out:
return ret;
}
static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{
u32 die_info;
u16 die_info;
int ret;
if (wl->chip.id == CHIP_ID_1283_PG20)
die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1,
&die_info);
else
die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1,
&die_info);
return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
if (ret >= 0 && ver)
*ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET);
return ret;
}
static void wl12xx_get_mac(struct wl1271 *wl)
static int wl12xx_get_mac(struct wl1271 *wl)
{
if (wl12xx_mac_in_fuse(wl))
wl12xx_get_fuse_mac(wl);
return wl12xx_get_fuse_mac(wl);
return 0;
}
static void wl12xx_set_tx_desc_csum(struct wl1271 *wl,
@ -1448,10 +1614,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
wl->fw_status_priv_len = 0;
wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap,
sizeof(wl12xx_ht_cap));
memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap,
sizeof(wl12xx_ht_cap));
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
wl12xx_conf_init(wl);
if (!fref_param) {

View File

@ -32,25 +32,21 @@ enum {
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_ACX_EVENTS_VECTOR (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_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#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;

View File

@ -24,37 +24,52 @@
#include "io.h"
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{
u32 tmp;
int ret;
if (WARN_ON(addr % 2))
return;
return -EINVAL;
if ((addr % 4) == 0) {
tmp = wl1271_read32(wl, addr);
ret = wlcore_read32(wl, addr, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff0000) | val;
wl1271_write32(wl, addr, tmp);
ret = wlcore_write32(wl, addr, tmp);
} else {
tmp = wl1271_read32(wl, addr - 2);
ret = wlcore_read32(wl, addr - 2, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff) | (val << 16);
wl1271_write32(wl, addr - 2, tmp);
ret = wlcore_write32(wl, addr - 2, tmp);
}
out:
return ret;
}
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr)
int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
{
u32 val;
int ret;
if (WARN_ON(addr % 2))
return 0;
return -EINVAL;
if ((addr % 4) == 0) {
/* address is 4-bytes aligned */
val = wl1271_read32(wl, addr);
return val & 0xffff;
ret = wlcore_read32(wl, addr, &val);
if (ret >= 0 && out)
*out = val & 0xffff;
} else {
val = wl1271_read32(wl, addr - 2);
return (val & 0xffff0000) >> 16;
ret = wlcore_read32(wl, addr - 2, &val);
if (ret >= 0 && out)
*out = (val & 0xffff0000) >> 16;
}
return ret;
}

View File

@ -22,7 +22,7 @@
#ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr);
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__ */

View File

@ -43,10 +43,11 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
static char *ht_mode_param = "wide";
static char *ht_mode_param = "default";
static char *board_type_param = "hdk";
static bool checksum_param = false;
static bool enable_11a_param = true;
static int num_rx_desc_param = -1;
/* phy paramters */
static int dc2dc_param = -1;
@ -372,6 +373,7 @@ static struct wlcore_conf wl18xx_conf = {
.forced_ps = false,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
.sta_sleep_auth = WL1271_PSM_ILLEGAL,
},
.itrim = {
.enable = false,
@ -606,24 +608,15 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
wl->plt_fw_name = WL18XX_FW_NAME;
wl->quirks |= WLCORE_QUIRK_NO_ELP |
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
WLCORE_QUIRK_TX_PAD_LAST_FRAME;
break;
case CHIP_ID_185x_PG10:
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)",
wl->chip.id);
wl->sr_fw_name = WL18XX_FW_NAME;
/* wl18xx uses the same firmware for PLT */
wl->plt_fw_name = WL18XX_FW_NAME;
wl->quirks |= WLCORE_QUIRK_NO_ELP |
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED |
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
wl->chip.id);
ret = -ENODEV;
goto out;
/* PG 1.0 has some problems with MCS_13, so disable it */
wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5);
break;
default:
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
ret = -ENODEV;
@ -634,123 +627,178 @@ out:
return ret;
}
static void wl18xx_set_clk(struct wl1271 *wl)
static int wl18xx_set_clk(struct wl1271 *wl)
{
u32 clk_freq;
u16 clk_freq;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
if (ret < 0)
goto out;
/* TODO: PG2: apparently we need to read the clk type */
clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT);
ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq,
wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m,
wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n);
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
wl18xx_clk_table[clk_freq].n);
if (ret < 0)
goto out;
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M,
wl18xx_clk_table[clk_freq].m);
if (ret < 0)
goto out;
if (wl18xx_clk_table[clk_freq].swallow) {
/* first the 16 lower bits */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].q &
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].q &
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
if (ret < 0)
goto out;
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].q >> 16) &
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].q >> 16) &
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
if (ret < 0)
goto out;
/* first the 16 lower bits */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].p &
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].p &
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
if (ret < 0)
goto out;
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].p >> 16) &
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].p >> 16) &
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
} else {
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
}
out:
return ret;
}
static void wl18xx_boot_soft_reset(struct wl1271 *wl)
static int wl18xx_boot_soft_reset(struct wl1271 *wl)
{
int ret;
/* disable Rx/Tx */
wl1271_write32(wl, WL18XX_ENABLE, 0x0);
ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0);
if (ret < 0)
goto out;
/* disable auto calibration on start*/
wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff);
ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff);
out:
return ret;
}
static int wl18xx_pre_boot(struct wl1271 *wl)
{
wl18xx_set_clk(wl);
int ret;
ret = wl18xx_set_clk(wl);
if (ret < 0)
goto out;
/* Continue the ELP wake up sequence */
wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
if (ret < 0)
goto out;
udelay(500);
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
if (ret < 0)
goto out;
/* Disable interrupts */
wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
if (ret < 0)
goto out;
wl18xx_boot_soft_reset(wl);
ret = wl18xx_boot_soft_reset(wl);
return 0;
out:
return ret;
}
static void wl18xx_pre_upload(struct wl1271 *wl)
static int wl18xx_pre_upload(struct wl1271 *wl)
{
u32 tmp;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
if (ret < 0)
goto out;
/* TODO: check if this is all needed */
wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
if (ret < 0)
goto out;
tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
tmp = wl1271_read32(wl, WL18XX_SCR_PAD2);
ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
out:
return ret;
}
static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
size_t len;
int ret;
/* the parameters struct is smaller for PG1 */
if (wl->chip.id == CHIP_ID_185x_PG10)
len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1;
else
len = sizeof(struct wl18xx_mac_and_phy_params);
ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
if (ret < 0)
goto out;
wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len,
false);
ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy,
sizeof(struct wl18xx_mac_and_phy_params), false);
out:
return ret;
}
static void wl18xx_enable_interrupts(struct wl1271 *wl)
static int wl18xx_enable_interrupts(struct wl1271 *wl)
{
u32 event_mask, intr_mask;
int ret;
if (wl->chip.id == CHIP_ID_185x_PG10) {
event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1;
intr_mask = WL18XX_INTR_MASK_PG1;
} else {
event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2;
intr_mask = WL18XX_INTR_MASK_PG2;
}
event_mask = WL18XX_ACX_EVENTS_VECTOR;
intr_mask = WL18XX_INTR_MASK;
wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
if (ret < 0)
goto out;
wlcore_enable_interrupts(wl);
wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~intr_mask);
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~intr_mask);
out:
return ret;
}
static int wl18xx_boot(struct wl1271 *wl)
@ -761,25 +809,29 @@ static int wl18xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
wl18xx_pre_upload(wl);
ret = wl18xx_pre_upload(wl);
if (ret < 0)
goto out;
ret = wlcore_boot_upload_firmware(wl);
if (ret < 0)
goto out;
wl18xx_set_mac_and_phy(wl);
ret = wl18xx_set_mac_and_phy(wl);
if (ret < 0)
goto out;
ret = wlcore_boot_run_firmware(wl);
if (ret < 0)
goto out;
wl18xx_enable_interrupts(wl);
ret = wl18xx_enable_interrupts(wl);
out:
return ret;
}
static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len)
{
struct wl18xx_priv *priv = wl->priv;
@ -787,13 +839,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
memcpy(priv->cmd_buf, buf, len);
memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len);
wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE,
false);
return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
WL18XX_CMD_MAX_SIZE, false);
}
static void wl18xx_ack_event(struct wl1271 *wl)
static int wl18xx_ack_event(struct wl1271 *wl)
{
wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK);
return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
WL18XX_INTR_TRIG_EVENT_ACK);
}
static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
@ -975,34 +1028,32 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
} else if (!strcmp(ht_mode_param, "mimo")) {
wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
/*
* PG 1.0 has some problems with MCS_13, so disable it
*
* TODO: instead of hacking this in here, we should
* make it more general and change a bit in the
* wlvif->rate_set instead.
*/
if (wl->chip.id == CHIP_ID_185x_PG10)
return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13;
return CONF_TX_MIMO_RATES;
} else {
return 0;
}
}
static s8 wl18xx_get_pg_ver(struct wl1271 *wl)
static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{
u32 fuse;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
if (ret < 0)
goto out;
fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3);
fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
if (ret < 0)
goto out;
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
if (ver)
*ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
return (s8)fuse;
ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
out:
return ret;
}
#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
@ -1021,8 +1072,7 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
}
if (fw->size != WL18XX_CONF_SIZE) {
wl1271_error("configuration binary file size is wrong, "
"expected %ld got %zd",
wl1271_error("configuration binary file size is wrong, expected %zu got %zu",
WL18XX_CONF_SIZE, fw->size);
ret = -EINVAL;
goto out;
@ -1069,26 +1119,41 @@ out:
static int wl18xx_plt_init(struct wl1271 *wl)
{
wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
int ret;
ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
if (ret < 0)
return ret;
return wl->ops->boot(wl);
}
static void wl18xx_get_mac(struct wl1271 *wl)
static int wl18xx_get_mac(struct wl1271 *wl)
{
u32 mac1, mac2;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
if (ret < 0)
goto out;
mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1);
mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2);
ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1);
if (ret < 0)
goto out;
ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2);
if (ret < 0)
goto out;
/* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
((mac1 & 0xff000000) >> 24);
wl->fuse_nic_addr = (mac1 & 0xffffff);
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
out:
return ret;
}
static int wl18xx_handle_static_data(struct wl1271 *wl,
@ -1214,8 +1279,8 @@ static struct wlcore_ops wl18xx_ops = {
.pre_pkt_send = wl18xx_pre_pkt_send,
};
/* HT cap appropriate for wide channels */
static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = {
/* HT cap appropriate for wide channels in 2Ghz */
static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40,
.ht_supported = true,
@ -1228,6 +1293,20 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = {
},
};
/* HT cap appropriate for wide channels in 5Ghz */
static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_SUP_WIDTH_20_40,
.ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.mcs = {
.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
.rx_highest = cpu_to_le16(150),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
};
/* HT cap appropriate for SISO 20 */
static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
.cap = IEEE80211_HT_CAP_SGI_20,
@ -1254,18 +1333,6 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
},
};
static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = {
.cap = IEEE80211_HT_CAP_SGI_20,
.ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.mcs = {
.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
.rx_highest = cpu_to_le16(72),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
};
static int __devinit wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
@ -1286,7 +1353,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = 32;
wl->num_rx_desc = 16;
wl->num_rx_desc = 32;
wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
@ -1294,32 +1361,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
if (!strcmp(ht_mode_param, "wide")) {
memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
&wl18xx_siso40_ht_cap,
sizeof(wl18xx_siso40_ht_cap));
memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
&wl18xx_siso40_ht_cap,
sizeof(wl18xx_siso40_ht_cap));
} else if (!strcmp(ht_mode_param, "mimo")) {
memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
&wl18xx_mimo_ht_cap_2ghz,
sizeof(wl18xx_mimo_ht_cap_2ghz));
memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
&wl18xx_mimo_ht_cap_5ghz,
sizeof(wl18xx_mimo_ht_cap_5ghz));
} else if (!strcmp(ht_mode_param, "siso20")) {
memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
&wl18xx_siso20_ht_cap,
sizeof(wl18xx_siso20_ht_cap));
memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
&wl18xx_siso20_ht_cap,
sizeof(wl18xx_siso20_ht_cap));
} else {
wl1271_error("invalid ht_mode '%s'", ht_mode_param);
ret = -EINVAL;
goto out_free;
}
if (num_rx_desc_param != -1)
wl->num_rx_desc = num_rx_desc_param;
ret = wl18xx_conf_init(wl, &pdev->dev);
if (ret < 0)
@ -1366,6 +1409,37 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
if (dc2dc_param != -1)
priv->conf.phy.external_pa_dc2dc = dc2dc_param;
if (!strcmp(ht_mode_param, "default")) {
/*
* Only support mimo with multiple antennas. Fall back to
* siso20.
*/
if (priv->conf.phy.number_of_assembled_ant2_4 >= 2)
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_mimo_ht_cap_2ghz);
else
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_siso20_ht_cap);
/* 5Ghz is always wide */
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
&wl18xx_siso40_ht_cap_5ghz);
} else if (!strcmp(ht_mode_param, "wide")) {
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_siso40_ht_cap_2ghz);
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
&wl18xx_siso40_ht_cap_5ghz);
} else if (!strcmp(ht_mode_param, "siso20")) {
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_siso20_ht_cap);
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
&wl18xx_siso20_ht_cap);
} else {
wl1271_error("invalid ht_mode '%s'", ht_mode_param);
ret = -EINVAL;
goto out_free;
}
if (!checksum_param) {
wl18xx_ops.set_rx_csum = NULL;
wl18xx_ops.init_vif = NULL;
@ -1410,7 +1484,7 @@ static void __exit wl18xx_exit(void)
module_exit(wl18xx_exit);
module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20");
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20");
module_param_named(board_type, board_type_param, charp, S_IRUSR);
MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
@ -1458,6 +1532,11 @@ module_param_named(pwr_limit_reference_11_abg,
MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 "
"(default is 0xc8)");
module_param_named(num_rx_desc,
num_rx_desc_param, int, S_IRUSR);
MODULE_PARM_DESC(num_rx_desc_param,
"Number of Rx descriptors: u8 (default is 32)");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_FIRMWARE(WL18XX_FW_NAME);

Some files were not shown because too many files have changed in this diff Show More