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

This commit is contained in:
John W. Linville 2012-09-14 13:53:49 -04:00
commit 9316f0e3c6
130 changed files with 3662 additions and 916 deletions

View File

@ -227,7 +227,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
void bcma_bus_unregister(struct bcma_bus *bus) void bcma_bus_unregister(struct bcma_bus *bus)
{ {
struct bcma_device *cores[3];
cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
bcma_unregister_cores(bus); bcma_unregister_cores(bus);
kfree(cores[2]);
kfree(cores[1]);
kfree(cores[0]);
} }
int __init bcma_bus_early_register(struct bcma_bus *bus, int __init bcma_bus_early_register(struct bcma_bus *bus,

View File

@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C) }, { USB_DEVICE(0x0489, 0xE03C) },
{ USB_DEVICE(0x0489, 0xE036) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };

View File

@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Apple-specific (Broadcom) devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
/* Broadcom SoftSailing reporting vendor specific */ /* Broadcom SoftSailing reporting vendor specific */
{ USB_DEVICE(0x0a5c, 0x21e1) }, { USB_DEVICE(0x0a5c, 0x21e1) },
@ -94,16 +97,14 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */ /* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0489, 0xe042) }, { USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x0a5c, 0x21e6) },
{ USB_DEVICE(0x0a5c, 0x21e8) },
{ USB_DEVICE(0x0a5c, 0x21f3) },
{ USB_DEVICE(0x0a5c, 0x21f4) },
{ USB_DEVICE(0x413c, 0x8197) }, { USB_DEVICE(0x413c, 0x8197) },
/* Foxconn - Hon Hai */ /* Foxconn - Hon Hai */
{ USB_DEVICE(0x0489, 0xe033) }, { USB_DEVICE(0x0489, 0xe033) },
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -141,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
/* Broadcom BCM2035 */ /* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },

View File

@ -87,7 +87,6 @@ static struct pci_driver airo_driver = {
/* Include Wireless Extension definition and check version - Jean II */ /* Include Wireless Extension definition and check version - Jean II */
#include <linux/wireless.h> #include <linux/wireless.h>
#define WIRELESS_SPY /* enable iwspy support */ #define WIRELESS_SPY /* enable iwspy support */
#include <net/iw_handler.h> /* New driver API */
#define CISCO_EXT /* enable Cisco extensions */ #define CISCO_EXT /* enable Cisco extensions */
#ifdef CISCO_EXT #ifdef CISCO_EXT
@ -5984,13 +5983,11 @@ static int airo_set_wap(struct net_device *dev,
Cmd cmd; Cmd cmd;
Resp rsp; Resp rsp;
APListRid APList_rid; APListRid APList_rid;
static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
if (awrq->sa_family != ARPHRD_ETHER) if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL; return -EINVAL;
else if (!memcmp(any, awrq->sa_data, ETH_ALEN) || else if (is_broadcast_ether_addr(awrq->sa_data) ||
!memcmp(off, awrq->sa_data, ETH_ALEN)) { is_zero_ether_addr(awrq->sa_data)) {
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LOSE_SYNC; cmd.cmd=CMD_LOSE_SYNC;
if (down_interruptible(&local->sem)) if (down_interruptible(&local->sem))

View File

@ -498,36 +498,6 @@ exit:
return ret; return ret;
} }
#define HEX2STR_BUFFERS 4
#define HEX2STR_MAX_LEN 64
/* Convert binary data into hex string */
static char *hex2str(void *buf, size_t len)
{
static atomic_t a = ATOMIC_INIT(0);
static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)];
char *obuf = ret;
u8 *ibuf = buf;
if (len > HEX2STR_MAX_LEN)
len = HEX2STR_MAX_LEN;
if (len == 0)
goto exit;
while (len--) {
obuf = hex_byte_pack(obuf, *ibuf++);
*obuf++ = '-';
}
obuf--;
exit:
*obuf = '\0';
return ret;
}
/* LED trigger */ /* LED trigger */
static int tx_activity; static int tx_activity;
static void at76_ledtrig_tx_timerfunc(unsigned long data); static void at76_ledtrig_tx_timerfunc(unsigned long data);
@ -1004,9 +974,9 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN; WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
for (i = 0; i < WEP_KEYS; i++) for (i = 0; i < WEP_KEYS; i++)
at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s", at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %*phD",
wiphy_name(priv->hw->wiphy), i, wiphy_name(priv->hw->wiphy), i,
hex2str(m->wep_default_keyvalue[i], key_len)); key_len, m->wep_default_keyvalue[i]);
exit: exit:
kfree(m); kfree(m);
} }
@ -1031,7 +1001,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration " at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
"%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d " "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
"CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d " "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
"current_bssid %pM current_essid %s current_bss_type %d " "current_bssid %pM current_essid %*phD current_bss_type %d "
"pm_mode %d ibss_change %d res %d " "pm_mode %d ibss_change %d res %d "
"multi_domain_capability_implemented %d " "multi_domain_capability_implemented %d "
"international_roaming %d country_string %.3s", "international_roaming %d country_string %.3s",
@ -1041,7 +1011,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window), le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
m->CFP_mode, m->privacy_option_implemented, m->DTIM_period, m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
m->CFP_period, m->current_bssid, m->CFP_period, m->current_bssid,
hex2str(m->current_essid, IW_ESSID_MAX_SIZE), IW_ESSID_MAX_SIZE, m->current_essid,
m->current_bss_type, m->power_mgmt_mode, m->ibss_change, m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
m->res, m->multi_domain_capability_implemented, m->res, m->multi_domain_capability_implemented,
m->multi_domain_capability_enabled, m->country_string); m->multi_domain_capability_enabled, m->country_string);
@ -1069,7 +1039,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
"cwmin %d cwmax %d short_retry_time %d long_retry_time %d " "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
"scan_type %d scan_channel %d probe_delay %u " "scan_type %d scan_channel %d probe_delay %u "
"min_channel_time %d max_channel_time %d listen_int %d " "min_channel_time %d max_channel_time %d listen_int %d "
"desired_ssid %s desired_bssid %pM desired_bsstype %d", "desired_ssid %*phD desired_bssid %pM desired_bsstype %d",
wiphy_name(priv->hw->wiphy), wiphy_name(priv->hw->wiphy),
le32_to_cpu(m->max_tx_msdu_lifetime), le32_to_cpu(m->max_tx_msdu_lifetime),
le32_to_cpu(m->max_rx_lifetime), le32_to_cpu(m->max_rx_lifetime),
@ -1080,7 +1050,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
le16_to_cpu(m->min_channel_time), le16_to_cpu(m->min_channel_time),
le16_to_cpu(m->max_channel_time), le16_to_cpu(m->max_channel_time),
le16_to_cpu(m->listen_interval), le16_to_cpu(m->listen_interval),
hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE), IW_ESSID_MAX_SIZE, m->desired_ssid,
m->desired_bssid, m->desired_bsstype); m->desired_bssid, m->desired_bsstype);
exit: exit:
kfree(m); kfree(m);
@ -1160,13 +1130,13 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
goto exit; goto exit;
} }
at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s", at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %*phD",
wiphy_name(priv->hw->wiphy), wiphy_name(priv->hw->wiphy),
hex2str(m->channel_list, sizeof(m->channel_list))); (int)sizeof(m->channel_list), m->channel_list);
at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s", at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %*phD",
wiphy_name(priv->hw->wiphy), wiphy_name(priv->hw->wiphy),
hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel))); (int)sizeof(m->tx_powerlevel), m->tx_powerlevel);
exit: exit:
kfree(m); kfree(m);
} }
@ -1369,9 +1339,9 @@ static int at76_startup_device(struct at76_priv *priv)
int ret; int ret;
at76_dbg(DBG_PARAMS, at76_dbg(DBG_PARAMS,
"%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d " "%s param: ssid %.*s (%*phD) mode %s ch %d wep %s key %d "
"keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size, "keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size,
priv->essid, hex2str(priv->essid, IW_ESSID_MAX_SIZE), priv->essid, IW_ESSID_MAX_SIZE, priv->essid,
priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra", priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
priv->channel, priv->wep_enabled ? "enabled" : "disabled", priv->channel, priv->wep_enabled ? "enabled" : "disabled",
priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]); priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);

View File

@ -237,7 +237,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
entry_cck->fir_step_level); entry_cck->fir_step_level);
/* Skip MRC CCK for pre AR9003 families */ /* Skip MRC CCK for pre AR9003 families */
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah))
return; return;
if (aniState->mrcCCK != entry_cck->mrc_cck_on) if (aniState->mrcCCK != entry_cck->mrc_cck_on)

View File

@ -138,7 +138,8 @@ static const struct ar9300_eeprom ar9300_default = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -713,7 +714,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -1289,7 +1291,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -1865,7 +1868,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -2440,7 +2444,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -3520,7 +3525,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
else if (AR_SREV_9462(ah) || AR_SREV_9550(ah)) else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
else { else {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@ -3568,7 +3573,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9462_ALL, value); AR_SWITCH_TABLE_COM_AR9462_ALL, value);
} else if (AR_SREV_9550(ah)) { } else if (AR_SREV_9550(ah)) {
@ -3612,7 +3617,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
} }
} }
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) { if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
/* /*
* main_lnaconf, alt_lnaconf, main_tb, alt_tb * main_lnaconf, alt_lnaconf, main_tb, alt_tb
@ -3622,19 +3627,16 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
regval &= (~AR_ANT_DIV_CTRL_ALL); regval &= (~AR_ANT_DIV_CTRL_ALL);
regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
/* enable_lnadiv */ /* enable_lnadiv */
regval &= (~AR_PHY_9485_ANT_DIV_LNADIV); regval &= (~AR_PHY_ANT_DIV_LNADIV);
regval |= ((value >> 6) & 0x1) << regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
AR_PHY_9485_ANT_DIV_LNADIV_S;
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
/*enable fast_div */ /*enable fast_div */
regval = REG_READ(ah, AR_PHY_CCK_DETECT); regval = REG_READ(ah, AR_PHY_CCK_DETECT);
regval &= (~AR_FAST_DIV_ENABLE); regval &= (~AR_FAST_DIV_ENABLE);
regval |= ((value >> 7) & 0x1) << regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
AR_FAST_DIV_ENABLE_S;
REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
ant_div_ctl1 = ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
/* check whether antenna diversity is enabled */ /* check whether antenna diversity is enabled */
if ((ant_div_ctl1 >> 0x6) == 0x3) { if ((ant_div_ctl1 >> 0x6) == 0x3) {
regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
@ -3642,15 +3644,15 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
* clear bits 25-30 main_lnaconf, alt_lnaconf, * clear bits 25-30 main_lnaconf, alt_lnaconf,
* main_tb, alt_tb * main_tb, alt_tb
*/ */
regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | regval &= (~(AR_PHY_ANT_DIV_MAIN_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_LNACONF | AR_PHY_ANT_DIV_ALT_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_GAINTB | AR_PHY_ANT_DIV_ALT_GAINTB |
AR_PHY_9485_ANT_DIV_MAIN_GAINTB)); AR_PHY_ANT_DIV_MAIN_GAINTB));
/* by default use LNA1 for the main antenna */ /* by default use LNA1 for the main antenna */
regval |= (AR_PHY_9485_ANT_DIV_LNA1 << regval |= (AR_PHY_ANT_DIV_LNA1 <<
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S); AR_PHY_ANT_DIV_MAIN_LNACONF_S);
regval |= (AR_PHY_9485_ANT_DIV_LNA2 << regval |= (AR_PHY_ANT_DIV_LNA2 <<
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S); AR_PHY_ANT_DIV_ALT_LNACONF_S);
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
} }
@ -3843,7 +3845,7 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return; return;
} else if (AR_SREV_9462(ah)) { } else if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
reg_val = le32_to_cpu(pBase->swreg); reg_val = le32_to_cpu(pBase->swreg);
REG_WRITE(ah, AR_PHY_PMU1, reg_val); REG_WRITE(ah, AR_PHY_PMU1, reg_val);
} else { } else {
@ -3874,7 +3876,7 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
while (!REG_READ_FIELD(ah, AR_PHY_PMU2, while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
AR_PHY_PMU2_PGM)) AR_PHY_PMU2_PGM))
udelay(10); udelay(10);
} else if (AR_SREV_9462(ah)) } else if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1); REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
else { else {
reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) | reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
@ -3977,6 +3979,62 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz)
bias & 0x3); bias & 0x3);
} }
static int ar9003_hw_get_thermometer(struct ath_hw *ah)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
int thermometer = (pBase->miscConfiguration >> 1) & 0x3;
return --thermometer;
}
static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
{
int thermometer = ar9003_hw_get_thermometer(ah);
u8 therm_on = (thermometer < 0) ? 0 : 1;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
if (ah->caps.tx_chainmask & BIT(1))
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
if (ah->caps.tx_chainmask & BIT(2))
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
therm_on = (thermometer < 0) ? 0 : (thermometer == 0);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
if (ah->caps.tx_chainmask & BIT(1)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
}
if (ah->caps.tx_chainmask & BIT(2)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 2);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
}
}
static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
{
u32 data, ko, kg;
if (!AR_SREV_9462_20(ah))
return;
ar9300_otp_read_word(ah, 1, &data);
ko = data & 0xff;
kg = (data >> 8) & 0xff;
if (ko || kg) {
REG_RMW_FIELD(ah, AR_PHY_BB_THERM_ADC_3,
AR_PHY_BB_THERM_ADC_3_THERM_ADC_OFFSET, ko);
REG_RMW_FIELD(ah, AR_PHY_BB_THERM_ADC_3,
AR_PHY_BB_THERM_ADC_3_THERM_ADC_SCALE_GAIN,
kg + 256);
}
}
static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
@ -3992,6 +4050,8 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_internal_regulator_apply(ah); ar9003_hw_internal_regulator_apply(ah);
ar9003_hw_apply_tuning_caps(ah); ar9003_hw_apply_tuning_caps(ah);
ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
ar9003_hw_thermometer_apply(ah);
ar9003_hw_thermo_cal_apply(ah);
} }
static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
@ -4528,7 +4588,7 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
{ {
int tempSlope = 0; int tempSlope = 0;
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
int f[3], t[3]; int f[8], t[8], i;
REG_RMW(ah, AR_PHY_TPC_11_B0, REG_RMW(ah, AR_PHY_TPC_11_B0,
(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
@ -4561,7 +4621,14 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
*/ */
if (frequency < 4000) if (frequency < 4000)
tempSlope = eep->modalHeader2G.tempSlope; tempSlope = eep->modalHeader2G.tempSlope;
else if (eep->base_ext2.tempSlopeLow != 0) { else if ((eep->baseEepHeader.miscConfiguration & 0x20) != 0) {
for (i = 0; i < 8; i++) {
t[i] = eep->base_ext1.tempslopextension[i];
f[i] = FBIN2FREQ(eep->calFreqPier5G[i], 0);
}
tempSlope = ar9003_hw_power_interpolate((s32) frequency,
f, t, 8);
} else if (eep->base_ext2.tempSlopeLow != 0) {
t[0] = eep->base_ext2.tempSlopeLow; t[0] = eep->base_ext2.tempSlopeLow;
f[0] = 5180; f[0] = 5180;
t[1] = eep->modalHeader5G.tempSlope; t[1] = eep->modalHeader5G.tempSlope;

View File

@ -267,7 +267,8 @@ struct cal_ctl_data_5g {
struct ar9300_BaseExtension_1 { struct ar9300_BaseExtension_1 {
u8 ant_div_control; u8 ant_div_control;
u8 future[11]; u8 future[3];
u8 tempslopextension[8];
int8_t quick_drop_low; int8_t quick_drop_low;
int8_t quick_drop_high; int8_t quick_drop_high;
} __packed; } __packed;

View File

@ -24,6 +24,7 @@
#include "ar955x_1p0_initvals.h" #include "ar955x_1p0_initvals.h"
#include "ar9580_1p0_initvals.h" #include "ar9580_1p0_initvals.h"
#include "ar9462_2p0_initvals.h" #include "ar9462_2p0_initvals.h"
#include "ar9565_1p0_initvals.h"
/* General hardware code for the AR9003 hadware family */ /* General hardware code for the AR9003 hadware family */
@ -34,14 +35,12 @@
*/ */
static void ar9003_hw_init_mode_regs(struct ath_hw *ah) static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{ {
#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
#define AR9462_BB_CTX_COEFJ(x) \ #define AR9462_BB_CTX_COEFJ(x) \
ar9462_##x##_baseband_core_txfir_coeff_japan_2484 ar9462_##x##_baseband_core_txfir_coeff_japan_2484
#define AR9462_BBC_TXIFR_COEFFJ \ #define AR9462_BBC_TXIFR_COEFFJ \
ar9462_2p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
if (AR_SREV_9330_11(ah)) { if (AR_SREV_9330_11(ah)) {
/* mac */ /* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@ -220,10 +219,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* Awake -> Sleep Setting */ /* Awake -> Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes, INIT_INI_ARRAY(&ah->iniPcieSerdes,
PCIE_PLL_ON_CREQ_DIS_L1_2P0); ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
/* Sleep -> Awake Setting */ /* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
PCIE_PLL_ON_CREQ_DIS_L1_2P0); ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
/* Fast clock modal settings */ /* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesFastClock, INIT_INI_ARRAY(&ah->iniModesFastClock,
@ -302,6 +301,39 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesFastClock, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9580_1p0_modes_fast_clock); ar9580_1p0_modes_fast_clock);
} else if (AR_SREV_9565(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9565_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9565_1p0_mac_postamble);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9565_1p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9565_1p0_baseband_postamble);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9565_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9565_1p0_radio_postamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9565_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9565_1p0_soc_postamble);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9565_1p0_Common_rx_gain_table);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p0_Modes_lowest_ob_db_tx_gain_table);
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9565_1p0_modes_fast_clock);
} else { } else {
/* mac */ /* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@ -374,6 +406,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_low_ob_db_tx_gain_table_2p0); ar9462_modes_low_ob_db_tx_gain_table_2p0);
else if (AR_SREV_9565(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p0_modes_low_ob_db_tx_gain_table);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2); ar9300Modes_lowest_ob_db_tx_gain_table_2p2);
@ -402,6 +437,9 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_high_ob_db_tx_gain_table_2p0); ar9462_modes_high_ob_db_tx_gain_table_2p0);
else if (AR_SREV_9565(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p0_modes_high_ob_db_tx_gain_table);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2); ar9300Modes_high_ob_db_tx_gain_table_2p2);
@ -424,6 +462,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
else if (AR_SREV_9580(ah)) else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table); ar9580_1p0_low_ob_db_tx_gain_table);
else if (AR_SREV_9565(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p0_modes_low_ob_db_tx_gain_table);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2); ar9300Modes_low_ob_db_tx_gain_table_2p2);
@ -446,6 +487,9 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
else if (AR_SREV_9580(ah)) else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_power_tx_gain_table); ar9580_1p0_high_power_tx_gain_table);
else if (AR_SREV_9565(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p0_modes_high_power_tx_gain_table);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_power_tx_gain_table_2p2); ar9300Modes_high_power_tx_gain_table_2p2);
@ -538,6 +582,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
} else if (AR_SREV_9580(ah)) } else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table); ar9580_1p0_wo_xlna_rx_gain_table);
else if (AR_SREV_9565(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9565_1p0_common_wo_xlna_rx_gain_table);
else else
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2); ar9300Common_wo_xlna_rx_gain_table_2p2);

View File

@ -31,7 +31,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
u32 val, ctl12, ctl17; u32 val, ctl12, ctl17;
u8 desc_len; u8 desc_len;
desc_len = (AR_SREV_9462(ah) ? 0x18 : 0x17); desc_len = ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x18 : 0x17);
val = (ATHEROS_VENDOR_ID << AR_DescId_S) | val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
(1 << AR_TxRxDesc_S) | (1 << AR_TxRxDesc_S) |
@ -531,7 +531,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_PHY; rxs->rs_status |= ATH9K_RXERR_PHY;
rxs->rs_phyerr = phyerr; rxs->rs_phyerr = phyerr;
} }
}; }
} }
if (rxsp->status11 & AR_KeyMiss) if (rxsp->status11 & AR_KeyMiss)

View File

@ -714,6 +714,7 @@ bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
return true; return true;
} }
EXPORT_SYMBOL(ar9003_mci_start_reset);
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata) struct ath9k_hw_cal_data *caldata)
@ -1201,12 +1202,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
ar9003_mci_2g5g_switch(ah, false); ar9003_mci_2g5g_switch(ah, false);
break; break;
case MCI_STATE_SET_BT_CAL_START:
mci->bt_state = MCI_BT_CAL_START;
break;
case MCI_STATE_SET_BT_CAL:
mci->bt_state = MCI_BT_CAL;
break;
case MCI_STATE_RESET_REQ_WAKE: case MCI_STATE_RESET_REQ_WAKE:
ar9003_mci_reset_req_wakeup(ah); ar9003_mci_reset_req_wakeup(ah);
mci->update_2g5g = true; mci->update_2g5g = true;
@ -1327,6 +1322,10 @@ u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
if (first) { if (first) {
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
if (gpm_ptr >= mci->gpm_len)
gpm_ptr = 0;
mci->gpm_idx = gpm_ptr; mci->gpm_idx = gpm_ptr;
return gpm_ptr; return gpm_ptr;
} }
@ -1371,6 +1370,10 @@ u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
more_gpm = MCI_GPM_NOMORE; more_gpm = MCI_GPM_NOMORE;
temp_index = mci->gpm_idx; temp_index = mci->gpm_idx;
if (temp_index >= mci->gpm_len)
temp_index = 0;
mci->gpm_idx++; mci->gpm_idx++;
if (mci->gpm_idx >= mci->gpm_len) if (mci->gpm_idx >= mci->gpm_len)

View File

@ -190,8 +190,6 @@ enum mci_bt_state {
enum mci_state_type { enum mci_state_type {
MCI_STATE_ENABLE, MCI_STATE_ENABLE,
MCI_STATE_SET_BT_AWAKE, MCI_STATE_SET_BT_AWAKE,
MCI_STATE_SET_BT_CAL_START,
MCI_STATE_SET_BT_CAL,
MCI_STATE_LAST_SCHD_MSG_OFFSET, MCI_STATE_LAST_SCHD_MSG_OFFSET,
MCI_STATE_REMOTE_SLEEP, MCI_STATE_REMOTE_SLEEP,
MCI_STATE_RESET_REQ_WAKE, MCI_STATE_RESET_REQ_WAKE,

View File

@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
}; };
int training_power; int training_power;
int i, val; int i, val;
u32 am2pm_mask = ah->paprd_ratemask;
if (IS_CHAN_2GHZ(ah->curchan)) if (IS_CHAN_2GHZ(ah->curchan))
training_power = ar9003_get_training_power_2g(ah); training_power = ar9003_get_training_power_2g(ah);
@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
} }
ah->paprd_training_power = training_power; ah->paprd_training_power = training_power;
if (AR_SREV_9330(ah))
am2pm_mask = 0;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask); ah->paprd_ratemask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
ah->paprd_ratemask); am2pm_mask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
ah->paprd_ratemask_ht40); ah->paprd_ratemask_ht40);
@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
} }
EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
struct ath9k_hw_cal_data *caldata,
int chain)
{
u32 *pa_in = caldata->pa_table[chain];
int capdiv_offset, quick_drop_offset;
int capdiv2g, quick_drop;
int count = 0;
int i;
if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
return false;
capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
if (quick_drop)
quick_drop -= 0x40;
for (i = 0; i < NUM_BIN + 1; i++) {
if (pa_in[i] == 1400)
count++;
}
if (AR_SREV_9485(ah)) {
if (pa_in[23] < 800) {
capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
capdiv2g += capdiv_offset;
if (capdiv2g > 7) {
capdiv2g = 7;
if (pa_in[23] < 600) {
quick_drop++;
if (quick_drop > 0)
quick_drop = 0;
}
}
} else if (pa_in[23] == 1400) {
quick_drop_offset = min_t(int, count / 3, 2);
quick_drop += quick_drop_offset;
capdiv2g += quick_drop_offset / 2;
if (capdiv2g > 7)
capdiv2g = 7;
if (quick_drop > 0) {
quick_drop = 0;
capdiv2g -= quick_drop_offset;
if (capdiv2g < 0)
capdiv2g = 0;
}
} else {
return false;
}
} else if (AR_SREV_9330(ah)) {
if (pa_in[23] < 1000) {
capdiv_offset = (1000 - pa_in[23]) / 100;
capdiv2g += capdiv_offset;
if (capdiv_offset > 3) {
capdiv_offset = 1;
quick_drop--;
}
capdiv2g += capdiv_offset;
if (capdiv2g > 6)
capdiv2g = 6;
if (quick_drop < -4)
quick_drop = -4;
} else if (pa_in[23] == 1400) {
if (count > 3) {
quick_drop++;
capdiv2g -= count / 4;
if (quick_drop > -2)
quick_drop = -2;
} else {
capdiv2g--;
}
if (capdiv2g < 0)
capdiv2g = 0;
} else {
return false;
}
}
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
quick_drop);
return true;
}
int ar9003_paprd_create_curve(struct ath_hw *ah, int ar9003_paprd_create_curve(struct ath_hw *ah,
struct ath9k_hw_cal_data *caldata, int chain) struct ath9k_hw_cal_data *caldata, int chain)
{ {
@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,
if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
status = -2; status = -2;
if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
status = -EINPROGRESS;
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);

View File

@ -88,7 +88,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = (freq * 4) / div; channelSel = (freq * 4) / div;
chan_frac = (((freq * 4) % div) * 0x20000) / div; chan_frac = (((freq * 4) % div) * 0x20000) / div;
channelSel = (channelSel << 17) | chan_frac; channelSel = (channelSel << 17) | chan_frac;
} else if (AR_SREV_9485(ah)) { } else if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
u32 chan_frac; u32 chan_frac;
/* /*
@ -206,6 +206,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
for (i = 0; i < max_spur_cnts; i++) { for (i = 0; i < max_spur_cnts; i++) {
if (AR_SREV_9462(ah) && (i == 0 || i == 3)) if (AR_SREV_9462(ah) && (i == 0 || i == 3))
continue; continue;
negative = 0; negative = 0;
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
AR_SREV_9550(ah)) AR_SREV_9550(ah))
@ -301,7 +302,9 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
int freq_offset, int freq_offset,
int spur_freq_sd, int spur_freq_sd,
int spur_delta_phase, int spur_delta_phase,
int spur_subchannel_sd) int spur_subchannel_sd,
int range,
int synth_freq)
{ {
int mask_index = 0; int mask_index = 0;
@ -316,8 +319,11 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd); AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd);
REG_RMW_FIELD(ah, AR_PHY_TIMING11, REG_RMW_FIELD(ah, AR_PHY_TIMING11,
AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1); AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1);
REG_RMW_FIELD(ah, AR_PHY_TIMING11,
AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1); if (!(AR_SREV_9565(ah) && range == 10 && synth_freq == 2437))
REG_RMW_FIELD(ah, AR_PHY_TIMING11,
AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1);
REG_RMW_FIELD(ah, AR_PHY_TIMING4, REG_RMW_FIELD(ah, AR_PHY_TIMING4,
AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1); AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
@ -358,9 +364,44 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff); AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
} }
static void ar9003_hw_spur_ofdm_9565(struct ath_hw *ah,
int freq_offset)
{
int mask_index = 0;
mask_index = (freq_offset << 4) / 5;
if (mask_index < 0)
mask_index = mask_index - 1;
mask_index = mask_index & 0x7f;
REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_B,
mask_index);
/* A == B */
REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_B,
AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A,
mask_index);
REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_B,
mask_index);
REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_B, 0xe);
REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_B, 0xe);
/* A == B */
REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_B,
AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
}
static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah, static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
int freq_offset) int freq_offset,
int range,
int synth_freq)
{ {
int spur_freq_sd = 0; int spur_freq_sd = 0;
int spur_subchannel_sd = 0; int spur_subchannel_sd = 0;
@ -402,7 +443,8 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
freq_offset, freq_offset,
spur_freq_sd, spur_freq_sd,
spur_delta_phase, spur_delta_phase,
spur_subchannel_sd); spur_subchannel_sd,
range, synth_freq);
} }
/* Spur mitigation for OFDM */ /* Spur mitigation for OFDM */
@ -447,7 +489,17 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i], mode); freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i], mode);
freq_offset -= synth_freq; freq_offset -= synth_freq;
if (abs(freq_offset) < range) { if (abs(freq_offset) < range) {
ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); ar9003_hw_spur_ofdm_work(ah, chan, freq_offset,
range, synth_freq);
if (AR_SREV_9565(ah) && (i < 4)) {
freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i + 1],
mode);
freq_offset -= synth_freq;
if (abs(freq_offset) < range)
ar9003_hw_spur_ofdm_9565(ah, freq_offset);
}
break; break;
} }
} }
@ -456,7 +508,8 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
static void ar9003_hw_spur_mitigate(struct ath_hw *ah, static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
ar9003_hw_spur_mitigate_mrc_cck(ah, chan); if (!AR_SREV_9565(ah))
ar9003_hw_spur_mitigate_mrc_cck(ah, chan);
ar9003_hw_spur_mitigate_ofdm(ah, chan); ar9003_hw_spur_mitigate_ofdm(ah, chan);
} }
@ -736,7 +789,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (chan->channel == 2484) if (chan->channel == 2484)
ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
AR_GLB_SWREG_DISCONT_EN_BT_WLAN); AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
@ -746,9 +799,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
ath9k_hw_apply_txpower(ah, chan, false); ath9k_hw_apply_txpower(ah, chan, false);
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0, if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
ah->enabled_cals |= TX_IQ_CAL; ah->enabled_cals |= TX_IQ_CAL;
else else
ah->enabled_cals &= ~TX_IQ_CAL; ah->enabled_cals &= ~TX_IQ_CAL;
@ -1111,7 +1164,7 @@ static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
if (AR_SREV_9330(ah)) if (AR_SREV_9330(ah))
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ; ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ; ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ;
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9462_2GHZ; ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9462_2GHZ;
ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ; ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ;
@ -1223,17 +1276,17 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
} }
static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf) struct ath_hw_antcomb_conf *antconf)
{ {
u32 regval; u32 regval;
regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >> antconf->main_lna_conf = (regval & AR_PHY_ANT_DIV_MAIN_LNACONF) >>
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S; AR_PHY_ANT_DIV_MAIN_LNACONF_S;
antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >> antconf->alt_lna_conf = (regval & AR_PHY_ANT_DIV_ALT_LNACONF) >>
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S; AR_PHY_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >> antconf->fast_div_bias = (regval & AR_PHY_ANT_FAST_DIV_BIAS) >>
AR_PHY_9485_ANT_FAST_DIV_BIAS_S; AR_PHY_ANT_FAST_DIV_BIAS_S;
if (AR_SREV_9330_11(ah)) { if (AR_SREV_9330_11(ah)) {
antconf->lna1_lna2_delta = -9; antconf->lna1_lna2_delta = -9;
@ -1253,22 +1306,21 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
u32 regval; u32 regval;
regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_LNACONF | AR_PHY_ANT_DIV_ALT_LNACONF |
AR_PHY_9485_ANT_FAST_DIV_BIAS | AR_PHY_ANT_FAST_DIV_BIAS |
AR_PHY_9485_ANT_DIV_MAIN_GAINTB | AR_PHY_ANT_DIV_MAIN_GAINTB |
AR_PHY_9485_ANT_DIV_ALT_GAINTB); AR_PHY_ANT_DIV_ALT_GAINTB);
regval |= ((antconf->main_lna_conf << regval |= ((antconf->main_lna_conf << AR_PHY_ANT_DIV_MAIN_LNACONF_S)
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S) & AR_PHY_ANT_DIV_MAIN_LNACONF);
& AR_PHY_9485_ANT_DIV_MAIN_LNACONF); regval |= ((antconf->alt_lna_conf << AR_PHY_ANT_DIV_ALT_LNACONF_S)
regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S) & AR_PHY_ANT_DIV_ALT_LNACONF);
& AR_PHY_9485_ANT_DIV_ALT_LNACONF); regval |= ((antconf->fast_div_bias << AR_PHY_ANT_FAST_DIV_BIAS_S)
regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S) & AR_PHY_ANT_FAST_DIV_BIAS);
& AR_PHY_9485_ANT_FAST_DIV_BIAS); regval |= ((antconf->main_gaintb << AR_PHY_ANT_DIV_MAIN_GAINTB_S)
regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S) & AR_PHY_ANT_DIV_MAIN_GAINTB);
& AR_PHY_9485_ANT_DIV_MAIN_GAINTB); regval |= ((antconf->alt_gaintb << AR_PHY_ANT_DIV_ALT_GAINTB_S)
regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S) & AR_PHY_ANT_DIV_ALT_GAINTB);
& AR_PHY_9485_ANT_DIV_ALT_GAINTB);
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
} }
@ -1312,10 +1364,10 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
if (AR_SREV_9462_20(ah)) if (AR_SREV_9462_20(ah))
ar9003_hw_prog_ini(ah, ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
&ah->ini_radio_post_sys2ant, modesIndex);
modesIndex);
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
@ -1326,6 +1378,9 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites);
if (AR_SREV_9565(ah))
REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites); REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
ah->modes_index = modesIndex; ah->modes_index = modesIndex;

