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)
{
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);
kfree(cores[2]);
kfree(cores[1]);
kfree(cores[0]);
}
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 */
{ USB_DEVICE(0x0489, 0xE03C) },
{ USB_DEVICE(0x0489, 0xE036) },
{ } /* Terminating entry */
};
@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */
};

View File

@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Apple-specific (Broadcom) devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
/* Broadcom SoftSailing reporting vendor specific */
{ USB_DEVICE(0x0a5c, 0x21e1) },
@ -94,16 +97,14 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */
{ 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) },
/* Foxconn - Hon Hai */
{ USB_DEVICE(0x0489, 0xe033) },
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
{ } /* Terminating entry */
};
@ -141,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
/* Broadcom BCM2035 */
{ 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 <linux/wireless.h>
#define WIRELESS_SPY /* enable iwspy support */
#include <net/iw_handler.h> /* New driver API */
#define CISCO_EXT /* enable Cisco extensions */
#ifdef CISCO_EXT
@ -5984,13 +5983,11 @@ static int airo_set_wap(struct net_device *dev,
Cmd cmd;
Resp rsp;
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)
return -EINVAL;
else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
!memcmp(off, awrq->sa_data, ETH_ALEN)) {
else if (is_broadcast_ether_addr(awrq->sa_data) ||
is_zero_ether_addr(awrq->sa_data)) {
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LOSE_SYNC;
if (down_interruptible(&local->sem))

View File

@ -498,36 +498,6 @@ exit:
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 */
static int tx_activity;
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;
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,
hex2str(m->wep_default_keyvalue[i], key_len));
key_len, m->wep_default_keyvalue[i]);
exit:
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 "
"%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 "
"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 "
"multi_domain_capability_implemented %d "
"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),
m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
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->res, m->multi_domain_capability_implemented,
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 "
"scan_type %d scan_channel %d probe_delay %u "
"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),
le32_to_cpu(m->max_tx_msdu_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->max_channel_time),
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);
exit:
kfree(m);
@ -1160,13 +1130,13 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
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),
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),
hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
(int)sizeof(m->tx_powerlevel), m->tx_powerlevel);
exit:
kfree(m);
}
@ -1369,9 +1339,9 @@ static int at76_startup_device(struct at76_priv *priv)
int ret;
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,
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->channel, priv->wep_enabled ? "enabled" : "disabled",
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);
/* 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;
if (aniState->mrcCCK != entry_cck->mrc_cck_on)

View File

@ -138,7 +138,8 @@ static const struct ar9300_eeprom ar9300_default = {
},
.base_ext1 = {
.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 = {
FREQ2FBIN(2412, 1),
@ -713,7 +714,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
},
.base_ext1 = {
.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 = {
FREQ2FBIN(2412, 1),
@ -1289,7 +1291,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
},
.base_ext1 = {
.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 = {
FREQ2FBIN(2412, 1),
@ -1865,7 +1868,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
},
.base_ext1 = {
.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 = {
FREQ2FBIN(2412, 1),
@ -2440,7 +2444,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
},
.base_ext1 = {
.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 = {
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))
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);
else {
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);
if (AR_SREV_9462(ah)) {
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9462_ALL, value);
} 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);
/*
* 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 |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
/* enable_lnadiv */
regval &= (~AR_PHY_9485_ANT_DIV_LNADIV);
regval |= ((value >> 6) & 0x1) <<
AR_PHY_9485_ANT_DIV_LNADIV_S;
regval &= (~AR_PHY_ANT_DIV_LNADIV);
regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
/*enable fast_div */
regval = REG_READ(ah, AR_PHY_CCK_DETECT);
regval &= (~AR_FAST_DIV_ENABLE);
regval |= ((value >> 7) & 0x1) <<
AR_FAST_DIV_ENABLE_S;
regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
ant_div_ctl1 =
ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
/* check whether antenna diversity is enabled */
if ((ant_div_ctl1 >> 0x6) == 0x3) {
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,
* main_tb, alt_tb
*/
regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_GAINTB |
AR_PHY_9485_ANT_DIV_MAIN_GAINTB));
regval &= (~(AR_PHY_ANT_DIV_MAIN_LNACONF |
AR_PHY_ANT_DIV_ALT_LNACONF |
AR_PHY_ANT_DIV_ALT_GAINTB |
AR_PHY_ANT_DIV_MAIN_GAINTB));
/* by default use LNA1 for the main antenna */
regval |= (AR_PHY_9485_ANT_DIV_LNA1 <<
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S);
regval |= (AR_PHY_9485_ANT_DIV_LNA2 <<
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S);
regval |= (AR_PHY_ANT_DIV_LNA1 <<
AR_PHY_ANT_DIV_MAIN_LNACONF_S);
regval |= (AR_PHY_ANT_DIV_LNA2 <<
AR_PHY_ANT_DIV_ALT_LNACONF_S);
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);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
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_WRITE(ah, AR_PHY_PMU1, reg_val);
} else {
@ -3874,7 +3876,7 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
AR_PHY_PMU2_PGM))
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);
else {
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);
}
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,
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_apply_tuning_caps(ah);
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,
@ -4528,7 +4588,7 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
{
int tempSlope = 0;
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,
(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)
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;
f[0] = 5180;
t[1] = eep->modalHeader5G.tempSlope;

View File

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

View File

@ -24,6 +24,7 @@
#include "ar955x_1p0_initvals.h"
#include "ar9580_1p0_initvals.h"
#include "ar9462_2p0_initvals.h"
#include "ar9565_1p0_initvals.h"
/* General hardware code for the AR9003 hadware family */
@ -34,14 +35,12 @@
*/
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) \
ar9462_##x##_baseband_core_txfir_coeff_japan_2484
#define AR9462_BBC_TXIFR_COEFFJ \
ar9462_2p0_baseband_core_txfir_coeff_japan_2484
if (AR_SREV_9330_11(ah)) {
/* mac */
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 */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
PCIE_PLL_ON_CREQ_DIS_L1_2P0);
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
/* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
PCIE_PLL_ON_CREQ_DIS_L1_2P0);
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
/* Fast clock modal settings */
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,
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 {
/* mac */
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))
INIT_INI_ARRAY(&ah->iniModesTxGain,
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
INIT_INI_ARRAY(&ah->iniModesTxGain,
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))
INIT_INI_ARRAY(&ah->iniModesTxGain,
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
INIT_INI_ARRAY(&ah->iniModesTxGain,
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))
INIT_INI_ARRAY(&ah->iniModesTxGain,
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
INIT_INI_ARRAY(&ah->iniModesTxGain,
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))
INIT_INI_ARRAY(&ah->iniModesTxGain,
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
INIT_INI_ARRAY(&ah->iniModesTxGain,
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))
INIT_INI_ARRAY(&ah->iniModesRxGain,
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
INIT_INI_ARRAY(&ah->iniModesRxGain,
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;
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) |
(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_phyerr = phyerr;
}
};
}
}
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;
}
EXPORT_SYMBOL(ar9003_mci_start_reset);
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
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);
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:
ar9003_mci_reset_req_wakeup(ah);
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) {
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;
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;
temp_index = mci->gpm_idx;
if (temp_index >= mci->gpm_len)
temp_index = 0;
mci->gpm_idx++;
if (mci->gpm_idx >= mci->gpm_len)

View File

@ -190,8 +190,6 @@ enum mci_bt_state {
enum mci_state_type {
MCI_STATE_ENABLE,
MCI_STATE_SET_BT_AWAKE,
MCI_STATE_SET_BT_CAL_START,
MCI_STATE_SET_BT_CAL,
MCI_STATE_LAST_SCHD_MSG_OFFSET,
MCI_STATE_REMOTE_SLEEP,
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 i, val;
u32 am2pm_mask = ah->paprd_ratemask;
if (IS_CHAN_2GHZ(ah->curchan))
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;
if (AR_SREV_9330(ah))
am2pm_mask = 0;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask);
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,
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);
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,
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))
status = -2;
if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
status = -EINPROGRESS;
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
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;
chan_frac = (((freq * 4) % div) * 0x20000) / div;
channelSel = (channelSel << 17) | chan_frac;
} else if (AR_SREV_9485(ah)) {
} else if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
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++) {
if (AR_SREV_9462(ah) && (i == 0 || i == 3))
continue;
negative = 0;
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
AR_SREV_9550(ah))
@ -301,7 +302,9 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
int freq_offset,
int spur_freq_sd,
int spur_delta_phase,
int spur_subchannel_sd)
int spur_subchannel_sd,
int range,
int synth_freq)
{
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);
REG_RMW_FIELD(ah, AR_PHY_TIMING11,
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,
AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
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);
}
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,
struct ath9k_channel *chan,
int freq_offset)
int freq_offset,
int range,
int synth_freq)
{
int spur_freq_sd = 0;
int spur_subchannel_sd = 0;
@ -402,7 +443,8 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
freq_offset,
spur_freq_sd,
spur_delta_phase,
spur_subchannel_sd);
spur_subchannel_sd,
range, synth_freq);
}
/* 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 -= synth_freq;
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;
}
}
@ -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,
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);
}
@ -736,7 +789,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (chan->channel == 2484)
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,
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);
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,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
ah->enabled_cals |= TX_IQ_CAL;
else
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))
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.nominal = AR_PHY_CCA_NOM_VAL_9462_2GHZ;
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,
struct ath_hw_antcomb_conf *antconf)
struct ath_hw_antcomb_conf *antconf)
{
u32 regval;
regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >>
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S;
antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >>
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
antconf->main_lna_conf = (regval & AR_PHY_ANT_DIV_MAIN_LNACONF) >>
AR_PHY_ANT_DIV_MAIN_LNACONF_S;
antconf->alt_lna_conf = (regval & AR_PHY_ANT_DIV_ALT_LNACONF) >>
AR_PHY_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_ANT_FAST_DIV_BIAS) >>
AR_PHY_ANT_FAST_DIV_BIAS_S;
if (AR_SREV_9330_11(ah)) {
antconf->lna1_lna2_delta = -9;
@ -1253,22 +1306,21 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
u32 regval;
regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
AR_PHY_9485_ANT_DIV_ALT_LNACONF |
AR_PHY_9485_ANT_FAST_DIV_BIAS |
AR_PHY_9485_ANT_DIV_MAIN_GAINTB |
AR_PHY_9485_ANT_DIV_ALT_GAINTB);
regval |= ((antconf->main_lna_conf <<
AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S)
& AR_PHY_9485_ANT_DIV_MAIN_LNACONF);
regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S)
& AR_PHY_9485_ANT_DIV_ALT_LNACONF);
regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S)
& AR_PHY_9485_ANT_FAST_DIV_BIAS);
regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S)
& AR_PHY_9485_ANT_DIV_MAIN_GAINTB);
regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S)
& AR_PHY_9485_ANT_DIV_ALT_GAINTB);
regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
AR_PHY_ANT_DIV_ALT_LNACONF |
AR_PHY_ANT_FAST_DIV_BIAS |
AR_PHY_ANT_DIV_MAIN_GAINTB |
AR_PHY_ANT_DIV_ALT_GAINTB);
regval |= ((antconf->main_lna_conf << AR_PHY_ANT_DIV_MAIN_LNACONF_S)
& AR_PHY_ANT_DIV_MAIN_LNACONF);
regval |= ((antconf->alt_lna_conf << AR_PHY_ANT_DIV_ALT_LNACONF_S)
& AR_PHY_ANT_DIV_ALT_LNACONF);
regval |= ((antconf->fast_div_bias << AR_PHY_ANT_FAST_DIV_BIAS_S)
& AR_PHY_ANT_FAST_DIV_BIAS);
regval |= ((antconf->main_gaintb << AR_PHY_ANT_DIV_MAIN_GAINTB_S)
& AR_PHY_ANT_DIV_MAIN_GAINTB);
regval |= ((antconf->alt_gaintb << AR_PHY_ANT_DIV_ALT_GAINTB_S)
& AR_PHY_ANT_DIV_ALT_GAINTB);
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->iniBB[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
if (AR_SREV_9462_20(ah))
ar9003_hw_prog_ini(ah,
&ah->ini_radio_post_sys2ant,
modesIndex);
ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
modesIndex);
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))
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);
ah->modes_index = modesIndex;

View File

@ -223,15 +223,24 @@
#define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c)
#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_A 0x1F
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0
#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_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_S 5
#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_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
@ -271,23 +280,23 @@
#define AR_ANT_DIV_ENABLE_S 24
#define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00
#define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9
#define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000
#define AR_PHY_9485_ANT_DIV_LNADIV_S 24
#define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000
#define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25
#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27
#define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000
#define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29
#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30
#define AR_PHY_ANT_FAST_DIV_BIAS 0x00007e00
#define AR_PHY_ANT_FAST_DIV_BIAS_S 9
#define AR_PHY_ANT_DIV_LNADIV 0x01000000
#define AR_PHY_ANT_DIV_LNADIV_S 24
#define AR_PHY_ANT_DIV_ALT_LNACONF 0x06000000
#define AR_PHY_ANT_DIV_ALT_LNACONF_S 25
#define AR_PHY_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR_PHY_ANT_DIV_MAIN_LNACONF_S 27
#define AR_PHY_ANT_DIV_ALT_GAINTB 0x20000000
#define AR_PHY_ANT_DIV_ALT_GAINTB_S 29
#define AR_PHY_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR_PHY_ANT_DIV_MAIN_GAINTB_S 30
#define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0
#define AR_PHY_9485_ANT_DIV_LNA2 0x1
#define AR_PHY_9485_ANT_DIV_LNA1 0x2
#define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3
#define AR_PHY_ANT_DIV_LNA1_MINUS_LNA2 0x0
#define AR_PHY_ANT_DIV_LNA2 0x1
#define AR_PHY_ANT_DIV_LNA1 0x2
#define AR_PHY_ANT_DIV_LNA1_PLUS_LNA2 0x3
#define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c)
#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_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_LATEST_THERM_VALUE 0x000000ff
#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_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_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
#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) || AR_SREV_9565(ah)) ? 0 : 1)
#define AR_PHY_65NM_CH0_SYNTH7 0x16098
#define AR_PHY_65NM_CH0_BIAS1 0x160c0
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
@ -637,7 +656,7 @@
#define AR_PHY_65NM_CH2_RXTX4 0x1690c
#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_S (AR_SREV_9550(ah) ? 6 : 8)
@ -665,7 +684,7 @@
#define AR_SWITCH_TABLE_ALL_S (0)
#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_S 31
@ -687,17 +706,17 @@
#define AR_CH0_TOP2_XPABIASLVL_S 12
#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_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#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_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_S 21
@ -877,6 +896,8 @@
#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_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_S 30

View File

@ -58,7 +58,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
{0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{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_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_beacon(struct ath_softc *sc);
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
/*******************/
/* Link Monitoring */
@ -473,7 +472,7 @@ struct ath_btcoex {
unsigned long op_flags;
int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */
u32 btcoex_period; /* in msec */
u32 btscan_no_stomp; /* in usec */
u32 duty_cycle;
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++;
if (status & ATH9K_INT_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,
@ -418,6 +420,7 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
PR_IS("DTIM", dtim);
PR_IS("TSFOOR", tsfoor);
PR_IS("MCI", mci);
PR_IS("GENTIMER", gen_timer);
PR_IS("TOTAL", total);
len += snprintf(buf + len, mxlen - len,

View File

@ -41,7 +41,6 @@ enum ath_reset_type {
RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG,
RESET_TYPE_BEACON_STUCK,
RESET_TYPE_MCI,
__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
* (programmable) threshold
* @local_timeout: Internal bus timeout.
* @mci: MCI interrupt, specific to MCI based BTCOEX chipsets
* @gen_timer: Generic hardware timer interrupt
*/
struct ath_interrupt_stats {
u32 total;
@ -100,6 +101,7 @@ struct ath_interrupt_stats {
u32 bb_watchdog;
u32 tsfoor;
u32 mci;
u32 gen_timer;
/* Sync-cause stats */
u32 sync_cause_all;

View File

@ -96,6 +96,7 @@
#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
#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 AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
@ -108,7 +109,7 @@
#define EEP_RFSILENT_ENABLED_S 0
#define EEP_RFSILENT_POLARITY 0x0002
#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 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;
else if (AR_SREV_9300(sc->sc_ah))
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;
else
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);
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)
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;
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)

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)
{
int transfer, err;
const void *data = hif_dev->firmware->data;
size_t len = hif_dev->firmware->size;
const void *data = hif_dev->fw_data;
size_t len = hif_dev->fw_size;
u32 addr = AR9271_FIRMWARE;
u8 *buf = kzalloc(4096, GFP_KERNEL);
u32 firm_offset;
@ -1017,7 +1017,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
return -EIO;
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;
}
@ -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->udev->dev);
if (hif_dev->htc_handle == NULL) {
goto err_fw;
}
if (hif_dev->htc_handle == NULL)
goto err_dev_alloc;
hif_dev->firmware = fw;
hif_dev->fw_data = fw->data;
hif_dev->fw_size = fw->size;
/* 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;
}
release_firmware(fw);
hif_dev->flags |= HIF_USB_READY;
complete(&hif_dev->fw_done);
return;
@ -1129,8 +1131,8 @@ err_htc_hw_init:
ath9k_hif_usb_dev_deinit(hif_dev);
err_dev_init:
ath9k_htc_hw_free(hif_dev->htc_handle);
err_dev_alloc:
release_firmware(fw);
hif_dev->firmware = NULL;
err_fw:
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);
if (hif_dev->firmware) {
if (hif_dev->flags & HIF_USB_READY) {
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
ath9k_htc_hw_free(hif_dev->htc_handle);
ath9k_hif_usb_dev_deinit(hif_dev);
release_firmware(hif_dev->firmware);
}
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 htc_target *htc_handle = hif_dev->htc_handle;
int ret;
const struct firmware *fw;
ret = ath9k_hif_usb_alloc_urbs(hif_dev);
if (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);
release_firmware(fw);
if (ret)
goto fail_resume;
} else {

View File

@ -85,12 +85,14 @@ struct cmd_buf {
};
#define HIF_USB_START BIT(0)
#define HIF_USB_READY BIT(1)
struct hif_device_usb {
struct usb_device *udev;
struct usb_interface *interface;
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 htc_target *htc_handle;
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 &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
ath9k_hw_btcoex_disable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_htc_cancel_btcoex_work(priv);
ath9k_hw_btcoex_disable(ah);
}
}
void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
{
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
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) {
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_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) { \
.center_freq = (_freq), \
.hw_value = (_idx), \
@ -635,6 +639,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
common->hw = priv->hw;
common->priv = priv;
common->debug_mask = ath9k_debug;
common->btcoex_enabled = ath9k_htc_btcoex_enable == 1;
spin_lock_init(&priv->beacon_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;
memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
tsta.is_vif_sta = 0;
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 {
memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
tsta.is_vif_sta = 1;
tsta.maxampdu = cpu_to_be16(0xffff);
}
tsta.sta_index = sta_idx;
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);
if (ret) {
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;
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;
else
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;
}
/* PAPRD needs some more work to be enabled */
ah->config.paprd_disable = 1;
ah->config.rx_intr_mitigation = true;
ah->config.pcieSerDesWrite = true;
@ -605,6 +602,11 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (AR_SREV_9462(ah))
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_config(ah);
@ -650,6 +652,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9340:
case AR_SREV_VERSION_9462:
case AR_SREV_VERSION_9550:
case AR_SREV_VERSION_9565:
break;
default:
ath_err(common,
@ -711,7 +714,7 @@ int ath9k_hw_init(struct ath_hw *ah)
int ret;
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) {
case AR5416_DEVID_PCI:
case AR5416_DEVID_PCIE:
@ -731,6 +734,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9580:
case AR9300_DEVID_AR9462:
case AR9485_DEVID_AR1111:
case AR9300_DEVID_AR9565:
break;
default:
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;
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 */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
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);
if (AR_SREV_9565(ah))
pll |= 0x40000;
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
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
imr_reg |= AR_IMR_TXOK;
if (opmode == NL80211_IFTYPE_AP)
imr_reg |= AR_IMR_MIB;
ENABLE_REGWRITE_BUFFER(ah);
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 */
memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan);
} else if (caldata) {
caldata->paprd_packet_sent = false;
}
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);
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_NDP2_TIMER_MODE, 0xff);
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)
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;
else if (AR_SREV_9462(ah))
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)) {
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->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->txs_len = sizeof(struct ar9003_txs);
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;
} else {
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;
}
if (AR_SREV_9462(ah)) {
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
pCap->hw_caps |= ATH9K_HW_CAP_MCI;
if (AR_SREV_9462_20(ah))
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);
if (AR_SREV_9462(ah))
if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
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,
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
* 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,
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 */
REG_CLR_BIT(ah, AR_IMR_S5,
(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_9462, "9462" },
{ AR_SREV_VERSION_9550, "9550" },
{ AR_SREV_VERSION_9565, "9565" },
};
/* For devices with external radios */

