forked from Minki/linux
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
commit
6ed0e321a0
@ -90,6 +90,7 @@ static struct usb_device_id ath3k_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x0489, 0xe04e) },
|
||||
{ USB_DEVICE(0x0489, 0xe056) },
|
||||
{ USB_DEVICE(0x0489, 0xe04d) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||
@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -148,6 +148,7 @@ static struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||
@ -926,6 +927,22 @@ static void btusb_waker(struct work_struct *work)
|
||||
usb_autopm_put_interface(data->intf);
|
||||
}
|
||||
|
||||
static int btusb_setup_bcm92035(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 val = 0x00;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb));
|
||||
else
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btusb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@ -1022,11 +1039,14 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
|
||||
SET_HCIDEV_DEV(hdev, &intf->dev);
|
||||
|
||||
hdev->open = btusb_open;
|
||||
hdev->close = btusb_close;
|
||||
hdev->flush = btusb_flush;
|
||||
hdev->send = btusb_send_frame;
|
||||
hdev->notify = btusb_notify;
|
||||
hdev->open = btusb_open;
|
||||
hdev->close = btusb_close;
|
||||
hdev->flush = btusb_flush;
|
||||
hdev->send = btusb_send_frame;
|
||||
hdev->notify = btusb_notify;
|
||||
|
||||
if (id->driver_info & BTUSB_BCM92035)
|
||||
hdev->setup = btusb_setup_bcm92035;
|
||||
|
||||
/* Interface numbers are hardcoded in the specification */
|
||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
@ -1065,17 +1085,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
data->isoc = NULL;
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_BCM92035) {
|
||||
unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
|
||||
if (skb) {
|
||||
memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
|
||||
skb_queue_tail(&hdev->driver_init, skb);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->isoc) {
|
||||
err = usb_driver_claim_interface(&btusb_driver,
|
||||
data->isoc, data);
|
||||
|
@ -153,6 +153,9 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
ret = hci_recv_stream_fragment(hu->hdev, data, count);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Frame Reassembly Failed");
|
||||
|
@ -260,12 +260,12 @@ static int hci_uart_send_frame(struct sk_buff *skb)
|
||||
|
||||
/* ------ LDISC part ------ */
|
||||
/* hci_uart_tty_open
|
||||
*
|
||||
*
|
||||
* Called when line discipline changed to HCI_UART.
|
||||
*
|
||||
* Arguments:
|
||||
* tty pointer to tty info structure
|
||||
* Return Value:
|
||||
* Return Value:
|
||||
* 0 if success, otherwise error code
|
||||
*/
|
||||
static int hci_uart_tty_open(struct tty_struct *tty)
|
||||
@ -365,15 +365,15 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
||||
}
|
||||
|
||||
/* hci_uart_tty_receive()
|
||||
*
|
||||
*
|
||||
* Called by tty low level driver when receive data is
|
||||
* available.
|
||||
*
|
||||
*
|
||||
* Arguments: tty pointer to tty isntance data
|
||||
* data pointer to received data
|
||||
* flags pointer to flags for data
|
||||
* count count of received data in bytes
|
||||
*
|
||||
*
|
||||
* Return Value: None
|
||||
*/
|
||||
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
||||
@ -388,7 +388,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
|
||||
|
||||
spin_lock(&hu->rx_lock);
|
||||
hu->proto->recv(hu, (void *) data, count);
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
|
||||
if (hu->hdev)
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
|
||||
spin_unlock(&hu->rx_lock);
|
||||
|
||||
tty_unthrottle(tty);
|
||||
|
@ -1293,7 +1293,8 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
|
||||
{
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
struct ieee80211_conf *conf = &dev->conf;
|
||||
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
|
||||
int channel =
|
||||
ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
|
||||
|
||||
if (channel != priv->channel) {
|
||||
priv->channel = channel;
|
||||
|
@ -1943,12 +1943,12 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct at76_priv *priv = hw->priv;
|
||||
|
||||
at76_dbg(DBG_MAC80211, "%s(): channel %d",
|
||||
__func__, hw->conf.channel->hw_value);
|
||||
__func__, hw->conf.chandef.chan->hw_value);
|
||||
at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
|
||||
|
||||
mutex_lock(&priv->mtx);
|
||||
|
||||
priv->channel = hw->conf.channel->hw_value;
|
||||
priv->channel = hw->conf.chandef.chan->hw_value;
|
||||
|
||||
if (is_valid_ether_addr(priv->bssid))
|
||||
at76_join(priv);
|
||||
|
@ -457,14 +457,14 @@ static int ar5523_set_chan(struct ar5523 *ar)
|
||||
memset(&reset, 0, sizeof(reset));
|
||||
reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ);
|
||||
reset.flags |= cpu_to_be32(UATH_CHAN_OFDM);
|
||||
reset.freq = cpu_to_be32(conf->channel->center_freq);
|
||||
reset.freq = cpu_to_be32(conf->chandef.chan->center_freq);
|
||||
reset.maxrdpower = cpu_to_be32(50); /* XXX */
|
||||
reset.channelchange = cpu_to_be32(1);
|
||||
reset.keeprccontent = cpu_to_be32(0);
|
||||
|
||||
ar5523_dbg(ar, "set chan flags 0x%x freq %d\n",
|
||||
be32_to_cpu(reset.flags),
|
||||
conf->channel->center_freq);
|
||||
conf->chandef.chan->center_freq);
|
||||
return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0);
|
||||
}
|
||||
|
||||
@ -594,7 +594,7 @@ static void ar5523_data_rx_cb(struct urb *urb)
|
||||
rx_status = IEEE80211_SKB_RXCB(data->skb);
|
||||
memset(rx_status, 0, sizeof(*rx_status));
|
||||
rx_status->freq = be32_to_cpu(desc->channel);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
rx_status->signal = -95 + be32_to_cpu(desc->rssi);
|
||||
|
||||
ieee80211_rx_irqsafe(hw, data->skb);
|
||||
@ -1153,13 +1153,13 @@ static int ar5523_get_wlan_mode(struct ar5523 *ar,
|
||||
struct ieee80211_sta *sta;
|
||||
u32 sta_rate_set;
|
||||
|
||||
band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
|
||||
band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
|
||||
sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
|
||||
if (!sta) {
|
||||
ar5523_info(ar, "STA not found!\n");
|
||||
return WLAN_MODE_11b;
|
||||
}
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
|
||||
|
||||
for (bit = 0; bit < band->n_bitrates; bit++) {
|
||||
if (sta_rate_set & 1) {
|
||||
@ -1197,11 +1197,11 @@ static void ar5523_create_rateset(struct ar5523 *ar,
|
||||
ar5523_info(ar, "STA not found. Cannot set rates\n");
|
||||
sta_rate_set = bss_conf->basic_rates;
|
||||
} else
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
|
||||
|
||||
ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
|
||||
|
||||
band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
|
||||
band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
|
||||
for (bit = 0; bit < band->n_bitrates; bit++) {
|
||||
BUG_ON(i >= AR5523_MAX_NRATES);
|
||||
ar5523_dbg(ar, "Considering rate %d : %d\n",
|
||||
|
@ -10,6 +10,7 @@ ath5k-y += phy.o
|
||||
ath5k-y += reset.o
|
||||
ath5k-y += attach.o
|
||||
ath5k-y += base.o
|
||||
CFLAGS_base.o += -I$(src)
|
||||
ath5k-y += led.o
|
||||
ath5k-y += rfkill.o
|
||||
ath5k-y += ani.o
|
||||
|
@ -2639,7 +2639,7 @@ int ath5k_start(struct ieee80211_hw *hw)
|
||||
* be followed by initialization of the appropriate bits
|
||||
* and then setup of the interrupt mask.
|
||||
*/
|
||||
ah->curchan = ah->hw->conf.channel;
|
||||
ah->curchan = ah->hw->conf.chandef.chan;
|
||||
ah->imask = AR5K_INT_RXOK
|
||||
| AR5K_INT_RXERR
|
||||
| AR5K_INT_RXEOL
|
||||
|
@ -202,7 +202,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
mutex_lock(&ah->lock);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
ret = ath5k_chan_set(ah, conf->channel);
|
||||
ret = ath5k_chan_set(ah, conf->chandef.chan);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
}
|
||||
@ -678,7 +678,7 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
|
||||
|
||||
memcpy(survey, &ah->survey, sizeof(*survey));
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->channel = conf->chandef.chan;
|
||||
survey->noise = ah->ah_noise_floor;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
|
@ -97,7 +97,7 @@ TRACE_EVENT(ath5k_tx_complete,
|
||||
#if defined(CONFIG_ATH5K_TRACER) && !defined(__CHECKER__)
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "hw-ops.h"
|
||||
#include "../regd.h"
|
||||
#include "ar9002_phy.h"
|
||||
#include "ar5008_initvals.h"
|
||||
|
||||
/* All code below is for AR5008, AR9001, AR9002 */
|
||||
|
||||
@ -43,23 +44,16 @@ static const int m2ThreshLowExt_off = 127;
|
||||
static const int m1ThreshExt_off = 127;
|
||||
static const int m2ThreshExt_off = 127;
|
||||
|
||||
static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
|
||||
static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
|
||||
static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);
|
||||
static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3);
|
||||
static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7);
|
||||
|
||||
static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
|
||||
int col)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < array->ia_rows; i++)
|
||||
bank[i] = INI_RA(array, i, col);
|
||||
}
|
||||
|
||||
|
||||
#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
|
||||
ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
|
||||
|
||||
static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
|
||||
u32 *data, unsigned int *writecnt)
|
||||
static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)
|
||||
{
|
||||
struct ar5416IniArray *array = &ah->iniBank6;
|
||||
u32 *data = ah->analogBank6Data;
|
||||
int r;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
@ -165,7 +159,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
|
||||
ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
|
||||
|
||||
/* write Bank 6 with new params */
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
|
||||
ar5008_write_bank6(ah, ®_writes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -469,31 +463,16 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
|
||||
*/
|
||||
static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
#define ATH_ALLOC_BANK(bank, size) do { \
|
||||
bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \
|
||||
if (!bank) \
|
||||
goto error; \
|
||||
} while (0);
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int size = ah->iniBank6.ia_rows * sizeof(u32);
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
return 0;
|
||||
|
||||
ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
|
||||
ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
|
||||
if (!ah->analogBank6Data)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
#undef ATH_ALLOC_BANK
|
||||
error:
|
||||
ath_err(common, "Cannot allocate RF banks\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
@ -517,6 +496,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
|
||||
u32 ob5GHz = 0, db5GHz = 0;
|
||||
u32 ob2GHz = 0, db2GHz = 0;
|
||||
int regWrites = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Software does not need to program bank data
|
||||
@ -529,25 +509,8 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
|
||||
/* Setup rf parameters */
|
||||
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
|
||||
|
||||
/* Setup Bank 0 Write */
|
||||
ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
|
||||
|
||||
/* Setup Bank 1 Write */
|
||||
ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
|
||||
|
||||
/* Setup Bank 2 Write */
|
||||
ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
|
||||
|
||||
/* Setup Bank 6 Write */
|
||||
ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
|
||||
modesIndex);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
|
||||
ah->analogBank6Data[i] =
|
||||
INI_RA(&ah->iniBank6TPC, i, modesIndex);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ah->iniBank6.ia_rows; i++)
|
||||
ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);
|
||||
|
||||
/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
|
||||
if (eepMinorRev >= 2) {
|
||||
@ -568,22 +531,13 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup Bank 7 Setup */
|
||||
ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
|
||||
|
||||
/* Write Analog registers */
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
|
||||
regWrites);
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
|
||||
regWrites);
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
|
||||
regWrites);
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
|
||||
regWrites);
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
|
||||
regWrites);
|
||||
REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
|
||||
regWrites);
|
||||
REG_WRITE_ARRAY(&bank0, 1, regWrites);
|
||||
REG_WRITE_ARRAY(&bank1, 1, regWrites);
|
||||
REG_WRITE_ARRAY(&bank2, 1, regWrites);
|
||||
REG_WRITE_ARRAY(&bank3, modesIndex, regWrites);
|
||||
ar5008_write_bank6(ah, ®Writes);
|
||||
REG_WRITE_ARRAY(&bank7, 1, regWrites);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -67,12 +67,10 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
} else if (AR_SREV_9100_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100);
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
|
||||
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC);
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
|
||||
}
|
||||
|
||||
@ -80,20 +78,11 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
/* Common for AR5416, AR913x, AR9160 */
|
||||
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0);
|
||||
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1);
|
||||
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2);
|
||||
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3);
|
||||
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7);
|
||||
|
||||
/* Common for AR5416, AR9160 */
|
||||
if (!AR_SREV_9100(ah))
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6);
|
||||
|
||||
/* Common for AR913x, AR9160 */
|
||||
if (!AR_SREV_5416(ah))
|
||||
INIT_INI_ARRAY(&ah->iniBank6TPC,
|
||||
ar5416Bank6TPC_9100);
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
|
||||
}
|
||||
|
||||
/* iniAddac needs to be modified for these chips */
|
||||
|
@ -234,6 +234,7 @@ struct ath_buf {
|
||||
dma_addr_t bf_daddr; /* physical addr of desc */
|
||||
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
|
||||
bool bf_stale;
|
||||
struct ieee80211_tx_rate rates[4];
|
||||
struct ath_buf_state bf_state;
|
||||
};
|
||||
|
||||
@ -311,6 +312,7 @@ struct ath_rx_edma {
|
||||
struct ath_rx {
|
||||
u8 defant;
|
||||
u8 rxotherant;
|
||||
bool discard_next;
|
||||
u32 *rxlink;
|
||||
u32 num_pkts;
|
||||
unsigned int rxfilter;
|
||||
@ -657,11 +659,10 @@ enum sc_op_flags {
|
||||
struct ath_rate_table;
|
||||
|
||||
struct ath9k_vif_iter_data {
|
||||
const u8 *hw_macaddr; /* phy's hardware address, set
|
||||
* before starting iteration for
|
||||
* valid bssid mask.
|
||||
*/
|
||||
u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
|
||||
u8 mask[ETH_ALEN]; /* bssid mask */
|
||||
bool has_hw_macaddr;
|
||||
|
||||
int naps; /* number of AP vifs */
|
||||
int nmeshes; /* number of mesh vifs */
|
||||
int nstations; /* number of station vifs */
|
||||
|
@ -79,7 +79,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
u8 chainmask = ah->txchainmask;
|
||||
u8 rate = 0;
|
||||
|
||||
sband = &sc->sbands[common->hw->conf.channel->band];
|
||||
sband = &sc->sbands[common->hw->conf.chandef.chan->band];
|
||||
rate = sband->bitrates[rateidx].hw_value;
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
rate |= sband->bitrates[rateidx].hw_value_short;
|
||||
|
@ -208,7 +208,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
|
||||
return true;
|
||||
|
||||
ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
|
||||
currCal->calData->calType, conf->channel->center_freq);
|
||||
currCal->calData->calType, conf->chandef.chan->center_freq);
|
||||
|
||||
ah->caldata->CalValid &= ~currCal->calData->calType;
|
||||
currCal->calState = CAL_WAITING;
|
||||
|
@ -33,6 +33,12 @@ struct ar5416IniArray {
|
||||
u32 ia_columns;
|
||||
};
|
||||
|
||||
#define STATIC_INI_ARRAY(array) { \
|
||||
.ia_array = (u32 *)(array), \
|
||||
.ia_rows = ARRAY_SIZE(array), \
|
||||
.ia_columns = ARRAY_SIZE(array[0]), \
|
||||
}
|
||||
|
||||
#define INIT_INI_ARRAY(iniarray, array) do { \
|
||||
(iniarray)->ia_array = (u32 *)(array); \
|
||||
(iniarray)->ia_rows = ARRAY_SIZE(array); \
|
||||
|
@ -27,20 +27,6 @@ MODULE_AUTHOR("Atheros Communications");
|
||||
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
int ath9k_cmn_padpos(__le16 frame_control)
|
||||
{
|
||||
int padpos = 24;
|
||||
if (ieee80211_has_a4(frame_control)) {
|
||||
padpos += ETH_ALEN;
|
||||
}
|
||||
if (ieee80211_is_data_qos(frame_control)) {
|
||||
padpos += IEEE80211_QOS_CTL_LEN;
|
||||
}
|
||||
|
||||
return padpos;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_padpos);
|
||||
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
@ -133,13 +119,14 @@ EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
|
||||
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
|
||||
struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
|
||||
struct ath9k_channel *channel;
|
||||
u8 chan_idx;
|
||||
|
||||
chan_idx = curchan->hw_value;
|
||||
channel = &ah->channels[chan_idx];
|
||||
ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
|
||||
ath9k_cmn_update_ichannel(channel, curchan,
|
||||
cfg80211_get_chandef_type(&hw->conf.chandef));
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
@ -42,7 +42,6 @@
|
||||
#define ATH_EP_RND(x, mul) \
|
||||
(((x) + ((mul)/2)) / (mul))
|
||||
|
||||
int ath9k_cmn_padpos(__le16 frame_control);
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
|
||||
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
|
||||
struct ieee80211_channel *chan,
|
||||
|
@ -55,12 +55,6 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
|
||||
u8 rssi;
|
||||
u16 dur;
|
||||
|
||||
ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
|
||||
"pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
|
||||
ard->pulse_bw_info,
|
||||
ard->pulse_length_pri, ard->rssi,
|
||||
ard->pulse_length_ext, ard->ext_rssi);
|
||||
|
||||
/*
|
||||
* Only the last 2 bits of the BW info are relevant, they indicate
|
||||
* which channel the radar was detected in.
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "dfs_pattern_detector.h"
|
||||
#include "dfs_pri_detector.h"
|
||||
#include "ath9k.h"
|
||||
|
||||
/*
|
||||
* tolerated deviation of radar time stamp in usecs on both sides
|
||||
@ -142,6 +143,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
||||
{
|
||||
u32 sz, i;
|
||||
struct channel_detector *cd;
|
||||
struct ath_common *common = ath9k_hw_common(dpd->ah);
|
||||
|
||||
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
|
||||
if (cd == NULL)
|
||||
@ -165,7 +167,8 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
||||
return cd;
|
||||
|
||||
fail:
|
||||
pr_err("failed to allocate channel_detector for freq=%d\n", freq);
|
||||
ath_dbg(common, DFS,
|
||||
"failed to allocate channel_detector for freq=%d\n", freq);
|
||||
channel_detector_exit(dpd, cd);
|
||||
return NULL;
|
||||
}
|
||||
@ -216,34 +219,34 @@ static bool
|
||||
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
|
||||
{
|
||||
u32 i;
|
||||
bool ts_wraparound;
|
||||
struct channel_detector *cd;
|
||||
|
||||
if (dpd->region == NL80211_DFS_UNSET) {
|
||||
/*
|
||||
* pulses received for a non-supported or un-initialized
|
||||
* domain are treated as detected radars
|
||||
*/
|
||||
/*
|
||||
* pulses received for a non-supported or un-initialized
|
||||
* domain are treated as detected radars for fail-safety
|
||||
*/
|
||||
if (dpd->region == NL80211_DFS_UNSET)
|
||||
return true;
|
||||
}
|
||||
|
||||
cd = channel_detector_get(dpd, event->freq);
|
||||
if (cd == NULL)
|
||||
return false;
|
||||
|
||||
ts_wraparound = (event->ts < dpd->last_pulse_ts);
|
||||
dpd->last_pulse_ts = event->ts;
|
||||
if (ts_wraparound) {
|
||||
/*
|
||||
* reset detector on time stamp wraparound
|
||||
* with monotonic time stamps, this should never happen
|
||||
*/
|
||||
pr_warn("DFS: time stamp wraparound detected, resetting\n");
|
||||
/* reset detector on time stamp wraparound, caused by TSF reset */
|
||||
if (event->ts < dpd->last_pulse_ts)
|
||||
dpd_reset(dpd);
|
||||
}
|
||||
|
||||
/* do type individual pattern matching */
|
||||
for (i = 0; i < dpd->num_radar_types; i++) {
|
||||
if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
|
||||
struct pri_detector *pd = cd->detectors[i];
|
||||
struct pri_sequence *ps = pd->add_pulse(pd, event);
|
||||
if (ps != NULL) {
|
||||
ath_dbg(ath9k_hw_common(dpd->ah), DFS,
|
||||
"DFS: radar found on freq=%d: id=%d, pri=%d, "
|
||||
"count=%d, count_false=%d\n",
|
||||
event->freq, pd->rs->type_id,
|
||||
ps->pri, ps->count, ps->count_falses);
|
||||
channel_detector_reset(dpd, cd);
|
||||
return true;
|
||||
}
|
||||
@ -285,9 +288,10 @@ static struct dfs_pattern_detector default_dpd = {
|
||||
};
|
||||
|
||||
struct dfs_pattern_detector *
|
||||
dfs_pattern_detector_init(enum nl80211_dfs_regions region)
|
||||
dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
|
||||
{
|
||||
struct dfs_pattern_detector *dpd;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
|
||||
if (dpd == NULL)
|
||||
@ -296,10 +300,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
|
||||
*dpd = default_dpd;
|
||||
INIT_LIST_HEAD(&dpd->channel_detectors);
|
||||
|
||||
dpd->ah = ah;
|
||||
if (dpd->set_dfs_domain(dpd, region))
|
||||
return dpd;
|
||||
|
||||
pr_err("Could not set DFS domain to %d. ", region);
|
||||
ath_dbg(common, DFS,"Could not set DFS domain to %d", region);
|
||||
kfree(dpd);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ struct dfs_pattern_detector {
|
||||
enum nl80211_dfs_regions region;
|
||||
u8 num_radar_types;
|
||||
u64 last_pulse_ts;
|
||||
/* needed for ath_dbg() */
|
||||
struct ath_hw *ah;
|
||||
|
||||
const struct radar_detector_specs *radar_spec;
|
||||
struct list_head channel_detectors;
|
||||
@ -92,10 +94,10 @@ struct dfs_pattern_detector {
|
||||
*/
|
||||
#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
|
||||
extern struct dfs_pattern_detector *
|
||||
dfs_pattern_detector_init(enum nl80211_dfs_regions region);
|
||||
dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region);
|
||||
#else
|
||||
static inline struct dfs_pattern_detector *
|
||||
dfs_pattern_detector_init(enum nl80211_dfs_regions region)
|
||||
dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -22,28 +22,6 @@
|
||||
#include "dfs_pri_detector.h"
|
||||
#include "dfs_debug.h"
|
||||
|
||||
/**
|
||||
* struct pri_sequence - sequence of pulses matching one PRI
|
||||
* @head: list_head
|
||||
* @pri: pulse repetition interval (PRI) in usecs
|
||||
* @dur: duration of sequence in usecs
|
||||
* @count: number of pulses in this sequence
|
||||
* @count_falses: number of not matching pulses in this sequence
|
||||
* @first_ts: time stamp of first pulse in usecs
|
||||
* @last_ts: time stamp of last pulse in usecs
|
||||
* @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
|
||||
*/
|
||||
struct pri_sequence {
|
||||
struct list_head head;
|
||||
u32 pri;
|
||||
u32 dur;
|
||||
u32 count;
|
||||
u32 count_falses;
|
||||
u64 first_ts;
|
||||
u64 last_ts;
|
||||
u64 deadline_ts;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pulse_elem - elements in pulse queue
|
||||
* @ts: time stamp in usecs
|
||||
@ -393,8 +371,8 @@ static void pri_detector_exit(struct pri_detector *de)
|
||||
kfree(de);
|
||||
}
|
||||
|
||||
static bool pri_detector_add_pulse(struct pri_detector *de,
|
||||
struct pulse_event *event)
|
||||
static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de,
|
||||
struct pulse_event *event)
|
||||
{
|
||||
u32 max_updated_seq;
|
||||
struct pri_sequence *ps;
|
||||
@ -403,38 +381,33 @@ static bool pri_detector_add_pulse(struct pri_detector *de,
|
||||
|
||||
/* ignore pulses not within width range */
|
||||
if ((rs->width_min > event->width) || (rs->width_max < event->width))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
if ((ts - de->last_ts) < rs->max_pri_tolerance)
|
||||
/* if delta to last pulse is too short, don't use this pulse */
|
||||
return false;
|
||||
return NULL;
|
||||
de->last_ts = ts;
|
||||
|
||||
max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts);
|
||||
|
||||
if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
|
||||
pr_err("failed to create pulse sequences\n");
|
||||
pri_detector_reset(de, ts);
|
||||
return false;
|
||||
}
|
||||
|
||||
ps = pseq_handler_check_detection(de);
|
||||
|
||||
if (ps != NULL) {
|
||||
pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n",
|
||||
ps->pri, ps->count, ps->count_falses);
|
||||
pri_detector_reset(de, ts);
|
||||
return true;
|
||||
}
|
||||
pulse_queue_enqueue(de, ts);
|
||||
return false;
|
||||
if (ps == NULL)
|
||||
pulse_queue_enqueue(de, ts);
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
struct pri_detector *
|
||||
pri_detector_init(const struct radar_detector_specs *rs)
|
||||
struct pri_detector *pri_detector_init(const struct radar_detector_specs *rs)
|
||||
{
|
||||
struct pri_detector *de;
|
||||
de = kzalloc(sizeof(*de), GFP_KERNEL);
|
||||
|
||||
de = kzalloc(sizeof(*de), GFP_ATOMIC);
|
||||
if (de == NULL)
|
||||
return NULL;
|
||||
de->exit = pri_detector_exit;
|
||||
|
@ -19,10 +19,32 @@
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
/**
|
||||
* struct pri_sequence - sequence of pulses matching one PRI
|
||||
* @head: list_head
|
||||
* @pri: pulse repetition interval (PRI) in usecs
|
||||
* @dur: duration of sequence in usecs
|
||||
* @count: number of pulses in this sequence
|
||||
* @count_falses: number of not matching pulses in this sequence
|
||||
* @first_ts: time stamp of first pulse in usecs
|
||||
* @last_ts: time stamp of last pulse in usecs
|
||||
* @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
|
||||
*/
|
||||
struct pri_sequence {
|
||||
struct list_head head;
|
||||
u32 pri;
|
||||
u32 dur;
|
||||
u32 count;
|
||||
u32 count_falses;
|
||||
u64 first_ts;
|
||||
u64 last_ts;
|
||||
u64 deadline_ts;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pri_detector - PRI detector element for a dedicated radar type
|
||||
* @exit(): destructor
|
||||
* @add_pulse(): add pulse event, returns true if pattern was detected
|
||||
* @add_pulse(): add pulse event, returns pri_sequence if pattern was detected
|
||||
* @reset(): clear states and reset to given time stamp
|
||||
* @rs: detector specs for this detector element
|
||||
* @last_ts: last pulse time stamp considered for this element in usecs
|
||||
@ -34,7 +56,8 @@
|
||||
*/
|
||||
struct pri_detector {
|
||||
void (*exit) (struct pri_detector *de);
|
||||
bool (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
|
||||
struct pri_sequence *
|
||||
(*add_pulse)(struct pri_detector *de, struct pulse_event *e);
|
||||
void (*reset) (struct pri_detector *de, u64 ts);
|
||||
|
||||
/* private: internal use only */
|
||||
|
@ -308,7 +308,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
|
||||
while(skb) {
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padpos = ieee80211_hdrlen(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len > padpos) {
|
||||
if (skb_headroom(skb) < padsize) {
|
||||
|
@ -190,7 +190,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_channel *channel = priv->hw->conf.channel;
|
||||
struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
|
||||
struct ath9k_hw_cal_data *caldata = NULL;
|
||||
enum htc_phymode mode;
|
||||
__be16 htc_mode;
|
||||
@ -250,7 +250,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_conf *conf = &common->hw->conf;
|
||||
bool fastcc;
|
||||
struct ieee80211_channel *channel = hw->conf.channel;
|
||||
struct ieee80211_channel *channel = hw->conf.chandef.chan;
|
||||
struct ath9k_hw_cal_data *caldata = NULL;
|
||||
enum htc_phymode mode;
|
||||
__be16 htc_mode;
|
||||
@ -602,7 +602,7 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
|
||||
u32 caps = 0;
|
||||
int i, j;
|
||||
|
||||
sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
|
||||
sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
|
||||
|
||||
for (i = 0, j = 0; i < sband->n_bitrates; i++) {
|
||||
if (sta->supp_rates[sband->band] & BIT(i)) {
|
||||
@ -866,7 +866,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw,
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
/* Add the padding after the header if this is not already done */
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padpos = ieee80211_hdrlen(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len > padpos) {
|
||||
if (skb_headroom(skb) < padsize) {
|
||||
@ -904,7 +904,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
|
||||
struct ath9k_channel *init_channel;
|
||||
int ret = 0;
|
||||
enum htc_phymode mode;
|
||||
@ -1193,15 +1193,17 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
|
||||
enum nl80211_channel_type channel_type =
|
||||
cfg80211_get_chandef_type(&hw->conf.chandef);
|
||||
int pos = curchan->hw_value;
|
||||
|
||||
ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
|
||||
hw->conf.channel,
|
||||
hw->conf.channel_type);
|
||||
hw->conf.chandef.chan,
|
||||
channel_type);
|
||||
|
||||
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
|
||||
ath_err(common, "Unable to set channel\n");
|
||||
|
@ -490,7 +490,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
|
||||
if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
|
||||
rate->flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
} else {
|
||||
if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
|
||||
if (cur_conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
|
||||
rate->idx += 4; /* No CCK rates */
|
||||
}
|
||||
|
||||
@ -939,7 +939,7 @@ static void ath9k_process_rate(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
band = hw->conf.channel->band;
|
||||
band = hw->conf.chandef.chan->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
@ -966,7 +966,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct sk_buff *skb = rxbuf->skb;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
int hdrlen, padpos, padsize;
|
||||
int hdrlen, padsize;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
|
||||
@ -996,11 +996,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
fc = hdr->frame_control;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
|
||||
padpos = ath9k_cmn_padpos(fc);
|
||||
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len >= padpos+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
padsize = hdrlen & 3;
|
||||
if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
@ -1082,8 +1080,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
}
|
||||
|
||||
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
rx_status->freq = hw->conf.chandef.chan->center_freq;
|
||||
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
|
||||
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_END;
|
||||
|
@ -139,7 +139,7 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
|
||||
clockrate = 117;
|
||||
else if (!ah->curchan) /* should really check for CCK instead */
|
||||
clockrate = ATH9K_CLOCK_RATE_CCK;
|
||||
else if (conf->channel->band == IEEE80211_BAND_2GHZ)
|
||||
else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
|
||||
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
|
||||
else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
|
||||
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
|
||||
@ -1100,7 +1100,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
/* As defined by IEEE 802.11-2007 17.3.8.6 */
|
||||
acktimeout = slottime + sifstime + 3 * ah->coverage_class + ack_offset;
|
||||
slottime += 3 * ah->coverage_class;
|
||||
acktimeout = slottime + sifstime + ack_offset;
|
||||
ctstimeout = acktimeout;
|
||||
|
||||
/*
|
||||
@ -1110,7 +1111,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
|
||||
* BA frames in some implementations, but it has been found to fix ACK
|
||||
* timeout issues in other cases as well.
|
||||
*/
|
||||
if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ &&
|
||||
if (conf->chandef.chan &&
|
||||
conf->chandef.chan->band == IEEE80211_BAND_2GHZ &&
|
||||
!IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
|
||||
acktimeout += 64 - sifstime - ah->slottime;
|
||||
ctstimeout += 48 - sifstime - ah->slottime;
|
||||
@ -1697,12 +1699,11 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah,
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
|
||||
REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
|
||||
| macStaId1
|
||||
REG_RMW(ah, AR_STA_ID1, macStaId1
|
||||
| AR_STA_ID1_RTS_USE_DEF
|
||||
| (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
|
||||
| ah->sta_id1_defaults);
|
||||
| ah->sta_id1_defaults,
|
||||
~AR_STA_ID1_SADH_MASK);
|
||||
ath_hw_setbssidmask(common);
|
||||
REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
|
||||
ath9k_hw_write_associd(ah);
|
||||
|
@ -847,14 +847,7 @@ struct ath_hw {
|
||||
struct ath_hw_ops ops;
|
||||
|
||||
/* Used to program the radio on non single-chip devices */
|
||||
u32 *analogBank0Data;
|
||||
u32 *analogBank1Data;
|
||||
u32 *analogBank2Data;
|
||||
u32 *analogBank3Data;
|
||||
u32 *analogBank6Data;
|
||||
u32 *analogBank6TPCData;
|
||||
u32 *analogBank7Data;
|
||||
u32 *bank6Temp;
|
||||
|
||||
int coverage_class;
|
||||
u32 slottime;
|
||||
@ -885,14 +878,8 @@ struct ath_hw {
|
||||
|
||||
struct ar5416IniArray iniModes;
|
||||
struct ar5416IniArray iniCommon;
|
||||
struct ar5416IniArray iniBank0;
|
||||
struct ar5416IniArray iniBB_RfGain;
|
||||
struct ar5416IniArray iniBank1;
|
||||
struct ar5416IniArray iniBank2;
|
||||
struct ar5416IniArray iniBank3;
|
||||
struct ar5416IniArray iniBank6;
|
||||
struct ar5416IniArray iniBank6TPC;
|
||||
struct ar5416IniArray iniBank7;
|
||||
struct ar5416IniArray iniAddac;
|
||||
struct ar5416IniArray iniPcieSerdes;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -577,7 +577,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
atomic_set(&ah->intr_ref_cnt, -1);
|
||||
sc->sc_ah = ah;
|
||||
|
||||
sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET);
|
||||
sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
|
||||
|
||||
if (!pdata) {
|
||||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
@ -766,7 +766,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS;
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SUPPORTS_RC_TABLE;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
|
@ -214,7 +214,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
|
||||
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
|
||||
|
||||
memset(tx_info, 0, sizeof(*tx_info));
|
||||
tx_info->band = hw->conf.channel->band;
|
||||
tx_info->band = hw->conf.chandef.chan->band;
|
||||
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
tx_info->control.rates[0].idx = 0;
|
||||
tx_info->control.rates[0].count = 1;
|
||||
|
@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
else if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
rs->rs_status |= ATH9K_RXERR_MIC;
|
||||
} else {
|
||||
if (ads.ds_rxstatus8 &
|
||||
(AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))
|
||||
rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
|
||||
|
||||
/* Only up to MCS16 supported, everything above is invalid */
|
||||
if (rs->rs_rate >= 0x90)
|
||||
rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
|
||||
}
|
||||
|
||||
if (ads.ds_rxstatus8 & AR_KeyMiss)
|
||||
|
@ -183,6 +183,7 @@ struct ath_htc_rx_status {
|
||||
#define ATH9K_RXERR_DECRYPT 0x08
|
||||
#define ATH9K_RXERR_MIC 0x10
|
||||
#define ATH9K_RXERR_KEYMISS 0x20
|
||||
#define ATH9K_RXERR_CORRUPT_DESC 0x40
|
||||
|
||||
#define ATH9K_RX_MORE 0x01
|
||||
#define ATH9K_RX_MORE_AGGR 0x02
|
||||
|
@ -589,7 +589,7 @@ static int ath9k_start(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);
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
|
||||
struct ath9k_channel *init_channel;
|
||||
int r;
|
||||
|
||||
@ -839,10 +839,14 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
struct ath9k_vif_iter_data *iter_data = data;
|
||||
int i;
|
||||
|
||||
if (iter_data->hw_macaddr)
|
||||
if (iter_data->has_hw_macaddr) {
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
iter_data->mask[i] &=
|
||||
~(iter_data->hw_macaddr[i] ^ mac[i]);
|
||||
} else {
|
||||
memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
|
||||
iter_data->has_hw_macaddr = true;
|
||||
}
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
@ -891,7 +895,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
|
||||
* together with the BSSID mask when matching addresses.
|
||||
*/
|
||||
memset(iter_data, 0, sizeof(*iter_data));
|
||||
iter_data->hw_macaddr = common->macaddr;
|
||||
memset(&iter_data->mask, 0xff, ETH_ALEN);
|
||||
|
||||
if (vif)
|
||||
@ -901,6 +904,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_vif_iter, iter_data);
|
||||
|
||||
memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/* Called with sc->mutex held. */
|
||||
@ -1188,7 +1193,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
|
||||
enum nl80211_channel_type channel_type =
|
||||
cfg80211_get_chandef_type(&conf->chandef);
|
||||
int pos = curchan->hw_value;
|
||||
int old_pos = -1;
|
||||
unsigned long flags;
|
||||
@ -1197,7 +1204,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
old_pos = ah->curchan - &ah->channels[0];
|
||||
|
||||
ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
|
||||
curchan->center_freq, conf->channel_type);
|
||||
curchan->center_freq, channel_type);
|
||||
|
||||
/* update survey stats for the old channel before switching */
|
||||
spin_lock_irqsave(&common->cc_lock, flags);
|
||||
@ -1212,7 +1219,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
ath9k_hw_getnf(ah, ah->curchan);
|
||||
|
||||
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
|
||||
curchan, conf->channel_type);
|
||||
curchan, channel_type);
|
||||
|
||||
/*
|
||||
* If the operating channel changes, change the survey in-use flags
|
||||
|
@ -814,7 +814,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
* So, set fourth rate in series to be same as third one for
|
||||
* above conditions.
|
||||
*/
|
||||
if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
|
||||
if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) &&
|
||||
(conf_is_ht(&sc->hw->conf))) {
|
||||
u8 dot11rate = rate_table->info[rix].dot11rate;
|
||||
u8 phy = rate_table->info[rix].phy;
|
||||
@ -1328,7 +1328,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
||||
|
||||
ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
|
||||
"Operating HT Bandwidth changed to: %d\n",
|
||||
sc->hw->conf.channel_type);
|
||||
cfg80211_get_chandef_type(&sc->hw->conf.chandef));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,13 +124,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
|
||||
|
||||
SKB_CB_ATHBUF(skb) = bf;
|
||||
ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
|
||||
skb_queue_tail(&rx_edma->rx_fifo, skb);
|
||||
__skb_queue_tail(&rx_edma->rx_fifo, skb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
|
||||
enum ath9k_rx_qtype qtype, int size)
|
||||
enum ath9k_rx_qtype qtype)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_buf *bf, *tbf;
|
||||
@ -155,7 +155,7 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
|
||||
|
||||
rx_edma = &sc->rx.rx_edma[qtype];
|
||||
|
||||
while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
|
||||
while ((skb = __skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
|
||||
bf = SKB_CB_ATHBUF(skb);
|
||||
BUG_ON(!bf);
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
@ -250,15 +250,9 @@ rx_init_fail:
|
||||
static void ath_edma_start_recv(struct ath_softc *sc)
|
||||
{
|
||||
ath9k_hw_rxena(sc->sc_ah);
|
||||
|
||||
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
|
||||
sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
|
||||
|
||||
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
|
||||
sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
|
||||
|
||||
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
|
||||
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
|
||||
ath_opmode_init(sc);
|
||||
|
||||
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
|
||||
}
|
||||
|
||||
@ -280,49 +274,47 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
|
||||
sc->sc_ah->caps.rx_status_len;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
return ath_rx_edma_init(sc, nbufs);
|
||||
} else {
|
||||
ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
common->cachelsz, common->rx_bufsize);
|
||||
|
||||
/* Initialize rx descriptors */
|
||||
ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
common->cachelsz, common->rx_bufsize);
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
|
||||
"rx", nbufs, 1, 0);
|
||||
if (error != 0) {
|
||||
ath_err(common,
|
||||
"failed to allocate rx descriptors: %d\n",
|
||||
error);
|
||||
/* Initialize rx descriptors */
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
|
||||
"rx", nbufs, 1, 0);
|
||||
if (error != 0) {
|
||||
ath_err(common,
|
||||
"failed to allocate rx descriptors: %d\n",
|
||||
error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = ath_rxbuf_alloc(common, common->rx_bufsize,
|
||||
GFP_KERNEL);
|
||||
if (skb == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = ath_rxbuf_alloc(common, common->rx_bufsize,
|
||||
GFP_KERNEL);
|
||||
if (skb == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bf->bf_mpdu = skb;
|
||||
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev,
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
bf->bf_buf_addr = 0;
|
||||
ath_err(common,
|
||||
"dma_mapping_error() on RX init\n");
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
bf->bf_mpdu = skb;
|
||||
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev,
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
bf->bf_buf_addr = 0;
|
||||
ath_err(common,
|
||||
"dma_mapping_error() on RX init\n");
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
sc->rx.rxlink = NULL;
|
||||
}
|
||||
|
||||
sc->rx.rxlink = NULL;
|
||||
err:
|
||||
if (error)
|
||||
ath_rx_cleanup(sc);
|
||||
@ -340,17 +332,17 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
ath_rx_edma_cleanup(sc);
|
||||
return;
|
||||
} else {
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = bf->bf_mpdu;
|
||||
if (skb) {
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
bf->bf_buf_addr = 0;
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = bf->bf_mpdu;
|
||||
if (skb) {
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
bf->bf_buf_addr = 0;
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -727,6 +719,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
|
||||
if (ret == -EINPROGRESS)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* mark descriptor as zero-length and set the 'more'
|
||||
* flag to ensure that both buffers get discarded
|
||||
*/
|
||||
rs->rs_datalen = 0;
|
||||
rs->rs_more = true;
|
||||
}
|
||||
|
||||
list_del(&bf->list);
|
||||
@ -863,7 +862,7 @@ static int ath9k_process_rate(struct ath_common *common,
|
||||
unsigned int i = 0;
|
||||
struct ath_softc __maybe_unused *sc = common->priv;
|
||||
|
||||
band = hw->conf.channel->band;
|
||||
band = hw->conf.chandef.chan->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
if (rx_stats->rs_rate & 0x80) {
|
||||
@ -933,14 +932,20 @@ static void ath9k_process_rssi(struct ath_common *common,
|
||||
* up the frame up to let mac80211 handle the actual error case, be it no
|
||||
* decryption key or real decryption error. This let us keep statistics there.
|
||||
*/
|
||||
static int ath9k_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
bool discard_current = sc->rx.discard_next;
|
||||
|
||||
sc->rx.discard_next = rx_stats->rs_more;
|
||||
if (discard_current)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
@ -958,14 +963,15 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
|
||||
return -EINVAL;
|
||||
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
rx_status->freq = hw->conf.chandef.chan->center_freq;
|
||||
rx_status->signal = ah->noise + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_END;
|
||||
if (rx_stats->rs_moreaggr)
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
|
||||
sc->rx.discard_next = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -985,7 +991,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padpos = ieee80211_hdrlen(fc);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
@ -1166,6 +1172,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
u64 tsf = 0;
|
||||
u32 tsf_lower = 0;
|
||||
unsigned long flags;
|
||||
dma_addr_t new_buf_addr;
|
||||
|
||||
if (edma)
|
||||
dma_type = DMA_BIDIRECTIONAL;
|
||||
@ -1242,8 +1249,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
}
|
||||
}
|
||||
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
|
||||
&decrypt_error);
|
||||
if (retval)
|
||||
goto requeue_drop_frag;
|
||||
|
||||
@ -1264,10 +1271,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
goto requeue_drop_frag;
|
||||
}
|
||||
|
||||
/* We will now give hardware our shiny new allocated skb */
|
||||
new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
|
||||
common->rx_bufsize, dma_type);
|
||||
if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
|
||||
dev_kfree_skb_any(requeue_skb);
|
||||
goto requeue_drop_frag;
|
||||
}
|
||||
|
||||
/* Unmap the frame */
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize,
|
||||
dma_type);
|
||||
common->rx_bufsize, dma_type);
|
||||
|
||||
bf->bf_mpdu = requeue_skb;
|
||||
bf->bf_buf_addr = new_buf_addr;
|
||||
|
||||
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
|
||||
if (ah->caps.rx_status_len)
|
||||
@ -1277,21 +1294,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
|
||||
rxs, decrypt_error);
|
||||
|
||||
/* We will now give hardware our shiny new allocated skb */
|
||||
bf->bf_mpdu = requeue_skb;
|
||||
bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
|
||||
common->rx_bufsize,
|
||||
dma_type);
|
||||
if (unlikely(dma_mapping_error(sc->dev,
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(requeue_skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
bf->bf_buf_addr = 0;
|
||||
ath_err(common, "dma_mapping_error() on RX\n");
|
||||
ieee80211_rx(hw, skb);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rs.rs_more) {
|
||||
RX_STAT_INC(rx_frags);
|
||||
/*
|
||||
@ -1309,6 +1311,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
sc->rx.frag = skb;
|
||||
goto requeue;
|
||||
}
|
||||
if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
|
||||
goto requeue_drop_frag;
|
||||
|
||||
if (sc->rx.frag) {
|
||||
int space = skb->len - skb_tailroom(hdr_skb);
|
||||
|
@ -1493,9 +1493,6 @@ enum {
|
||||
#define AR9271_RADIO_RF_RST 0x20
|
||||
#define AR9271_GATE_MAC_CTL 0x4000
|
||||
|
||||
#define AR_STA_ID0 0x8000
|
||||
#define AR_STA_ID1 0x8004
|
||||
#define AR_STA_ID1_SADH_MASK 0x0000FFFF
|
||||
#define AR_STA_ID1_STA_AP 0x00010000
|
||||
#define AR_STA_ID1_ADHOC 0x00020000
|
||||
#define AR_STA_ID1_PWR_SAV 0x00040000
|
||||
|
@ -157,6 +157,13 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
|
||||
seqno << IEEE80211_SEQ_SEQ_SHIFT);
|
||||
}
|
||||
|
||||
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ath_buf *bf)
|
||||
{
|
||||
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
}
|
||||
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = tid->ac->txq;
|
||||
@ -189,6 +196,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
|
||||
sendbar = true;
|
||||
} else {
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
ath_tx_send_normal(sc, txq, NULL, skb);
|
||||
}
|
||||
}
|
||||
@ -407,7 +415,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
memcpy(rates, tx_info->control.rates, sizeof(rates));
|
||||
memcpy(rates, bf->rates, sizeof(rates));
|
||||
|
||||
retries = ts->ts_longretry + 1;
|
||||
for (i = 0; i < ts->ts_rateindex; i++)
|
||||
@ -516,8 +524,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
* not a holding desc.
|
||||
*/
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
|
||||
bf_next != NULL || !bf_last->bf_stale)
|
||||
if (bf_next != NULL || !bf_last->bf_stale)
|
||||
list_move_tail(&bf->list, &bf_head);
|
||||
|
||||
if (!txpending || (tid->state & AGGR_CLEANUP)) {
|
||||
@ -537,8 +544,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
!txfail);
|
||||
} else {
|
||||
/* retry the un-acked ones */
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
||||
bf->bf_next == NULL && bf_last->bf_stale) {
|
||||
if (bf->bf_next == NULL && bf_last->bf_stale) {
|
||||
struct ath_buf *tbf;
|
||||
|
||||
tbf = ath_clone_txbuf(sc, bf_last);
|
||||
@ -738,8 +744,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
bool first_subfrm)
|
||||
{
|
||||
#define FIRST_DESC_NDELIMS 60
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
u32 nsymbits, nsymbols;
|
||||
u16 minlen;
|
||||
u8 flags, rix;
|
||||
@ -780,8 +784,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
if (tid->an->mpdudensity == 0)
|
||||
return ndelim;
|
||||
|
||||
rix = tx_info->control.rates[0].idx;
|
||||
flags = tx_info->control.rates[0].flags;
|
||||
rix = bf->rates[0].idx;
|
||||
flags = bf->rates[0].flags;
|
||||
width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
|
||||
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
|
||||
|
||||
@ -860,6 +864,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
|
||||
bf_first = bf;
|
||||
|
||||
if (!rl) {
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
aggr_limit = ath_lookup_rate(sc, bf, tid);
|
||||
rl = 1;
|
||||
}
|
||||
@ -1000,14 +1005,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
|
||||
|
||||
skb = bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
rates = tx_info->control.rates;
|
||||
rates = bf->rates;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
/* set dur_update_en for l-sig computation except for PS-Poll frames */
|
||||
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
|
||||
info->rtscts_rate = fi->rtscts_rate;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(bf->rates); i++) {
|
||||
bool is_40, is_sgi, is_sp;
|
||||
int phy;
|
||||
|
||||
@ -1745,6 +1750,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
return;
|
||||
}
|
||||
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
bf->bf_state.bf_type = BUF_AMPDU;
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_add(&bf->list, &bf_head);
|
||||
@ -1894,49 +1900,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
|
||||
return bf;
|
||||
}
|
||||
|
||||
/* FIXME: tx power */
|
||||
static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf;
|
||||
u8 tidno;
|
||||
|
||||
if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
tidno = ieee80211_get_qos_ctl(hdr)[0] &
|
||||
IEEE80211_QOS_CTL_TID_MASK;
|
||||
tid = ATH_AN_2_TID(txctl->an, tidno);
|
||||
|
||||
WARN_ON(tid->ac->txq != txctl->txq);
|
||||
}
|
||||
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
|
||||
/*
|
||||
* Try aggregation if it's a unicast data frame
|
||||
* and the destination is HT capable.
|
||||
*/
|
||||
ath_tx_send_ampdu(sc, tid, skb, txctl);
|
||||
} else {
|
||||
bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
|
||||
if (!bf) {
|
||||
if (txctl->paprd)
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
bf->bf_state.bfs_paprd = txctl->paprd;
|
||||
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
||||
ath_tx_send_normal(sc, txctl->txq, tid, skb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Upon failure caller should free skb */
|
||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ath_tx_control *txctl)
|
||||
@ -1947,8 +1910,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf;
|
||||
int padpos, padsize;
|
||||
int frmlen = skb->len + FCS_LEN;
|
||||
u8 tidno;
|
||||
int q;
|
||||
|
||||
/* NOTE: sta can be NULL according to net/mac80211.h */
|
||||
@ -1971,7 +1937,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/* Add the padding after the header if this is not already done */
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padpos = ieee80211_hdrlen(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len > padpos) {
|
||||
if (skb_headroom(skb) < padsize)
|
||||
@ -2004,8 +1970,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
txq->stopped = true;
|
||||
}
|
||||
|
||||
ath_tx_start_dma(sc, skb, txctl);
|
||||
if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
tidno = ieee80211_get_qos_ctl(hdr)[0] &
|
||||
IEEE80211_QOS_CTL_TID_MASK;
|
||||
tid = ATH_AN_2_TID(txctl->an, tidno);
|
||||
|
||||
WARN_ON(tid->ac->txq != txctl->txq);
|
||||
}
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
|
||||
/*
|
||||
* Try aggregation if it's a unicast data frame
|
||||
* and the destination is HT capable.
|
||||
*/
|
||||
ath_tx_send_ampdu(sc, tid, skb, txctl);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
|
||||
if (!bf) {
|
||||
if (txctl->paprd)
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bf->bf_state.bfs_paprd = txctl->paprd;
|
||||
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
||||
ath_set_rates(vif, sta, bf);
|
||||
ath_tx_send_normal(sc, txctl->txq, tid, skb);
|
||||
|
||||
out:
|
||||
ath_txq_unlock(sc, txq);
|
||||
|
||||
return 0;
|
||||
@ -2033,7 +2032,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
/* Frame was ACKed */
|
||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padpos = ieee80211_hdrlen(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>padpos+padsize) {
|
||||
/*
|
||||
@ -2264,6 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
struct ath_txq *txq;
|
||||
struct ath_buf *bf, *lastbf;
|
||||
struct list_head bf_head;
|
||||
struct list_head *fifo_list;
|
||||
int status;
|
||||
|
||||
for (;;) {
|
||||
@ -2291,20 +2291,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
|
||||
TX_STAT_INC(txq->axq_qnum, txprocdesc);
|
||||
|
||||
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
|
||||
fifo_list = &txq->txq_fifo[txq->txq_tailidx];
|
||||
if (list_empty(fifo_list)) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
return;
|
||||
}
|
||||
|
||||
bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
|
||||
struct ath_buf, list);
|
||||
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
||||
if (bf->bf_stale) {
|
||||
list_del(&bf->list);
|
||||
ath_tx_return_buffer(sc, bf);
|
||||
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
||||
}
|
||||
|
||||
lastbf = bf->bf_lastbf;
|
||||
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
|
||||
&lastbf->list);
|
||||
|
||||
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
|
||||
if (list_is_last(&lastbf->list, fifo_list)) {
|
||||
list_splice_tail_init(fifo_list, &bf_head);
|
||||
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
|
||||
|
||||
if (!list_empty(&txq->axq_q)) {
|
||||
@ -2315,6 +2319,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
list_splice_tail_init(&txq->axq_q, &bf_q);
|
||||
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
|
||||
}
|
||||
} else {
|
||||
lastbf->bf_stale = true;
|
||||
if (bf != lastbf)
|
||||
list_cut_position(&bf_head, fifo_list,
|
||||
lastbf->list.prev);
|
||||
}
|
||||
|
||||
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
|
||||
|
@ -654,8 +654,8 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
|
||||
goto out;
|
||||
|
||||
case 'P':
|
||||
err = carl9170_set_channel(ar, ar->hw->conf.channel,
|
||||
ar->hw->conf.channel_type);
|
||||
err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
|
||||
cfg80211_get_chandef_type(&ar->hw->conf.chandef));
|
||||
if (err < 0)
|
||||
count = err;
|
||||
|
||||
|
@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
|
||||
if (conf_is_ht40(&ar->hw->conf))
|
||||
val = 0x010a;
|
||||
else {
|
||||
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
|
||||
if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
|
||||
val = 0x105;
|
||||
else
|
||||
val = 0x104;
|
||||
@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar)
|
||||
rts_rate = 0x1da;
|
||||
cts_rate = 0x10a;
|
||||
} else {
|
||||
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
|
||||
if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
|
||||
/* 11 mbit CCK */
|
||||
rts_rate = 033;
|
||||
cts_rate = 003;
|
||||
@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
|
||||
if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) ||
|
||||
vif->bss_conf.use_short_slot)
|
||||
slottime = 9;
|
||||
|
||||
@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar)
|
||||
basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
|
||||
if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
|
||||
mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
|
||||
else
|
||||
mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
|
||||
|
@ -929,6 +929,9 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
enum nl80211_channel_type channel_type =
|
||||
cfg80211_get_chandef_type(&hw->conf.chandef);
|
||||
|
||||
/* adjust slot time for 5 GHz */
|
||||
err = carl9170_set_slot_time(ar);
|
||||
if (err)
|
||||
@ -938,8 +941,8 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = carl9170_set_channel(ar, hw->conf.channel,
|
||||
hw->conf.channel_type);
|
||||
err = carl9170_set_channel(ar, hw->conf.chandef.chan,
|
||||
channel_type);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -957,7 +960,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
err = carl9170_set_mac_tpc(ar, ar->hw->conf.channel);
|
||||
err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -1331,7 +1331,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
|
||||
* CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
|
||||
*/
|
||||
ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
|
||||
ar->hw->conf.channel->band);
|
||||
ar->hw->conf.chandef.chan->band);
|
||||
|
||||
/* ctl group not found - either invalid band (NO_CTL) or ww roaming */
|
||||
if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
|
||||
@ -1341,7 +1341,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
|
||||
/* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
|
||||
return;
|
||||
|
||||
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
|
||||
if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
|
||||
modes = mode_list_2ghz;
|
||||
nr_modes = ARRAY_SIZE(mode_list_2ghz);
|
||||
} else {
|
||||
|
@ -118,6 +118,12 @@
|
||||
void ath_hw_setbssidmask(struct ath_common *common)
|
||||
{
|
||||
void *ah = common->ah;
|
||||
u32 id1;
|
||||
|
||||
REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
|
||||
id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK;
|
||||
id1 |= get_unaligned_le16(common->macaddr + 4);
|
||||
REG_WRITE(ah, AR_STA_ID1, id1);
|
||||
|
||||
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
|
||||
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
|
||||
|
@ -23,6 +23,10 @@
|
||||
#define AR_MIBC_CMC 0x00000004
|
||||
#define AR_MIBC_MCS 0x00000008
|
||||
|
||||
#define AR_STA_ID0 0x8000
|
||||
#define AR_STA_ID1 0x8004
|
||||
#define AR_STA_ID1_SADH_MASK 0x0000ffff
|
||||
|
||||
/*
|
||||
* BSSID mask registers. See ath_hw_set_bssid_mask()
|
||||
* for detailed documentation about these registers.
|
||||
|
@ -191,8 +191,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
|
||||
* - Phy info
|
||||
*/
|
||||
static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb,
|
||||
volatile struct vring_rx_desc *d)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct wil6210_rtap {
|
||||
@ -216,6 +215,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
|
||||
__le16 vendor_skip;
|
||||
u8 vendor_data[0];
|
||||
} __packed;
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
struct wil6210_rtap_vendor *rtap_vendor;
|
||||
int rtap_len = sizeof(struct wil6210_rtap);
|
||||
int phy_length = 0; /* phy info header size, bytes */
|
||||
@ -312,6 +312,8 @@ static void wil_swap_ethaddr(void *data)
|
||||
/**
|
||||
* reap 1 frame from @swhead
|
||||
*
|
||||
* Rx descriptor copied to skb->cb
|
||||
*
|
||||
* Safe to call from IRQ
|
||||
*/
|
||||
static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
@ -320,12 +322,15 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
volatile struct vring_rx_desc *d;
|
||||
struct vring_rx_desc *d1;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t pa;
|
||||
unsigned int sz = RX_BUF_LEN;
|
||||
u8 ftype;
|
||||
u8 ds_bits;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
|
||||
|
||||
if (wil_vring_is_empty(vring))
|
||||
return NULL;
|
||||
|
||||
@ -340,11 +345,14 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
|
||||
skb_trim(skb, d->dma.length);
|
||||
|
||||
wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
|
||||
d1 = wil_skb_rxdesc(skb);
|
||||
*d1 = *d;
|
||||
|
||||
wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1);
|
||||
|
||||
/* use radiotap header only if required */
|
||||
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
|
||||
wil_rx_add_radiotap_header(wil, skb, d);
|
||||
wil_rx_add_radiotap_header(wil, skb);
|
||||
|
||||
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
@ -360,7 +368,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
* Driver should recognize it by frame type, that is found
|
||||
* in Rx descriptor. If type is not data, it is 802.11 frame as is
|
||||
*/
|
||||
ftype = wil_rxdesc_ftype(d) << 2;
|
||||
ftype = wil_rxdesc_ftype(d1) << 2;
|
||||
if (ftype != IEEE80211_FTYPE_DATA) {
|
||||
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
/* TODO: process it */
|
||||
@ -375,7 +383,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ds_bits = wil_rxdesc_ds_bits(d);
|
||||
ds_bits = wil_rxdesc_ds_bits(d1);
|
||||
if (ds_bits == 1) {
|
||||
/*
|
||||
* HW bug - in ToDS mode, i.e. Rx on AP side,
|
||||
@ -517,6 +525,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
||||
.vring_cfg = {
|
||||
.tx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
|
||||
.ring_size = cpu_to_le16(size),
|
||||
},
|
||||
.ringid = id,
|
||||
.cidxtid = (cid & 0xf) | ((tid & 0xf) << 4),
|
||||
@ -548,7 +557,6 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
||||
goto out;
|
||||
|
||||
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
||||
cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size);
|
||||
|
||||
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
||||
@ -779,9 +787,14 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
||||
|
||||
while (!wil_vring_is_empty(vring)) {
|
||||
volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
|
||||
volatile struct vring_tx_desc *d1 =
|
||||
&vring->va[vring->swtail].tx;
|
||||
struct vring_tx_desc dd, *d = ⅆ
|
||||
dma_addr_t pa;
|
||||
struct sk_buff *skb;
|
||||
|
||||
dd = *d1;
|
||||
|
||||
if (!(d->dma.status & TX_DMA_STATUS_DU))
|
||||
break;
|
||||
|
||||
|
@ -339,24 +339,59 @@ union vring_desc {
|
||||
struct vring_rx_desc rx;
|
||||
} __packed;
|
||||
|
||||
static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d)
|
||||
static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->dma.d0, 16, 29);
|
||||
return WIL_GET_BITS(d->mac.d0, 0, 3);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d)
|
||||
static inline int wil_rxdesc_cid(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d1, 21, 24);
|
||||
return WIL_GET_BITS(d->mac.d0, 4, 6);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d)
|
||||
static inline int wil_rxdesc_mid(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d1, 8, 9);
|
||||
return WIL_GET_BITS(d->mac.d0, 8, 9);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d)
|
||||
static inline int wil_rxdesc_ftype(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 10, 11);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_subtype(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 12, 15);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_seq(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 16, 27);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 28, 31);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d1, 8, 9);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_mcs(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d1, 21, 24);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->dma.d0, 16, 29);
|
||||
}
|
||||
|
||||
static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb->cb;
|
||||
}
|
||||
|
||||
#endif /* WIL6210_TXRX_H */
|
||||
|
@ -980,7 +980,7 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
|
||||
*/
|
||||
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
|
||||
{
|
||||
return wl->hw->conf.channel->band;
|
||||
return wl->hw->conf.chandef.chan->band;
|
||||
}
|
||||
|
||||
static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
|
||||
|
@ -3852,7 +3852,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
dev = wl->current_dev;
|
||||
|
||||
/* Switch the band (if necessary). This might change the active core. */
|
||||
err = b43_switch_band(wl, conf->channel);
|
||||
err = b43_switch_band(wl, conf->chandef.chan);
|
||||
if (err)
|
||||
goto out_unlock_mutex;
|
||||
|
||||
@ -3882,8 +3882,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
/* Switch to the requested channel.
|
||||
* The firmware takes care of races with the TX handler. */
|
||||
if (conf->channel->hw_value != phy->channel)
|
||||
b43_switch_channel(dev, conf->channel->hw_value);
|
||||
if (conf->chandef.chan->hw_value != phy->channel)
|
||||
b43_switch_channel(dev, conf->chandef.chan->hw_value);
|
||||
|
||||
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
@ -5006,7 +5006,7 @@ static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->channel = conf->chandef.chan;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = dev->stats.link_noise;
|
||||
|
||||
|
@ -30,6 +30,17 @@
|
||||
#include "radio_2059.h"
|
||||
#include "main.h"
|
||||
|
||||
/* Force values to keep compatibility with wl */
|
||||
enum ht_rssi_type {
|
||||
HT_RSSI_W1 = 0,
|
||||
HT_RSSI_W2 = 1,
|
||||
HT_RSSI_NB = 2,
|
||||
HT_RSSI_IQ = 3,
|
||||
HT_RSSI_TSSI_2G = 4,
|
||||
HT_RSSI_TSSI_5G = 5,
|
||||
HT_RSSI_TBD = 6,
|
||||
};
|
||||
|
||||
/**************************************************
|
||||
* Radio 2059.
|
||||
**************************************************/
|
||||
@ -37,8 +48,9 @@
|
||||
static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
|
||||
const struct b43_phy_ht_channeltab_e_radio2059 *e)
|
||||
{
|
||||
u8 i;
|
||||
u16 routing;
|
||||
static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
|
||||
u16 r;
|
||||
int core;
|
||||
|
||||
b43_radio_write(dev, 0x16, e->radio_syn16);
|
||||
b43_radio_write(dev, 0x17, e->radio_syn17);
|
||||
@ -53,25 +65,17 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
|
||||
b43_radio_write(dev, 0x41, e->radio_syn41);
|
||||
b43_radio_write(dev, 0x43, e->radio_syn43);
|
||||
b43_radio_write(dev, 0x47, e->radio_syn47);
|
||||
b43_radio_write(dev, 0x4a, e->radio_syn4a);
|
||||
b43_radio_write(dev, 0x58, e->radio_syn58);
|
||||
b43_radio_write(dev, 0x5a, e->radio_syn5a);
|
||||
b43_radio_write(dev, 0x6a, e->radio_syn6a);
|
||||
b43_radio_write(dev, 0x6d, e->radio_syn6d);
|
||||
b43_radio_write(dev, 0x6e, e->radio_syn6e);
|
||||
b43_radio_write(dev, 0x92, e->radio_syn92);
|
||||
b43_radio_write(dev, 0x98, e->radio_syn98);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
routing = i ? R2059_RXRX1 : R2059_TXRX0;
|
||||
b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
|
||||
b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
|
||||
b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
|
||||
b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
|
||||
b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
|
||||
b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
|
||||
b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
|
||||
b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
|
||||
for (core = 0; core < 3; core++) {
|
||||
r = routing[core];
|
||||
b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
|
||||
b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
|
||||
b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
|
||||
b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
|
||||
b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
|
||||
b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
|
||||
b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
|
||||
b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
|
||||
}
|
||||
|
||||
udelay(50);
|
||||
@ -87,7 +91,7 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
|
||||
|
||||
static void b43_radio_2059_init(struct b43_wldev *dev)
|
||||
{
|
||||
const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
|
||||
const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
|
||||
const u16 radio_values[3][2] = {
|
||||
{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
|
||||
};
|
||||
@ -106,17 +110,17 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
|
||||
b43_radio_mask(dev, 0xc0, ~0x0080);
|
||||
|
||||
if (1) { /* FIXME */
|
||||
b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
|
||||
b43_radio_set(dev, R2059_C3 | 0x4, 0x1);
|
||||
udelay(10);
|
||||
b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
|
||||
b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
|
||||
b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
|
||||
b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
|
||||
|
||||
b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
|
||||
b43_radio_set(dev, R2059_C3 | 0x4, 0x2);
|
||||
udelay(100);
|
||||
b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
|
||||
b43_radio_mask(dev, R2059_C3 | 0x4, ~0x2);
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
|
||||
if (b43_radio_read(dev, R2059_C3 | 0x145) & 1) {
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
@ -125,7 +129,7 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
|
||||
if (i)
|
||||
b43err(dev->wl, "radio 0x945 timeout\n");
|
||||
|
||||
b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
|
||||
b43_radio_mask(dev, R2059_C3 | 0x4, ~0x1);
|
||||
b43_radio_set(dev, 0xa, 0x60);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
@ -390,14 +394,14 @@ static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
|
||||
**************************************************/
|
||||
|
||||
static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
|
||||
u8 rssi_type)
|
||||
enum ht_rssi_type rssi_type)
|
||||
{
|
||||
static const u16 ctl_regs[3][2] = {
|
||||
{ B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
|
||||
{ B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
|
||||
{ B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
|
||||
};
|
||||
static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, };
|
||||
static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
|
||||
int core;
|
||||
|
||||
if (core_sel == 0) {
|
||||
@ -411,13 +415,13 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
|
||||
continue;
|
||||
|
||||
switch (rssi_type) {
|
||||
case 4:
|
||||
case HT_RSSI_TSSI_2G:
|
||||
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
|
||||
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
|
||||
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
|
||||
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
|
||||
|
||||
b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1);
|
||||
b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
|
||||
b43_radio_write(dev, radio_r[core] | 0x159,
|
||||
0x11);
|
||||
break;
|
||||
@ -429,8 +433,8 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
|
||||
}
|
||||
}
|
||||
|
||||
static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
|
||||
u8 nsamp)
|
||||
static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type,
|
||||
s32 *buf, u8 nsamp)
|
||||
{
|
||||
u16 phy_regs_values[12];
|
||||
static const u16 phy_regs_to_save[] = {
|
||||
@ -504,15 +508,17 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
|
||||
static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
|
||||
B43_PHY_HT_TXPCTL_CMD_C2,
|
||||
B43_PHY_HT_TXPCTL_CMD_C3 };
|
||||
static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1,
|
||||
B43_PHY_HT_TX_PCTL_STATUS_C2,
|
||||
B43_PHY_HT_TX_PCTL_STATUS_C3 };
|
||||
int i;
|
||||
|
||||
if (!enable) {
|
||||
if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
|
||||
/* We disable enabled TX pwr ctl, save it's state */
|
||||
/*
|
||||
* TODO: find the registers. On N-PHY they were 0x1ed
|
||||
* and 0x1ee, we need 3 such a registers for HT-PHY
|
||||
*/
|
||||
for (i = 0; i < 3; i++)
|
||||
phy_ht->tx_pwr_idx[i] =
|
||||
b43_phy_read(dev, status_regs[i]);
|
||||
}
|
||||
b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits);
|
||||
} else {
|
||||
@ -536,13 +542,25 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
|
||||
static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_ht *phy_ht = dev->phy.ht;
|
||||
static const u16 base[] = { 0x840, 0x860, 0x880 };
|
||||
u16 save_regs[3][3];
|
||||
s32 rssi_buf[6];
|
||||
int core;
|
||||
|
||||
/* TODO */
|
||||
for (core = 0; core < 3; core++) {
|
||||
save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
|
||||
save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
|
||||
save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
|
||||
|
||||
b43_phy_write(dev, base[core] + 6, 0);
|
||||
b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
|
||||
b43_phy_set(dev, base[core] + 0, 0x0400);
|
||||
b43_phy_set(dev, base[core] + 0, 0x1000);
|
||||
}
|
||||
|
||||
b43_phy_ht_tx_tone(dev);
|
||||
udelay(20);
|
||||
b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1);
|
||||
b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1);
|
||||
b43_phy_ht_stop_playback(dev);
|
||||
b43_phy_ht_reset_cca(dev);
|
||||
|
||||
@ -550,7 +568,23 @@ static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
|
||||
phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
|
||||
|
||||
/* TODO */
|
||||
for (core = 0; core < 3; core++) {
|
||||
b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
|
||||
b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
|
||||
b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
|
||||
}
|
||||
}
|
||||
|
||||
static void b43_phy_ht_tssi_setup(struct b43_wldev *dev)
|
||||
{
|
||||
static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
|
||||
int core;
|
||||
|
||||
/* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */
|
||||
for (core = 0; core < 3; core++) {
|
||||
b43_radio_set(dev, 0x8bf, 0x1);
|
||||
b43_radio_write(dev, routing[core] | 0x0159, 0x0011);
|
||||
}
|
||||
}
|
||||
|
||||
static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
|
||||
@ -946,6 +980,7 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
|
||||
b43_phy_ht_tx_power_ctl(dev, false);
|
||||
b43_phy_ht_tx_power_ctl_idle_tssi(dev);
|
||||
b43_phy_ht_tx_power_ctl_setup(dev);
|
||||
b43_phy_ht_tssi_setup(dev);
|
||||
b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
|
||||
|
||||
return 0;
|
||||
@ -1011,8 +1046,9 @@ static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
|
||||
enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
|
||||
struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
|
||||
enum nl80211_channel_type channel_type =
|
||||
cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if ((new_channel < 1) || (new_channel > 14))
|
||||
|
@ -23,6 +23,9 @@
|
||||
#define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */
|
||||
#define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */
|
||||
#define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */
|
||||
#define B43_PHY_HT_EST_PWR_C1 0x118
|
||||
#define B43_PHY_HT_EST_PWR_C2 0x119
|
||||
#define B43_PHY_HT_EST_PWR_C3 0x11A
|
||||
#define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */
|
||||
#define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */
|
||||
#define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */
|
||||
@ -53,6 +56,8 @@
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8
|
||||
#define B43_PHY_HT_TX_PCTL_STATUS_C1 0x1ED
|
||||
#define B43_PHY_HT_TX_PCTL_STATUS_C2 0x1EE
|
||||
#define B43_PHY_HT_TXPCTL_CMD_C2 0x222
|
||||
#define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F
|
||||
#define B43_PHY_HT_RSSI_C1 0x219
|
||||
@ -97,6 +102,7 @@
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF
|
||||
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0
|
||||
#define B43_PHY_HT_TX_PCTL_STATUS_C3 B43_PHY_EXTG(0x169)
|
||||
|
||||
#define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A)
|
||||
|
||||
|
@ -808,8 +808,9 @@ static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
|
||||
enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
|
||||
struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
|
||||
enum nl80211_channel_type channel_type =
|
||||
cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if ((new_channel < 1) || (new_channel > 14))
|
||||
|
@ -281,8 +281,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
|
||||
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
|
||||
(dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
|
||||
(sprom->boardflags_lo & B43_BFL_FEM))) {
|
||||
(dev->dev->board_type == SSB_BOARD_BU4312) ||
|
||||
(dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) {
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -54,10 +54,15 @@
|
||||
#define B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT 7
|
||||
#define B43_NPHY_C1_INITGAIN_TRRX 0x1000 /* TR RX index */
|
||||
#define B43_NPHY_C1_INITGAIN_TRTX 0x2000 /* TR TX index */
|
||||
#define B43_NPHY_REV3_C1_INITGAIN_A B43_PHY_N(0x020)
|
||||
#define B43_NPHY_C1_CLIP1_HIGAIN B43_PHY_N(0x021) /* Core 1 clip1 high gain code */
|
||||
#define B43_NPHY_REV3_C1_INITGAIN_B B43_PHY_N(0x021)
|
||||
#define B43_NPHY_C1_CLIP1_MEDGAIN B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP_HIGAIN_A B43_PHY_N(0x022)
|
||||
#define B43_NPHY_C1_CLIP1_LOGAIN B43_PHY_N(0x023) /* Core 1 clip1 low gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP_HIGAIN_B B43_PHY_N(0x023)
|
||||
#define B43_NPHY_C1_CLIP2_GAIN B43_PHY_N(0x024) /* Core 1 clip2 gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_A B43_PHY_N(0x024)
|
||||
#define B43_NPHY_C1_FILTERGAIN B43_PHY_N(0x025) /* Core 1 filter gain */
|
||||
#define B43_NPHY_C1_LPF_QHPF_BW B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */
|
||||
#define B43_NPHY_C1_CLIPWBTHRES B43_PHY_N(0x027) /* Core 1 clip wideband threshold */
|
||||
@ -107,10 +112,15 @@
|
||||
#define B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT 7
|
||||
#define B43_NPHY_C2_INITGAIN_TRRX 0x1000 /* TR RX index */
|
||||
#define B43_NPHY_C2_INITGAIN_TRTX 0x2000 /* TR TX index */
|
||||
#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_B B43_PHY_N(0x036)
|
||||
#define B43_NPHY_C2_CLIP1_HIGAIN B43_PHY_N(0x037) /* Core 2 clip1 high gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP_LOGAIN_A B43_PHY_N(0x037)
|
||||
#define B43_NPHY_C2_CLIP1_MEDGAIN B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP_LOGAIN_B B43_PHY_N(0x038)
|
||||
#define B43_NPHY_C2_CLIP1_LOGAIN B43_PHY_N(0x039) /* Core 2 clip1 low gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP2_GAIN_A B43_PHY_N(0x039)
|
||||
#define B43_NPHY_C2_CLIP2_GAIN B43_PHY_N(0x03A) /* Core 2 clip2 gain code */
|
||||
#define B43_NPHY_REV3_C1_CLIP2_GAIN_B B43_PHY_N(0x03A)
|
||||
#define B43_NPHY_C2_FILTERGAIN B43_PHY_N(0x03B) /* Core 2 filter gain */
|
||||
#define B43_NPHY_C2_LPF_QHPF_BW B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */
|
||||
#define B43_NPHY_C2_CLIPWBTHRES B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */
|
||||
@ -706,10 +716,146 @@
|
||||
#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power control init */
|
||||
#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */
|
||||
#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0
|
||||
#define B43_NPHY_ED_CRSEN B43_PHY_N(0x223)
|
||||
#define B43_NPHY_ED_CRS40ASSERTTHRESH0 B43_PHY_N(0x224)
|
||||
#define B43_NPHY_ED_CRS40ASSERTTHRESH1 B43_PHY_N(0x225)
|
||||
#define B43_NPHY_ED_CRS40DEASSERTTHRESH0 B43_PHY_N(0x226)
|
||||
#define B43_NPHY_ED_CRS40DEASSERTTHRESH1 B43_PHY_N(0x227)
|
||||
#define B43_NPHY_ED_CRS20LASSERTTHRESH0 B43_PHY_N(0x228)
|
||||
#define B43_NPHY_ED_CRS20LASSERTTHRESH1 B43_PHY_N(0x229)
|
||||
#define B43_NPHY_ED_CRS20LDEASSERTTHRESH0 B43_PHY_N(0x22A)
|
||||
#define B43_NPHY_ED_CRS20LDEASSERTTHRESH1 B43_PHY_N(0x22B)
|
||||
#define B43_NPHY_ED_CRS20UASSERTTHRESH0 B43_PHY_N(0x22C)
|
||||
#define B43_NPHY_ED_CRS20UASSERTTHRESH1 B43_PHY_N(0x22D)
|
||||
#define B43_NPHY_ED_CRS20UDEASSERTTHRESH0 B43_PHY_N(0x22E)
|
||||
#define B43_NPHY_ED_CRS20UDEASSERTTHRESH1 B43_PHY_N(0x22F)
|
||||
#define B43_NPHY_ED_CRS B43_PHY_N(0x230)
|
||||
#define B43_NPHY_TIMEOUTEN B43_PHY_N(0x231)
|
||||
#define B43_NPHY_OFDMPAYDECODETIMEOUTLEN B43_PHY_N(0x232)
|
||||
#define B43_NPHY_CCKPAYDECODETIMEOUTLEN B43_PHY_N(0x233)
|
||||
#define B43_NPHY_NONPAYDECODETIMEOUTLEN B43_PHY_N(0x234)
|
||||
#define B43_NPHY_TIMEOUTSTATUS B43_PHY_N(0x235)
|
||||
#define B43_NPHY_RFCTRLCORE0GPIO0 B43_PHY_N(0x236)
|
||||
#define B43_NPHY_RFCTRLCORE0GPIO1 B43_PHY_N(0x237)
|
||||
#define B43_NPHY_RFCTRLCORE0GPIO2 B43_PHY_N(0x238)
|
||||
#define B43_NPHY_RFCTRLCORE0GPIO3 B43_PHY_N(0x239)
|
||||
#define B43_NPHY_RFCTRLCORE1GPIO0 B43_PHY_N(0x23A)
|
||||
#define B43_NPHY_RFCTRLCORE1GPIO1 B43_PHY_N(0x23B)
|
||||
#define B43_NPHY_RFCTRLCORE1GPIO2 B43_PHY_N(0x23C)
|
||||
#define B43_NPHY_RFCTRLCORE1GPIO3 B43_PHY_N(0x23D)
|
||||
#define B43_NPHY_BPHYTESTCONTROL B43_PHY_N(0x23E)
|
||||
/* REV3+ */
|
||||
#define B43_NPHY_FORCEFRONT0 B43_PHY_N(0x23F)
|
||||
#define B43_NPHY_FORCEFRONT1 B43_PHY_N(0x240)
|
||||
#define B43_NPHY_NORMVARHYSTTH B43_PHY_N(0x241)
|
||||
#define B43_NPHY_TXCCKERROR B43_PHY_N(0x242)
|
||||
#define B43_NPHY_AFESEQINITDACGAIN B43_PHY_N(0x243)
|
||||
#define B43_NPHY_TXANTSWLUT B43_PHY_N(0x244)
|
||||
#define B43_NPHY_CORECONFIG B43_PHY_N(0x245)
|
||||
#define B43_NPHY_ANTENNADIVDWELLTIME B43_PHY_N(0x246)
|
||||
#define B43_NPHY_ANTENNACCKDIVDWELLTIME B43_PHY_N(0x247)
|
||||
#define B43_NPHY_ANTENNADIVBACKOFFGAIN B43_PHY_N(0x248)
|
||||
#define B43_NPHY_ANTENNADIVMINGAIN B43_PHY_N(0x249)
|
||||
#define B43_NPHY_BRDSEL_NORMVARHYSTTH B43_PHY_N(0x24A)
|
||||
#define B43_NPHY_RXANTSWITCHCTRL B43_PHY_N(0x24B)
|
||||
#define B43_NPHY_ENERGYDROPTIMEOUTLEN2 B43_PHY_N(0x24C)
|
||||
#define B43_NPHY_ML_LOG_TXEVM0 B43_PHY_N(0x250)
|
||||
#define B43_NPHY_ML_LOG_TXEVM1 B43_PHY_N(0x251)
|
||||
#define B43_NPHY_ML_LOG_TXEVM2 B43_PHY_N(0x252)
|
||||
#define B43_NPHY_ML_LOG_TXEVM3 B43_PHY_N(0x253)
|
||||
#define B43_NPHY_ML_LOG_TXEVM4 B43_PHY_N(0x254)
|
||||
#define B43_NPHY_ML_LOG_TXEVM5 B43_PHY_N(0x255)
|
||||
#define B43_NPHY_ML_LOG_TXEVM6 B43_PHY_N(0x256)
|
||||
#define B43_NPHY_ML_LOG_TXEVM7 B43_PHY_N(0x257)
|
||||
#define B43_NPHY_ML_SCALE_TWEAK B43_PHY_N(0x258)
|
||||
#define B43_NPHY_MLUA B43_PHY_N(0x259)
|
||||
#define B43_NPHY_ZFUA B43_PHY_N(0x25A)
|
||||
#define B43_NPHY_CHANUPSYM01 B43_PHY_N(0x25B)
|
||||
#define B43_NPHY_CHANUPSYM2 B43_PHY_N(0x25C)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM00 B43_PHY_N(0x25D)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM01 B43_PHY_N(0x25E)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM02 B43_PHY_N(0x25F)
|
||||
#define B43_NPHY_RXSTRNFILT20DEN00 B43_PHY_N(0x260)
|
||||
#define B43_NPHY_RXSTRNFILT20DEN01 B43_PHY_N(0x261)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM10 B43_PHY_N(0x262)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM11 B43_PHY_N(0x263)
|
||||
#define B43_NPHY_RXSTRNFILT20NUM12 B43_PHY_N(0x264)
|
||||
#define B43_NPHY_RXSTRNFILT20DEN10 B43_PHY_N(0x265)
|
||||
#define B43_NPHY_RXSTRNFILT20DEN11 B43_PHY_N(0x266)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM00 B43_PHY_N(0x267)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM01 B43_PHY_N(0x268)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM02 B43_PHY_N(0x269)
|
||||
#define B43_NPHY_RXSTRNFILT40DEN00 B43_PHY_N(0x26A)
|
||||
#define B43_NPHY_RXSTRNFILT40DEN01 B43_PHY_N(0x26B)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM10 B43_PHY_N(0x26C)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM11 B43_PHY_N(0x26D)
|
||||
#define B43_NPHY_RXSTRNFILT40NUM12 B43_PHY_N(0x26E)
|
||||
#define B43_NPHY_RXSTRNFILT40DEN10 B43_PHY_N(0x26F)
|
||||
#define B43_NPHY_RXSTRNFILT40DEN11 B43_PHY_N(0x270)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD1 B43_PHY_N(0x271)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD2 B43_PHY_N(0x272)
|
||||
#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLD B43_PHY_N(0x273)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD1L B43_PHY_N(0x274)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD2L B43_PHY_N(0x275)
|
||||
#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDL B43_PHY_N(0x276)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD1U B43_PHY_N(0x277)
|
||||
#define B43_NPHY_CRSHIGHPOWTHRESHOLD2U B43_PHY_N(0x278)
|
||||
#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDU B43_PHY_N(0x279)
|
||||
#define B43_NPHY_CRSACIDETECTTHRESH B43_PHY_N(0x27A)
|
||||
#define B43_NPHY_CRSACIDETECTTHRESHL B43_PHY_N(0x27B)
|
||||
#define B43_NPHY_CRSACIDETECTTHRESHU B43_PHY_N(0x27C)
|
||||
#define B43_NPHY_CRSMINPOWER0 B43_PHY_N(0x27D)
|
||||
#define B43_NPHY_CRSMINPOWER1 B43_PHY_N(0x27E)
|
||||
#define B43_NPHY_CRSMINPOWER2 B43_PHY_N(0x27F)
|
||||
#define B43_NPHY_CRSMINPOWERL0 B43_PHY_N(0x280)
|
||||
#define B43_NPHY_CRSMINPOWERL1 B43_PHY_N(0x281)
|
||||
#define B43_NPHY_CRSMINPOWERL2 B43_PHY_N(0x282)
|
||||
#define B43_NPHY_CRSMINPOWERU0 B43_PHY_N(0x283)
|
||||
#define B43_NPHY_CRSMINPOWERU1 B43_PHY_N(0x284)
|
||||
#define B43_NPHY_CRSMINPOWERU2 B43_PHY_N(0x285)
|
||||
#define B43_NPHY_STRPARAM B43_PHY_N(0x286)
|
||||
#define B43_NPHY_STRPARAML B43_PHY_N(0x287)
|
||||
#define B43_NPHY_STRPARAMU B43_PHY_N(0x288)
|
||||
#define B43_NPHY_BPHYCRSMINPOWER0 B43_PHY_N(0x289)
|
||||
#define B43_NPHY_BPHYCRSMINPOWER1 B43_PHY_N(0x28A)
|
||||
#define B43_NPHY_BPHYCRSMINPOWER2 B43_PHY_N(0x28B)
|
||||
#define B43_NPHY_BPHYFILTDEN0COEF B43_PHY_N(0x28C)
|
||||
#define B43_NPHY_BPHYFILTDEN1COEF B43_PHY_N(0x28D)
|
||||
#define B43_NPHY_BPHYFILTDEN2COEF B43_PHY_N(0x28E)
|
||||
#define B43_NPHY_BPHYFILTNUM0COEF B43_PHY_N(0x28F)
|
||||
#define B43_NPHY_BPHYFILTNUM1COEF B43_PHY_N(0x290)
|
||||
#define B43_NPHY_BPHYFILTNUM2COEF B43_PHY_N(0x291)
|
||||
#define B43_NPHY_BPHYFILTNUM01COEF2 B43_PHY_N(0x292)
|
||||
#define B43_NPHY_BPHYFILTBYPASS B43_PHY_N(0x293)
|
||||
#define B43_NPHY_SGILTRNOFFSET B43_PHY_N(0x294)
|
||||
#define B43_NPHY_RADAR_T2_MIN B43_PHY_N(0x295)
|
||||
#define B43_NPHY_TXPWRCTRLDAMPING B43_PHY_N(0x296)
|
||||
#define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */
|
||||
#define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */
|
||||
#define B43_NPHY_EPS_OVERRIDEI_0 B43_PHY_N(0x299)
|
||||
#define B43_NPHY_EPS_OVERRIDEQ_0 B43_PHY_N(0x29A)
|
||||
#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
|
||||
#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
|
||||
#define B43_NPHY_EPS_OVERRIDEI_1 B43_PHY_N(0x29D)
|
||||
#define B43_NPHY_EPS_OVERRIDEQ_1 B43_PHY_N(0x29E)
|
||||
#define B43_NPHY_PAPD_CAL_ADDRESS B43_PHY_N(0x29F)
|
||||
#define B43_NPHY_PAPD_CAL_YREFEPSILON B43_PHY_N(0x2A0)
|
||||
#define B43_NPHY_PAPD_CAL_SETTLE B43_PHY_N(0x2A1)
|
||||
#define B43_NPHY_PAPD_CAL_CORRELATE B43_PHY_N(0x2A2)
|
||||
#define B43_NPHY_PAPD_CAL_SHIFTS0 B43_PHY_N(0x2A3)
|
||||
#define B43_NPHY_PAPD_CAL_SHIFTS1 B43_PHY_N(0x2A4)
|
||||
#define B43_NPHY_SAMPLE_START_ADDR B43_PHY_N(0x2A5)
|
||||
#define B43_NPHY_RADAR_ADC_TO_DBM B43_PHY_N(0x2A6)
|
||||
#define B43_NPHY_REV3_C2_INITGAIN_A B43_PHY_N(0x2A7)
|
||||
#define B43_NPHY_REV3_C2_INITGAIN_B B43_PHY_N(0x2A8)
|
||||
#define B43_NPHY_REV3_C2_CLIP_HIGAIN_A B43_PHY_N(0x2A9)
|
||||
#define B43_NPHY_REV3_C2_CLIP_HIGAIN_B B43_PHY_N(0x2AA)
|
||||
#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_A B43_PHY_N(0x2AB)
|
||||
#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_B B43_PHY_N(0x2AC)
|
||||
#define B43_NPHY_REV3_C2_CLIP_LOGAIN_A B43_PHY_N(0x2AD)
|
||||
#define B43_NPHY_REV3_C2_CLIP_LOGAIN_B B43_PHY_N(0x2AE)
|
||||
#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
|
||||
#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
|
||||
|
||||
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
|
||||
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
|
||||
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
|
||||
r20, r21, r22, r23, r24, r25, r26, r27, r28) \
|
||||
r20) \
|
||||
.radio_syn16 = r00, \
|
||||
.radio_syn17 = r01, \
|
||||
.radio_syn22 = r02, \
|
||||
@ -41,22 +41,14 @@
|
||||
.radio_syn41 = r10, \
|
||||
.radio_syn43 = r11, \
|
||||
.radio_syn47 = r12, \
|
||||
.radio_syn4a = r13, \
|
||||
.radio_syn58 = r14, \
|
||||
.radio_syn5a = r15, \
|
||||
.radio_syn6a = r16, \
|
||||
.radio_syn6d = r17, \
|
||||
.radio_syn6e = r18, \
|
||||
.radio_syn92 = r19, \
|
||||
.radio_syn98 = r20, \
|
||||
.radio_rxtx4a = r21, \
|
||||
.radio_rxtx58 = r22, \
|
||||
.radio_rxtx5a = r23, \
|
||||
.radio_rxtx6a = r24, \
|
||||
.radio_rxtx6d = r25, \
|
||||
.radio_rxtx6e = r26, \
|
||||
.radio_rxtx92 = r27, \
|
||||
.radio_rxtx98 = r28
|
||||
.radio_rxtx4a = r13, \
|
||||
.radio_rxtx58 = r14, \
|
||||
.radio_rxtx5a = r15, \
|
||||
.radio_rxtx6a = r16, \
|
||||
.radio_rxtx6d = r17, \
|
||||
.radio_rxtx6e = r18, \
|
||||
.radio_rxtx92 = r19, \
|
||||
.radio_rxtx98 = r20
|
||||
|
||||
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
|
||||
.phy_regs.bw1 = r0, \
|
||||
@ -70,91 +62,78 @@ static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radi
|
||||
{ .freq = 2412,
|
||||
RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
|
||||
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
|
||||
},
|
||||
{ .freq = 2417,
|
||||
RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
|
||||
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
|
||||
},
|
||||
{ .freq = 2422,
|
||||
RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
|
||||
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
|
||||
},
|
||||
{ .freq = 2427,
|
||||
RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
|
||||
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
|
||||
},
|
||||
{ .freq = 2432,
|
||||
RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
|
||||
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
|
||||
},
|
||||
{ .freq = 2437,
|
||||
RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
|
||||
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
|
||||
},
|
||||
{ .freq = 2442,
|
||||
RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
|
||||
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
|
||||
},
|
||||
{ .freq = 2447,
|
||||
RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
|
||||
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
|
||||
},
|
||||
{ .freq = 2452,
|
||||
RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
|
||||
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
|
||||
},
|
||||
{ .freq = 2457,
|
||||
RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
|
||||
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
|
||||
},
|
||||
{ .freq = 2462,
|
||||
RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
|
||||
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
|
||||
},
|
||||
{ .freq = 2467,
|
||||
RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
|
||||
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
|
||||
},
|
||||
{ .freq = 2472,
|
||||
RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
|
||||
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x00),
|
||||
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
|
||||
},
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
#include "phy_ht.h"
|
||||
|
||||
#define R2059_SYN 0x000
|
||||
#define R2059_TXRX0 0x400
|
||||
#define R2059_RXRX1 0x800
|
||||
#define R2059_C1 0x000
|
||||
#define R2059_C2 0x400
|
||||
#define R2059_C3 0x800
|
||||
#define R2059_ALL 0xC00
|
||||
|
||||
/* Values for various registers uploaded on channel switching */
|
||||
@ -28,14 +28,6 @@ struct b43_phy_ht_channeltab_e_radio2059 {
|
||||
u8 radio_syn41;
|
||||
u8 radio_syn43;
|
||||
u8 radio_syn47;
|
||||
u8 radio_syn4a;
|
||||
u8 radio_syn58;
|
||||
u8 radio_syn5a;
|
||||
u8 radio_syn6a;
|
||||
u8 radio_syn6d;
|
||||
u8 radio_syn6e;
|
||||
u8 radio_syn92;
|
||||
u8 radio_syn98;
|
||||
u8 radio_rxtx4a;
|
||||
u8 radio_rxtx58;
|
||||
u8 radio_rxtx5a;
|
||||
|
@ -2174,7 +2174,7 @@ static const u16 b43_ntab_loftlt1_r3[] = {
|
||||
/* volatile tables, PHY revision >= 3 */
|
||||
|
||||
/* indexed by antswctl2g */
|
||||
static const u16 b43_ntab_antswctl2g_r3[4][32] = {
|
||||
static const u16 b43_ntab_antswctl_r3[4][32] = {
|
||||
{
|
||||
0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
|
||||
0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
|
||||
@ -3095,9 +3095,55 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
|
||||
}
|
||||
|
||||
#define ntab_upload(dev, offset, data) do { \
|
||||
b43_ntab_write_bulk(dev, offset, offset##_SIZE, data); \
|
||||
b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
|
||||
} while (0)
|
||||
void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
|
||||
|
||||
static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
|
||||
{
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
u8 antswlut;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
|
||||
antswlut = sprom->fem.ghz5.antswlut;
|
||||
else
|
||||
antswlut = sprom->fem.ghz2.antswlut;
|
||||
|
||||
/* Static tables */
|
||||
ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
|
||||
ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
|
||||
ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
|
||||
ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
|
||||
ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
|
||||
ntab_upload(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
|
||||
ntab_upload(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
|
||||
ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
|
||||
ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
|
||||
ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
|
||||
ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
|
||||
ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
|
||||
ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
|
||||
ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
|
||||
ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
|
||||
ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
|
||||
ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
|
||||
ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
|
||||
ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
|
||||
ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
|
||||
ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
|
||||
ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
|
||||
ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
|
||||
ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
|
||||
ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
|
||||
|
||||
/* Volatile tables */
|
||||
if (antswlut < ARRAY_SIZE(b43_ntab_antswctl_r3))
|
||||
ntab_upload(dev, B43_NTAB_ANT_SW_CTL_R3,
|
||||
b43_ntab_antswctl_r3[antswlut]);
|
||||
else
|
||||
B43_WARN_ON(1);
|
||||
}
|
||||
|
||||
static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
|
||||
{
|
||||
/* Static tables */
|
||||
ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
|
||||
@ -3130,48 +3176,13 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
|
||||
ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
|
||||
}
|
||||
|
||||
#define ntab_upload_r3(dev, offset, data) do { \
|
||||
b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
|
||||
} while (0)
|
||||
void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
|
||||
void b43_nphy_tables_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
|
||||
/* Static tables */
|
||||
ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C0_ESTPLT_R3,
|
||||
b43_ntab_estimatepowerlt0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C1_ESTPLT_R3,
|
||||
b43_ntab_estimatepowerlt1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
|
||||
ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
|
||||
|
||||
/* Volatile tables */
|
||||
if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3))
|
||||
ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3,
|
||||
b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]);
|
||||
if (dev->phy.rev >= 3)
|
||||
b43_nphy_tables_init_rev3(dev);
|
||||
else
|
||||
B43_WARN_ON(1);
|
||||
b43_nphy_tables_init_rev0(dev);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
|
||||
|
@ -115,22 +115,22 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
#define B43_NTAB_NOISEVAR11_SIZE 256
|
||||
#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
|
||||
#define B43_NTAB_C0_ESTPLT_SIZE 64
|
||||
#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_ESTPLT_SIZE 64
|
||||
#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
|
||||
#define B43_NTAB_C0_ADJPLT_SIZE 128
|
||||
#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_ADJPLT_SIZE 128
|
||||
#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
|
||||
#define B43_NTAB_C0_GAINCTL_SIZE 128
|
||||
#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_GAINCTL_SIZE 128
|
||||
#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
|
||||
#define B43_NTAB_C0_IQLT_SIZE 128
|
||||
#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_IQLT_SIZE 128
|
||||
#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
|
||||
#define B43_NTAB_C0_LOFEEDTH_SIZE 128
|
||||
#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_ESTPLT_SIZE 64
|
||||
#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_ADJPLT_SIZE 128
|
||||
#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_GAINCTL_SIZE 128
|
||||
#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_IQLT_SIZE 128
|
||||
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
|
||||
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
|
||||
|
||||
@ -154,15 +154,17 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */
|
||||
#define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */
|
||||
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */
|
||||
#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
|
||||
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */
|
||||
#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
|
||||
#define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */
|
||||
#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
|
||||
#define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */
|
||||
#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
|
||||
#define B43_NTAB_C0_LOFEEDTH_R3 B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0 */
|
||||
#define B43_NTAB_C0_PAPD_COMP_R3 B43_NTAB16(26, 576)
|
||||
#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
|
||||
#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
|
||||
#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
|
||||
#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
|
||||
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
|
||||
#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
|
||||
|
||||
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
|
||||
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
|
||||
@ -182,8 +184,7 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
|
||||
void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
|
||||
unsigned int nr_elements, const void *_data);
|
||||
|
||||
void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev);
|
||||
void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
|
||||
void b43_nphy_tables_init(struct b43_wldev *dev);
|
||||
|
||||
const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
|
||||
|
||||
|
@ -2720,7 +2720,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
|
||||
goto out_unlock_mutex;
|
||||
|
||||
/* Switch the PHY mode (if necessary). */
|
||||
switch (conf->channel->band) {
|
||||
switch (conf->chandef.chan->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
if (phy->type == B43legacy_PHYTYPE_B)
|
||||
new_phymode = B43legacy_PHYMODE_B;
|
||||
@ -2748,8 +2748,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
|
||||
|
||||
/* Switch to the requested channel.
|
||||
* The firmware takes care of races with the TX handler. */
|
||||
if (conf->channel->hw_value != phy->channel)
|
||||
b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
|
||||
if (conf->chandef.chan->hw_value != phy->channel)
|
||||
b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
|
||||
0);
|
||||
|
||||
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
@ -3558,7 +3559,7 @@ static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->channel = conf->chandef.chan;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = dev->stats.link_noise;
|
||||
|
||||
|
@ -37,15 +37,6 @@ config BRCMFMAC_SDIO
|
||||
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
|
||||
use the driver for a SDIO wireless card.
|
||||
|
||||
config BRCMFMAC_SDIO_OOB
|
||||
bool "Out of band interrupt support for SDIO interface chipset"
|
||||
depends on BRCMFMAC_SDIO
|
||||
---help---
|
||||
This option enables out-of-band interrupt support for Broadcom
|
||||
SDIO Wifi chipset using fullmac in order to gain better
|
||||
performance and deep sleep wake up capability on certain
|
||||
platforms. Say N if you are unsure.
|
||||
|
||||
config BRCMFMAC_USB
|
||||
bool "USB bus interface support for FullMAC driver"
|
||||
depends on USB
|
||||
|
@ -30,7 +30,8 @@ brcmfmac-objs += \
|
||||
p2p.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
dhd_linux.o \
|
||||
btcoex.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
||||
dhd_sdio.o \
|
||||
bcmsdh.o \
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/platform_data/brcmfmac-sdio.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <brcm_hw_ids.h>
|
||||
@ -37,16 +38,15 @@
|
||||
|
||||
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
|
||||
|
||||
static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_dbg(INTR, "oob intr triggered\n");
|
||||
brcmf_dbg(INTR, "OOB intr triggered\n");
|
||||
|
||||
/*
|
||||
* out-of-band interrupt is level-triggered which won't
|
||||
/* out-of-band interrupt is level-triggered which won't
|
||||
* be cleared until dpc
|
||||
*/
|
||||
if (sdiodev->irq_en) {
|
||||
@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 data;
|
||||
unsigned long flags;
|
||||
|
||||
brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
|
||||
|
||||
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
|
||||
sdiodev->irq_flags, "brcmf_oob_intr",
|
||||
&sdiodev->func[1]->dev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
spin_lock_init(&sdiodev->irq_en_lock);
|
||||
spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
|
||||
sdiodev->irq_en = true;
|
||||
spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
|
||||
|
||||
ret = enable_irq_wake(sdiodev->irq);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
sdiodev->irq_wake = true;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
/* must configure SDIO_CCCR_IENx to enable irq */
|
||||
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
|
||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
|
||||
|
||||
/* redirect, configure and enable io for interrupt signal */
|
||||
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
||||
if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
|
||||
data |= SDIO_SEPINT_ACT_HI;
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
||||
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Entering\n");
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
if (sdiodev->irq_wake) {
|
||||
disable_irq_wake(sdiodev->irq);
|
||||
sdiodev->irq_wake = false;
|
||||
}
|
||||
free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
|
||||
sdiodev->irq_en = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
static void brcmf_sdio_irqhandler(struct sdio_func *func)
|
||||
static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_dbg(INTR, "ib intr triggered\n");
|
||||
brcmf_dbg(INTR, "IB intr triggered\n");
|
||||
|
||||
brcmf_sdbrcm_isr(sdiodev->bus);
|
||||
}
|
||||
@ -136,12 +76,56 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
|
||||
|
||||
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Entering\n");
|
||||
int ret = 0;
|
||||
u8 data;
|
||||
unsigned long flags;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
|
||||
sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
|
||||
brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
|
||||
sdiodev->pdata->oob_irq_nr);
|
||||
ret = request_irq(sdiodev->pdata->oob_irq_nr,
|
||||
brcmf_sdio_oob_irqhandler,
|
||||
sdiodev->pdata->oob_irq_flags,
|
||||
"brcmf_oob_intr",
|
||||
&sdiodev->func[1]->dev);
|
||||
if (ret != 0) {
|
||||
brcmf_err("request_irq failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
sdiodev->oob_irq_requested = true;
|
||||
spin_lock_init(&sdiodev->irq_en_lock);
|
||||
spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
|
||||
sdiodev->irq_en = true;
|
||||
spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
|
||||
|
||||
ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
|
||||
if (ret != 0) {
|
||||
brcmf_err("enable_irq_wake failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
sdiodev->irq_wake = true;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
/* must configure SDIO_CCCR_IENx to enable irq */
|
||||
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
|
||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
|
||||
|
||||
/* redirect, configure and enable io for interrupt signal */
|
||||
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
||||
if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
|
||||
data |= SDIO_SEPINT_ACT_HI;
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
||||
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
} else {
|
||||
brcmf_dbg(SDIO, "Entering\n");
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
|
||||
sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -150,14 +134,31 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Entering\n");
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
sdio_release_irq(sdiodev->func[2]);
|
||||
sdio_release_irq(sdiodev->func[1]);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
if (sdiodev->oob_irq_requested) {
|
||||
sdiodev->oob_irq_requested = false;
|
||||
if (sdiodev->irq_wake) {
|
||||
disable_irq_wake(sdiodev->pdata->oob_irq_nr);
|
||||
sdiodev->irq_wake = false;
|
||||
}
|
||||
free_irq(sdiodev->pdata->oob_irq_nr,
|
||||
&sdiodev->func[1]->dev);
|
||||
sdiodev->irq_en = false;
|
||||
}
|
||||
} else {
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
sdio_release_irq(sdiodev->func[2]);
|
||||
sdio_release_irq(sdiodev->func[1]);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
int
|
||||
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
|
||||
@ -457,36 +458,80 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
|
||||
u8 *buf, uint nbytes)
|
||||
int
|
||||
brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
|
||||
u8 *data, uint size)
|
||||
{
|
||||
struct sk_buff *mypkt;
|
||||
bool write = rw ? SDIOH_WRITE : SDIOH_READ;
|
||||
int err;
|
||||
int bcmerror = 0;
|
||||
struct sk_buff *pkt;
|
||||
u32 sdaddr;
|
||||
uint dsize;
|
||||
|
||||
addr &= SBSDIO_SB_OFT_ADDR_MASK;
|
||||
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
||||
|
||||
mypkt = brcmu_pkt_buf_get_skb(nbytes);
|
||||
if (!mypkt) {
|
||||
brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
|
||||
nbytes);
|
||||
dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
|
||||
pkt = dev_alloc_skb(dsize);
|
||||
if (!pkt) {
|
||||
brcmf_err("dev_alloc_skb failed: len %d\n", dsize);
|
||||
return -EIO;
|
||||
}
|
||||
pkt->priority = 0;
|
||||
|
||||
/* For a write, copy the buffer data into the packet. */
|
||||
if (write)
|
||||
memcpy(mypkt->data, buf, nbytes);
|
||||
/* Determine initial transfer parameters */
|
||||
sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
|
||||
if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
|
||||
dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
|
||||
else
|
||||
dsize = size;
|
||||
|
||||
err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
|
||||
SDIO_FUNC_1, addr, mypkt);
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
/* For a read, copy the packet data back to the buffer. */
|
||||
if (!err && !write)
|
||||
memcpy(buf, mypkt->data, nbytes);
|
||||
/* Do the transfer(s) */
|
||||
while (size) {
|
||||
/* Set the backplane window to include the start address */
|
||||
bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address);
|
||||
if (bcmerror)
|
||||
break;
|
||||
|
||||
brcmu_pkt_buf_free_skb(mypkt);
|
||||
return err;
|
||||
brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
|
||||
write ? "write" : "read", dsize,
|
||||
sdaddr, address & SBSDIO_SBWINDOW_MASK);
|
||||
|
||||
sdaddr &= SBSDIO_SB_OFT_ADDR_MASK;
|
||||
sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
||||
|
||||
skb_put(pkt, dsize);
|
||||
if (write)
|
||||
memcpy(pkt->data, data, dsize);
|
||||
bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
|
||||
write, SDIO_FUNC_1,
|
||||
sdaddr, pkt);
|
||||
if (bcmerror) {
|
||||
brcmf_err("membytes transfer failed\n");
|
||||
break;
|
||||
}
|
||||
if (!write)
|
||||
memcpy(data, pkt->data, dsize);
|
||||
skb_trim(pkt, dsize);
|
||||
|
||||
/* Adjust for next transfer (if any) */
|
||||
size -= dsize;
|
||||
if (size) {
|
||||
data += dsize;
|
||||
address += dsize;
|
||||
sdaddr = 0;
|
||||
dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
|
||||
}
|
||||
}
|
||||
|
||||
dev_kfree_skb(pkt);
|
||||
|
||||
/* Return the window to backplane enumeration space for core access */
|
||||
if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad))
|
||||
brcmf_err("FAILED to set window back to 0x%x\n",
|
||||
sdiodev->sbwad);
|
||||
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/sched.h> /* request_irq() */
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/brcmfmac-sdio.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <defs.h>
|
||||
@ -40,32 +41,30 @@
|
||||
|
||||
#define DMA_ALIGN_MASK 0x03
|
||||
|
||||
#define SDIO_DEVICE_ID_BROADCOM_43143 43143
|
||||
#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
|
||||
#define SDIO_DEVICE_ID_BROADCOM_4335 0x4335
|
||||
|
||||
#define SDIO_FUNC1_BLOCKSIZE 64
|
||||
#define SDIO_FUNC2_BLOCKSIZE 512
|
||||
|
||||
/* devices we support, null terminated */
|
||||
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
|
||||
{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)},
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4335)},
|
||||
{ /* end: all zeroes */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static struct list_head oobirq_lh;
|
||||
struct brcmf_sdio_oobirq {
|
||||
unsigned int irq;
|
||||
unsigned long flags;
|
||||
struct list_head list;
|
||||
};
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
|
||||
|
||||
|
||||
static bool
|
||||
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
|
||||
@ -424,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
struct brcmf_sdio_oobirq *oobirq_entry;
|
||||
|
||||
if (list_empty(&oobirq_lh)) {
|
||||
brcmf_err("no valid oob irq resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
|
||||
list);
|
||||
|
||||
sdiodev->irq = oobirq_entry->irq;
|
||||
sdiodev->irq_flags = oobirq_entry->flags;
|
||||
list_del(&oobirq_entry->list);
|
||||
kfree(oobirq_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
@ -491,15 +463,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
dev_set_drvdata(&func->dev, bus_if);
|
||||
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
|
||||
sdiodev->dev = &sdiodev->func[1]->dev;
|
||||
sdiodev->pdata = brcmfmac_sdio_pdata;
|
||||
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
init_waitqueue_head(&sdiodev->request_byte_wait);
|
||||
init_waitqueue_head(&sdiodev->request_word_wait);
|
||||
init_waitqueue_head(&sdiodev->request_chain_wait);
|
||||
init_waitqueue_head(&sdiodev->request_buffer_wait);
|
||||
err = brcmf_sdio_getintrcfg(sdiodev);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
|
||||
err = brcmf_sdio_probe(sdiodev);
|
||||
@ -594,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = {
|
||||
static struct sdio_driver brcmf_sdmmc_driver = {
|
||||
.probe = brcmf_ops_sdio_probe,
|
||||
.remove = brcmf_ops_sdio_remove,
|
||||
.name = "brcmfmac",
|
||||
.name = BRCMFMAC_SDIO_PDATA_NAME,
|
||||
.id_table = brcmf_sdmmc_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.drv = {
|
||||
@ -603,43 +573,40 @@ static struct sdio_driver brcmf_sdmmc_driver = {
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct brcmf_sdio_oobirq *oobirq_entry;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&oobirq_lh);
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
if (!res)
|
||||
break;
|
||||
brcmfmac_sdio_pdata = pdev->dev.platform_data;
|
||||
|
||||
oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
|
||||
GFP_KERNEL);
|
||||
if (!oobirq_entry)
|
||||
return -ENOMEM;
|
||||
oobirq_entry->irq = res->start;
|
||||
oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
|
||||
list_add_tail(&oobirq_entry->list, &oobirq_lh);
|
||||
}
|
||||
if (i == 0)
|
||||
return -ENXIO;
|
||||
if (brcmfmac_sdio_pdata->power_on)
|
||||
brcmfmac_sdio_pdata->power_on();
|
||||
|
||||
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
if (ret)
|
||||
brcmf_err("sdio_register_driver failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int brcmf_sdio_pd_remove(struct platform_device *pdev)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
if (brcmfmac_sdio_pdata->power_off)
|
||||
brcmfmac_sdio_pdata->power_off();
|
||||
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver brcmf_sdio_pd = {
|
||||
.probe = brcmf_sdio_pd_probe,
|
||||
.remove = brcmf_sdio_pd_remove,
|
||||
.driver = {
|
||||
.name = "brcmf_sdio_pd"
|
||||
.name = BRCMFMAC_SDIO_PDATA_NAME
|
||||
}
|
||||
};
|
||||
|
||||
@ -647,9 +614,10 @@ void brcmf_sdio_exit(void)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
platform_driver_unregister(&brcmf_sdio_pd);
|
||||
if (brcmfmac_sdio_pdata)
|
||||
platform_driver_unregister(&brcmf_sdio_pd);
|
||||
else
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
}
|
||||
|
||||
void brcmf_sdio_init(void)
|
||||
@ -658,28 +626,12 @@ void brcmf_sdio_init(void)
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
ret = platform_driver_register(&brcmf_sdio_pd);
|
||||
ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
|
||||
if (ret == -ENODEV) {
|
||||
brcmf_dbg(SDIO, "No platform data available, registering without.\n");
|
||||
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
brcmf_err("platform_driver_register failed: %d\n", ret);
|
||||
brcmf_err("driver registration failed: %d\n", ret);
|
||||
}
|
||||
#else
|
||||
void brcmf_sdio_exit(void)
|
||||
{
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
}
|
||||
|
||||
void brcmf_sdio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
if (ret)
|
||||
brcmf_err("sdio_register_driver failed: %d\n", ret);
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
497
drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
Normal file
497
drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <defs.h>
|
||||
#include <dhd.h>
|
||||
#include <dhd_dbg.h>
|
||||
#include "fwil.h"
|
||||
#include "fwil_types.h"
|
||||
#include "btcoex.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
|
||||
/* T1 start SCO/eSCO priority suppression */
|
||||
#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000
|
||||
|
||||
/* BT registers values during DHCP */
|
||||
#define BRCMF_BT_DHCP_REG50 0x8022
|
||||
#define BRCMF_BT_DHCP_REG51 0
|
||||
#define BRCMF_BT_DHCP_REG64 0
|
||||
#define BRCMF_BT_DHCP_REG65 0
|
||||
#define BRCMF_BT_DHCP_REG71 0
|
||||
#define BRCMF_BT_DHCP_REG66 0x2710
|
||||
#define BRCMF_BT_DHCP_REG41 0x33
|
||||
#define BRCMF_BT_DHCP_REG68 0x190
|
||||
|
||||
/* number of samples for SCO detection */
|
||||
#define BRCMF_BT_SCO_SAMPLES 12
|
||||
|
||||
/**
|
||||
* enum brcmf_btcoex_state - BT coex DHCP state machine states
|
||||
* @BRCMF_BT_DHCP_IDLE: DCHP is idle
|
||||
* @BRCMF_BT_DHCP_START: DHCP started, wait before
|
||||
* boosting wifi priority
|
||||
* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended,
|
||||
* boost wifi priority
|
||||
* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end,
|
||||
* restore defaults
|
||||
*/
|
||||
enum brcmf_btcoex_state {
|
||||
BRCMF_BT_DHCP_IDLE,
|
||||
BRCMF_BT_DHCP_START,
|
||||
BRCMF_BT_DHCP_OPPR_WIN,
|
||||
BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_btcoex_info - BT coex related information
|
||||
* @vif: interface for which request was done.
|
||||
* @timer: timer for DHCP state machine
|
||||
* @timeout: configured timeout.
|
||||
* @timer_on: DHCP timer active
|
||||
* @dhcp_done: DHCP finished before T1/T2 timer expiration
|
||||
* @bt_state: DHCP state machine state
|
||||
* @work: DHCP state machine work
|
||||
* @cfg: driver private data for cfg80211 interface
|
||||
* @reg66: saved value of btc_params 66
|
||||
* @reg41: saved value of btc_params 41
|
||||
* @reg68: saved value of btc_params 68
|
||||
* @saved_regs_part1: flag indicating regs 66,41,68
|
||||
* have been saved
|
||||
* @reg51: saved value of btc_params 51
|
||||
* @reg64: saved value of btc_params 64
|
||||
* @reg65: saved value of btc_params 65
|
||||
* @reg71: saved value of btc_params 71
|
||||
* @saved_regs_part1: flag indicating regs 50,51,64,65,71
|
||||
* have been saved
|
||||
*/
|
||||
struct brcmf_btcoex_info {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct timer_list timer;
|
||||
u16 timeout;
|
||||
bool timer_on;
|
||||
bool dhcp_done;
|
||||
enum brcmf_btcoex_state bt_state;
|
||||
struct work_struct work;
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
u32 reg66;
|
||||
u32 reg41;
|
||||
u32 reg68;
|
||||
bool saved_regs_part1;
|
||||
u32 reg50;
|
||||
u32 reg51;
|
||||
u32 reg64;
|
||||
u32 reg65;
|
||||
u32 reg71;
|
||||
bool saved_regs_part2;
|
||||
};
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_params_write() - write btc_params firmware variable
|
||||
* @ifp: interface
|
||||
* @addr: btc_params register number
|
||||
* @data: data to write
|
||||
*/
|
||||
static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data)
|
||||
{
|
||||
struct {
|
||||
__le32 addr;
|
||||
__le32 data;
|
||||
} reg_write;
|
||||
|
||||
reg_write.addr = cpu_to_le32(addr);
|
||||
reg_write.data = cpu_to_le32(data);
|
||||
return brcmf_fil_iovar_data_set(ifp, "btc_params",
|
||||
®_write, sizeof(reg_write));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_params_read() - read btc_params firmware variable
|
||||
* @ifp: interface
|
||||
* @addr: btc_params register number
|
||||
* @data: read data
|
||||
*/
|
||||
static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
|
||||
{
|
||||
*data = addr;
|
||||
|
||||
return brcmf_fil_iovar_int_get(ifp, "btc_params", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters
|
||||
* @btci: BT coex info
|
||||
* @trump_sco:
|
||||
* true - set SCO/eSCO parameters for compatibility
|
||||
* during DHCP window
|
||||
* false - restore saved parameter values
|
||||
*
|
||||
* Enhanced BT COEX settings for eSCO compatibility during DHCP window
|
||||
*/
|
||||
static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
|
||||
bool trump_sco)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
|
||||
|
||||
if (trump_sco && !btci->saved_regs_part2) {
|
||||
/* this should reduce eSCO agressive
|
||||
* retransmit w/o breaking it
|
||||
*/
|
||||
|
||||
/* save current */
|
||||
brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n");
|
||||
brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
|
||||
brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
|
||||
brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
|
||||
brcmf_btcoex_params_read(ifp, 65, &btci->reg65);
|
||||
brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
|
||||
|
||||
btci->saved_regs_part2 = true;
|
||||
brcmf_dbg(TRACE,
|
||||
"saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
btci->reg50, btci->reg51, btci->reg64,
|
||||
btci->reg65, btci->reg71);
|
||||
|
||||
/* pacify the eSco */
|
||||
brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50);
|
||||
brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51);
|
||||
brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64);
|
||||
brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65);
|
||||
brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71);
|
||||
|
||||
} else if (btci->saved_regs_part2) {
|
||||
/* restore previously saved bt params */
|
||||
brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n");
|
||||
brcmf_btcoex_params_write(ifp, 50, btci->reg50);
|
||||
brcmf_btcoex_params_write(ifp, 51, btci->reg51);
|
||||
brcmf_btcoex_params_write(ifp, 64, btci->reg64);
|
||||
brcmf_btcoex_params_write(ifp, 65, btci->reg65);
|
||||
brcmf_btcoex_params_write(ifp, 71, btci->reg71);
|
||||
|
||||
brcmf_dbg(TRACE,
|
||||
"restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
btci->reg50, btci->reg51, btci->reg64,
|
||||
btci->reg65, btci->reg71);
|
||||
|
||||
btci->saved_regs_part2 = false;
|
||||
} else {
|
||||
brcmf_err("attempted to restore not saved BTCOEX params\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active
|
||||
* @ifp: interface
|
||||
*
|
||||
* return: true if SCO/eSCO session is active
|
||||
*/
|
||||
static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
|
||||
{
|
||||
int ioc_res = 0;
|
||||
bool res = false;
|
||||
int sco_id_cnt = 0;
|
||||
u32 param27;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) {
|
||||
ioc_res = brcmf_btcoex_params_read(ifp, 27, ¶m27);
|
||||
|
||||
if (ioc_res < 0) {
|
||||
brcmf_err("ioc read btc params error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27);
|
||||
|
||||
if ((param27 & 0x6) == 2) { /* count both sco & esco */
|
||||
sco_id_cnt++;
|
||||
}
|
||||
|
||||
if (sco_id_cnt > 2) {
|
||||
brcmf_dbg(TRACE,
|
||||
"sco/esco detected, pkt id_cnt:%d samples:%d\n",
|
||||
sco_id_cnt, i);
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
brcmf_dbg(TRACE, "exit: result=%d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* btcmf_btcoex_save_part1() - save first step parameters.
|
||||
*/
|
||||
static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->vif->ifp;
|
||||
|
||||
if (!btci->saved_regs_part1) {
|
||||
/* Retrieve and save original reg value */
|
||||
brcmf_btcoex_params_read(ifp, 66, &btci->reg66);
|
||||
brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
|
||||
brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
|
||||
btci->saved_regs_part1 = true;
|
||||
brcmf_dbg(TRACE,
|
||||
"saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
|
||||
btci->reg66, btci->reg41,
|
||||
btci->reg68);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_restore_part1() - restore first step parameters.
|
||||
*/
|
||||
static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
if (btci->saved_regs_part1) {
|
||||
btci->saved_regs_part1 = false;
|
||||
ifp = btci->vif->ifp;
|
||||
brcmf_btcoex_params_write(ifp, 66, btci->reg66);
|
||||
brcmf_btcoex_params_write(ifp, 41, btci->reg41);
|
||||
brcmf_btcoex_params_write(ifp, 68, btci->reg68);
|
||||
brcmf_dbg(TRACE,
|
||||
"restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
|
||||
btci->reg66, btci->reg41,
|
||||
btci->reg68);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_timerfunc() - BT coex timer callback
|
||||
*/
|
||||
static void brcmf_btcoex_timerfunc(ulong data)
|
||||
{
|
||||
struct brcmf_btcoex_info *bt_local = (struct brcmf_btcoex_info *)data;
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
bt_local->timer_on = false;
|
||||
schedule_work(&bt_local->work);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_handler() - BT coex state machine work handler
|
||||
* @work: work
|
||||
*/
|
||||
static void brcmf_btcoex_handler(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_btcoex_info *btci;
|
||||
btci = container_of(work, struct brcmf_btcoex_info, work);
|
||||
if (btci->timer_on) {
|
||||
btci->timer_on = false;
|
||||
del_timer_sync(&btci->timer);
|
||||
}
|
||||
|
||||
switch (btci->bt_state) {
|
||||
case BRCMF_BT_DHCP_START:
|
||||
/* DHCP started provide OPPORTUNITY window
|
||||
to get DHCP address
|
||||
*/
|
||||
brcmf_dbg(TRACE, "DHCP started\n");
|
||||
btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
|
||||
if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
|
||||
mod_timer(&btci->timer, btci->timer.expires);
|
||||
} else {
|
||||
btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME;
|
||||
mod_timer(&btci->timer,
|
||||
jiffies +
|
||||
msecs_to_jiffies(BRCMF_BTCOEX_OPPR_WIN_TIME));
|
||||
}
|
||||
btci->timer_on = true;
|
||||
break;
|
||||
|
||||
case BRCMF_BT_DHCP_OPPR_WIN:
|
||||
if (btci->dhcp_done) {
|
||||
brcmf_dbg(TRACE, "DHCP done before T1 expiration\n");
|
||||
goto idle;
|
||||
}
|
||||
|
||||
/* DHCP is not over yet, start lowering BT priority */
|
||||
brcmf_dbg(TRACE, "DHCP T1:%d expired\n",
|
||||
BRCMF_BTCOEX_OPPR_WIN_TIME);
|
||||
brcmf_btcoex_boost_wifi(btci, true);
|
||||
|
||||
btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
|
||||
mod_timer(&btci->timer,
|
||||
jiffies + msecs_to_jiffies(btci->timeout));
|
||||
btci->timer_on = true;
|
||||
break;
|
||||
|
||||
case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
|
||||
if (btci->dhcp_done)
|
||||
brcmf_dbg(TRACE, "DHCP done before T2 expiration\n");
|
||||
else
|
||||
brcmf_dbg(TRACE, "DHCP T2:%d expired\n",
|
||||
BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
|
||||
|
||||
goto idle;
|
||||
|
||||
default:
|
||||
brcmf_err("invalid state=%d !!!\n", btci->bt_state);
|
||||
goto idle;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
idle:
|
||||
btci->bt_state = BRCMF_BT_DHCP_IDLE;
|
||||
btci->timer_on = false;
|
||||
brcmf_btcoex_boost_wifi(btci, false);
|
||||
cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL);
|
||||
brcmf_btcoex_restore_part1(btci);
|
||||
btci->vif = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_attach() - initialize BT coex data
|
||||
* @cfg: driver private cfg80211 data
|
||||
*
|
||||
* return: 0 on success
|
||||
*/
|
||||
int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_btcoex_info *btci = NULL;
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL);
|
||||
if (!btci)
|
||||
return -ENOMEM;
|
||||
|
||||
btci->bt_state = BRCMF_BT_DHCP_IDLE;
|
||||
|
||||
/* Set up timer for BT */
|
||||
btci->timer_on = false;
|
||||
btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
|
||||
init_timer(&btci->timer);
|
||||
btci->timer.data = (ulong)btci;
|
||||
btci->timer.function = brcmf_btcoex_timerfunc;
|
||||
btci->cfg = cfg;
|
||||
btci->saved_regs_part1 = false;
|
||||
btci->saved_regs_part2 = false;
|
||||
|
||||
INIT_WORK(&btci->work, brcmf_btcoex_handler);
|
||||
|
||||
cfg->btcoex = btci;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_detach - clean BT coex data
|
||||
* @cfg: driver private cfg80211 data
|
||||
*/
|
||||
void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
if (!cfg->btcoex)
|
||||
return;
|
||||
|
||||
if (cfg->btcoex->timer_on) {
|
||||
cfg->btcoex->timer_on = false;
|
||||
del_timer_sync(&cfg->btcoex->timer);
|
||||
}
|
||||
|
||||
cancel_work_sync(&cfg->btcoex->work);
|
||||
|
||||
brcmf_btcoex_boost_wifi(cfg->btcoex, false);
|
||||
brcmf_btcoex_restore_part1(cfg->btcoex);
|
||||
|
||||
kfree(cfg->btcoex);
|
||||
cfg->btcoex = NULL;
|
||||
}
|
||||
|
||||
static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
struct brcmf_if *ifp = btci->vif->ifp;
|
||||
|
||||
btcmf_btcoex_save_part1(btci);
|
||||
/* set new regs values */
|
||||
brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66);
|
||||
brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41);
|
||||
brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68);
|
||||
btci->dhcp_done = false;
|
||||
btci->bt_state = BRCMF_BT_DHCP_START;
|
||||
schedule_work(&btci->work);
|
||||
brcmf_dbg(TRACE, "enable BT DHCP Timer\n");
|
||||
}
|
||||
|
||||
static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
|
||||
{
|
||||
/* Stop any bt timer because DHCP session is done */
|
||||
btci->dhcp_done = true;
|
||||
if (btci->timer_on) {
|
||||
brcmf_dbg(TRACE, "disable BT DHCP Timer\n");
|
||||
btci->timer_on = false;
|
||||
del_timer_sync(&btci->timer);
|
||||
|
||||
/* schedule worker if transition to IDLE is needed */
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
|
||||
brcmf_dbg(TRACE, "bt_state:%d\n",
|
||||
btci->bt_state);
|
||||
schedule_work(&btci->work);
|
||||
}
|
||||
} else {
|
||||
/* Restore original values */
|
||||
brcmf_btcoex_restore_part1(btci);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_btcoex_set_mode - set BT coex mode
|
||||
* @cfg: driver private cfg80211 data
|
||||
* @mode: Wifi-Bluetooth coexistence mode
|
||||
*
|
||||
* return: 0 on success
|
||||
*/
|
||||
int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
|
||||
enum brcmf_btcoex_mode mode, u16 duration)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
|
||||
struct brcmf_btcoex_info *btci = cfg->btcoex;
|
||||
struct brcmf_if *ifp = cfg->pub->iflist[0];
|
||||
|
||||
switch (mode) {
|
||||
case BRCMF_BTCOEX_DISABLED:
|
||||
brcmf_dbg(TRACE, "DHCP session starts\n");
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
|
||||
return -EBUSY;
|
||||
/* Start BT timer only for SCO connection */
|
||||
if (brcmf_btcoex_is_sco_active(ifp)) {
|
||||
btci->timeout = duration;
|
||||
btci->vif = vif;
|
||||
brcmf_btcoex_dhcp_start(btci);
|
||||
}
|
||||
break;
|
||||
|
||||
case BRCMF_BTCOEX_ENABLED:
|
||||
brcmf_dbg(TRACE, "DHCP session ends\n");
|
||||
if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
|
||||
vif == btci->vif) {
|
||||
brcmf_btcoex_dhcp_end(btci);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
brcmf_dbg(TRACE, "Unknown mode, ignored\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
29
drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
Normal file
29
drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef WL_BTCOEX_H_
|
||||
#define WL_BTCOEX_H_
|
||||
|
||||
enum brcmf_btcoex_mode {
|
||||
BRCMF_BTCOEX_DISABLED,
|
||||
BRCMF_BTCOEX_ENABLED
|
||||
};
|
||||
|
||||
int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
|
||||
enum brcmf_btcoex_mode mode, u16 duration);
|
||||
|
||||
#endif /* WL_BTCOEX_H_ */
|
@ -28,6 +28,7 @@
|
||||
/*******************************************************************************
|
||||
* IO codes that are interpreted by dongle firmware
|
||||
******************************************************************************/
|
||||
#define BRCMF_C_GET_VERSION 1
|
||||
#define BRCMF_C_UP 2
|
||||
#define BRCMF_C_DOWN 3
|
||||
#define BRCMF_C_SET_PROMISC 10
|
||||
|
@ -754,14 +754,14 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
/* this is P2P_DEVICE interface */
|
||||
brcmf_dbg(INFO, "allocate non-netdev interface\n");
|
||||
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
|
||||
if (!ifp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
} else {
|
||||
brcmf_dbg(INFO, "allocate netdev interface\n");
|
||||
/* Allocate netdev, including space for private structure */
|
||||
ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
|
||||
if (!ndev) {
|
||||
brcmf_err("OOM - alloc_netdev\n");
|
||||
if (!ndev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
@ -899,7 +899,10 @@ int brcmf_bus_start(struct device *dev)
|
||||
goto fail;
|
||||
|
||||
drvr->fw_signals = true;
|
||||
(void)brcmf_fws_init(drvr);
|
||||
ret = brcmf_fws_init(drvr);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
brcmf_fws_add_interface(ifp);
|
||||
|
||||
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/platform_data/brcmfmac-sdio.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
@ -324,6 +325,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME);
|
||||
*/
|
||||
#define BRCMF_IDLE_INTERVAL 1
|
||||
|
||||
#define KSO_WAIT_US 50
|
||||
#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
|
||||
|
||||
/*
|
||||
* Conversion of 802.1D priority to precedence level
|
||||
*/
|
||||
@ -333,95 +337,6 @@ static uint prio2prec(u32 prio)
|
||||
(prio^2) : prio;
|
||||
}
|
||||
|
||||
/* core registers */
|
||||
struct sdpcmd_regs {
|
||||
u32 corecontrol; /* 0x00, rev8 */
|
||||
u32 corestatus; /* rev8 */
|
||||
u32 PAD[1];
|
||||
u32 biststatus; /* rev8 */
|
||||
|
||||
/* PCMCIA access */
|
||||
u16 pcmciamesportaladdr; /* 0x010, rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciamesportalmask; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciawrframebc; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciaunderflowtimer; /* rev8 */
|
||||
u16 PAD[1];
|
||||
|
||||
/* interrupt */
|
||||
u32 intstatus; /* 0x020, rev8 */
|
||||
u32 hostintmask; /* rev8 */
|
||||
u32 intmask; /* rev8 */
|
||||
u32 sbintstatus; /* rev8 */
|
||||
u32 sbintmask; /* rev8 */
|
||||
u32 funcintmask; /* rev4 */
|
||||
u32 PAD[2];
|
||||
u32 tosbmailbox; /* 0x040, rev8 */
|
||||
u32 tohostmailbox; /* rev8 */
|
||||
u32 tosbmailboxdata; /* rev8 */
|
||||
u32 tohostmailboxdata; /* rev8 */
|
||||
|
||||
/* synchronized access to registers in SDIO clock domain */
|
||||
u32 sdioaccess; /* 0x050, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* PCMCIA frame control */
|
||||
u8 pcmciaframectrl; /* 0x060, rev8 */
|
||||
u8 PAD[3];
|
||||
u8 pcmciawatermark; /* rev8 */
|
||||
u8 PAD[155];
|
||||
|
||||
/* interrupt batching control */
|
||||
u32 intrcvlazy; /* 0x100, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* counters */
|
||||
u32 cmd52rd; /* 0x110, rev8 */
|
||||
u32 cmd52wr; /* rev8 */
|
||||
u32 cmd53rd; /* rev8 */
|
||||
u32 cmd53wr; /* rev8 */
|
||||
u32 abort; /* rev8 */
|
||||
u32 datacrcerror; /* rev8 */
|
||||
u32 rdoutofsync; /* rev8 */
|
||||
u32 wroutofsync; /* rev8 */
|
||||
u32 writebusy; /* rev8 */
|
||||
u32 readwait; /* rev8 */
|
||||
u32 readterm; /* rev8 */
|
||||
u32 writeterm; /* rev8 */
|
||||
u32 PAD[40];
|
||||
u32 clockctlstatus; /* rev8 */
|
||||
u32 PAD[7];
|
||||
|
||||
u32 PAD[128]; /* DMA engines */
|
||||
|
||||
/* SDIO/PCMCIA CIS region */
|
||||
char cis[512]; /* 0x400-0x5ff, rev6 */
|
||||
|
||||
/* PCMCIA function control registers */
|
||||
char pcmciafcr[256]; /* 0x600-6ff, rev6 */
|
||||
u16 PAD[55];
|
||||
|
||||
/* PCMCIA backplane access */
|
||||
u16 backplanecsr; /* 0x76E, rev6 */
|
||||
u16 backplaneaddr0; /* rev6 */
|
||||
u16 backplaneaddr1; /* rev6 */
|
||||
u16 backplaneaddr2; /* rev6 */
|
||||
u16 backplaneaddr3; /* rev6 */
|
||||
u16 backplanedata0; /* rev6 */
|
||||
u16 backplanedata1; /* rev6 */
|
||||
u16 backplanedata2; /* rev6 */
|
||||
u16 backplanedata3; /* rev6 */
|
||||
u16 PAD[31];
|
||||
|
||||
/* sprom "size" & "blank" info */
|
||||
u16 spromstatus; /* 0x7BE, rev2 */
|
||||
u32 PAD[464];
|
||||
|
||||
u16 PAD[0x80];
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Device console log buffer state */
|
||||
struct brcmf_console {
|
||||
@ -588,12 +503,14 @@ struct brcmf_sdio {
|
||||
|
||||
bool txoff; /* Transmit flow-controlled */
|
||||
struct brcmf_sdio_count sdcnt;
|
||||
bool sr_enabled; /* SaveRestore enabled */
|
||||
bool sleeping; /* SDIO bus sleeping */
|
||||
};
|
||||
|
||||
/* clkstate */
|
||||
#define CLK_NONE 0
|
||||
#define CLK_SDONLY 1
|
||||
#define CLK_PENDING 2 /* Not used yet */
|
||||
#define CLK_PENDING 2
|
||||
#define CLK_AVAIL 3
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -601,7 +518,7 @@ static int qcount[NUMPRIO];
|
||||
static int tx_packets[NUMPRIO];
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
|
||||
#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
|
||||
|
||||
#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
|
||||
|
||||
@ -665,6 +582,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
|
||||
{
|
||||
u8 wr_val = 0, rd_val, cmp_val, bmask;
|
||||
int err = 0;
|
||||
int try_cnt = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
|
||||
/* 1st KSO write goes to AOS wake up core if device is asleep */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
||||
wr_val, &err);
|
||||
if (err) {
|
||||
brcmf_err("SDIO_AOS KSO write error: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
/* device WAKEUP through KSO:
|
||||
* write bit 0 & read back until
|
||||
* both bits 0 (kso bit) & 1 (dev on status) are set
|
||||
*/
|
||||
cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
|
||||
SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
|
||||
bmask = cmp_val;
|
||||
usleep_range(2000, 3000);
|
||||
} else {
|
||||
/* Put device to sleep, turn off KSO */
|
||||
cmp_val = 0;
|
||||
/* only check for bit0, bit1(dev on status) may not
|
||||
* get cleared right away
|
||||
*/
|
||||
bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
|
||||
}
|
||||
|
||||
do {
|
||||
/* reliable KSO bit set/clr:
|
||||
* the sdiod sleep write access is synced to PMU 32khz clk
|
||||
* just one write attempt may fail,
|
||||
* read it back until it matches written value
|
||||
*/
|
||||
rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
||||
&err);
|
||||
if (((rd_val & bmask) == cmp_val) && !err)
|
||||
break;
|
||||
brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
|
||||
try_cnt, MAX_KSO_ATTEMPTS, err);
|
||||
udelay(KSO_WAIT_US);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
||||
wr_val, &err);
|
||||
} while (try_cnt++ < MAX_KSO_ATTEMPTS);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
|
||||
|
||||
#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
|
||||
@ -680,6 +653,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
||||
|
||||
clkctl = 0;
|
||||
|
||||
if (bus->sr_enabled) {
|
||||
bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
/* Request HT Avail */
|
||||
clkreq =
|
||||
@ -856,6 +834,63 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
|
||||
{
|
||||
int err = 0;
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(SDIO, "request %s currently %s\n",
|
||||
(sleep ? "SLEEP" : "WAKE"),
|
||||
(bus->sleeping ? "SLEEP" : "WAKE"));
|
||||
|
||||
/* If SR is enabled control bus state with KSO */
|
||||
if (bus->sr_enabled) {
|
||||
/* Done if we're already in the requested state */
|
||||
if (sleep == bus->sleeping)
|
||||
goto end;
|
||||
|
||||
/* Going to sleep */
|
||||
if (sleep) {
|
||||
/* Don't sleep if something is pending */
|
||||
if (atomic_read(&bus->intstatus) ||
|
||||
atomic_read(&bus->ipend) > 0 ||
|
||||
(!atomic_read(&bus->fcstate) &&
|
||||
brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
|
||||
data_ok(bus)))
|
||||
return -EBUSY;
|
||||
err = brcmf_sdbrcm_kso_control(bus, false);
|
||||
/* disable watchdog */
|
||||
if (!err)
|
||||
brcmf_sdbrcm_wd_timer(bus, 0);
|
||||
} else {
|
||||
bus->idlecount = 0;
|
||||
err = brcmf_sdbrcm_kso_control(bus, true);
|
||||
}
|
||||
if (!err) {
|
||||
/* Change state */
|
||||
bus->sleeping = sleep;
|
||||
brcmf_dbg(SDIO, "new state %s\n",
|
||||
(sleep ? "SLEEP" : "WAKE"));
|
||||
} else {
|
||||
brcmf_err("error while changing bus sleep state %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
/* control clocks */
|
||||
if (sleep) {
|
||||
if (!bus->sr_enabled)
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok);
|
||||
} else {
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
|
||||
{
|
||||
u32 intstatus = 0;
|
||||
@ -1960,7 +1995,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Enable clock for device interrupts */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
brcmf_sdbrcm_bus_sleep(bus, false, false);
|
||||
|
||||
/* Disable and clear interrupts at the chip level also */
|
||||
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
|
||||
@ -2012,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
||||
bus->tx_seq = bus->rx_seq = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
|
||||
if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
|
||||
enable_irq(bus->sdiodev->irq);
|
||||
bus->sdiodev->irq_en = true;
|
||||
if (bus->sdiodev->oob_irq_requested) {
|
||||
spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
|
||||
if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
|
||||
enable_irq(bus->sdiodev->pdata->oob_irq_nr);
|
||||
bus->sdiodev->irq_en = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
|
||||
}
|
||||
#else
|
||||
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
|
||||
{
|
||||
@ -2096,7 +2127,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* If waiting for HTAVAIL, check status */
|
||||
if (bus->clkstate == CLK_PENDING) {
|
||||
if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
|
||||
u8 clkctl, devctl = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -2142,7 +2173,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||
}
|
||||
|
||||
/* Make sure backplane clock is on */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
|
||||
brcmf_sdbrcm_bus_sleep(bus, false, true);
|
||||
|
||||
/* Pending interrupt indicates new device status */
|
||||
if (atomic_read(&bus->ipend) > 0) {
|
||||
@ -2288,8 +2319,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||
if ((bus->clkstate != CLK_PENDING)
|
||||
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
|
||||
bus->activity = false;
|
||||
brcmf_dbg(SDIO, "idle state\n");
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
brcmf_sdbrcm_bus_sleep(bus, true, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
}
|
||||
@ -2362,69 +2394,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
|
||||
uint size)
|
||||
{
|
||||
int bcmerror = 0;
|
||||
u32 sdaddr;
|
||||
uint dsize;
|
||||
|
||||
/* Determine initial transfer parameters */
|
||||
sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
|
||||
if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
|
||||
dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
|
||||
else
|
||||
dsize = size;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Set the backplane window to include the start address */
|
||||
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
|
||||
if (bcmerror) {
|
||||
brcmf_err("window change failed\n");
|
||||
goto xfer_done;
|
||||
}
|
||||
|
||||
/* Do the transfer(s) */
|
||||
while (size) {
|
||||
brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
|
||||
write ? "write" : "read", dsize,
|
||||
sdaddr, address & SBSDIO_SBWINDOW_MASK);
|
||||
bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
|
||||
sdaddr, data, dsize);
|
||||
if (bcmerror) {
|
||||
brcmf_err("membytes transfer failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Adjust for next transfer (if any) */
|
||||
size -= dsize;
|
||||
if (size) {
|
||||
data += dsize;
|
||||
address += dsize;
|
||||
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
|
||||
address);
|
||||
if (bcmerror) {
|
||||
brcmf_err("window change failed\n");
|
||||
break;
|
||||
}
|
||||
sdaddr = 0;
|
||||
dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
|
||||
}
|
||||
}
|
||||
|
||||
xfer_done:
|
||||
/* Return the window to backplane enumeration space for core access */
|
||||
if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
|
||||
brcmf_err("FAILED to set window back to 0x%x\n",
|
||||
bus->sdiodev->sbwad);
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#define CONSOLE_LINE_MAX 192
|
||||
|
||||
@ -2441,8 +2410,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
|
||||
|
||||
/* Read console log struct */
|
||||
addr = bus->console_addr + offsetof(struct rte_console, log_le);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
|
||||
sizeof(c->log_le));
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
|
||||
sizeof(c->log_le));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2467,7 +2436,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
|
||||
|
||||
/* Read the console buffer */
|
||||
addr = le32_to_cpu(c->log_le.buf);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2592,7 +2561,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
||||
|
||||
/* Make sure backplane clock is on */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
brcmf_sdbrcm_bus_sleep(bus, false, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
|
||||
@ -2650,6 +2619,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
||||
|
||||
bus->activity = false;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_dbg(INFO, "idle\n");
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
} else {
|
||||
@ -2679,16 +2649,15 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
struct sdpcm_shared_le sh_le;
|
||||
__le32 addr_le;
|
||||
|
||||
shaddr = bus->ramsize - 4;
|
||||
shaddr = bus->ci->rambase + bus->ramsize - 4;
|
||||
|
||||
/*
|
||||
* Read last word in socram to determine
|
||||
* address of sdpcm_shared structure
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
||||
(u8 *)&addr_le, 4);
|
||||
brcmf_sdbrcm_bus_sleep(bus, false, false);
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
@ -2708,8 +2677,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
}
|
||||
|
||||
/* Read hndrte_shared structure */
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2745,22 +2714,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
|
||||
|
||||
/* obtain console information from device memory */
|
||||
addr = sh->console_addr + offsetof(struct rte_console, log_le);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
console_ptr = le32_to_cpu(sh_val);
|
||||
|
||||
addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
console_size = le32_to_cpu(sh_val);
|
||||
|
||||
addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
||||
(u8 *)&sh_val, sizeof(u32));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
console_index = le32_to_cpu(sh_val);
|
||||
@ -2774,8 +2743,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
|
||||
|
||||
/* obtain the console data from device */
|
||||
conbuf[console_size] = '\0';
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
|
||||
console_size);
|
||||
rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
|
||||
console_size);
|
||||
if (rv < 0)
|
||||
goto done;
|
||||
|
||||
@ -2812,8 +2781,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
@ -2856,14 +2825,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (sh->assert_file_addr != 0) {
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
|
||||
(u8 *)file, 80);
|
||||
error = brcmf_sdio_ramrw(bus->sdiodev, false,
|
||||
sh->assert_file_addr, (u8 *)file, 80);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
if (sh->assert_exp_addr != 0) {
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr,
|
||||
(u8 *)expr, 80);
|
||||
error = brcmf_sdio_ramrw(bus->sdiodev, false,
|
||||
sh->assert_exp_addr, (u8 *)expr, 80);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
@ -3021,84 +2990,8 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
||||
return rxlen ? (int)rxlen : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
|
||||
static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
||||
{
|
||||
int bcmerror = 0;
|
||||
u32 varaddr;
|
||||
u32 varsizew;
|
||||
__le32 varsizew_le;
|
||||
#ifdef DEBUG
|
||||
char *nvram_ularray;
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Even if there are no vars are to be written, we still
|
||||
need to set the ramsize. */
|
||||
varaddr = (bus->ramsize - 4) - bus->varsz;
|
||||
|
||||
if (bus->vars) {
|
||||
/* Write the vars list */
|
||||
bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr,
|
||||
bus->vars, bus->varsz);
|
||||
#ifdef DEBUG
|
||||
/* Verify NVRAM bytes */
|
||||
brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n",
|
||||
bus->varsz);
|
||||
nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
|
||||
if (!nvram_ularray)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Upload image to verify downloaded contents. */
|
||||
memset(nvram_ularray, 0xaa, bus->varsz);
|
||||
|
||||
/* Read the vars list to temp buffer for comparison */
|
||||
bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
|
||||
nvram_ularray, bus->varsz);
|
||||
if (bcmerror) {
|
||||
brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
|
||||
bcmerror, bus->varsz, varaddr);
|
||||
}
|
||||
/* Compare the org NVRAM with the one read from RAM */
|
||||
if (memcmp(bus->vars, nvram_ularray, bus->varsz))
|
||||
brcmf_err("Downloaded NVRAM image is corrupted\n");
|
||||
else
|
||||
brcmf_err("Download/Upload/Compare of NVRAM ok\n");
|
||||
|
||||
kfree(nvram_ularray);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
/* adjust to the user specified RAM */
|
||||
brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
|
||||
brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
|
||||
varaddr, bus->varsz);
|
||||
|
||||
/*
|
||||
* Determine the length token:
|
||||
* Varsize, converted to words, in lower 16-bits, checksum
|
||||
* in upper 16-bits.
|
||||
*/
|
||||
if (bcmerror) {
|
||||
varsizew = 0;
|
||||
varsizew_le = cpu_to_le32(0);
|
||||
} else {
|
||||
varsizew = bus->varsz / 4;
|
||||
varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
|
||||
varsizew_le = cpu_to_le32(varsizew);
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
|
||||
bus->varsz, varsizew);
|
||||
|
||||
/* Write the length token to the last word */
|
||||
bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
|
||||
(u8 *)&varsizew_le, 4);
|
||||
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
||||
{
|
||||
int bcmerror = 0;
|
||||
struct chip_info *ci = bus->ci;
|
||||
|
||||
/* To enter download state, disable ARM and reset SOCRAM.
|
||||
@ -3107,41 +3000,19 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
||||
if (enter) {
|
||||
bus->alp_only = true;
|
||||
|
||||
ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
||||
|
||||
ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
|
||||
|
||||
/* Clear the top bit of memory */
|
||||
if (bus->ramsize) {
|
||||
u32 zeros = 0;
|
||||
brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
|
||||
(u8 *)&zeros, 4);
|
||||
}
|
||||
brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
|
||||
} else {
|
||||
if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
|
||||
brcmf_err("SOCRAM core is down after reset?\n");
|
||||
bcmerror = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bcmerror = brcmf_sdbrcm_write_vars(bus);
|
||||
if (bcmerror) {
|
||||
brcmf_err("no vars written to RAM\n");
|
||||
bcmerror = 0;
|
||||
}
|
||||
|
||||
w_sdreg32(bus, 0xFFFFFFFF,
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
|
||||
ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
||||
if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars,
|
||||
bus->varsz))
|
||||
return false;
|
||||
|
||||
/* Allow HT Clock now that the ARM is running. */
|
||||
bus->alp_only = false;
|
||||
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
|
||||
}
|
||||
fail:
|
||||
return bcmerror;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
|
||||
@ -3156,10 +3027,11 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
|
||||
|
||||
static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
||||
{
|
||||
int offset = 0;
|
||||
int offset;
|
||||
uint len;
|
||||
u8 *memblock = NULL, *memptr;
|
||||
int ret;
|
||||
u8 idx;
|
||||
|
||||
brcmf_dbg(INFO, "Enter\n");
|
||||
|
||||
@ -3180,10 +3052,15 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
||||
memptr += (BRCMF_SDALIGN -
|
||||
((u32)(unsigned long)memblock % BRCMF_SDALIGN));
|
||||
|
||||
offset = bus->ci->rambase;
|
||||
|
||||
/* Download image */
|
||||
while ((len =
|
||||
brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
|
||||
ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
|
||||
len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
|
||||
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4);
|
||||
if (BRCMF_MAX_CORENUM != idx)
|
||||
memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec));
|
||||
while (len) {
|
||||
ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len);
|
||||
if (ret) {
|
||||
brcmf_err("error %d on writing %d membytes at 0x%08x\n",
|
||||
ret, MEMBLOCK, offset);
|
||||
@ -3191,6 +3068,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
||||
}
|
||||
|
||||
offset += MEMBLOCK;
|
||||
len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
|
||||
}
|
||||
|
||||
err:
|
||||
@ -3298,7 +3176,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
||||
int bcmerror = -1;
|
||||
|
||||
/* Keep arm in reset */
|
||||
if (brcmf_sdbrcm_download_state(bus, true)) {
|
||||
if (!brcmf_sdbrcm_download_state(bus, true)) {
|
||||
brcmf_err("error placing ARM core in reset\n");
|
||||
goto err;
|
||||
}
|
||||
@ -3314,7 +3192,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
||||
}
|
||||
|
||||
/* Take arm out of reset */
|
||||
if (brcmf_sdbrcm_download_state(bus, false)) {
|
||||
if (!brcmf_sdbrcm_download_state(bus, false)) {
|
||||
brcmf_err("error getting out of ARM core reset\n");
|
||||
goto err;
|
||||
}
|
||||
@ -3325,6 +3203,103 @@ err:
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
|
||||
{
|
||||
u32 addr, reg;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* old chips with PMU version less than 17 don't support save restore */
|
||||
if (bus->ci->pmurev < 17)
|
||||
return false;
|
||||
|
||||
/* read PMU chipcontrol register 3*/
|
||||
addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
|
||||
brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL);
|
||||
addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
|
||||
reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL);
|
||||
|
||||
return (bool)reg;
|
||||
}
|
||||
|
||||
static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
|
||||
{
|
||||
int err = 0;
|
||||
u8 val;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
|
||||
&err);
|
||||
if (err) {
|
||||
brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
|
||||
val, &err);
|
||||
if (err) {
|
||||
brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add CMD14 Support */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
|
||||
(SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
|
||||
SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
|
||||
&err);
|
||||
if (err) {
|
||||
brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
|
||||
return;
|
||||
}
|
||||
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
SBSDIO_FORCE_HT, &err);
|
||||
if (err) {
|
||||
brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* set flag */
|
||||
bus->sr_enabled = true;
|
||||
brcmf_dbg(INFO, "SR enabled\n");
|
||||
}
|
||||
|
||||
/* enable KSO bit */
|
||||
static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
|
||||
{
|
||||
u8 val;
|
||||
int err = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* KSO bit added in SDIO core rev 12 */
|
||||
if (bus->ci->c_inf[1].rev < 12)
|
||||
return 0;
|
||||
|
||||
val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
||||
&err);
|
||||
if (err) {
|
||||
brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
|
||||
val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
|
||||
SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
||||
val, &err);
|
||||
if (err) {
|
||||
brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
||||
{
|
||||
@ -3423,8 +3398,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
/* Restore previous clock setting */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
|
||||
if (brcmf_sdbrcm_sr_capable(bus)) {
|
||||
brcmf_sdbrcm_sr_init(bus);
|
||||
} else {
|
||||
/* Restore previous clock setting */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
saveclk, &err);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = brcmf_sdio_intr_register(bus->sdiodev);
|
||||
@ -3485,7 +3465,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
||||
brcmf_dbg(TIMER, "Enter\n");
|
||||
|
||||
/* Poll period: check device if appropriate. */
|
||||
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
|
||||
if (!bus->sr_enabled &&
|
||||
bus->poll && (++bus->polltick >= bus->pollrate)) {
|
||||
u32 intstatus = 0;
|
||||
|
||||
/* Reset poll tick */
|
||||
@ -3536,7 +3517,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
||||
bus->console.count -= bus->console_interval;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
/* Make sure backplane clock is on */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
brcmf_sdbrcm_bus_sleep(bus, false, false);
|
||||
if (brcmf_sdbrcm_readconsole(bus) < 0)
|
||||
/* stop on error */
|
||||
bus->console_interval = 0;
|
||||
@ -3553,8 +3534,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
||||
bus->activity = false;
|
||||
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
|
||||
} else {
|
||||
brcmf_dbg(SDIO, "idle\n");
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
brcmf_sdbrcm_bus_sleep(bus, true, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
}
|
||||
@ -3565,6 +3547,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
||||
|
||||
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
|
||||
{
|
||||
if (chipid == BCM43143_CHIP_ID)
|
||||
return true;
|
||||
if (chipid == BCM43241_CHIP_ID)
|
||||
return true;
|
||||
if (chipid == BCM4329_CHIP_ID)
|
||||
@ -3573,6 +3557,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
|
||||
return true;
|
||||
if (chipid == BCM4334_CHIP_ID)
|
||||
return true;
|
||||
if (chipid == BCM4335_CHIP_ID)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3650,7 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
||||
int err = 0;
|
||||
int reg_addr;
|
||||
u32 reg_val;
|
||||
u8 idx;
|
||||
u32 drivestrength;
|
||||
|
||||
bus->alp_only = true;
|
||||
|
||||
@ -3686,8 +3672,16 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
|
||||
SDIO_DRIVE_STRENGTH);
|
||||
if (brcmf_sdbrcm_kso_init(bus)) {
|
||||
brcmf_err("error enabling KSO\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
|
||||
drivestrength = bus->sdiodev->pdata->drive_strength;
|
||||
else
|
||||
drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
|
||||
brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
|
||||
|
||||
/* Get info on the SOCRAM cores... */
|
||||
bus->ramsize = bus->ci->ramsize;
|
||||
@ -3696,12 +3690,37 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set core control so an SDIO reset does a backplane reset */
|
||||
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
||||
reg_addr = bus->ci->c_inf[idx].base +
|
||||
offsetof(struct sdpcmd_regs, corecontrol);
|
||||
reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
|
||||
brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
|
||||
/* Set card control so an SDIO card reset does a WLAN backplane reset */
|
||||
reg_val = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SDIO_CCCR_BRCM_CARDCTRL, &err);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
|
||||
|
||||
brcmf_sdio_regwb(bus->sdiodev,
|
||||
SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
/* set PMUControl so a backplane reset does PMU state reload */
|
||||
reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
|
||||
pmucontrol);
|
||||
reg_val = brcmf_sdio_regrl(bus->sdiodev,
|
||||
reg_addr,
|
||||
&err);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
|
||||
|
||||
brcmf_sdio_regwl(bus->sdiodev,
|
||||
reg_addr,
|
||||
reg_val,
|
||||
&err);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
@ -3755,6 +3774,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
|
||||
bus->use_rxchain = false;
|
||||
bus->sd_rxchain = false;
|
||||
|
||||
/* SR state */
|
||||
bus->sleeping = false;
|
||||
bus->sr_enabled = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <uapi/linux/nl80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
@ -31,8 +32,11 @@
|
||||
#include "dhd_dbg.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "fwil.h"
|
||||
#include "fwil_types.h"
|
||||
#include "fweh.h"
|
||||
#include "fwsignal.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
|
||||
/**
|
||||
* DOC: Firmware Signalling
|
||||
@ -144,6 +148,9 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
|
||||
#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01
|
||||
#define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02
|
||||
|
||||
#define BRCMF_FWS_RET_OK_NOSCHEDULE 0
|
||||
#define BRCMF_FWS_RET_OK_SCHEDULE 1
|
||||
|
||||
/**
|
||||
* enum brcmf_fws_skb_state - indicates processing state of skb.
|
||||
*
|
||||
@ -265,6 +272,9 @@ struct brcmf_skbuff_cb {
|
||||
brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
|
||||
BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
|
||||
|
||||
/* How long to defer borrowing in jiffies */
|
||||
#define BRCMF_FWS_BORROW_DEFER_PERIOD (HZ / 10)
|
||||
|
||||
/**
|
||||
* enum brcmf_fws_fifo - fifo indices used by dongle firmware.
|
||||
*
|
||||
@ -419,9 +429,11 @@ struct brcmf_fws_info {
|
||||
struct work_struct fws_dequeue_work;
|
||||
u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
|
||||
int fifo_credit[BRCMF_FWS_FIFO_COUNT];
|
||||
int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
|
||||
int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
|
||||
u32 fifo_credit_map;
|
||||
u32 fifo_delay_map;
|
||||
unsigned long borrow_defer_timestamp;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -678,28 +690,28 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
|
||||
}
|
||||
|
||||
static struct brcmf_fws_mac_descriptor*
|
||||
brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da)
|
||||
brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp,
|
||||
u8 *da)
|
||||
{
|
||||
struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
|
||||
struct brcmf_if *ifp;
|
||||
bool multicast;
|
||||
enum nl80211_iftype iftype;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
|
||||
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
|
||||
|
||||
multicast = is_multicast_ether_addr(da);
|
||||
ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0];
|
||||
if (WARN_ON(!ifp))
|
||||
goto done;
|
||||
iftype = brcmf_cfg80211_get_iftype(ifp);
|
||||
|
||||
/* Multicast destination and P2P clients get the interface entry.
|
||||
* STA gets the interface entry if there is no exact match. For
|
||||
* example, TDLS destinations have their own entry.
|
||||
*/
|
||||
entry = NULL;
|
||||
if (multicast && ifp->fws_desc)
|
||||
if ((multicast || iftype == NL80211_IFTYPE_STATION ||
|
||||
iftype == NL80211_IFTYPE_P2P_CLIENT) && ifp->fws_desc)
|
||||
entry = ifp->fws_desc;
|
||||
|
||||
if (entry != NULL && multicast)
|
||||
if (entry != NULL && iftype != NL80211_IFTYPE_STATION)
|
||||
goto done;
|
||||
|
||||
entry = brcmf_fws_mac_descriptor_lookup(fws, da);
|
||||
@ -711,26 +723,29 @@ done:
|
||||
return entry;
|
||||
}
|
||||
|
||||
static bool brcmf_fws_mac_desc_ready(struct brcmf_fws_mac_descriptor *entry,
|
||||
int fifo)
|
||||
static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws,
|
||||
struct brcmf_fws_mac_descriptor *entry,
|
||||
int fifo)
|
||||
{
|
||||
bool ready;
|
||||
struct brcmf_fws_mac_descriptor *if_entry;
|
||||
bool closed;
|
||||
|
||||
/*
|
||||
* destination entry is ready when firmware says it is OPEN
|
||||
* and there are no packets enqueued for it.
|
||||
/* for unique destination entries the related interface
|
||||
* may be closed.
|
||||
*/
|
||||
ready = entry->state == BRCMF_FWS_STATE_OPEN &&
|
||||
!entry->suppressed &&
|
||||
brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0;
|
||||
if (entry->mac_handle) {
|
||||
if_entry = &fws->desc.iface[entry->interface_id];
|
||||
if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
|
||||
return true;
|
||||
}
|
||||
/* an entry is closed when the state is closed and
|
||||
* the firmware did not request anything.
|
||||
*/
|
||||
closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
|
||||
!entry->requested_credit && !entry->requested_packet;
|
||||
|
||||
/*
|
||||
* Or when the destination entry is CLOSED, but firmware has
|
||||
* specifically requested packets for this entry.
|
||||
*/
|
||||
ready = ready || (entry->state == BRCMF_FWS_STATE_CLOSE &&
|
||||
(entry->requested_credit + entry->requested_packet));
|
||||
return ready;
|
||||
/* Or firmware does not allow traffic for given fifo */
|
||||
return closed || !(entry->ac_bitmap & BIT(fifo));
|
||||
}
|
||||
|
||||
static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
|
||||
@ -825,11 +840,12 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
|
||||
{
|
||||
struct brcmf_if *ifp = fws->drvr->iflist[if_id];
|
||||
|
||||
brcmf_dbg(TRACE,
|
||||
"enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
|
||||
if (WARN_ON(!ifp))
|
||||
return;
|
||||
|
||||
brcmf_dbg(TRACE,
|
||||
"enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
|
||||
|
||||
if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
|
||||
pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
|
||||
brcmf_txflowblock_if(ifp,
|
||||
@ -861,9 +877,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
|
||||
entry = &fws->desc.nodes[mac_handle & 0x1F];
|
||||
if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
|
||||
brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx);
|
||||
if (entry->occupied)
|
||||
if (entry->occupied) {
|
||||
brcmf_fws_mac_desc_cleanup(fws, entry, -1);
|
||||
brcmf_fws_clear_mac_descriptor(entry);
|
||||
else
|
||||
} else
|
||||
fws->stats.mac_update_failed++;
|
||||
return 0;
|
||||
}
|
||||
@ -914,12 +931,13 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
|
||||
entry->requested_credit = 0;
|
||||
if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
|
||||
entry->state = BRCMF_FWS_STATE_OPEN;
|
||||
return BRCMF_FWS_RET_OK_SCHEDULE;
|
||||
} else {
|
||||
entry->state = BRCMF_FWS_STATE_CLOSE;
|
||||
for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++)
|
||||
brcmf_fws_tim_update(fws, entry, i);
|
||||
}
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
}
|
||||
|
||||
static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
|
||||
@ -946,10 +964,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
|
||||
switch (type) {
|
||||
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
|
||||
entry->state = BRCMF_FWS_STATE_OPEN;
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_SCHEDULE;
|
||||
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
|
||||
entry->state = BRCMF_FWS_STATE_CLOSE;
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@ -979,15 +997,40 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
|
||||
entry->requested_packet = data[0];
|
||||
|
||||
entry->ac_bitmap = data[2];
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_SCHEDULE;
|
||||
}
|
||||
|
||||
static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
|
||||
u8 fifo, u8 credits)
|
||||
{
|
||||
int lender_ac;
|
||||
int *borrowed;
|
||||
int *fifo_credit;
|
||||
|
||||
if (!credits)
|
||||
return;
|
||||
|
||||
if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
|
||||
(fws->credits_borrowed[0])) {
|
||||
for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
|
||||
lender_ac--) {
|
||||
borrowed = &fws->credits_borrowed[lender_ac];
|
||||
if (*borrowed) {
|
||||
fws->fifo_credit_map |= (1 << lender_ac);
|
||||
fifo_credit = &fws->fifo_credit[lender_ac];
|
||||
if (*borrowed >= credits) {
|
||||
*borrowed -= credits;
|
||||
*fifo_credit += credits;
|
||||
return;
|
||||
} else {
|
||||
credits -= *borrowed;
|
||||
*fifo_credit += *borrowed;
|
||||
*borrowed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fws->fifo_credit_map |= 1 << fifo;
|
||||
fws->fifo_credit[fifo] += credits;
|
||||
}
|
||||
@ -1074,7 +1117,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
|
||||
int num_nodes;
|
||||
int node_pos;
|
||||
int prec_out;
|
||||
int pmsk = 3;
|
||||
int pmsk;
|
||||
int i;
|
||||
|
||||
table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
|
||||
@ -1083,11 +1126,14 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
entry = &table[(node_pos + i) % num_nodes];
|
||||
if (!entry->occupied)
|
||||
if (!entry->occupied ||
|
||||
brcmf_fws_mac_desc_closed(fws, entry, fifo))
|
||||
continue;
|
||||
|
||||
if (entry->suppressed)
|
||||
pmsk = 2;
|
||||
else
|
||||
pmsk = 3;
|
||||
p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
|
||||
if (p == NULL) {
|
||||
if (entry->suppressed) {
|
||||
@ -1250,7 +1296,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
|
||||
|
||||
if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
|
||||
brcmf_dbg(INFO, "ignored\n");
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
}
|
||||
|
||||
brcmf_dbg(TRACE, "enter: data %pM\n", data);
|
||||
@ -1259,8 +1305,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
|
||||
|
||||
brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map,
|
||||
fws->fifo_delay_map);
|
||||
brcmf_fws_schedule_deq(fws);
|
||||
return 0;
|
||||
return BRCMF_FWS_RET_OK_SCHEDULE;
|
||||
}
|
||||
|
||||
static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
|
||||
@ -1344,6 +1389,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
u8 type;
|
||||
u8 len;
|
||||
u8 *data;
|
||||
s32 status;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
|
||||
ifidx, skb->len, signal_len);
|
||||
@ -1363,6 +1410,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
data_len = signal_len;
|
||||
signal_data = skb->data;
|
||||
|
||||
status = BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
while (data_len > 0) {
|
||||
/* extract tlv info */
|
||||
type = signal_data[0];
|
||||
@ -1388,6 +1436,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
if (len != brcmf_fws_get_tlv_len(fws, type))
|
||||
break;
|
||||
|
||||
err = BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
switch (type) {
|
||||
case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
|
||||
case BRCMF_FWS_TYPE_COMP_TXSTATUS:
|
||||
@ -1398,21 +1447,22 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_MAC_OPEN:
|
||||
case BRCMF_FWS_TYPE_MAC_CLOSE:
|
||||
brcmf_fws_macdesc_state_indicate(fws, type, data);
|
||||
err = brcmf_fws_macdesc_state_indicate(fws, type, data);
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
|
||||
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
|
||||
brcmf_fws_interface_state_indicate(fws, type, data);
|
||||
err = brcmf_fws_interface_state_indicate(fws, type,
|
||||
data);
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
|
||||
case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
|
||||
brcmf_fws_request_indicate(fws, type, data);
|
||||
err = brcmf_fws_request_indicate(fws, type, data);
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_TXSTATUS:
|
||||
brcmf_fws_txstatus_indicate(fws, data);
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
|
||||
brcmf_fws_fifocreditback_indicate(fws, data);
|
||||
err = brcmf_fws_fifocreditback_indicate(fws, data);
|
||||
break;
|
||||
case BRCMF_FWS_TYPE_RSSI:
|
||||
brcmf_fws_rssi_indicate(fws, *data);
|
||||
@ -1426,7 +1476,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
fws->stats.tlv_invalid_type++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == BRCMF_FWS_RET_OK_SCHEDULE)
|
||||
status = BRCMF_FWS_RET_OK_SCHEDULE;
|
||||
signal_data += len + 2;
|
||||
data_len -= len + 2;
|
||||
}
|
||||
@ -1434,6 +1485,9 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
if (data_len != 0)
|
||||
fws->stats.tlv_parse_failed++;
|
||||
|
||||
if (status == BRCMF_FWS_RET_OK_SCHEDULE)
|
||||
brcmf_fws_schedule_deq(fws);
|
||||
|
||||
/* signalling processing result does
|
||||
* not affect the actual ethernet packet.
|
||||
*/
|
||||
@ -1553,7 +1607,7 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
@ -1595,7 +1649,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
|
||||
/* free the hanger slot */
|
||||
brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
|
||||
&pktout, true);
|
||||
brcmf_txfinalize(fws->drvr, skb, false);
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
@ -1629,11 +1682,31 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
|
||||
|
||||
|
||||
fail:
|
||||
if (rc)
|
||||
if (rc) {
|
||||
brcmf_txfinalize(fws->drvr, skb, false);
|
||||
fws->stats.rollback_failed++;
|
||||
else
|
||||
} else
|
||||
fws->stats.rollback_success++;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
|
||||
{
|
||||
int lender_ac;
|
||||
|
||||
if (time_after(fws->borrow_defer_timestamp, jiffies))
|
||||
return -ENAVAIL;
|
||||
|
||||
for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
|
||||
if (fws->fifo_credit[lender_ac]) {
|
||||
fws->credits_borrowed[lender_ac]++;
|
||||
fws->fifo_credit[lender_ac]--;
|
||||
if (fws->fifo_credit[lender_ac] == 0)
|
||||
fws->fifo_credit_map &= ~(1 << lender_ac);
|
||||
brcmf_dbg(TRACE, "borrow credit from: %d\n", lender_ac);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENAVAIL;
|
||||
}
|
||||
|
||||
static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
|
||||
@ -1669,8 +1742,17 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fifo != BRCMF_FWS_FIFO_AC_BE)
|
||||
fws->borrow_defer_timestamp = jiffies +
|
||||
BRCMF_FWS_BORROW_DEFER_PERIOD;
|
||||
|
||||
if (!(*credit)) {
|
||||
brcmf_dbg(TRACE, "exit: credits depleted\n");
|
||||
/* Try to borrow a credit from other queue */
|
||||
if (fifo == BRCMF_FWS_FIFO_AC_BE &&
|
||||
brcmf_fws_borrow_credit(fws) == 0)
|
||||
return 0;
|
||||
|
||||
brcmf_dbg(TRACE, "exit: ac=%d, credits depleted\n", fifo);
|
||||
return -ENAVAIL;
|
||||
}
|
||||
(*credit)--;
|
||||
@ -1712,17 +1794,17 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
|
||||
return rc;
|
||||
|
||||
rollback:
|
||||
rc = brcmf_fws_rollback_toq(fws, skb);
|
||||
brcmf_fws_rollback_toq(fws, skb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_fws_info *fws = drvr->fws;
|
||||
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
|
||||
struct ethhdr *eh = (struct ethhdr *)(skb->data);
|
||||
ulong flags;
|
||||
u8 ifidx = ifp->ifidx;
|
||||
int fifo = BRCMF_FWS_FIFO_BCMC;
|
||||
bool multicast = is_multicast_ether_addr(eh->h_dest);
|
||||
|
||||
@ -1734,9 +1816,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&ifp->pend_8021x_cnt);
|
||||
|
||||
if (!brcmf_fws_fc_active(drvr->fws)) {
|
||||
if (!brcmf_fws_fc_active(fws)) {
|
||||
/* If the protocol uses a data header, apply it */
|
||||
brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
|
||||
brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
|
||||
|
||||
/* Use bus module to send data frame */
|
||||
return brcmf_bus_txdata(drvr->bus_if, skb);
|
||||
@ -1744,9 +1826,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
|
||||
/* set control buffer information */
|
||||
skcb->if_flags = 0;
|
||||
skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest);
|
||||
skcb->mac = brcmf_fws_find_mac_desc(fws, ifp, eh->h_dest);
|
||||
skcb->state = BRCMF_FWS_SKBSTATE_NEW;
|
||||
brcmf_skb_if_flags_set_field(skb, INDEX, ifidx);
|
||||
brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
|
||||
if (!multicast)
|
||||
fifo = brcmf_fws_prio2fifo[skb->priority];
|
||||
brcmf_skb_if_flags_set_field(skb, FIFO, fifo);
|
||||
@ -1755,14 +1837,18 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
multicast, fifo);
|
||||
|
||||
brcmf_fws_lock(drvr, flags);
|
||||
if (!brcmf_fws_mac_desc_ready(skcb->mac, fifo) ||
|
||||
if (skcb->mac->suppressed ||
|
||||
brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
|
||||
brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
|
||||
(!multicast &&
|
||||
brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) {
|
||||
brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
|
||||
/* enqueue the packet in delayQ */
|
||||
drvr->fws->fifo_delay_map |= 1 << fifo;
|
||||
brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
|
||||
brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
|
||||
} else {
|
||||
brcmf_fws_commit_skb(drvr->fws, fifo, skb);
|
||||
if (brcmf_fws_commit_skb(fws, fifo, skb))
|
||||
if (!multicast)
|
||||
brcmf_skb_pick_up_credit(fws, fifo, skb);
|
||||
}
|
||||
brcmf_fws_unlock(drvr, flags);
|
||||
return 0;
|
||||
@ -1799,14 +1885,17 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
|
||||
void brcmf_fws_del_interface(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
|
||||
ulong flags;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
brcmf_fws_lock(ifp->drvr, flags);
|
||||
ifp->fws_desc = NULL;
|
||||
brcmf_fws_clear_mac_descriptor(entry);
|
||||
brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
|
||||
brcmf_fws_unlock(ifp->drvr, flags);
|
||||
}
|
||||
|
||||
static void brcmf_fws_dequeue_worker(struct work_struct *worker)
|
||||
@ -1826,14 +1915,29 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
|
||||
fws->fifo_credit[fifo]);
|
||||
for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
|
||||
skb = brcmf_fws_deq(fws, fifo);
|
||||
if (!skb)
|
||||
if (!skb || brcmf_fws_commit_skb(fws, fifo, skb))
|
||||
break;
|
||||
if (!brcmf_fws_commit_skb(fws, fifo, skb) &&
|
||||
brcmf_skbcb(skb)->if_flags &
|
||||
if (brcmf_skbcb(skb)->if_flags &
|
||||
BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
|
||||
credit++;
|
||||
}
|
||||
fws->fifo_credit[fifo] -= credit;
|
||||
if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
|
||||
(credit == fws->fifo_credit[fifo])) {
|
||||
fws->fifo_credit[fifo] -= credit;
|
||||
while (brcmf_fws_borrow_credit(fws) == 0) {
|
||||
skb = brcmf_fws_deq(fws, fifo);
|
||||
if (!skb) {
|
||||
brcmf_fws_return_credits(fws, fifo, 1);
|
||||
break;
|
||||
}
|
||||
if (brcmf_fws_commit_skb(fws, fifo, skb)) {
|
||||
brcmf_fws_return_credits(fws, fifo, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fws->fifo_credit[fifo] -= credit;
|
||||
}
|
||||
}
|
||||
brcmf_fws_unlock(fws->drvr, flags);
|
||||
}
|
||||
@ -1872,16 +1976,20 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
|
||||
BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
|
||||
BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE;
|
||||
|
||||
rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
|
||||
rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
|
||||
brcmf_fws_notify_credit_map);
|
||||
if (rc < 0) {
|
||||
brcmf_err("failed to set bdcv2 tlv signaling\n");
|
||||
brcmf_err("register credit map handler failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
|
||||
brcmf_fws_notify_credit_map)) {
|
||||
brcmf_err("register credit map handler failed\n");
|
||||
goto fail;
|
||||
/* setting the iovar may fail if feature is unsupported
|
||||
* so leave the rc as is so driver initialization can
|
||||
* continue.
|
||||
*/
|
||||
if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
|
||||
brcmf_err("failed to set bdcv2 tlv signaling\n");
|
||||
goto fail_event;
|
||||
}
|
||||
|
||||
brcmf_fws_hanger_init(&drvr->fws->hanger);
|
||||
@ -1897,9 +2005,9 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
|
||||
drvr->fw_signals ? "enabled" : "disabled", tlv);
|
||||
return 0;
|
||||
|
||||
fail_event:
|
||||
brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
|
||||
fail:
|
||||
/* disable flow control entirely */
|
||||
drvr->fw_signals = false;
|
||||
brcmf_fws_deinit(drvr);
|
||||
return rc;
|
||||
}
|
||||
@ -1912,6 +2020,14 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
|
||||
if (!fws)
|
||||
return;
|
||||
|
||||
/* disable firmware signalling entirely
|
||||
* to avoid using the workqueue.
|
||||
*/
|
||||
drvr->fw_signals = false;
|
||||
|
||||
if (drvr->fws->fws_wq)
|
||||
destroy_workqueue(drvr->fws->fws_wq);
|
||||
|
||||
/* cleanup */
|
||||
brcmf_fws_lock(drvr, flags);
|
||||
brcmf_fws_cleanup(fws, -1);
|
||||
|
@ -423,29 +423,6 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec.
|
||||
*
|
||||
* @channel: channel number
|
||||
*/
|
||||
static u16 brcmf_p2p_chnr_to_chspec(u16 channel)
|
||||
{
|
||||
u16 chanspec;
|
||||
|
||||
chanspec = channel & WL_CHANSPEC_CHAN_MASK;
|
||||
|
||||
if (channel <= CH_MAX_2G_CHANNEL)
|
||||
chanspec |= WL_CHANSPEC_BAND_2G;
|
||||
else
|
||||
chanspec |= WL_CHANSPEC_BAND_5G;
|
||||
|
||||
chanspec |= WL_CHANSPEC_BW_20;
|
||||
chanspec |= WL_CHANSPEC_CTL_SB_NONE;
|
||||
|
||||
return chanspec;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
|
||||
*
|
||||
@ -837,7 +814,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
|
||||
IEEE80211_CHAN_PASSIVE_SCAN))
|
||||
continue;
|
||||
|
||||
chanspecs[i] = channel_to_chanspec(chan);
|
||||
chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
|
||||
chan);
|
||||
brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n",
|
||||
num_nodfs, chan->hw_value, chanspecs[i]);
|
||||
num_nodfs++;
|
||||
@ -945,8 +923,8 @@ static s32
|
||||
brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct brcmu_chan ch;
|
||||
s32 err = 0;
|
||||
u16 chanspec;
|
||||
|
||||
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||
if (!vif) {
|
||||
@ -961,9 +939,11 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
chanspec = brcmf_p2p_chnr_to_chspec(channel);
|
||||
ch.chnum = channel;
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
|
||||
chanspec, (u16)duration);
|
||||
ch.chspec, (u16)duration);
|
||||
if (!err) {
|
||||
set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status);
|
||||
p2p->remain_on_channel_cookie++;
|
||||
@ -1075,6 +1055,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
|
||||
u32 channel_cnt;
|
||||
u16 *default_chan_list;
|
||||
u32 i;
|
||||
struct brcmu_chan ch;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
@ -1089,15 +1070,23 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
if (channel) {
|
||||
ch.chnum = channel;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
/* insert same channel to the chan_list */
|
||||
for (i = 0; i < channel_cnt; i++)
|
||||
default_chan_list[i] =
|
||||
brcmf_p2p_chnr_to_chspec(channel);
|
||||
default_chan_list[i] = ch.chspec;
|
||||
} else {
|
||||
default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1);
|
||||
default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2);
|
||||
default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3);
|
||||
ch.chnum = SOCIAL_CHAN_1;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
default_chan_list[0] = ch.chspec;
|
||||
ch.chnum = SOCIAL_CHAN_2;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
default_chan_list[1] = ch.chspec;
|
||||
ch.chnum = SOCIAL_CHAN_3;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
default_chan_list[2] = ch.chspec;
|
||||
}
|
||||
err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
|
||||
WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START,
|
||||
@ -1227,6 +1216,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
{
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
|
||||
struct brcmu_chan ch;
|
||||
u8 *ie;
|
||||
s32 err;
|
||||
u8 p2p_dev_addr[ETH_ALEN];
|
||||
@ -1252,8 +1242,12 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
p2p_dev_addr, sizeof(p2p_dev_addr));
|
||||
if ((err >= 0) &&
|
||||
(!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) {
|
||||
afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch :
|
||||
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
|
||||
if (!bi->ctl_ch) {
|
||||
ch.chspec = le16_to_cpu(bi->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
bi->ctl_ch = ch.chnum;
|
||||
}
|
||||
afx_hdl->peer_chan = bi->ctl_ch;
|
||||
brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n",
|
||||
afx_hdl->tx_dst_addr, afx_hdl->peer_chan);
|
||||
complete(&afx_hdl->act_frm_scan);
|
||||
@ -1360,12 +1354,14 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
u8 *frame = (u8 *)(rxframe + 1);
|
||||
struct brcmf_p2p_pub_act_frame *act_frm;
|
||||
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
|
||||
u16 chanspec = be16_to_cpu(rxframe->chanspec);
|
||||
struct brcmu_chan ch;
|
||||
struct ieee80211_mgmt *mgmt_frame;
|
||||
s32 freq;
|
||||
u16 mgmt_type;
|
||||
u8 action;
|
||||
|
||||
ch.chspec = be16_to_cpu(rxframe->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
/* Check if wpa_supplicant has registered for this frame */
|
||||
brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
|
||||
mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4;
|
||||
@ -1384,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
&p2p->status) &&
|
||||
(memcmp(afx_hdl->tx_dst_addr, e->addr,
|
||||
ETH_ALEN) == 0)) {
|
||||
afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
|
||||
afx_hdl->peer_chan = ch.chnum;
|
||||
brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
|
||||
afx_hdl->peer_chan);
|
||||
complete(&afx_hdl->act_frm_scan);
|
||||
@ -1427,8 +1423,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
memcpy(&mgmt_frame->u, frame, mgmt_frame_len);
|
||||
mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
|
||||
|
||||
freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
|
||||
CHSPEC_IS2G(chanspec) ?
|
||||
freq = ieee80211_channel_to_frequency(ch.chnum,
|
||||
ch.band == BRCMU_CHAN_BAND_2G ?
|
||||
IEEE80211_BAND_2GHZ :
|
||||
IEEE80211_BAND_5GHZ);
|
||||
|
||||
@ -1854,6 +1850,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
struct brcmf_cfg80211_vif *vif = ifp->vif;
|
||||
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
|
||||
u16 chanspec = be16_to_cpu(rxframe->chanspec);
|
||||
struct brcmu_chan ch;
|
||||
u8 *mgmt_frame;
|
||||
u32 mgmt_frame_len;
|
||||
s32 freq;
|
||||
@ -1862,9 +1859,12 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
|
||||
e->reason);
|
||||
|
||||
ch.chspec = be16_to_cpu(rxframe->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
|
||||
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
|
||||
(memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) {
|
||||
afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
|
||||
afx_hdl->peer_chan = ch.chnum;
|
||||
brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
|
||||
afx_hdl->peer_chan);
|
||||
complete(&afx_hdl->act_frm_scan);
|
||||
@ -1889,8 +1889,8 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
|
||||
mgmt_frame = (u8 *)(rxframe + 1);
|
||||
mgmt_frame_len = e->datalen - sizeof(*rxframe);
|
||||
freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
|
||||
CHSPEC_IS2G(chanspec) ?
|
||||
freq = ieee80211_channel_to_frequency(ch.chnum,
|
||||
ch.band == BRCMU_CHAN_BAND_2G ?
|
||||
IEEE80211_BAND_2GHZ :
|
||||
IEEE80211_BAND_5GHZ);
|
||||
|
||||
@ -2014,21 +2014,19 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_fil_chan_info_le ci;
|
||||
struct brcmu_chan ch;
|
||||
s32 err;
|
||||
|
||||
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||
|
||||
*chanspec = 11 & WL_CHANSPEC_CHAN_MASK;
|
||||
ch.chnum = 11;
|
||||
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
|
||||
if (!err) {
|
||||
*chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK;
|
||||
if (*chanspec < CH_MAX_2G_CHANNEL)
|
||||
*chanspec |= WL_CHANSPEC_BAND_2G;
|
||||
else
|
||||
*chanspec |= WL_CHANSPEC_BAND_5G;
|
||||
}
|
||||
*chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
|
||||
if (!err)
|
||||
ch.chnum = le32_to_cpu(ci.hw_channel);
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
*chanspec = ch.chspec;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,6 +40,15 @@
|
||||
#define BCM4329_CORE_ARM_BASE 0x18002000
|
||||
#define BCM4329_RAMSIZE 0x48000
|
||||
|
||||
/* bcm43143 */
|
||||
/* SDIO device core */
|
||||
#define BCM43143_CORE_BUS_BASE 0x18002000
|
||||
/* internal memory core */
|
||||
#define BCM43143_CORE_SOCRAM_BASE 0x18004000
|
||||
/* ARM Cortex M3 core, ID 0x82a */
|
||||
#define BCM43143_CORE_ARM_BASE 0x18003000
|
||||
#define BCM43143_RAMSIZE 0x70000
|
||||
|
||||
#define SBCOREREV(sbidh) \
|
||||
((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
|
||||
((sbidh) & SSB_IDHIGH_RCLO))
|
||||
@ -52,6 +61,9 @@
|
||||
#define CIB_REV_MASK 0xff000000
|
||||
#define CIB_REV_SHIFT 24
|
||||
|
||||
/* ARM CR4 core specific control flag bits */
|
||||
#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
|
||||
|
||||
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
|
||||
/* SDIO Pad drive strength to select value mappings */
|
||||
struct sdiod_drive_str {
|
||||
@ -70,6 +82,14 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
|
||||
{0, 0x1}
|
||||
};
|
||||
|
||||
/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
|
||||
static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
|
||||
{16, 0x7},
|
||||
{12, 0x5},
|
||||
{8, 0x3},
|
||||
{4, 0x1}
|
||||
};
|
||||
|
||||
u8
|
||||
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
|
||||
{
|
||||
@ -149,7 +169,7 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
|
||||
|
||||
static void
|
||||
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid)
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits)
|
||||
{
|
||||
u32 regdata, base;
|
||||
u8 idx;
|
||||
@ -235,7 +255,7 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
|
||||
|
||||
static void
|
||||
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid)
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits)
|
||||
{
|
||||
u8 idx;
|
||||
u32 regdata;
|
||||
@ -249,19 +269,36 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
|
||||
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
|
||||
return;
|
||||
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
/* ensure no pending backplane operation
|
||||
* 300uc should be sufficient for backplane ops to be finish
|
||||
* extra 10ms is taken into account for firmware load stage
|
||||
* after 10300us carry on disabling the core anyway
|
||||
*/
|
||||
SPINWAIT(brcmf_sdio_regrl(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
|
||||
NULL), 10300);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
|
||||
NULL);
|
||||
udelay(10);
|
||||
if (regdata)
|
||||
brcmf_err("disabling core 0x%x with reset status %x\n",
|
||||
coreid, regdata);
|
||||
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
BCMA_RESET_CTL_RESET, NULL);
|
||||
udelay(1);
|
||||
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
core_bits, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
usleep_range(10, 20);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid)
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits)
|
||||
{
|
||||
u32 regdata;
|
||||
u8 idx;
|
||||
@ -272,7 +309,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
|
||||
* Must do the disable sequence first to work for
|
||||
* arbitrary current core state.
|
||||
*/
|
||||
brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
|
||||
brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
|
||||
|
||||
/*
|
||||
* Now do the initialization sequence.
|
||||
@ -325,7 +362,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
|
||||
|
||||
static void
|
||||
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid)
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits)
|
||||
{
|
||||
u8 idx;
|
||||
u32 regdata;
|
||||
@ -333,31 +370,69 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
|
||||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
|
||||
/* must disable first to work for arbitrary current core state */
|
||||
brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
|
||||
brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
|
||||
|
||||
/* now do initialization sequence */
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
|
||||
core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
0, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
NULL);
|
||||
udelay(1);
|
||||
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
BCMA_IOCTL_CLK, NULL);
|
||||
core_bits | BCMA_IOCTL_CLK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* safety check for chipinfo */
|
||||
static int brcmf_sdio_chip_cichk(struct chip_info *ci)
|
||||
{
|
||||
u8 core_idx;
|
||||
|
||||
/* check RAM core presence for ARM CM3 core */
|
||||
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
|
||||
if (BRCMF_MAX_CORENUM != core_idx) {
|
||||
core_idx = brcmf_sdio_chip_getinfidx(ci,
|
||||
BCMA_CORE_INTERNAL_MEM);
|
||||
if (BRCMF_MAX_CORENUM == core_idx) {
|
||||
brcmf_err("RAM core not provided with ARM CM3 core\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* check RAM base for ARM CR4 core */
|
||||
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
|
||||
if (BRCMF_MAX_CORENUM != core_idx) {
|
||||
if (ci->rambase == 0) {
|
||||
brcmf_err("RAM base not provided with ARM CR4 core\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* DEBUG */
|
||||
static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u32 regs)
|
||||
{
|
||||
u32 regdata;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Get CC core rev
|
||||
/* Get CC core rev
|
||||
* Chipid is assume to be at offset 0 from regs arg
|
||||
* For different chiptypes or old sdio hosts w/o chipcommon,
|
||||
* other ways of recognition should be added here.
|
||||
@ -375,6 +450,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 BCM43143_CHIP_ID:
|
||||
ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
|
||||
ci->c_inf[0].cib = 0x2b000000;
|
||||
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
|
||||
ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
|
||||
ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
|
||||
ci->c_inf[1].cib = 0x18000000;
|
||||
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
|
||||
ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
|
||||
ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
|
||||
ci->c_inf[2].cib = 0x14000000;
|
||||
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
|
||||
ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
|
||||
ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
|
||||
ci->c_inf[3].cib = 0x07000000;
|
||||
ci->ramsize = BCM43143_RAMSIZE;
|
||||
break;
|
||||
case BCM43241_CHIP_ID:
|
||||
ci->c_inf[0].wrapbase = 0x18100000;
|
||||
ci->c_inf[0].cib = 0x2a084411;
|
||||
@ -435,11 +527,29 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
|
||||
ci->c_inf[3].cib = 0x07004211;
|
||||
ci->ramsize = 0x80000;
|
||||
break;
|
||||
case BCM4335_CHIP_ID:
|
||||
ci->c_inf[0].wrapbase = 0x18100000;
|
||||
ci->c_inf[0].cib = 0x2b084411;
|
||||
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
|
||||
ci->c_inf[1].base = 0x18005000;
|
||||
ci->c_inf[1].wrapbase = 0x18105000;
|
||||
ci->c_inf[1].cib = 0x0f004211;
|
||||
ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
|
||||
ci->c_inf[2].base = 0x18002000;
|
||||
ci->c_inf[2].wrapbase = 0x18102000;
|
||||
ci->c_inf[2].cib = 0x01084411;
|
||||
ci->ramsize = 0xc0000;
|
||||
ci->rambase = 0x180000;
|
||||
break;
|
||||
default:
|
||||
brcmf_err("chipid 0x%x is not supported\n", ci->chip);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = brcmf_sdio_chip_cichk(ci);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (ci->socitype) {
|
||||
case SOCI_SB:
|
||||
ci->iscoreup = brcmf_sdio_sb_iscoreup;
|
||||
@ -539,7 +649,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
|
||||
* Make sure any on-chip ARM is off (in case strapping is wrong),
|
||||
* or downloaded code was already running.
|
||||
*/
|
||||
ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
|
||||
ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
|
||||
}
|
||||
|
||||
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
|
||||
@ -600,21 +710,37 @@ void
|
||||
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u32 drivestrength)
|
||||
{
|
||||
struct sdiod_drive_str *str_tab = NULL;
|
||||
u32 str_mask = 0;
|
||||
u32 str_shift = 0;
|
||||
const struct sdiod_drive_str *str_tab = NULL;
|
||||
u32 str_mask;
|
||||
u32 str_shift;
|
||||
char chn[8];
|
||||
u32 base = ci->c_inf[0].base;
|
||||
u32 i;
|
||||
u32 drivestrength_sel = 0;
|
||||
u32 cc_data_temp;
|
||||
u32 addr;
|
||||
|
||||
if (!(ci->c_inf[0].caps & CC_CAP_PMU))
|
||||
return;
|
||||
|
||||
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
|
||||
case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
|
||||
str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
|
||||
str_tab = sdiod_drvstr_tab1_1v8;
|
||||
str_mask = 0x00003800;
|
||||
str_shift = 11;
|
||||
break;
|
||||
case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
|
||||
/* note: 43143 does not support tristate */
|
||||
i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
|
||||
if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
|
||||
str_tab = sdiod_drvstr_tab2_3v3;
|
||||
str_mask = 0x00000007;
|
||||
str_shift = 0;
|
||||
} else
|
||||
brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
|
||||
brcmf_sdio_chip_name(ci->chip, chn, 8),
|
||||
drivestrength);
|
||||
break;
|
||||
default:
|
||||
brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
|
||||
brcmf_sdio_chip_name(ci->chip, chn, 8),
|
||||
@ -623,30 +749,207 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
|
||||
}
|
||||
|
||||
if (str_tab != NULL) {
|
||||
u32 drivestrength_sel = 0;
|
||||
u32 cc_data_temp;
|
||||
int i;
|
||||
|
||||
for (i = 0; str_tab[i].strength != 0; i++) {
|
||||
if (drivestrength >= str_tab[i].strength) {
|
||||
drivestrength_sel = str_tab[i].sel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
|
||||
1, NULL);
|
||||
cc_data_temp =
|
||||
brcmf_sdio_regrl(sdiodev,
|
||||
CORE_CC_REG(base, chipcontrol_addr),
|
||||
NULL);
|
||||
addr = CORE_CC_REG(base, chipcontrol_addr);
|
||||
brcmf_sdio_regwl(sdiodev, addr, 1, NULL);
|
||||
cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL);
|
||||
cc_data_temp &= ~str_mask;
|
||||
drivestrength_sel <<= str_shift;
|
||||
cc_data_temp |= drivestrength_sel;
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
|
||||
cc_data_temp, NULL);
|
||||
brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL);
|
||||
|
||||
brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
|
||||
drivestrength, cc_data_temp);
|
||||
brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
|
||||
str_tab[i].strength, drivestrength, cc_data_temp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
|
||||
char *nvram_dat, uint nvram_sz)
|
||||
{
|
||||
char *nvram_ularray;
|
||||
int err;
|
||||
bool ret = true;
|
||||
|
||||
/* read back and verify */
|
||||
brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
|
||||
nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
|
||||
/* do not proceed while no memory but */
|
||||
if (!nvram_ularray)
|
||||
return true;
|
||||
|
||||
/* Upload image to verify downloaded contents. */
|
||||
memset(nvram_ularray, 0xaa, nvram_sz);
|
||||
|
||||
/* Read the vars list to temp buffer for comparison */
|
||||
err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
|
||||
nvram_sz);
|
||||
if (err) {
|
||||
brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
|
||||
err, nvram_sz, nvram_addr);
|
||||
} else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
|
||||
brcmf_err("Downloaded NVRAM image is corrupted\n");
|
||||
ret = false;
|
||||
}
|
||||
kfree(nvram_ularray);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else /* DEBUG */
|
||||
static inline bool
|
||||
brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
|
||||
char *nvram_dat, uint nvram_sz)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci,
|
||||
char *nvram_dat, uint nvram_sz)
|
||||
{
|
||||
int err;
|
||||
u32 nvram_addr;
|
||||
u32 token;
|
||||
__le32 token_le;
|
||||
|
||||
nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
|
||||
|
||||
/* Write the vars list */
|
||||
err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
|
||||
if (err) {
|
||||
brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
|
||||
err, nvram_sz, nvram_addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
|
||||
nvram_dat, nvram_sz))
|
||||
return false;
|
||||
|
||||
/* generate token:
|
||||
* nvram size, converted to words, in lower 16-bits, checksum
|
||||
* in upper 16-bits.
|
||||
*/
|
||||
token = nvram_sz / 4;
|
||||
token = (~token << 16) | (token & 0x0000FFFF);
|
||||
token_le = cpu_to_le32(token);
|
||||
|
||||
brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
|
||||
brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
|
||||
nvram_addr, nvram_sz, token);
|
||||
|
||||
/* Write the length token to the last word */
|
||||
if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
|
||||
(u8 *)&token_le, 4))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci)
|
||||
{
|
||||
u32 zeros = 0;
|
||||
|
||||
ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
|
||||
ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
|
||||
|
||||
/* clear length token */
|
||||
brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
|
||||
char *nvram_dat, uint nvram_sz)
|
||||
{
|
||||
u8 core_idx;
|
||||
u32 reg_addr;
|
||||
|
||||
if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
|
||||
brcmf_err("SOCRAM core is down after reset?\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
|
||||
return false;
|
||||
|
||||
/* clear all interrupts */
|
||||
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
|
||||
reg_addr = ci->c_inf[core_idx].base;
|
||||
reg_addr += offsetof(struct sdpcmd_regs, intstatus);
|
||||
brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
|
||||
|
||||
ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci)
|
||||
{
|
||||
ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
|
||||
ARMCR4_BCMA_IOCTL_CPUHALT);
|
||||
}
|
||||
|
||||
static bool
|
||||
brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
|
||||
char *nvram_dat, uint nvram_sz)
|
||||
{
|
||||
u8 core_idx;
|
||||
u32 reg_addr;
|
||||
|
||||
if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
|
||||
return false;
|
||||
|
||||
/* clear all interrupts */
|
||||
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
|
||||
reg_addr = ci->c_inf[core_idx].base;
|
||||
reg_addr += offsetof(struct sdpcmd_regs, intstatus);
|
||||
brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
|
||||
|
||||
/* Write reset vector to address 0 */
|
||||
brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
|
||||
sizeof(ci->rst_vec));
|
||||
|
||||
/* restore ARM */
|
||||
ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci)
|
||||
{
|
||||
u8 arm_core_idx;
|
||||
|
||||
arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
|
||||
if (BRCMF_MAX_CORENUM != arm_core_idx) {
|
||||
brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
|
||||
return;
|
||||
}
|
||||
|
||||
brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
|
||||
}
|
||||
|
||||
bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, char *nvram_dat,
|
||||
uint nvram_sz)
|
||||
{
|
||||
u8 arm_core_idx;
|
||||
|
||||
arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
|
||||
if (BRCMF_MAX_CORENUM != arm_core_idx)
|
||||
return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
|
||||
nvram_sz);
|
||||
|
||||
return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
|
||||
}
|
||||
|
@ -73,15 +73,17 @@ struct chip_info {
|
||||
u32 pmurev;
|
||||
u32 pmucaps;
|
||||
u32 ramsize;
|
||||
u32 rambase;
|
||||
u32 rst_vec; /* reset vertor for ARM CR4 core */
|
||||
|
||||
bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
|
||||
u16 coreid);
|
||||
u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
|
||||
u16 coreid);
|
||||
void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid);
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits);
|
||||
void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid);
|
||||
struct chip_info *ci, u16 coreid, u32 core_bits);
|
||||
};
|
||||
|
||||
struct sbconfig {
|
||||
@ -124,6 +126,95 @@ struct sbconfig {
|
||||
u32 sbidhigh; /* identification */
|
||||
};
|
||||
|
||||
/* sdio core registers */
|
||||
struct sdpcmd_regs {
|
||||
u32 corecontrol; /* 0x00, rev8 */
|
||||
u32 corestatus; /* rev8 */
|
||||
u32 PAD[1];
|
||||
u32 biststatus; /* rev8 */
|
||||
|
||||
/* PCMCIA access */
|
||||
u16 pcmciamesportaladdr; /* 0x010, rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciamesportalmask; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciawrframebc; /* rev8 */
|
||||
u16 PAD[1];
|
||||
u16 pcmciaunderflowtimer; /* rev8 */
|
||||
u16 PAD[1];
|
||||
|
||||
/* interrupt */
|
||||
u32 intstatus; /* 0x020, rev8 */
|
||||
u32 hostintmask; /* rev8 */
|
||||
u32 intmask; /* rev8 */
|
||||
u32 sbintstatus; /* rev8 */
|
||||
u32 sbintmask; /* rev8 */
|
||||
u32 funcintmask; /* rev4 */
|
||||
u32 PAD[2];
|
||||
u32 tosbmailbox; /* 0x040, rev8 */
|
||||
u32 tohostmailbox; /* rev8 */
|
||||
u32 tosbmailboxdata; /* rev8 */
|
||||
u32 tohostmailboxdata; /* rev8 */
|
||||
|
||||
/* synchronized access to registers in SDIO clock domain */
|
||||
u32 sdioaccess; /* 0x050, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* PCMCIA frame control */
|
||||
u8 pcmciaframectrl; /* 0x060, rev8 */
|
||||
u8 PAD[3];
|
||||
u8 pcmciawatermark; /* rev8 */
|
||||
u8 PAD[155];
|
||||
|
||||
/* interrupt batching control */
|
||||
u32 intrcvlazy; /* 0x100, rev8 */
|
||||
u32 PAD[3];
|
||||
|
||||
/* counters */
|
||||
u32 cmd52rd; /* 0x110, rev8 */
|
||||
u32 cmd52wr; /* rev8 */
|
||||
u32 cmd53rd; /* rev8 */
|
||||
u32 cmd53wr; /* rev8 */
|
||||
u32 abort; /* rev8 */
|
||||
u32 datacrcerror; /* rev8 */
|
||||
u32 rdoutofsync; /* rev8 */
|
||||
u32 wroutofsync; /* rev8 */
|
||||
u32 writebusy; /* rev8 */
|
||||
u32 readwait; /* rev8 */
|
||||
u32 readterm; /* rev8 */
|
||||
u32 writeterm; /* rev8 */
|
||||
u32 PAD[40];
|
||||
u32 clockctlstatus; /* rev8 */
|
||||
u32 PAD[7];
|
||||
|
||||
u32 PAD[128]; /* DMA engines */
|
||||
|
||||
/* SDIO/PCMCIA CIS region */
|
||||
char cis[512]; /* 0x400-0x5ff, rev6 */
|
||||
|
||||
/* PCMCIA function control registers */
|
||||
char pcmciafcr[256]; /* 0x600-6ff, rev6 */
|
||||
u16 PAD[55];
|
||||
|
||||
/* PCMCIA backplane access */
|
||||
u16 backplanecsr; /* 0x76E, rev6 */
|
||||
u16 backplaneaddr0; /* rev6 */
|
||||
u16 backplaneaddr1; /* rev6 */
|
||||
u16 backplaneaddr2; /* rev6 */
|
||||
u16 backplaneaddr3; /* rev6 */
|
||||
u16 backplanedata0; /* rev6 */
|
||||
u16 backplanedata1; /* rev6 */
|
||||
u16 backplanedata2; /* rev6 */
|
||||
u16 backplanedata3; /* rev6 */
|
||||
u16 PAD[31];
|
||||
|
||||
/* sprom "size" & "blank" info */
|
||||
u16 spromstatus; /* 0x7BE, rev2 */
|
||||
u32 PAD[464];
|
||||
|
||||
u16 PAD[0x80];
|
||||
};
|
||||
|
||||
extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info **ci_ptr, u32 regs);
|
||||
extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
|
||||
@ -131,6 +222,10 @@ extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci,
|
||||
u32 drivestrength);
|
||||
extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
|
||||
|
||||
extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci);
|
||||
extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, char *nvram_dat,
|
||||
uint nvram_sz);
|
||||
|
||||
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
|
||||
|
@ -48,7 +48,13 @@
|
||||
#define SBSDIO_NUM_FUNCTION 3
|
||||
|
||||
/* function 0 vendor specific CCCR registers */
|
||||
#define SDIO_CCCR_BRCM_SEPINT 0xf2
|
||||
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
|
||||
#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
|
||||
#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
|
||||
#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
|
||||
#define SDIO_CCCR_BRCM_SEPINT 0xf2
|
||||
|
||||
#define SDIO_SEPINT_MASK 0x01
|
||||
#define SDIO_SEPINT_OE 0x02
|
||||
@ -97,9 +103,23 @@
|
||||
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
|
||||
/* Read Frame Byte Count High */
|
||||
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
|
||||
/* MesBusyCtl (rev 11) */
|
||||
#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
|
||||
/* Sdio Core Rev 12 */
|
||||
#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
|
||||
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
|
||||
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
|
||||
#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
|
||||
#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
|
||||
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
|
||||
|
||||
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
|
||||
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
|
||||
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
|
||||
|
||||
/* function 1 OCP space */
|
||||
|
||||
@ -154,13 +174,11 @@ struct brcmf_sdio_dev {
|
||||
wait_queue_head_t request_buffer_wait;
|
||||
struct device *dev;
|
||||
struct brcmf_bus *bus_if;
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
unsigned int irq; /* oob interrupt number */
|
||||
unsigned long irq_flags; /* board specific oob flags */
|
||||
struct brcmfmac_sdio_platform_data *pdata;
|
||||
bool oob_irq_requested;
|
||||
bool irq_en; /* irq enable flags */
|
||||
spinlock_t irq_en_lock;
|
||||
bool irq_wake; /* irq wake enable flags */
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
};
|
||||
|
||||
/* Register/deregister interrupt handler. */
|
||||
@ -224,6 +242,8 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
||||
*/
|
||||
extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
|
||||
u32 addr, u8 *buf, uint nbytes);
|
||||
extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write,
|
||||
u32 address, u8 *data, uint size);
|
||||
|
||||
/* Issue an abort to the specified function */
|
||||
extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "tracepoint.h"
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
#include "btcoex.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "fwil.h"
|
||||
|
||||
@ -334,22 +335,16 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
|
||||
return qdbm;
|
||||
}
|
||||
|
||||
u16 channel_to_chanspec(struct ieee80211_channel *ch)
|
||||
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
|
||||
struct ieee80211_channel *ch)
|
||||
{
|
||||
u16 chanspec;
|
||||
struct brcmu_chan ch_inf;
|
||||
|
||||
chanspec = ieee80211_frequency_to_channel(ch->center_freq);
|
||||
chanspec &= WL_CHANSPEC_CHAN_MASK;
|
||||
ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq);
|
||||
ch_inf.bw = BRCMU_CHAN_BW_20;
|
||||
d11inf->encchspec(&ch_inf);
|
||||
|
||||
if (ch->band == IEEE80211_BAND_2GHZ)
|
||||
chanspec |= WL_CHANSPEC_BAND_2G;
|
||||
else
|
||||
chanspec |= WL_CHANSPEC_BAND_5G;
|
||||
|
||||
chanspec |= WL_CHANSPEC_BW_20;
|
||||
chanspec |= WL_CHANSPEC_CTL_SB_NONE;
|
||||
|
||||
return chanspec;
|
||||
return ch_inf.chspec;
|
||||
}
|
||||
|
||||
/* Traverse a string of 1-byte tag/1-byte length/variable-length value
|
||||
@ -680,7 +675,8 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
|
||||
static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_scan_params_le *params_le,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
u32 n_ssids;
|
||||
@ -712,7 +708,8 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
|
||||
n_channels);
|
||||
if (n_channels > 0) {
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
chanspec = channel_to_chanspec(request->channels[i]);
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf,
|
||||
request->channels[i]);
|
||||
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
|
||||
request->channels[i]->hw_value, chanspec);
|
||||
params_le->channel_list[i] = cpu_to_le16(chanspec);
|
||||
@ -784,7 +781,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
||||
goto exit;
|
||||
}
|
||||
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
|
||||
brcmf_escan_prep(¶ms->params_le, request);
|
||||
brcmf_escan_prep(cfg, ¶ms->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);
|
||||
@ -860,6 +857,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
|
||||
cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
|
||||
brcmf_err("Scanning suppressed: status (%lu)\n",
|
||||
cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
|
||||
brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
|
||||
return -EAGAIN;
|
||||
@ -1050,6 +1052,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
|
||||
|
||||
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
|
||||
s32 err = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
@ -1063,6 +1066,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
|
||||
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
|
||||
}
|
||||
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
|
||||
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
|
||||
brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
}
|
||||
|
||||
@ -1182,7 +1187,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
|
||||
params->chandef.chan->center_freq);
|
||||
if (params->channel_fixed) {
|
||||
/* adding chanspec */
|
||||
chanspec = channel_to_chanspec(params->chandef.chan);
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf,
|
||||
params->chandef.chan);
|
||||
join_params.params_le.chanspec_list[0] =
|
||||
cpu_to_le16(chanspec);
|
||||
join_params.params_le.chanspec_num = cpu_to_le32(1);
|
||||
@ -1572,7 +1578,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
||||
if (chan) {
|
||||
cfg->channel =
|
||||
ieee80211_frequency_to_channel(chan->center_freq);
|
||||
chanspec = channel_to_chanspec(chan);
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf, chan);
|
||||
brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",
|
||||
cfg->channel, chan->center_freq, chanspec);
|
||||
} else {
|
||||
@ -2231,6 +2237,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
|
||||
struct ieee80211_channel *notify_channel;
|
||||
struct cfg80211_bss *bss;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct brcmu_chan ch;
|
||||
s32 err = 0;
|
||||
u16 channel;
|
||||
u32 freq;
|
||||
@ -2245,8 +2252,12 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel = bi->ctl_ch ? bi->ctl_ch :
|
||||
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
|
||||
if (!bi->ctl_ch) {
|
||||
ch.chspec = le16_to_cpu(bi->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
bi->ctl_ch = ch.chnum;
|
||||
}
|
||||
channel = bi->ctl_ch;
|
||||
|
||||
if (channel <= CH_MAX_2G_CHANNEL)
|
||||
band = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
@ -2321,9 +2332,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi = NULL;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct cfg80211_bss *bss;
|
||||
struct brcmu_chan ch;
|
||||
u8 *buf = NULL;
|
||||
s32 err = 0;
|
||||
u16 channel;
|
||||
u32 freq;
|
||||
u16 notify_capability;
|
||||
u16 notify_interval;
|
||||
@ -2350,15 +2361,15 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
|
||||
|
||||
bi = (struct brcmf_bss_info_le *)(buf + 4);
|
||||
|
||||
channel = bi->ctl_ch ? bi->ctl_ch :
|
||||
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
|
||||
ch.chspec = le16_to_cpu(bi->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
|
||||
if (channel <= CH_MAX_2G_CHANNEL)
|
||||
if (ch.band == BRCMU_CHAN_BAND_2G)
|
||||
band = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
else
|
||||
band = wiphy->bands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
freq = ieee80211_channel_to_frequency(channel, band->band);
|
||||
freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
|
||||
notify_channel = ieee80211_get_channel(wiphy, freq);
|
||||
|
||||
notify_capability = le16_to_cpu(bi->capability);
|
||||
@ -2367,7 +2378,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
|
||||
notify_ielen = le32_to_cpu(bi->ie_length);
|
||||
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
|
||||
|
||||
brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
|
||||
brcmf_dbg(CONN, "channel: %d(%d)\n", ch.chnum, freq);
|
||||
brcmf_dbg(CONN, "capability: %X\n", notify_capability);
|
||||
brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
|
||||
brcmf_dbg(CONN, "signal: %d\n", notify_signal);
|
||||
@ -2490,12 +2501,19 @@ static void brcmf_escan_timeout(unsigned long data)
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
|
||||
brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bss,
|
||||
struct brcmf_bss_info_le *bss_info_le)
|
||||
{
|
||||
struct brcmu_chan ch_bss, ch_bss_info_le;
|
||||
|
||||
ch_bss.chspec = le16_to_cpu(bss->chanspec);
|
||||
cfg->d11inf.decchspec(&ch_bss);
|
||||
ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec);
|
||||
cfg->d11inf.decchspec(&ch_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))) &&
|
||||
ch_bss.band == ch_bss_info_le.band &&
|
||||
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) ==
|
||||
@ -2593,7 +2611,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
|
||||
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))
|
||||
if (brcmf_compare_update_same_bss(cfg, bss,
|
||||
bss_info_le))
|
||||
goto exit;
|
||||
}
|
||||
memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
|
||||
@ -3007,6 +3026,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
||||
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
|
||||
brcmf_err("Scanning suppressed: status (%lu)\n",
|
||||
cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!request->n_ssids || !request->n_match_sets) {
|
||||
brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
|
||||
@ -3993,6 +4017,39 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
enum nl80211_crit_proto_id proto,
|
||||
u16 duration)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||
|
||||
/* only DHCP support for now */
|
||||
if (proto != NL80211_CRIT_PROTO_DHCP)
|
||||
return -EINVAL;
|
||||
|
||||
/* suppress and abort scanning */
|
||||
set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
|
||||
brcmf_abort_scanning(cfg);
|
||||
|
||||
return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
|
||||
}
|
||||
|
||||
static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||
|
||||
brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
|
||||
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
|
||||
}
|
||||
|
||||
static struct cfg80211_ops wl_cfg80211_ops = {
|
||||
.add_virtual_intf = brcmf_cfg80211_add_iface,
|
||||
.del_virtual_intf = brcmf_cfg80211_del_iface,
|
||||
@ -4029,6 +4086,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
|
||||
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
|
||||
.start_p2p_device = brcmf_p2p_start_device,
|
||||
.stop_p2p_device = brcmf_p2p_stop_device,
|
||||
.crit_proto_start = brcmf_cfg80211_crit_proto_start,
|
||||
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
.testmode_cmd = brcmf_cfg80211_testmode
|
||||
#endif
|
||||
@ -4337,9 +4396,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
|
||||
struct ieee80211_channel *notify_channel = NULL;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct brcmf_bss_info_le *bi;
|
||||
struct brcmu_chan ch;
|
||||
u32 freq;
|
||||
s32 err = 0;
|
||||
u32 target_channel;
|
||||
u8 *buf;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
@ -4363,15 +4422,15 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
|
||||
goto done;
|
||||
|
||||
bi = (struct brcmf_bss_info_le *)(buf + 4);
|
||||
target_channel = bi->ctl_ch ? bi->ctl_ch :
|
||||
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
|
||||
ch.chspec = le16_to_cpu(bi->chanspec);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
|
||||
if (target_channel <= CH_MAX_2G_CHANNEL)
|
||||
if (ch.band == BRCMU_CHAN_BAND_2G)
|
||||
band = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
else
|
||||
band = wiphy->bands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
freq = ieee80211_channel_to_frequency(target_channel, band->band);
|
||||
freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
|
||||
notify_channel = ieee80211_get_channel(wiphy, freq);
|
||||
|
||||
done:
|
||||
@ -4725,6 +4784,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct brcmf_if *ifp;
|
||||
s32 err = 0;
|
||||
s32 io_type;
|
||||
|
||||
if (!ndev) {
|
||||
brcmf_err("ndev is invalid\n");
|
||||
@ -4765,6 +4825,21 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
brcmf_err("P2P initilisation failed (%d)\n", err);
|
||||
goto cfg80211_p2p_attach_out;
|
||||
}
|
||||
err = brcmf_btcoex_attach(cfg);
|
||||
if (err) {
|
||||
brcmf_err("BT-coex initialisation failed (%d)\n", err);
|
||||
brcmf_p2p_detach(&cfg->p2p);
|
||||
goto cfg80211_p2p_attach_out;
|
||||
}
|
||||
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
|
||||
&io_type);
|
||||
if (err) {
|
||||
brcmf_err("Failed to get D11 version (%d)\n", err);
|
||||
goto cfg80211_p2p_attach_out;
|
||||
}
|
||||
cfg->d11inf.io_type = (u8)io_type;
|
||||
brcmu_d11_attach(&cfg->d11inf);
|
||||
|
||||
return cfg;
|
||||
|
||||
@ -4783,6 +4858,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
||||
struct brcmf_cfg80211_vif *tmp;
|
||||
|
||||
wl_deinit_priv(cfg);
|
||||
brcmf_btcoex_detach(cfg);
|
||||
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
|
||||
brcmf_free_vif(vif);
|
||||
}
|
||||
@ -4885,11 +4961,11 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
|
||||
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
|
||||
struct ieee80211_channel *band_chan_arr;
|
||||
struct brcmf_chanspec_list *list;
|
||||
struct brcmu_chan ch;
|
||||
s32 err;
|
||||
u8 *pbuf;
|
||||
u32 i, j;
|
||||
u32 total;
|
||||
u16 chanspec;
|
||||
enum ieee80211_band band;
|
||||
u32 channel;
|
||||
u32 *n_cnt;
|
||||
@ -4918,42 +4994,30 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
|
||||
|
||||
total = le32_to_cpu(list->count);
|
||||
for (i = 0; i < total; i++) {
|
||||
chanspec = (u16)le32_to_cpu(list->element[i]);
|
||||
channel = CHSPEC_CHANNEL(chanspec);
|
||||
ch.chspec = (u16)le32_to_cpu(list->element[i]);
|
||||
cfg->d11inf.decchspec(&ch);
|
||||
|
||||
if (CHSPEC_IS40(chanspec)) {
|
||||
if (CHSPEC_SB_UPPER(chanspec))
|
||||
channel += CH_10MHZ_APART;
|
||||
else
|
||||
channel -= CH_10MHZ_APART;
|
||||
} else if (CHSPEC_IS80(chanspec)) {
|
||||
brcmf_dbg(INFO, "HT80 center channel : %d\n",
|
||||
channel);
|
||||
continue;
|
||||
}
|
||||
if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
|
||||
(channel <= CH_MAX_2G_CHANNEL)) {
|
||||
if (ch.band == BRCMU_CHAN_BAND_2G) {
|
||||
band_chan_arr = __wl_2ghz_channels;
|
||||
array_size = ARRAY_SIZE(__wl_2ghz_channels);
|
||||
n_cnt = &__wl_band_2ghz.n_channels;
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
|
||||
} else if (CHSPEC_IS5G(chanspec) &&
|
||||
channel >= CH_MIN_5G_CHANNEL) {
|
||||
} else if (ch.band == BRCMU_CHAN_BAND_5G) {
|
||||
band_chan_arr = __wl_5ghz_a_channels;
|
||||
array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
|
||||
n_cnt = &__wl_band_5ghz_a.n_channels;
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
|
||||
} else {
|
||||
brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
|
||||
brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec);
|
||||
continue;
|
||||
}
|
||||
if (!ht40_allowed && CHSPEC_IS40(chanspec))
|
||||
if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40)
|
||||
continue;
|
||||
update = false;
|
||||
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
|
||||
if (band_chan_arr[j].hw_value == channel) {
|
||||
if (band_chan_arr[j].hw_value == ch.chnum) {
|
||||
update = true;
|
||||
break;
|
||||
}
|
||||
@ -4964,16 +5028,16 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
|
||||
index = *n_cnt;
|
||||
if (index < array_size) {
|
||||
band_chan_arr[index].center_freq =
|
||||
ieee80211_channel_to_frequency(channel, band);
|
||||
band_chan_arr[index].hw_value = channel;
|
||||
ieee80211_channel_to_frequency(ch.chnum, band);
|
||||
band_chan_arr[index].hw_value = ch.chnum;
|
||||
|
||||
if (CHSPEC_IS40(chanspec) && ht40_allowed) {
|
||||
if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) {
|
||||
/* assuming the order is HT20, HT40 Upper,
|
||||
* HT40 lower from chanspecs
|
||||
*/
|
||||
ht40_flag = band_chan_arr[index].flags &
|
||||
IEEE80211_CHAN_NO_HT40;
|
||||
if (CHSPEC_SB_UPPER(chanspec)) {
|
||||
if (ch.sb == BRCMU_CHAN_SB_U) {
|
||||
if (ht40_flag == IEEE80211_CHAN_NO_HT40)
|
||||
band_chan_arr[index].flags &=
|
||||
~IEEE80211_CHAN_NO_HT40;
|
||||
@ -4993,11 +5057,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
|
||||
} else {
|
||||
band_chan_arr[index].flags =
|
||||
IEEE80211_CHAN_NO_HT40;
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
channel |= WL_CHANSPEC_BAND_2G;
|
||||
else
|
||||
channel |= WL_CHANSPEC_BAND_5G;
|
||||
channel |= WL_CHANSPEC_BW_20;
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
cfg->d11inf.encchspec(&ch);
|
||||
channel = ch.chspec;
|
||||
err = brcmf_fil_bsscfg_int_get(ifp,
|
||||
"per_chan_info",
|
||||
&channel);
|
||||
@ -5226,6 +5288,13 @@ s32 brcmf_cfg80211_down(struct net_device *ndev)
|
||||
return err;
|
||||
}
|
||||
|
||||
enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
|
||||
{
|
||||
struct wireless_dev *wdev = &ifp->vif->wdev;
|
||||
|
||||
return wdev->iftype;
|
||||
}
|
||||
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
@ -17,6 +17,9 @@
|
||||
#ifndef _wl_cfg80211_h_
|
||||
#define _wl_cfg80211_h_
|
||||
|
||||
/* for brcmu_d11inf */
|
||||
#include <brcmu_d11.h>
|
||||
|
||||
#define WL_NUM_SCAN_MAX 10
|
||||
#define WL_NUM_PMKIDS_MAX MAXPMKID
|
||||
#define WL_TLV_INFO_MAX 1024
|
||||
@ -74,14 +77,16 @@
|
||||
|
||||
|
||||
/**
|
||||
* enum brcmf_scan_status - dongle scan status
|
||||
* enum brcmf_scan_status - scan engine status
|
||||
*
|
||||
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
|
||||
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
|
||||
* @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver.
|
||||
*/
|
||||
enum brcmf_scan_status {
|
||||
BRCMF_SCAN_STATUS_BUSY,
|
||||
BRCMF_SCAN_STATUS_ABORT,
|
||||
BRCMF_SCAN_STATUS_SUPPRESS,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -346,6 +351,7 @@ struct brcmf_cfg80211_vif_event {
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @p2p: peer-to-peer specific information.
|
||||
* @btcoex: Bluetooth coexistence information.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
@ -379,6 +385,7 @@ struct brcmf_cfg80211_info {
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct brcmf_p2p_info p2p;
|
||||
struct brcmf_btcoex_info *btcoex;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_scan_results *bss_list;
|
||||
@ -408,6 +415,7 @@ struct brcmf_cfg80211_info {
|
||||
u8 vif_cnt;
|
||||
struct brcmf_cfg80211_vif_event vif_event;
|
||||
struct completion vif_disabled;
|
||||
struct brcmu_d11inf d11inf;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -474,6 +482,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
|
||||
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
@ -484,7 +493,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct ieee80211_channel *ch);
|
||||
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
|
||||
struct ieee80211_channel *ch);
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
|
@ -21,7 +21,7 @@ ccflags-y := \
|
||||
-Idrivers/net/wireless/brcm80211/brcmsmac/phy \
|
||||
-Idrivers/net/wireless/brcm80211/include
|
||||
|
||||
BRCMSMAC_OFILES := \
|
||||
brcmsmac-y := \
|
||||
mac80211_if.o \
|
||||
ucode_loader.o \
|
||||
ampdu.o \
|
||||
@ -43,11 +43,6 @@ BRCMSMAC_OFILES := \
|
||||
brcms_trace_events.o \
|
||||
debug.o
|
||||
|
||||
ifdef CONFIG_BCMA_DRIVER_GPIO
|
||||
BRCMSMAC_OFILES += led.o
|
||||
endif
|
||||
brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
|
||||
|
||||
MODULEPFX := brcmsmac
|
||||
|
||||
obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
|
||||
$(MODULEPFX)-objs = $(BRCMSMAC_OFILES)
|
||||
obj-$(CONFIG_BRCMSMAC) += brcmsmac.o
|
||||
|
@ -379,7 +379,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
|
||||
u8 local_constraint_qdbm)
|
||||
{
|
||||
struct brcms_c_info *wlc = wlc_cm->wlc;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
|
||||
struct txpwr_limits txpwr;
|
||||
|
||||
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
|
||||
@ -404,7 +404,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
|
||||
struct txpwr_limits *txpwr)
|
||||
{
|
||||
struct brcms_c_info *wlc = wlc_cm->wlc;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
|
||||
uint i;
|
||||
uint chan;
|
||||
int maxpwr;
|
||||
|
@ -556,10 +556,10 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
|
||||
new_int);
|
||||
}
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
if (conf->channel_type == NL80211_CHAN_HT20 ||
|
||||
conf->channel_type == NL80211_CHAN_NO_HT)
|
||||
if (conf->chandef.width == NL80211_CHAN_WIDTH_20 ||
|
||||
conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
|
||||
err = brcms_c_set_channel(wl->wlc,
|
||||
conf->channel->hw_value);
|
||||
conf->chandef.chan->hw_value);
|
||||
else
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
|
@ -5135,7 +5135,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
|
||||
wlc->pub->up = true;
|
||||
|
||||
if (wlc->bandinit_pending) {
|
||||
ch = wlc->pub->ieee_hw->conf.channel;
|
||||
ch = wlc->pub->ieee_hw->conf.chandef.chan;
|
||||
brcms_c_suspend_mac_and_wait(wlc);
|
||||
brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
|
||||
wlc->bandinit_pending = false;
|
||||
@ -7919,7 +7919,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
|
||||
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
|
||||
{
|
||||
struct bcma_device *core = wlc->hw->d11core;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
|
||||
u16 chanspec;
|
||||
|
||||
brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
|
||||
|
@ -19,10 +19,5 @@ ccflags-y := \
|
||||
-Idrivers/net/wireless/brcm80211/brcmutil \
|
||||
-Idrivers/net/wireless/brcm80211/include
|
||||
|
||||
BRCMUTIL_OFILES := \
|
||||
utils.o
|
||||
|
||||
MODULEPFX := brcmutil
|
||||
|
||||
obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o
|
||||
$(MODULEPFX)-objs = $(BRCMUTIL_OFILES)
|
||||
obj-$(CONFIG_BRCMUTIL) += brcmutil.o
|
||||
brcmutil-objs = utils.o d11.o
|
||||
|
162
drivers/net/wireless/brcm80211/brcmutil/d11.c
Normal file
162
drivers/net/wireless/brcm80211/brcmutil/d11.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
/*********************channel spec common functions*********************/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_d11.h>
|
||||
|
||||
static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
|
||||
{
|
||||
ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
|
||||
|
||||
switch (ch->bw) {
|
||||
case BRCMU_CHAN_BW_20:
|
||||
ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
|
||||
break;
|
||||
case BRCMU_CHAN_BW_40:
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch->chnum <= CH_MAX_2G_CHANNEL)
|
||||
ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
|
||||
else
|
||||
ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
|
||||
}
|
||||
|
||||
static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
|
||||
{
|
||||
ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
|
||||
|
||||
switch (ch->bw) {
|
||||
case BRCMU_CHAN_BW_20:
|
||||
ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
|
||||
break;
|
||||
case BRCMU_CHAN_BW_40:
|
||||
case BRCMU_CHAN_BW_80:
|
||||
case BRCMU_CHAN_BW_80P80:
|
||||
case BRCMU_CHAN_BW_160:
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch->chnum <= CH_MAX_2G_CHANNEL)
|
||||
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
|
||||
else
|
||||
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
|
||||
}
|
||||
|
||||
static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
|
||||
|
||||
switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
|
||||
case BRCMU_CHSPEC_D11N_BW_20:
|
||||
ch->bw = BRCMU_CHAN_BW_20;
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11N_BW_40:
|
||||
ch->bw = BRCMU_CHAN_BW_40;
|
||||
val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
|
||||
if (val == BRCMU_CHSPEC_D11N_SB_L) {
|
||||
ch->sb = BRCMU_CHAN_SB_L;
|
||||
ch->chnum -= CH_10MHZ_APART;
|
||||
} else {
|
||||
ch->sb = BRCMU_CHAN_SB_U;
|
||||
ch->chnum += CH_10MHZ_APART;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
|
||||
case BRCMU_CHSPEC_D11N_BND_5G:
|
||||
ch->band = BRCMU_CHAN_BAND_5G;
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11N_BND_2G:
|
||||
ch->band = BRCMU_CHAN_BAND_2G;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
|
||||
|
||||
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
|
||||
case BRCMU_CHSPEC_D11AC_BW_20:
|
||||
ch->bw = BRCMU_CHAN_BW_20;
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11AC_BW_40:
|
||||
ch->bw = BRCMU_CHAN_BW_40;
|
||||
val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
|
||||
if (val == BRCMU_CHSPEC_D11AC_SB_L) {
|
||||
ch->sb = BRCMU_CHAN_SB_L;
|
||||
ch->chnum -= CH_10MHZ_APART;
|
||||
} else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
|
||||
ch->sb = BRCMU_CHAN_SB_U;
|
||||
ch->chnum += CH_10MHZ_APART;
|
||||
} else {
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11AC_BW_80:
|
||||
ch->bw = BRCMU_CHAN_BW_80;
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11AC_BW_8080:
|
||||
case BRCMU_CHSPEC_D11AC_BW_160:
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
|
||||
case BRCMU_CHSPEC_D11AC_BND_5G:
|
||||
ch->band = BRCMU_CHAN_BAND_5G;
|
||||
break;
|
||||
case BRCMU_CHSPEC_D11AC_BND_2G:
|
||||
ch->band = BRCMU_CHAN_BAND_2G;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
|
||||
{
|
||||
if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
|
||||
d11inf->encchspec = brcmu_d11n_encchspec;
|
||||
d11inf->decchspec = brcmu_d11n_decchspec;
|
||||
} else {
|
||||
d11inf->encchspec = brcmu_d11ac_encchspec;
|
||||
d11inf->decchspec = brcmu_d11ac_decchspec;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_d11_attach);
|
@ -45,17 +45,9 @@ void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
|
||||
{
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
WARN_ON(skb->next);
|
||||
if (skb->destructor)
|
||||
/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
|
||||
* destructor exists
|
||||
*/
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
/* can free immediately (even in_irq()) if destructor
|
||||
* does not exist
|
||||
*/
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
/* Chipcommon Core Chip IDs */
|
||||
#define BCM4313_CHIP_ID 0x4313
|
||||
#define BCM43143_CHIP_ID 43143
|
||||
#define BCM43224_CHIP_ID 43224
|
||||
#define BCM43225_CHIP_ID 43225
|
||||
#define BCM43235_CHIP_ID 43235
|
||||
@ -39,5 +40,6 @@
|
||||
#define BCM4330_CHIP_ID 0x4330
|
||||
#define BCM4331_CHIP_ID 0x4331
|
||||
#define BCM4334_CHIP_ID 0x4334
|
||||
#define BCM4335_CHIP_ID 0x4335
|
||||
|
||||
#endif /* _BRCM_HW_IDS_H_ */
|
||||
|
145
drivers/net/wireless/brcm80211/include/brcmu_d11.h
Normal file
145
drivers/net/wireless/brcm80211/include/brcmu_d11.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _BRCMU_D11_H_
|
||||
#define _BRCMU_D11_H_
|
||||
|
||||
/* d11 io type */
|
||||
#define BRCMU_D11N_IOTYPE 1
|
||||
#define BRCMU_D11AC_IOTYPE 2
|
||||
|
||||
/* A chanspec (channel specification) holds the channel number, band,
|
||||
* bandwidth and control sideband
|
||||
*/
|
||||
|
||||
/* chanspec binary format */
|
||||
|
||||
#define BRCMU_CHSPEC_INVALID 255
|
||||
/* bit 0~7 channel number
|
||||
* for 80+80 channels: bit 0~3 low channel id, bit 4~7 high channel id
|
||||
*/
|
||||
#define BRCMU_CHSPEC_CH_MASK 0x00ff
|
||||
#define BRCMU_CHSPEC_CH_SHIFT 0
|
||||
#define BRCMU_CHSPEC_CHL_MASK 0x000f
|
||||
#define BRCMU_CHSPEC_CHL_SHIFT 0
|
||||
#define BRCMU_CHSPEC_CHH_MASK 0x00f0
|
||||
#define BRCMU_CHSPEC_CHH_SHIFT 4
|
||||
|
||||
/* bit 8~16 for dot 11n IO types
|
||||
* bit 8~9 sideband
|
||||
* bit 10~11 bandwidth
|
||||
* bit 12~13 spectral band
|
||||
* bit 14~15 not used
|
||||
*/
|
||||
#define BRCMU_CHSPEC_D11N_SB_MASK 0x0300
|
||||
#define BRCMU_CHSPEC_D11N_SB_SHIFT 8
|
||||
#define BRCMU_CHSPEC_D11N_SB_L 0x0100 /* control lower */
|
||||
#define BRCMU_CHSPEC_D11N_SB_U 0x0200 /* control upper */
|
||||
#define BRCMU_CHSPEC_D11N_SB_N 0x0300 /* none */
|
||||
#define BRCMU_CHSPEC_D11N_BW_MASK 0x0c00
|
||||
#define BRCMU_CHSPEC_D11N_BW_SHIFT 10
|
||||
#define BRCMU_CHSPEC_D11N_BW_10 0x0400
|
||||
#define BRCMU_CHSPEC_D11N_BW_20 0x0800
|
||||
#define BRCMU_CHSPEC_D11N_BW_40 0x0c00
|
||||
#define BRCMU_CHSPEC_D11N_BND_MASK 0x3000
|
||||
#define BRCMU_CHSPEC_D11N_BND_SHIFT 12
|
||||
#define BRCMU_CHSPEC_D11N_BND_5G 0x1000
|
||||
#define BRCMU_CHSPEC_D11N_BND_2G 0x2000
|
||||
|
||||
/* bit 8~16 for dot 11ac IO types
|
||||
* bit 8~10 sideband
|
||||
* bit 11~13 bandwidth
|
||||
* bit 14~15 spectral band
|
||||
*/
|
||||
#define BRCMU_CHSPEC_D11AC_SB_MASK 0x0700
|
||||
#define BRCMU_CHSPEC_D11AC_SB_SHIFT 8
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LLL 0x0000
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LLU 0x0100
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LUL 0x0200
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LUU 0x0300
|
||||
#define BRCMU_CHSPEC_D11AC_SB_ULL 0x0400
|
||||
#define BRCMU_CHSPEC_D11AC_SB_ULU 0x0500
|
||||
#define BRCMU_CHSPEC_D11AC_SB_UUL 0x0600
|
||||
#define BRCMU_CHSPEC_D11AC_SB_UUU 0x0700
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LL BRCMU_CHSPEC_D11AC_SB_LLL
|
||||
#define BRCMU_CHSPEC_D11AC_SB_LU BRCMU_CHSPEC_D11AC_SB_LLU
|
||||
#define BRCMU_CHSPEC_D11AC_SB_UL BRCMU_CHSPEC_D11AC_SB_LUL
|
||||
#define BRCMU_CHSPEC_D11AC_SB_UU BRCMU_CHSPEC_D11AC_SB_LUU
|
||||
#define BRCMU_CHSPEC_D11AC_SB_L BRCMU_CHSPEC_D11AC_SB_LLL
|
||||
#define BRCMU_CHSPEC_D11AC_SB_U BRCMU_CHSPEC_D11AC_SB_LLU
|
||||
#define BRCMU_CHSPEC_D11AC_BW_MASK 0x3800
|
||||
#define BRCMU_CHSPEC_D11AC_BW_SHIFT 11
|
||||
#define BRCMU_CHSPEC_D11AC_BW_5 0x0000
|
||||
#define BRCMU_CHSPEC_D11AC_BW_10 0x0800
|
||||
#define BRCMU_CHSPEC_D11AC_BW_20 0x1000
|
||||
#define BRCMU_CHSPEC_D11AC_BW_40 0x1800
|
||||
#define BRCMU_CHSPEC_D11AC_BW_80 0x2000
|
||||
#define BRCMU_CHSPEC_D11AC_BW_160 0x2800
|
||||
#define BRCMU_CHSPEC_D11AC_BW_8080 0x3000
|
||||
#define BRCMU_CHSPEC_D11AC_BND_MASK 0xc000
|
||||
#define BRCMU_CHSPEC_D11AC_BND_SHIFT 14
|
||||
#define BRCMU_CHSPEC_D11AC_BND_2G 0x0000
|
||||
#define BRCMU_CHSPEC_D11AC_BND_3G 0x4000
|
||||
#define BRCMU_CHSPEC_D11AC_BND_4G 0x8000
|
||||
#define BRCMU_CHSPEC_D11AC_BND_5G 0xc000
|
||||
|
||||
#define BRCMU_CHAN_BAND_2G 0
|
||||
#define BRCMU_CHAN_BAND_5G 1
|
||||
|
||||
enum brcmu_chan_bw {
|
||||
BRCMU_CHAN_BW_20,
|
||||
BRCMU_CHAN_BW_40,
|
||||
BRCMU_CHAN_BW_80,
|
||||
BRCMU_CHAN_BW_80P80,
|
||||
BRCMU_CHAN_BW_160,
|
||||
};
|
||||
|
||||
enum brcmu_chan_sb {
|
||||
BRCMU_CHAN_SB_NONE = 0,
|
||||
BRCMU_CHAN_SB_L,
|
||||
BRCMU_CHAN_SB_U,
|
||||
BRCMU_CHAN_SB_LL,
|
||||
BRCMU_CHAN_SB_LU,
|
||||
BRCMU_CHAN_SB_UL,
|
||||
BRCMU_CHAN_SB_UU,
|
||||
BRCMU_CHAN_SB_LLL,
|
||||
BRCMU_CHAN_SB_LLU,
|
||||
BRCMU_CHAN_SB_LUL,
|
||||
BRCMU_CHAN_SB_LUU,
|
||||
BRCMU_CHAN_SB_ULL,
|
||||
BRCMU_CHAN_SB_ULU,
|
||||
BRCMU_CHAN_SB_UUL,
|
||||
BRCMU_CHAN_SB_UUU,
|
||||
};
|
||||
|
||||
struct brcmu_chan {
|
||||
u16 chspec;
|
||||
u8 chnum;
|
||||
u8 band;
|
||||
enum brcmu_chan_bw bw;
|
||||
enum brcmu_chan_sb sb;
|
||||
};
|
||||
|
||||
struct brcmu_d11inf {
|
||||
u8 io_type;
|
||||
|
||||
void (*encchspec)(struct brcmu_chan *ch);
|
||||
void (*decchspec)(struct brcmu_chan *ch);
|
||||
};
|
||||
|
||||
extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
|
||||
|
||||
#endif /* _BRCMU_CHANNELS_H_ */
|
@ -205,7 +205,7 @@ struct chipcregs {
|
||||
u32 res_req_timer_sel;
|
||||
u32 res_req_timer;
|
||||
u32 res_req_mask;
|
||||
u32 PAD;
|
||||
u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */
|
||||
u32 chipcontrol_addr; /* 0x650 */
|
||||
u32 chipcontrol_data; /* 0x654 */
|
||||
u32 regcontrol_addr;
|
||||
@ -214,7 +214,11 @@ struct chipcregs {
|
||||
u32 pllcontrol_data;
|
||||
u32 pmustrapopt; /* 0x668, corerev >= 28 */
|
||||
u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
|
||||
u32 PAD[100];
|
||||
u32 retention_ctl; /* 0x670, pmurev >= 15 */
|
||||
u32 PAD[3];
|
||||
u32 retention_grpidx; /* 0x680 */
|
||||
u32 retention_grpctl; /* 0x684 */
|
||||
u32 PAD[94];
|
||||
u16 sromotp[768];
|
||||
};
|
||||
|
||||
@ -276,6 +280,12 @@ struct chipcregs {
|
||||
#define PCAP5_VC_SHIFT 22
|
||||
#define PCAP5_CC_MASK 0xf8000000
|
||||
#define PCAP5_CC_SHIFT 27
|
||||
/* pmucapabilites_ext PMU rev >= 15 */
|
||||
#define PCAPEXT_SR_SUPPORTED_MASK (1 << 1)
|
||||
/* retention_ctl PMU rev >= 15 */
|
||||
#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26)
|
||||
#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27)
|
||||
|
||||
|
||||
/*
|
||||
* Maximum delay for the PMU state transition in us.
|
||||
|
@ -4167,17 +4167,11 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf)
|
||||
static ssize_t store_debug_level(struct device_driver *d,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
char *p = (char *)buf;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
|
||||
p++;
|
||||
if (p[0] == 'x' || p[0] == 'X')
|
||||
p++;
|
||||
val = simple_strtoul(p, &p, 16);
|
||||
} else
|
||||
val = simple_strtoul(p, &p, 10);
|
||||
if (p == buf)
|
||||
ret = kstrtou32(buf, 0, &val);
|
||||
if (ret)
|
||||
IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf);
|
||||
else
|
||||
ipw2100_debug_level = val;
|
||||
@ -4238,27 +4232,15 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
|
||||
{
|
||||
struct ipw2100_priv *priv = dev_get_drvdata(d);
|
||||
struct net_device *dev = priv->net_dev;
|
||||
char buffer[] = "00000000";
|
||||
unsigned long len =
|
||||
(sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
|
||||
unsigned long val;
|
||||
char *p = buffer;
|
||||
int ret;
|
||||
|
||||
(void)dev; /* kill unused-var warning for debug-only code */
|
||||
|
||||
IPW_DEBUG_INFO("enter\n");
|
||||
|
||||
strncpy(buffer, buf, len);
|
||||
buffer[len] = 0;
|
||||
|
||||
if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
|
||||
p++;
|
||||
if (p[0] == 'x' || p[0] == 'X')
|
||||
p++;
|
||||
val = simple_strtoul(p, &p, 16);
|
||||
} else
|
||||
val = simple_strtoul(p, &p, 10);
|
||||
if (p == buffer) {
|
||||
ret = kstrtoul(buf, 0, &val);
|
||||
if (ret) {
|
||||
IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name);
|
||||
} else {
|
||||
priv->ieee->scan_age = val;
|
||||
@ -4266,7 +4248,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
IPW_DEBUG_INFO("exit\n");
|
||||
return len;
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
|
||||
|
@ -347,7 +347,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
|
||||
|
||||
psta = (struct il3945_sta_priv *)sta->drv_priv;
|
||||
rs_sta = &psta->rs_sta;
|
||||
sband = hw->wiphy->bands[conf->channel->band];
|
||||
sband = hw->wiphy->bands[conf->chandef.chan->band];
|
||||
|
||||
rs_sta->il = il;
|
||||
|
||||
|
@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct il_priv *il = hw->priv;
|
||||
const struct il_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = ch_switch->channel;
|
||||
struct ieee80211_channel *channel = ch_switch->chandef.chan;
|
||||
struct il_ht_config *ht_conf = &il->current_ht_config;
|
||||
u16 ch;
|
||||
|
||||
@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
il->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
il->ht.enabled = conf_is_ht(conf);
|
||||
if (il->ht.enabled) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
il->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
il->ht.is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
il->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
il->ht.is_40mhz = true;
|
||||
} else {
|
||||
il->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
il->ht.is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
case NL80211_CHAN_HT20:
|
||||
il->ht.is_40mhz = false;
|
||||
il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
break;
|
||||
case NL80211_CHAN_HT40MINUS:
|
||||
il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
il->ht.is_40mhz = true;
|
||||
break;
|
||||
case NL80211_CHAN_HT40PLUS:
|
||||
il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
il->ht.is_40mhz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((le16_to_cpu(il->staging.channel) != ch))
|
||||
il->staging.flags = 0;
|
||||
|
@ -2300,7 +2300,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
|
||||
|
||||
sta_priv = (struct il_station_priv *)sta->drv_priv;
|
||||
lq_sta = &sta_priv->lq_sta;
|
||||
sband = hw->wiphy->bands[conf->channel->band];
|
||||
sband = hw->wiphy->bands[conf->chandef.chan->band];
|
||||
|
||||
lq_sta->lq.sta_id = sta_id;
|
||||
|
||||
|
@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,
|
||||
|
||||
cmd.band = band;
|
||||
cmd.expect_beacon = 0;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
ch = ch_switch->chandef.chan->hw_value;
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = il->staging.flags;
|
||||
cmd.rxon_filter_flags = il->staging.filter_flags;
|
||||
|
@ -4971,7 +4971,7 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct il_priv *il = hw->priv;
|
||||
const struct il_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = conf->channel;
|
||||
struct ieee80211_channel *channel = conf->chandef.chan;
|
||||
struct il_ht_config *ht_conf = &il->current_ht_config;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
|
@ -73,6 +73,8 @@
|
||||
/* AUX (TX during scan dwell) queue */
|
||||
#define IWL_AUX_QUEUE 10
|
||||
|
||||
#define IWL_INVALID_STATION 255
|
||||
|
||||
/* device operations */
|
||||
extern struct iwl_lib_ops iwl1000_lib;
|
||||
extern struct iwl_lib_ops iwl2000_lib;
|
||||
@ -176,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
|
||||
/* lib */
|
||||
int iwlagn_send_tx_power(struct iwl_priv *priv);
|
||||
void iwlagn_temperature(struct iwl_priv *priv);
|
||||
int iwlagn_txfifo_flush(struct iwl_priv *priv);
|
||||
int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk);
|
||||
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv);
|
||||
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
|
||||
int iwl_send_statistics_request(struct iwl_priv *priv,
|
||||
@ -210,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u8 buf_size);
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||
};
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
ch = ch_switch->chandef.chan->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
ctx->active.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
cmd.expect_beacon =
|
||||
ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
hcmd.data[0] = cmd;
|
||||
|
||||
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
ch = ch_switch->chandef.chan->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||
ctx->active.channel, ch);
|
||||
cmd->channel = cpu_to_le16(ch);
|
||||
@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd->switch_time);
|
||||
cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
cmd->expect_beacon =
|
||||
ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
err = iwl_dvm_send_cmd(priv, &hcmd);
|
||||
kfree(cmd);
|
||||
|
@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
* 1. acquire mutex before calling
|
||||
* 2. make sure rf is on and not in exit state
|
||||
*/
|
||||
int iwlagn_txfifo_flush(struct iwl_priv *priv)
|
||||
int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
|
||||
{
|
||||
struct iwl_txfifo_flush_cmd flush_cmd;
|
||||
struct iwl_host_cmd cmd = {
|
||||
@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv)
|
||||
if (priv->nvm_data->sku_cap_11n_enable)
|
||||
flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
|
||||
|
||||
if (scd_q_msk)
|
||||
flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
|
||||
flush_cmd.queue_control);
|
||||
flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
|
||||
@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
|
||||
{
|
||||
mutex_lock(&priv->mutex);
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
if (iwlagn_txfifo_flush(priv)) {
|
||||
if (iwlagn_txfifo_flush(priv, 0)) {
|
||||
IWL_ERR(priv, "flush request fail\n");
|
||||
goto done;
|
||||
}
|
||||
@ -1084,7 +1087,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
|
||||
struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
|
||||
struct iwlagn_d3_config_cmd d3_cfg_cmd = {};
|
||||
struct iwlagn_d3_config_cmd d3_cfg_cmd = {
|
||||
/*
|
||||
* Program the minimum sleep time to 10 seconds, as many
|
||||
* platforms have issues processing a wakeup signal while
|
||||
* still being in the process of suspending.
|
||||
*/
|
||||
.min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
|
||||
};
|
||||
struct wowlan_key_data key_data = {
|
||||
.ctx = ctx,
|
||||
.bssid = ctx->active.bssid_addr,
|
||||
|
@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_HT(priv, "start Tx\n");
|
||||
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
IWL_DEBUG_HT(priv, "Flush Tx\n");
|
||||
ret = iwlagn_tx_agg_flush(priv, vif, sta, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
IWL_DEBUG_HT(priv, "stop Tx\n");
|
||||
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
|
||||
if ((ret == 0) && (priv->agg_tids_count > 0)) {
|
||||
@ -967,7 +970,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = ch_switch->channel;
|
||||
struct ieee80211_channel *channel = ch_switch->chandef.chan;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
/*
|
||||
* MULTI-FIXME
|
||||
@ -1005,11 +1008,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
ctx->ht.enabled = conf_is_ht(conf);
|
||||
if (ctx->ht.enabled)
|
||||
iwlagn_config_ht40(conf, ctx);
|
||||
else
|
||||
switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
case NL80211_CHAN_HT20:
|
||||
ctx->ht.is_40mhz = false;
|
||||
ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
break;
|
||||
case NL80211_CHAN_HT40MINUS:
|
||||
ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ctx->ht.is_40mhz = true;
|
||||
break;
|
||||
case NL80211_CHAN_HT40PLUS:
|
||||
ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ctx->ht.is_40mhz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((le16_to_cpu(ctx->staging.channel) != ch))
|
||||
ctx->staging.flags = 0;
|
||||
@ -1122,7 +1135,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
*/
|
||||
if (drop) {
|
||||
IWL_DEBUG_MAC80211(priv, "send flush command\n");
|
||||
if (iwlagn_txfifo_flush(priv)) {
|
||||
if (iwlagn_txfifo_flush(priv, 0)) {
|
||||
IWL_ERR(priv, "flush request fail\n");
|
||||
goto done;
|
||||
}
|
||||
|
@ -2831,7 +2831,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
|
||||
|
||||
sta_priv = (struct iwl_station_priv *) sta->drv_priv;
|
||||
lq_sta = &sta_priv->lq_sta;
|
||||
sband = hw->wiphy->bands[conf->channel->band];
|
||||
sband = hw->wiphy->bands[conf->chandef.chan->band];
|
||||
|
||||
|
||||
lq_sta->lq.sta_id = sta_id;
|
||||
|
@ -78,8 +78,9 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
#endif
|
||||
|
||||
ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value);
|
||||
priv->band = priv->hw->conf.channel->band;
|
||||
ctx->staging.channel =
|
||||
cpu_to_le16(priv->hw->conf.chandef.chan->hw_value);
|
||||
priv->band = priv->hw->conf.chandef.chan->band;
|
||||
|
||||
iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
|
||||
|
||||
@ -951,7 +952,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
|
||||
unsigned long basic = ctx->vif->bss_conf.basic_rates;
|
||||
int i;
|
||||
|
||||
sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
|
||||
sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
|
||||
|
||||
for_each_set_bit(i, &basic, BITS_PER_LONG) {
|
||||
int hw = sband->bitrates[i].hw_value;
|
||||
@ -1159,7 +1160,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
}
|
||||
|
||||
void iwlagn_config_ht40(struct ieee80211_conf *conf,
|
||||
struct iwl_rxon_context *ctx)
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ctx->ht.extension_chan_offset =
|
||||
@ -1181,7 +1182,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = conf->channel;
|
||||
struct ieee80211_channel *channel = conf->chandef.chan;
|
||||
int ret = 0;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed);
|
||||
|
@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct iwl_tid_data *tid_data;
|
||||
enum iwl_agg_state agg_state;
|
||||
int sta_id, txq_id;
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
/*
|
||||
* First set the agg state to OFF to avoid calling
|
||||
* ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty.
|
||||
*/
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
tid_data = &priv->tid_data[sta_id][tid];
|
||||
txq_id = tid_data->agg.txq_id;
|
||||
agg_state = tid_data->agg.state;
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Flush AGG: sta %d tid %d q %d state %d\n",
|
||||
sta_id, tid, txq_id, tid_data->agg.state);
|
||||
|
||||
tid_data->agg.state = IWL_AGG_OFF;
|
||||
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
if (iwlagn_txfifo_flush(priv, BIT(txq_id)))
|
||||
IWL_ERR(priv, "Couldn't flush the AGG queue\n");
|
||||
|
||||
if (test_bit(txq_id, priv->agg_q_alloc)) {
|
||||
/*
|
||||
* If the transport didn't know that we wanted to start
|
||||
* agreggation, don't tell it that we want to stop them.
|
||||
* This can happen when we don't get the addBA response on
|
||||
* time, or we hadn't time to drain the AC queues.
|
||||
*/
|
||||
if (agg_state == IWL_AGG_ON)
|
||||
iwl_trans_txq_disable(priv->trans, txq_id);
|
||||
else
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
|
||||
agg_state);
|
||||
iwlagn_dealloc_agg_txq(priv, txq_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u8 buf_size)
|
||||
{
|
||||
|
@ -912,8 +912,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
}
|
||||
}
|
||||
|
||||
IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
|
||||
|
||||
/*
|
||||
* In mvm uCode there is no difference between data and instructions
|
||||
* sections.
|
||||
@ -970,6 +968,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
else
|
||||
op = &iwlwifi_opmode_table[DVM_OP_MODE];
|
||||
|
||||
IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
|
||||
drv->fw.fw_version, op->name);
|
||||
|
||||
/* add this device to the list of devices using this op_mode */
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
||||
@ -997,8 +998,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
* else from proceeding if the module fails to load
|
||||
* or hangs loading.
|
||||
*/
|
||||
if (load_module)
|
||||
request_module("%s", op->name);
|
||||
if (load_module) {
|
||||
err = request_module("%s", op->name);
|
||||
if (err)
|
||||
IWL_ERR(drv,
|
||||
"failed to load module %s (error %d), is dynamic loading enabled?\n",
|
||||
op->name, err);
|
||||
}
|
||||
return;
|
||||
|
||||
try_again:
|
||||
|
@ -305,7 +305,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
|
||||
* currently supports
|
||||
*/
|
||||
#define IWL_MAX_HW_QUEUES 32
|
||||
#define IWL_INVALID_STATION 255
|
||||
#define IWL_MAX_TID_COUNT 8
|
||||
#define IWL_FRAME_LIMIT 64
|
||||
|
||||
@ -682,7 +681,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
|
||||
static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
|
||||
int fifo)
|
||||
{
|
||||
iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
|
||||
iwl_trans_txq_enable(trans, queue, fifo, -1,
|
||||
IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user