View File

@ -223,15 +223,24 @@
#define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c) #define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c)
#define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20) #define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20)
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A 0x00000FE0 #define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A 0x00000FE0
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S 5 #define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S 5
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A 0x1F #define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A 0x1F
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0 #define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_B 0x00FE0000
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_B_S 17
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_B 0x0001F000
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_B_S 12
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A 0x00000FE0 #define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A 0x00000FE0
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S 5 #define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S 5
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A 0x1F #define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A 0x1F
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S 0 #define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S 0
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_B 0x00FE0000
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_B_S 17
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_B 0x0001F000
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_B_S 12
/* /*
* MRC Feild Definitions * MRC Feild Definitions
@ -271,23 +280,23 @@
#define AR_ANT_DIV_ENABLE_S 24 #define AR_ANT_DIV_ENABLE_S 24
#define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00 #define AR_PHY_ANT_FAST_DIV_BIAS 0x00007e00
#define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9 #define AR_PHY_ANT_FAST_DIV_BIAS_S 9
#define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000 #define AR_PHY_ANT_DIV_LNADIV 0x01000000
#define AR_PHY_9485_ANT_DIV_LNADIV_S 24 #define AR_PHY_ANT_DIV_LNADIV_S 24
#define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000 #define AR_PHY_ANT_DIV_ALT_LNACONF 0x06000000
#define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25 #define AR_PHY_ANT_DIV_ALT_LNACONF_S 25
#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000 #define AR_PHY_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27 #define AR_PHY_ANT_DIV_MAIN_LNACONF_S 27
#define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000 #define AR_PHY_ANT_DIV_ALT_GAINTB 0x20000000
#define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29 #define AR_PHY_ANT_DIV_ALT_GAINTB_S 29
#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000 #define AR_PHY_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30 #define AR_PHY_ANT_DIV_MAIN_GAINTB_S 30
#define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0 #define AR_PHY_ANT_DIV_LNA1_MINUS_LNA2 0x0
#define AR_PHY_9485_ANT_DIV_LNA2 0x1 #define AR_PHY_ANT_DIV_LNA2 0x1
#define AR_PHY_9485_ANT_DIV_LNA1 0x2 #define AR_PHY_ANT_DIV_LNA1 0x2
#define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3 #define AR_PHY_ANT_DIV_LNA1_PLUS_LNA2 0x3
#define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c)
#define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30)
@ -609,6 +618,12 @@
#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff #define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff
#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 #define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0
#define AR_PHY_BB_THERM_ADC_3 (AR_SM_BASE + 0x250)
#define AR_PHY_BB_THERM_ADC_3_THERM_ADC_SCALE_GAIN 0x0001ff00
#define AR_PHY_BB_THERM_ADC_3_THERM_ADC_SCALE_GAIN_S 8
#define AR_PHY_BB_THERM_ADC_3_THERM_ADC_OFFSET 0x000000ff
#define AR_PHY_BB_THERM_ADC_3_THERM_ADC_OFFSET_S 0
#define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254) #define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254)
#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff
#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0 #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0
@ -625,9 +640,13 @@
#define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
#define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
#define AR_PHY_65NM_CH0_TXRF3 0x16048
#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e
#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1
#define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_65NM_CH0_SYNTH4 0x1608c
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002) #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00000001 : 0x00000002)
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0 : 1)
#define AR_PHY_65NM_CH0_SYNTH7 0x16098 #define AR_PHY_65NM_CH0_SYNTH7 0x16098
#define AR_PHY_65NM_CH0_BIAS1 0x160c0 #define AR_PHY_65NM_CH0_BIAS1 0x160c0
#define AR_PHY_65NM_CH0_BIAS2 0x160c4 #define AR_PHY_65NM_CH0_BIAS2 0x160c4
@ -637,7 +656,7 @@
#define AR_PHY_65NM_CH2_RXTX4 0x1690c #define AR_PHY_65NM_CH2_RXTX4 0x1690c
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \ #define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
((AR_SREV_9462(ah) ? 0x1628c : 0x16280))) (((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x1628c : 0x16280)))
#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300) #define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
#define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8) #define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8)
@ -665,7 +684,7 @@
#define AR_SWITCH_TABLE_ALL_S (0) #define AR_SWITCH_TABLE_ALL_S (0)
#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\ #define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
(AR_SREV_9462(ah) ? 0x16294 : 0x1628c)) ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c))
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
@ -687,17 +706,17 @@
#define AR_CH0_TOP2_XPABIASLVL_S 12 #define AR_CH0_TOP2_XPABIASLVL_S 12
#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \ #define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \
(AR_SREV_9462(ah) ? 0x16298 : 0x16290)) ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : 0x16290))
#define AR_CH0_XTAL_CAPINDAC 0x7f000000 #define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24 #define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#define AR_CH0_XTAL_CAPOUTDAC_S 17 #define AR_CH0_XTAL_CAPOUTDAC_S 17
#define AR_PHY_PMU1 (AR_SREV_9462(ah) ? 0x16340 : 0x16c40) #define AR_PHY_PMU1 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16340 : 0x16c40)
#define AR_PHY_PMU1_PWD 0x1 #define AR_PHY_PMU1_PWD 0x1
#define AR_PHY_PMU1_PWD_S 0 #define AR_PHY_PMU1_PWD_S 0
#define AR_PHY_PMU2 (AR_SREV_9462(ah) ? 0x16344 : 0x16c44) #define AR_PHY_PMU2 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16344 : 0x16c44)
#define AR_PHY_PMU2_PGM 0x00200000 #define AR_PHY_PMU2_PGM 0x00200000
#define AR_PHY_PMU2_PGM_S 21 #define AR_PHY_PMU2_PGM_S 21
@ -877,6 +896,8 @@
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR 0x20000000
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S 29
#define AR_PHY_65NM_RXTX4_XLNA_BIAS 0xC0000000 #define AR_PHY_65NM_RXTX4_XLNA_BIAS 0xC0000000
#define AR_PHY_65NM_RXTX4_XLNA_BIAS_S 30 #define AR_PHY_65NM_RXTX4_XLNA_BIAS_S 30

View File

@ -58,7 +58,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, {0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},

File diff suppressed because it is too large Load Diff

View File

@ -423,7 +423,6 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_beacon(struct ath_softc *sc); void ath9k_set_beacon(struct ath_softc *sc);
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
/*******************/ /*******************/
/* Link Monitoring */ /* Link Monitoring */
@ -473,7 +472,7 @@ struct ath_btcoex {
unsigned long op_flags; unsigned long op_flags;
int bt_stomp_type; /* Types of BT stomping */ int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* in usec */ u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */ u32 btcoex_period; /* in msec */
u32 btscan_no_stomp; /* in usec */ u32 btscan_no_stomp; /* in usec */
u32 duty_cycle; u32 duty_cycle;
u32 bt_wait_time; u32 bt_wait_time;

View File

@ -373,6 +373,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
sc->debug.stats.istats.tsfoor++; sc->debug.stats.istats.tsfoor++;
if (status & ATH9K_INT_MCI) if (status & ATH9K_INT_MCI)
sc->debug.stats.istats.mci++; sc->debug.stats.istats.mci++;
if (status & ATH9K_INT_GENTIMER)
sc->debug.stats.istats.gen_timer++;
} }
static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
@ -418,6 +420,7 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
PR_IS("DTIM", dtim); PR_IS("DTIM", dtim);
PR_IS("TSFOOR", tsfoor); PR_IS("TSFOOR", tsfoor);
PR_IS("MCI", mci); PR_IS("MCI", mci);
PR_IS("GENTIMER", gen_timer);
PR_IS("TOTAL", total); PR_IS("TOTAL", total);
len += snprintf(buf + len, mxlen - len, len += snprintf(buf + len, mxlen - len,

View File

@ -41,7 +41,6 @@ enum ath_reset_type {
RESET_TYPE_PLL_HANG, RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG, RESET_TYPE_MAC_HANG,
RESET_TYPE_BEACON_STUCK, RESET_TYPE_BEACON_STUCK,
RESET_TYPE_MCI,
__RESET_TYPE_MAX __RESET_TYPE_MAX
}; };
@ -74,6 +73,8 @@ enum ath_reset_type {
* from a beacon differs from the PCU's internal TSF by more than a * from a beacon differs from the PCU's internal TSF by more than a
* (programmable) threshold * (programmable) threshold
* @local_timeout: Internal bus timeout. * @local_timeout: Internal bus timeout.
* @mci: MCI interrupt, specific to MCI based BTCOEX chipsets
* @gen_timer: Generic hardware timer interrupt
*/ */
struct ath_interrupt_stats { struct ath_interrupt_stats {
u32 total; u32 total;
@ -100,6 +101,7 @@ struct ath_interrupt_stats {
u32 bb_watchdog; u32 bb_watchdog;
u32 tsfoor; u32 tsfoor;
u32 mci; u32 mci;
u32 gen_timer;
/* Sync-cause stats */ /* Sync-cause stats */
u32 sync_cause_all; u32 sync_cause_all;

View File

@ -96,6 +96,7 @@
#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) #define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
@ -108,7 +109,7 @@
#define EEP_RFSILENT_ENABLED_S 0 #define EEP_RFSILENT_ENABLED_S 0
#define EEP_RFSILENT_POLARITY 0x0002 #define EEP_RFSILENT_POLARITY 0x0002
#define EEP_RFSILENT_POLARITY_S 1 #define EEP_RFSILENT_POLARITY_S 1
#define EEP_RFSILENT_GPIO_SEL (AR_SREV_9462(ah) ? 0x00fc : 0x001c) #define EEP_RFSILENT_GPIO_SEL ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00fc : 0x001c)
#define EEP_RFSILENT_GPIO_SEL_S 2 #define EEP_RFSILENT_GPIO_SEL_S 2
#define AR5416_OPFLAGS_11A 0x01 #define AR5416_OPFLAGS_11A 0x01

View File

@ -51,7 +51,7 @@ void ath_init_leds(struct ath_softc *sc)
sc->sc_ah->led_pin = ATH_LED_PIN_9485; sc->sc_ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(sc->sc_ah)) else if (AR_SREV_9300(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9300; sc->sc_ah->led_pin = ATH_LED_PIN_9300;
else if (AR_SREV_9462(sc->sc_ah)) else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9462; sc->sc_ah->led_pin = ATH_LED_PIN_9462;
else else
sc->sc_ah->led_pin = ATH_LED_PIN_DEF; sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
@ -228,7 +228,12 @@ static void ath_btcoex_period_timer(unsigned long data)
ath9k_hw_btcoex_enable(ah); ath9k_hw_btcoex_enable(ah);
spin_unlock_bh(&btcoex->btcoex_lock); spin_unlock_bh(&btcoex->btcoex_lock);
if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { /*
* btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
* ensure that we properly convert btcoex_period to usec
* for any comparision with (btcoex/btscan_)no_stomp.
*/
if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
if (btcoex->hw_timer_enabled) if (btcoex->hw_timer_enabled)
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
@ -341,7 +346,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
{ {
struct ath_btcoex *btcoex = &sc->btcoex; struct ath_btcoex *btcoex = &sc->btcoex;
ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); if (btcoex->hw_timer_enabled)
ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
} }
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)

View File

@ -973,8 +973,8 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
{ {
int transfer, err; int transfer, err;
const void *data = hif_dev->firmware->data; const void *data = hif_dev->fw_data;
size_t len = hif_dev->firmware->size; size_t len = hif_dev->fw_size;
u32 addr = AR9271_FIRMWARE; u32 addr = AR9271_FIRMWARE;
u8 *buf = kzalloc(4096, GFP_KERNEL); u8 *buf = kzalloc(4096, GFP_KERNEL);
u32 firm_offset; u32 firm_offset;
@ -1017,7 +1017,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
return -EIO; return -EIO;
dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n",
hif_dev->fw_name, (unsigned long) hif_dev->firmware->size); hif_dev->fw_name, (unsigned long) hif_dev->fw_size);
return 0; return 0;
} }
@ -1099,11 +1099,11 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb, hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
&hif_dev->udev->dev); &hif_dev->udev->dev);
if (hif_dev->htc_handle == NULL) { if (hif_dev->htc_handle == NULL)
goto err_fw; goto err_dev_alloc;
}
hif_dev->firmware = fw; hif_dev->fw_data = fw->data;
hif_dev->fw_size = fw->size;
/* Proceed with initialization */ /* Proceed with initialization */
@ -1121,6 +1121,8 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
goto err_htc_hw_init; goto err_htc_hw_init;
} }
release_firmware(fw);
hif_dev->flags |= HIF_USB_READY;
complete(&hif_dev->fw_done); complete(&hif_dev->fw_done);
return; return;
@ -1129,8 +1131,8 @@ err_htc_hw_init:
ath9k_hif_usb_dev_deinit(hif_dev); ath9k_hif_usb_dev_deinit(hif_dev);
err_dev_init: err_dev_init:
ath9k_htc_hw_free(hif_dev->htc_handle); ath9k_htc_hw_free(hif_dev->htc_handle);
err_dev_alloc:
release_firmware(fw); release_firmware(fw);
hif_dev->firmware = NULL;
err_fw: err_fw:
ath9k_hif_usb_firmware_fail(hif_dev); ath9k_hif_usb_firmware_fail(hif_dev);
} }
@ -1277,11 +1279,10 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
wait_for_completion(&hif_dev->fw_done); wait_for_completion(&hif_dev->fw_done);
if (hif_dev->firmware) { if (hif_dev->flags & HIF_USB_READY) {
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
ath9k_htc_hw_free(hif_dev->htc_handle); ath9k_htc_hw_free(hif_dev->htc_handle);
ath9k_hif_usb_dev_deinit(hif_dev); ath9k_hif_usb_dev_deinit(hif_dev);
release_firmware(hif_dev->firmware);
} }
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
@ -1317,13 +1318,23 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
struct hif_device_usb *hif_dev = usb_get_intfdata(interface); struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
struct htc_target *htc_handle = hif_dev->htc_handle; struct htc_target *htc_handle = hif_dev->htc_handle;
int ret; int ret;
const struct firmware *fw;
ret = ath9k_hif_usb_alloc_urbs(hif_dev); ret = ath9k_hif_usb_alloc_urbs(hif_dev);
if (ret) if (ret)
return ret; return ret;
if (hif_dev->firmware) { if (hif_dev->flags & HIF_USB_READY) {
/* request cached firmware during suspend/resume cycle */
ret = request_firmware(&fw, hif_dev->fw_name,
&hif_dev->udev->dev);
if (ret)
goto fail_resume;
hif_dev->fw_data = fw->data;
hif_dev->fw_size = fw->size;
ret = ath9k_hif_usb_download_fw(hif_dev); ret = ath9k_hif_usb_download_fw(hif_dev);
release_firmware(fw);
if (ret) if (ret)
goto fail_resume; goto fail_resume;
} else { } else {

View File

@ -85,12 +85,14 @@ struct cmd_buf {
}; };
#define HIF_USB_START BIT(0) #define HIF_USB_START BIT(0)
#define HIF_USB_READY BIT(1)
struct hif_device_usb { struct hif_device_usb {
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *interface; struct usb_interface *interface;
const struct usb_device_id *usb_device_id; const struct usb_device_id *usb_device_id;
const struct firmware *firmware; const void *fw_data;
size_t fw_size;
struct completion fw_done; struct completion fw_done;
struct htc_target *htc_handle; struct htc_target *htc_handle;
struct hif_usb_tx tx; struct hif_usb_tx tx;

View File

@ -173,17 +173,26 @@ void ath9k_htc_stop_btcoex(struct ath9k_htc_priv *priv)
if (ah->btcoex_hw.enabled && if (ah->btcoex_hw.enabled &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
ath9k_hw_btcoex_disable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_htc_cancel_btcoex_work(priv); ath_htc_cancel_btcoex_work(priv);
ath9k_hw_btcoex_disable(ah);
} }
} }
void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product) void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
{ {
struct ath_hw *ah = priv->ah; struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
int qnum; int qnum;
/*
* Check if BTCOEX is globally disabled.
*/
if (!common->btcoex_enabled) {
ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_NONE;
return;
}
if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
} }