View File

@ -50,6 +50,7 @@
#define AR9300_DEVID_AR9330 0x0035
#define AR9300_DEVID_QCA955X 0x0038
#define AR9485_DEVID_AR1111 0x0037
#define AR9300_DEVID_AR9565 0x0036
#define AR5416_AR9100_DEVID 0x000b
@ -405,6 +406,7 @@ struct ath9k_hw_cal_data {
int8_t iCoff;
int8_t qCoff;
bool rtt_done;
bool paprd_packet_sent;
bool paprd_done;
bool nfcal_pending;
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_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;
else if (AR_SREV_9462(ah))
max_streams = 2;

View File

@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)
int chain_ok = 0;
int chain;
int len = 1800;
int ret;
if (!caldata)
if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
return;
ath9k_ps_wakeup(sc);
@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)
continue;
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);
ath_dbg(common, CALIBRATE,
@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)
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,
"PAPRD create curve failed on chain %d\n",
chain);

View File

@ -986,47 +986,21 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
int ret = 0;
ath9k_ps_wakeup(sc);
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);
sc->nvifs++;
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, vif);
ath9k_ps_restore(sc);
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
out:
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
return ret;
return 0;
}
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_common *common = ath9k_hw_common(sc->sc_ah);
int ret = 0;
ath_dbg(common, CONFIG, "Change Interface\n");
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))
ath9k_beacon_remove_slot(sc, vif);
@ -1058,14 +1020,15 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
vif->type = new_type;
vif->p2p = p2p;
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, vif);
ath9k_ps_restore(sc);
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
out:
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
return ret;
return 0;
}
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");
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
sc->nvifs--;
@ -1084,10 +1046,11 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_remove_slot(sc, vif);
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, NULL);
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
ath9k_ps_restore(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);
ath_cancel_work(sc);
del_timer_sync(&common->ani.timer);
ath_stop_ani(sc);
del_timer_sync(&sc->rx_poll_timer);
if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {

View File

@ -191,6 +191,23 @@ skip_tuning:
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)
{
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) {
case MCI_GPM_BT_CAL_REQ:
if (mci_hw->bt_state == MCI_BT_AWAKE) {
ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
ath9k_queue_reset(sc, RESET_TYPE_MCI);
mci_hw->bt_state = MCI_BT_CAL_START;
ath_mci_wait_btcal_done(sc);
}
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
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, 0x0034) }, /* PCI-E AR9462 */
{ PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */
{ 0 }
};