View File

@ -30,6 +30,10 @@ int htc_modparam_nohwcrypt;
module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444); module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
static int ath9k_htc_btcoex_enable;
module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
#define CHAN2G(_freq, _idx) { \ #define CHAN2G(_freq, _idx) { \
.center_freq = (_freq), \ .center_freq = (_freq), \
.hw_value = (_idx), \ .hw_value = (_idx), \
@ -635,6 +639,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
common->hw = priv->hw; common->hw = priv->hw;
common->priv = priv; common->priv = priv;
common->debug_mask = ath9k_debug; common->debug_mask = ath9k_debug;
common->btcoex_enabled = ath9k_htc_btcoex_enable == 1;
spin_lock_init(&priv->beacon_lock); spin_lock_init(&priv->beacon_lock);
spin_lock_init(&priv->tx.tx_lock); spin_lock_init(&priv->tx.tx_lock);

View File

@ -489,24 +489,20 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
ista = (struct ath9k_htc_sta *) sta->drv_priv; ista = (struct ath9k_htc_sta *) sta->drv_priv;
memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
tsta.is_vif_sta = 0;
ista->index = sta_idx; ista->index = sta_idx;
tsta.is_vif_sta = 0;
maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
tsta.maxampdu = cpu_to_be16(maxampdu);
} else { } else {
memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
tsta.is_vif_sta = 1; tsta.is_vif_sta = 1;
tsta.maxampdu = cpu_to_be16(0xffff);
} }
tsta.sta_index = sta_idx; tsta.sta_index = sta_idx;
tsta.vif_index = avp->index; tsta.vif_index = avp->index;
if (!sta) {
tsta.maxampdu = cpu_to_be16(0xffff);
} else {
maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
tsta.maxampdu = cpu_to_be16(maxampdu);
}
WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
if (ret) { if (ret) {
if (sta) if (sta)

View File

@ -355,7 +355,7 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
ah->is_pciexpress = true; ah->is_pciexpress = true;
else else
ah->is_pciexpress = (val & ah->is_pciexpress = (val &
@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.spurchans[i][1] = AR_NO_SPUR; ah->config.spurchans[i][1] = AR_NO_SPUR;
} }
/* PAPRD needs some more work to be enabled */
ah->config.paprd_disable = 1;
ah->config.rx_intr_mitigation = true; ah->config.rx_intr_mitigation = true;
ah->config.pcieSerDesWrite = true; ah->config.pcieSerDesWrite = true;
@ -605,6 +602,11 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah))
ah->WARegVal &= ~AR_WA_D3_L1_DISABLE; ah->WARegVal &= ~AR_WA_D3_L1_DISABLE;
if (AR_SREV_9565(ah)) {
ah->WARegVal |= AR_WA_BIT22;
REG_WRITE(ah, AR_WA, ah->WARegVal);
}
ath9k_hw_init_defaults(ah); ath9k_hw_init_defaults(ah);
ath9k_hw_init_config(ah); ath9k_hw_init_config(ah);
@ -650,6 +652,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9340: case AR_SREV_VERSION_9340:
case AR_SREV_VERSION_9462: case AR_SREV_VERSION_9462:
case AR_SREV_VERSION_9550: case AR_SREV_VERSION_9550:
case AR_SREV_VERSION_9565:
break; break;
default: default:
ath_err(common, ath_err(common,
@ -711,7 +714,7 @@ int ath9k_hw_init(struct ath_hw *ah)
int ret; int ret;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
/* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */ /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
switch (ah->hw_version.devid) { switch (ah->hw_version.devid) {
case AR5416_DEVID_PCI: case AR5416_DEVID_PCI:
case AR5416_DEVID_PCIE: case AR5416_DEVID_PCIE:
@ -731,6 +734,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9580:
case AR9300_DEVID_AR9462: case AR9300_DEVID_AR9462:
case AR9485_DEVID_AR1111: case AR9485_DEVID_AR1111:
case AR9300_DEVID_AR9565:
break; break;
default: default:
if (common->bus_ops->ath_bus_type == ATH_USB) if (common->bus_ops->ath_bus_type == ATH_USB)
@ -803,8 +807,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
{ {
u32 pll; u32 pll;
if (AR_SREV_9485(ah)) { if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
/* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
AR_CH0_BB_DPLL2_PLL_PWD, 0x1); AR_CH0_BB_DPLL2_PLL_PWD, 0x1);
@ -915,7 +918,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
} }
pll = ath9k_hw_compute_pll_control(ah, chan); pll = ath9k_hw_compute_pll_control(ah, chan);
if (AR_SREV_9565(ah))
pll |= 0x40000;
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
@ -978,9 +982,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
else else
imr_reg |= AR_IMR_TXOK; imr_reg |= AR_IMR_TXOK;
if (opmode == NL80211_IFTYPE_AP)
imr_reg |= AR_IMR_MIB;
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_IMR, imr_reg); REG_WRITE(ah, AR_IMR, imr_reg);
@ -1778,6 +1779,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
/* Operating channel changed, reset channel calibration data */ /* Operating channel changed, reset channel calibration data */
memset(caldata, 0, sizeof(*caldata)); memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan); ath9k_init_nfcal_hist_buffer(ah, chan);
} else if (caldata) {
caldata->paprd_packet_sent = false;
} }
ah->noise = ath9k_hw_getchan_noise(ah, chan); ah->noise = ath9k_hw_getchan_noise(ah, chan);
@ -2038,7 +2041,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah)
{ {
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff); REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff);
REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff); REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff);
REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff); REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff);
@ -2405,7 +2408,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (eeval & AR5416_OPFLAGS_11G) if (eeval & AR5416_OPFLAGS_11G)
pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah)) if (AR_SREV_9485(ah) ||
AR_SREV_9285(ah) ||
AR_SREV_9330(ah) ||
AR_SREV_9565(ah))
chip_chainmask = 1; chip_chainmask = 1;
else if (AR_SREV_9462(ah)) else if (AR_SREV_9462(ah))
chip_chainmask = 3; chip_chainmask = 3;
@ -2493,7 +2499,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah)) { if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah)) if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && !AR_SREV_9565(ah))
pCap->hw_caps |= ATH9K_HW_CAP_LDPC; pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@ -2502,7 +2508,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->tx_desc_len = sizeof(struct ar9003_txc);
pCap->txs_len = sizeof(struct ar9003_txs); pCap->txs_len = sizeof(struct ar9003_txs);
if (!ah->config.paprd_disable && if (!ah->config.paprd_disable &&
ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) ah->eep_ops->get_eeprom(ah, EEP_PAPRD) &&
!AR_SREV_9462(ah))
pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
} else { } else {
pCap->tx_desc_len = sizeof(struct ath_desc); pCap->tx_desc_len = sizeof(struct ath_desc);
@ -2575,14 +2582,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->enabled_cals |= TX_IQ_ON_AGC_CAL; ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
} }
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
pCap->hw_caps |= ATH9K_HW_CAP_MCI; pCap->hw_caps |= ATH9K_HW_CAP_MCI;
if (AR_SREV_9462_20(ah)) if (AR_SREV_9462_20(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT; pCap->hw_caps |= ATH9K_HW_CAP_RTT;
} }
@ -2748,7 +2753,7 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER; bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
REG_WRITE(ah, AR_RX_FILTER, bits); REG_WRITE(ah, AR_RX_FILTER, bits);
@ -3045,7 +3050,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask); gen_tmr_configuration[timer->index].mode_mask);
if (AR_SREV_9462(ah)) { if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
/* /*
* Starting from AR9462, each generic timer can select which tsf * Starting from AR9462, each generic timer can select which tsf
* to use. But we still follow the old rule, 0 - 7 use tsf and * to use. But we still follow the old rule, 0 - 7 use tsf and
@ -3079,6 +3084,16 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask); gen_tmr_configuration[timer->index].mode_mask);
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
/*
* Need to switch back to TSF if it was using TSF2.
*/
if ((timer->index >= AR_GEN_TIMER_BANK_1_LEN)) {
REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
(1 << timer->index));
}
}
/* Disable both trigger and thresh interrupt masks */ /* Disable both trigger and thresh interrupt masks */
REG_CLR_BIT(ah, AR_IMR_S5, REG_CLR_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@ -3160,6 +3175,7 @@ static struct {
{ AR_SREV_VERSION_9485, "9485" }, { AR_SREV_VERSION_9485, "9485" },
{ AR_SREV_VERSION_9462, "9462" }, { AR_SREV_VERSION_9462, "9462" },
{ AR_SREV_VERSION_9550, "9550" }, { AR_SREV_VERSION_9550, "9550" },
{ AR_SREV_VERSION_9565, "9565" },
}; };
/* For devices with external radios */ /* For devices with external radios */

View File

@ -50,6 +50,7 @@
#define AR9300_DEVID_AR9330 0x0035 #define AR9300_DEVID_AR9330 0x0035
#define AR9300_DEVID_QCA955X 0x0038 #define AR9300_DEVID_QCA955X 0x0038
#define AR9485_DEVID_AR1111 0x0037 #define AR9485_DEVID_AR1111 0x0037
#define AR9300_DEVID_AR9565 0x0036
#define AR5416_AR9100_DEVID 0x000b #define AR5416_AR9100_DEVID 0x000b
@ -405,6 +406,7 @@ struct ath9k_hw_cal_data {
int8_t iCoff; int8_t iCoff;
int8_t qCoff; int8_t qCoff;
bool rtt_done; bool rtt_done;
bool paprd_packet_sent;
bool paprd_done; bool paprd_done;
bool nfcal_pending; bool nfcal_pending;
bool nfcal_interference; bool nfcal_interference;

View File

@ -258,7 +258,7 @@ static void setup_ht_cap(struct ath_softc *sc,
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah))
max_streams = 1; max_streams = 1;
else if (AR_SREV_9462(ah)) else if (AR_SREV_9462(ah))
max_streams = 2; max_streams = 2;

View File

@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)
int chain_ok = 0; int chain_ok = 0;
int chain; int chain;
int len = 1800; int len = 1800;
int ret;
if (!caldata) if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
return; return;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)
continue; continue;
chain_ok = 0; chain_ok = 0;
ath_dbg(common, CALIBRATE,
"Sending PAPRD frame for thermal measurement on chain %d\n",
chain);
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
ar9003_paprd_setup_gain_table(ah, chain); ar9003_paprd_setup_gain_table(ah, chain);
ath_dbg(common, CALIBRATE, ath_dbg(common, CALIBRATE,
@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)
break; break;
} }
if (ar9003_paprd_create_curve(ah, caldata, chain)) { ret = ar9003_paprd_create_curve(ah, caldata, chain);
if (ret == -EINPROGRESS) {
ath_dbg(common, CALIBRATE,
"PAPRD curve on chain %d needs to be re-trained\n",
chain);
break;
} else if (ret) {
ath_dbg(common, CALIBRATE, ath_dbg(common, CALIBRATE,
"PAPRD create curve failed on chain %d\n", "PAPRD create curve failed on chain %d\n",
chain); chain);

View File

@ -986,47 +986,21 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
int ret = 0;
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
break;
default:
ath_err(common, "Interface type %d not yet supported\n",
vif->type);
ret = -EOPNOTSUPP;
goto out;
}
if (ath9k_uses_beacons(vif->type)) {
if (sc->nbcnvifs >= ATH_BCBUF) {
ath_err(common, "Not enough beacon buffers when adding"
" new interface of type: %i\n",
vif->type);
ret = -ENOBUFS;
goto out;
}
}
ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
sc->nvifs++; sc->nvifs++;
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, vif); ath9k_calculate_summary_state(hw, vif);
ath9k_ps_restore(sc);
if (ath9k_uses_beacons(vif->type)) if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif); ath9k_beacon_assign_slot(sc, vif);
out:
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc); return 0;
return ret;
} }
static int ath9k_change_interface(struct ieee80211_hw *hw, static int ath9k_change_interface(struct ieee80211_hw *hw,
@ -1036,21 +1010,9 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
{ {
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int ret = 0;
ath_dbg(common, CONFIG, "Change Interface\n"); ath_dbg(common, CONFIG, "Change Interface\n");
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
if (ath9k_uses_beacons(new_type) &&
!ath9k_uses_beacons(vif->type)) {
if (sc->nbcnvifs >= ATH_BCBUF) {
ath_err(common, "No beacon slot available\n");
ret = -ENOBUFS;
goto out;
}
}
if (ath9k_uses_beacons(vif->type)) if (ath9k_uses_beacons(vif->type))
ath9k_beacon_remove_slot(sc, vif); ath9k_beacon_remove_slot(sc, vif);
@ -1058,14 +1020,15 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
vif->type = new_type; vif->type = new_type;
vif->p2p = p2p; vif->p2p = p2p;
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, vif); ath9k_calculate_summary_state(hw, vif);
ath9k_ps_restore(sc);
if (ath9k_uses_beacons(vif->type)) if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif); ath9k_beacon_assign_slot(sc, vif);
out:
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
return ret; return 0;
} }
static void ath9k_remove_interface(struct ieee80211_hw *hw, static void ath9k_remove_interface(struct ieee80211_hw *hw,
@ -1076,7 +1039,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "Detach Interface\n"); ath_dbg(common, CONFIG, "Detach Interface\n");
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
sc->nvifs--; sc->nvifs--;
@ -1084,10 +1046,11 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
if (ath9k_uses_beacons(vif->type)) if (ath9k_uses_beacons(vif->type))
ath9k_beacon_remove_slot(sc, vif); ath9k_beacon_remove_slot(sc, vif);
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, NULL); ath9k_calculate_summary_state(hw, NULL);
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
} }
static void ath9k_enable_ps(struct ath_softc *sc) static void ath9k_enable_ps(struct ath_softc *sc)
@ -2260,7 +2223,7 @@ static int ath9k_suspend(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
ath_cancel_work(sc); ath_cancel_work(sc);
del_timer_sync(&common->ani.timer); ath_stop_ani(sc);
del_timer_sync(&sc->rx_poll_timer); del_timer_sync(&sc->rx_poll_timer);
if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {

View File

@ -191,6 +191,23 @@ skip_tuning:
ath9k_btcoex_timer_resume(sc); ath9k_btcoex_timer_resume(sc);
} }
static void ath_mci_wait_btcal_done(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
/* Stop tx & rx */
ieee80211_stop_queues(sc->hw);
ath_stoprecv(sc);
ath_drain_all_txq(sc, false);
/* Wait for cal done */
ar9003_mci_start_reset(ah, ah->curchan);
/* Resume tx & rx */
ath_startrecv(sc);
ieee80211_wake_queues(sc->hw);
}
static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
@ -201,8 +218,8 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
switch (opcode) { switch (opcode) {
case MCI_GPM_BT_CAL_REQ: case MCI_GPM_BT_CAL_REQ:
if (mci_hw->bt_state == MCI_BT_AWAKE) { if (mci_hw->bt_state == MCI_BT_AWAKE) {
ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START); mci_hw->bt_state = MCI_BT_CAL_START;
ath9k_queue_reset(sc, RESET_TYPE_MCI); ath_mci_wait_btcal_done(sc);
} }
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state); ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
break; break;

View File

@ -38,6 +38,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
{ PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */
{ PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */
{ 0 } { 0 }
}; };

View File

@ -801,6 +801,8 @@
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_VERSION_9462 0x280 #define AR_SREV_VERSION_9462 0x280
#define AR_SREV_REVISION_9462_20 2 #define AR_SREV_REVISION_9462_20 2
#define AR_SREV_VERSION_9565 0x2C0
#define AR_SREV_REVISION_9565_10 0
#define AR_SREV_VERSION_9550 0x400 #define AR_SREV_VERSION_9550 0x400
#define AR_SREV_5416(_ah) \ #define AR_SREV_5416(_ah) \
@ -909,6 +911,13 @@
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
#define AR_SREV_9565(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
#define AR_SREV_9565_10(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
#define AR_SREV_9550(_ah) \ #define AR_SREV_9550(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550)) (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550))

View File

@ -568,7 +568,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!an->sleeping) { if (!an->sleeping) {
ath_tx_queue_tid(txq, tid); ath_tx_queue_tid(txq, tid);
if (ts->ts_status & ATH9K_TXERR_FILT) if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->ac->clear_ps_filter = true; tid->ac->clear_ps_filter = true;
} }
} }
@ -2019,6 +2019,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
if (sc->sc_ah->caldata)
sc->sc_ah->caldata->paprd_packet_sent = true;
if (!(tx_flags & ATH_TX_ERROR)) if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */ /* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK; tx_info->flags |= IEEE80211_TX_STAT_ACK;

View File

@ -55,6 +55,14 @@ config BRCMFMAC_USB
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
use the driver for an USB wireless card. use the driver for an USB wireless card.
config BRCMISCAN
bool "Broadcom I-Scan (OBSOLETE)"
depends on BRCMFMAC
---help---
This option enables the I-Scan method. By default fullmac uses the
new E-Scan method which uses less memory in firmware and gives no
limitation on the number of scan results.
config BRCMDBG config BRCMDBG
bool "Broadcom driver debug functions" bool "Broadcom driver debug functions"
depends on BRCMSMAC || BRCMFMAC depends on BRCMSMAC || BRCMFMAC

View File

@ -42,6 +42,7 @@
#define DMA_ALIGN_MASK 0x03 #define DMA_ALIGN_MASK 0x03
#define SDIO_DEVICE_ID_BROADCOM_43241 0x4324
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
@ -51,6 +52,7 @@
/* devices we support, null terminated */ /* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = { static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, {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_4330)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},

View File

@ -130,6 +130,10 @@
#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
#define BRCMF_EVENT_MSG_GROUP 0x04 #define BRCMF_EVENT_MSG_GROUP 0x04
#define BRCMF_ESCAN_REQ_VERSION 1
#define WLC_BSS_RSSI_ON_CHANNEL 0x0002
struct brcmf_event_msg { struct brcmf_event_msg {
__be16 version; __be16 version;
__be16 flags; __be16 flags;
@ -140,6 +144,8 @@ struct brcmf_event_msg {
__be32 datalen; __be32 datalen;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
u8 ifidx;
u8 bsscfgidx;
} __packed; } __packed;
struct brcm_ethhdr { struct brcm_ethhdr {
@ -454,6 +460,24 @@ struct brcmf_scan_results_le {
__le32 count; __le32 count;
}; };
struct brcmf_escan_params_le {
__le32 version;
__le16 action;
__le16 sync_id;
struct brcmf_scan_params_le params_le;
};
struct brcmf_escan_result_le {
__le32 buflen;
__le32 version;
__le16 sync_id;
__le16 bss_count;
struct brcmf_bss_info_le bss_info_le;
};
#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \
sizeof(struct brcmf_bss_info_le))
/* used for association with a specific BSSID and chanspec list */ /* used for association with a specific BSSID and chanspec list */
struct brcmf_assoc_params_le { struct brcmf_assoc_params_le {
/* 00:00:00:00:00:00: broadcast scan */ /* 00:00:00:00:00:00: broadcast scan */
@ -638,6 +662,7 @@ extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd);
/* Return pointer to interface name */ /* Return pointer to interface name */
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);

View File

@ -103,7 +103,7 @@ extern int brcmf_attach(uint bus_hdrlen, struct device *dev);
extern void brcmf_detach(struct device *dev); extern void brcmf_detach(struct device *dev);
/* Indication from bus module to change flow-control state */ /* Indication from bus module to change flow-control state */
extern void brcmf_txflowcontrol(struct device *dev, int ifidx, bool on); extern void brcmf_txflowblock(struct device *dev, bool state);
/* Notify tx completion */ /* Notify tx completion */
extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,

View File

@ -205,7 +205,8 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, { BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
BRCMF_E_IF, "IF"}, { BRCMF_E_IF, "IF"}, {
BRCMF_E_RSSI, "RSSI"}, { BRCMF_E_RSSI, "RSSI"}, {
BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT"}
}; };
uint event_type, flags, auth_type, datalen; uint event_type, flags, auth_type, datalen;
static u32 seqnum_prev; static u32 seqnum_prev;
@ -350,6 +351,11 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name); brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
break; break;
case BRCMF_E_ESCAN_RESULT:
brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
datalen = 0;
break;
case BRCMF_E_PFN_NET_FOUND: case BRCMF_E_PFN_NET_FOUND:
case BRCMF_E_PFN_NET_LOST: case BRCMF_E_PFN_NET_LOST:
case BRCMF_E_PFN_SCAN_COMPLETE: case BRCMF_E_PFN_SCAN_COMPLETE:

View File

@ -350,19 +350,23 @@ done:
return 0; return 0;
} }
void brcmf_txflowcontrol(struct device *dev, int ifidx, bool state) void brcmf_txflowblock(struct device *dev, bool state)
{ {
struct net_device *ndev; struct net_device *ndev;
struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_pub *drvr = bus_if->drvr;
int i;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
ndev = drvr->iflist[ifidx]->ndev; for (i = 0; i < BRCMF_MAX_IFS; i++)
if (state == ON) if (drvr->iflist[i]) {
netif_stop_queue(ndev); ndev = drvr->iflist[i]->ndev;
else if (state)
netif_wake_queue(ndev); netif_stop_queue(ndev);
else
netif_wake_queue(ndev);
}
} }
static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx, static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
@ -775,6 +779,14 @@ done:
return err; return err;
} }
int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd)
{
brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n",
dcmd->cmd, dcmd->buf, dcmd->len);
return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len);
}
static int brcmf_netdev_stop(struct net_device *ndev) static int brcmf_netdev_stop(struct net_device *ndev)
{ {
struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);

View File

@ -2235,8 +2235,8 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
if (bus->sdiodev->bus_if->drvr_up && if (bus->sdiodev->bus_if->drvr_up &&
(bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) && (bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
bus->txoff = OFF; bus->txoff = false;
brcmf_txflowcontrol(bus->sdiodev->dev, 0, OFF); brcmf_txflowblock(bus->sdiodev->dev, false);
} }
return cnt; return cnt;
@ -2672,8 +2672,8 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
spin_unlock_bh(&bus->txqlock); spin_unlock_bh(&bus->txqlock);
if (pktq_len(&bus->txq) >= TXHI) { if (pktq_len(&bus->txq) >= TXHI) {
bus->txoff = ON; bus->txoff = true;
brcmf_txflowcontrol(bus->sdiodev->dev, 0, ON); brcmf_txflowblock(bus->sdiodev->dev, true);
} }
#ifdef DEBUG #ifdef DEBUG
@ -3881,6 +3881,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
static bool brcmf_sdbrcm_chipmatch(u16 chipid) static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{ {
if (chipid == BCM43241_CHIP_ID)
return true;
if (chipid == BCM4329_CHIP_ID) if (chipid == BCM4329_CHIP_ID)
return true; return true;
if (chipid == BCM4330_CHIP_ID) if (chipid == BCM4330_CHIP_ID)

View File

@ -377,6 +377,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
/* Address of cores for new chips should be added here */ /* Address of cores for new chips should be added here */
switch (ci->chip) { switch (ci->chip) {
case BCM43241_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x2a084411;
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 = 0x0e004211;
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 = 0x14080401;
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 = 0x90000;
break;
case BCM4329_CHIP_ID: case BCM4329_CHIP_ID:
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;

View File

@ -66,7 +66,9 @@
#define BRCMF_USB_CBCTL_READ 1 #define BRCMF_USB_CBCTL_READ 1
#define BRCMF_USB_MAX_PKT_SIZE 1600 #define BRCMF_USB_MAX_PKT_SIZE 1600
#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin"
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin" #define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
enum usbdev_suspend_state { enum usbdev_suspend_state {
USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
@ -78,20 +80,6 @@ enum usbdev_suspend_state {
USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */ USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
}; };
struct brcmf_usb_probe_info {
void *usbdev_info;
struct usb_device *usb; /* USB device pointer from OS */
uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
int intr_size; /* Size of interrupt message */
int interval; /* Interrupt polling interval */
int vid;
int pid;
enum usb_device_speed device_speed;
enum usbdev_suspend_state suspend_state;
struct usb_interface *intf;
};
static struct brcmf_usb_probe_info usbdev_probe_info;
struct brcmf_usb_image { struct brcmf_usb_image {
void *data; void *data;
u32 len; u32 len;
@ -117,9 +105,8 @@ struct brcmf_usbdev_info {
int rx_low_watermark; int rx_low_watermark;
int tx_low_watermark; int tx_low_watermark;
int tx_high_watermark; int tx_high_watermark;
bool txoff; int tx_freecount;
bool rxoff; bool tx_flowblock;
bool txoverride;
struct brcmf_usbreq *tx_reqs; struct brcmf_usbreq *tx_reqs;
struct brcmf_usbreq *rx_reqs; struct brcmf_usbreq *rx_reqs;
@ -133,7 +120,6 @@ struct brcmf_usbdev_info {
struct usb_device *usbdev; struct usb_device *usbdev;
struct device *dev; struct device *dev;
enum usb_device_speed device_speed;
int ctl_in_pipe, ctl_out_pipe; int ctl_in_pipe, ctl_out_pipe;
struct urb *ctl_urb; /* URB for control endpoint */ struct urb *ctl_urb; /* URB for control endpoint */
@ -153,9 +139,6 @@ struct brcmf_usbdev_info {
int intr_size; /* Size of interrupt message */ int intr_size; /* Size of interrupt message */
int interval; /* Interrupt polling interval */ int interval; /* Interrupt polling interval */
struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */ struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
struct brcmf_usb_probe_info probe_info;
}; };
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
@ -177,14 +160,6 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
return brcmf_usb_get_buspub(dev)->devinfo; return brcmf_usb_get_buspub(dev)->devinfo;
} }
#if 0
static void
brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff)
{
dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff);
}
#endif
static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
uint *condition, bool *pending) uint *condition, bool *pending)
{ {
@ -366,13 +341,13 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
if (test_and_set_bit(0, &devinfo->ctl_op)) if (test_and_set_bit(0, &devinfo->ctl_op))
return -EIO; return -EIO;
devinfo->ctl_completed = false;
err = brcmf_usb_send_ctl(devinfo, buf, len); err = brcmf_usb_send_ctl(devinfo, buf, len);
if (err) { if (err) {
brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
return err; return err;
} }
devinfo->ctl_completed = false;
timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
&pending); &pending);
clear_bit(0, &devinfo->ctl_op); clear_bit(0, &devinfo->ctl_op);
@ -418,7 +393,7 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
} }
static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
struct list_head *q) struct list_head *q, int *counter)
{ {
unsigned long flags; unsigned long flags;
struct brcmf_usbreq *req; struct brcmf_usbreq *req;
@ -429,17 +404,22 @@ static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
} }
req = list_entry(q->next, struct brcmf_usbreq, list); req = list_entry(q->next, struct brcmf_usbreq, list);
list_del_init(q->next); list_del_init(q->next);
if (counter)
(*counter)--;
spin_unlock_irqrestore(&devinfo->qlock, flags); spin_unlock_irqrestore(&devinfo->qlock, flags);
return req; return req;
} }
static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo, static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
struct list_head *q, struct brcmf_usbreq *req) struct list_head *q, struct brcmf_usbreq *req,
int *counter)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&devinfo->qlock, flags); spin_lock_irqsave(&devinfo->qlock, flags);
list_add_tail(&req->list, q); list_add_tail(&req->list, q);
if (counter)
(*counter)++;
spin_unlock_irqrestore(&devinfo->qlock, flags); spin_unlock_irqrestore(&devinfo->qlock, flags);
} }
@ -519,10 +499,14 @@ static void brcmf_usb_tx_complete(struct urb *urb)
else else
devinfo->bus_pub.bus->dstats.tx_errors++; devinfo->bus_pub.bus->dstats.tx_errors++;
dev_kfree_skb(req->skb); brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL; req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
devinfo->tx_flowblock) {
brcmf_txflowblock(devinfo->dev, false);
devinfo->tx_flowblock = false;
}
} }
static void brcmf_usb_rx_complete(struct urb *urb) static void brcmf_usb_rx_complete(struct urb *urb)
@ -540,8 +524,8 @@ static void brcmf_usb_rx_complete(struct urb *urb)
devinfo->bus_pub.bus->dstats.rx_packets++; devinfo->bus_pub.bus->dstats.rx_packets++;
} else { } else {
devinfo->bus_pub.bus->dstats.rx_errors++; devinfo->bus_pub.bus->dstats.rx_errors++;
dev_kfree_skb(skb); brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
return; return;
} }
@ -551,12 +535,12 @@ static void brcmf_usb_rx_complete(struct urb *urb)
brcmf_dbg(ERROR, "rx protocol error\n"); brcmf_dbg(ERROR, "rx protocol error\n");
brcmu_pkt_buf_free_skb(skb); brcmu_pkt_buf_free_skb(skb);
devinfo->bus_pub.bus->dstats.rx_errors++; devinfo->bus_pub.bus->dstats.rx_errors++;
} else { } else
brcmf_rx_packet(devinfo->dev, ifidx, skb); brcmf_rx_packet(devinfo->dev, ifidx, skb);
brcmf_usb_rx_refill(devinfo, req); brcmf_usb_rx_refill(devinfo, req);
}
} else { } else {
dev_kfree_skb(skb); brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
} }
return; return;
@ -573,7 +557,7 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu); skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
if (!skb) { if (!skb) {
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
return; return;
} }
req->skb = skb; req->skb = skb;
@ -581,16 +565,15 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
req); req);
req->urb->transfer_flags |= URB_ZERO_PACKET;
req->devinfo = devinfo; req->devinfo = devinfo;
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);
ret = usb_submit_urb(req->urb, GFP_ATOMIC); ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (ret == 0) { if (ret) {
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); brcmf_usb_del_fromq(devinfo, req);
} else { brcmu_pkt_buf_free_skb(req->skb);
dev_kfree_skb(req->skb);
req->skb = NULL; req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
} }
return; return;
} }
@ -603,7 +586,7 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
brcmf_dbg(ERROR, "bus is not up\n"); brcmf_dbg(ERROR, "bus is not up\n");
return; return;
} }
while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL) while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
brcmf_usb_rx_refill(devinfo, req); brcmf_usb_rx_refill(devinfo, req);
} }
@ -681,27 +664,34 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
return -EIO; return -EIO;
} }
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
&devinfo->tx_freecount);
if (!req) { if (!req) {
brcmu_pkt_buf_free_skb(skb);
brcmf_dbg(ERROR, "no req to send\n"); brcmf_dbg(ERROR, "no req to send\n");
return -ENOMEM; return -ENOMEM;
} }
if (!req->urb) {
brcmf_dbg(ERROR, "no urb for req %p\n", req);
return -ENOBUFS;
}
req->skb = skb; req->skb = skb;
req->devinfo = devinfo; req->devinfo = devinfo;
usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
skb->data, skb->len, brcmf_usb_tx_complete, req); skb->data, skb->len, brcmf_usb_tx_complete, req);
req->urb->transfer_flags |= URB_ZERO_PACKET; req->urb->transfer_flags |= URB_ZERO_PACKET;
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
ret = usb_submit_urb(req->urb, GFP_ATOMIC); ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (!ret) { if (ret) {
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
} else { brcmf_usb_del_fromq(devinfo, req);
brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL; req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
&devinfo->tx_freecount);
} else {
if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
!devinfo->tx_flowblock) {
brcmf_txflowblock(dev, true);
devinfo->tx_flowblock = true;
}
} }
return ret; return ret;
@ -1112,10 +1102,14 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
static bool brcmf_usb_chip_support(int chipid, int chiprev) static bool brcmf_usb_chip_support(int chipid, int chiprev)
{ {
switch(chipid) { switch(chipid) {
case 43143:
return true;
case 43235: case 43235:
case 43236: case 43236:
case 43238: case 43238:
return (chiprev == 3); return (chiprev == 3);
case 43242:
return true;
default: default:
break; break;
} }
@ -1154,11 +1148,8 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
} }
static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub) static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
{ {
struct brcmf_usbdev_info *devinfo =
(struct brcmf_usbdev_info *)bus_pub;
brcmf_dbg(TRACE, "devinfo %p\n", devinfo); brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
/* store the image globally */ /* store the image globally */
@ -1175,7 +1166,6 @@ static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub)
kfree(devinfo->tx_reqs); kfree(devinfo->tx_reqs);
kfree(devinfo->rx_reqs); kfree(devinfo->rx_reqs);
kfree(devinfo);
} }
#define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_MAGIC 0x30524448 /* "HDR0" */
@ -1228,7 +1218,22 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
if (devinfo->image) if (devinfo->image)
return 0; return 0;
fwname = BRCMF_USB_43236_FW_NAME; switch (devinfo->bus_pub.devid) {
case 43143:
fwname = BRCMF_USB_43143_FW_NAME;
break;
case 43235:
case 43236:
case 43238:
fwname = BRCMF_USB_43236_FW_NAME;
break;
case 43242:
fwname = BRCMF_USB_43242_FW_NAME;
break;
default:
return -EINVAL;
break;
}
err = request_firmware(&fw, fwname, devinfo->dev); err = request_firmware(&fw, fwname, devinfo->dev);
if (!fw) { if (!fw) {
@ -1253,14 +1258,9 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
static static
struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
int nrxq, int ntxq)
{ {
struct brcmf_usbdev_info *devinfo;
devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC);
if (devinfo == NULL)
return NULL;
devinfo->bus_pub.nrxq = nrxq; devinfo->bus_pub.nrxq = nrxq;
devinfo->rx_low_watermark = nrxq / 2; devinfo->rx_low_watermark = nrxq / 2;
devinfo->bus_pub.devinfo = devinfo; devinfo->bus_pub.devinfo = devinfo;
@ -1269,18 +1269,6 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
/* flow control when too many tx urbs posted */ /* flow control when too many tx urbs posted */
devinfo->tx_low_watermark = ntxq / 4; devinfo->tx_low_watermark = ntxq / 4;
devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3; devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3;
devinfo->dev = dev;
devinfo->usbdev = usbdev_probe_info.usb;
devinfo->tx_pipe = usbdev_probe_info.tx_pipe;
devinfo->rx_pipe = usbdev_probe_info.rx_pipe;
devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2;
devinfo->intr_pipe = usbdev_probe_info.intr_pipe;
devinfo->interval = usbdev_probe_info.interval;
devinfo->intr_size = usbdev_probe_info.intr_size;
memcpy(&devinfo->probe_info, &usbdev_probe_info,
sizeof(struct brcmf_usb_probe_info));
devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE; devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE;
/* Initialize other structure content */ /* Initialize other structure content */
@ -1295,6 +1283,8 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
INIT_LIST_HEAD(&devinfo->tx_freeq); INIT_LIST_HEAD(&devinfo->tx_freeq);
INIT_LIST_HEAD(&devinfo->tx_postq); INIT_LIST_HEAD(&devinfo->tx_postq);
devinfo->tx_flowblock = false;
devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq); devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
if (!devinfo->rx_reqs) if (!devinfo->rx_reqs)
goto error; goto error;
@ -1302,6 +1292,7 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq); devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
if (!devinfo->tx_reqs) if (!devinfo->tx_reqs)
goto error; goto error;
devinfo->tx_freecount = ntxq;
devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC); devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->intr_urb) { if (!devinfo->intr_urb) {
@ -1336,19 +1327,19 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
error: error:
brcmf_dbg(ERROR, "failed!\n"); brcmf_dbg(ERROR, "failed!\n");
brcmf_usb_detach(&devinfo->bus_pub); brcmf_usb_detach(devinfo);
return NULL; return NULL;
} }
static int brcmf_usb_probe_cb(struct device *dev, const char *desc, static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
u32 bustype, u32 hdrlen) const char *desc, u32 bustype, u32 hdrlen)
{ {
struct brcmf_bus *bus = NULL; struct brcmf_bus *bus = NULL;
struct brcmf_usbdev *bus_pub = NULL; struct brcmf_usbdev *bus_pub = NULL;
int ret; int ret;
struct device *dev = devinfo->dev;
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev);
if (!bus_pub) { if (!bus_pub) {
ret = -ENODEV; ret = -ENODEV;
goto fail; goto fail;
@ -1387,23 +1378,21 @@ static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
return 0; return 0;
fail: fail:
/* Release resources in reverse order */ /* Release resources in reverse order */
if (bus_pub)
brcmf_usb_detach(bus_pub);
kfree(bus); kfree(bus);
brcmf_usb_detach(devinfo);
return ret; return ret;
} }
static void static void
brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub) brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
{ {
if (!bus_pub) if (!devinfo)
return; return;
brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub); brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
brcmf_detach(bus_pub->devinfo->dev);
kfree(bus_pub->bus);
brcmf_usb_detach(bus_pub);
brcmf_detach(devinfo->dev);
kfree(devinfo->bus_pub.bus);
brcmf_usb_detach(devinfo);
} }
static int static int
@ -1415,18 +1404,18 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_device *usb = interface_to_usbdev(intf); struct usb_device *usb = interface_to_usbdev(intf);
int num_of_eps; int num_of_eps;
u8 endpoint_num; u8 endpoint_num;
struct brcmf_usbdev_info *devinfo;
brcmf_dbg(TRACE, "enter\n"); brcmf_dbg(TRACE, "enter\n");
usbdev_probe_info.usb = usb; devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
usbdev_probe_info.intf = intf; if (devinfo == NULL)
return -ENOMEM;
if (id != NULL) { devinfo->usbdev = usb;
usbdev_probe_info.vid = id->idVendor; devinfo->dev = &usb->dev;
usbdev_probe_info.pid = id->idProduct;
}
usb_set_intfdata(intf, &usbdev_probe_info); usb_set_intfdata(intf, devinfo);
/* Check that the device supports only one configuration */ /* Check that the device supports only one configuration */
if (usb->descriptor.bNumConfigurations != 1) { if (usb->descriptor.bNumConfigurations != 1) {
@ -1475,11 +1464,11 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
} }
endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num); devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num);
usbdev_probe_info.rx_pipe = 0; devinfo->rx_pipe = 0;
usbdev_probe_info.rx_pipe2 = 0; devinfo->rx_pipe2 = 0;
usbdev_probe_info.tx_pipe = 0; devinfo->tx_pipe = 0;
num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
/* Check data endpoints and get pipes */ /* Check data endpoints and get pipes */
@ -1496,35 +1485,33 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
USB_ENDPOINT_NUMBER_MASK; USB_ENDPOINT_NUMBER_MASK;
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
== USB_DIR_IN) { == USB_DIR_IN) {
if (!usbdev_probe_info.rx_pipe) { if (!devinfo->rx_pipe) {
usbdev_probe_info.rx_pipe = devinfo->rx_pipe =
usb_rcvbulkpipe(usb, endpoint_num); usb_rcvbulkpipe(usb, endpoint_num);
} else { } else {
usbdev_probe_info.rx_pipe2 = devinfo->rx_pipe2 =
usb_rcvbulkpipe(usb, endpoint_num); usb_rcvbulkpipe(usb, endpoint_num);
} }
} else { } else {
usbdev_probe_info.tx_pipe = devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num);
usb_sndbulkpipe(usb, endpoint_num);
} }
} }
/* Allocate interrupt URB and data buffer */ /* Allocate interrupt URB and data buffer */
/* RNDIS says 8-byte intr, our old drivers used 4-byte */ /* RNDIS says 8-byte intr, our old drivers used 4-byte */
if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
usbdev_probe_info.intr_size = 8; devinfo->intr_size = 8;
else else
usbdev_probe_info.intr_size = 4; devinfo->intr_size = 4;
usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
usbdev_probe_info.device_speed = usb->speed;
if (usb->speed == USB_SPEED_HIGH) if (usb->speed == USB_SPEED_HIGH)
brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n"); brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
else else
brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n"); brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0); ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0);
if (ret) if (ret)
goto fail; goto fail;
@ -1533,6 +1520,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
fail: fail:
brcmf_dbg(ERROR, "failed with errno %d\n", ret); brcmf_dbg(ERROR, "failed with errno %d\n", ret);
kfree(devinfo);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
return ret; return ret;
@ -1541,11 +1529,12 @@ fail:
static void static void
brcmf_usb_disconnect(struct usb_interface *intf) brcmf_usb_disconnect(struct usb_interface *intf)
{ {
struct usb_device *usb = interface_to_usbdev(intf); struct brcmf_usbdev_info *devinfo;
brcmf_dbg(TRACE, "enter\n"); brcmf_dbg(TRACE, "enter\n");
brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev)); devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL); brcmf_usb_disconnect_cb(devinfo);
kfree(devinfo);
} }
/* /*
@ -1577,17 +1566,23 @@ static int brcmf_usb_resume(struct usb_interface *intf)
} }
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c #define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
#define BRCMF_USB_DEVICE_ID_43236 0xbd17 #define BRCMF_USB_DEVICE_ID_43236 0xbd17
#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc #define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
static struct usb_device_id brcmf_usb_devid_table[] = { static struct usb_device_id brcmf_usb_devid_table[] = {
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) },
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) },
/* special entry for device with firmware loaded and running */ /* special entry for device with firmware loaded and running */
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
{ } { }
}; };
MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
/* TODO: suspend and resume entries */ /* TODO: suspend and resume entries */
static struct usb_driver brcmf_usbdrvr = { static struct usb_driver brcmf_usbdrvr = {

View File

@ -28,6 +28,7 @@
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
#include <net/netlink.h>
#include <brcmu_utils.h> #include <brcmu_utils.h>
#include <defs.h> #include <defs.h>
@ -489,8 +490,8 @@ static void brcmf_set_mpc(struct net_device *ndev, int mpc)
} }
} }
static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
struct brcmf_ssid *ssid) struct brcmf_ssid *ssid)
{ {
memcpy(params_le->bssid, ether_bcast, ETH_ALEN); memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
params_le->bss_type = DOT11_BSSTYPE_ANY; params_le->bss_type = DOT11_BSSTYPE_ANY;
@ -544,7 +545,7 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
return -ENOMEM; return -ENOMEM;
BUG_ON(params_size >= BRCMF_DCMD_SMLEN); BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
wl_iscan_prep(&params->params_le, ssid); brcmf_iscan_prep(&params->params_le, ssid);
params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION); params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
params->action = cpu_to_le16(action); params->action = cpu_to_le16(action);
@ -597,9 +598,9 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
} }
static s32 static s32
__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request, struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid) struct cfg80211_ssid *this_ssid)
{ {
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids; struct cfg80211_ssid *ssids;
@ -690,11 +691,342 @@ scan_out:
return err; return err;
} }
static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
struct cfg80211_scan_request *request)
{
u32 n_ssids;
u32 n_channels;
s32 i;
s32 offset;
__le16 chanspec;
u16 channel;
struct ieee80211_channel *req_channel;
char *ptr;
struct brcmf_ssid ssid;
memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
params_le->bss_type = DOT11_BSSTYPE_ANY;
params_le->scan_type = 0;
params_le->channel_num = 0;
params_le->nprobes = cpu_to_le32(-1);
params_le->active_time = cpu_to_le32(-1);
params_le->passive_time = cpu_to_le32(-1);
params_le->home_time = cpu_to_le32(-1);
memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
/* if request is null exit so it will be all channel broadcast scan */
if (!request)
return;
n_ssids = request->n_ssids;
n_channels = request->n_channels;
/* Copy channel array if applicable */
WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
chanspec = 0;
req_channel = request->channels[i];
channel = ieee80211_frequency_to_channel(
req_channel->center_freq);
if (req_channel->band == IEEE80211_BAND_2GHZ)
chanspec |= WL_CHANSPEC_BAND_2G;
else
chanspec |= WL_CHANSPEC_BAND_5G;
if (req_channel->flags & IEEE80211_CHAN_NO_HT40) {
chanspec |= WL_CHANSPEC_BW_20;
chanspec |= WL_CHANSPEC_CTL_SB_NONE;
} else {
chanspec |= WL_CHANSPEC_BW_40;
if (req_channel->flags &
IEEE80211_CHAN_NO_HT40PLUS)
chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
else
chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
}
params_le->channel_list[i] =
(channel & WL_CHANSPEC_CHAN_MASK) |
chanspec;
WL_SCAN("Chan : %d, Channel spec: %x\n",
channel, params_le->channel_list[i]);
params_le->channel_list[i] =
cpu_to_le16(params_le->channel_list[i]);
}
} else {
WL_SCAN("Scanning all channels\n");
}
/* Copy ssid array if applicable */
WL_SCAN("### List of SSIDs to scan ### %d\n", n_ssids);
if (n_ssids > 0) {
offset = offsetof(struct brcmf_scan_params_le, channel_list) +
n_channels * sizeof(u16);
offset = roundup(offset, sizeof(u32));
ptr = (char *)params_le + offset;
for (i = 0; i < n_ssids; i++) {
memset(&ssid, 0, sizeof(ssid));
ssid.SSID_len = cpu_to_le32(request->ssids[i].ssid_len);
memcpy(ssid.SSID, request->ssids[i].ssid,
request->ssids[i].ssid_len);
if (!ssid.SSID_len)
WL_SCAN("%d: Broadcast scan\n", i);
else
WL_SCAN("%d: scan for %s size =%d\n", i,
ssid.SSID, ssid.SSID_len);
memcpy(ptr, &ssid, sizeof(ssid));
ptr += sizeof(ssid);
}
} else {
WL_SCAN("Broadcast scan %p\n", request->ssids);
if ((request->ssids) && request->ssids->ssid_len) {
WL_SCAN("SSID %s len=%d\n", params_le->ssid_le.SSID,
request->ssids->ssid_len);
params_le->ssid_le.SSID_len =
cpu_to_le32(request->ssids->ssid_len);
memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
request->ssids->ssid_len);
}
}
/* Adding mask to channel numbers */
params_le->channel_num =
cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
}
static s32
brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
bool aborted, bool fw_abort)
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
s32 err = 0;
WL_SCAN("Enter\n");
/* clear scan request, because the FW abort can cause a second call */
/* to this functon and might cause a double cfg80211_scan_done */
scan_request = cfg_priv->scan_request;
cfg_priv->scan_request = NULL;
if (timer_pending(&cfg_priv->escan_timeout))
del_timer_sync(&cfg_priv->escan_timeout);
if (fw_abort) {
/* Do a scan abort to stop the driver's scan engine */
WL_SCAN("ABORT scan in firmware\n");
memset(&params_le, 0, sizeof(params_le));
memcpy(params_le.bssid, ether_bcast, ETH_ALEN);
params_le.bss_type = DOT11_BSSTYPE_ANY;
params_le.scan_type = 0;
params_le.channel_num = cpu_to_le32(1);
params_le.nprobes = cpu_to_le32(1);
params_le.active_time = cpu_to_le32(-1);
params_le.passive_time = cpu_to_le32(-1);
params_le.home_time = cpu_to_le32(-1);
/* Scan is aborted by setting channel_list[0] to -1 */
params_le.channel_list[0] = cpu_to_le16(-1);
/* E-Scan (or anyother type) can be aborted by SCAN */
err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &params_le,
sizeof(params_le));
if (err)
WL_ERR("Scan abort failed\n");
}
if (scan_request) {
WL_SCAN("ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
brcmf_set_mpc(ndev, 1);
}
if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scan complete while device not scanning\n");
return -EPERM;
}
return err;
}
static s32
brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev,
struct cfg80211_scan_request *request, u16 action)
{
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
offsetof(struct brcmf_escan_params_le, params_le);
struct brcmf_escan_params_le *params;
s32 err = 0;
WL_SCAN("E-SCAN START\n");
if (request != NULL) {
/* Allocate space for populating ssids in struct */
params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
/* Allocate space for populating ssids in struct */
params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
}
params = kzalloc(params_size, GFP_KERNEL);
if (!params) {
err = -ENOMEM;
goto exit;
}
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
brcmf_escan_prep(&params->params_le, request);
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
params->action = cpu_to_le16(action);
params->sync_id = cpu_to_le16(0x1234);
err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size,
cfg_priv->escan_ioctl_buf, BRCMF_DCMD_MEDLEN);
if (err) {
if (err == -EBUSY)
WL_INFO("system busy : escan canceled\n");
else
WL_ERR("error (%d)\n", err);
}
kfree(params);
exit:
return err;
}
static s32
brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy,
struct net_device *ndev, struct cfg80211_scan_request *request)
{
s32 err;
__le32 passive_scan;
struct brcmf_scan_results *results;
WL_SCAN("Enter\n");
cfg_priv->escan_info.ndev = ndev;
cfg_priv->escan_info.wiphy = wiphy;
cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
if (err) {
WL_ERR("error (%d)\n", err);
return err;
}
brcmf_set_mpc(ndev, 0);
results = (struct brcmf_scan_results *)cfg_priv->escan_info.escan_buf;
results->version = 0;
results->count = 0;
results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
err = brcmf_run_escan(cfg_priv, ndev, request, WL_ESCAN_ACTION_START);
if (err)
brcmf_set_mpc(ndev, 1);
return err;
}
static s32
brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid)
{
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids;
struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
__le32 passive_scan;
bool escan_req;
bool spec_scan;
s32 err;
u32 SSID_len;
WL_SCAN("START ESCAN\n");
if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
return -EAGAIN;
}
if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
WL_ERR("Scanning being aborted : status (%lu)\n",
cfg_priv->status);
return -EAGAIN;
}
if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
WL_ERR("Connecting : status (%lu)\n",
cfg_priv->status);
return -EAGAIN;
}
/* Arm scan timeout timer */
mod_timer(&cfg_priv->escan_timeout, jiffies +
WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
escan_req = false;
if (request) {
/* scan bss */
ssids = request->ssids;
escan_req = true;
} else {
/* scan in ibss */
/* we don't do escan in ibss */
ssids = this_ssid;
}
cfg_priv->scan_request = request;
set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
if (escan_req) {
err = brcmf_do_escan(cfg_priv, wiphy, ndev, request);
if (!err)
return err;
else
goto scan_out;
} else {
WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
ssids->ssid, ssids->ssid_len);
memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
sr->ssid_le.SSID_len = cpu_to_le32(0);
spec_scan = false;
if (SSID_len) {
memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
spec_scan = true;
} else
WL_SCAN("Broadcast scan\n");
passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
if (err) {
WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
brcmf_set_mpc(ndev, 0);
err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
sizeof(sr->ssid_le));
if (err) {
if (err == -EBUSY)
WL_INFO("BUSY: scan for \"%s\" canceled\n",
sr->ssid_le.SSID);
else
WL_ERR("WLC_SCAN error (%d)\n", err);
brcmf_set_mpc(ndev, 1);
goto scan_out;
}
}
return 0;
scan_out:
clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
if (timer_pending(&cfg_priv->escan_timeout))
del_timer_sync(&cfg_priv->escan_timeout);
cfg_priv->scan_request = NULL;
return err;
}
static s32 static s32
brcmf_cfg80211_scan(struct wiphy *wiphy, brcmf_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request) struct cfg80211_scan_request *request)
{ {
struct net_device *ndev = request->wdev->netdev; struct net_device *ndev = request->wdev->netdev;
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
s32 err = 0; s32 err = 0;
WL_TRACE("Enter\n"); WL_TRACE("Enter\n");
@ -702,7 +1034,11 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
if (!check_sys_up(wiphy)) if (!check_sys_up(wiphy))
return -EIO; return -EIO;
err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL); if (cfg_priv->iscan_on)
err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
else if (cfg_priv->escan_on)
err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
if (err) if (err)
WL_ERR("scan error (%d)\n", err); WL_ERR("scan error (%d)\n", err);
@ -1876,16 +2212,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
} }
if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
scb_val.val = cpu_to_le32(0); memset(&scb_val, 0, sizeof(scb_val));
err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
sizeof(struct brcmf_scb_val_le)); sizeof(struct brcmf_scb_val_le));
if (err) if (err) {
WL_ERR("Could not get rssi (%d)\n", err); WL_ERR("Could not get rssi (%d)\n", err);
} else {
rssi = le32_to_cpu(scb_val.val); rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL; sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi; sinfo->signal = rssi;
WL_CONN("RSSI %d dBm\n", rssi); WL_CONN("RSSI %d dBm\n", rssi);
}
} }
done: done:
@ -2470,6 +2807,175 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
return err; return err;
} }
static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
{
struct brcmf_cfg80211_priv *cfg_priv =
container_of(work, struct brcmf_cfg80211_priv,
escan_timeout_work);
brcmf_notify_escan_complete(cfg_priv,
cfg_priv->escan_info.ndev, true, true);
}
static void brcmf_escan_timeout(unsigned long data)
{
struct brcmf_cfg80211_priv *cfg_priv =
(struct brcmf_cfg80211_priv *)data;
if (cfg_priv->scan_request) {
WL_ERR("timer expired\n");
if (cfg_priv->escan_on)
schedule_work(&cfg_priv->escan_timeout_work);
}
}
static s32
brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
struct brcmf_bss_info_le *bss_info_le)
{
if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
(CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
bss_info_le->SSID_len == bss->SSID_len &&
!memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
(bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
/* preserve max RSSI if the measurements are
* both on-channel or both off-channel
*/
if (bss_info_le->RSSI > bss->RSSI)
bss->RSSI = bss_info_le->RSSI;
} else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
(bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
/* preserve the on-channel rssi measurement
* if the new measurement is off channel
*/
bss->RSSI = bss_info_le->RSSI;
bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
}
return 1;
}
return 0;
}
static s32
brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
s32 status;
s32 err = 0;
struct brcmf_escan_result_le *escan_result_le;
struct brcmf_bss_info_le *bss_info_le;
struct brcmf_bss_info_le *bss = NULL;
u32 bi_length;
struct brcmf_scan_results *list;
u32 i;
status = be32_to_cpu(e->status);
if (!ndev || !cfg_priv->escan_on ||
!test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
ndev, cfg_priv->escan_on,
!test_bit(WL_STATUS_SCANNING, &cfg_priv->status));
return -EPERM;
}
if (status == BRCMF_E_STATUS_PARTIAL) {
WL_SCAN("ESCAN Partial result\n");
escan_result_le = (struct brcmf_escan_result_le *) data;
if (!escan_result_le) {
WL_ERR("Invalid escan result (NULL pointer)\n");
goto exit;
}
if (!cfg_priv->scan_request) {
WL_SCAN("result without cfg80211 request\n");
goto exit;
}
if (le16_to_cpu(escan_result_le->bss_count) != 1) {
WL_ERR("Invalid bss_count %d: ignoring\n",
escan_result_le->bss_count);
goto exit;
}
bss_info_le = &escan_result_le->bss_info_le;
bi_length = le32_to_cpu(bss_info_le->length);
if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
WL_ESCAN_RESULTS_FIXED_SIZE)) {
WL_ERR("Invalid bss_info length %d: ignoring\n",
bi_length);
goto exit;
}
if (!(cfg_to_wiphy(cfg_priv)->interface_modes &
BIT(NL80211_IFTYPE_ADHOC))) {
if (le16_to_cpu(bss_info_le->capability) &
WLAN_CAPABILITY_IBSS) {
WL_ERR("Ignoring IBSS result\n");
goto exit;
}
}
list = (struct brcmf_scan_results *)
cfg_priv->escan_info.escan_buf;
if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
WL_ERR("Buffer is too small: ignoring\n");
goto exit;
}
for (i = 0; i < list->count; i++) {
bss = bss ? (struct brcmf_bss_info_le *)
((unsigned char *)bss +
le32_to_cpu(bss->length)) : list->bss_info_le;
if (brcmf_compare_update_same_bss(bss, bss_info_le))
goto exit;
}
memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]),
bss_info_le, bi_length);
list->version = le32_to_cpu(bss_info_le->version);
list->buflen += bi_length;
list->count++;
} else {
cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (cfg_priv->scan_request) {
cfg_priv->bss_list = (struct brcmf_scan_results *)
cfg_priv->escan_info.escan_buf;
brcmf_inform_bss(cfg_priv);
if (status == BRCMF_E_STATUS_SUCCESS) {
WL_SCAN("ESCAN Completed\n");
brcmf_notify_escan_complete(cfg_priv, ndev,
false, false);
} else {
WL_ERR("ESCAN Aborted, Event 0x%x\n", status);
brcmf_notify_escan_complete(cfg_priv, ndev,
true, false);
}
brcmf_set_mpc(ndev, 1);
} else
WL_ERR("Unexpected scan result 0x%x\n", status);
}
exit:
return err;
}
static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv)
{
if (cfg_priv->escan_on) {
cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] =
brcmf_cfg80211_escan_handler;
cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
/* Init scan_timeout timer */
init_timer(&cfg_priv->escan_timeout);
cfg_priv->escan_timeout.data = (unsigned long) cfg_priv;
cfg_priv->escan_timeout.function = brcmf_escan_timeout;
INIT_WORK(&cfg_priv->escan_timeout_work,
brcmf_cfg80211_escan_timeout_worker);
}
}
static __always_inline void brcmf_delay(u32 ms) static __always_inline void brcmf_delay(u32 ms)
{ {
if (ms < 1000 / HZ) { if (ms < 1000 / HZ) {
@ -2545,10 +3051,8 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
/* Turn off watchdog timer */ /* Turn off watchdog timer */
if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { if (test_bit(WL_STATUS_READY, &cfg_priv->status))
WL_INFO("Enable MPC\n");
brcmf_set_mpc(ndev, 1); brcmf_set_mpc(ndev, 1);
}
WL_TRACE("Exit\n"); WL_TRACE("Exit\n");
@ -2723,6 +3227,25 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
} }
#ifdef CONFIG_NL80211_TESTMODE
static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_priv->wdev->netdev;
struct brcmf_dcmd *dcmd = data;
struct sk_buff *reply;
int ret;
ret = brcmf_netlink_dcmd(ndev, dcmd);
if (ret == 0) {
reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
ret = cfg80211_testmode_reply(reply);
}
return ret;
}
#endif
static struct cfg80211_ops wl_cfg80211_ops = { static struct cfg80211_ops wl_cfg80211_ops = {
.change_virtual_intf = brcmf_cfg80211_change_iface, .change_virtual_intf = brcmf_cfg80211_change_iface,
.scan = brcmf_cfg80211_scan, .scan = brcmf_cfg80211_scan,
@ -2745,7 +3268,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.resume = brcmf_cfg80211_resume, .resume = brcmf_cfg80211_resume,
.set_pmksa = brcmf_cfg80211_set_pmksa, .set_pmksa = brcmf_cfg80211_set_pmksa,
.del_pmksa = brcmf_cfg80211_del_pmksa, .del_pmksa = brcmf_cfg80211_del_pmksa,
.flush_pmksa = brcmf_cfg80211_flush_pmksa .flush_pmksa = brcmf_cfg80211_flush_pmksa,
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode
#endif
}; };
static s32 brcmf_mode_to_nl80211_iftype(s32 mode) static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
@ -3170,10 +3696,8 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
err = brcmf_inform_bss(cfg_priv); err = brcmf_inform_bss(cfg_priv);
if (err) { if (err)
scan_abort = true; scan_abort = true;
goto scan_done_out;
}
scan_done_out: scan_done_out:
if (cfg_priv->scan_request) { if (cfg_priv->scan_request) {
@ -3220,6 +3744,8 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
cfg_priv->profile = NULL; cfg_priv->profile = NULL;
kfree(cfg_priv->scan_req_int); kfree(cfg_priv->scan_req_int);
cfg_priv->scan_req_int = NULL; cfg_priv->scan_req_int = NULL;
kfree(cfg_priv->escan_ioctl_buf);
cfg_priv->escan_ioctl_buf = NULL;
kfree(cfg_priv->dcmd_buf); kfree(cfg_priv->dcmd_buf);
cfg_priv->dcmd_buf = NULL; cfg_priv->dcmd_buf = NULL;
kfree(cfg_priv->extra_buf); kfree(cfg_priv->extra_buf);
@ -3248,6 +3774,9 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
GFP_KERNEL); GFP_KERNEL);
if (!cfg_priv->scan_req_int) if (!cfg_priv->scan_req_int)
goto init_priv_mem_out; goto init_priv_mem_out;
cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
if (!cfg_priv->escan_ioctl_buf)
goto init_priv_mem_out;
cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
if (!cfg_priv->dcmd_buf) if (!cfg_priv->dcmd_buf)
goto init_priv_mem_out; goto init_priv_mem_out;
@ -3297,18 +3826,28 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event(
static s32 static s32
brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
const struct brcmf_event_msg *msg) const struct brcmf_event_msg *msg, void *data)
{ {
struct brcmf_cfg80211_event_q *e; struct brcmf_cfg80211_event_q *e;
s32 err = 0; s32 err = 0;
ulong flags; ulong flags;
u32 data_len;
u32 total_len;
e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC); total_len = sizeof(struct brcmf_cfg80211_event_q);
if (data)
data_len = be32_to_cpu(msg->datalen);
else
data_len = 0;
total_len += data_len;
e = kzalloc(total_len, GFP_ATOMIC);
if (!e) if (!e)
return -ENOMEM; return -ENOMEM;
e->etype = event; e->etype = event;
memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
if (data)
memcpy(&e->edata, data, data_len);
spin_lock_irqsave(&cfg_priv->evt_q_lock, flags); spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
@ -3374,8 +3913,17 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
cfg_priv->scan_request = NULL; cfg_priv->scan_request = NULL;
cfg_priv->pwr_save = true; cfg_priv->pwr_save = true;
#ifdef CONFIG_BRCMISCAN
cfg_priv->iscan_on = true; /* iscan on & off switch. cfg_priv->iscan_on = true; /* iscan on & off switch.
we enable iscan per default */ we enable iscan per default */
cfg_priv->escan_on = false; /* escan on & off switch.
we disable escan per default */
#else
cfg_priv->iscan_on = false; /* iscan on & off switch.
we disable iscan per default */
cfg_priv->escan_on = true; /* escan on & off switch.
we enable escan per default */
#endif
cfg_priv->roam_on = true; /* roam on & off switch. cfg_priv->roam_on = true; /* roam on & off switch.
we enable roam per default */ we enable roam per default */
@ -3393,6 +3941,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
err = brcmf_init_iscan(cfg_priv); err = brcmf_init_iscan(cfg_priv);
if (err) if (err)
return err; return err;
brcmf_init_escan(cfg_priv);
brcmf_init_conf(cfg_priv->conf); brcmf_init_conf(cfg_priv->conf);
brcmf_init_prof(cfg_priv->profile); brcmf_init_prof(cfg_priv->profile);
brcmf_link_down(cfg_priv); brcmf_link_down(cfg_priv);
@ -3477,7 +4026,7 @@ brcmf_cfg80211_event(struct net_device *ndev,
u32 event_type = be32_to_cpu(e->event_type); u32 event_type = be32_to_cpu(e->event_type);
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
if (!brcmf_enq_event(cfg_priv, event_type, e)) if (!brcmf_enq_event(cfg_priv, event_type, e, data))
schedule_work(&cfg_priv->event_work); schedule_work(&cfg_priv->event_work);
} }
@ -3551,6 +4100,7 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, BRCMF_E_TXFAIL); setbit(eventmask, BRCMF_E_TXFAIL);
setbit(eventmask, BRCMF_E_JOIN_START); setbit(eventmask, BRCMF_E_JOIN_START);
setbit(eventmask, BRCMF_E_SCAN_COMPLETE); setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
setbit(eventmask, BRCMF_E_ESCAN_RESULT);
brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
iovbuf, sizeof(iovbuf)); iovbuf, sizeof(iovbuf));