View File

@ -801,6 +801,8 @@
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_VERSION_9462 0x280
#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_5416(_ah) \
@ -909,6 +911,13 @@
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_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) \
(((_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) {
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;
}
}
@ -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);
if (sc->sc_ah->caldata)
sc->sc_ah->caldata->paprd_packet_sent = true;
if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
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
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
bool "Broadcom driver debug functions"
depends on BRCMSMAC || BRCMFMAC

View File

@ -42,6 +42,7 @@
#define DMA_ALIGN_MASK 0x03
#define SDIO_DEVICE_ID_BROADCOM_43241 0x4324
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
@ -51,6 +52,7 @@
/* devices we support, null terminated */
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_4330)},
{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_GROUP 0x04
#define BRCMF_ESCAN_REQ_VERSION 1
#define WLC_BSS_RSSI_ON_CHANNEL 0x0002
struct brcmf_event_msg {
__be16 version;
__be16 flags;
@ -140,6 +144,8 @@ struct brcmf_event_msg {
__be32 datalen;
u8 addr[ETH_ALEN];
char ifname[IFNAMSIZ];
u8 ifidx;
u8 bsscfgidx;
} __packed;
struct brcm_ethhdr {
@ -454,6 +460,24 @@ struct brcmf_scan_results_le {
__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 */
struct brcmf_assoc_params_le {
/* 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 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 */
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);
/* 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 */
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_IF, "IF"}, {
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;
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);
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_LOST:
case BRCMF_E_PFN_SCAN_COMPLETE:

View File

@ -350,19 +350,23 @@ done:
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 brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
int i;
brcmf_dbg(TRACE, "Enter\n");
ndev = drvr->iflist[ifidx]->ndev;
if (state == ON)
netif_stop_queue(ndev);
else
netif_wake_queue(ndev);
for (i = 0; i < BRCMF_MAX_IFS; i++)
if (drvr->iflist[i]) {
ndev = drvr->iflist[i]->ndev;
if (state)
netif_stop_queue(ndev);
else
netif_wake_queue(ndev);
}
}
static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
@ -775,6 +779,14 @@ done:
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)
{
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 &&
(bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
bus->txoff = OFF;
brcmf_txflowcontrol(bus->sdiodev->dev, 0, OFF);
bus->txoff = false;
brcmf_txflowblock(bus->sdiodev->dev, false);
}
return cnt;
@ -2672,8 +2672,8 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
spin_unlock_bh(&bus->txqlock);
if (pktq_len(&bus->txq) >= TXHI) {
bus->txoff = ON;
brcmf_txflowcontrol(bus->sdiodev->dev, 0, ON);
bus->txoff = true;
brcmf_txflowblock(bus->sdiodev->dev, true);
}
#ifdef DEBUG
@ -3881,6 +3881,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
if (chipid == BCM43241_CHIP_ID)
return true;
if (chipid == BCM4329_CHIP_ID)
return true;
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 */
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:
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;

View File

@ -66,7 +66,9 @@
#define BRCMF_USB_CBCTL_READ 1
#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_43242_FW_NAME "brcm/brcmfmac43242a.bin"
enum usbdev_suspend_state {
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 */
};
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 {
void *data;
u32 len;
@ -117,9 +105,8 @@ struct brcmf_usbdev_info {
int rx_low_watermark;
int tx_low_watermark;
int tx_high_watermark;
bool txoff;
bool rxoff;
bool txoverride;
int tx_freecount;
bool tx_flowblock;
struct brcmf_usbreq *tx_reqs;
struct brcmf_usbreq *rx_reqs;
@ -133,7 +120,6 @@ struct brcmf_usbdev_info {
struct usb_device *usbdev;
struct device *dev;
enum usb_device_speed device_speed;
int ctl_in_pipe, ctl_out_pipe;
struct urb *ctl_urb; /* URB for control endpoint */
@ -153,9 +139,6 @@ struct brcmf_usbdev_info {
int intr_size; /* Size of interrupt message */
int interval; /* Interrupt polling interval */
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,
@ -177,14 +160,6 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
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,
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))
return -EIO;
devinfo->ctl_completed = false;
err = brcmf_usb_send_ctl(devinfo, buf, len);
if (err) {
brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
return err;
}
devinfo->ctl_completed = false;
timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
&pending);
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,
struct list_head *q)
struct list_head *q, int *counter)
{
unsigned long flags;
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);
list_del_init(q->next);
if (counter)
(*counter)--;
spin_unlock_irqrestore(&devinfo->qlock, flags);
return req;
}
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;
spin_lock_irqsave(&devinfo->qlock, flags);
list_add_tail(&req->list, q);
if (counter)
(*counter)++;
spin_unlock_irqrestore(&devinfo->qlock, flags);
}
@ -519,10 +499,14 @@ static void brcmf_usb_tx_complete(struct urb *urb)
else
devinfo->bus_pub.bus->dstats.tx_errors++;
dev_kfree_skb(req->skb);
brcmu_pkt_buf_free_skb(req->skb);
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)
@ -540,8 +524,8 @@ static void brcmf_usb_rx_complete(struct urb *urb)
devinfo->bus_pub.bus->dstats.rx_packets++;
} else {
devinfo->bus_pub.bus->dstats.rx_errors++;
dev_kfree_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
return;
}
@ -551,12 +535,12 @@ static void brcmf_usb_rx_complete(struct urb *urb)
brcmf_dbg(ERROR, "rx protocol error\n");
brcmu_pkt_buf_free_skb(skb);
devinfo->bus_pub.bus->dstats.rx_errors++;
} else {
} else
brcmf_rx_packet(devinfo->dev, ifidx, skb);
brcmf_usb_rx_refill(devinfo, req);
}
brcmf_usb_rx_refill(devinfo, req);
} else {
dev_kfree_skb(skb);
brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
}
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);
if (!skb) {
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
return;
}
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,
skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
req);
req->urb->transfer_flags |= URB_ZERO_PACKET;
req->devinfo = devinfo;
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);
ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (ret == 0) {
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
} else {
dev_kfree_skb(req->skb);
if (ret) {
brcmf_usb_del_fromq(devinfo, req);
brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
}
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");
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);
}
@ -681,27 +664,34 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
return -EIO;
}
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
&devinfo->tx_freecount);
if (!req) {
brcmu_pkt_buf_free_skb(skb);
brcmf_dbg(ERROR, "no req to send\n");
return -ENOMEM;
}
if (!req->urb) {
brcmf_dbg(ERROR, "no urb for req %p\n", req);
return -ENOBUFS;
}
req->skb = skb;
req->devinfo = devinfo;
usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
skb->data, skb->len, brcmf_usb_tx_complete, req);
req->urb->transfer_flags |= URB_ZERO_PACKET;
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (!ret) {
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
} else {
if (ret) {
brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
brcmf_usb_del_fromq(devinfo, req);
brcmu_pkt_buf_free_skb(req->skb);
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;
@ -1112,10 +1102,14 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
static bool brcmf_usb_chip_support(int chipid, int chiprev)
{
switch(chipid) {
case 43143:
return true;
case 43235:
case 43236:
case 43238:
return (chiprev == 3);
case 43242:
return true;
default:
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);
/* 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->rx_reqs);
kfree(devinfo);
}
#define TRX_MAGIC 0x30524448 /* "HDR0" */
@ -1228,7 +1218,22 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
if (devinfo->image)
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);
if (!fw) {
@ -1253,14 +1258,9 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
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->rx_low_watermark = nrxq / 2;
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 */
devinfo->tx_low_watermark = ntxq / 4;
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;
/* 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_postq);
devinfo->tx_flowblock = false;
devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
if (!devinfo->rx_reqs)
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);
if (!devinfo->tx_reqs)
goto error;
devinfo->tx_freecount = ntxq;
devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->intr_urb) {
@ -1336,19 +1327,19 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
error:
brcmf_dbg(ERROR, "failed!\n");
brcmf_usb_detach(&devinfo->bus_pub);
brcmf_usb_detach(devinfo);
return NULL;
}
static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
u32 bustype, u32 hdrlen)
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
const char *desc, u32 bustype, u32 hdrlen)
{
struct brcmf_bus *bus = NULL;
struct brcmf_usbdev *bus_pub = NULL;
int ret;
struct device *dev = devinfo->dev;
bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev);
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
if (!bus_pub) {
ret = -ENODEV;
goto fail;
@ -1387,23 +1378,21 @@ static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
return 0;
fail:
/* Release resources in reverse order */
if (bus_pub)
brcmf_usb_detach(bus_pub);
kfree(bus);
brcmf_usb_detach(devinfo);
return ret;
}
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;
brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub);
brcmf_detach(bus_pub->devinfo->dev);
kfree(bus_pub->bus);
brcmf_usb_detach(bus_pub);
brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
brcmf_detach(devinfo->dev);
kfree(devinfo->bus_pub.bus);
brcmf_usb_detach(devinfo);
}
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);
int num_of_eps;
u8 endpoint_num;
struct brcmf_usbdev_info *devinfo;
brcmf_dbg(TRACE, "enter\n");
usbdev_probe_info.usb = usb;
usbdev_probe_info.intf = intf;
devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
if (devinfo == NULL)
return -ENOMEM;
if (id != NULL) {
usbdev_probe_info.vid = id->idVendor;
usbdev_probe_info.pid = id->idProduct;
}
devinfo->usbdev = usb;
devinfo->dev = &usb->dev;
usb_set_intfdata(intf, &usbdev_probe_info);
usb_set_intfdata(intf, devinfo);
/* Check that the device supports only one configuration */
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;
usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num);
devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num);
usbdev_probe_info.rx_pipe = 0;
usbdev_probe_info.rx_pipe2 = 0;
usbdev_probe_info.tx_pipe = 0;
devinfo->rx_pipe = 0;
devinfo->rx_pipe2 = 0;
devinfo->tx_pipe = 0;
num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
/* 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;
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
== USB_DIR_IN) {
if (!usbdev_probe_info.rx_pipe) {
usbdev_probe_info.rx_pipe =
if (!devinfo->rx_pipe) {
devinfo->rx_pipe =
usb_rcvbulkpipe(usb, endpoint_num);
} else {
usbdev_probe_info.rx_pipe2 =
devinfo->rx_pipe2 =
usb_rcvbulkpipe(usb, endpoint_num);
}
} else {
usbdev_probe_info.tx_pipe =
usb_sndbulkpipe(usb, endpoint_num);
devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num);
}
}
/* Allocate interrupt URB and data buffer */
/* RNDIS says 8-byte intr, our old drivers used 4-byte */
if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
usbdev_probe_info.intr_size = 8;
devinfo->intr_size = 8;
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)
brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
else
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)
goto fail;
@ -1533,6 +1520,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
fail:
brcmf_dbg(ERROR, "failed with errno %d\n", ret);
kfree(devinfo);
usb_set_intfdata(intf, NULL);
return ret;
@ -1541,11 +1529,12 @@ fail:
static void
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_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev));
usb_set_intfdata(intf, NULL);
devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
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_DEVICE_ID_43143 0xbd1e
#define BRCMF_USB_DEVICE_ID_43236 0xbd17
#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
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_43242) },
/* special entry for device with firmware loaded and running */
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
{ }
};
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_43242_FW_NAME);
/* TODO: suspend and resume entries */
static struct usb_driver brcmf_usbdrvr = {

View File

@ -28,6 +28,7 @@
#include <linux/ieee80211.h>
#include <linux/uaccess.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
#include <brcmu_utils.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,
struct brcmf_ssid *ssid)
static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
struct brcmf_ssid *ssid)
{
memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
params_le->bss_type = DOT11_BSSTYPE_ANY;
@ -544,7 +545,7 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
return -ENOMEM;
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->action = cpu_to_le16(action);
@ -597,9 +598,9 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
}
static s32
__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid)
brcmf_cfg80211_iscan(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;
@ -690,11 +691,342 @@ scan_out:
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
brcmf_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct net_device *ndev = request->wdev->netdev;
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
s32 err = 0;
WL_TRACE("Enter\n");
@ -702,7 +1034,11 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
if (!check_sys_up(wiphy))
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)
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)) {
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,
sizeof(struct brcmf_scb_val_le));
if (err)
if (err) {
WL_ERR("Could not get rssi (%d)\n", err);
rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi;
WL_CONN("RSSI %d dBm\n", rssi);
} else {
rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi;
WL_CONN("RSSI %d dBm\n", rssi);
}
}
done:
@ -2470,6 +2807,175 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
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)
{
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);
/* Turn off watchdog timer */
if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
WL_INFO("Enable MPC\n");
if (test_bit(WL_STATUS_READY, &cfg_priv->status))
brcmf_set_mpc(ndev, 1);
}
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 = {
.change_virtual_intf = brcmf_cfg80211_change_iface,
.scan = brcmf_cfg80211_scan,
@ -2745,7 +3268,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.resume = brcmf_cfg80211_resume,
.set_pmksa = brcmf_cfg80211_set_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)
@ -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);
err = brcmf_inform_bss(cfg_priv);
if (err) {
if (err)
scan_abort = true;
goto scan_done_out;
}
scan_done_out:
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;
kfree(cfg_priv->scan_req_int);
cfg_priv->scan_req_int = NULL;
kfree(cfg_priv->escan_ioctl_buf);
cfg_priv->escan_ioctl_buf = NULL;
kfree(cfg_priv->dcmd_buf);
cfg_priv->dcmd_buf = NULL;
kfree(cfg_priv->extra_buf);
@ -3248,6 +3774,9 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
GFP_KERNEL);
if (!cfg_priv->scan_req_int)
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);
if (!cfg_priv->dcmd_buf)
goto init_priv_mem_out;
@ -3297,18 +3826,28 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event(
static s32
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;
s32 err = 0;
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)
return -ENOMEM;
e->etype = event;
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);
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->pwr_save = true;
#ifdef CONFIG_BRCMISCAN
cfg_priv->iscan_on = true; /* iscan on & off switch.
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.
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);
if (err)
return err;
brcmf_init_escan(cfg_priv);
brcmf_init_conf(cfg_priv->conf);
brcmf_init_prof(cfg_priv->profile);
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);
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);
}
@ -3551,6 +4100,7 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, BRCMF_E_TXFAIL);
setbit(eventmask, BRCMF_E_JOIN_START);
setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
setbit(eventmask, BRCMF_E_ESCAN_RESULT);
brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
iovbuf, sizeof(iovbuf));

View File

@ -123,6 +123,13 @@ do { \
#define WL_SCAN_UNASSOC_TIME 40
#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 */
enum wl_status {
WL_STATUS_READY,
@ -275,6 +282,19 @@ struct brcmf_cfg80211_pmk_list {
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 */
struct brcmf_cfg80211_priv {
struct wireless_dev *wdev; /* representing wl cfg80211 device */
@ -315,6 +335,11 @@ struct brcmf_cfg80211_priv {
u8 *dcmd_buf; /* dcmd buffer */
u8 *extra_buf; /* maily to grab assoc information */
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);
};

View File

@ -535,9 +535,6 @@ void ai_detach(struct si_pub *sih)
{
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);
if (sii == NULL)

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <net/lib80211.h>
#include "hostap_wlan.h"
@ -3221,8 +3222,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
return -EINVAL;
addr = ext->addr.sa_data;
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
if (is_broadcast_ether_addr(addr)) {
sta_ptr = NULL;
crypt = &local->crypt_info.crypt[i];
} else {
@ -3394,8 +3394,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
i--;
addr = ext->addr.sa_data;
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
if (is_broadcast_ether_addr(addr)) {
sta_ptr = NULL;
crypt = &local->crypt_info.crypt[i];
} else {
@ -3458,9 +3457,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
param->u.crypt.key_len)
return -EINVAL;
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
if (is_broadcast_ether_addr(param->sta_addr)) {
if (param->u.crypt.idx >= WEP_KEYS)
return -EINVAL;
sta_ptr = NULL;
@ -3593,9 +3590,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
if (max_key_len < 0)
return -EINVAL;
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
if (is_broadcast_ether_addr(param->sta_addr)) {
sta_ptr = NULL;
if (param->u.crypt.idx >= WEP_KEYS)
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);
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)
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);
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
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
return -EINVAL;
@ -6981,8 +6974,8 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
goto done;
}
if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
!memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
if (is_broadcast_ether_addr(wrqu->ap_addr.sa_data) ||
is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
/* we disable mandatory BSSID association */
IPW_DEBUG_WX("exit - disable mandatory BSSID\n");
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);
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)
return -EINVAL;
mutex_lock(&priv->mutex);
if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
!memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
if (is_broadcast_ether_addr(wrqu->ap_addr.sa_data) ||
is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
/* we disable mandatory BSSID association */
IPW_DEBUG_WX("Setting AP BSSID to ANY\n");
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_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_ANTENNA_MSK 0xf0
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70
#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_NONE (0x0 << 8)

View File

@ -771,6 +771,7 @@ struct iwl_priv {
u8 agg_tids_count;
struct iwl_rx_phy_res last_phy_res;
u32 ampdu_ref;
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);
priv->last_phy_res_valid = true;
priv->ampdu_ref++;
memcpy(&priv->last_phy_res, pkt->data,
sizeof(struct iwl_rx_phy_res));
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)
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 */
if (rate_n_flags & RATE_MCS_HT_MSK)
rx_status.flag |= RX_FLAG_HT;