View File

@ -123,6 +123,13 @@ do { \
#define WL_SCAN_UNASSOC_TIME 40 #define WL_SCAN_UNASSOC_TIME 40
#define WL_SCAN_PASSIVE_TIME 120 #define WL_SCAN_PASSIVE_TIME 120
#define WL_ESCAN_BUF_SIZE (1024 * 64)
#define WL_ESCAN_TIMER_INTERVAL_MS 8000 /* E-Scan timeout */
#define WL_ESCAN_ACTION_START 1
#define WL_ESCAN_ACTION_CONTINUE 2
#define WL_ESCAN_ACTION_ABORT 3
/* dongle status */ /* dongle status */
enum wl_status { enum wl_status {
WL_STATUS_READY, WL_STATUS_READY,
@ -275,6 +282,19 @@ struct brcmf_cfg80211_pmk_list {
struct pmkid foo[MAXPMKID - 1]; struct pmkid foo[MAXPMKID - 1];
}; };
/* dongle escan state */
enum wl_escan_state {
WL_ESCAN_STATE_IDLE,
WL_ESCAN_STATE_SCANNING
};
struct escan_info {
u32 escan_state;
u8 escan_buf[WL_ESCAN_BUF_SIZE];
struct wiphy *wiphy;
struct net_device *ndev;
};
/* dongle private data of cfg80211 interface */ /* dongle private data of cfg80211 interface */
struct brcmf_cfg80211_priv { struct brcmf_cfg80211_priv {
struct wireless_dev *wdev; /* representing wl cfg80211 device */ struct wireless_dev *wdev; /* representing wl cfg80211 device */
@ -315,6 +335,11 @@ struct brcmf_cfg80211_priv {
u8 *dcmd_buf; /* dcmd buffer */ u8 *dcmd_buf; /* dcmd buffer */
u8 *extra_buf; /* maily to grab assoc information */ u8 *extra_buf; /* maily to grab assoc information */
struct dentry *debugfsdir; struct dentry *debugfsdir;
bool escan_on; /* escan on/off switch */
struct escan_info escan_info; /* escan information */
struct timer_list escan_timeout; /* Timer for catch scan timeout */
struct work_struct escan_timeout_work; /* scan timeout worker */
u8 *escan_ioctl_buf;
u8 ci[0] __aligned(NETDEV_ALIGN); u8 ci[0] __aligned(NETDEV_ALIGN);
}; };

View File

@ -535,9 +535,6 @@ void ai_detach(struct si_pub *sih)
{ {
struct si_info *sii; struct si_info *sii;
struct si_pub *si_local = NULL;
memcpy(&si_local, &sih, sizeof(struct si_pub **));
sii = container_of(sih, struct si_info, pub); sii = container_of(sih, struct si_info, pub);
if (sii == NULL) if (sii == NULL)

View File

@ -34,6 +34,7 @@
#define BCM43235_CHIP_ID 43235 #define BCM43235_CHIP_ID 43235
#define BCM43236_CHIP_ID 43236 #define BCM43236_CHIP_ID 43236
#define BCM43238_CHIP_ID 43238 #define BCM43238_CHIP_ID 43238
#define BCM43241_CHIP_ID 0x4324
#define BCM4329_CHIP_ID 0x4329 #define BCM4329_CHIP_ID 0x4329
#define BCM4330_CHIP_ID 0x4330 #define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331 #define BCM4331_CHIP_ID 0x4331

View File

@ -4,6 +4,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/etherdevice.h>
#include "hostap_wlan.h" #include "hostap_wlan.h"
#include "hostap.h" #include "hostap.h"
#include "hostap_ap.h" #include "hostap_ap.h"
@ -463,8 +464,7 @@ static void handle_info_queue_scanresults(local_info_t *local)
prism2_host_roaming(local); prism2_host_roaming(local);
if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA && if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA &&
memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00", !is_zero_ether_addr(local->preferred_ap)) {
ETH_ALEN) != 0) {
/* /*
* Firmware seems to be getting into odd state in host_roaming * Firmware seems to be getting into odd state in host_roaming
* mode 2 when hostscan is used without join command, so try * mode 2 when hostscan is used without join command, so try

View File

@ -6,6 +6,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/etherdevice.h>
#include <net/lib80211.h> #include <net/lib80211.h>
#include "hostap_wlan.h" #include "hostap_wlan.h"
@ -3221,8 +3222,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
return -EINVAL; return -EINVAL;
addr = ext->addr.sa_data; addr = ext->addr.sa_data;
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && if (is_broadcast_ether_addr(addr)) {
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
sta_ptr = NULL; sta_ptr = NULL;
crypt = &local->crypt_info.crypt[i]; crypt = &local->crypt_info.crypt[i];
} else { } else {
@ -3394,8 +3394,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
i--; i--;
addr = ext->addr.sa_data; addr = ext->addr.sa_data;
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && if (is_broadcast_ether_addr(addr)) {
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
sta_ptr = NULL; sta_ptr = NULL;
crypt = &local->crypt_info.crypt[i]; crypt = &local->crypt_info.crypt[i];
} else { } else {
@ -3458,9 +3457,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
param->u.crypt.key_len) param->u.crypt.key_len)
return -EINVAL; return -EINVAL;
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && if (is_broadcast_ether_addr(param->sta_addr)) {
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
if (param->u.crypt.idx >= WEP_KEYS) if (param->u.crypt.idx >= WEP_KEYS)
return -EINVAL; return -EINVAL;
sta_ptr = NULL; sta_ptr = NULL;
@ -3593,9 +3590,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
if (max_key_len < 0) if (max_key_len < 0)
return -EINVAL; return -EINVAL;
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && if (is_broadcast_ether_addr(param->sta_addr)) {
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
sta_ptr = NULL; sta_ptr = NULL;
if (param->u.crypt.idx >= WEP_KEYS) if (param->u.crypt.idx >= WEP_KEYS)
param->u.crypt.idx = local->crypt_info.tx_keyidx; param->u.crypt.idx = local->crypt_info.tx_keyidx;

View File

@ -1084,7 +1084,7 @@ int prism2_sta_deauth(local_info_t *local, u16 reason)
__le16 val = cpu_to_le16(reason); __le16 val = cpu_to_le16(reason);
if (local->iw_mode != IW_MODE_INFRA || if (local->iw_mode != IW_MODE_INFRA ||
memcmp(local->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 || is_zero_ether_addr(local->bssid) ||
memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0) memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0)
return 0; return 0;

View File

@ -6964,13 +6964,6 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
struct ipw2100_priv *priv = libipw_priv(dev); struct ipw2100_priv *priv = libipw_priv(dev);
int err = 0; int err = 0;
static const unsigned char any[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const unsigned char off[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// sanity checks // sanity checks
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
return -EINVAL; return -EINVAL;
@ -6981,8 +6974,8 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
goto done; goto done;
} }
if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || if (is_broadcast_ether_addr(wrqu->ap_addr.sa_data) ||
!memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
/* we disable mandatory BSSID association */ /* we disable mandatory BSSID association */
IPW_DEBUG_WX("exit - disable mandatory BSSID\n"); IPW_DEBUG_WX("exit - disable mandatory BSSID\n");
priv->config &= ~CFG_STATIC_BSSID; priv->config &= ~CFG_STATIC_BSSID;

View File

@ -9037,18 +9037,11 @@ static int ipw_wx_set_wap(struct net_device *dev,
{ {
struct ipw_priv *priv = libipw_priv(dev); struct ipw_priv *priv = libipw_priv(dev);
static const unsigned char any[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const unsigned char off[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || if (is_broadcast_ether_addr(wrqu->ap_addr.sa_data) ||
!memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
/* we disable mandatory BSSID association */ /* we disable mandatory BSSID association */
IPW_DEBUG_WX("Setting AP BSSID to ANY\n"); IPW_DEBUG_WX("Setting AP BSSID to ANY\n");
priv->config &= ~CFG_STATIC_BSSID; priv->config &= ~CFG_STATIC_BSSID;

View File

@ -1055,8 +1055,9 @@ struct iwl_wep_cmd {
#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1) #define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1)
#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0xf0 #define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70
#define RX_RES_PHY_FLAGS_ANTENNA_POS 4 #define RX_RES_PHY_FLAGS_ANTENNA_POS 4
#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7)
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)

View File

@ -771,6 +771,7 @@ struct iwl_priv {
u8 agg_tids_count; u8 agg_tids_count;
struct iwl_rx_phy_res last_phy_res; struct iwl_rx_phy_res last_phy_res;
u32 ampdu_ref;
bool last_phy_res_valid; bool last_phy_res_valid;
/* /*

View File

@ -667,6 +667,7 @@ static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
priv->last_phy_res_valid = true; priv->last_phy_res_valid = true;
priv->ampdu_ref++;
memcpy(&priv->last_phy_res, pkt->data, memcpy(&priv->last_phy_res, pkt->data,
sizeof(struct iwl_rx_phy_res)); sizeof(struct iwl_rx_phy_res));
return 0; return 0;
@ -981,6 +982,16 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
rx_status.flag |= RX_FLAG_SHORTPRE; rx_status.flag |= RX_FLAG_SHORTPRE;
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
/*
* We know which subframes of an A-MPDU belong
* together since we get a single PHY response
* from the firmware for all of them
*/
rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
rx_status.ampdu_reference = priv->ampdu_ref;
}
/* Set up the HT phy flags */ /* Set up the HT phy flags */
if (rate_n_flags & RATE_MCS_HT_MSK) if (rate_n_flags & RATE_MCS_HT_MSK)
rx_status.flag |= RX_FLAG_HT; rx_status.flag |= RX_FLAG_HT;

View File

@ -29,6 +29,7 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/device.h> #include <linux/device.h>
#include "iwl-trans.h"
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
@ -237,27 +238,34 @@ TRACE_EVENT(iwlwifi_dbg,
#define TRACE_SYSTEM iwlwifi #define TRACE_SYSTEM iwlwifi
TRACE_EVENT(iwlwifi_dev_hcmd, TRACE_EVENT(iwlwifi_dev_hcmd,
TP_PROTO(const struct device *dev, u32 flags, TP_PROTO(const struct device *dev,
const void *hcmd0, size_t len0, struct iwl_host_cmd *cmd, u16 total_size,
const void *hcmd1, size_t len1, const void *hdr, size_t hdr_len),
const void *hcmd2, size_t len2), TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
TP_STRUCT__entry( TP_STRUCT__entry(
DEV_ENTRY DEV_ENTRY
__dynamic_array(u8, hcmd0, len0) __dynamic_array(u8, hcmd, total_size)
__dynamic_array(u8, hcmd1, len1)
__dynamic_array(u8, hcmd2, len2)
__field(u32, flags) __field(u32, flags)
), ),
TP_fast_assign( TP_fast_assign(
int i, offset = hdr_len;
DEV_ASSIGN; DEV_ASSIGN;
memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); __entry->flags = cmd->flags;
memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
__entry->flags = flags; for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
continue;
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
continue;
memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
cmd->data[i], cmd->len[i]);
offset += cmd->len[i];
}
), ),
TP_printk("[%s] hcmd %#.2x (%ssync)", TP_printk("[%s] hcmd %#.2x (%ssync)",
__get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0], __get_str(dev), ((u8 *)__get_dynamic_array(hcmd))[0],
__entry->flags & CMD_ASYNC ? "a" : "") __entry->flags & CMD_ASYNC ? "a" : "")
); );

View File

@ -85,8 +85,6 @@ struct iwl_eeprom_data {
int n_hw_addrs; int n_hw_addrs;
u8 hw_addr[ETH_ALEN]; u8 hw_addr[ETH_ALEN];
u16 radio_config;
u8 calib_version; u8 calib_version;
__le16 calib_voltage; __le16 calib_voltage;

View File

@ -522,11 +522,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
bool had_nocopy = false; bool had_nocopy = false;
int i; int i;
u32 cmd_pos; u32 cmd_pos;
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
int trace_idx;
#endif
copy_size = sizeof(out_cmd->hdr); copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr); cmd_size = sizeof(out_cmd->hdr);
@ -628,11 +623,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
dma_unmap_len_set(out_meta, len, copy_size); dma_unmap_len_set(out_meta, len, copy_size);
iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1); iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[0] = &out_cmd->hdr;
trace_lens[0] = copy_size;
trace_idx = 1;
#endif
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i]) if (!cmd->len[i])
@ -651,25 +641,14 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
cmd->len[i], 0); cmd->len[i], 0);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[trace_idx] = cmd->data[i];
trace_lens[trace_idx] = cmd->len[i];
trace_idx++;
#endif
} }
out_meta->flags = cmd->flags; out_meta->flags = cmd->flags;
txq->need_update = 1; txq->need_update = 1;
/* check that tracing gets all possible blocks */ trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); &out_cmd->hdr, copy_size);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_iwlwifi_dev_hcmd(trans->dev, cmd->flags,
trace_bufs[0], trace_lens[0],
trace_bufs[1], trace_lens[1],
trace_bufs[2], trace_lens[2]);
#endif
/* start timer if queue currently empty */ /* start timer if queue currently empty */
if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)

View File

@ -1159,6 +1159,22 @@ void lbs_set_mac_control(struct lbs_private *priv)
lbs_deb_leave(LBS_DEB_CMD); lbs_deb_leave(LBS_DEB_CMD);
} }
int lbs_set_mac_control_sync(struct lbs_private *priv)
{
struct cmd_ds_mac_control cmd;
int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(priv->mac_control);
cmd.reserved = 0;
ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd);
lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
/** /**
* lbs_allocate_cmd_buffer - allocates the command buffer and links * lbs_allocate_cmd_buffer - allocates the command buffer and links
* it to command free queue * it to command free queue

View File

@ -96,6 +96,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv);
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
void lbs_set_mac_control(struct lbs_private *priv); void lbs_set_mac_control(struct lbs_private *priv);
int lbs_set_mac_control_sync(struct lbs_private *priv);
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
s16 *maxlevel); s16 *maxlevel);

View File

@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)
mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
/* If we're powered off anyway, just let the mmc layer remove the
* card. */
if (!lbs_iface_active(card->priv))
return -ENOSYS;
dev_info(dev, "%s: suspend: PM flags = 0x%x\n", dev_info(dev, "%s: suspend: PM flags = 0x%x\n",
sdio_func_id(func), flags); sdio_func_id(func), flags);

View File

@ -682,8 +682,10 @@ static int lbs_setup_firmware(struct lbs_private *priv)
/* Send cmd to FW to enable 11D function */ /* Send cmd to FW to enable 11D function */
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1); ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
if (ret)
goto done;
lbs_set_mac_control(priv); ret = lbs_set_mac_control_sync(priv);
done: done:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret; return ret;

View File

@ -175,23 +175,6 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
return 0; return 0;
} }
/*
* This function handles the command response of 11n configuration request.
*
* Handling includes changing the header fields into CPU format.
*/
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
struct mwifiex_ds_11n_tx_cfg *tx_cfg)
{
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
if (tx_cfg) {
tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
}
return 0;
}
/* /*
* This function prepares command of reconfigure Tx buffer. * This function prepares command of reconfigure Tx buffer.
* *
@ -257,27 +240,6 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
return 0; return 0;
} }
/*
* This function handles the command response of AMSDU aggregation
* control request.
*
* Handling includes changing the header fields into CPU format.
*/
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
struct mwifiex_ds_11n_amsdu_aggr_ctrl
*amsdu_aggr_ctrl)
{
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&resp->params.amsdu_aggr_ctrl;
if (amsdu_aggr_ctrl) {
amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
amsdu_aggr_ctrl->curr_buf_size =
le16_to_cpu(amsdu_ctrl->curr_buf_size);
}
return 0;
}
/* /*
* This function prepares 11n configuration command. * This function prepares 11n configuration command.
* *

View File

@ -28,8 +28,6 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp); struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp); struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
struct mwifiex_ds_11n_tx_cfg *tx_cfg);
int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
struct mwifiex_ds_11n_tx_cfg *txcfg); struct mwifiex_ds_11n_tx_cfg *txcfg);
@ -60,9 +58,6 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
struct mwifiex_ds_rx_reorder_tbl *buf); struct mwifiex_ds_rx_reorder_tbl *buf);
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
struct mwifiex_ds_tx_ba_stream_tbl *buf); struct mwifiex_ds_tx_ba_stream_tbl *buf);
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
struct mwifiex_ds_11n_amsdu_aggr_ctrl
*amsdu_aggr_ctrl);
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, struct host_cmd_ds_command *cmd,
int cmd_action, u16 *buf_size); int cmd_action, u16 *buf_size);

View File

@ -37,6 +37,36 @@ static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
.beacon_int_infra_match = true, .beacon_int_infra_match = true,
}; };
static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
.n_reg_rules = 7,
.alpha2 = "99",
.reg_rules = {
/* Channel 1 - 11 */
REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
/* Channel 12 - 13 */
REG_RULE(2467-10, 2472+10, 20, 3, 20,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
/* Channel 14 */
REG_RULE(2484-10, 2484+10, 20, 3, 20,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* Channel 36 - 48 */
REG_RULE(5180-10, 5240+10, 40, 3, 20,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
/* Channel 149 - 165 */
REG_RULE(5745-10, 5825+10, 40, 3, 20,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
/* Channel 52 - 64 */
REG_RULE(5260-10, 5320+10, 40, 3, 30,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
/* Channel 100 - 140 */
REG_RULE(5500-10, 5700+10, 40, 3, 30,
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
/* /*
* This function maps the nl802.11 channel type into driver channel type. * This function maps the nl802.11 channel type into driver channel type.
* *
@ -969,15 +999,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
bss_cfg->channel = bss_cfg->channel =
(u8)ieee80211_frequency_to_channel(params->channel->center_freq); (u8)ieee80211_frequency_to_channel(params->channel->center_freq);
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
/* Set appropriate bands */ /* Set appropriate bands */
if (params->channel->band == IEEE80211_BAND_2GHZ) { if (params->channel->band == IEEE80211_BAND_2GHZ) {
bss_cfg->band_cfg = BAND_CONFIG_BG;
if (params->channel_type == NL80211_CHAN_NO_HT) if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_B | BAND_G; config_bands = BAND_B | BAND_G;
else else
config_bands = BAND_B | BAND_G | BAND_GN; config_bands = BAND_B | BAND_G | BAND_GN;
} else { } else {
bss_cfg->band_cfg = BAND_CONFIG_A;
if (params->channel_type == NL80211_CHAN_NO_HT) if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_A; config_bands = BAND_A;
else else
@ -988,6 +1021,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
~priv->adapter->fw_bands)) ~priv->adapter->fw_bands))
priv->adapter->config_bands = config_bands; priv->adapter->config_bands = config_bands;
mwifiex_set_uap_rates(bss_cfg, params);
mwifiex_send_domain_info_cmd_fw(wiphy); mwifiex_send_domain_info_cmd_fw(wiphy);
if (mwifiex_set_secure_params(priv, bss_cfg, params)) { if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
@ -1153,7 +1187,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
~priv->adapter->fw_bands)) ~priv->adapter->fw_bands))
priv->adapter->config_bands = config_bands; priv->adapter->config_bands = config_bands;
} }
mwifiex_send_domain_info_cmd_fw(priv->wdev->wiphy);
} }
/* As this is new association, clear locally stored /* As this is new association, clear locally stored
@ -1637,7 +1670,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_STA; priv->bss_type = MWIFIEX_BSS_TYPE_STA;
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
priv->bss_priority = MWIFIEX_BSS_ROLE_STA; priv->bss_priority = 0;
priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_num = 0; priv->bss_num = 0;
@ -1660,7 +1693,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_UAP; priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; priv->bss_priority = 0;
priv->bss_role = MWIFIEX_BSS_ROLE_UAP; priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
priv->bss_started = 0; priv->bss_started = 0;
priv->bss_num = 0; priv->bss_num = 0;
@ -1830,7 +1863,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_CUSTOM_REGULATORY;
wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
@ -1859,8 +1895,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
return ret; return ret;
} }
country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
if (country_code && regulatory_hint(wiphy, country_code)) if (country_code)
dev_err(adapter->dev, "regulatory_hint() failed\n"); dev_info(adapter->dev,
"ignoring F/W country code %2.2s\n", country_code);
adapter->wiphy = wiphy; adapter->wiphy = wiphy;
return ret; return ret;

View File

@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
cmd_code = le16_to_cpu(host_cmd->command); cmd_code = le16_to_cpu(host_cmd->command);
cmd_size = le16_to_cpu(host_cmd->size); cmd_size = le16_to_cpu(host_cmd->size);
skb_trim(cmd_node->cmd_skb, cmd_size); /* Adjust skb length */
if (cmd_node->cmd_skb->len > cmd_size)
/*
* cmd_size is less than sizeof(struct host_cmd_ds_command).
* Trim off the unused portion.
*/
skb_trim(cmd_node->cmd_skb, cmd_size);
else if (cmd_node->cmd_skb->len < cmd_size)
/*
* cmd_size is larger than sizeof(struct host_cmd_ds_command)
* because we have appended custom IE TLV. Increase skb length
* accordingly.
*/
skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
do_gettimeofday(&tstamp); do_gettimeofday(&tstamp);
dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"

View File

@ -108,6 +108,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define MGMT_MASK_BEACON 0x100 #define MGMT_MASK_BEACON 0x100
#define TLV_TYPE_UAP_SSID 0x0000 #define TLV_TYPE_UAP_SSID 0x0000
#define TLV_TYPE_UAP_RATES 0x0001
#define PROPRIETARY_TLV_BASE_ID 0x0100 #define PROPRIETARY_TLV_BASE_ID 0x0100
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
@ -309,7 +310,7 @@ enum ENH_PS_MODES {
#define HostCmd_SCAN_RADIO_TYPE_A 1 #define HostCmd_SCAN_RADIO_TYPE_A 1
#define HOST_SLEEP_CFG_CANCEL 0xffffffff #define HOST_SLEEP_CFG_CANCEL 0xffffffff
#define HOST_SLEEP_CFG_COND_DEF 0x0000000f #define HOST_SLEEP_CFG_COND_DEF 0x00000000
#define HOST_SLEEP_CFG_GPIO_DEF 0xff #define HOST_SLEEP_CFG_GPIO_DEF 0xff
#define HOST_SLEEP_CFG_GAP_DEF 0 #define HOST_SLEEP_CFG_GAP_DEF 0
@ -1284,6 +1285,11 @@ struct host_cmd_tlv_ssid {
u8 ssid[0]; u8 ssid[0];
} __packed; } __packed;
struct host_cmd_tlv_rates {
struct host_cmd_tlv tlv;
u8 rates[0];
} __packed;
struct host_cmd_tlv_bcast_ssid { struct host_cmd_tlv_bcast_ssid {
struct host_cmd_tlv tlv; struct host_cmd_tlv tlv;
u8 bcast_ctl; u8 bcast_ctl;

View File

@ -73,7 +73,6 @@ static void scan_delay_timer_fn(unsigned long data)
list_for_each_entry_safe(cmd_node, tmp_node, list_for_each_entry_safe(cmd_node, tmp_node,
&adapter->scan_pending_q, list) { &adapter->scan_pending_q, list) {
list_del(&cmd_node->list); list_del(&cmd_node->list);
cmd_node->wait_q_enabled = false;
mwifiex_insert_cmd_to_free_q(adapter, cmd_node); mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
} }
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
@ -92,6 +91,11 @@ static void scan_delay_timer_fn(unsigned long data)
kfree(priv->user_scan_cfg); kfree(priv->user_scan_cfg);
priv->user_scan_cfg = NULL; priv->user_scan_cfg = NULL;
} }
if (priv->scan_pending_on_block) {
priv->scan_pending_on_block = false;
up(&priv->async_sem);
}
goto done; goto done;
} }

View File

@ -81,7 +81,11 @@ struct wep_key {
#define KEY_MGMT_ON_HOST 0x03 #define KEY_MGMT_ON_HOST 0x03
#define MWIFIEX_AUTH_MODE_AUTO 0xFF #define MWIFIEX_AUTH_MODE_AUTO 0xFF
#define BAND_CONFIG_MANUAL 0x00 #define BAND_CONFIG_BG 0x00
#define BAND_CONFIG_A 0x01
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
struct mwifiex_uap_bss_param { struct mwifiex_uap_bss_param {
u8 channel; u8 channel;
u8 band_cfg; u8 band_cfg;
@ -100,6 +104,7 @@ struct mwifiex_uap_bss_param {
struct wpa_param wpa_cfg; struct wpa_param wpa_cfg;
struct wep_key wep_cfg[NUM_WEP_KEYS]; struct wep_key wep_cfg[NUM_WEP_KEYS];
struct ieee80211_ht_cap ht_cap; struct ieee80211_ht_cap ht_cap;
u8 rates[MWIFIEX_SUPPORTED_RATES];
}; };
enum { enum {

View File

@ -72,7 +72,6 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
goto error; goto error;
adapter->priv[i]->adapter = adapter; adapter->priv[i]->adapter = adapter;
adapter->priv[i]->bss_priority = i;
adapter->priv_num++; adapter->priv_num++;
} }
mwifiex_init_lock_list(adapter); mwifiex_init_lock_list(adapter);

View File

@ -116,6 +116,7 @@ enum {
#define MAX_BITMAP_RATES_SIZE 10 #define MAX_BITMAP_RATES_SIZE 10
#define MAX_CHANNEL_BAND_BG 14 #define MAX_CHANNEL_BAND_BG 14
#define MAX_CHANNEL_BAND_A 165
#define MAX_FREQUENCY_BAND_BG 2484 #define MAX_FREQUENCY_BAND_BG 2484
@ -249,10 +250,6 @@ struct ieee_types_header {
u8 len; u8 len;
} __packed; } __packed;
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
struct ieee_types_vendor_specific { struct ieee_types_vendor_specific {
struct ieee_types_vendor_header vend_hdr; struct ieee_types_vendor_header vend_hdr;
u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
@ -487,6 +484,7 @@ struct mwifiex_private {
s32 cqm_rssi_thold; s32 cqm_rssi_thold;
u32 cqm_rssi_hyst; u32 cqm_rssi_hyst;
u8 subsc_evt_rssi_state; u8 subsc_evt_rssi_state;
struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage;
struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
u16 beacon_idx; u16 beacon_idx;
u16 proberesp_idx; u16 proberesp_idx;
@ -814,6 +812,7 @@ struct mwifiex_sta_node *
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
void mwifiex_delete_all_station_list(struct mwifiex_private *priv); void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
struct mwifiex_scan_cmd_config *scan_cfg); struct mwifiex_scan_cmd_config *scan_cfg);
@ -872,6 +871,8 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
void mwifiex_set_ht_params(struct mwifiex_private *priv, void mwifiex_set_ht_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg, struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params); struct cfg80211_ap_settings *params);
void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
/* /*
* This function checks if the queuing is RA based or not. * This function checks if the queuing is RA based or not.

View File

@ -726,7 +726,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
struct mwifiex_ie_types_num_probes *num_probes_tlv; struct mwifiex_ie_types_num_probes *num_probes_tlv;
struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
struct mwifiex_ie_types_rates_param_set *rates_tlv; struct mwifiex_ie_types_rates_param_set *rates_tlv;
const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
u8 *tlv_pos; u8 *tlv_pos;
u32 num_probes; u32 num_probes;
u32 ssid_len; u32 ssid_len;
@ -840,8 +839,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
* or BSSID filter applied to the scan results in the firmware. * or BSSID filter applied to the scan results in the firmware.
*/ */
if ((i && ssid_filter) || if ((i && ssid_filter) ||
memcmp(scan_cfg_out->specific_bssid, &zero_mac, !is_zero_ether_addr(scan_cfg_out->specific_bssid))
sizeof(zero_mac)))
*filtered_scan = true; *filtered_scan = true;
} else { } else {
scan_cfg_out->bss_mode = (u8) adapter->scan_mode; scan_cfg_out->bss_mode = (u8) adapter->scan_mode;

View File

@ -551,7 +551,6 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
struct host_cmd_tlv_mac_addr *tlv_mac; struct host_cmd_tlv_mac_addr *tlv_mac;
u16 key_param_len = 0, cmd_size; u16 key_param_len = 0, cmd_size;
int ret = 0; int ret = 0;
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
key_material->action = cpu_to_le16(cmd_action); key_material->action = cpu_to_le16(cmd_action);
@ -593,7 +592,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
/* set 0 when re-key */ /* set 0 when re-key */
key_material->key_param_set.key[1] = 0; key_material->key_param_set.key[1] = 0;
if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) { if (!is_broadcast_ether_addr(enc_key->mac_addr)) {
/* WAPI pairwise key: unicast */ /* WAPI pairwise key: unicast */
key_material->key_param_set.key_info |= key_material->key_param_set.key_info |=
cpu_to_le16(KEY_UNICAST); cpu_to_le16(KEY_UNICAST);

View File

@ -123,7 +123,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
{ {
struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
&resp->params.rssi_info_rsp; &resp->params.rssi_info_rsp;
struct mwifiex_ds_misc_subsc_evt subsc_evt; struct mwifiex_ds_misc_subsc_evt *subsc_evt =
&priv->async_subsc_evt_storage;
priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@ -140,26 +141,27 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
if (priv->subsc_evt_rssi_state == EVENT_HANDLED) if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
return 0; return 0;
memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
/* Resubscribe low and high rssi events with new thresholds */ /* Resubscribe low and high rssi events with new thresholds */
memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; subsc_evt->action = HostCmd_ACT_BITWISE_SET;
subsc_evt.action = HostCmd_ACT_BITWISE_SET;
if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
priv->cqm_rssi_hyst); priv->cqm_rssi_hyst);
subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
} else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
priv->cqm_rssi_hyst); priv->cqm_rssi_hyst);
} }
subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
priv->subsc_evt_rssi_state = EVENT_HANDLED; priv->subsc_evt_rssi_state = EVENT_HANDLED;
mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
0, 0, &subsc_evt); 0, 0, subsc_evt);
return 0; return 0;
} }
@ -736,7 +738,6 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
{ {
struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
&(resp->params.ibss_coalescing); &(resp->params.ibss_coalescing);
u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
return 0; return 0;
@ -745,7 +746,7 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
"info: new BSSID %pM\n", ibss_coal_resp->bssid); "info: new BSSID %pM\n", ibss_coal_resp->bssid);
/* If rsp has NULL BSSID, Just return..... No Action */ /* If rsp has NULL BSSID, Just return..... No Action */
if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); dev_warn(priv->adapter->dev, "new BSSID is NULL\n");
return 0; return 0;
} }
@ -775,8 +776,7 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
* This function handles the command response for subscribe event command. * This function handles the command response for subscribe event command.
*/ */
static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp, struct host_cmd_ds_command *resp)
struct mwifiex_ds_misc_subsc_evt *sub_event)
{ {
struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
&resp->params.subsc_evt; &resp->params.subsc_evt;
@ -786,10 +786,6 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n", dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n",
le16_to_cpu(cmd_sub_event->events)); le16_to_cpu(cmd_sub_event->events));
/*Return the subscribed event info for a Get request*/
if (sub_event)
sub_event->events = le16_to_cpu(cmd_sub_event->events);
return 0; return 0;
} }
@ -913,7 +909,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
le16_to_cpu(resp->params.tx_buf.mp_end_port)); le16_to_cpu(resp->params.tx_buf.mp_end_port));
break; break;
case HostCmd_CMD_AMSDU_AGGR_CTRL: case HostCmd_CMD_AMSDU_AGGR_CTRL:
ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf);
break; break;
case HostCmd_CMD_WMM_GET_STATUS: case HostCmd_CMD_WMM_GET_STATUS:
ret = mwifiex_ret_wmm_get_status(priv, resp); ret = mwifiex_ret_wmm_get_status(priv, resp);
@ -932,12 +927,11 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_SET_BSS_MODE: case HostCmd_CMD_SET_BSS_MODE:
break; break;
case HostCmd_CMD_11N_CFG: case HostCmd_CMD_11N_CFG:
ret = mwifiex_ret_11n_cfg(resp, data_buf);
break; break;
case HostCmd_CMD_PCIE_DESC_DETAILS: case HostCmd_CMD_PCIE_DESC_DETAILS:
break; break;
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); ret = mwifiex_ret_subsc_evt(priv, resp);
break; break;
case HostCmd_CMD_UAP_SYS_CONFIG: case HostCmd_CMD_UAP_SYS_CONFIG:
break; break;