View File

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

View File

@ -85,8 +85,6 @@ struct iwl_eeprom_data {
int n_hw_addrs;
u8 hw_addr[ETH_ALEN];
u16 radio_config;
u8 calib_version;
__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;
int i;
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);
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);
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++) {
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,
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;
txq->need_update = 1;
/* check that tracing gets all possible blocks */
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
#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
trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
&out_cmd->hdr, copy_size);
/* start timer if queue currently empty */
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);
}
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
* 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);
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,
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);
/* 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",
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 */
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:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;

View File

@ -175,23 +175,6 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
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.
*
@ -257,27 +240,6 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
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.
*

View File

@ -28,8 +28,6 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
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,
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);
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
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,
struct host_cmd_ds_command *cmd,
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,
};
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.
*
@ -969,15 +999,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
bss_cfg->channel =
(u8)ieee80211_frequency_to_channel(params->channel->center_freq);
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
/* Set appropriate bands */
if (params->channel->band == IEEE80211_BAND_2GHZ) {
bss_cfg->band_cfg = BAND_CONFIG_BG;
if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_B | BAND_G;
else
config_bands = BAND_B | BAND_G | BAND_GN;
} else {
bss_cfg->band_cfg = BAND_CONFIG_A;
if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
@ -988,6 +1021,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
~priv->adapter->fw_bands))
priv->adapter->config_bands = config_bands;
mwifiex_set_uap_rates(bss_cfg, params);
mwifiex_send_domain_info_cmd_fw(wiphy);
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->config_bands = config_bands;
}
mwifiex_send_domain_info_cmd_fw(priv->wdev->wiphy);
}
/* 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->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_num = 0;
@ -1660,7 +1693,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
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_started = 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);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
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 |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
@ -1859,8 +1895,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
return ret;
}
country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
if (country_code && regulatory_hint(wiphy, country_code))
dev_err(adapter->dev, "regulatory_hint() failed\n");
if (country_code)
dev_info(adapter->dev,
"ignoring F/W country code %2.2s\n", country_code);
adapter->wiphy = wiphy;
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_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);
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 TLV_TYPE_UAP_SSID 0x0000
#define TLV_TYPE_UAP_RATES 0x0001
#define PROPRIETARY_TLV_BASE_ID 0x0100
#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 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_GAP_DEF 0
@ -1284,6 +1285,11 @@ struct host_cmd_tlv_ssid {
u8 ssid[0];
} __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 tlv;
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,
&adapter->scan_pending_q, list) {
list_del(&cmd_node->list);
cmd_node->wait_q_enabled = false;
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
}
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);
priv->user_scan_cfg = NULL;
}
if (priv->scan_pending_on_block) {
priv->scan_pending_on_block = false;
up(&priv->async_sem);
}
goto done;
}

View File

@ -81,7 +81,11 @@ struct wep_key {
#define KEY_MGMT_ON_HOST 0x03
#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 {
u8 channel;
u8 band_cfg;
@ -100,6 +104,7 @@ struct mwifiex_uap_bss_param {
struct wpa_param wpa_cfg;
struct wep_key wep_cfg[NUM_WEP_KEYS];
struct ieee80211_ht_cap ht_cap;
u8 rates[MWIFIEX_SUPPORTED_RATES];
};
enum {

View File

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

View File

@ -116,6 +116,7 @@ enum {
#define MAX_BITMAP_RATES_SIZE 10
#define MAX_CHANNEL_BAND_BG 14
#define MAX_CHANNEL_BAND_A 165
#define MAX_FREQUENCY_BAND_BG 2484
@ -249,10 +250,6 @@ struct ieee_types_header {
u8 len;
} __packed;
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
struct ieee_types_vendor_specific {
struct ieee_types_vendor_header vend_hdr;
u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
@ -487,6 +484,7 @@ struct mwifiex_private {
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
u8 subsc_evt_rssi_state;
struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage;
struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
u16 beacon_idx;
u16 proberesp_idx;
@ -814,6 +812,7 @@ struct mwifiex_sta_node *
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
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_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
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,
struct mwifiex_uap_bss_param *bss_cfg,
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.

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_wildcard_ssid_params *wildcard_ssid_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;
u32 num_probes;
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.
*/
if ((i && ssid_filter) ||
memcmp(scan_cfg_out->specific_bssid, &zero_mac,
sizeof(zero_mac)))
!is_zero_ether_addr(scan_cfg_out->specific_bssid))
*filtered_scan = true;
} else {
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;
u16 key_param_len = 0, cmd_size;
int ret = 0;
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
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 */
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 */
key_material->key_param_set.key_info |=
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 =
&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_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)
return 0;
memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
/* 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.action = HostCmd_ACT_BITWISE_SET;
subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
subsc_evt->action = HostCmd_ACT_BITWISE_SET;
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);
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) {
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_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
priv->cqm_rssi_hyst);
}
subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
priv->subsc_evt_rssi_state = EVENT_HANDLED;
mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
0, 0, &subsc_evt);
0, 0, subsc_evt);
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 =
&(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)
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);
/* 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");
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.
*/
static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
struct mwifiex_ds_misc_subsc_evt *sub_event)
struct host_cmd_ds_command *resp)
{
struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
&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",
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;
}
@ -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));
break;
case HostCmd_CMD_AMSDU_AGGR_CTRL:
ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf);
break;
case HostCmd_CMD_WMM_GET_STATUS:
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:
break;
case HostCmd_CMD_11N_CFG:
ret = mwifiex_ret_11n_cfg(resp, data_buf);
break;
case HostCmd_CMD_PCIE_DESC_DETAILS:
break;
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
ret = mwifiex_ret_subsc_evt(priv, resp, data_buf);
ret = mwifiex_ret_subsc_evt(priv, resp);
break;
case HostCmd_CMD_UAP_SYS_CONFIG:
break;

View File

@ -192,6 +192,44 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
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 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;
if (bss) {
mwifiex_process_country_ie(priv, bss);
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
GFP_KERNEL);

View File

@ -75,7 +75,11 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
u8 *head_ptr;
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 (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd =

View File

@ -177,6 +177,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
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 helps FW in ignoring invalid values. These values may or may not
* 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_encrypt_protocol *encrypt_protocol;
struct host_cmd_tlv_auth_type *auth_type;
struct host_cmd_tlv_rates *tlv_rates;
struct mwifiex_ie_types_htcap *htcap;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
int i;
u16 cmd_size = *param_size;
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);
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->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
chan_band->tlv.len =

View File

@ -253,3 +253,73 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
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 ==
(struct mwifiex_bss_prio_node *)
&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]
.bss_prio_head,
struct mwifiex_bss_prio_node,
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 {
priv_tmp = bssprio_node->priv;
hqp = &priv_tmp->wmm.highest_queued_prio;

View File

@ -7,6 +7,7 @@
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/cfg80211.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);
int err = -EINPROGRESS; /* Call commit handler */
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)
return -EBUSY;
/* Enable automatic roaming - no sanity checks are needed */
if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
if (is_zero_ether_addr(ap_addr->sa_data) ||
is_broadcast_ether_addr(ap_addr->sa_data)) {
priv->bssid_fixed = 0;
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,
struct ieee80211_vif *vif)
{
struct ieee80211_tx_control control = { };
struct sk_buff *beacon;
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
* 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_low32 = 0;

View File

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

View File

@ -205,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 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
@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
u32 reg;
/*
* Allocate eeprom data.
@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (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.
*/

View File

@ -660,16 +660,26 @@
/*
* GPIOCSR: GPIO control register.
* GPIOCSR_VALx: Actual GPIO pin x value
* GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
*/
#define GPIOCSR 0x0120
#define GPIOCSR_BIT0 FIELD32(0x00000001)
#define GPIOCSR_BIT1 FIELD32(0x00000002)
#define GPIOCSR_BIT2 FIELD32(0x00000004)
#define GPIOCSR_BIT3 FIELD32(0x00000008)
#define GPIOCSR_BIT4 FIELD32(0x00000010)
#define GPIOCSR_BIT5 FIELD32(0x00000020)
#define GPIOCSR_BIT6 FIELD32(0x00000040)
#define GPIOCSR_BIT7 FIELD32(0x00000080)
#define GPIOCSR_VAL0 FIELD32(0x00000001)
#define GPIOCSR_VAL1 FIELD32(0x00000002)
#define GPIOCSR_VAL2 FIELD32(0x00000004)
#define GPIOCSR_VAL3 FIELD32(0x00000008)
#define GPIOCSR_VAL4 FIELD32(0x00000010)
#define GPIOCSR_VAL5 FIELD32(0x00000020)
#define GPIOCSR_VAL6 FIELD32(0x00000040)
#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.

View File

@ -205,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 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
@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
u32 reg;
/*
* Allocate eeprom data.
@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (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.
*/

View File

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

View File

@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u16 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
@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
u16 reg;
/*
* Allocate eeprom data.
@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
if (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.
*/

View File

@ -187,16 +187,26 @@
/*
* 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_BIT0 FIELD32(0x0001)
#define MAC_CSR19_BIT1 FIELD32(0x0002)
#define MAC_CSR19_BIT2 FIELD32(0x0004)
#define MAC_CSR19_BIT3 FIELD32(0x0008)
#define MAC_CSR19_BIT4 FIELD32(0x0010)
#define MAC_CSR19_BIT5 FIELD32(0x0020)
#define MAC_CSR19_BIT6 FIELD32(0x0040)
#define MAC_CSR19_BIT7 FIELD32(0x0080)
#define MAC_CSR19_VAL0 FIELD16(0x0001)
#define MAC_CSR19_VAL1 FIELD16(0x0002)
#define MAC_CSR19_VAL2 FIELD16(0x0004)
#define MAC_CSR19_VAL3 FIELD16(0x0008)
#define MAC_CSR19_VAL4 FIELD16(0x0010)
#define MAC_CSR19_VAL5 FIELD16(0x0020)
#define MAC_CSR19_VAL6 FIELD16(0x0040)
#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.

View File

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

View File

@ -923,8 +923,8 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
} else {
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
}
}
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,
eesk_pin, 0);
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, gpio_bit3);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
}
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:
if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390)) {
rt2x00_eeprom_read(rt2x00dev,
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_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT7, 0);
rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
if (rf->channel <= 14)
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 1);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
else
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 0);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
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,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@ -2182,6 +2237,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
case RF3290:
rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
break;
case RF3322:
rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
break;
case RF5360:
case RF5370:
case RF5372:
@ -2194,6 +2252,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
if (rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3322) ||
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) ||
@ -2212,10 +2271,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Change BBP settings
*/
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 (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 27, 0x0);
rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
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 (!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_BUSY_STA, &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)
@ -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_CFG1, 0x00000000);
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)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
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)))
return -EACCES;
if (rt2x00_rt(rt2x00dev, RT3352)) {
rt2800_bbp_write(rt2x00dev, 3, 0x00);
rt2800_bbp_write(rt2x00dev, 4, 0x50);
}
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
@ -3388,15 +3472,20 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2800_is_305x_soc(rt2x00dev) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
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, 66, 0x38);
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
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, 73, 0x12);
} else if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
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)) {
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
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 {
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);
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 86, 0x38);
else
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, 91, 0x04);
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
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, RT3390, REV_RT3390E) ||
rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
@ -3502,6 +3600,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 103, 0x00);
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
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);
else if (rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 105, 0x1c);
else if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 105, 0x34);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c);
@ -3519,11 +3620,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 106, 0x03);
else if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 106, 0x05);
else if (rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 106, 0x12);
else
rt2800_bbp_write(rt2x00dev, 106, 0x35);
if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 120, 0x50);
if (rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
@ -3534,6 +3640,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 135, 0xf6);
}
if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 137, 0x0f);
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
@ -3574,6 +3683,28 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
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) ||
rt2x00_rt(rt2x00dev, RT5392)) {
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)) {
u32 reg;
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT6, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 0);
rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 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)
rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 1);
rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 1);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
}
/* 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, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3290) &&
!rt2x00_rt(rt2x00dev, RT3352) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
!rt2x00_rt(rt2x00dev, RT3572) &&
!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, 31, 0x00);
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)) {
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
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);
msleep(1);
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);
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);
} else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390) ||
rt2x00_rt(rt2x00dev, RT3572)) {
drv_data->calibration_bw20 =
@ -4391,13 +4589,18 @@ void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
}
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;
u16 word;
u8 *mac;
u8 default_lna_gain;
/*
* Read the EEPROM.
*/
rt2800_read_eeprom(rt2x00dev);
/*
* Start validation of the data that has been read.
*/
@ -4520,9 +4723,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
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;
u16 value;
@ -4561,6 +4763,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RT3071:
case RT3090:
case RT3290:
case RT3352:
case RT3390:
case RT3572:
case RT5390:
@ -4583,6 +4786,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF3052:
case RF3290:
case RF3320:
case RF3322:
case RF5360:
case RF5370:
case RF5372:
@ -4607,6 +4811,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390)) {
value = rt2x00_get_field16(eeprom,
EEPROM_NIC_CONF1_ANT_DIVERSITY);
@ -4680,7 +4885,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
/*
* RF value list for rt28xx
@ -4823,7 +5027,7 @@ static const struct rf_channel rf_vals_3x[] = {
{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 channel_info *info;
@ -4900,6 +5104,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF3022) ||
rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3320) ||
rt2x00_rf(rt2x00dev, RF3322) ||
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) ||
@ -4999,7 +5204,72 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
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.

View File

@ -43,6 +43,9 @@ struct rt2800_ops {
const unsigned int offset,
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,
const u8 *data, const size_t len);
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);
}
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,
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);
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_mode(struct rt2x00_dev *rt2x00dev);
int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);
void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
u16 *iv16);

View File

@ -54,6 +54,11 @@ static bool modparam_nohwcrypt = false;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
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)
{
unsigned int i;
@ -965,76 +970,14 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
/*
* 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))
rt2800pci_read_eeprom_soc(rt2x00dev);
else if (rt2800pci_efuse_detect(rt2x00dev))
rt2800pci_read_eeprom_efuse(rt2x00dev);
else
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 = {
@ -1072,6 +1015,8 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.register_multiread = rt2x00pci_register_multiread,
.register_multiwrite = rt2x00pci_register_multiwrite,
.regbusy_read = rt2x00pci_regbusy_read,
.read_eeprom = rt2800pci_read_eeprom,
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800pci_init_registers,
.drv_get_txwi = rt2800pci_get_txwi,
@ -1084,7 +1029,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.tbtt_tasklet = rt2800pci_tbtt_tasklet,
.rxdone_tasklet = rt2800pci_rxdone_tasklet,
.autowake_tasklet = rt2800pci_autowake_tasklet,
.probe_hw = rt2800pci_probe_hw,
.probe_hw = rt2800_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_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_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
}
/*
* Queue handlers.
*/
@ -667,8 +672,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
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);
/*
@ -722,64 +735,27 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
/*
* 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))
rt2800_read_eeprom_efuse(rt2x00dev);
else
rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
EEPROM_SIZE);
return rt2800_validate_eeprom(rt2x00dev);
}
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
/*
* Allocate eeprom data.
*/
retval = rt2800usb_validate_eeprom(rt2x00dev);
if (retval)
return retval;
retval = rt2800_init_eeprom(rt2x00dev);
retval = rt2800_probe_hw(rt2x00dev);
if (retval)
return retval;
/*
* Initialize hw specifications.
* Set txstatus timer function.
*/
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 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;
rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;
/*
* Overwrite TX done handler
@ -825,6 +801,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
.register_multiread = rt2x00usb_register_multiread,
.register_multiwrite = rt2x00usb_register_multiwrite,
.regbusy_read = rt2x00usb_regbusy_read,
.read_eeprom = rt2800usb_read_eeprom,
.hwcrypt_disabled = rt2800usb_hwcrypt_disabled,
.drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers,
.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, 0x0761) },
{ USB_DEVICE(0x1690, 0x0764) },
/* ASUS */
{ USB_DEVICE(0x0b05, 0x179d) },
/* Cisco */
{ USB_DEVICE(0x167b, 0x4001) },
/* EnGenius */
@ -1222,7 +1202,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1760) },
{ USB_DEVICE(0x0b05, 0x1761) },
{ USB_DEVICE(0x0b05, 0x1790) },
{ USB_DEVICE(0x0b05, 0x179d) },
/* AzureWave */
{ USB_DEVICE(0x13d3, 0x3262) },
{ USB_DEVICE(0x13d3, 0x3284) },

View File

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

View File

@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
*/
if (unlikely(rxdesc.size == 0 ||
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);
dev_kfree_skb(entry->skb);
goto renew_skb;

View File

@ -243,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 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
@ -715,11 +715,11 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_BIT4, p1);
rt2x00_set_field32(&reg, MAC_CSR13_BIT12, 0);
rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
rt2x00_set_field32(&reg, MAC_CSR13_BIT3, !p2);
rt2x00_set_field32(&reg, MAC_CSR13_BIT11, 0);
rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
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)
{
int retval;
u32 reg;
/*
* Disable power saving.
@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
if (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.
*/

View File

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

View File

@ -189,7 +189,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 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
@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
u32 reg;
/*
* Allocate eeprom data.
@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
if (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.
*/

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