View File

@ -192,6 +192,44 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
return ret; return ret;
} }
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
struct cfg80211_bss *bss)
{
u8 *country_ie, country_ie_len;
struct mwifiex_802_11d_domain_reg *domain_info =
&priv->adapter->domain_reg;
country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
if (!country_ie)
return 0;
country_ie_len = country_ie[1];
if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
return 0;
domain_info->country_code[0] = country_ie[2];
domain_info->country_code[1] = country_ie[3];
domain_info->country_code[2] = ' ';
country_ie_len -= IEEE80211_COUNTRY_STRING_LEN;
domain_info->no_of_triplet =
country_ie_len / sizeof(struct ieee80211_country_ie_triplet);
memcpy((u8 *)domain_info->triplet,
&country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
HostCmd_ACT_GEN_SET, 0, NULL)) {
wiphy_err(priv->adapter->wiphy,
"11D: setting domain info in FW\n");
return -1;
}
return 0;
}
/* /*
* In Ad-Hoc mode, the IBSS is created if not found in scan list. * In Ad-Hoc mode, the IBSS is created if not found in scan list.
* In both Ad-Hoc and infra mode, an deauthentication is performed * In both Ad-Hoc and infra mode, an deauthentication is performed
@ -207,6 +245,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
priv->scan_block = false; priv->scan_block = false;
if (bss) { if (bss) {
mwifiex_process_country_ie(priv, bss);
/* Allocate and fill new bss descriptor */ /* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
GFP_KERNEL); GFP_KERNEL);

View File

@ -75,7 +75,11 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
u8 *head_ptr; u8 *head_ptr;
struct txpd *local_tx_pd = NULL; struct txpd *local_tx_pd = NULL;
head_ptr = mwifiex_process_sta_txpd(priv, skb); if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
head_ptr = mwifiex_process_uap_txpd(priv, skb);
else
head_ptr = mwifiex_process_sta_txpd(priv, skb);
if (head_ptr) { if (head_ptr) {
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd = local_tx_pd =

View File

@ -177,6 +177,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
return; return;
} }
/* This function finds supported rates IE from beacon parameter and sets
* these rates into bss_config structure.
*/
void
mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params)
{
struct ieee_types_header *rate_ie;
int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
const u8 *var_pos = params->beacon.head + var_offset;
int len = params->beacon.head_len - var_offset;
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
if (rate_ie)
memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
return;
}
/* This function initializes some of mwifiex_uap_bss_param variables. /* This function initializes some of mwifiex_uap_bss_param variables.
* This helps FW in ignoring invalid values. These values may or may not * This helps FW in ignoring invalid values. These values may or may not
* be get updated to valid ones at later stage. * be get updated to valid ones at later stage.
@ -323,8 +342,10 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
struct host_cmd_tlv_retry_limit *retry_limit; struct host_cmd_tlv_retry_limit *retry_limit;
struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
struct host_cmd_tlv_auth_type *auth_type; struct host_cmd_tlv_auth_type *auth_type;
struct host_cmd_tlv_rates *tlv_rates;
struct mwifiex_ie_types_htcap *htcap; struct mwifiex_ie_types_htcap *htcap;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
int i;
u16 cmd_size = *param_size; u16 cmd_size = *param_size;
if (bss_cfg->ssid.ssid_len) { if (bss_cfg->ssid.ssid_len) {
@ -344,7 +365,23 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
tlv += sizeof(struct host_cmd_tlv_bcast_ssid); tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
} }
if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { if (bss_cfg->rates[0]) {
tlv_rates = (struct host_cmd_tlv_rates *)tlv;
tlv_rates->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
i++)
tlv_rates->rates[i] = bss_cfg->rates[i];
tlv_rates->tlv.len = cpu_to_le16(i);
cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
tlv += sizeof(struct host_cmd_tlv_rates) + i;
}
if (bss_cfg->channel &&
((bss_cfg->band_cfg == BAND_CONFIG_BG &&
bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
(bss_cfg->band_cfg == BAND_CONFIG_A &&
bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
chan_band = (struct host_cmd_tlv_channel_band *)tlv; chan_band = (struct host_cmd_tlv_channel_band *)tlv;
chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
chan_band->tlv.len = chan_band->tlv.len =

View File

@ -253,3 +253,73 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
return ret; return ret;
} }
/*
* This function fills the TxPD for AP tx packets.
*
* The Tx buffer received by this function should already have the
* header space allocated for TxPD.
*
* This function inserts the TxPD in between interface header and actual
* data and adjusts the buffer pointers accordingly.
*
* The following TxPD fields are set by this function, as required -
* - BSS number
* - Tx packet length and offset
* - Priority
* - Packet delay
* - Priority specific Tx control
* - Flags
*/
void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
struct sk_buff *skb)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct uap_txpd *txpd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
int pad, len;
if (!skb->len) {
dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
tx_info->status_code = -1;
return skb->data;
}
/* If skb->data is not aligned, add padding */
pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
len = sizeof(*txpd) + pad;
BUG_ON(skb_headroom(skb) < len + INTF_HEADER_LEN);
skb_push(skb, len);
txpd = (struct uap_txpd *)skb->data;
memset(txpd, 0, sizeof(*txpd));
txpd->bss_num = priv->bss_num;
txpd->bss_type = priv->bss_type;
txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - len));
txpd->priority = (u8)skb->priority;
txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
/*
* Set the priority specific tx_control field, setting of 0 will
* cause the default value to be used later in this function.
*/
txpd->tx_control =
cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]);
/* Offset of actual data */
txpd->tx_pkt_offset = cpu_to_le16(len);
/* make space for INTF_HEADER_LEN */
skb_push(skb, INTF_HEADER_LEN);
if (!txpd->tx_control)
/* TxCtrl set by user or default */
txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
return skb->data;
}

View File

@ -907,17 +907,16 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
if (adapter->bss_prio_tbl[j].bss_prio_cur == if (adapter->bss_prio_tbl[j].bss_prio_cur ==
(struct mwifiex_bss_prio_node *) (struct mwifiex_bss_prio_node *)
&adapter->bss_prio_tbl[j].bss_prio_head) { &adapter->bss_prio_tbl[j].bss_prio_head) {
bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur =
list_first_entry(&adapter->bss_prio_tbl[j] list_first_entry(&adapter->bss_prio_tbl[j]
.bss_prio_head, .bss_prio_head,
struct mwifiex_bss_prio_node, struct mwifiex_bss_prio_node,
list); list);
bssprio_head = bssprio_node;
} else {
bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
bssprio_head = bssprio_node;
} }
bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
bssprio_head = bssprio_node;
do { do {
priv_tmp = bssprio_node->priv; priv_tmp = bssprio_node->priv;
hqp = &priv_tmp->wmm.highest_queued_prio; hqp = &priv_tmp->wmm.highest_queued_prio;

View File

@ -7,6 +7,7 @@
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <net/iw_handler.h> #include <net/iw_handler.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
#include <net/cfg80211-wext.h> #include <net/cfg80211-wext.h>
@ -159,15 +160,13 @@ static int orinoco_ioctl_setwap(struct net_device *dev,
struct orinoco_private *priv = ndev_priv(dev); struct orinoco_private *priv = ndev_priv(dev);
int err = -EINPROGRESS; /* Call commit handler */ int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags; unsigned long flags;
static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
if (orinoco_lock(priv, &flags) != 0) if (orinoco_lock(priv, &flags) != 0)
return -EBUSY; return -EBUSY;
/* Enable automatic roaming - no sanity checks are needed */ /* Enable automatic roaming - no sanity checks are needed */
if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || if (is_zero_ether_addr(ap_addr->sa_data) ||
memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { is_broadcast_ether_addr(ap_addr->sa_data)) {
priv->bssid_fixed = 0; priv->bssid_fixed = 0;
memset(priv->desired_bssid, 0, ETH_ALEN); memset(priv->desired_bssid, 0, ETH_ALEN);

View File

@ -139,6 +139,7 @@ static int p54_beacon_format_ie_tim(struct sk_buff *skb)
static int p54_beacon_update(struct p54_common *priv, static int p54_beacon_update(struct p54_common *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct ieee80211_tx_control control = { };
struct sk_buff *beacon; struct sk_buff *beacon;
int ret; int ret;
@ -158,7 +159,7 @@ static int p54_beacon_update(struct p54_common *priv,
* to cancel the old beacon template by hand, instead the firmware * to cancel the old beacon template by hand, instead the firmware
* will release the previous one through the feedback mechanism. * will release the previous one through the feedback mechanism.
*/ */
p54_tx_80211(priv->hw, NULL, beacon); p54_tx_80211(priv->hw, &control, beacon);
priv->tsf_high32 = 0; priv->tsf_high32 = 0;
priv->tsf_low32 = 0; priv->tsf_low32 = 0;

View File

@ -1959,9 +1959,6 @@ static int rndis_scan(struct wiphy *wiphy,
*/ */
rndis_check_bssid_list(usbdev, NULL, NULL); rndis_check_bssid_list(usbdev, NULL, NULL);
if (!request)
return -EINVAL;
if (priv->scan_request && priv->scan_request != request) if (priv->scan_request && priv->scan_request != request)
return -EBUSY; return -EBUSY;

View File

@ -205,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg; u32 reg;
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg); rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_BIT0); return rt2x00_get_field32(reg, GPIOCSR_VAL0);
} }
#ifdef CONFIG_RT2X00_LIB_LEDS #ifdef CONFIG_RT2X00_LIB_LEDS
@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
u32 reg;
/* /*
* Allocate eeprom data. * Allocate eeprom data.
@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval) if (retval)
return retval; return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
/* /*
* Initialize hw specifications. * Initialize hw specifications.
*/ */

View File

@ -660,16 +660,26 @@
/* /*
* GPIOCSR: GPIO control register. * GPIOCSR: GPIO control register.
* GPIOCSR_VALx: Actual GPIO pin x value
* GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
*/ */
#define GPIOCSR 0x0120 #define GPIOCSR 0x0120
#define GPIOCSR_BIT0 FIELD32(0x00000001) #define GPIOCSR_VAL0 FIELD32(0x00000001)
#define GPIOCSR_BIT1 FIELD32(0x00000002) #define GPIOCSR_VAL1 FIELD32(0x00000002)
#define GPIOCSR_BIT2 FIELD32(0x00000004) #define GPIOCSR_VAL2 FIELD32(0x00000004)
#define GPIOCSR_BIT3 FIELD32(0x00000008) #define GPIOCSR_VAL3 FIELD32(0x00000008)
#define GPIOCSR_BIT4 FIELD32(0x00000010) #define GPIOCSR_VAL4 FIELD32(0x00000010)
#define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_VAL5 FIELD32(0x00000020)
#define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_VAL6 FIELD32(0x00000040)
#define GPIOCSR_BIT7 FIELD32(0x00000080) #define GPIOCSR_VAL7 FIELD32(0x00000080)
#define GPIOCSR_DIR0 FIELD32(0x00000100)
#define GPIOCSR_DIR1 FIELD32(0x00000200)
#define GPIOCSR_DIR2 FIELD32(0x00000400)
#define GPIOCSR_DIR3 FIELD32(0x00000800)
#define GPIOCSR_DIR4 FIELD32(0x00001000)
#define GPIOCSR_DIR5 FIELD32(0x00002000)
#define GPIOCSR_DIR6 FIELD32(0x00004000)
#define GPIOCSR_DIR7 FIELD32(0x00008000)
/* /*
* BBPPCSR: BBP Pin control register. * BBPPCSR: BBP Pin control register.

View File

@ -205,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg; u32 reg;
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg); rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_BIT0); return rt2x00_get_field32(reg, GPIOCSR_VAL0);
} }
#ifdef CONFIG_RT2X00_LIB_LEDS #ifdef CONFIG_RT2X00_LIB_LEDS
@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
u32 reg;
/* /*
* Allocate eeprom data. * Allocate eeprom data.
@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval) if (retval)
return retval; return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
/* /*
* Initialize hw specifications. * Initialize hw specifications.
*/ */

View File

@ -789,16 +789,18 @@
/* /*
* GPIOCSR: GPIO control register. * GPIOCSR: GPIO control register.
* GPIOCSR_VALx: GPIO value
* GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
*/ */
#define GPIOCSR 0x0120 #define GPIOCSR 0x0120
#define GPIOCSR_BIT0 FIELD32(0x00000001) #define GPIOCSR_VAL0 FIELD32(0x00000001)
#define GPIOCSR_BIT1 FIELD32(0x00000002) #define GPIOCSR_VAL1 FIELD32(0x00000002)
#define GPIOCSR_BIT2 FIELD32(0x00000004) #define GPIOCSR_VAL2 FIELD32(0x00000004)
#define GPIOCSR_BIT3 FIELD32(0x00000008) #define GPIOCSR_VAL3 FIELD32(0x00000008)
#define GPIOCSR_BIT4 FIELD32(0x00000010) #define GPIOCSR_VAL4 FIELD32(0x00000010)
#define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_VAL5 FIELD32(0x00000020)
#define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_VAL6 FIELD32(0x00000040)
#define GPIOCSR_BIT7 FIELD32(0x00000080) #define GPIOCSR_VAL7 FIELD32(0x00000080)
#define GPIOCSR_DIR0 FIELD32(0x00000100) #define GPIOCSR_DIR0 FIELD32(0x00000100)
#define GPIOCSR_DIR1 FIELD32(0x00000200) #define GPIOCSR_DIR1 FIELD32(0x00000200)
#define GPIOCSR_DIR2 FIELD32(0x00000400) #define GPIOCSR_DIR2 FIELD32(0x00000400)

View File

@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u16 reg; u16 reg;
rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg); rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
return rt2x00_get_field32(reg, MAC_CSR19_BIT7); return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
} }
#ifdef CONFIG_RT2X00_LIB_LEDS #ifdef CONFIG_RT2X00_LIB_LEDS
@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
u16 reg;
/* /*
* Allocate eeprom data. * Allocate eeprom data.
@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval) if (retval)
return retval; return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
/* /*
* Initialize hw specifications. * Initialize hw specifications.
*/ */

View File

@ -187,16 +187,26 @@
/* /*
* MAC_CSR19: GPIO control register. * MAC_CSR19: GPIO control register.
* MAC_CSR19_VALx: GPIO value
* MAC_CSR19_DIRx: GPIO direction: 0 = input; 1 = output
*/ */
#define MAC_CSR19 0x0426 #define MAC_CSR19 0x0426
#define MAC_CSR19_BIT0 FIELD32(0x0001) #define MAC_CSR19_VAL0 FIELD16(0x0001)
#define MAC_CSR19_BIT1 FIELD32(0x0002) #define MAC_CSR19_VAL1 FIELD16(0x0002)
#define MAC_CSR19_BIT2 FIELD32(0x0004) #define MAC_CSR19_VAL2 FIELD16(0x0004)
#define MAC_CSR19_BIT3 FIELD32(0x0008) #define MAC_CSR19_VAL3 FIELD16(0x0008)
#define MAC_CSR19_BIT4 FIELD32(0x0010) #define MAC_CSR19_VAL4 FIELD16(0x0010)
#define MAC_CSR19_BIT5 FIELD32(0x0020) #define MAC_CSR19_VAL5 FIELD16(0x0020)
#define MAC_CSR19_BIT6 FIELD32(0x0040) #define MAC_CSR19_VAL6 FIELD16(0x0040)
#define MAC_CSR19_BIT7 FIELD32(0x0080) #define MAC_CSR19_VAL7 FIELD16(0x0080)
#define MAC_CSR19_DIR0 FIELD16(0x0100)
#define MAC_CSR19_DIR1 FIELD16(0x0200)
#define MAC_CSR19_DIR2 FIELD16(0x0400)
#define MAC_CSR19_DIR3 FIELD16(0x0800)
#define MAC_CSR19_DIR4 FIELD16(0x1000)
#define MAC_CSR19_DIR5 FIELD16(0x2000)
#define MAC_CSR19_DIR6 FIELD16(0x4000)
#define MAC_CSR19_DIR7 FIELD16(0x8000)
/* /*
* MAC_CSR20: LED control register. * MAC_CSR20: LED control register.

View File

@ -439,26 +439,33 @@
#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) #define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000)
/* /*
* GPIO_CTRL_CFG: * GPIO_CTRL:
* GPIOD: GPIO direction, 0: Output, 1: Input * GPIO_CTRL_VALx: GPIO value
* GPIO_CTRL_DIRx: GPIO direction: 0 = output; 1 = input
*/ */
#define GPIO_CTRL_CFG 0x0228 #define GPIO_CTRL 0x0228
#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) #define GPIO_CTRL_VAL0 FIELD32(0x00000001)
#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) #define GPIO_CTRL_VAL1 FIELD32(0x00000002)
#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) #define GPIO_CTRL_VAL2 FIELD32(0x00000004)
#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) #define GPIO_CTRL_VAL3 FIELD32(0x00000008)
#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) #define GPIO_CTRL_VAL4 FIELD32(0x00000010)
#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) #define GPIO_CTRL_VAL5 FIELD32(0x00000020)
#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) #define GPIO_CTRL_VAL6 FIELD32(0x00000040)
#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) #define GPIO_CTRL_VAL7 FIELD32(0x00000080)
#define GPIO_CTRL_CFG_GPIOD_BIT0 FIELD32(0x00000100) #define GPIO_CTRL_DIR0 FIELD32(0x00000100)
#define GPIO_CTRL_CFG_GPIOD_BIT1 FIELD32(0x00000200) #define GPIO_CTRL_DIR1 FIELD32(0x00000200)
#define GPIO_CTRL_CFG_GPIOD_BIT2 FIELD32(0x00000400) #define GPIO_CTRL_DIR2 FIELD32(0x00000400)
#define GPIO_CTRL_CFG_GPIOD_BIT3 FIELD32(0x00000800) #define GPIO_CTRL_DIR3 FIELD32(0x00000800)
#define GPIO_CTRL_CFG_GPIOD_BIT4 FIELD32(0x00001000) #define GPIO_CTRL_DIR4 FIELD32(0x00001000)
#define GPIO_CTRL_CFG_GPIOD_BIT5 FIELD32(0x00002000) #define GPIO_CTRL_DIR5 FIELD32(0x00002000)
#define GPIO_CTRL_CFG_GPIOD_BIT6 FIELD32(0x00004000) #define GPIO_CTRL_DIR6 FIELD32(0x00004000)
#define GPIO_CTRL_CFG_GPIOD_BIT7 FIELD32(0x00008000) #define GPIO_CTRL_DIR7 FIELD32(0x00008000)
#define GPIO_CTRL_VAL8 FIELD32(0x00010000)
#define GPIO_CTRL_VAL9 FIELD32(0x00020000)
#define GPIO_CTRL_VAL10 FIELD32(0x00040000)
#define GPIO_CTRL_DIR8 FIELD32(0x01000000)
#define GPIO_CTRL_DIR9 FIELD32(0x02000000)
#define GPIO_CTRL_DIR10 FIELD32(0x04000000)
/* /*
* MCU_CMD_CFG * MCU_CMD_CFG
@ -1935,6 +1942,11 @@ struct mac_iveiv_entry {
#define BBP47_TSSI_TSSI_MODE FIELD8(0x18) #define BBP47_TSSI_TSSI_MODE FIELD8(0x18)
#define BBP47_TSSI_ADC6 FIELD8(0x80) #define BBP47_TSSI_ADC6 FIELD8(0x80)
/*
* BBP 49
*/
#define BBP49_UPDATE_FLAG FIELD8(0x01)
/* /*
* BBP 109 * BBP 109
*/ */

View File

@ -923,8 +923,8 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg); rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
} else { } else {
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg); rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
} }
} }
EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
@ -1570,10 +1570,10 @@ static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff, rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
eesk_pin, 0); eesk_pin, 0);
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg); rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0); rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, gpio_bit3); rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
} }
void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
@ -1615,6 +1615,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
case 1: case 1:
if (rt2x00_rt(rt2x00dev, RT3070) || if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390)) { rt2x00_rt(rt2x00dev, RT3390)) {
rt2x00_eeprom_read(rt2x00dev, rt2x00_eeprom_read(rt2x00dev,
EEPROM_NIC_CONF1, &eeprom); EEPROM_NIC_CONF1, &eeprom);
@ -1995,13 +1996,13 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
} }
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg); rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT7, 0); rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
if (rf->channel <= 14) if (rf->channel <= 14)
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 1); rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
else else
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 0); rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
@ -2053,6 +2054,60 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
} }
} }
static void rt2800_config_channel_rf3322(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_write(rt2x00dev, 11, 0x42);
rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
if (info->default_power1 > POWER_BOUND)
rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND);
else
rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1);
if (info->default_power2 > POWER_BOUND)
rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND);
else
rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);
rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
if ( rt2x00dev->default_ant.tx_chain_num == 2 )
rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
else
rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
if ( rt2x00dev->default_ant.rx_chain_num == 2 )
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
else
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
rt2800_rfcsr_write(rt2x00dev, 31, 80);
}
static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, struct ieee80211_conf *conf,
struct rf_channel *rf, struct rf_channel *rf,
@ -2182,6 +2237,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
case RF3290: case RF3290:
rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
break; break;
case RF3322:
rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
break;
case RF5360: case RF5360:
case RF5370: case RF5370:
case RF5372: case RF5372:
@ -2194,6 +2252,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
} }
if (rt2x00_rf(rt2x00dev, RF3290) || if (rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3322) ||
rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) || rt2x00_rf(rt2x00dev, RF5372) ||
@ -2212,10 +2271,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
/* /*
* Change BBP settings * Change BBP settings
*/ */
rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 27, 0x0);
rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 86, 0); rt2800_bbp_write(rt2x00dev, 27, 0x20);
rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
} else {
rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 86, 0);
}
if (rf->channel <= 14) { if (rf->channel <= 14) {
if (!rt2x00_rt(rt2x00dev, RT5390) && if (!rt2x00_rt(rt2x00dev, RT5390) &&
@ -2310,6 +2376,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg); rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg); rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg); rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
/*
* Clear update flag
*/
if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_read(rt2x00dev, 49, &bbp);
rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
rt2800_bbp_write(rt2x00dev, 49, bbp);
}
} }
static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
@ -2998,6 +3073,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
} else if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
} else if (rt2x00_rt(rt2x00dev, RT3572)) { } else if (rt2x00_rt(rt2x00dev, RT3572)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@ -3378,6 +3457,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_wait_bbp_ready(rt2x00dev))) rt2800_wait_bbp_ready(rt2x00dev)))
return -EACCES; return -EACCES;
if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 3, 0x00);
rt2800_bbp_write(rt2x00dev, 4, 0x50);
}
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) { rt2x00_rt(rt2x00dev, RT5392)) {
@ -3388,15 +3472,20 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2800_is_305x_soc(rt2x00dev) || if (rt2800_is_305x_soc(rt2x00dev) ||
rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 31, 0x08); rt2800_bbp_write(rt2x00dev, 31, 0x08);
if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 47, 0x48);
rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 65, 0x2c);
rt2800_bbp_write(rt2x00dev, 66, 0x38); rt2800_bbp_write(rt2x00dev, 66, 0x38);
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 68, 0x0b); rt2800_bbp_write(rt2x00dev, 68, 0x0b);
@ -3405,6 +3494,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 69, 0x16);
rt2800_bbp_write(rt2x00dev, 73, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x12);
} else if (rt2x00_rt(rt2x00dev, RT3290) || } else if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) { rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 69, 0x12);
@ -3436,6 +3526,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
} else if (rt2800_is_305x_soc(rt2x00dev)) { } else if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 78, 0x0e);
rt2800_bbp_write(rt2x00dev, 80, 0x08); rt2800_bbp_write(rt2x00dev, 80, 0x08);
} else if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
rt2800_bbp_write(rt2x00dev, 80, 0x08);
rt2800_bbp_write(rt2x00dev, 81, 0x37);
} else { } else {
rt2800_bbp_write(rt2x00dev, 81, 0x37); rt2800_bbp_write(rt2x00dev, 81, 0x37);
} }
@ -3465,18 +3559,21 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 84, 0x99);
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 86, 0x38); rt2800_bbp_write(rt2x00dev, 86, 0x38);
else else
rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 86, 0x00);
if (rt2x00_rt(rt2x00dev, RT5392)) if (rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 88, 0x90); rt2800_bbp_write(rt2x00dev, 88, 0x90);
rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 91, 0x04);
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 92, 0x02); rt2800_bbp_write(rt2x00dev, 92, 0x02);
@ -3493,6 +3590,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) || rt2x00_rt(rt2x00dev, RT5392) ||
@ -3502,6 +3600,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 103, 0x00);
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 104, 0x92); rt2800_bbp_write(rt2x00dev, 104, 0x92);
@ -3510,6 +3609,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 105, 0x01); rt2800_bbp_write(rt2x00dev, 105, 0x01);
else if (rt2x00_rt(rt2x00dev, RT3290)) else if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 105, 0x1c); rt2800_bbp_write(rt2x00dev, 105, 0x1c);
else if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 105, 0x34);
else if (rt2x00_rt(rt2x00dev, RT5390) || else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c); rt2800_bbp_write(rt2x00dev, 105, 0x3c);
@ -3519,11 +3620,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390)) rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 106, 0x03); rt2800_bbp_write(rt2x00dev, 106, 0x03);
else if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 106, 0x05);
else if (rt2x00_rt(rt2x00dev, RT5392)) else if (rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 106, 0x12); rt2800_bbp_write(rt2x00dev, 106, 0x12);
else else
rt2800_bbp_write(rt2x00dev, 106, 0x35); rt2800_bbp_write(rt2x00dev, 106, 0x35);
if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 120, 0x50);
if (rt2x00_rt(rt2x00dev, RT3290) || if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) rt2x00_rt(rt2x00dev, RT5392))
@ -3534,6 +3640,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 135, 0xf6); rt2800_bbp_write(rt2x00dev, 135, 0xf6);
} }
if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 137, 0x0f);
if (rt2x00_rt(rt2x00dev, RT3071) || if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) || rt2x00_rt(rt2x00dev, RT3390) ||
@ -3574,6 +3683,28 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 3, value); rt2800_bbp_write(rt2x00dev, 3, value);
} }
if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 163, 0xbd);
/* Set ITxBF timeout to 0x9c40=1000msec */
rt2800_bbp_write(rt2x00dev, 179, 0x02);
rt2800_bbp_write(rt2x00dev, 180, 0x00);
rt2800_bbp_write(rt2x00dev, 182, 0x40);
rt2800_bbp_write(rt2x00dev, 180, 0x01);
rt2800_bbp_write(rt2x00dev, 182, 0x9c);
rt2800_bbp_write(rt2x00dev, 179, 0x00);
/* Reprogram the inband interface to put right values in RXWI */
rt2800_bbp_write(rt2x00dev, 142, 0x04);
rt2800_bbp_write(rt2x00dev, 143, 0x3b);
rt2800_bbp_write(rt2x00dev, 142, 0x06);
rt2800_bbp_write(rt2x00dev, 143, 0xa0);
rt2800_bbp_write(rt2x00dev, 142, 0x07);
rt2800_bbp_write(rt2x00dev, 143, 0xa1);
rt2800_bbp_write(rt2x00dev, 142, 0x08);
rt2800_bbp_write(rt2x00dev, 143, 0xa2);
rt2800_bbp_write(rt2x00dev, 148, 0xc8);
}
if (rt2x00_rt(rt2x00dev, RT5390) || if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) { rt2x00_rt(rt2x00dev, RT5392)) {
int ant, div_mode; int ant, div_mode;
@ -3587,16 +3718,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
u32 reg; u32 reg;
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg); rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0); rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT6, 0); rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 0); rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 0); rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 0);
if (ant == 0) if (ant == 0)
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 1); rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 1);
else if (ant == 1) else if (ant == 1)
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 1); rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 1);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
} }
/* This chip has hardware antenna diversity*/ /* This chip has hardware antenna diversity*/
@ -3707,6 +3838,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
!rt2x00_rt(rt2x00dev, RT3071) && !rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) && !rt2x00_rt(rt2x00dev, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3290) && !rt2x00_rt(rt2x00dev, RT3290) &&
!rt2x00_rt(rt2x00dev, RT3352) &&
!rt2x00_rt(rt2x00dev, RT3390) && !rt2x00_rt(rt2x00dev, RT3390) &&
!rt2x00_rt(rt2x00dev, RT3572) && !rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) && !rt2x00_rt(rt2x00dev, RT5390) &&
@ -3903,6 +4035,70 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 30, 0x00); rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
rt2800_rfcsr_write(rt2x00dev, 31, 0x00); rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
return 0; return 0;
} else if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
rt2800_rfcsr_write(rt2x00dev, 3, 0x18);
rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
rt2800_rfcsr_write(rt2x00dev, 6, 0x33);
rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
rt2800_rfcsr_write(rt2x00dev, 10, 0xd2);
rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
rt2800_rfcsr_write(rt2x00dev, 14, 0x5a);
rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
rt2800_rfcsr_write(rt2x00dev, 16, 0x01);
rt2800_rfcsr_write(rt2x00dev, 18, 0x45);
rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
rt2800_rfcsr_write(rt2x00dev, 28, 0x03);
rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
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, 0x01);
rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 46, 0xdd);
rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
} else if (rt2x00_rt(rt2x00dev, RT5390)) { } else if (rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80); rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
@ -4089,6 +4285,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, LDO_CFG0, reg); rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
msleep(1); msleep(1);
rt2800_register_read(rt2x00dev, LDO_CFG0, &reg); rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1); rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
rt2800_register_write(rt2x00dev, LDO_CFG0, reg); rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
} }
@ -4103,6 +4300,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
} else if (rt2x00_rt(rt2x00dev, RT3071) || } else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390) || rt2x00_rt(rt2x00dev, RT3390) ||
rt2x00_rt(rt2x00dev, RT3572)) { rt2x00_rt(rt2x00dev, RT3572)) {
drv_data->calibration_bw20 = drv_data->calibration_bw20 =
@ -4391,13 +4589,18 @@ void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
} }
EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
{ {
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
u16 word; u16 word;
u8 *mac; u8 *mac;
u8 default_lna_gain; u8 default_lna_gain;
/*
* Read the EEPROM.
*/
rt2800_read_eeprom(rt2x00dev);
/* /*
* Start validation of the data that has been read. * Start validation of the data that has been read.
*/ */
@ -4520,9 +4723,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
{ {
u32 reg; u32 reg;
u16 value; u16 value;
@ -4561,6 +4763,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RT3071: case RT3071:
case RT3090: case RT3090:
case RT3290: case RT3290:
case RT3352:
case RT3390: case RT3390:
case RT3572: case RT3572:
case RT5390: case RT5390:
@ -4583,6 +4786,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF3052: case RF3052:
case RF3290: case RF3290:
case RF3320: case RF3320:
case RF3322:
case RF5360: case RF5360:
case RF5370: case RF5370:
case RF5372: case RF5372:
@ -4607,6 +4811,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3070) || if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390)) { rt2x00_rt(rt2x00dev, RT3390)) {
value = rt2x00_get_field16(eeprom, value = rt2x00_get_field16(eeprom,
EEPROM_NIC_CONF1_ANT_DIVERSITY); EEPROM_NIC_CONF1_ANT_DIVERSITY);
@ -4680,7 +4885,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
/* /*
* RF value list for rt28xx * RF value list for rt28xx
@ -4823,7 +5027,7 @@ static const struct rf_channel rf_vals_3x[] = {
{173, 0x61, 0, 9}, {173, 0x61, 0, 9},
}; };
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{ {
struct hw_mode_spec *spec = &rt2x00dev->spec; struct hw_mode_spec *spec = &rt2x00dev->spec;
struct channel_info *info; struct channel_info *info;
@ -4900,6 +5104,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF3022) || rt2x00_rf(rt2x00dev, RF3022) ||
rt2x00_rf(rt2x00dev, RF3290) || rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3320) || rt2x00_rf(rt2x00dev, RF3320) ||
rt2x00_rf(rt2x00dev, RF3322) ||
rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) || rt2x00_rf(rt2x00dev, RF5372) ||
@ -4999,7 +5204,72 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);
int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
u32 reg;
/*
* Allocate eeprom data.
*/
retval = rt2800_validate_eeprom(rt2x00dev);
if (retval)
return retval;
retval = rt2800_init_eeprom(rt2x00dev);
if (retval)
return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR2, 1);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
/*
* Initialize hw specifications.
*/
retval = rt2800_probe_hw_mode(rt2x00dev);
if (retval)
return retval;
/*
* Set device capabilities.
*/
__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
if (!rt2x00_is_usb(rt2x00dev))
__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
/*
* Set device requirements.
*/
if (!rt2x00_is_soc(rt2x00dev))
__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
if (!rt2800_hwcrypt_disabled(rt2x00dev))
__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
if (rt2x00_is_usb(rt2x00dev))
__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
else {
__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
}
/*
* Set the rssi offset.
*/
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_probe_hw);
/* /*
* IEEE80211 stack callback functions. * IEEE80211 stack callback functions.

View File

@ -43,6 +43,9 @@ struct rt2800_ops {
const unsigned int offset, const unsigned int offset,
const struct rt2x00_field32 field, u32 *reg); const struct rt2x00_field32 field, u32 *reg);
void (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len); const u8 *data, const size_t len);
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
@ -114,6 +117,20 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
} }
static inline void rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
rt2800ops->read_eeprom(rt2x00dev);
}
static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
return rt2800ops->hwcrypt_disabled(rt2x00dev);
}
static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev, static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len) const u8 *data, const size_t len)
{ {
@ -191,9 +208,8 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev); int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
u16 *iv16); u16 *iv16);

View File

@ -54,6 +54,11 @@ static bool modparam_nohwcrypt = false;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
}
static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
{ {
unsigned int i; unsigned int i;
@ -965,76 +970,14 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
/* /*
* Device probe functions. * Device probe functions.
*/ */
static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static void rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
{ {
/*
* Read EEPROM into buffer
*/
if (rt2x00_is_soc(rt2x00dev)) if (rt2x00_is_soc(rt2x00dev))
rt2800pci_read_eeprom_soc(rt2x00dev); rt2800pci_read_eeprom_soc(rt2x00dev);
else if (rt2800pci_efuse_detect(rt2x00dev)) else if (rt2800pci_efuse_detect(rt2x00dev))
rt2800pci_read_eeprom_efuse(rt2x00dev); rt2800pci_read_eeprom_efuse(rt2x00dev);
else else
rt2800pci_read_eeprom_pci(rt2x00dev); rt2800pci_read_eeprom_pci(rt2x00dev);
return rt2800_validate_eeprom(rt2x00dev);
}
static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
/*
* Allocate eeprom data.
*/
retval = rt2800pci_validate_eeprom(rt2x00dev);
if (retval)
return retval;
retval = rt2800_init_eeprom(rt2x00dev);
if (retval)
return retval;
/*
* Initialize hw specifications.
*/
retval = rt2800_probe_hw_mode(rt2x00dev);
if (retval)
return retval;
/*
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
*/
__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
/*
* This device has a pre tbtt interrupt and thus fetches
* a new beacon directly prior to transmission.
*/
__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
/*
* This device requires firmware.
*/
if (!rt2x00_is_soc(rt2x00dev))
__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
/*
* Set the rssi offset.
*/
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
return 0;
} }
static const struct ieee80211_ops rt2800pci_mac80211_ops = { static const struct ieee80211_ops rt2800pci_mac80211_ops = {
@ -1072,6 +1015,8 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.register_multiread = rt2x00pci_register_multiread, .register_multiread = rt2x00pci_register_multiread,
.register_multiwrite = rt2x00pci_register_multiwrite, .register_multiwrite = rt2x00pci_register_multiwrite,
.regbusy_read = rt2x00pci_regbusy_read, .regbusy_read = rt2x00pci_regbusy_read,
.read_eeprom = rt2800pci_read_eeprom,
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware, .drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800pci_init_registers, .drv_init_registers = rt2800pci_init_registers,
.drv_get_txwi = rt2800pci_get_txwi, .drv_get_txwi = rt2800pci_get_txwi,
@ -1084,7 +1029,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.tbtt_tasklet = rt2800pci_tbtt_tasklet, .tbtt_tasklet = rt2800pci_tbtt_tasklet,
.rxdone_tasklet = rt2800pci_rxdone_tasklet, .rxdone_tasklet = rt2800pci_rxdone_tasklet,
.autowake_tasklet = rt2800pci_autowake_tasklet, .autowake_tasklet = rt2800pci_autowake_tasklet,
.probe_hw = rt2800pci_probe_hw, .probe_hw = rt2800_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name, .get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware, .check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware, .load_firmware = rt2800_load_firmware,

View File

@ -49,6 +49,11 @@ static bool modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
}
/* /*
* Queue handlers. * Queue handlers.
*/ */
@ -667,8 +672,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
skb_pull(entry->skb, RXINFO_DESC_SIZE); skb_pull(entry->skb, RXINFO_DESC_SIZE);
/* /*
* FIXME: we need to check for rx_pkt_len validity * Check for rx_pkt_len validity. Return if invalid, leaving
* rxdesc->size zeroed out by the upper level.
*/ */
if (unlikely(rx_pkt_len == 0 ||
rx_pkt_len > entry->queue->data_size)) {
ERROR(entry->queue->rt2x00dev,
"Bad frame size %d, forcing to 0\n", rx_pkt_len);
return;
}
rxd = (__le32 *)(entry->skb->data + rx_pkt_len); rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
/* /*
@ -722,64 +735,27 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
/* /*
* Device probe functions. * Device probe functions.
*/ */
static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static void rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
{ {
if (rt2800_efuse_detect(rt2x00dev)) if (rt2800_efuse_detect(rt2x00dev))
rt2800_read_eeprom_efuse(rt2x00dev); rt2800_read_eeprom_efuse(rt2x00dev);
else else
rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
EEPROM_SIZE); EEPROM_SIZE);
return rt2800_validate_eeprom(rt2x00dev);
} }
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
/* retval = rt2800_probe_hw(rt2x00dev);
* Allocate eeprom data.
*/
retval = rt2800usb_validate_eeprom(rt2x00dev);
if (retval)
return retval;
retval = rt2800_init_eeprom(rt2x00dev);
if (retval) if (retval)
return retval; return retval;
/* /*
* Initialize hw specifications. * Set txstatus timer function.
*/ */
retval = rt2800_probe_hw_mode(rt2x00dev); rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;
if (retval)
return retval;
/*
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
*/
__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
/*
* This device requires firmware.
*/
__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout,
/*
* Set the rssi offset.
*/
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
/* /*
* Overwrite TX done handler * Overwrite TX done handler
@ -825,6 +801,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
.register_multiread = rt2x00usb_register_multiread, .register_multiread = rt2x00usb_register_multiread,
.register_multiwrite = rt2x00usb_register_multiwrite, .register_multiwrite = rt2x00usb_register_multiwrite,
.regbusy_read = rt2x00usb_regbusy_read, .regbusy_read = rt2x00usb_regbusy_read,
.read_eeprom = rt2800usb_read_eeprom,
.hwcrypt_disabled = rt2800usb_hwcrypt_disabled,
.drv_write_firmware = rt2800usb_write_firmware, .drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers, .drv_init_registers = rt2800usb_init_registers,
.drv_get_txwi = rt2800usb_get_txwi, .drv_get_txwi = rt2800usb_get_txwi,
@ -1157,6 +1135,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0744) },
{ USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0761) },
{ USB_DEVICE(0x1690, 0x0764) }, { USB_DEVICE(0x1690, 0x0764) },
/* ASUS */
{ USB_DEVICE(0x0b05, 0x179d) },
/* Cisco */ /* Cisco */
{ USB_DEVICE(0x167b, 0x4001) }, { USB_DEVICE(0x167b, 0x4001) },
/* EnGenius */ /* EnGenius */
@ -1222,7 +1202,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1760) },
{ USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1761) },
{ USB_DEVICE(0x0b05, 0x1790) }, { USB_DEVICE(0x0b05, 0x1790) },
{ USB_DEVICE(0x0b05, 0x179d) },
/* AzureWave */ /* AzureWave */
{ USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3262) },
{ USB_DEVICE(0x13d3, 0x3284) }, { USB_DEVICE(0x13d3, 0x3284) },

View File

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

View File

@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
*/ */
if (unlikely(rxdesc.size == 0 || if (unlikely(rxdesc.size == 0 ||
rxdesc.size > entry->queue->data_size)) { rxdesc.size > entry->queue->data_size)) {
WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
rxdesc.size, entry->queue->data_size); rxdesc.size, entry->queue->data_size);
dev_kfree_skb(entry->skb); dev_kfree_skb(entry->skb);
goto renew_skb; goto renew_skb;

View File

@ -243,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg; u32 reg;
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg); rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_BIT5); return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
} }
#ifdef CONFIG_RT2X00_LIB_LEDS #ifdef CONFIG_RT2X00_LIB_LEDS
@ -715,11 +715,11 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg); rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_BIT4, p1); rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
rt2x00_set_field32(&reg, MAC_CSR13_BIT12, 0); rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
rt2x00_set_field32(&reg, MAC_CSR13_BIT3, !p2); rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
rt2x00_set_field32(&reg, MAC_CSR13_BIT11, 0); rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
} }
@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
u32 reg;
/* /*
* Disable power saving. * Disable power saving.
@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval) if (retval)
return retval; return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
/* /*
* Initialize hw specifications. * Initialize hw specifications.
*/ */

View File

@ -357,21 +357,22 @@ struct hw_pairwise_ta_entry {
/* /*
* MAC_CSR13: GPIO. * MAC_CSR13: GPIO.
* MAC_CSR13_VALx: GPIO value
* MAC_CSR13_DIRx: GPIO direction: 0 = output; 1 = input
*/ */
#define MAC_CSR13 0x3034 #define MAC_CSR13 0x3034
#define MAC_CSR13_BIT0 FIELD32(0x00000001) #define MAC_CSR13_VAL0 FIELD32(0x00000001)
#define MAC_CSR13_BIT1 FIELD32(0x00000002) #define MAC_CSR13_VAL1 FIELD32(0x00000002)
#define MAC_CSR13_BIT2 FIELD32(0x00000004) #define MAC_CSR13_VAL2 FIELD32(0x00000004)
#define MAC_CSR13_BIT3 FIELD32(0x00000008) #define MAC_CSR13_VAL3 FIELD32(0x00000008)
#define MAC_CSR13_BIT4 FIELD32(0x00000010) #define MAC_CSR13_VAL4 FIELD32(0x00000010)
#define MAC_CSR13_BIT5 FIELD32(0x00000020) #define MAC_CSR13_VAL5 FIELD32(0x00000020)
#define MAC_CSR13_BIT6 FIELD32(0x00000040) #define MAC_CSR13_DIR0 FIELD32(0x00000100)
#define MAC_CSR13_BIT7 FIELD32(0x00000080) #define MAC_CSR13_DIR1 FIELD32(0x00000200)
#define MAC_CSR13_BIT8 FIELD32(0x00000100) #define MAC_CSR13_DIR2 FIELD32(0x00000400)
#define MAC_CSR13_BIT9 FIELD32(0x00000200) #define MAC_CSR13_DIR3 FIELD32(0x00000800)
#define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_DIR4 FIELD32(0x00001000)
#define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_DIR5 FIELD32(0x00002000)
#define MAC_CSR13_BIT12 FIELD32(0x00001000)
/* /*
* MAC_CSR14: LED control register. * MAC_CSR14: LED control register.

View File

@ -189,7 +189,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg; u32 reg;
rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg); rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_BIT7); return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
} }
#ifdef CONFIG_RT2X00_LIB_LEDS #ifdef CONFIG_RT2X00_LIB_LEDS
@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{ {
int retval; int retval;
u32 reg;
/* /*
* Allocate eeprom data. * Allocate eeprom data.
@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
if (retval) if (retval)
return retval; return retval;
/*
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
/* /*
* Initialize hw specifications. * Initialize hw specifications.
*/ */

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