mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 09:30:53 +07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
bfe34ebbaa
@ -64,6 +64,32 @@ void rndis_status(struct usbnet *dev, struct urb *urb)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rndis_status);
|
||||
|
||||
/*
|
||||
* RNDIS indicate messages.
|
||||
*/
|
||||
static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
|
||||
int buflen)
|
||||
{
|
||||
struct cdc_state *info = (void *)&dev->data;
|
||||
struct device *udev = &info->control->dev;
|
||||
|
||||
if (dev->driver_info->indication) {
|
||||
dev->driver_info->indication(dev, msg, buflen);
|
||||
} else {
|
||||
switch (msg->status) {
|
||||
case RNDIS_STATUS_MEDIA_CONNECT:
|
||||
dev_info(udev, "rndis media connect\n");
|
||||
break;
|
||||
case RNDIS_STATUS_MEDIA_DISCONNECT:
|
||||
dev_info(udev, "rndis media disconnect\n");
|
||||
break;
|
||||
default:
|
||||
dev_info(udev, "rndis indication: 0x%08x\n",
|
||||
le32_to_cpu(msg->status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC done RNDIS-style. Caller guarantees:
|
||||
* - message is properly byteswapped
|
||||
@ -143,27 +169,9 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
|
||||
request_id, xid);
|
||||
/* then likely retry */
|
||||
} else switch (buf->msg_type) {
|
||||
case RNDIS_MSG_INDICATE: { /* fault/event */
|
||||
struct rndis_indicate *msg = (void *)buf;
|
||||
int state = 0;
|
||||
case RNDIS_MSG_INDICATE: /* fault/event */
|
||||
rndis_msg_indicate(dev, (void *)buf, buflen);
|
||||
|
||||
switch (msg->status) {
|
||||
case RNDIS_STATUS_MEDIA_CONNECT:
|
||||
state = 1;
|
||||
case RNDIS_STATUS_MEDIA_DISCONNECT:
|
||||
dev_info(&info->control->dev,
|
||||
"rndis media %sconnect\n",
|
||||
!state?"dis":"");
|
||||
if (dev->driver_info->link_change)
|
||||
dev->driver_info->link_change(
|
||||
dev, state);
|
||||
break;
|
||||
default:
|
||||
dev_info(&info->control->dev,
|
||||
"rndis indication: 0x%08x\n",
|
||||
le32_to_cpu(msg->status));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RNDIS_MSG_KEEPALIVE: { /* ping */
|
||||
struct rndis_keepalive_c *msg = (void *)buf;
|
||||
|
@ -601,21 +601,25 @@ int usbnet_stop (struct net_device *net)
|
||||
info->description);
|
||||
}
|
||||
|
||||
// ensure there are no more active urbs
|
||||
if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
|
||||
/* ensure there are no more active urbs */
|
||||
add_wait_queue(&unlink_wakeup, &wait);
|
||||
dev->wait = &unlink_wakeup;
|
||||
temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
|
||||
temp = unlink_urbs(dev, &dev->txq) +
|
||||
unlink_urbs(dev, &dev->rxq);
|
||||
|
||||
// maybe wait for deletions to finish.
|
||||
/* maybe wait for deletions to finish. */
|
||||
while (!skb_queue_empty(&dev->rxq)
|
||||
&& !skb_queue_empty(&dev->txq)
|
||||
&& !skb_queue_empty(&dev->done)) {
|
||||
msleep(UNLINK_TIMEOUT_MS);
|
||||
if (netif_msg_ifdown(dev))
|
||||
devdbg (dev, "waited for %d urb completions", temp);
|
||||
devdbg(dev, "waited for %d urb completions",
|
||||
temp);
|
||||
}
|
||||
dev->wait = NULL;
|
||||
remove_wait_queue(&unlink_wakeup, &wait);
|
||||
}
|
||||
|
||||
usb_kill_urb(dev->interrupt);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
menu "Wireless LAN"
|
||||
depends on !S390
|
||||
|
||||
config WLAN_PRE80211
|
||||
menuconfig WLAN_PRE80211
|
||||
bool "Wireless LAN (pre-802.11)"
|
||||
depends on NETDEVICES
|
||||
---help---
|
||||
@ -101,7 +101,7 @@ config PCMCIA_NETWAVE
|
||||
called netwave_cs. If unsure, say N.
|
||||
|
||||
|
||||
config WLAN_80211
|
||||
menuconfig WLAN_80211
|
||||
bool "Wireless LAN (IEEE 802.11)"
|
||||
depends on NETDEVICES
|
||||
---help---
|
||||
|
@ -1773,6 +1773,9 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
|
||||
|
||||
at76_dbg(DBG_MAC80211, "%s()", __func__);
|
||||
|
||||
cancel_delayed_work(&priv->dwork_hw_scan);
|
||||
cancel_work_sync(&priv->work_set_promisc);
|
||||
|
||||
mutex_lock(&priv->mtx);
|
||||
|
||||
if (!priv->device_unplugged) {
|
||||
@ -1872,7 +1875,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)
|
||||
/* FIXME: add maximum time for scan to complete */
|
||||
|
||||
if (ret != CMD_STATUS_COMPLETE) {
|
||||
queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
|
||||
SCAN_POLL_INTERVAL);
|
||||
mutex_unlock(&priv->mtx);
|
||||
return;
|
||||
@ -1934,7 +1937,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
|
||||
SCAN_POLL_INTERVAL);
|
||||
|
||||
exit:
|
||||
@ -2024,7 +2027,7 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
|
||||
} else
|
||||
return;
|
||||
|
||||
queue_work(hw->workqueue, &priv->work_set_promisc);
|
||||
ieee80211_queue_work(hw, &priv->work_set_promisc);
|
||||
}
|
||||
|
||||
static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
@ -2295,11 +2298,8 @@ static void at76_delete_device(struct at76_priv *priv)
|
||||
|
||||
tasklet_kill(&priv->rx_tasklet);
|
||||
|
||||
if (priv->mac80211_registered) {
|
||||
cancel_delayed_work(&priv->dwork_hw_scan);
|
||||
flush_workqueue(priv->hw->workqueue);
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_unregister_hw(priv->hw);
|
||||
}
|
||||
|
||||
if (priv->tx_urb) {
|
||||
usb_kill_urb(priv->tx_urb);
|
||||
|
@ -1,9 +1,24 @@
|
||||
config ATH_COMMON
|
||||
menuconfig ATH_COMMON
|
||||
tristate "Atheros Wireless Cards"
|
||||
depends on WLAN_80211
|
||||
depends on ATH5K || ATH9K || AR9170_USB
|
||||
depends on CFG80211
|
||||
---help---
|
||||
This will enable the support for the Atheros wireless drivers.
|
||||
ath5k, ath9k and ar9170 drivers share some common code, this option
|
||||
enables the common ath.ko module which currently shares just common
|
||||
regulatory EEPROM helpers but will likely be extended later to share
|
||||
more between modules.
|
||||
|
||||
For more information and documentation on this module you can visit:
|
||||
|
||||
http://wireless.kernel.org/en/users/Drivers/ath
|
||||
|
||||
For information on all Atheros wireless drivers visit:
|
||||
|
||||
http://wireless.kernel.org/en/users/Drivers/Atheros
|
||||
|
||||
if ATH_COMMON
|
||||
source "drivers/net/wireless/ath/ath5k/Kconfig"
|
||||
source "drivers/net/wireless/ath/ath9k/Kconfig"
|
||||
source "drivers/net/wireless/ath/ar9170/Kconfig"
|
||||
|
||||
endif
|
||||
|
@ -1,13 +1,13 @@
|
||||
config AR9170_USB
|
||||
tristate "Atheros AR9170 802.11n USB support"
|
||||
depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
|
||||
depends on USB && MAC80211 && WLAN_80211
|
||||
select FW_LOADER
|
||||
select ATH_COMMON
|
||||
help
|
||||
This is a driver for the Atheros "otus" 802.11n USB devices.
|
||||
|
||||
These devices require additional firmware (2 files).
|
||||
For now, these files can be downloaded from here:
|
||||
|
||||
http://wireless.kernel.org/en/users/Drivers/ar9170
|
||||
|
||||
If you choose to build a module, it'll be called ar9170usb.
|
||||
|
@ -90,8 +90,11 @@ static void ar9170_update_leds(struct work_struct *work)
|
||||
ar9170_set_leds_state(ar, led_val);
|
||||
mutex_unlock(&ar->mutex);
|
||||
|
||||
if (rerun)
|
||||
queue_delayed_work(ar->hw->workqueue, &ar->led_work,
|
||||
if (!rerun)
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(ar->hw,
|
||||
&ar->led_work,
|
||||
msecs_to_jiffies(blink_delay));
|
||||
}
|
||||
|
||||
@ -110,7 +113,7 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
|
||||
}
|
||||
|
||||
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
|
||||
queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
|
||||
ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
|
||||
}
|
||||
|
||||
static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
|
||||
|
@ -595,8 +595,10 @@ static void ar9170_tx_janitor(struct work_struct *work)
|
||||
|
||||
ar9170_tx_fake_ampdu_status(ar);
|
||||
|
||||
if (resched)
|
||||
queue_delayed_work(ar->hw->workqueue,
|
||||
if (!resched)
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(ar->hw,
|
||||
&ar->tx_janitor,
|
||||
msecs_to_jiffies(AR9170_JANITOR_DELAY));
|
||||
}
|
||||
@ -648,7 +650,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
* pre-TBTT event
|
||||
*/
|
||||
if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
|
||||
queue_work(ar->hw->workqueue, &ar->beacon_work);
|
||||
ieee80211_queue_work(ar->hw, &ar->beacon_work);
|
||||
break;
|
||||
|
||||
case 0xc2:
|
||||
@ -1290,14 +1292,13 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
|
||||
if (IS_STARTED(ar))
|
||||
ar->state = AR9170_IDLE;
|
||||
|
||||
flush_workqueue(ar->hw->workqueue);
|
||||
|
||||
cancel_delayed_work_sync(&ar->tx_janitor);
|
||||
#ifdef CONFIG_AR9170_LEDS
|
||||
cancel_delayed_work_sync(&ar->led_work);
|
||||
#endif
|
||||
cancel_work_sync(&ar->filter_config_work);
|
||||
cancel_work_sync(&ar->beacon_work);
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
|
||||
if (IS_ACCEPTING_CMD(ar)) {
|
||||
@ -1826,8 +1827,10 @@ static void ar9170_tx(struct ar9170 *ar)
|
||||
}
|
||||
}
|
||||
|
||||
if (schedule_garbagecollector)
|
||||
queue_delayed_work(ar->hw->workqueue,
|
||||
if (!schedule_garbagecollector)
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(ar->hw,
|
||||
&ar->tx_janitor,
|
||||
msecs_to_jiffies(AR9170_JANITOR_DELAY));
|
||||
}
|
||||
@ -2158,7 +2161,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (likely(IS_STARTED(ar)))
|
||||
queue_work(ar->hw->workqueue, &ar->filter_config_work);
|
||||
ieee80211_queue_work(ar->hw, &ar->filter_config_work);
|
||||
}
|
||||
|
||||
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
@ -2416,7 +2419,7 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (IS_STARTED(ar) && ar->filter_changed)
|
||||
queue_work(ar->hw->workqueue, &ar->filter_config_work);
|
||||
ieee80211_queue_work(ar->hw, &ar->filter_config_work);
|
||||
}
|
||||
|
||||
static int ar9170_get_stats(struct ieee80211_hw *hw,
|
||||
|
@ -1,7 +1,6 @@
|
||||
config ATH5K
|
||||
tristate "Atheros 5xxx wireless cards support"
|
||||
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
|
||||
select ATH_COMMON
|
||||
depends on PCI && MAC80211 && WLAN_80211
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
|
@ -1117,6 +1117,8 @@ ath5k_mode_setup(struct ath5k_softc *sc)
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
u32 rfilt;
|
||||
|
||||
ah->ah_op_mode = sc->opmode;
|
||||
|
||||
/* configure rx filter */
|
||||
rfilt = sc->filter_flags;
|
||||
ath5k_hw_set_rx_filter(ah, rfilt);
|
||||
@ -1998,9 +2000,12 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
||||
static void
|
||||
ath5k_tasklet_tx(unsigned long data)
|
||||
{
|
||||
int i;
|
||||
struct ath5k_softc *sc = (void *)data;
|
||||
|
||||
ath5k_tx_processq(sc, sc->txq);
|
||||
for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
|
||||
if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
|
||||
ath5k_tx_processq(sc, &sc->txqs[i]);
|
||||
}
|
||||
|
||||
|
||||
@ -2768,6 +2773,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
|
||||
ath5k_mode_setup(sc);
|
||||
|
||||
ret = 0;
|
||||
end:
|
||||
|
@ -1,7 +1,6 @@
|
||||
config ATH9K
|
||||
tristate "Atheros 802.11n wireless cards support"
|
||||
depends on PCI && MAC80211 && WLAN_80211
|
||||
select ATH_COMMON
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
|
@ -119,7 +119,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
sc->bus_ops = &ath_ahb_bus_ops;
|
||||
sc->irq = irq;
|
||||
|
||||
ret = ath_attach(AR5416_AR9100_DEVID, sc);
|
||||
ret = ath_init_device(AR5416_AR9100_DEVID, sc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
|
||||
ret = -ENODEV;
|
||||
|
@ -777,7 +777,7 @@ void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_attach(struct ath_hw *ah)
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -822,9 +822,9 @@ void ath9k_hw_ani_attach(struct ath_hw *ah)
|
||||
ah->proc_phyerr |= HAL_PROCESS_ANI;
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_detach(struct ath_hw *ah)
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n");
|
||||
|
||||
if (ah->has_hw_phycounters) {
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
|
@ -132,7 +132,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah,
|
||||
const struct ath9k_node_stats *stats);
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_attach(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_detach(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah);
|
||||
|
||||
#endif /* ANI_H */
|
||||
|
@ -642,7 +642,7 @@ extern struct ieee80211_ops ath9k_ops;
|
||||
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
void ath_cleanup(struct ath_softc *sc);
|
||||
int ath_attach(u16 devid, struct ath_softc *sc);
|
||||
int ath_init_device(u16 devid, struct ath_softc *sc);
|
||||
void ath_detach(struct ath_softc *sc);
|
||||
const char *ath_mac_bb_name(u32 mac_bb_version);
|
||||
const char *ath_rf_name(u16 rf_version);
|
||||
|
@ -753,6 +753,98 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
|
||||
{
|
||||
u32 regVal;
|
||||
unsigned int i;
|
||||
u32 regList [][2] = {
|
||||
{ 0x786c, 0 },
|
||||
{ 0x7854, 0 },
|
||||
{ 0x7820, 0 },
|
||||
{ 0x7824, 0 },
|
||||
{ 0x7868, 0 },
|
||||
{ 0x783c, 0 },
|
||||
{ 0x7838, 0 } ,
|
||||
{ 0x7828, 0 } ,
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
regList[i][1] = REG_READ(ah, regList[i][0]);
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal |= (0x1 << 27);
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
/* 786c,b23,1, pwddac=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
|
||||
/* 7854, b5,1, pdrxtxbb=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
|
||||
/* 7854, b7,1, pdv2i=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
|
||||
/* 7854, b8,1, pddacinterface=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
|
||||
/* 7824,b12,0, offcal=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
|
||||
/* 7838, b1,0, pwddb=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
|
||||
/* 7820,b11,0, enpacal=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
|
||||
/* 7820,b25,1, pdpadrv1=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
|
||||
/* 7820,b24,0, pdpadrv2=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
|
||||
/* 7820,b23,0, pdpaout=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
|
||||
/* 783c,b14-16,7, padrvgn2tab_0=7 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
/*
|
||||
* 7838,b29-31,0, padrvgn1tab_0=0
|
||||
* does not matter since we turn it off
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
|
||||
|
||||
/* Set:
|
||||
* localmode=1,bmode=1,bmoderxtx=1,synthon=1,
|
||||
* txon=1,paon=1,oscon=1,synthon_force=1
|
||||
*/
|
||||
REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
|
||||
udelay(30);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
|
||||
|
||||
/* find off_6_1; */
|
||||
for (i = 6; i >= 0; i--) {
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= (1 << (20 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
udelay(1);
|
||||
//regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1 << (20 + i)));
|
||||
regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
|
||||
<< (20 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
}
|
||||
|
||||
/* Empirical offset correction */
|
||||
#if 0
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
|
||||
#endif
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= 0x1;
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal &= (~(0x1 << 27));
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
REG_WRITE(ah, regList[i][0], regList[i][1]);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
|
||||
{
|
||||
|
||||
@ -869,14 +961,26 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
}
|
||||
}
|
||||
|
||||
/* Do NF cal only at longer intervals */
|
||||
if (longcal) {
|
||||
if (AR_SREV_9285_11_OR_LATER(ah))
|
||||
/* Do periodic PAOffset Cal */
|
||||
if (AR_SREV_9271(ah))
|
||||
ath9k_hw_9271_pa_cal(ah);
|
||||
else if (AR_SREV_9285_11_OR_LATER(ah))
|
||||
ath9k_hw_9285_pa_cal(ah);
|
||||
|
||||
if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
|
||||
ath9k_olc_temp_compensation(ah);
|
||||
|
||||
/* Get the value from the previous NF cal and update history buffer */
|
||||
ath9k_hw_getnf(ah, chan);
|
||||
|
||||
/*
|
||||
* Load the NF from history buffer of the current channel.
|
||||
* NF is slow time-variant, so it is OK to use a historical value.
|
||||
*/
|
||||
ath9k_hw_loadnf(ah, ah->curchan);
|
||||
|
||||
ath9k_hw_start_nfcal(ah);
|
||||
}
|
||||
|
||||
|
@ -1237,6 +1237,10 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
|
||||
}
|
||||
|
||||
/*
|
||||
* Read EEPROM header info and program the device for correct operation
|
||||
* given the channel value.
|
||||
*/
|
||||
static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -1313,38 +1317,110 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
|
||||
if (AR_SREV_9271(ah)) {
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9271_AN_RF2G3_OB_cck,
|
||||
AR9271_AN_RF2G3_OB_cck_S,
|
||||
ob[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9271_AN_RF2G3_OB_psk,
|
||||
AR9271_AN_RF2G3_OB_psk_S,
|
||||
ob[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9271_AN_RF2G3_OB_qam,
|
||||
AR9271_AN_RF2G3_OB_qam_S,
|
||||
ob[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9271_AN_RF2G3_DB_1,
|
||||
AR9271_AN_RF2G3_DB_1_S,
|
||||
db1[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9271_AN_RF2G4_DB_2,
|
||||
AR9271_AN_RF2G4_DB_2_S,
|
||||
db2[0]);
|
||||
} else {
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_0,
|
||||
AR9285_AN_RF2G3_OB_0_S,
|
||||
ob[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_1,
|
||||
AR9285_AN_RF2G3_OB_1_S,
|
||||
ob[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_2,
|
||||
AR9285_AN_RF2G3_OB_2_S,
|
||||
ob[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_3,
|
||||
AR9285_AN_RF2G3_OB_3_S,
|
||||
ob[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_OB_4,
|
||||
AR9285_AN_RF2G3_OB_4_S,
|
||||
ob[4]);
|
||||
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_0,
|
||||
AR9285_AN_RF2G3_DB1_0_S,
|
||||
db1[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_1,
|
||||
AR9285_AN_RF2G3_DB1_1_S,
|
||||
db1[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G3,
|
||||
AR9285_AN_RF2G3_DB1_2,
|
||||
AR9285_AN_RF2G3_DB1_2_S,
|
||||
db1[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB1_3,
|
||||
AR9285_AN_RF2G4_DB1_3_S,
|
||||
db1[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB1_4,
|
||||
AR9285_AN_RF2G4_DB1_4_S, db1[4]);
|
||||
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_0,
|
||||
AR9285_AN_RF2G4_DB2_0_S,
|
||||
db2[0]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_1,
|
||||
AR9285_AN_RF2G4_DB2_1_S,
|
||||
db2[1]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_2,
|
||||
AR9285_AN_RF2G4_DB2_2_S,
|
||||
db2[2]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_3,
|
||||
AR9285_AN_RF2G4_DB2_3_S,
|
||||
db2[3]);
|
||||
ath9k_hw_analog_shift_rmw(ah,
|
||||
AR9285_AN_RF2G4,
|
||||
AR9285_AN_RF2G4_DB2_4,
|
||||
AR9285_AN_RF2G4_DB2_4_S,
|
||||
db2[4]);
|
||||
}
|
||||
|
||||
|
||||
if (AR_SREV_9285_11(ah))
|
||||
@ -2794,7 +2870,7 @@ static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
|
||||
|
||||
static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
struct ar9287_eeprom_t *eep = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
u16 *eep_data;
|
||||
int addr, eep_start_loc = AR9287_EEP_START_LOC;
|
||||
eep_data = (u16 *)eep;
|
||||
@ -2803,7 +2879,7 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
|
||||
"Reading from EEPROM, not flash\n");
|
||||
}
|
||||
|
||||
for (addr = 0; addr < sizeof(struct ar9287_eeprom_t) / sizeof(u16);
|
||||
for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
|
||||
addr++) {
|
||||
if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
@ -2816,12 +2892,11 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
|
||||
}
|
||||
static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
#define SIZE_EEPROM_87 (sizeof(struct ar9287_eeprom_t) / sizeof(u16))
|
||||
u32 sum = 0, el, integer;
|
||||
u16 temp, word, magic, magic2, *eepdata;
|
||||
int i, addr;
|
||||
bool need_swap = false;
|
||||
struct ar9287_eeprom_t *eep = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
if (!ath9k_hw_nvram_read
|
||||
@ -2842,7 +2917,9 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
need_swap = true;
|
||||
eepdata = (u16 *)(&ah->eeprom);
|
||||
|
||||
for (addr = 0; addr < SIZE_EEPROM_87; addr++) {
|
||||
for (addr = 0;
|
||||
addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
|
||||
addr++) {
|
||||
temp = swab16(*eepdata);
|
||||
*eepdata = temp;
|
||||
eepdata++;
|
||||
@ -2862,8 +2939,13 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
else
|
||||
el = ah->eeprom.map9287.baseEepHeader.length;
|
||||
|
||||
if (el > sizeof(struct ar9287_eeprom))
|
||||
el = sizeof(struct ar9287_eeprom) / sizeof(u16);
|
||||
else
|
||||
el = el / sizeof(u16);
|
||||
|
||||
eepdata = (u16 *)(&ah->eeprom);
|
||||
for (i = 0; i < min(el, SIZE_EEPROM_87); i++)
|
||||
for (i = 0; i < el; i++)
|
||||
sum ^= *eepdata++;
|
||||
|
||||
if (need_swap) {
|
||||
@ -2914,13 +2996,12 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#undef SIZE_EEPROM_87
|
||||
}
|
||||
|
||||
static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
|
||||
enum eeprom_param param)
|
||||
{
|
||||
struct ar9287_eeprom_t *eep = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
|
||||
struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
|
||||
u16 ver_minor;
|
||||
@ -3210,7 +3291,7 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
|
||||
u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
|
||||
u32 reg32, regOffset, regChainOffset;
|
||||
int16_t modalIdx, diff = 0;
|
||||
struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
|
||||
xpdMask = pEepData->modalHeader.xpdGain;
|
||||
if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
|
||||
@ -3380,7 +3461,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
|
||||
struct chan_centers centers;
|
||||
int tx_chainmask;
|
||||
u16 twiceMinEdgePower;
|
||||
struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
tx_chainmask = ah->txchainmask;
|
||||
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
@ -3613,7 +3694,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
|
||||
{
|
||||
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
|
||||
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
|
||||
struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
|
||||
int16_t ratesArray[Ar5416RateSize];
|
||||
int16_t txPowerIndexOffset = 0;
|
||||
@ -3776,7 +3857,7 @@ static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah,
|
||||
static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ar9287_eeprom_t *eep = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
|
||||
|
||||
u16 antWrites[AR9287_ANT_16S];
|
||||
@ -3928,7 +4009,7 @@ static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
|
||||
static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ar9287_eeprom_t *eep = &ah->eeprom.map9287;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
|
||||
return pModal->antCtrlCommon & 0xFFFF;
|
||||
}
|
||||
@ -3978,13 +4059,13 @@ static struct eeprom_ops eep_AR9287_ops = {
|
||||
};
|
||||
|
||||
|
||||
int ath9k_hw_eeprom_attach(struct ath_hw *ah)
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah)
|
||||
{
|
||||
int status;
|
||||
if (AR_SREV_9287(ah)) {
|
||||
ah->eep_map = EEP_MAP_AR9287;
|
||||
ah->eep_ops = &eep_AR9287_ops;
|
||||
} else if (AR_SREV_9285(ah)) {
|
||||
} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
|
||||
ah->eep_map = EEP_MAP_4KBITS;
|
||||
ah->eep_ops = &eep_4k_ops;
|
||||
} else {
|
||||
|
@ -600,7 +600,7 @@ struct ar5416_eeprom_4k {
|
||||
u8 padding;
|
||||
} __packed;
|
||||
|
||||
struct ar9287_eeprom_t {
|
||||
struct ar9287_eeprom {
|
||||
struct base_eep_ar9287_header baseEepHeader;
|
||||
u8 custData[AR9287_DATA_SZ];
|
||||
struct modal_eep_ar9287_header modalHeader;
|
||||
@ -665,6 +665,6 @@ struct eeprom_ops {
|
||||
(((_txchainmask >> 2) & 1) + \
|
||||
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
|
||||
|
||||
int ath9k_hw_eeprom_attach(struct ath_hw *ah);
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah);
|
||||
|
||||
#endif /* EEPROM_H */
|
||||
|
@ -388,7 +388,7 @@ static const char *ath9k_hw_devname(u16 devid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ath9k_hw_set_defaults(struct ath_hw *ah)
|
||||
static void ath9k_hw_init_config(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -437,27 +437,14 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
|
||||
ah->config.serialize_regmode = SER_REG_MODE_AUTO;
|
||||
}
|
||||
|
||||
static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
|
||||
int *status)
|
||||
static void ath9k_hw_init_defaults(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw *ah;
|
||||
|
||||
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
|
||||
if (ah == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Cannot allocate memory for state block\n");
|
||||
*status = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ah->ah_sc = sc;
|
||||
ah->hw_version.magic = AR5416_MAGIC;
|
||||
ah->regulatory.country_code = CTRY_DEFAULT;
|
||||
ah->hw_version.devid = devid;
|
||||
ah->hw_version.subvendorid = 0;
|
||||
|
||||
ah->ah_flags = 0;
|
||||
if ((devid == AR5416_AR9100_DEVID))
|
||||
if (ah->hw_version.devid == AR5416_AR9100_DEVID)
|
||||
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
|
||||
if (!AR_SREV_9100(ah))
|
||||
ah->ah_flags = AH_USE_EEPROM;
|
||||
@ -479,8 +466,6 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
|
||||
ah->gbeacon_rate = 0;
|
||||
|
||||
ah->power_mode = ATH9K_PM_UNDEFINED;
|
||||
|
||||
return ah;
|
||||
}
|
||||
|
||||
static int ath9k_hw_rfattach(struct ath_hw *ah)
|
||||
@ -593,7 +578,7 @@ static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
static int ath9k_hw_post_attach(struct ath_hw *ah)
|
||||
static int ath9k_hw_post_init(struct ath_hw *ah)
|
||||
{
|
||||
int ecode;
|
||||
|
||||
@ -604,7 +589,7 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
|
||||
if (ecode != 0)
|
||||
return ecode;
|
||||
|
||||
ecode = ath9k_hw_eeprom_attach(ah);
|
||||
ecode = ath9k_hw_eeprom_init(ah);
|
||||
if (ecode != 0)
|
||||
return ecode;
|
||||
|
||||
@ -617,71 +602,52 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
|
||||
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
ath9k_hw_ani_setup(ah);
|
||||
ath9k_hw_ani_attach(ah);
|
||||
ath9k_hw_ani_init(ah);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
int *status)
|
||||
static bool ath9k_hw_devid_supported(u16 devid)
|
||||
{
|
||||
struct ath_hw *ah;
|
||||
int ecode;
|
||||
u32 i, j;
|
||||
|
||||
ah = ath9k_hw_newstate(devid, sc, status);
|
||||
if (ah == NULL)
|
||||
return NULL;
|
||||
|
||||
ath9k_hw_set_defaults(ah);
|
||||
|
||||
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
|
||||
ecode = -EIO;
|
||||
goto bad;
|
||||
switch (devid) {
|
||||
case AR5416_DEVID_PCI:
|
||||
case AR5416_DEVID_PCIE:
|
||||
case AR5416_AR9100_DEVID:
|
||||
case AR9160_DEVID_PCI:
|
||||
case AR9280_DEVID_PCI:
|
||||
case AR9280_DEVID_PCIE:
|
||||
case AR9285_DEVID_PCIE:
|
||||
case AR5416_DEVID_AR9287_PCI:
|
||||
case AR5416_DEVID_AR9287_PCIE:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
|
||||
ecode = -EIO;
|
||||
goto bad;
|
||||
static bool ath9k_hw_macversion_supported(u32 macversion)
|
||||
{
|
||||
switch (macversion) {
|
||||
case AR_SREV_VERSION_5416_PCI:
|
||||
case AR_SREV_VERSION_5416_PCIE:
|
||||
case AR_SREV_VERSION_9160:
|
||||
case AR_SREV_VERSION_9100:
|
||||
case AR_SREV_VERSION_9280:
|
||||
case AR_SREV_VERSION_9285:
|
||||
case AR_SREV_VERSION_9287:
|
||||
return true;
|
||||
/* Not yet */
|
||||
case AR_SREV_VERSION_9271:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
|
||||
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
|
||||
(AR_SREV_9280(ah) && !ah->is_pciexpress)) {
|
||||
ah->config.serialize_regmode =
|
||||
SER_REG_MODE_ON;
|
||||
} else {
|
||||
ah->config.serialize_regmode =
|
||||
SER_REG_MODE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
|
||||
ah->config.serialize_regmode);
|
||||
|
||||
if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
|
||||
(ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
|
||||
(ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
|
||||
(!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) &&
|
||||
(!AR_SREV_9285(ah)) && (!AR_SREV_9287(ah))) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Mac Chip Rev 0x%02x.%x is not supported by "
|
||||
"this driver\n", ah->hw_version.macVersion,
|
||||
ah->hw_version.macRev);
|
||||
ecode = -EOPNOTSUPP;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (AR_SREV_9100(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_multi_sample;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
ah->is_pciexpress = false;
|
||||
}
|
||||
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
|
||||
|
||||
static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
@ -702,10 +668,18 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
}
|
||||
ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9271(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0,
|
||||
ARRAY_SIZE(ar9271Modes_9271_1_0), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0,
|
||||
ARRAY_SIZE(ar9271Common_9271_1_0), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
ah->ani_function = ATH9K_ANI_ALL;
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
|
||||
@ -867,16 +841,10 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
|
||||
ARRAY_SIZE(ar5416Addac), 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (ah->is_pciexpress)
|
||||
ath9k_hw_configpcipowersave(ah, 0);
|
||||
else
|
||||
ath9k_hw_disablepcie(ah);
|
||||
|
||||
ecode = ath9k_hw_post_attach(ah);
|
||||
if (ecode != 0)
|
||||
goto bad;
|
||||
|
||||
static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9287Modes_rx_gain_9287_1_1,
|
||||
@ -913,8 +881,11 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ath9k_hw_fill_cap_info(ah);
|
||||
static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
|
||||
{
|
||||
u32 i, j;
|
||||
|
||||
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
|
||||
test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
|
||||
@ -933,29 +904,97 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecode = ath9k_hw_init_macaddr(ah);
|
||||
if (ecode != 0) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Failed to initialize MAC address\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (AR_SREV_9285(ah))
|
||||
int ath9k_hw_init(struct ath_hw *ah)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (!ath9k_hw_devid_supported(ah->hw_version.devid))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ath9k_hw_init_defaults(ah);
|
||||
ath9k_hw_init_config(ah);
|
||||
|
||||
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
|
||||
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
|
||||
(AR_SREV_9280(ah) && !ah->is_pciexpress)) {
|
||||
ah->config.serialize_regmode =
|
||||
SER_REG_MODE_ON;
|
||||
} else {
|
||||
ah->config.serialize_regmode =
|
||||
SER_REG_MODE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
|
||||
ah->config.serialize_regmode);
|
||||
|
||||
if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Mac Chip Rev 0x%02x.%x is not supported by "
|
||||
"this driver\n", ah->hw_version.macVersion,
|
||||
ah->hw_version.macRev);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (AR_SREV_9100(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_multi_sample;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
ah->is_pciexpress = false;
|
||||
}
|
||||
|
||||
if (AR_SREV_9271(ah))
|
||||
ah->is_pciexpress = false;
|
||||
|
||||
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
|
||||
|
||||
ath9k_hw_init_cal_settings(ah);
|
||||
|
||||
ah->ani_function = ATH9K_ANI_ALL;
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
|
||||
|
||||
ath9k_hw_init_mode_regs(ah);
|
||||
|
||||
if (ah->is_pciexpress)
|
||||
ath9k_hw_configpcipowersave(ah, 0);
|
||||
else
|
||||
ath9k_hw_disablepcie(ah);
|
||||
|
||||
r = ath9k_hw_post_init(ah);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ath9k_hw_init_mode_gain_regs(ah);
|
||||
ath9k_hw_fill_cap_info(ah);
|
||||
ath9k_hw_init_11a_eeprom_fix(ah);
|
||||
|
||||
r = ath9k_hw_init_macaddr(ah);
|
||||
if (r) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Failed to initialize MAC address\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
|
||||
ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
|
||||
else
|
||||
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
|
||||
|
||||
ath9k_init_nfcal_hist_buffer(ah);
|
||||
|
||||
return ah;
|
||||
bad:
|
||||
if (ah)
|
||||
ath9k_hw_detach(ah);
|
||||
if (status)
|
||||
*status = ecode;
|
||||
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_bb(struct ath_hw *ah,
|
||||
@ -1194,35 +1233,12 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid)
|
||||
void ath9k_hw_detach(struct ath_hw *ah)
|
||||
{
|
||||
if (!AR_SREV_9100(ah))
|
||||
ath9k_hw_ani_detach(ah);
|
||||
ath9k_hw_ani_disable(ah);
|
||||
|
||||
ath9k_hw_rfdetach(ah);
|
||||
ath9k_hw_rf_free(ah);
|
||||
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
|
||||
kfree(ah);
|
||||
}
|
||||
|
||||
struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
|
||||
{
|
||||
struct ath_hw *ah = NULL;
|
||||
|
||||
switch (devid) {
|
||||
case AR5416_DEVID_PCI:
|
||||
case AR5416_DEVID_PCIE:
|
||||
case AR5416_AR9100_DEVID:
|
||||
case AR9160_DEVID_PCI:
|
||||
case AR9280_DEVID_PCI:
|
||||
case AR9280_DEVID_PCIE:
|
||||
case AR9285_DEVID_PCIE:
|
||||
case AR5416_DEVID_AR9287_PCI:
|
||||
case AR5416_DEVID_AR9287_PCIE:
|
||||
ah = ath9k_hw_do_attach(devid, sc, error);
|
||||
break;
|
||||
default:
|
||||
*error = -ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return ah;
|
||||
ah = NULL;
|
||||
}
|
||||
|
||||
/*******/
|
||||
@ -1232,6 +1248,27 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
|
||||
static void ath9k_hw_override_ini(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (AR_SREV_9271(ah)) {
|
||||
/*
|
||||
* Enable spectral scan to solution for issues with stuck
|
||||
* beacons on AR9271 1.0. The beacon stuck issue is not seeon on
|
||||
* AR9271 1.1
|
||||
*/
|
||||
if (AR_SREV_9271_10(ah)) {
|
||||
val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE;
|
||||
REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
|
||||
}
|
||||
else if (AR_SREV_9271_11(ah))
|
||||
/*
|
||||
* change AR_PHY_RF_CTL3 setting to fix MAC issue
|
||||
* present on AR9271 1.1
|
||||
*/
|
||||
REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the RX_ABORT and RX_DIS and clear if off only after
|
||||
* RXE is set for MAC. This prevents frames with corrupted
|
||||
@ -1243,7 +1280,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
|
||||
if (!AR_SREV_5416_20_OR_LATER(ah) ||
|
||||
AR_SREV_9280_10_OR_LATER(ah))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Disable BB clock gating
|
||||
* Necessary to avoid issues on AR5416 2.0
|
||||
*/
|
||||
REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
|
||||
}
|
||||
|
||||
@ -1475,23 +1515,48 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
/*
|
||||
* set AHB_MODE not to do cacheline prefetches
|
||||
*/
|
||||
regval = REG_READ(ah, AR_AHB_MODE);
|
||||
REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
|
||||
|
||||
/*
|
||||
* let mac dma reads be in 128 byte chunks
|
||||
*/
|
||||
regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
|
||||
REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
|
||||
|
||||
/*
|
||||
* Restore TX Trigger Level to its pre-reset value.
|
||||
* The initial value depends on whether aggregation is enabled, and is
|
||||
* adjusted whenever underruns are detected.
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
|
||||
|
||||
/*
|
||||
* let mac dma writes be in 128 byte chunks
|
||||
*/
|
||||
regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
|
||||
REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
|
||||
|
||||
/*
|
||||
* Setup receive FIFO threshold to hold off TX activities
|
||||
*/
|
||||
REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
|
||||
|
||||
/*
|
||||
* reduce the number of usable entries in PCU TXBUF to avoid
|
||||
* wrap around issues.
|
||||
*/
|
||||
if (AR_SREV_9285(ah)) {
|
||||
/* For AR9285 the number of Fifos are reduced to half.
|
||||
* So set the usable tx buf size also to half to
|
||||
* avoid data/delimiter underruns
|
||||
*/
|
||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
||||
AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
|
||||
} else {
|
||||
} else if (!AR_SREV_9271(ah)) {
|
||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
||||
AR_PCU_TXBUF_CTRL_USABLE_SIZE);
|
||||
}
|
||||
@ -2297,11 +2362,26 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
|
||||
ath9k_hw_mark_phy_inactive(ah);
|
||||
|
||||
if (AR_SREV_9271(ah) && ah->htc_reset_init) {
|
||||
REG_WRITE(ah,
|
||||
AR9271_RESET_POWER_DOWN_CONTROL,
|
||||
AR9271_RADIO_RF_RST);
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
if (!ath9k_hw_chip_reset(ah, chan)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (AR_SREV_9271(ah) && ah->htc_reset_init) {
|
||||
ah->htc_reset_init = false;
|
||||
REG_WRITE(ah,
|
||||
AR9271_RESET_POWER_DOWN_CONTROL,
|
||||
AR9271_GATE_MAC_CTL);
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||
|
||||
@ -2437,6 +2517,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
|
||||
REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
|
||||
|
||||
/*
|
||||
* For big endian systems turn on swapping for descriptors
|
||||
*/
|
||||
if (AR_SREV_9100(ah)) {
|
||||
u32 mask;
|
||||
mask = REG_READ(ah, AR_CFG);
|
||||
@ -2451,7 +2534,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
|
||||
}
|
||||
} else {
|
||||
/* Configure AR9271 target WLAN */
|
||||
if (AR_SREV_9271(ah))
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
|
||||
#ifdef __BIG_ENDIAN
|
||||
else
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
|
||||
#endif
|
||||
}
|
||||
@ -2494,9 +2581,6 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
|
||||
|
||||
}
|
||||
|
||||
if (ah->curchan == NULL)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2921,7 +3005,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
|
||||
/*
|
||||
* AR9280 2.0 or later chips use SerDes values from the
|
||||
* initvals.h initialized depending on chipset during
|
||||
* ath9k_hw_do_attach()
|
||||
* ath9k_hw_init()
|
||||
*/
|
||||
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
|
||||
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
|
||||
@ -2982,7 +3066,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
|
||||
if (ah->config.pcie_waen) {
|
||||
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
|
||||
} else {
|
||||
if (AR_SREV_9285(ah))
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
|
||||
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
|
||||
/*
|
||||
* On AR9280 chips bit 22 of 0x4004 needs to be set to
|
||||
@ -3152,11 +3236,6 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
return true;
|
||||
}
|
||||
|
||||
enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah)
|
||||
{
|
||||
return ah->mask_reg;
|
||||
}
|
||||
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
|
||||
{
|
||||
u32 omask = ah->mask_reg;
|
||||
@ -3451,10 +3530,17 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
|
||||
/*
|
||||
* For AR9271 we will temporarilly uses the rx chainmax as read from
|
||||
* the EEPROM.
|
||||
*/
|
||||
if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
|
||||
!(eeval & AR5416_OPFLAGS_11A))
|
||||
!(eeval & AR5416_OPFLAGS_11A) &&
|
||||
!(AR_SREV_9271(ah)))
|
||||
/* CB71: GPIO 0 is pulled down to indicate 3 rx chains */
|
||||
pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
|
||||
else
|
||||
/* Use rx_chainmask from EEPROM. */
|
||||
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
|
||||
|
||||
if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
|
||||
|
@ -403,7 +403,7 @@ struct ath_hw {
|
||||
union {
|
||||
struct ar5416_eeprom_def def;
|
||||
struct ar5416_eeprom_4k map4k;
|
||||
struct ar9287_eeprom_t map9287;
|
||||
struct ar9287_eeprom map9287;
|
||||
} eeprom;
|
||||
const struct eeprom_ops *eep_ops;
|
||||
enum ath9k_eep_map eep_map;
|
||||
@ -419,6 +419,8 @@ struct ath_hw {
|
||||
u32 wlanactive_gpio;
|
||||
u32 ah_flags;
|
||||
|
||||
bool htc_reset_init;
|
||||
|
||||
enum nl80211_iftype opmode;
|
||||
enum ath9k_power_mode power_mode;
|
||||
|
||||
@ -541,11 +543,11 @@ struct ath_hw {
|
||||
struct ar5416IniArray iniModesTxGain;
|
||||
};
|
||||
|
||||
/* Attach, Detach, Reset */
|
||||
/* Initialization, Detach, Reset */
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
void ath9k_hw_detach(struct ath_hw *ah);
|
||||
struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
|
||||
void ath9k_hw_rfdetach(struct ath_hw *ah);
|
||||
int ath9k_hw_init(struct ath_hw *ah);
|
||||
void ath9k_hw_rf_free(struct ath_hw *ah);
|
||||
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
bool bChannelChange);
|
||||
void ath9k_hw_fill_cap_info(struct ath_hw *ah);
|
||||
@ -612,7 +614,6 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
|
||||
/* Interrupt Handling */
|
||||
bool ath9k_hw_intrpend(struct ath_hw *ah);
|
||||
bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
|
||||
enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah);
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
|
||||
|
||||
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
|
||||
|
@ -6365,3 +6365,669 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
|
||||
};
|
||||
|
||||
|
||||
/* AR9271 initialization values automaticaly created: 03/23/09 */
|
||||
static const u_int32_t ar9271Modes_9271_1_0[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
{ 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
|
||||
{ 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
|
||||
{ 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
|
||||
{ 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
|
||||
{ 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
|
||||
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
|
||||
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
|
||||
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
|
||||
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
|
||||
{ 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
|
||||
{ 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
|
||||
{ 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
|
||||
{ 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
|
||||
{ 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
|
||||
{ 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
|
||||
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
|
||||
{ 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 },
|
||||
{ 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
|
||||
{ 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
|
||||
{ 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
|
||||
{ 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
|
||||
{ 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
|
||||
{ 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
|
||||
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
|
||||
{ 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
|
||||
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
|
||||
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
|
||||
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
|
||||
{ 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
|
||||
{ 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
|
||||
{ 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
|
||||
{ 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
|
||||
{ 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
|
||||
{ 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
|
||||
{ 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
|
||||
{ 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
|
||||
{ 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
|
||||
{ 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
|
||||
{ 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
|
||||
{ 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
|
||||
{ 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
|
||||
{ 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
|
||||
{ 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
|
||||
{ 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
|
||||
{ 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
|
||||
{ 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
|
||||
{ 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
|
||||
{ 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
|
||||
{ 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
|
||||
{ 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
|
||||
{ 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
|
||||
{ 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
|
||||
{ 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
|
||||
{ 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
|
||||
{ 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
|
||||
{ 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
|
||||
{ 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
|
||||
{ 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
|
||||
{ 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
|
||||
{ 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
|
||||
{ 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
|
||||
{ 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
|
||||
{ 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
|
||||
{ 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
|
||||
{ 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
|
||||
{ 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
|
||||
{ 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
|
||||
{ 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
|
||||
{ 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
|
||||
{ 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
|
||||
{ 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
|
||||
{ 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
|
||||
{ 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
|
||||
{ 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
|
||||
{ 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
|
||||
{ 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
|
||||
{ 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
|
||||
{ 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
|
||||
{ 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
|
||||
{ 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
|
||||
{ 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
|
||||
{ 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
|
||||
{ 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
|
||||
{ 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
|
||||
{ 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
|
||||
{ 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
|
||||
{ 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
|
||||
{ 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
|
||||
{ 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
|
||||
{ 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
|
||||
{ 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
|
||||
{ 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
|
||||
{ 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
|
||||
{ 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
|
||||
{ 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
|
||||
{ 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
|
||||
{ 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
|
||||
{ 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
|
||||
{ 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
|
||||
{ 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
|
||||
{ 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
|
||||
{ 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
|
||||
{ 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
|
||||
{ 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
|
||||
{ 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
|
||||
{ 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
|
||||
{ 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
|
||||
{ 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
|
||||
{ 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
|
||||
{ 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
|
||||
{ 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
|
||||
{ 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
|
||||
{ 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
|
||||
{ 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
|
||||
{ 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
|
||||
{ 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
|
||||
{ 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
|
||||
{ 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
|
||||
{ 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
|
||||
{ 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
|
||||
{ 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
|
||||
{ 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
|
||||
{ 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
|
||||
{ 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
|
||||
{ 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
|
||||
{ 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
|
||||
{ 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
|
||||
{ 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
|
||||
{ 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
|
||||
{ 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
|
||||
{ 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
|
||||
{ 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
|
||||
{ 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
|
||||
{ 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
|
||||
{ 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
|
||||
{ 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
|
||||
{ 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
|
||||
{ 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
|
||||
{ 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
|
||||
{ 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
|
||||
{ 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
|
||||
{ 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
|
||||
{ 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
|
||||
{ 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
|
||||
{ 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
|
||||
{ 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
|
||||
{ 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
|
||||
{ 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
|
||||
{ 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
|
||||
{ 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
|
||||
{ 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
|
||||
{ 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
|
||||
{ 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
|
||||
{ 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
|
||||
{ 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
|
||||
{ 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
|
||||
{ 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
|
||||
{ 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
|
||||
{ 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
|
||||
{ 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
|
||||
{ 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
|
||||
{ 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
|
||||
{ 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
|
||||
{ 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
|
||||
{ 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
|
||||
{ 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
|
||||
{ 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
|
||||
{ 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
|
||||
{ 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
|
||||
{ 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
|
||||
{ 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
|
||||
{ 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
|
||||
{ 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
|
||||
{ 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
|
||||
{ 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
|
||||
{ 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
|
||||
{ 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
|
||||
{ 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
|
||||
{ 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
|
||||
{ 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
|
||||
{ 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
|
||||
{ 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
|
||||
{ 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
|
||||
{ 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
|
||||
{ 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
|
||||
{ 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
|
||||
{ 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
|
||||
{ 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
|
||||
{ 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
|
||||
{ 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
|
||||
{ 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
|
||||
{ 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
|
||||
{ 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
|
||||
{ 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
|
||||
{ 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
|
||||
{ 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
|
||||
{ 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
|
||||
{ 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
|
||||
{ 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
|
||||
{ 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
|
||||
{ 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
|
||||
{ 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
|
||||
{ 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
|
||||
{ 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
|
||||
{ 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
|
||||
{ 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
|
||||
{ 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
|
||||
{ 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
|
||||
{ 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
|
||||
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
|
||||
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
|
||||
{ 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
|
||||
{ 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 },
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
|
||||
{ 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
|
||||
{ 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
|
||||
{ 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 },
|
||||
{ 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 },
|
||||
{ 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 },
|
||||
{ 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 },
|
||||
{ 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 },
|
||||
{ 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 },
|
||||
{ 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 },
|
||||
{ 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 },
|
||||
{ 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 },
|
||||
{ 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 },
|
||||
{ 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
|
||||
{ 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
|
||||
{ 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
|
||||
{ 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
|
||||
{ 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
|
||||
};
|
||||
|
||||
static const u_int32_t ar9271Common_9271_1_0[][2] = {
|
||||
{ 0x0000000c, 0x00000000 },
|
||||
{ 0x00000030, 0x00020045 },
|
||||
{ 0x00000034, 0x00000005 },
|
||||
{ 0x00000040, 0x00000000 },
|
||||
{ 0x00000044, 0x00000008 },
|
||||
{ 0x00000048, 0x00000008 },
|
||||
{ 0x0000004c, 0x00000010 },
|
||||
{ 0x00000050, 0x00000000 },
|
||||
{ 0x00000054, 0x0000001f },
|
||||
{ 0x00000800, 0x00000000 },
|
||||
{ 0x00000804, 0x00000000 },
|
||||
{ 0x00000808, 0x00000000 },
|
||||
{ 0x0000080c, 0x00000000 },
|
||||
{ 0x00000810, 0x00000000 },
|
||||
{ 0x00000814, 0x00000000 },
|
||||
{ 0x00000818, 0x00000000 },
|
||||
{ 0x0000081c, 0x00000000 },
|
||||
{ 0x00000820, 0x00000000 },
|
||||
{ 0x00000824, 0x00000000 },
|
||||
{ 0x00001040, 0x002ffc0f },
|
||||
{ 0x00001044, 0x002ffc0f },
|
||||
{ 0x00001048, 0x002ffc0f },
|
||||
{ 0x0000104c, 0x002ffc0f },
|
||||
{ 0x00001050, 0x002ffc0f },
|
||||
{ 0x00001054, 0x002ffc0f },
|
||||
{ 0x00001058, 0x002ffc0f },
|
||||
{ 0x0000105c, 0x002ffc0f },
|
||||
{ 0x00001060, 0x002ffc0f },
|
||||
{ 0x00001064, 0x002ffc0f },
|
||||
{ 0x00001230, 0x00000000 },
|
||||
{ 0x00001270, 0x00000000 },
|
||||
{ 0x00001038, 0x00000000 },
|
||||
{ 0x00001078, 0x00000000 },
|
||||
{ 0x000010b8, 0x00000000 },
|
||||
{ 0x000010f8, 0x00000000 },
|
||||
{ 0x00001138, 0x00000000 },
|
||||
{ 0x00001178, 0x00000000 },
|
||||
{ 0x000011b8, 0x00000000 },
|
||||
{ 0x000011f8, 0x00000000 },
|
||||
{ 0x00001238, 0x00000000 },
|
||||
{ 0x00001278, 0x00000000 },
|
||||
{ 0x000012b8, 0x00000000 },
|
||||
{ 0x000012f8, 0x00000000 },
|
||||
{ 0x00001338, 0x00000000 },
|
||||
{ 0x00001378, 0x00000000 },
|
||||
{ 0x000013b8, 0x00000000 },
|
||||
{ 0x000013f8, 0x00000000 },
|
||||
{ 0x00001438, 0x00000000 },
|
||||
{ 0x00001478, 0x00000000 },
|
||||
{ 0x000014b8, 0x00000000 },
|
||||
{ 0x000014f8, 0x00000000 },
|
||||
{ 0x00001538, 0x00000000 },
|
||||
{ 0x00001578, 0x00000000 },
|
||||
{ 0x000015b8, 0x00000000 },
|
||||
{ 0x000015f8, 0x00000000 },
|
||||
{ 0x00001638, 0x00000000 },
|
||||
{ 0x00001678, 0x00000000 },
|
||||
{ 0x000016b8, 0x00000000 },
|
||||
{ 0x000016f8, 0x00000000 },
|
||||
{ 0x00001738, 0x00000000 },
|
||||
{ 0x00001778, 0x00000000 },
|
||||
{ 0x000017b8, 0x00000000 },
|
||||
{ 0x000017f8, 0x00000000 },
|
||||
{ 0x0000103c, 0x00000000 },
|
||||
{ 0x0000107c, 0x00000000 },
|
||||
{ 0x000010bc, 0x00000000 },
|
||||
{ 0x000010fc, 0x00000000 },
|
||||
{ 0x0000113c, 0x00000000 },
|
||||
{ 0x0000117c, 0x00000000 },
|
||||
{ 0x000011bc, 0x00000000 },
|
||||
{ 0x000011fc, 0x00000000 },
|
||||
{ 0x0000123c, 0x00000000 },
|
||||
{ 0x0000127c, 0x00000000 },
|
||||
{ 0x000012bc, 0x00000000 },
|
||||
{ 0x000012fc, 0x00000000 },
|
||||
{ 0x0000133c, 0x00000000 },
|
||||
{ 0x0000137c, 0x00000000 },
|
||||
{ 0x000013bc, 0x00000000 },
|
||||
{ 0x000013fc, 0x00000000 },
|
||||
{ 0x0000143c, 0x00000000 },
|
||||
{ 0x0000147c, 0x00000000 },
|
||||
{ 0x00004030, 0x00000002 },
|
||||
{ 0x0000403c, 0x00000002 },
|
||||
{ 0x00004024, 0x0000001f },
|
||||
{ 0x00004060, 0x00000000 },
|
||||
{ 0x00004064, 0x00000000 },
|
||||
{ 0x00008004, 0x00000000 },
|
||||
{ 0x00008008, 0x00000000 },
|
||||
{ 0x0000800c, 0x00000000 },
|
||||
{ 0x00008018, 0x00000700 },
|
||||
{ 0x00008020, 0x00000000 },
|
||||
{ 0x00008038, 0x00000000 },
|
||||
{ 0x0000803c, 0x00000000 },
|
||||
{ 0x00008048, 0x00000000 },
|
||||
{ 0x00008054, 0x00000000 },
|
||||
{ 0x00008058, 0x02000000 },
|
||||
{ 0x0000805c, 0x000fc78f },
|
||||
{ 0x00008060, 0x0000000f },
|
||||
{ 0x00008064, 0x00000000 },
|
||||
{ 0x00008070, 0x00000000 },
|
||||
{ 0x000080b0, 0x00000000 },
|
||||
{ 0x000080b4, 0x00000000 },
|
||||
{ 0x000080b8, 0x00000000 },
|
||||
{ 0x000080bc, 0x00000000 },
|
||||
{ 0x000080c0, 0x2a80001a },
|
||||
{ 0x000080c4, 0x05dc01e0 },
|
||||
{ 0x000080c8, 0x1f402710 },
|
||||
{ 0x000080cc, 0x01f40000 },
|
||||
{ 0x000080d0, 0x00001e00 },
|
||||
{ 0x000080d4, 0x00000000 },
|
||||
{ 0x000080d8, 0x00400000 },
|
||||
{ 0x000080e0, 0xffffffff },
|
||||
{ 0x000080e4, 0x0000ffff },
|
||||
{ 0x000080e8, 0x003f3f3f },
|
||||
{ 0x000080ec, 0x00000000 },
|
||||
{ 0x000080f0, 0x00000000 },
|
||||
{ 0x000080f4, 0x00000000 },
|
||||
{ 0x000080f8, 0x00000000 },
|
||||
{ 0x000080fc, 0x00020000 },
|
||||
{ 0x00008100, 0x00020000 },
|
||||
{ 0x00008104, 0x00000001 },
|
||||
{ 0x00008108, 0x00000052 },
|
||||
{ 0x0000810c, 0x00000000 },
|
||||
{ 0x00008110, 0x00000168 },
|
||||
{ 0x00008118, 0x000100aa },
|
||||
{ 0x0000811c, 0x00003210 },
|
||||
{ 0x00008120, 0x08f04814 },
|
||||
{ 0x00008124, 0x00000000 },
|
||||
{ 0x00008128, 0x00000000 },
|
||||
{ 0x0000812c, 0x00000000 },
|
||||
{ 0x00008130, 0x00000000 },
|
||||
{ 0x00008134, 0x00000000 },
|
||||
{ 0x00008138, 0x00000000 },
|
||||
{ 0x0000813c, 0x00000000 },
|
||||
{ 0x00008144, 0xffffffff },
|
||||
{ 0x00008168, 0x00000000 },
|
||||
{ 0x0000816c, 0x00000000 },
|
||||
{ 0x00008170, 0x32143320 },
|
||||
{ 0x00008174, 0xfaa4fa50 },
|
||||
{ 0x00008178, 0x00000100 },
|
||||
{ 0x0000817c, 0x00000000 },
|
||||
{ 0x000081c0, 0x00000000 },
|
||||
{ 0x000081d0, 0x0000320a },
|
||||
{ 0x000081ec, 0x00000000 },
|
||||
{ 0x000081f0, 0x00000000 },
|
||||
{ 0x000081f4, 0x00000000 },
|
||||
{ 0x000081f8, 0x00000000 },
|
||||
{ 0x000081fc, 0x00000000 },
|
||||
{ 0x00008200, 0x00000000 },
|
||||
{ 0x00008204, 0x00000000 },
|
||||
{ 0x00008208, 0x00000000 },
|
||||
{ 0x0000820c, 0x00000000 },
|
||||
{ 0x00008210, 0x00000000 },
|
||||
{ 0x00008214, 0x00000000 },
|
||||
{ 0x00008218, 0x00000000 },
|
||||
{ 0x0000821c, 0x00000000 },
|
||||
{ 0x00008220, 0x00000000 },
|
||||
{ 0x00008224, 0x00000000 },
|
||||
{ 0x00008228, 0x00000000 },
|
||||
{ 0x0000822c, 0x00000000 },
|
||||
{ 0x00008230, 0x00000000 },
|
||||
{ 0x00008234, 0x00000000 },
|
||||
{ 0x00008238, 0x00000000 },
|
||||
{ 0x0000823c, 0x00000000 },
|
||||
{ 0x00008240, 0x00100000 },
|
||||
{ 0x00008244, 0x0010f400 },
|
||||
{ 0x00008248, 0x00000100 },
|
||||
{ 0x0000824c, 0x0001e800 },
|
||||
{ 0x00008250, 0x00000000 },
|
||||
{ 0x00008254, 0x00000000 },
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
{ 0x0000827c, 0x00000000 },
|
||||
{ 0x00008284, 0x0000002c },
|
||||
{ 0x00008288, 0x0000002c },
|
||||
{ 0x0000828c, 0x00000000 },
|
||||
{ 0x00008294, 0x00000000 },
|
||||
{ 0x00008298, 0x00000000 },
|
||||
{ 0x0000829c, 0x00000000 },
|
||||
{ 0x00008300, 0x00000040 },
|
||||
{ 0x00008314, 0x00000000 },
|
||||
{ 0x00008328, 0x00000000 },
|
||||
{ 0x0000832c, 0x00000001 },
|
||||
{ 0x00008330, 0x00000302 },
|
||||
{ 0x00008334, 0x00000e00 },
|
||||
{ 0x00008338, 0x00ff0000 },
|
||||
{ 0x0000833c, 0x00000000 },
|
||||
{ 0x00008340, 0x00010380 },
|
||||
{ 0x00008344, 0x00581043 },
|
||||
{ 0x00007010, 0x00000030 },
|
||||
{ 0x00007034, 0x00000002 },
|
||||
{ 0x00007038, 0x000004c2 },
|
||||
{ 0x00007800, 0x00140000 },
|
||||
{ 0x00007804, 0x0e4548d8 },
|
||||
{ 0x00007808, 0x54214514 },
|
||||
{ 0x0000780c, 0x02025820 },
|
||||
{ 0x00007810, 0x71c0d388 },
|
||||
{ 0x00007814, 0x924934a8 },
|
||||
{ 0x0000781c, 0x00000000 },
|
||||
{ 0x00007820, 0x00000c04 },
|
||||
{ 0x00007824, 0x00d86bff },
|
||||
{ 0x00007828, 0x66964300 },
|
||||
{ 0x0000782c, 0x8db6d961 },
|
||||
{ 0x00007830, 0x8db6d96c },
|
||||
{ 0x00007834, 0x6140008b },
|
||||
{ 0x00007838, 0x00000029 },
|
||||
{ 0x0000783c, 0x72ee0a72 },
|
||||
{ 0x00007840, 0xbbfffffc },
|
||||
{ 0x00007844, 0x000c0db6 },
|
||||
{ 0x00007848, 0x6db61b6f },
|
||||
{ 0x0000784c, 0x6d9b66db },
|
||||
{ 0x00007850, 0x6d8c6dba },
|
||||
{ 0x00007854, 0x00040000 },
|
||||
{ 0x00007858, 0xdb003012 },
|
||||
{ 0x0000785c, 0x04924914 },
|
||||
{ 0x00007860, 0x21084210 },
|
||||
{ 0x00007864, 0xf7d7ffde },
|
||||
{ 0x00007868, 0xc2034080 },
|
||||
{ 0x0000786c, 0x48609eb4 },
|
||||
{ 0x00007870, 0x10142c00 },
|
||||
{ 0x00009808, 0x00000000 },
|
||||
{ 0x0000980c, 0xafe68e30 },
|
||||
{ 0x00009810, 0xfd14e000 },
|
||||
{ 0x00009814, 0x9c0a9f6b },
|
||||
{ 0x0000981c, 0x00000000 },
|
||||
{ 0x0000982c, 0x0000a000 },
|
||||
{ 0x00009830, 0x00000000 },
|
||||
{ 0x0000983c, 0x00200400 },
|
||||
{ 0x0000984c, 0x0040233c },
|
||||
{ 0x00009854, 0x00000044 },
|
||||
{ 0x00009900, 0x00000000 },
|
||||
{ 0x00009904, 0x00000000 },
|
||||
{ 0x00009908, 0x00000000 },
|
||||
{ 0x0000990c, 0x00000000 },
|
||||
{ 0x00009910, 0x30002310 },
|
||||
{ 0x0000991c, 0x10000fff },
|
||||
{ 0x00009920, 0x04900000 },
|
||||
{ 0x00009928, 0x00000001 },
|
||||
{ 0x0000992c, 0x00000004 },
|
||||
{ 0x00009934, 0x1e1f2022 },
|
||||
{ 0x00009938, 0x0a0b0c0d },
|
||||
{ 0x0000993c, 0x00000000 },
|
||||
{ 0x00009940, 0x14750604 },
|
||||
{ 0x00009948, 0x9280c00a },
|
||||
{ 0x0000994c, 0x00020028 },
|
||||
{ 0x00009954, 0x5f3ca3de },
|
||||
{ 0x00009958, 0x0108ecff },
|
||||
{ 0x00009968, 0x000003ce },
|
||||
{ 0x00009970, 0x192bb515 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
{ 0x0000997c, 0x00000000 },
|
||||
{ 0x00009980, 0x00000000 },
|
||||
{ 0x00009984, 0x00000000 },
|
||||
{ 0x00009988, 0x00000000 },
|
||||
{ 0x0000998c, 0x00000000 },
|
||||
{ 0x00009990, 0x00000000 },
|
||||
{ 0x00009994, 0x00000000 },
|
||||
{ 0x00009998, 0x00000000 },
|
||||
{ 0x0000999c, 0x00000000 },
|
||||
{ 0x000099a0, 0x00000000 },
|
||||
{ 0x000099a4, 0x00000001 },
|
||||
{ 0x000099a8, 0x201fff00 },
|
||||
{ 0x000099ac, 0x2def0400 },
|
||||
{ 0x000099b0, 0x03051000 },
|
||||
{ 0x000099b4, 0x00000820 },
|
||||
{ 0x000099dc, 0x00000000 },
|
||||
{ 0x000099e0, 0x00000000 },
|
||||
{ 0x000099e4, 0xaaaaaaaa },
|
||||
{ 0x000099e8, 0x3c466478 },
|
||||
{ 0x000099ec, 0x0cc80caa },
|
||||
{ 0x000099f0, 0x00000000 },
|
||||
{ 0x0000a1f4, 0x00000000 },
|
||||
{ 0x0000a1f8, 0x71733d01 },
|
||||
{ 0x0000a1fc, 0xd0ad5c12 },
|
||||
{ 0x0000a208, 0x803e68c8 },
|
||||
{ 0x0000a210, 0x4080a333 },
|
||||
{ 0x0000a214, 0x00206c10 },
|
||||
{ 0x0000a218, 0x009c4060 },
|
||||
{ 0x0000a220, 0x01834061 },
|
||||
{ 0x0000a224, 0x00000400 },
|
||||
{ 0x0000a228, 0x000003b5 },
|
||||
{ 0x0000a22c, 0x00000000 },
|
||||
{ 0x0000a234, 0x20202020 },
|
||||
{ 0x0000a238, 0x20202020 },
|
||||
{ 0x0000a244, 0x00000000 },
|
||||
{ 0x0000a248, 0xfffffffc },
|
||||
{ 0x0000a24c, 0x00000000 },
|
||||
{ 0x0000a254, 0x00000000 },
|
||||
{ 0x0000a258, 0x0ccb5380 },
|
||||
{ 0x0000a25c, 0x15151501 },
|
||||
{ 0x0000a260, 0xdfa90f01 },
|
||||
{ 0x0000a268, 0x00000000 },
|
||||
{ 0x0000a26c, 0x0ebae9e6 },
|
||||
{ 0x0000a278, 0x3bdef7bd },
|
||||
{ 0x0000a27c, 0x050e83bd },
|
||||
{ 0x0000a388, 0x0c000000 },
|
||||
{ 0x0000a38c, 0x20202020 },
|
||||
{ 0x0000a390, 0x20202020 },
|
||||
{ 0x0000a394, 0x3bdef7bd },
|
||||
{ 0x0000a398, 0x000003bd },
|
||||
{ 0x0000a39c, 0x00000001 },
|
||||
{ 0x0000a3a0, 0x00000000 },
|
||||
{ 0x0000a3a4, 0x00000000 },
|
||||
{ 0x0000a3a8, 0x00000000 },
|
||||
{ 0x0000a3ac, 0x00000000 },
|
||||
{ 0x0000a3b0, 0x00000000 },
|
||||
{ 0x0000a3b4, 0x00000000 },
|
||||
{ 0x0000a3b8, 0x00000000 },
|
||||
{ 0x0000a3bc, 0x00000000 },
|
||||
{ 0x0000a3c0, 0x00000000 },
|
||||
{ 0x0000a3c4, 0x00000000 },
|
||||
{ 0x0000a3cc, 0x20202020 },
|
||||
{ 0x0000a3d0, 0x20202020 },
|
||||
{ 0x0000a3d4, 0x20202020 },
|
||||
{ 0x0000a3dc, 0x3bdef7bd },
|
||||
{ 0x0000a3e0, 0x000003bd },
|
||||
{ 0x0000a3e4, 0x00000000 },
|
||||
{ 0x0000a3e8, 0x18c43433 },
|
||||
{ 0x0000a3ec, 0x00f70081 },
|
||||
{ 0x0000a3f0, 0x01036a2f },
|
||||
{ 0x0000a3f4, 0x00000000 },
|
||||
{ 0x0000d270, 0x0d820820 },
|
||||
{ 0x0000d35c, 0x07ffffef },
|
||||
{ 0x0000d360, 0x0fffffe7 },
|
||||
{ 0x0000d364, 0x17ffffe5 },
|
||||
{ 0x0000d368, 0x1fffffe4 },
|
||||
{ 0x0000d36c, 0x37ffffe3 },
|
||||
{ 0x0000d370, 0x3fffffe3 },
|
||||
{ 0x0000d374, 0x57ffffe3 },
|
||||
{ 0x0000d378, 0x5fffffe2 },
|
||||
{ 0x0000d37c, 0x7fffffe2 },
|
||||
{ 0x0000d380, 0x7f3c7bba },
|
||||
{ 0x0000d384, 0xf3307ff0 },
|
||||
};
|
||||
|
@ -973,7 +973,8 @@ static void ath_led_blink_work(struct work_struct *work)
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
|
||||
(sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
|
||||
|
||||
queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
|
||||
ieee80211_queue_delayed_work(sc->hw,
|
||||
&sc->ath_led_blink_work,
|
||||
(sc->sc_flags & SC_OP_LED_ON) ?
|
||||
msecs_to_jiffies(sc->led_off_duration) :
|
||||
msecs_to_jiffies(sc->led_on_duration));
|
||||
@ -1013,7 +1014,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||
case LED_FULL:
|
||||
if (led->led_type == ATH_LED_ASSOC) {
|
||||
sc->sc_flags |= SC_OP_LED_ASSOCIATED;
|
||||
queue_delayed_work(sc->hw->workqueue,
|
||||
ieee80211_queue_delayed_work(sc->hw,
|
||||
&sc->ath_led_blink_work, 0);
|
||||
} else if (led->led_type == ATH_LED_RADIO) {
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
|
||||
@ -1056,7 +1057,6 @@ static void ath_unregister_led(struct ath_led *led)
|
||||
|
||||
static void ath_deinit_leds(struct ath_softc *sc)
|
||||
{
|
||||
cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
ath_unregister_led(&sc->assoc_led);
|
||||
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
ath_unregister_led(&sc->tx_led);
|
||||
@ -1113,6 +1113,7 @@ static void ath_init_leds(struct ath_softc *sc)
|
||||
return;
|
||||
|
||||
fail:
|
||||
cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
ath_deinit_leds(sc);
|
||||
}
|
||||
|
||||
@ -1252,9 +1253,6 @@ void ath_detach(struct ath_softc *sc)
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
|
||||
|
||||
ath_deinit_leds(sc);
|
||||
cancel_work_sync(&sc->chan_work);
|
||||
cancel_delayed_work_sync(&sc->wiphy_work);
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||
@ -1280,6 +1278,7 @@ void ath_detach(struct ath_softc *sc)
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
|
||||
ath9k_hw_detach(sc->sc_ah);
|
||||
sc->sc_ah = NULL;
|
||||
ath9k_exit_debug(sc);
|
||||
}
|
||||
|
||||
@ -1294,11 +1293,16 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
return ath_reg_notifier_apply(wiphy, request, reg);
|
||||
}
|
||||
|
||||
static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
/*
|
||||
* Initialize and fill ath_softc, ath_sofct is the
|
||||
* "Software Carrier" struct. Historically it has existed
|
||||
* to allow the separation between hardware specific
|
||||
* variables (now in ath_hw) and driver specific variables.
|
||||
*/
|
||||
static int ath_init_softc(u16 devid, struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = NULL;
|
||||
int status;
|
||||
int error = 0, i;
|
||||
int r = 0, i;
|
||||
int csz = 0;
|
||||
|
||||
/* XXX: hardware will not be ready until ath_open() being called */
|
||||
@ -1325,14 +1329,23 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
/* XXX assert csz is non-zero */
|
||||
sc->cachelsz = csz << 2; /* convert to bytes */
|
||||
|
||||
ah = ath9k_hw_attach(devid, sc, &status);
|
||||
if (ah == NULL) {
|
||||
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
|
||||
if (!ah) {
|
||||
r = -ENOMEM;
|
||||
goto bad_no_ah;
|
||||
}
|
||||
|
||||
ah->ah_sc = sc;
|
||||
ah->hw_version.devid = devid;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
r = ath9k_hw_init(ah);
|
||||
if (r) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to attach hardware; HAL status %d\n", status);
|
||||
error = -ENXIO;
|
||||
"Unable to initialize hardware; "
|
||||
"initialization status: %d\n", r);
|
||||
goto bad;
|
||||
}
|
||||
sc->sc_ah = ah;
|
||||
|
||||
/* Get the hardware key cache size. */
|
||||
sc->keymax = ah->caps.keycache_size;
|
||||
@ -1350,9 +1363,6 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
for (i = 0; i < sc->keymax; i++)
|
||||
ath9k_hw_keyreset(ah, (u16) i);
|
||||
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
/* default to MONITOR mode */
|
||||
sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
|
||||
|
||||
@ -1372,14 +1382,14 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
if (sc->beacon.beaconq == -1) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup a beacon xmit queue\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
|
||||
if (sc->beacon.cabq == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup CAB xmit queue\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
@ -1394,26 +1404,26 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for BK traffic\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for BE traffic\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for VI traffic\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for VO traffic\n");
|
||||
error = -EIO;
|
||||
r = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
@ -1507,11 +1517,12 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
if (ATH_TXQ_SETUP(sc, i))
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
bad:
|
||||
if (ah)
|
||||
ath9k_hw_detach(ah);
|
||||
sc->sc_ah = NULL;
|
||||
bad_no_ah:
|
||||
ath9k_exit_debug(sc);
|
||||
|
||||
return error;
|
||||
return r;
|
||||
}
|
||||
|
||||
void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
@ -1551,7 +1562,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
&sc->sbands[IEEE80211_BAND_5GHZ];
|
||||
}
|
||||
|
||||
int ath_attach(u16 devid, struct ath_softc *sc)
|
||||
/* Device driver core initialization */
|
||||
int ath_init_device(u16 devid, struct ath_softc *sc)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
int error = 0, i;
|
||||
@ -1559,7 +1571,7 @@ int ath_attach(u16 devid, struct ath_softc *sc)
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
|
||||
|
||||
error = ath_init(devid, sc);
|
||||
error = ath_init_softc(devid, sc);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
@ -1617,6 +1629,7 @@ int ath_attach(u16 devid, struct ath_softc *sc)
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
|
||||
ath9k_hw_detach(sc->sc_ah);
|
||||
sc->sc_ah = NULL;
|
||||
ath9k_exit_debug(sc);
|
||||
|
||||
return error;
|
||||
@ -1975,7 +1988,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0);
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
|
||||
|
||||
mutex_unlock:
|
||||
mutex_unlock(&sc->mutex);
|
||||
@ -2089,6 +2102,14 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
|
||||
aphy->state = ATH_WIPHY_INACTIVE;
|
||||
|
||||
cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
if (!sc->num_sec_wiphy) {
|
||||
cancel_delayed_work_sync(&sc->wiphy_work);
|
||||
cancel_work_sync(&sc->chan_work);
|
||||
}
|
||||
|
||||
if (sc->sc_flags & SC_OP_INVALID) {
|
||||
DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
|
||||
return;
|
||||
@ -2096,6 +2117,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
if (ath9k_wiphy_started(sc)) {
|
||||
mutex_unlock(&sc->mutex);
|
||||
return; /* another wiphy still in use */
|
||||
|
@ -178,7 +178,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
sc->mem = mem;
|
||||
sc->bus_ops = &ath_pci_bus_ops;
|
||||
|
||||
if (ath_attach(id->device, sc) != 0) {
|
||||
if (ath_init_device(id->device, sc) != 0) {
|
||||
ret = -ENODEV;
|
||||
goto bad3;
|
||||
}
|
||||
|
@ -264,44 +264,23 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
}
|
||||
|
||||
void
|
||||
ath9k_hw_rfdetach(struct ath_hw *ah)
|
||||
ath9k_hw_rf_free(struct ath_hw *ah)
|
||||
{
|
||||
if (ah->analogBank0Data != NULL) {
|
||||
kfree(ah->analogBank0Data);
|
||||
ah->analogBank0Data = NULL;
|
||||
}
|
||||
if (ah->analogBank1Data != NULL) {
|
||||
kfree(ah->analogBank1Data);
|
||||
ah->analogBank1Data = NULL;
|
||||
}
|
||||
if (ah->analogBank2Data != NULL) {
|
||||
kfree(ah->analogBank2Data);
|
||||
ah->analogBank2Data = NULL;
|
||||
}
|
||||
if (ah->analogBank3Data != NULL) {
|
||||
kfree(ah->analogBank3Data);
|
||||
ah->analogBank3Data = NULL;
|
||||
}
|
||||
if (ah->analogBank6Data != NULL) {
|
||||
kfree(ah->analogBank6Data);
|
||||
ah->analogBank6Data = NULL;
|
||||
}
|
||||
if (ah->analogBank6TPCData != NULL) {
|
||||
kfree(ah->analogBank6TPCData);
|
||||
ah->analogBank6TPCData = NULL;
|
||||
}
|
||||
if (ah->analogBank7Data != NULL) {
|
||||
kfree(ah->analogBank7Data);
|
||||
ah->analogBank7Data = NULL;
|
||||
}
|
||||
if (ah->addac5416_21 != NULL) {
|
||||
kfree(ah->addac5416_21);
|
||||
ah->addac5416_21 = NULL;
|
||||
}
|
||||
if (ah->bank6Temp != NULL) {
|
||||
kfree(ah->bank6Temp);
|
||||
ah->bank6Temp = NULL;
|
||||
}
|
||||
#define ATH_FREE_BANK(bank) do { \
|
||||
kfree(bank); \
|
||||
bank = NULL; \
|
||||
} while (0);
|
||||
|
||||
ATH_FREE_BANK(ah->analogBank0Data);
|
||||
ATH_FREE_BANK(ah->analogBank1Data);
|
||||
ATH_FREE_BANK(ah->analogBank2Data);
|
||||
ATH_FREE_BANK(ah->analogBank3Data);
|
||||
ATH_FREE_BANK(ah->analogBank6Data);
|
||||
ATH_FREE_BANK(ah->analogBank6TPCData);
|
||||
ATH_FREE_BANK(ah->analogBank7Data);
|
||||
ATH_FREE_BANK(ah->addac5416_21);
|
||||
ATH_FREE_BANK(ah->bank6Temp);
|
||||
#undef ATH_FREE_BANK
|
||||
}
|
||||
|
||||
bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
|
||||
|
@ -185,6 +185,9 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
|
||||
#define AR_PHY_PLL_CTL_44_2133 0xeb
|
||||
#define AR_PHY_PLL_CTL_40_2133 0xea
|
||||
|
||||
#define AR_PHY_SPECTRAL_SCAN 0x9912
|
||||
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
|
||||
|
||||
#define AR_PHY_RX_DELAY 0x9914
|
||||
#define AR_PHY_SEARCH_START_DELAY 0x9918
|
||||
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
|
||||
|
@ -44,7 +44,7 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
|
||||
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
|
||||
29300, 0x0c, 0x00, 108,
|
||||
4, 7, 7, 7, 7, 0 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
|
||||
{ VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
|
||||
6400, 0x80, 0x00, 0,
|
||||
0, 8, 24, 8, 24, 3216 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
|
||||
@ -463,8 +463,6 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
|
||||
if (!ignore_cw && WLAN_RC_PHY_HT(phy))
|
||||
if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
|
||||
return 0;
|
||||
if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1043,9 +1041,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
||||
/* Monotonicity is kept only for rates below the current rate. */
|
||||
if (ath_rc_priv->per[tx_rate] < last_per) {
|
||||
for (rate = tx_rate - 1; rate >= 0; rate--) {
|
||||
if (rate_table->info[rate].phy !=
|
||||
rate_table->info[tx_rate].phy)
|
||||
break;
|
||||
|
||||
if (ath_rc_priv->per[rate] >
|
||||
ath_rc_priv->per[rate+1]) {
|
||||
|
@ -744,6 +744,9 @@
|
||||
#define AR_SREV_VERSION_9287 0x180
|
||||
#define AR_SREV_REVISION_9287_10 0
|
||||
#define AR_SREV_REVISION_9287_11 1
|
||||
#define AR_SREV_VERSION_9271 0x140
|
||||
#define AR_SREV_REVISION_9271_10 0
|
||||
#define AR_SREV_REVISION_9271_11 1
|
||||
|
||||
#define AR_SREV_5416(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
|
||||
@ -815,6 +818,15 @@
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
|
||||
|
||||
#define AR_SREV_9271(_ah) \
|
||||
(((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
|
||||
#define AR_SREV_9271_10(_ah) \
|
||||
(AR_SREV_9271(_ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10))
|
||||
#define AR_SREV_9271_11(_ah) \
|
||||
(AR_SREV_9271(_ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
|
||||
|
||||
#define AR_RADIO_SREV_MAJOR 0xf0
|
||||
#define AR_RAD5133_SREV_MAJOR 0xc0
|
||||
#define AR_RAD2133_SREV_MAJOR 0xd0
|
||||
@ -1142,12 +1154,32 @@ enum {
|
||||
#define AR9285_AN_RF2G4_DB2_4 0x00003800
|
||||
#define AR9285_AN_RF2G4_DB2_4_S 11
|
||||
|
||||
/* AR9271 : 0x7828, 0x782c different setting from AR9285 */
|
||||
#define AR9271_AN_RF2G3_OB_cck 0x001C0000
|
||||
#define AR9271_AN_RF2G3_OB_cck_S 18
|
||||
#define AR9271_AN_RF2G3_OB_psk 0x00038000
|
||||
#define AR9271_AN_RF2G3_OB_psk_S 15
|
||||
#define AR9271_AN_RF2G3_OB_qam 0x00007000
|
||||
#define AR9271_AN_RF2G3_OB_qam_S 12
|
||||
|
||||
#define AR9271_AN_RF2G3_DB_1 0x00E00000
|
||||
#define AR9271_AN_RF2G3_DB_1_S 21
|
||||
|
||||
#define AR9271_AN_RF2G3_CCOMP 0xFFF
|
||||
#define AR9271_AN_RF2G3_CCOMP_S 0
|
||||
|
||||
#define AR9271_AN_RF2G4_DB_2 0xE0000000
|
||||
#define AR9271_AN_RF2G4_DB_2_S 29
|
||||
|
||||
#define AR9285_AN_RF2G6 0x7834
|
||||
#define AR9285_AN_RF2G6_CCOMP 0x00007800
|
||||
#define AR9285_AN_RF2G6_CCOMP_S 11
|
||||
#define AR9285_AN_RF2G6_OFFS 0x03f00000
|
||||
#define AR9285_AN_RF2G6_OFFS_S 20
|
||||
|
||||
#define AR9271_AN_RF2G6_OFFS 0x07f00000
|
||||
#define AR9271_AN_RF2G6_OFFS_S 20
|
||||
|
||||
#define AR9285_AN_RF2G7 0x7838
|
||||
#define AR9285_AN_RF2G7_PWDDB 0x00000002
|
||||
#define AR9285_AN_RF2G7_PWDDB_S 1
|
||||
@ -1208,6 +1240,11 @@ enum {
|
||||
#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000
|
||||
#define AR9287_AN_TOP2_XPABIAS_LVL_S 30
|
||||
|
||||
/* AR9271 specific stuff */
|
||||
#define AR9271_RESET_POWER_DOWN_CONTROL 0x50044
|
||||
#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
|
||||
|
@ -351,7 +351,7 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
* Drop from tasklet to work to allow mutex for channel
|
||||
* change.
|
||||
*/
|
||||
queue_work(aphy->sc->hw->workqueue,
|
||||
ieee80211_queue_work(aphy->sc->hw,
|
||||
&aphy->sc->chan_work);
|
||||
}
|
||||
}
|
||||
@ -367,7 +367,7 @@ static void ath9k_mark_paused(struct ath_wiphy *aphy)
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
aphy->state = ATH_WIPHY_PAUSED;
|
||||
if (!__ath9k_wiphy_pausing(sc))
|
||||
queue_work(sc->hw->workqueue, &sc->chan_work);
|
||||
ieee80211_queue_work(sc->hw, &sc->chan_work);
|
||||
}
|
||||
|
||||
static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
@ -521,7 +521,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
ath_radio_disable(sc);
|
||||
ath_radio_enable(sc);
|
||||
queue_work(aphy->sc->hw->workqueue,
|
||||
ieee80211_queue_work(aphy->sc->hw,
|
||||
&aphy->sc->chan_work);
|
||||
return -EBUSY; /* previous select still in progress */
|
||||
}
|
||||
@ -541,7 +541,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
|
||||
|
||||
if (now) {
|
||||
/* Ready to request channel change immediately */
|
||||
queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
|
||||
ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -648,7 +648,8 @@ void ath9k_wiphy_work(struct work_struct *work)
|
||||
"change\n");
|
||||
}
|
||||
|
||||
queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
|
||||
ieee80211_queue_delayed_work(sc->hw,
|
||||
&sc->wiphy_work,
|
||||
sc->wiphy_scheduler_int);
|
||||
}
|
||||
|
||||
@ -657,7 +658,7 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
|
||||
cancel_delayed_work_sync(&sc->wiphy_work);
|
||||
sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
|
||||
if (sc->wiphy_scheduler_int)
|
||||
queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
|
||||
sc->wiphy_scheduler_int);
|
||||
}
|
||||
|
||||
|
@ -2063,7 +2063,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work,
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
|
||||
msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,17 @@
|
||||
#define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
|
||||
#define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
|
||||
|
||||
/* SPROM boardflags_hi values */
|
||||
#define B43_BFH_NOPA 0x0001 /* has no PA */
|
||||
#define B43_BFH_RSSIINV 0x0002 /* RSSI uses positive slope (not TSSI) */
|
||||
#define B43_BFH_PAREF 0x0004 /* uses the PARef LDO */
|
||||
#define B43_BFH_3TSWITCH 0x0008 /* uses a triple throw switch shared
|
||||
* with bluetooth */
|
||||
#define B43_BFH_PHASESHIFT 0x0010 /* can support phase shifter */
|
||||
#define B43_BFH_BUCKBOOST 0x0020 /* has buck/booster */
|
||||
#define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna
|
||||
* with bluetooth */
|
||||
|
||||
/* GPIO register offset, in both ChipCommon and PCI core. */
|
||||
#define B43_GPIO_CONTROL 0x6c
|
||||
|
||||
|
@ -1334,13 +1334,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
|
||||
B43_WARN_ON(!ring->tx);
|
||||
/* Check if the queue was stopped in mac80211,
|
||||
* but we got called nevertheless.
|
||||
* That would be a mac80211 bug. */
|
||||
B43_WARN_ON(ring->stopped);
|
||||
|
||||
if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
|
||||
b43warn(dev->wl, "DMA queue overflow\n");
|
||||
if (unlikely(ring->stopped)) {
|
||||
/* We get here only because of a bug in mac80211.
|
||||
* Because of a race, one packet may be queued after
|
||||
* the queue is stopped, thus we got called when we shouldn't.
|
||||
* For now, just refuse the transmit. */
|
||||
if (b43_debug(dev, B43_DBG_DMAVERBOSE))
|
||||
b43err(dev->wl, "Packet after queue stopped\n");
|
||||
err = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
|
||||
/* If we get here, we have a real error with the queue
|
||||
* full, but queues not stopped. */
|
||||
b43err(dev->wl, "DMA queue overflow\n");
|
||||
err = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
|
||||
/* Unaligned access */
|
||||
b43_shm_control_word(dev, routing, offset >> 2);
|
||||
ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
|
||||
ret <<= 16;
|
||||
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
|
||||
ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
|
||||
ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16;
|
||||
|
||||
goto out;
|
||||
}
|
||||
@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value
|
||||
/* Unaligned access */
|
||||
b43_shm_control_word(dev, routing, offset >> 2);
|
||||
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
|
||||
(value >> 16) & 0xffff);
|
||||
value & 0xFFFF);
|
||||
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
|
||||
b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
|
||||
b43_write16(dev, B43_MMIO_SHM_DATA,
|
||||
(value >> 16) & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
offset >>= 2;
|
||||
@ -1524,10 +1524,13 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
|
||||
/* Looks like PLCP headers plus packet timings are stored for
|
||||
* all possible basic rates
|
||||
*/
|
||||
/* FIXME this is the wrong offset : it goes in tkip rx phase1 shm */
|
||||
#if 0
|
||||
b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
|
||||
b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
|
||||
b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
|
||||
b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
|
||||
#endif
|
||||
|
||||
size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
|
||||
b43_write_template_common(dev, probe_resp_data,
|
||||
@ -1654,7 +1657,7 @@ static void b43_update_templates(struct b43_wl *wl)
|
||||
wl->current_beacon = beacon;
|
||||
wl->beacon0_uploaded = 0;
|
||||
wl->beacon1_uploaded = 0;
|
||||
queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
|
||||
ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
|
||||
}
|
||||
|
||||
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
|
||||
@ -2914,7 +2917,7 @@ static void b43_periodic_work_handler(struct work_struct *work)
|
||||
delay = msecs_to_jiffies(50);
|
||||
else
|
||||
delay = round_jiffies_relative(HZ * 15);
|
||||
queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
|
||||
ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
@ -2925,15 +2928,16 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
|
||||
|
||||
dev->periodic_state = 0;
|
||||
INIT_DELAYED_WORK(work, b43_periodic_work_handler);
|
||||
queue_delayed_work(dev->wl->hw->workqueue, work, 0);
|
||||
ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
|
||||
}
|
||||
|
||||
/* Check if communication with the device works correctly. */
|
||||
static int b43_validate_chipaccess(struct b43_wldev *dev)
|
||||
{
|
||||
u32 v, backup;
|
||||
u32 v, backup0, backup4;
|
||||
|
||||
backup = b43_shm_read32(dev, B43_SHM_SHARED, 0);
|
||||
backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0);
|
||||
backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4);
|
||||
|
||||
/* Check for read/write and endianness problems. */
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
|
||||
@ -2943,7 +2947,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
|
||||
if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
|
||||
goto error;
|
||||
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup);
|
||||
/* Check if unaligned 32bit SHM_SHARED access works properly.
|
||||
* However, don't bail out on failure, because it's noncritical. */
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788);
|
||||
if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344)
|
||||
b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n");
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD);
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 ||
|
||||
b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD ||
|
||||
b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB ||
|
||||
b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788)
|
||||
b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n");
|
||||
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
|
||||
|
||||
if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
|
||||
/* The 32bit register shadows the two 16bit registers
|
||||
@ -4871,7 +4891,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
|
||||
if (b43_status(dev) < B43_STAT_INITIALIZED)
|
||||
return;
|
||||
b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
|
||||
queue_work(dev->wl->hw->workqueue, &dev->restart_work);
|
||||
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -240,6 +240,13 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
dev->phy.ops->phy_write(dev, reg, value);
|
||||
}
|
||||
|
||||
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
|
||||
{
|
||||
assert_mac_suspended(dev);
|
||||
dev->phy.ops->phy_write(dev, destreg,
|
||||
dev->phy.ops->phy_read(dev, srcreg));
|
||||
}
|
||||
|
||||
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
@ -352,7 +359,7 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
|
||||
|
||||
/* We must adjust the transmission power in hardware.
|
||||
* Schedule b43_phy_txpower_adjust_work(). */
|
||||
queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
|
||||
ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
|
||||
}
|
||||
|
||||
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
|
||||
|
@ -290,6 +290,11 @@ u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
|
||||
*/
|
||||
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
|
||||
|
||||
/**
|
||||
* b43_phy_copy - copy contents of 16bit PHY register to another
|
||||
*/
|
||||
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg);
|
||||
|
||||
/**
|
||||
* b43_phy_mask - Mask a PHY register with a mask
|
||||
*/
|
||||
|
@ -66,7 +66,99 @@ static void lpphy_table_init(struct b43_wldev *dev)
|
||||
|
||||
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
|
||||
{
|
||||
B43_WARN_ON(1);//TODO rev < 2 not supported, yet.
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
u16 tmp, tmp2;
|
||||
|
||||
if (dev->phy.rev == 1 &&
|
||||
(bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900);
|
||||
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 ||
|
||||
(bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
|
||||
(bus->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);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
|
||||
} else if (dev->phy.rev == 1 ||
|
||||
(bus->sprom.boardflags_lo & B43_BFL_FEM)) {
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300);
|
||||
} else {
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
|
||||
}
|
||||
if (dev->phy.rev == 1) {
|
||||
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
|
||||
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
|
||||
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
|
||||
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
|
||||
}
|
||||
if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
|
||||
(bus->chip_id == 0x5354) &&
|
||||
(bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
|
||||
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
|
||||
b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
|
||||
b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
|
||||
b43_hf_write(dev, b43_hf_read(dev) | 0x0800ULL << 32);
|
||||
}
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
|
||||
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040);
|
||||
b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400);
|
||||
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00);
|
||||
b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007);
|
||||
b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003);
|
||||
b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020);
|
||||
b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
|
||||
} else { /* 5GHz */
|
||||
b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF);
|
||||
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF);
|
||||
}
|
||||
if (dev->phy.rev == 1) {
|
||||
tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
|
||||
tmp2 = (tmp & 0x03E0) >> 5;
|
||||
tmp2 |= tmp << 5;
|
||||
b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
|
||||
tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0);
|
||||
tmp2 = (tmp & 0x1F00) >> 8;
|
||||
tmp2 |= tmp << 5;
|
||||
b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
|
||||
tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
|
||||
tmp2 = tmp & 0x00FF;
|
||||
tmp2 |= tmp << 8;
|
||||
b43_phy_write(dev, B43_LPPHY_4C5, tmp2);
|
||||
}
|
||||
}
|
||||
|
||||
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
|
||||
|
@ -273,12 +273,19 @@
|
||||
#define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */
|
||||
#define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */
|
||||
#define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */
|
||||
#define B43_LPPHY_TRLOOKUP3 B43_PHY_OFDM(0xBB) /* TRLookup3 */
|
||||
#define B43_LPPHY_TRLOOKUP4 B43_PHY_OFDM(0xBC) /* TRLookup4 */
|
||||
#define B43_LPPHY_TR_LOOKUP_3 B43_PHY_OFDM(0xBB) /* TR Lookup 3 */
|
||||
#define B43_LPPHY_TR_LOOKUP_4 B43_PHY_OFDM(0xBC) /* TR Lookup 4 */
|
||||
#define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */
|
||||
#define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */
|
||||
#define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */
|
||||
#define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */
|
||||
#define B43_LPPHY_4C3 B43_PHY_OFDM(0xC3) /* unknown, used during BB init */
|
||||
#define B43_LPPHY_4C4 B43_PHY_OFDM(0xC4) /* unknown, used during BB init */
|
||||
#define B43_LPPHY_4C5 B43_PHY_OFDM(0xC5) /* unknown, used during BB init */
|
||||
#define B43_LPPHY_TR_LOOKUP_5 B43_PHY_OFDM(0xC7) /* TR Lookup 5 */
|
||||
#define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
|
||||
#define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
|
||||
#define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
|
||||
|
||||
|
||||
|
||||
|
@ -137,7 +137,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
|
||||
b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
|
||||
msleep(1);
|
||||
if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) {
|
||||
if ((sprom->revision != 4) ||
|
||||
!(sprom->boardflags_hi & B43_BFH_RSSIINV)) {
|
||||
if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
|
||||
(binfo->type != 0x46D) ||
|
||||
(binfo->rev < 0x41)) {
|
||||
|
@ -783,7 +783,7 @@ void b43_pio_rx(struct b43_pio_rxqueue *q)
|
||||
{
|
||||
/* Due to latency issues we must run the RX path in
|
||||
* a workqueue to be able to schedule between packets. */
|
||||
queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
|
||||
ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
|
||||
}
|
||||
|
||||
static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
|
||||
|
@ -1366,15 +1366,25 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
|
||||
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
B43legacy_WARN_ON(!ring->tx);
|
||||
if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
|
||||
b43legacywarn(dev->wl, "DMA queue overflow\n");
|
||||
|
||||
if (unlikely(ring->stopped)) {
|
||||
/* We get here only because of a bug in mac80211.
|
||||
* Because of a race, one packet may be queued after
|
||||
* the queue is stopped, thus we got called when we shouldn't.
|
||||
* For now, just refuse the transmit. */
|
||||
if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
|
||||
b43legacyerr(dev->wl, "Packet after queue stopped\n");
|
||||
err = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) {
|
||||
/* If we get here, we have a real error with the queue
|
||||
* full, but queues not stopped. */
|
||||
b43legacyerr(dev->wl, "DMA queue overflow\n");
|
||||
err = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
/* Check if the queue was stopped in mac80211,
|
||||
* but we got called nevertheless.
|
||||
* That would be a mac80211 bug. */
|
||||
B43legacy_BUG_ON(ring->stopped);
|
||||
|
||||
err = dma_tx_fragment(ring, skb);
|
||||
if (unlikely(err == -ENOKEY)) {
|
||||
|
@ -1252,7 +1252,7 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
|
||||
wl->current_beacon = beacon;
|
||||
wl->beacon0_uploaded = 0;
|
||||
wl->beacon1_uploaded = 0;
|
||||
queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
|
||||
ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
|
||||
}
|
||||
|
||||
static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
|
||||
@ -2300,7 +2300,7 @@ static void b43legacy_periodic_work_handler(struct work_struct *work)
|
||||
delay = msecs_to_jiffies(50);
|
||||
else
|
||||
delay = round_jiffies_relative(HZ * 15);
|
||||
queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
|
||||
ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
@ -2311,7 +2311,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
|
||||
|
||||
dev->periodic_state = 0;
|
||||
INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
|
||||
queue_delayed_work(dev->wl->hw->workqueue, work, 0);
|
||||
ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
|
||||
}
|
||||
|
||||
/* Validate access to the chip (SHM) */
|
||||
@ -3885,7 +3885,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev,
|
||||
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
|
||||
return;
|
||||
b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
|
||||
queue_work(dev->wl->hw->workqueue, &dev->restart_work);
|
||||
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -73,6 +73,18 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
|
||||
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
|
||||
}
|
||||
|
||||
/* NIC configuration for 1000 series */
|
||||
static void iwl1000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl5000_nic_config(priv);
|
||||
|
||||
/* Setting digital SVR for 1000 card to 1.32V */
|
||||
/* locking is acquired in iwl_set_bits_mask_prph() function */
|
||||
iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
|
||||
APMG_SVR_DIGITAL_VOLTAGE_1_32,
|
||||
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl1000_lib = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
|
||||
@ -95,7 +107,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.config = iwl1000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
|
@ -198,6 +198,7 @@ int iwl5000_apm_reset(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
|
||||
/* NIC configuration for 5000 series and up */
|
||||
void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -239,18 +240,11 @@ void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) {
|
||||
/* Setting digital SVR for 1000 card to 1.32V */
|
||||
iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
|
||||
APMG_SVR_DIGITAL_VOLTAGE_1_32,
|
||||
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* EEPROM
|
||||
*/
|
||||
|
@ -68,6 +68,24 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
|
||||
}
|
||||
|
||||
/* NIC configuration for 6000 series */
|
||||
static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl5000_nic_config(priv);
|
||||
|
||||
/* no locking required for register write */
|
||||
if (priv->cfg->pa_type == IWL_PA_HYBRID) {
|
||||
/* 2x2 hybrid phy type */
|
||||
iwl_write32(priv, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB);
|
||||
} else if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
|
||||
/* 2x2 IPA phy type */
|
||||
iwl_write32(priv, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
}
|
||||
/* else do nothing, uCode configured */
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl6000_lib = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
|
||||
@ -90,7 +108,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
@ -132,23 +150,11 @@ static struct iwl_ops iwl6000_ops = {
|
||||
.utils = &iwl6000_hcmd_utils,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_2ag_cfg = {
|
||||
.name = "6000 Series 2x2 AG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_2agn_cfg = {
|
||||
/*
|
||||
* "h": Hybrid configuration, use both internal and external Power Amplifier
|
||||
*/
|
||||
struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
@ -162,6 +168,27 @@ struct iwl_cfg iwl6000_2agn_cfg = {
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
@ -178,6 +205,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
@ -194,6 +222,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
@ -210,6 +239,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
|
@ -1291,6 +1291,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
|
||||
size_t len;
|
||||
u32 api_ver, build;
|
||||
u32 inst_size, data_size, init_size, init_data_size, boot_size;
|
||||
u16 eeprom_ver;
|
||||
|
||||
/* Ask kernel firmware_class module to get the boot firmware off disk.
|
||||
* request_firmware() is synchronous, file is in memory on return. */
|
||||
@ -1368,6 +1369,11 @@ static int iwl_read_ucode(struct iwl_priv *priv)
|
||||
if (build)
|
||||
IWL_DEBUG_INFO(priv, "Build %u\n", build);
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM", eeprom_ver);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
priv->ucode_ver);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
|
||||
@ -2483,39 +2489,6 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_version(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct iwl_alive_resp *palive = &priv->card_alive;
|
||||
ssize_t pos = 0;
|
||||
u16 eeprom_ver;
|
||||
|
||||
if (palive->is_valid)
|
||||
pos += sprintf(buf + pos,
|
||||
"fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
|
||||
"fw type: 0x%01X 0x%01X\n",
|
||||
palive->ucode_major, palive->ucode_minor,
|
||||
palive->sw_rev[0], palive->sw_rev[1],
|
||||
palive->ver_type, palive->ver_subtype);
|
||||
else
|
||||
pos += sprintf(buf + pos, "fw not loaded\n");
|
||||
|
||||
if (priv->eeprom) {
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM", eeprom_ver);
|
||||
|
||||
} else {
|
||||
pos += sprintf(buf + pos, "EEPROM not initialzed\n");
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -2779,7 +2752,6 @@ static struct attribute *iwl_sysfs_entries[] = {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
&dev_attr_version.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -3139,15 +3111,12 @@ static struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
|
||||
/* 6000/6050 Series */
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},
|
||||
|
@ -548,9 +548,6 @@ int iwlcore_init_geos(struct iwl_priv *priv)
|
||||
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
/* Save flags for reg domain usage */
|
||||
geo_ch->orig_flags = geo_ch->flags;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
|
||||
ch->channel, geo_ch->center_freq,
|
||||
is_channel_a_band(ch) ? "5.2" : "2.4",
|
||||
@ -1140,7 +1137,6 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_flags_for_band);
|
||||
|
||||
/*
|
||||
* initialize rxon structure with default values from eeprom
|
||||
@ -2291,7 +2287,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
|
||||
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_card_state);
|
||||
|
||||
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
@ -2335,7 +2330,6 @@ void iwl_clear_isr_stats(struct iwl_priv *priv)
|
||||
{
|
||||
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_clear_isr_stats);
|
||||
|
||||
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
|
@ -206,6 +206,7 @@ struct iwl_mod_params {
|
||||
* filename is constructed as fw_name_pre<api>.ucode.
|
||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
@ -226,6 +227,7 @@ struct iwl_mod_params {
|
||||
* iwl_hcmd_utils_ops etc. we accommodate different command structures
|
||||
* and flows between hardware versions (4965/5000) as well as their API
|
||||
* versions.
|
||||
*
|
||||
*/
|
||||
struct iwl_cfg {
|
||||
const char *name;
|
||||
@ -242,6 +244,7 @@ struct iwl_cfg {
|
||||
u8 valid_rx_ant;
|
||||
bool need_pll_cfg;
|
||||
bool use_isr_legacy;
|
||||
enum iwl_pa_type pa_type;
|
||||
};
|
||||
|
||||
/***************************
|
||||
|
@ -91,7 +91,8 @@
|
||||
#define CSR_EEPROM_GP (CSR_BASE+0x030)
|
||||
#define CSR_OTP_GP_REG (CSR_BASE+0x034)
|
||||
#define CSR_GIO_REG (CSR_BASE+0x03C)
|
||||
#define CSR_GP_UCODE (CSR_BASE+0x044)
|
||||
#define CSR_GP_UCODE_REG (CSR_BASE+0x048)
|
||||
#define CSR_GP_DRIVER_REG (CSR_BASE+0x050)
|
||||
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
|
||||
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
|
||||
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
|
||||
@ -245,6 +246,13 @@
|
||||
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
|
||||
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
|
||||
|
||||
/* GP Driver */
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
|
||||
|
||||
|
||||
/* GI Chicken Bits */
|
||||
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
|
||||
#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
|
||||
|
@ -56,8 +56,8 @@ extern struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_bg_cfg;
|
||||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl6000_2ag_cfg;
|
||||
extern struct iwl_cfg iwl6000_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000h_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_3agn_cfg;
|
||||
@ -888,6 +888,19 @@ enum iwl_nvm_type {
|
||||
NVM_DEVICE_TYPE_OTP,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum iwl_pa_type - Power Amplifier type
|
||||
* @IWL_PA_SYSTEM: based on uCode configuration
|
||||
* @IWL_PA_HYBRID: use both Internal and external PA
|
||||
* @IWL_PA_INTERNAL: use Internal only
|
||||
*/
|
||||
enum iwl_pa_type {
|
||||
IWL_PA_SYSTEM = 0,
|
||||
IWL_PA_HYBRID = 1,
|
||||
IWL_PA_INTERNAL = 2,
|
||||
};
|
||||
|
||||
/* interrupt statistics */
|
||||
struct isr_statistics {
|
||||
u32 hw;
|
||||
|
@ -335,7 +335,6 @@ void iwl_leds_background(struct iwl_priv *priv)
|
||||
priv->last_blink_time = jiffies;
|
||||
priv->last_blink_rate = blink_idx;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_leds_background);
|
||||
|
||||
/* Register all led handler */
|
||||
int iwl_leds_register(struct iwl_priv *priv)
|
||||
|
@ -406,7 +406,6 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
rxq->free_count = 0;
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_queue_reset);
|
||||
|
||||
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
{
|
||||
|
@ -464,7 +464,6 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_remove_station);
|
||||
|
||||
/**
|
||||
* iwl_clear_stations_table - Clear the driver's station table
|
||||
|
@ -970,6 +970,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
out_cmd = txq->cmd[idx];
|
||||
out_meta = &txq->meta[idx];
|
||||
|
||||
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
|
||||
out_meta->flags = cmd->flags;
|
||||
if (cmd->flags & CMD_WANT_SKB)
|
||||
out_meta->source = cmd;
|
||||
|
@ -484,6 +484,8 @@ static int iwm_set_auth_type(struct iwm_priv *iwm,
|
||||
|
||||
static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
|
||||
{
|
||||
IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
|
||||
|
||||
if (!wpa_version) {
|
||||
iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
|
||||
return 0;
|
||||
@ -508,6 +510,9 @@ static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
|
||||
cipher);
|
||||
|
||||
switch (cipher) {
|
||||
case IW_AUTH_CIPHER_NONE:
|
||||
*profile_cipher = UMAC_CIPHER_TYPE_NONE;
|
||||
@ -584,11 +589,11 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
iwm->umac_profile->bss_num = 0;
|
||||
}
|
||||
|
||||
ret = iwm_set_auth_type(iwm, sme->auth_type);
|
||||
ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
|
||||
ret = iwm_set_auth_type(iwm, sme->auth_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -526,19 +526,6 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
|
||||
{
|
||||
struct iwm_umac_tx_key_id tx_key_id;
|
||||
|
||||
tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
|
||||
tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
|
||||
sizeof(struct iwm_umac_wifi_if));
|
||||
|
||||
tx_key_id.key_idx = key_idx;
|
||||
|
||||
return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
|
||||
}
|
||||
|
||||
static int iwm_check_profile(struct iwm_priv *iwm)
|
||||
{
|
||||
if (!iwm->umac_profile_active)
|
||||
@ -572,6 +559,32 @@ static int iwm_check_profile(struct iwm_priv *iwm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
|
||||
{
|
||||
struct iwm_umac_tx_key_id tx_key_id;
|
||||
int ret;
|
||||
|
||||
ret = iwm_check_profile(iwm);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* UMAC only allows to set default key for WEP and auth type is
|
||||
* NOT 802.1X or RSNA. */
|
||||
if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
|
||||
iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) ||
|
||||
iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X ||
|
||||
iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK)
|
||||
return 0;
|
||||
|
||||
tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
|
||||
tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
|
||||
sizeof(struct iwm_umac_wifi_if));
|
||||
|
||||
tx_key_id.key_idx = key_idx;
|
||||
|
||||
return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
|
||||
}
|
||||
|
||||
int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -596,6 +609,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
|
||||
key_idx = key->hdr.key_idx;
|
||||
|
||||
if (!remove) {
|
||||
u8 auth_type = iwm->umac_profile->sec.auth_type;
|
||||
|
||||
IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
|
||||
IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
|
||||
IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
|
||||
@ -618,7 +633,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
|
||||
memcpy(&wep40->key_hdr, key_hdr,
|
||||
sizeof(struct iwm_umac_key_hdr));
|
||||
memcpy(wep40->key, key_data, key_len);
|
||||
wep40->static_key = 1;
|
||||
wep40->static_key =
|
||||
!!((auth_type != UMAC_AUTH_TYPE_8021X) &&
|
||||
(auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
|
||||
|
||||
cmd_size = sizeof(struct iwm_umac_key_wep40);
|
||||
break;
|
||||
@ -632,7 +649,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
|
||||
memcpy(&wep104->key_hdr, key_hdr,
|
||||
sizeof(struct iwm_umac_key_hdr));
|
||||
memcpy(wep104->key, key_data, key_len);
|
||||
wep104->static_key = 1;
|
||||
wep104->static_key =
|
||||
!!((auth_type != UMAC_AUTH_TYPE_8021X) &&
|
||||
(auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
|
||||
|
||||
cmd_size = sizeof(struct iwm_umac_key_wep104);
|
||||
break;
|
||||
|
@ -376,7 +376,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
|
||||
err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
|
||||
if (err)
|
||||
return err;
|
||||
if (rval != mode) {
|
||||
if ((rval & 0xF) != mode) {
|
||||
lbs_pr_err("Can't read bus mode register.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1728,6 +1728,8 @@ static int lbs_set_auth(struct net_device *dev,
|
||||
}
|
||||
|
||||
switch (dwrq->flags & IW_AUTH_INDEX) {
|
||||
case IW_AUTH_PRIVACY_INVOKED:
|
||||
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
|
||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||
case IW_AUTH_CIPHER_PAIRWISE:
|
||||
case IW_AUTH_CIPHER_GROUP:
|
||||
|
@ -156,7 +156,48 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int orinoco_set_channel(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct orinoco_private *priv = wiphy_priv(wiphy);
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
int channel;
|
||||
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
if (channel_type != NL80211_CHAN_NO_HT)
|
||||
return -EINVAL;
|
||||
|
||||
if (chan->band != IEEE80211_BAND_2GHZ)
|
||||
return -EINVAL;
|
||||
|
||||
channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
|
||||
|
||||
if ((channel < 1) || (channel > NUM_CHANNELS) ||
|
||||
!(priv->channel_mask & (1 << (channel-1))))
|
||||
return -EINVAL;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
priv->channel = channel;
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Fast channel change - no commit if successful */
|
||||
hermes_t *hw = &priv->hw;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_SET_CHANNEL,
|
||||
channel, NULL);
|
||||
}
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct cfg80211_ops orinoco_cfg_ops = {
|
||||
.change_virtual_intf = orinoco_change_vif,
|
||||
.set_channel = orinoco_set_channel,
|
||||
.scan = orinoco_scan,
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ static void p54_update_leds(struct work_struct *work)
|
||||
wiphy_name(priv->hw->wiphy), err);
|
||||
|
||||
if (rerun)
|
||||
queue_delayed_work(priv->hw->workqueue, &priv->led_work,
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
|
||||
msecs_to_jiffies(blink_delay));
|
||||
}
|
||||
|
||||
@ -78,8 +78,7 @@ static void p54_led_brightness_set(struct led_classdev *led_dev,
|
||||
|
||||
if ((brightness) && (led->registered)) {
|
||||
led->toggled++;
|
||||
queue_delayed_work(priv->hw->workqueue, &priv->led_work,
|
||||
HZ/10);
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ static int p54_start(struct ieee80211_hw *dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
queue_delayed_work(dev->workqueue, &priv->work, 0);
|
||||
ieee80211_queue_delayed_work(dev, &priv->work, 0);
|
||||
|
||||
priv->softled_state = 0;
|
||||
err = p54_set_leds(priv);
|
||||
|
@ -391,7 +391,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config)
|
||||
struct spi_device *spi = config;
|
||||
struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
|
||||
|
||||
queue_work(priv->hw->workqueue, &priv->work);
|
||||
ieee80211_queue_work(priv->hw, &priv->work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -479,7 +479,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
list_add_tail(&di->tx_list, &priv->tx_pending);
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
|
||||
queue_work(priv->hw->workqueue, &priv->work);
|
||||
ieee80211_queue_work(priv->hw, &priv->work);
|
||||
}
|
||||
|
||||
static void p54spi_work(struct work_struct *work)
|
||||
|
@ -380,7 +380,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
|
||||
|
||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
|
||||
queue_delayed_work(priv->hw->workqueue, &priv->work,
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->work,
|
||||
msecs_to_jiffies(P54_STATISTICS_UPDATE));
|
||||
|
||||
return -1;
|
||||
|
@ -100,7 +100,6 @@ MODULE_PARM_DESC(workaround_interval,
|
||||
#define OID_GEN_RCV_ERROR cpu_to_le32(0x00020104)
|
||||
#define OID_GEN_RCV_NO_BUFFER cpu_to_le32(0x00020105)
|
||||
|
||||
#define OID_802_3_PERMANENT_ADDRESS cpu_to_le32(0x01010101)
|
||||
#define OID_802_3_CURRENT_ADDRESS cpu_to_le32(0x01010102)
|
||||
#define OID_802_3_MULTICAST_LIST cpu_to_le32(0x01010103)
|
||||
#define OID_802_3_MAXIMUM_LIST_SIZE cpu_to_le32(0x01010104)
|
||||
@ -202,6 +201,24 @@ enum ndis_80211_priv_filter {
|
||||
NDIS_80211_PRIV_8021X_WEP
|
||||
};
|
||||
|
||||
enum ndis_80211_status_type {
|
||||
NDIS_80211_STATUSTYPE_AUTHENTICATION,
|
||||
NDIS_80211_STATUSTYPE_MEDIASTREAMMODE,
|
||||
NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST,
|
||||
NDIS_80211_STATUSTYPE_RADIOSTATE,
|
||||
};
|
||||
|
||||
enum ndis_80211_media_stream_mode {
|
||||
NDIS_80211_MEDIA_STREAM_OFF,
|
||||
NDIS_80211_MEDIA_STREAM_ON
|
||||
};
|
||||
|
||||
enum ndis_80211_radio_status {
|
||||
NDIS_80211_RADIO_STATUS_ON,
|
||||
NDIS_80211_RADIO_STATUS_HARDWARE_OFF,
|
||||
NDIS_80211_RADIO_STATUS_SOFTWARE_OFF,
|
||||
};
|
||||
|
||||
enum ndis_80211_addkey_bits {
|
||||
NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28),
|
||||
NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29),
|
||||
@ -214,6 +231,35 @@ enum ndis_80211_addwep_bits {
|
||||
NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
|
||||
};
|
||||
|
||||
struct ndis_80211_auth_request {
|
||||
__le32 length;
|
||||
u8 bssid[6];
|
||||
u8 padding[2];
|
||||
__le32 flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_pmkid_candidate {
|
||||
u8 bssid[6];
|
||||
u8 padding[2];
|
||||
__le32 flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_pmkid_cand_list {
|
||||
__le32 version;
|
||||
__le32 num_candidates;
|
||||
struct ndis_80211_pmkid_candidate candidate_list[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_status_indication {
|
||||
__le32 status_type;
|
||||
union {
|
||||
enum ndis_80211_media_stream_mode media_stream_mode;
|
||||
enum ndis_80211_radio_status radio_status;
|
||||
struct ndis_80211_auth_request auth_request[0];
|
||||
struct ndis_80211_pmkid_cand_list cand_list;
|
||||
} u;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_ssid {
|
||||
__le32 length;
|
||||
u8 essid[NDIS_802_11_LENGTH_SSID];
|
||||
@ -281,6 +327,7 @@ struct ndis_80211_remove_key {
|
||||
__le32 size;
|
||||
__le32 index;
|
||||
u8 bssid[6];
|
||||
u8 padding[2];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_config_param {
|
||||
@ -366,6 +413,15 @@ static const struct ieee80211_rate rndis_rates[] = {
|
||||
{ .bitrate = 540 }
|
||||
};
|
||||
|
||||
struct rndis_wlan_encr_key {
|
||||
int len;
|
||||
int cipher;
|
||||
u8 material[32];
|
||||
u8 bssid[ETH_ALEN];
|
||||
bool pairwise;
|
||||
bool tx_key;
|
||||
};
|
||||
|
||||
/* RNDIS device private data */
|
||||
struct rndis_wlan_private {
|
||||
struct usbnet *usbdev;
|
||||
@ -409,9 +465,7 @@ struct rndis_wlan_private {
|
||||
|
||||
/* encryption stuff */
|
||||
int encr_tx_key_index;
|
||||
char encr_keys[4][32];
|
||||
int encr_key_len[4];
|
||||
char encr_key_wpa[4];
|
||||
struct rndis_wlan_encr_key encr_keys[4];
|
||||
int wpa_version;
|
||||
int wpa_keymgmt;
|
||||
int wpa_authalg;
|
||||
@ -478,6 +532,77 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
|
||||
}
|
||||
|
||||
|
||||
static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
|
||||
{
|
||||
int cipher = priv->encr_keys[idx].cipher;
|
||||
|
||||
return (cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
cipher == WLAN_CIPHER_SUITE_TKIP);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *oid_to_string(__le32 oid)
|
||||
{
|
||||
switch (oid) {
|
||||
#define OID_STR(oid) case oid: return(#oid)
|
||||
/* from rndis_host.h */
|
||||
OID_STR(OID_802_3_PERMANENT_ADDRESS);
|
||||
OID_STR(OID_GEN_MAXIMUM_FRAME_SIZE);
|
||||
OID_STR(OID_GEN_CURRENT_PACKET_FILTER);
|
||||
OID_STR(OID_GEN_PHYSICAL_MEDIUM);
|
||||
|
||||
/* from rndis_wlan.c */
|
||||
OID_STR(OID_GEN_LINK_SPEED);
|
||||
OID_STR(OID_GEN_RNDIS_CONFIG_PARAMETER);
|
||||
|
||||
OID_STR(OID_GEN_XMIT_OK);
|
||||
OID_STR(OID_GEN_RCV_OK);
|
||||
OID_STR(OID_GEN_XMIT_ERROR);
|
||||
OID_STR(OID_GEN_RCV_ERROR);
|
||||
OID_STR(OID_GEN_RCV_NO_BUFFER);
|
||||
|
||||
OID_STR(OID_802_3_CURRENT_ADDRESS);
|
||||
OID_STR(OID_802_3_MULTICAST_LIST);
|
||||
OID_STR(OID_802_3_MAXIMUM_LIST_SIZE);
|
||||
|
||||
OID_STR(OID_802_11_BSSID);
|
||||
OID_STR(OID_802_11_SSID);
|
||||
OID_STR(OID_802_11_INFRASTRUCTURE_MODE);
|
||||
OID_STR(OID_802_11_ADD_WEP);
|
||||
OID_STR(OID_802_11_REMOVE_WEP);
|
||||
OID_STR(OID_802_11_DISASSOCIATE);
|
||||
OID_STR(OID_802_11_AUTHENTICATION_MODE);
|
||||
OID_STR(OID_802_11_PRIVACY_FILTER);
|
||||
OID_STR(OID_802_11_BSSID_LIST_SCAN);
|
||||
OID_STR(OID_802_11_ENCRYPTION_STATUS);
|
||||
OID_STR(OID_802_11_ADD_KEY);
|
||||
OID_STR(OID_802_11_REMOVE_KEY);
|
||||
OID_STR(OID_802_11_ASSOCIATION_INFORMATION);
|
||||
OID_STR(OID_802_11_PMKID);
|
||||
OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED);
|
||||
OID_STR(OID_802_11_NETWORK_TYPE_IN_USE);
|
||||
OID_STR(OID_802_11_TX_POWER_LEVEL);
|
||||
OID_STR(OID_802_11_RSSI);
|
||||
OID_STR(OID_802_11_RSSI_TRIGGER);
|
||||
OID_STR(OID_802_11_FRAGMENTATION_THRESHOLD);
|
||||
OID_STR(OID_802_11_RTS_THRESHOLD);
|
||||
OID_STR(OID_802_11_SUPPORTED_RATES);
|
||||
OID_STR(OID_802_11_CONFIGURATION);
|
||||
OID_STR(OID_802_11_BSSID_LIST);
|
||||
#undef OID_STR
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
#else
|
||||
static const char *oid_to_string(__le32 oid)
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* translate error code */
|
||||
static int rndis_error_status(__le32 rndis_status)
|
||||
{
|
||||
@ -533,11 +658,21 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
||||
u.get->oid = oid;
|
||||
|
||||
ret = rndis_command(dev, u.header, buflen);
|
||||
if (ret < 0)
|
||||
devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d "
|
||||
"(%08x)", oid_to_string(oid), ret,
|
||||
le32_to_cpu(u.get_c->status));
|
||||
|
||||
if (ret == 0) {
|
||||
ret = le32_to_cpu(u.get_c->len);
|
||||
*len = (*len > ret) ? ret : *len;
|
||||
memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
|
||||
ret = rndis_error_status(u.get_c->status);
|
||||
|
||||
if (ret < 0)
|
||||
devdbg(dev, "rndis_query_oid(%s): device returned "
|
||||
"error, 0x%08x (%d)", oid_to_string(oid),
|
||||
le32_to_cpu(u.get_c->status), ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->command_lock);
|
||||
@ -583,9 +718,20 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
|
||||
memcpy(u.buf + sizeof(*u.set), data, len);
|
||||
|
||||
ret = rndis_command(dev, u.header, buflen);
|
||||
if (ret == 0)
|
||||
if (ret < 0)
|
||||
devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d "
|
||||
"(%08x)", oid_to_string(oid), ret,
|
||||
le32_to_cpu(u.set_c->status));
|
||||
|
||||
if (ret == 0) {
|
||||
ret = rndis_error_status(u.set_c->status);
|
||||
|
||||
if (ret < 0)
|
||||
devdbg(dev, "rndis_set_oid(%s): device returned error, "
|
||||
"0x%08x (%d)", oid_to_string(oid),
|
||||
le32_to_cpu(u.set_c->status), ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->command_lock);
|
||||
|
||||
if (u.buf != priv->command_buffer)
|
||||
@ -594,6 +740,28 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
|
||||
}
|
||||
|
||||
|
||||
static int rndis_reset(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct rndis_reset *reset;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->command_lock);
|
||||
|
||||
reset = (void *)priv->command_buffer;
|
||||
memset(reset, 0, sizeof(*reset));
|
||||
reset->msg_type = RNDIS_MSG_RESET;
|
||||
reset->msg_len = cpu_to_le32(sizeof(*reset));
|
||||
ret = rndis_command(usbdev, (void *)reset, CONTROL_BUFFER_SIZE);
|
||||
|
||||
mutex_unlock(&priv->command_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Specs say that we can only set config parameters only soon after device
|
||||
* initialization.
|
||||
@ -743,8 +911,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
|
||||
/*
|
||||
* common functions
|
||||
*/
|
||||
static int
|
||||
add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
|
||||
static void restore_keys(struct usbnet *usbdev);
|
||||
|
||||
static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
|
||||
{
|
||||
@ -963,7 +1130,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode);
|
||||
|
||||
@ -978,14 +1145,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
|
||||
/* NDIS drivers clear keys when infrastructure mode is
|
||||
* changed. But Linux tools assume otherwise. So set the
|
||||
* keys */
|
||||
if (priv->wpa_keymgmt == 0 ||
|
||||
priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
|
||||
add_wep_key(usbdev, priv->encr_keys[i],
|
||||
priv->encr_key_len[i], i);
|
||||
}
|
||||
}
|
||||
restore_keys(usbdev);
|
||||
|
||||
priv->infra_mode = mode;
|
||||
return 0;
|
||||
@ -1052,11 +1212,16 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_wep_key ndis_key;
|
||||
int ret;
|
||||
int cipher, ret;
|
||||
|
||||
if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
|
||||
if ((key_len != 5 || key_len != 13) || index < 0 || index > 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (key_len == 5)
|
||||
cipher = WLAN_CIPHER_SUITE_WEP40;
|
||||
else
|
||||
cipher = WLAN_CIPHER_SUITE_WEP104;
|
||||
|
||||
memset(&ndis_key, 0, sizeof(ndis_key));
|
||||
|
||||
ndis_key.size = cpu_to_le32(sizeof(ndis_key));
|
||||
@ -1081,30 +1246,44 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->encr_key_len[index] = key_len;
|
||||
priv->encr_key_wpa[index] = 0;
|
||||
memcpy(&priv->encr_keys[index], key, key_len);
|
||||
priv->encr_keys[index].len = key_len;
|
||||
priv->encr_keys[index].cipher = cipher;
|
||||
memcpy(&priv->encr_keys[index].material, key, key_len);
|
||||
memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
int index, const struct sockaddr *addr,
|
||||
const u8 *rx_seq, int alg, int flags)
|
||||
int index, const u8 *addr, const u8 *rx_seq, int cipher,
|
||||
int flags)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_key ndis_key;
|
||||
bool is_addr_ok;
|
||||
int ret;
|
||||
|
||||
if (index < 0 || index >= 4)
|
||||
if (index < 0 || index >= 4) {
|
||||
devdbg(usbdev, "add_wpa_key: index out of range (%i)", index);
|
||||
return -EINVAL;
|
||||
if (key_len > sizeof(ndis_key.material) || key_len < 0)
|
||||
}
|
||||
if (key_len > sizeof(ndis_key.material) || key_len < 0) {
|
||||
devdbg(usbdev, "add_wpa_key: key length out of range (%i)",
|
||||
key_len);
|
||||
return -EINVAL;
|
||||
if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq)
|
||||
}
|
||||
if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) {
|
||||
devdbg(usbdev, "add_wpa_key: recv seq flag without buffer");
|
||||
return -EINVAL;
|
||||
if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr)
|
||||
}
|
||||
is_addr_ok = addr && memcmp(addr, zero_bssid, ETH_ALEN) != 0 &&
|
||||
memcmp(addr, ffff_bssid, ETH_ALEN) != 0;
|
||||
if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) {
|
||||
devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
|
||||
!!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY),
|
||||
@ -1118,7 +1297,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
ndis_key.length = cpu_to_le32(key_len);
|
||||
ndis_key.index = cpu_to_le32(index) | flags;
|
||||
|
||||
if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) {
|
||||
if (cipher == WLAN_CIPHER_SUITE_TKIP && key_len == 32) {
|
||||
/* wpa_supplicant gives us the Michael MIC RX/TX keys in
|
||||
* different order than NDIS spec, so swap the order here. */
|
||||
memcpy(ndis_key.material, key, 16);
|
||||
@ -1132,7 +1311,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
|
||||
if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
|
||||
/* pairwise key */
|
||||
memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
|
||||
memcpy(ndis_key.bssid, addr, ETH_ALEN);
|
||||
} else {
|
||||
/* group key */
|
||||
if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
|
||||
@ -1147,8 +1326,14 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
priv->encr_key_len[index] = key_len;
|
||||
priv->encr_key_wpa[index] = 1;
|
||||
memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
|
||||
priv->encr_keys[index].len = key_len;
|
||||
priv->encr_keys[index].cipher = cipher;
|
||||
memcpy(&priv->encr_keys[index].material, key, key_len);
|
||||
if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY)
|
||||
memcpy(&priv->encr_keys[index].bssid, ndis_key.bssid, ETH_ALEN);
|
||||
else
|
||||
memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
|
||||
|
||||
if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY)
|
||||
priv->encr_tx_key_index = index;
|
||||
@ -1157,25 +1342,74 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
}
|
||||
|
||||
|
||||
static int restore_key(struct usbnet *usbdev, int key_idx)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct rndis_wlan_encr_key key;
|
||||
int flags;
|
||||
|
||||
key = priv->encr_keys[key_idx];
|
||||
|
||||
devdbg(usbdev, "restore_key: %i:%s:%i", key_idx,
|
||||
is_wpa_key(priv, key_idx) ? "wpa" : "wep",
|
||||
key.len);
|
||||
|
||||
if (key.len == 0)
|
||||
return 0;
|
||||
|
||||
if (is_wpa_key(priv, key_idx)) {
|
||||
flags = 0;
|
||||
|
||||
/*if (priv->encr_tx_key_index == key_idx)
|
||||
flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/
|
||||
|
||||
if (memcmp(key.bssid, zero_bssid, ETH_ALEN) != 0 &&
|
||||
memcmp(key.bssid, ffff_bssid, ETH_ALEN) != 0)
|
||||
flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
|
||||
|
||||
return add_wpa_key(usbdev, key.material, key.len, key_idx,
|
||||
key.bssid, NULL, key.cipher, flags);
|
||||
}
|
||||
|
||||
return add_wep_key(usbdev, key.material, key.len, key_idx);
|
||||
}
|
||||
|
||||
|
||||
static void restore_keys(struct usbnet *usbdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
restore_key(usbdev, i);
|
||||
}
|
||||
|
||||
|
||||
static void clear_key(struct rndis_wlan_private *priv, int idx)
|
||||
{
|
||||
memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
|
||||
}
|
||||
|
||||
|
||||
/* remove_key is for both wep and wpa */
|
||||
static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_remove_key remove_key;
|
||||
__le32 keyindex;
|
||||
bool is_wpa;
|
||||
int ret;
|
||||
|
||||
if (priv->encr_key_len[index] == 0)
|
||||
if (priv->encr_keys[index].len == 0)
|
||||
return 0;
|
||||
|
||||
priv->encr_key_len[index] = 0;
|
||||
priv->encr_key_wpa[index] = 0;
|
||||
memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
|
||||
is_wpa = is_wpa_key(priv, index);
|
||||
|
||||
if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
|
||||
priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
|
||||
priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
|
||||
priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
|
||||
devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep",
|
||||
priv->encr_keys[index].len);
|
||||
|
||||
clear_key(priv, index);
|
||||
|
||||
if (is_wpa) {
|
||||
remove_key.size = cpu_to_le32(sizeof(remove_key));
|
||||
remove_key.index = cpu_to_le32(index);
|
||||
if (bssid) {
|
||||
@ -1484,6 +1718,9 @@ static void rndis_get_scan_results(struct work_struct *work)
|
||||
|
||||
devdbg(usbdev, "get_scan_results");
|
||||
|
||||
if (!priv->scan_request)
|
||||
return;
|
||||
|
||||
ret = rndis_check_bssid_list(usbdev);
|
||||
|
||||
cfg80211_scan_done(priv->scan_request, ret < 0);
|
||||
@ -1716,8 +1953,9 @@ static int rndis_iw_set_encode(struct net_device *dev,
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct rndis_wlan_encr_key key;
|
||||
int ret, index, key_len;
|
||||
u8 *key;
|
||||
u8 *keybuf;
|
||||
|
||||
index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
|
||||
|
||||
@ -1752,17 +1990,18 @@ static int rndis_iw_set_encode(struct net_device *dev,
|
||||
|
||||
if (wrqu->data.length > 0) {
|
||||
key_len = wrqu->data.length;
|
||||
key = extra;
|
||||
keybuf = extra;
|
||||
} else {
|
||||
/* must be set as tx key */
|
||||
if (priv->encr_key_len[index] == 0)
|
||||
if (priv->encr_keys[index].len == 0)
|
||||
return -EINVAL;
|
||||
key_len = priv->encr_key_len[index];
|
||||
key = priv->encr_keys[index];
|
||||
key_len = key.len;
|
||||
keybuf = key.material;
|
||||
priv->encr_tx_key_index = index;
|
||||
}
|
||||
|
||||
if (add_wep_key(usbdev, key, key_len, index) != 0)
|
||||
if (add_wep_key(usbdev, keybuf, key_len, index) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (index == priv->encr_tx_key_index)
|
||||
@ -1779,7 +2018,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int keyidx, flags;
|
||||
int keyidx, flags, cipher;
|
||||
|
||||
keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
|
||||
|
||||
@ -1789,8 +2028,10 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
else
|
||||
keyidx = priv->encr_tx_key_index;
|
||||
|
||||
if (keyidx < 0 || keyidx >= 4)
|
||||
if (keyidx < 0 || keyidx >= 4) {
|
||||
devwarn(usbdev, "encryption index out of range (%u)", keyidx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ext->alg == WPA_ALG_WEP) {
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
|
||||
@ -1798,10 +2039,19 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
|
||||
}
|
||||
|
||||
cipher = -1;
|
||||
if (ext->alg == IW_ENCODE_ALG_TKIP)
|
||||
cipher = WLAN_CIPHER_SUITE_TKIP;
|
||||
else if (ext->alg == IW_ENCODE_ALG_CCMP)
|
||||
cipher = WLAN_CIPHER_SUITE_CCMP;
|
||||
|
||||
if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
|
||||
ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
|
||||
return remove_key(usbdev, keyidx, NULL);
|
||||
|
||||
if (cipher == -1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
flags = 0;
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
|
||||
flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
|
||||
@ -1810,8 +2060,9 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
|
||||
flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
|
||||
|
||||
return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
|
||||
ext->rx_seq, ext->alg, flags);
|
||||
return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx,
|
||||
(u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
||||
@ -2104,13 +2355,216 @@ static void rndis_wlan_set_multicast_list(struct net_device *dev)
|
||||
queue_work(priv->workqueue, &priv->work);
|
||||
}
|
||||
|
||||
static void rndis_wlan_link_change(struct usbnet *usbdev, int state)
|
||||
|
||||
static void rndis_wlan_auth_indication(struct usbnet *usbdev,
|
||||
struct ndis_80211_status_indication *indication,
|
||||
int len)
|
||||
{
|
||||
u8 *buf;
|
||||
const char *type;
|
||||
int flags, buflen;
|
||||
bool pairwise_error, group_error;
|
||||
struct ndis_80211_auth_request *auth_req;
|
||||
|
||||
/* must have at least one array entry */
|
||||
if (len < offsetof(struct ndis_80211_status_indication, u) +
|
||||
sizeof(struct ndis_80211_auth_request)) {
|
||||
devinfo(usbdev, "authentication indication: "
|
||||
"too short message (%i)", len);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = (void *)&indication->u.auth_request[0];
|
||||
buflen = len - offsetof(struct ndis_80211_status_indication, u);
|
||||
|
||||
while (buflen >= sizeof(*auth_req)) {
|
||||
auth_req = (void *)buf;
|
||||
type = "unknown";
|
||||
flags = le32_to_cpu(auth_req->flags);
|
||||
pairwise_error = false;
|
||||
group_error = false;
|
||||
|
||||
if (flags & 0x1)
|
||||
type = "reauth request";
|
||||
if (flags & 0x2)
|
||||
type = "key update request";
|
||||
if (flags & 0x6) {
|
||||
pairwise_error = true;
|
||||
type = "pairwise_error";
|
||||
}
|
||||
if (flags & 0xe) {
|
||||
group_error = true;
|
||||
type = "group_error";
|
||||
}
|
||||
|
||||
devinfo(usbdev, "authentication indication: %s (0x%08x)", type,
|
||||
le32_to_cpu(auth_req->flags));
|
||||
|
||||
if (pairwise_error || group_error) {
|
||||
union iwreq_data wrqu;
|
||||
struct iw_michaelmicfailure micfailure;
|
||||
|
||||
memset(&micfailure, 0, sizeof(micfailure));
|
||||
if (pairwise_error)
|
||||
micfailure.flags |= IW_MICFAILURE_PAIRWISE;
|
||||
if (group_error)
|
||||
micfailure.flags |= IW_MICFAILURE_GROUP;
|
||||
|
||||
memcpy(micfailure.src_addr.sa_data, auth_req->bssid,
|
||||
ETH_ALEN);
|
||||
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
wrqu.data.length = sizeof(micfailure);
|
||||
wireless_send_event(usbdev->net, IWEVMICHAELMICFAILURE,
|
||||
&wrqu, (u8 *)&micfailure);
|
||||
}
|
||||
|
||||
buflen -= le32_to_cpu(auth_req->length);
|
||||
buf += le32_to_cpu(auth_req->length);
|
||||
}
|
||||
}
|
||||
|
||||
static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev,
|
||||
struct ndis_80211_status_indication *indication,
|
||||
int len)
|
||||
{
|
||||
struct ndis_80211_pmkid_cand_list *cand_list;
|
||||
int list_len, expected_len, i;
|
||||
|
||||
if (len < offsetof(struct ndis_80211_status_indication, u) +
|
||||
sizeof(struct ndis_80211_pmkid_cand_list)) {
|
||||
devinfo(usbdev, "pmkid candidate list indication: "
|
||||
"too short message (%i)", len);
|
||||
return;
|
||||
}
|
||||
|
||||
list_len = le32_to_cpu(indication->u.cand_list.num_candidates) *
|
||||
sizeof(struct ndis_80211_pmkid_candidate);
|
||||
expected_len = sizeof(struct ndis_80211_pmkid_cand_list) + list_len +
|
||||
offsetof(struct ndis_80211_status_indication, u);
|
||||
|
||||
if (len < expected_len) {
|
||||
devinfo(usbdev, "pmkid candidate list indication: "
|
||||
"list larger than buffer (%i < %i)",
|
||||
len, expected_len);
|
||||
return;
|
||||
}
|
||||
|
||||
cand_list = &indication->u.cand_list;
|
||||
|
||||
devinfo(usbdev, "pmkid candidate list indication: "
|
||||
"version %i, candidates %i",
|
||||
le32_to_cpu(cand_list->version),
|
||||
le32_to_cpu(cand_list->num_candidates));
|
||||
|
||||
if (le32_to_cpu(cand_list->version) != 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) {
|
||||
struct iw_pmkid_cand pcand;
|
||||
union iwreq_data wrqu;
|
||||
struct ndis_80211_pmkid_candidate *cand =
|
||||
&cand_list->candidate_list[i];
|
||||
|
||||
devdbg(usbdev, "cand[%i]: flags: 0x%08x, bssid: %pM",
|
||||
i, le32_to_cpu(cand->flags), cand->bssid);
|
||||
|
||||
memset(&pcand, 0, sizeof(pcand));
|
||||
if (le32_to_cpu(cand->flags) & 0x01)
|
||||
pcand.flags |= IW_PMKID_CAND_PREAUTH;
|
||||
pcand.index = i;
|
||||
memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN);
|
||||
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
wrqu.data.length = sizeof(pcand);
|
||||
wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu,
|
||||
(u8 *)&pcand);
|
||||
}
|
||||
}
|
||||
|
||||
static void rndis_wlan_media_specific_indication(struct usbnet *usbdev,
|
||||
struct rndis_indicate *msg, int buflen)
|
||||
{
|
||||
struct ndis_80211_status_indication *indication;
|
||||
int len, offset;
|
||||
|
||||
offset = offsetof(struct rndis_indicate, status) +
|
||||
le32_to_cpu(msg->offset);
|
||||
len = le32_to_cpu(msg->length);
|
||||
|
||||
if (len < 8) {
|
||||
devinfo(usbdev, "media specific indication, "
|
||||
"ignore too short message (%i < 8)", len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset + len > buflen) {
|
||||
devinfo(usbdev, "media specific indication, "
|
||||
"too large to fit to buffer (%i > %i)",
|
||||
offset + len, buflen);
|
||||
return;
|
||||
}
|
||||
|
||||
indication = (void *)((u8 *)msg + offset);
|
||||
|
||||
switch (le32_to_cpu(indication->status_type)) {
|
||||
case NDIS_80211_STATUSTYPE_RADIOSTATE:
|
||||
devinfo(usbdev, "radio state indication: %i",
|
||||
le32_to_cpu(indication->u.radio_status));
|
||||
return;
|
||||
|
||||
case NDIS_80211_STATUSTYPE_MEDIASTREAMMODE:
|
||||
devinfo(usbdev, "media stream mode indication: %i",
|
||||
le32_to_cpu(indication->u.media_stream_mode));
|
||||
return;
|
||||
|
||||
case NDIS_80211_STATUSTYPE_AUTHENTICATION:
|
||||
rndis_wlan_auth_indication(usbdev, indication, len);
|
||||
return;
|
||||
|
||||
case NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST:
|
||||
rndis_wlan_pmkid_cand_list_indication(usbdev, indication, len);
|
||||
return;
|
||||
|
||||
default:
|
||||
devinfo(usbdev, "media specific indication: "
|
||||
"unknown status type 0x%08x",
|
||||
le32_to_cpu(indication->status_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct rndis_indicate *msg = ind;
|
||||
|
||||
switch (msg->status) {
|
||||
case RNDIS_STATUS_MEDIA_CONNECT:
|
||||
devinfo(usbdev, "media connect");
|
||||
|
||||
/* queue work to avoid recursive calls into rndis_command */
|
||||
set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending);
|
||||
set_bit(WORK_LINK_UP, &priv->work_pending);
|
||||
queue_work(priv->workqueue, &priv->work);
|
||||
break;
|
||||
|
||||
case RNDIS_STATUS_MEDIA_DISCONNECT:
|
||||
devinfo(usbdev, "media disconnect");
|
||||
|
||||
/* queue work to avoid recursive calls into rndis_command */
|
||||
set_bit(WORK_LINK_DOWN, &priv->work_pending);
|
||||
queue_work(priv->workqueue, &priv->work);
|
||||
break;
|
||||
|
||||
case RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION:
|
||||
rndis_wlan_media_specific_indication(usbdev, msg, buflen);
|
||||
break;
|
||||
|
||||
default:
|
||||
devinfo(usbdev, "indication: 0x%08x",
|
||||
le32_to_cpu(msg->status));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2457,9 +2911,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
disassociate(usbdev, 1);
|
||||
netif_carrier_off(usbdev->net);
|
||||
|
||||
queue_delayed_work(priv->workqueue, &priv->stats_work,
|
||||
round_jiffies_relative(STATS_UPDATE_JIFFIES));
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -2499,21 +2950,61 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
|
||||
static int rndis_wlan_reset(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int retval;
|
||||
|
||||
devdbg(usbdev, "rndis_wlan_reset");
|
||||
|
||||
retval = rndis_reset(usbdev);
|
||||
if (retval)
|
||||
devwarn(usbdev, "rndis_reset() failed: %d", retval);
|
||||
|
||||
/* rndis_reset cleared multicast list, so restore here.
|
||||
(set_multicast_list() also turns on current packet filter) */
|
||||
set_multicast_list(usbdev);
|
||||
|
||||
queue_delayed_work(priv->workqueue, &priv->stats_work,
|
||||
round_jiffies_relative(STATS_UPDATE_JIFFIES));
|
||||
|
||||
return deauthenticate(usbdev);
|
||||
}
|
||||
|
||||
|
||||
static int rndis_wlan_stop(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int retval;
|
||||
__le32 filter;
|
||||
|
||||
devdbg(usbdev, "rndis_wlan_stop");
|
||||
return disassociate(usbdev, 0);
|
||||
|
||||
retval = disassociate(usbdev, 0);
|
||||
|
||||
priv->work_pending = 0;
|
||||
cancel_delayed_work_sync(&priv->stats_work);
|
||||
cancel_delayed_work_sync(&priv->scan_work);
|
||||
cancel_work_sync(&priv->work);
|
||||
flush_workqueue(priv->workqueue);
|
||||
|
||||
if (priv->scan_request) {
|
||||
cfg80211_scan_done(priv->scan_request, true);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
|
||||
/* Set current packet filter zero to block receiving data packets from
|
||||
device. */
|
||||
filter = 0;
|
||||
rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter,
|
||||
sizeof(filter));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static const struct driver_info bcm4320b_info = {
|
||||
.description = "Wireless RNDIS device, BCM4320b based",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
|
||||
FLAG_AVOID_UNLINK_URBS,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
@ -2522,12 +3013,13 @@ static const struct driver_info bcm4320b_info = {
|
||||
.reset = rndis_wlan_reset,
|
||||
.stop = rndis_wlan_stop,
|
||||
.early_init = bcm4320b_early_init,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
.indication = rndis_wlan_indication,
|
||||
};
|
||||
|
||||
static const struct driver_info bcm4320a_info = {
|
||||
.description = "Wireless RNDIS device, BCM4320a based",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
|
||||
FLAG_AVOID_UNLINK_URBS,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
@ -2536,12 +3028,13 @@ static const struct driver_info bcm4320a_info = {
|
||||
.reset = rndis_wlan_reset,
|
||||
.stop = rndis_wlan_stop,
|
||||
.early_init = bcm4320a_early_init,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
.indication = rndis_wlan_indication,
|
||||
};
|
||||
|
||||
static const struct driver_info rndis_wlan_info = {
|
||||
.description = "Wireless RNDIS device",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
|
||||
FLAG_AVOID_UNLINK_URBS,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
@ -2550,7 +3043,7 @@ static const struct driver_info rndis_wlan_info = {
|
||||
.reset = rndis_wlan_reset,
|
||||
.stop = rndis_wlan_stop,
|
||||
.early_init = bcm4320a_early_init,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
.indication = rndis_wlan_indication,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
@ -1,8 +1,8 @@
|
||||
menuconfig RT2X00
|
||||
tristate "Ralink driver support"
|
||||
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
|
||||
depends on MAC80211 && WLAN_80211
|
||||
---help---
|
||||
This will enable the experimental support for the Ralink drivers,
|
||||
This will enable the support for the Ralink drivers,
|
||||
developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
|
||||
|
||||
These drivers make use of the mac80211 stack.
|
||||
@ -79,14 +79,14 @@ config RT73USB
|
||||
|
||||
config RT2800USB
|
||||
tristate "Ralink rt2800 (USB) support"
|
||||
depends on USB
|
||||
depends on USB && EXPERIMENTAL
|
||||
select RT2X00_LIB_USB
|
||||
select RT2X00_LIB_HT
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
---help---
|
||||
This adds support for rt2800 wireless chipset family.
|
||||
This adds experimental support for rt2800 wireless chipset family.
|
||||
Supported chips: RT2770, RT2870 & RT3070.
|
||||
|
||||
When compiled as a module, this driver will be called "rt2800usb.ko".
|
||||
|
@ -215,7 +215,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00lib_beacondone_iter,
|
||||
rt2x00dev);
|
||||
|
||||
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
|
||||
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
|
||||
|
||||
@ -892,6 +892,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Stop all work.
|
||||
*/
|
||||
cancel_work_sync(&rt2x00dev->filter_work);
|
||||
cancel_work_sync(&rt2x00dev->intf_work);
|
||||
|
||||
/*
|
||||
* Uninitialize device.
|
||||
*/
|
||||
|
@ -351,7 +351,7 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
rt2x00link_reset_tuner(rt2x00dev, false);
|
||||
|
||||
queue_delayed_work(rt2x00dev->hw->workqueue,
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->work, LINK_TUNE_INTERVAL);
|
||||
}
|
||||
|
||||
@ -461,7 +461,7 @@ static void rt2x00link_tuner(struct work_struct *work)
|
||||
* Increase tuner counter, and reschedule the next link tuner run.
|
||||
*/
|
||||
link->count++;
|
||||
queue_delayed_work(rt2x00dev->hw->workqueue,
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->work, LINK_TUNE_INTERVAL);
|
||||
}
|
||||
|
||||
|
@ -431,10 +431,20 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
|
||||
else
|
||||
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
|
||||
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
|
||||
|
||||
int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
rt2x00lib_beacondone(rt2x00dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
|
||||
|
||||
#ifdef CONFIG_RT2X00_LIB_CRYPTO
|
||||
static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
|
||||
{
|
||||
@ -454,16 +464,6 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
|
||||
sizeof(crypto->rx_mic));
|
||||
}
|
||||
|
||||
int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
rt2x00lib_beacondone(rt2x00dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
|
||||
|
||||
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
|
@ -2600,6 +2600,11 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Disable power saving.
|
||||
*/
|
||||
rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
|
||||
|
||||
/*
|
||||
* Allocate eeprom data.
|
||||
*/
|
||||
|
@ -220,7 +220,7 @@ static void rtl8187_tx_cb(struct urb *urb)
|
||||
* reading a register in the device. We are in interrupt mode
|
||||
* here, thus queue the skb and finish on a work queue. */
|
||||
skb_queue_tail(&priv->b_tx_status.queue, skb);
|
||||
queue_delayed_work(hw->workqueue, &priv->work, 0);
|
||||
ieee80211_queue_delayed_work(hw, &priv->work, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,11 +108,11 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
|
||||
struct rtl8187_priv *priv = hw->priv;
|
||||
|
||||
if (brightness == LED_OFF) {
|
||||
queue_delayed_work(hw->workqueue, &priv->led_off, 0);
|
||||
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
|
||||
/* The LED is off for 1/20 sec so that it just blinks. */
|
||||
queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
|
||||
ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
|
||||
} else
|
||||
queue_delayed_work(hw->workqueue, &priv->led_on, 0);
|
||||
ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
|
||||
}
|
||||
|
||||
static int rtl8187_register_led(struct ieee80211_hw *dev,
|
||||
@ -193,7 +193,7 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
|
||||
err = rtl8187_register_led(dev, &priv->led_rx, name,
|
||||
ieee80211_get_rx_led_name(dev), ledpin);
|
||||
if (!err) {
|
||||
queue_delayed_work(dev->workqueue, &priv->led_on, 0);
|
||||
ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
|
||||
return;
|
||||
}
|
||||
/* registration of RX LED failed - unregister TX */
|
||||
@ -209,7 +209,7 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
|
||||
/* turn the LED off before exiting */
|
||||
queue_delayed_work(dev->workqueue, &priv->led_off, 0);
|
||||
ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
|
||||
cancel_delayed_work_sync(&priv->led_off);
|
||||
cancel_delayed_work_sync(&priv->led_on);
|
||||
rtl8187_unregister_led(&priv->led_rx);
|
||||
|
@ -1550,9 +1550,12 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
if (time_after(jiffies, strip_info->pps_timer + HZ)) {
|
||||
unsigned long t = jiffies - strip_info->pps_timer;
|
||||
unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;
|
||||
unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;
|
||||
unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t;
|
||||
unsigned long rx_pps_count =
|
||||
DIV_ROUND_CLOSEST(strip_info->rx_pps_count*HZ*8, t);
|
||||
unsigned long tx_pps_count =
|
||||
DIV_ROUND_CLOSEST(strip_info->tx_pps_count*HZ*8, t);
|
||||
unsigned long sx_pps_count =
|
||||
DIV_ROUND_CLOSEST(strip_info->sx_pps_count*HZ*8, t);
|
||||
|
||||
strip_info->pps_timer = jiffies;
|
||||
strip_info->rx_pps_count = 0;
|
||||
|
@ -698,7 +698,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
|
||||
&& !mac->pass_ctrl)
|
||||
return 0;
|
||||
|
||||
fc = *(__le16 *)buffer;
|
||||
fc = get_unaligned((__le16*)buffer);
|
||||
need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
|
||||
|
||||
skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
|
||||
|
@ -47,6 +47,7 @@ enum rfkill_type {
|
||||
RFKILL_TYPE_UWB,
|
||||
RFKILL_TYPE_WIMAX,
|
||||
RFKILL_TYPE_WWAN,
|
||||
RFKILL_TYPE_GPS,
|
||||
NUM_RFKILL_TYPES,
|
||||
};
|
||||
|
||||
|
@ -76,6 +76,7 @@ struct rndis_msg_hdr {
|
||||
#define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb)
|
||||
#define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b)
|
||||
#define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c)
|
||||
#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION cpu_to_le32(0x40010012)
|
||||
|
||||
/* codes for OID_GEN_PHYSICAL_MEDIUM */
|
||||
#define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED cpu_to_le32(0x00000000)
|
||||
|
@ -86,6 +86,7 @@ struct driver_info {
|
||||
|
||||
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
|
||||
#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
|
||||
#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
|
||||
|
||||
|
||||
/* init device ... can sleep, or cause probe() failure */
|
||||
@ -121,9 +122,8 @@ struct driver_info {
|
||||
* right after minidriver have initialized hardware. */
|
||||
int (*early_init)(struct usbnet *dev);
|
||||
|
||||
/* called by minidriver when link state changes, state: 0=disconnect,
|
||||
* 1=connect */
|
||||
void (*link_change)(struct usbnet *dev, int state);
|
||||
/* called by minidriver when receiving indication */
|
||||
void (*indication)(struct usbnet *dev, void *ind, int indlen);
|
||||
|
||||
/* for new devices, use the descriptor-reading code instead */
|
||||
int in; /* rx endpoint */
|
||||
|
@ -1513,20 +1513,6 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
|
||||
*/
|
||||
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
|
||||
|
||||
/**
|
||||
* regulatory_hint_11d - hints a country IE as a regulatory domain
|
||||
* @wiphy: the wireless device giving the hint (used only for reporting
|
||||
* conflicts)
|
||||
* @country_ie: pointer to the country IE
|
||||
* @country_ie_len: length of the country IE
|
||||
*
|
||||
* We will intersect the rd with the what CRDA tells us should apply
|
||||
* for the alpha2 this country IE belongs to, this prevents APs from
|
||||
* sending us incorrect or outdated information against a country.
|
||||
*/
|
||||
extern void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len);
|
||||
/**
|
||||
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
|
||||
* @wiphy: the wireless device we want to process the regulatory domain on
|
||||
|
@ -72,6 +72,21 @@
|
||||
* not do so then mac80211 may add this under certain circumstances.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: mac80211 workqueue
|
||||
*
|
||||
* mac80211 provides its own workqueue for drivers and internal mac80211 use.
|
||||
* The workqueue is a single threaded workqueue and can only be accessed by
|
||||
* helpers for sanity checking. Drivers must ensure all work added onto the
|
||||
* mac80211 workqueue should be cancelled on the driver stop() callback.
|
||||
*
|
||||
* mac80211 will flushed the workqueue upon interface removal and during
|
||||
* suspend.
|
||||
*
|
||||
* All work performed on the mac80211 workqueue must not acquire the RTNL lock.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum ieee80211_max_queues - maximum number of queues
|
||||
*
|
||||
@ -913,12 +928,6 @@ enum ieee80211_hw_flags {
|
||||
*
|
||||
* @conf: &struct ieee80211_conf, device configuration, don't use.
|
||||
*
|
||||
* @workqueue: single threaded workqueue available for driver use,
|
||||
* allocated by mac80211 on registration and flushed when an
|
||||
* interface is removed.
|
||||
* NOTICE: All work performed on this workqueue must not
|
||||
* acquire the RTNL lock.
|
||||
*
|
||||
* @priv: pointer to private area that was allocated for driver use
|
||||
* along with this structure.
|
||||
*
|
||||
@ -954,7 +963,6 @@ enum ieee80211_hw_flags {
|
||||
struct ieee80211_hw {
|
||||
struct ieee80211_conf conf;
|
||||
struct wiphy *wiphy;
|
||||
struct workqueue_struct *workqueue;
|
||||
const char *rate_control_algorithm;
|
||||
void *priv;
|
||||
u32 flags;
|
||||
@ -1236,10 +1244,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
||||
* mac80211 needs to do and the amount of CPU wakeups, so you should
|
||||
* honour this flag if possible.
|
||||
*
|
||||
* @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then
|
||||
* only those addressed to this station
|
||||
* @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
|
||||
* is not set then only those addressed to this station.
|
||||
*
|
||||
* @FIF_OTHER_BSS: pass frames destined to other BSSes
|
||||
*
|
||||
* @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
|
||||
* those addressed to this station.
|
||||
*/
|
||||
enum ieee80211_filter_flags {
|
||||
FIF_PROMISC_IN_BSS = 1<<0,
|
||||
@ -1249,6 +1260,7 @@ enum ieee80211_filter_flags {
|
||||
FIF_BCN_PRBRESP_PROMISC = 1<<4,
|
||||
FIF_CONTROL = 1<<5,
|
||||
FIF_OTHER_BSS = 1<<6,
|
||||
FIF_PSPOLL = 1<<7,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1301,7 +1313,8 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* is disabled. This should turn off the hardware (at least
|
||||
* it must turn off frame reception.)
|
||||
* May be called right after add_interface if that rejects
|
||||
* an interface.
|
||||
* an interface. If you added any work onto the mac80211 workqueue
|
||||
* you should ensure to cancel it on this callback.
|
||||
* Must be implemented.
|
||||
*
|
||||
* @add_interface: Called when a netdevice attached to the hardware is
|
||||
@ -1927,6 +1940,31 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif),
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* ieee80211_queue_work - add work onto the mac80211 workqueue
|
||||
*
|
||||
* Drivers and mac80211 use this to add work onto the mac80211 workqueue.
|
||||
* This helper ensures drivers are not queueing work when they should not be.
|
||||
*
|
||||
* @hw: the hardware struct for the interface we are adding work for
|
||||
* @work: the work we want to add onto the mac80211 workqueue
|
||||
*/
|
||||
void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work);
|
||||
|
||||
/**
|
||||
* ieee80211_queue_delayed_work - add work onto the mac80211 workqueue
|
||||
*
|
||||
* Drivers and mac80211 use this to queue delayed work onto the mac80211
|
||||
* workqueue.
|
||||
*
|
||||
* @hw: the hardware struct for the interface we are adding work for
|
||||
* @dwork: delayable work to queue onto the mac80211 workqueue
|
||||
* @delay: number of jiffies to wait before queueing
|
||||
*/
|
||||
void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
||||
struct delayed_work *dwork,
|
||||
unsigned long delay);
|
||||
|
||||
/**
|
||||
* ieee80211_start_tx_ba_session - Start a tx Block Ack session.
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* bug in tracepoint.h, it should include this */
|
||||
#include <linux/module.h>
|
||||
|
||||
/* sparse isn't too happy with all macros... */
|
||||
#ifndef __CHECKER__
|
||||
#include "driver-ops.h"
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "driver-trace.h"
|
||||
#endif
|
||||
|
@ -781,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data)
|
||||
}
|
||||
|
||||
set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
|
||||
queue_work(local->hw.workqueue, &ifibss->work);
|
||||
ieee80211_queue_work(&local->hw, &ifibss->work);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -853,7 +853,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
case IEEE80211_STYPE_PROBE_REQ:
|
||||
case IEEE80211_STYPE_AUTH:
|
||||
skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
|
||||
queue_work(local->hw.workqueue, &sdata->u.ibss.work);
|
||||
ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
|
||||
@ -912,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_recalc_idle(sdata->local);
|
||||
|
||||
set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
|
||||
queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -280,6 +280,7 @@ struct ieee80211_if_managed {
|
||||
struct work_struct beacon_loss_work;
|
||||
|
||||
unsigned long probe_timeout;
|
||||
int probe_send_count;
|
||||
|
||||
struct mutex mtx;
|
||||
struct ieee80211_bss *associated;
|
||||
@ -614,6 +615,12 @@ struct ieee80211_local {
|
||||
|
||||
const struct ieee80211_ops *ops;
|
||||
|
||||
/*
|
||||
* private workqueue to mac80211. mac80211 makes this accessible
|
||||
* via ieee80211_queue_work()
|
||||
*/
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
|
||||
/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
|
||||
spinlock_t queue_stop_reason_lock;
|
||||
@ -621,7 +628,7 @@ struct ieee80211_local {
|
||||
int open_count;
|
||||
int monitors, cooked_mntrs;
|
||||
/* number of interfaces with corresponding FIF_ flags */
|
||||
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
|
||||
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
|
||||
unsigned int filter_flags; /* FIF_* */
|
||||
struct iw_statistics wstats;
|
||||
|
||||
|
@ -220,8 +220,10 @@ static int ieee80211_open(struct net_device *dev)
|
||||
local->fif_fcsfail++;
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
|
||||
local->fif_plcpfail++;
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
|
||||
local->fif_control++;
|
||||
local->fif_pspoll++;
|
||||
}
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
|
||||
local->fif_other_bss++;
|
||||
|
||||
@ -244,7 +246,14 @@ static int ieee80211_open(struct net_device *dev)
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
ieee80211_start_mesh(sdata);
|
||||
} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
local->fif_pspoll++;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
ieee80211_configure_filter(local);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
}
|
||||
|
||||
changed |= ieee80211_reset_erp_info(sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
ieee80211_enable_keys(sdata);
|
||||
@ -312,7 +321,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
* to fix this.
|
||||
*/
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
queue_work(local->hw.workqueue, &sdata->u.mgd.work);
|
||||
ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
|
||||
@ -388,6 +397,9 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
if (sdata->flags & IEEE80211_SDATA_PROMISC)
|
||||
atomic_dec(&local->iff_promiscs);
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
||||
local->fif_pspoll--;
|
||||
|
||||
netif_addr_lock_bh(dev);
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
__dev_addr_unsync(&local->mc_list, &local->mc_count,
|
||||
@ -401,7 +413,7 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
|
||||
/* APs need special treatment */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
struct ieee80211_sub_if_data *vlan, *tmp;
|
||||
struct ieee80211_sub_if_data *vlan, *tmpsdata;
|
||||
struct beacon_data *old_beacon = sdata->u.ap.beacon;
|
||||
|
||||
/* remove beacon */
|
||||
@ -410,7 +422,7 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
kfree(old_beacon);
|
||||
|
||||
/* down all dependent devices, that is VLANs */
|
||||
list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
|
||||
list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
|
||||
u.vlan.list)
|
||||
dev_close(vlan->dev);
|
||||
WARN_ON(!list_empty(&sdata->u.ap.vlans));
|
||||
@ -439,8 +451,10 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
local->fif_fcsfail--;
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
|
||||
local->fif_plcpfail--;
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
|
||||
local->fif_pspoll--;
|
||||
local->fif_control--;
|
||||
}
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
|
||||
local->fif_other_bss--;
|
||||
|
||||
@ -522,6 +536,16 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
ieee80211_scan_completed(&local->hw, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable beaconing for AP and mesh, IBSS can't
|
||||
* still be joined to a network at this point.
|
||||
*/
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
|
||||
ieee80211_bss_info_change_notify(sdata,
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
}
|
||||
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = dev->dev_addr;
|
||||
@ -541,7 +565,7 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
|
||||
ieee80211_led_radio(local, false);
|
||||
|
||||
flush_workqueue(local->hw.workqueue);
|
||||
flush_workqueue(local->workqueue);
|
||||
|
||||
tasklet_disable(&local->tx_pending_tasklet);
|
||||
tasklet_disable(&local->tasklet);
|
||||
|
@ -77,6 +77,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
|
||||
if (local->fif_other_bss)
|
||||
new_flags |= FIF_OTHER_BSS;
|
||||
|
||||
if (local->fif_pspoll)
|
||||
new_flags |= FIF_PSPOLL;
|
||||
|
||||
changed_flags = local->filter_flags ^ new_flags;
|
||||
|
||||
/* be a bit nasty */
|
||||
@ -198,7 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
if (local->quiescing || !netif_running(sdata->dev) ||
|
||||
test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
} else {
|
||||
/*
|
||||
@ -310,6 +314,31 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/*
|
||||
* XXX: This is temporary!
|
||||
*
|
||||
* The problem here is that when we get here, the driver will
|
||||
* quite likely have pretty much overwritten info->control by
|
||||
* using info->driver_data or info->rate_driver_data. Thus,
|
||||
* when passing out the frame to the driver again, we would be
|
||||
* passing completely bogus data since the driver would then
|
||||
* expect a properly filled info->control. In mac80211 itself
|
||||
* the same problem occurs, since we need info->control.vif
|
||||
* internally.
|
||||
*
|
||||
* To fix this, we should send the frame through TX processing
|
||||
* again. However, it's not that simple, since the frame will
|
||||
* have been software-encrypted (if applicable) already, and
|
||||
* encrypting it again doesn't do much good. So to properly do
|
||||
* that, we not only have to skip the actual 'raw' encryption
|
||||
* (key selection etc. still has to be done!) but also the
|
||||
* sequence number assignment since that impacts the crypto
|
||||
* encapsulation, of course.
|
||||
*
|
||||
* Hence, for now, fix the bug by just dropping the frame.
|
||||
*/
|
||||
goto drop;
|
||||
|
||||
sta->tx_filtered_count++;
|
||||
|
||||
/*
|
||||
@ -363,6 +392,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
return;
|
||||
}
|
||||
|
||||
drop:
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
if (net_ratelimit())
|
||||
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
|
||||
@ -794,9 +824,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
if (hw->queues > IEEE80211_MAX_QUEUES)
|
||||
hw->queues = IEEE80211_MAX_QUEUES;
|
||||
|
||||
local->hw.workqueue =
|
||||
local->workqueue =
|
||||
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
|
||||
if (!local->hw.workqueue) {
|
||||
if (!local->workqueue) {
|
||||
result = -ENOMEM;
|
||||
goto fail_workqueue;
|
||||
}
|
||||
@ -886,7 +916,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
sta_info_stop(local);
|
||||
fail_sta_info:
|
||||
debugfs_hw_del(local);
|
||||
destroy_workqueue(local->hw.workqueue);
|
||||
destroy_workqueue(local->workqueue);
|
||||
fail_workqueue:
|
||||
wiphy_unregister(local->hw.wiphy);
|
||||
fail_wiphy_register:
|
||||
@ -928,7 +958,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
||||
skb_queue_purge(&local->skb_queue);
|
||||
skb_queue_purge(&local->skb_queue_unreliable);
|
||||
|
||||
destroy_workqueue(local->hw.workqueue);
|
||||
destroy_workqueue(local->workqueue);
|
||||
wiphy_unregister(local->hw.wiphy);
|
||||
ieee80211_wep_free(local);
|
||||
ieee80211_led_exit(local);
|
||||
|
@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,7 +357,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
}
|
||||
|
||||
struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
|
||||
@ -471,7 +471,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
ifmsh->housekeeping = true;
|
||||
queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
}
|
||||
@ -619,7 +619,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||
queue_work(local->hw.workqueue, &sdata->u.mesh.work);
|
||||
ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@ -692,7 +692,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
case IEEE80211_STYPE_PROBE_RESP:
|
||||
case IEEE80211_STYPE_BEACON:
|
||||
skb_queue_tail(&ifmsh->skb_queue, skb);
|
||||
queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
|
||||
|
@ -660,14 +660,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
|
||||
spin_unlock(&ifmsh->mesh_preq_queue_lock);
|
||||
|
||||
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
|
||||
queue_work(sdata->local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
|
||||
|
||||
else if (time_before(jiffies, ifmsh->last_preq)) {
|
||||
/* avoid long wait if did not send preqs for a long time
|
||||
* and jiffies wrapped around
|
||||
*/
|
||||
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
|
||||
queue_work(sdata->local->hw.workqueue, &ifmsh->work);
|
||||
ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
|
||||
} else
|
||||
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
|
||||
min_preq_int_jiff(sdata));
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define IEEE80211_AUTH_MAX_TRIES 3
|
||||
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
|
||||
#define IEEE80211_ASSOC_MAX_TRIES 3
|
||||
#define IEEE80211_MAX_PROBE_TRIES 5
|
||||
|
||||
/*
|
||||
* beacon loss detection timeout
|
||||
@ -41,13 +42,13 @@
|
||||
* Time the connection can be idle before we probe
|
||||
* it to see if we can still talk to the AP.
|
||||
*/
|
||||
#define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ)
|
||||
#define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ)
|
||||
/*
|
||||
* Time we wait for a probe response after sending
|
||||
* a probe request because of beacon loss or for
|
||||
* checking the connection still works.
|
||||
*/
|
||||
#define IEEE80211_PROBE_WAIT (HZ / 5)
|
||||
#define IEEE80211_PROBE_WAIT (HZ / 2)
|
||||
|
||||
#define TMR_RUNNING_TIMER 0
|
||||
#define TMR_RUNNING_CHANSW 1
|
||||
@ -565,7 +566,7 @@ static void ieee80211_chswitch_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
|
||||
}
|
||||
|
||||
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
@ -597,7 +598,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->local->csa_channel = new_ch;
|
||||
|
||||
if (sw_elem->count <= 1) {
|
||||
queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
|
||||
} else {
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
@ -763,7 +764,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
|
||||
if (local->quiescing || local->suspended)
|
||||
return;
|
||||
|
||||
queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
|
||||
ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
|
||||
}
|
||||
|
||||
/* MLME */
|
||||
@ -916,12 +917,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, bss_info_changed);
|
||||
|
||||
/* will be same as sdata */
|
||||
if (local->ps_sdata) {
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
netif_tx_start_all_queues(sdata->dev);
|
||||
netif_carrier_on(sdata->dev);
|
||||
@ -950,7 +948,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
|
||||
* due to work needing to be done. Hence, queue the STAs work
|
||||
* again for that.
|
||||
*/
|
||||
queue_work(local->hw.workqueue, &ifmgd->work);
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->work);
|
||||
return RX_MGMT_CFG80211_AUTH_TO;
|
||||
}
|
||||
|
||||
@ -995,7 +993,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
|
||||
* due to work needing to be done. Hence, queue the STAs work
|
||||
* again for that.
|
||||
*/
|
||||
queue_work(local->hw.workqueue, &ifmgd->work);
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->work);
|
||||
return RX_MGMT_CFG80211_AUTH_TO;
|
||||
}
|
||||
|
||||
@ -1124,7 +1122,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
|
||||
* due to work needing to be done. Hence, queue the STAs work
|
||||
* again for that.
|
||||
*/
|
||||
queue_work(local->hw.workqueue, &ifmgd->work);
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->work);
|
||||
return RX_MGMT_CFG80211_ASSOC_TO;
|
||||
}
|
||||
|
||||
@ -1156,11 +1154,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
|
||||
}
|
||||
|
||||
static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
const u8 *ssid;
|
||||
|
||||
ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
|
||||
ssid + 2, ssid[1], NULL, 0);
|
||||
|
||||
ifmgd->probe_send_count++;
|
||||
ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
|
||||
run_again(ifmgd, ifmgd->probe_timeout);
|
||||
}
|
||||
|
||||
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
|
||||
bool beacon)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
const u8 *ssid;
|
||||
bool already = false;
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
@ -1203,18 +1214,12 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
|
||||
if (already)
|
||||
goto out;
|
||||
|
||||
ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
|
||||
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
ieee80211_recalc_ps(sdata->local, -1);
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
|
||||
ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
|
||||
ssid + 2, ssid[1], NULL, 0);
|
||||
|
||||
run_again(ifmgd, ifmgd->probe_timeout);
|
||||
|
||||
ifmgd->probe_send_count = 0;
|
||||
ieee80211_mgd_probe_ap_send(sdata);
|
||||
out:
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
}
|
||||
@ -1232,8 +1237,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
queue_work(sdata->local->hw.workqueue,
|
||||
&sdata->u.mgd.beacon_loss_work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_beacon_loss);
|
||||
|
||||
@ -1570,6 +1574,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||
wk->bss->cbss.bssid,
|
||||
ap_ht_cap_flags);
|
||||
|
||||
/* delete work item -- must be before set_associated for PS */
|
||||
list_del(&wk->list);
|
||||
|
||||
/* set AID and assoc capability,
|
||||
* ieee80211_set_associated() will tell the driver */
|
||||
bss_conf->aid = aid;
|
||||
@ -1583,7 +1590,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
|
||||
mod_beacon_timer(sdata);
|
||||
|
||||
list_del(&wk->list);
|
||||
kfree(wk);
|
||||
return RX_MGMT_CFG80211_ASSOC;
|
||||
}
|
||||
@ -1847,12 +1853,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
bssid, ap_ht_cap_flags);
|
||||
}
|
||||
|
||||
/* Note: country IE parsing is done for us by cfg80211 */
|
||||
if (elems.country_elem) {
|
||||
/* Note we are only reviewing this on beacons
|
||||
* for the BSSID we are associated to */
|
||||
regulatory_hint_11d(local->hw.wiphy,
|
||||
elems.country_elem, elems.country_elem_len);
|
||||
|
||||
/* TODO: IBSS also needs this */
|
||||
if (elems.pwr_constr_elem)
|
||||
ieee80211_handle_pwr_constr(sdata,
|
||||
@ -1888,7 +1890,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
case IEEE80211_STYPE_DISASSOC:
|
||||
case IEEE80211_STYPE_ACTION:
|
||||
skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
|
||||
queue_work(local->hw.workqueue, &sdata->u.mgd.work);
|
||||
ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
|
||||
@ -2026,7 +2028,7 @@ static void ieee80211_sta_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(local->hw.workqueue, &ifmgd->work);
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->work);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_work(struct work_struct *work)
|
||||
@ -2051,13 +2053,11 @@ static void ieee80211_sta_work(struct work_struct *work)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Nothing should have been stuffed into the workqueue during
|
||||
* the suspend->resume cycle. If this WARN is seen then there
|
||||
* is a bug with either the driver suspend or something in
|
||||
* mac80211 stuffing into the workqueue which we haven't yet
|
||||
* cleared during mac80211's suspend cycle.
|
||||
* ieee80211_queue_work() should have picked up most cases,
|
||||
* here we'll pick the the rest.
|
||||
*/
|
||||
if (WARN_ON(local->suspended))
|
||||
if (WARN(local->suspended, "STA MLME work scheduled while "
|
||||
"going to suspend\n"))
|
||||
return;
|
||||
|
||||
ifmgd = &sdata->u.mgd;
|
||||
@ -2072,17 +2072,27 @@ static void ieee80211_sta_work(struct work_struct *work)
|
||||
if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
|
||||
IEEE80211_STA_CONNECTION_POLL) &&
|
||||
ifmgd->associated) {
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
|
||||
if (time_is_after_jiffies(ifmgd->probe_timeout))
|
||||
run_again(ifmgd, ifmgd->probe_timeout);
|
||||
else {
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) {
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
printk(KERN_DEBUG "No probe response from AP %pM"
|
||||
" after %dms, try %d\n", bssid,
|
||||
(1000 * IEEE80211_PROBE_WAIT)/HZ,
|
||||
ifmgd->probe_send_count);
|
||||
#endif
|
||||
ieee80211_mgd_probe_ap_send(sdata);
|
||||
} else {
|
||||
/*
|
||||
* We actually lost the connection ... or did we?
|
||||
* Let's make sure!
|
||||
*/
|
||||
ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
||||
IEEE80211_STA_BEACON_POLL);
|
||||
memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
|
||||
printk(KERN_DEBUG "No probe response from AP %pM"
|
||||
" after %dms, disconnecting.\n",
|
||||
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
|
||||
@ -2113,7 +2123,7 @@ static void ieee80211_sta_work(struct work_struct *work)
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
|
||||
queue_delayed_work(local->hw.workqueue,
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
&local->scan_work,
|
||||
round_jiffies_relative(0));
|
||||
return;
|
||||
@ -2196,8 +2206,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
|
||||
if (local->quiescing)
|
||||
return;
|
||||
|
||||
queue_work(sdata->local->hw.workqueue,
|
||||
&sdata->u.mgd.beacon_loss_work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_conn_mon_timer(unsigned long data)
|
||||
@ -2210,7 +2219,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
|
||||
if (local->quiescing)
|
||||
return;
|
||||
|
||||
queue_work(local->hw.workqueue, &ifmgd->monitor_work);
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_monitor_work(struct work_struct *work)
|
||||
@ -2229,10 +2238,10 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
|
||||
IEEE80211_STA_CONNECTION_POLL);
|
||||
|
||||
/* let's probe the connection once */
|
||||
queue_work(sdata->local->hw.workqueue,
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->u.mgd.monitor_work);
|
||||
/* and do all the other regular work too */
|
||||
queue_work(sdata->local->hw.workqueue,
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->u.mgd.work);
|
||||
}
|
||||
}
|
||||
@ -2393,7 +2402,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
|
||||
list_add(&wk->list, &sdata->u.mgd.work_list);
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2467,7 +2476,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
else
|
||||
ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
|
||||
|
||||
queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
|
||||
|
||||
err = 0;
|
||||
|
||||
|
@ -26,7 +26,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
||||
/* make quiescing visible to timers everywhere */
|
||||
mb();
|
||||
|
||||
flush_workqueue(local->hw.workqueue);
|
||||
flush_workqueue(local->workqueue);
|
||||
|
||||
/* Don't try to run timers while suspended. */
|
||||
del_timer_sync(&local->sta_cleanup);
|
||||
@ -96,6 +96,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
||||
if (!netif_running(sdata->dev))
|
||||
continue;
|
||||
|
||||
/* disable beaconing */
|
||||
ieee80211_bss_info_change_notify(sdata,
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = sdata->dev->dev_addr;
|
||||
@ -113,7 +117,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
||||
* shouldn't be doing (or cancel everything in the
|
||||
* stop callback) that but better safe than sorry.
|
||||
*/
|
||||
flush_workqueue(local->hw.workqueue);
|
||||
flush_workqueue(local->workqueue);
|
||||
|
||||
local->suspended = true;
|
||||
/* need suspended to be visible before quiescing is false */
|
||||
|
@ -385,7 +385,8 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
||||
/* TODO: start scan as soon as all nullfunc frames are ACKed */
|
||||
queue_delayed_work(local->hw.workqueue, &local->scan_work,
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
&local->scan_work,
|
||||
IEEE80211_CHANNEL_TIME);
|
||||
|
||||
return 0;
|
||||
@ -715,8 +716,7 @@ void ieee80211_scan_work(struct work_struct *work)
|
||||
}
|
||||
} while (next_delay == 0);
|
||||
|
||||
queue_delayed_work(local->hw.workqueue, &local->scan_work,
|
||||
next_delay);
|
||||
ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
|
||||
}
|
||||
|
||||
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -1400,7 +1400,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_PS);
|
||||
queue_work(local->hw.workqueue,
|
||||
ieee80211_queue_work(&local->hw,
|
||||
&local->dynamic_ps_disable_work);
|
||||
}
|
||||
|
||||
|
@ -511,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic(
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
|
||||
|
||||
/*
|
||||
* Nothing should have been stuffed into the workqueue during
|
||||
* the suspend->resume cycle. If this WARN is seen then there
|
||||
* is a bug with either the driver suspend or something in
|
||||
* mac80211 stuffing into the workqueue which we haven't yet
|
||||
* cleared during mac80211's suspend cycle.
|
||||
*/
|
||||
static bool ieee80211_can_queue_work(struct ieee80211_local *local)
|
||||
{
|
||||
if (WARN(local->suspended, "queueing ieee80211 work while "
|
||||
"going to suspend\n"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
if (!ieee80211_can_queue_work(local))
|
||||
return;
|
||||
|
||||
queue_work(local->workqueue, work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_queue_work);
|
||||
|
||||
void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
||||
struct delayed_work *dwork,
|
||||
unsigned long delay)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
if (!ieee80211_can_queue_work(local))
|
||||
return;
|
||||
|
||||
queue_delayed_work(local->workqueue, dwork, delay);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
||||
|
||||
void ieee802_11_parse_elems(u8 *start, size_t len,
|
||||
struct ieee802_11_elems *elems)
|
||||
{
|
||||
@ -1114,3 +1154,4 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -589,11 +589,13 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
|
||||
return "wimax";
|
||||
case RFKILL_TYPE_WWAN:
|
||||
return "wwan";
|
||||
case RFKILL_TYPE_GPS:
|
||||
return "gps";
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_WWAN + 1);
|
||||
BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_GPS + 1);
|
||||
}
|
||||
|
||||
static ssize_t rfkill_type_show(struct device *dev,
|
||||
|
@ -34,9 +34,7 @@ MODULE_DESCRIPTION("wireless configuration support");
|
||||
LIST_HEAD(cfg80211_rdev_list);
|
||||
|
||||
/*
|
||||
* This is used to protect the cfg80211_rdev_list, cfg80211_regdomain,
|
||||
* country_ie_regdomain, the reg_beacon_list and the the last regulatory
|
||||
* request receipt (last_request).
|
||||
* This is used to protect the cfg80211_rdev_list
|
||||
*/
|
||||
DEFINE_MUTEX(cfg80211_mutex);
|
||||
|
||||
@ -314,7 +312,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev)
|
||||
ev->cr.req_ie, ev->cr.req_ie_len,
|
||||
ev->cr.resp_ie, ev->cr.resp_ie_len,
|
||||
ev->cr.status,
|
||||
ev->cr.status == WLAN_STATUS_SUCCESS);
|
||||
ev->cr.status == WLAN_STATUS_SUCCESS,
|
||||
NULL);
|
||||
break;
|
||||
case EVENT_ROAMED:
|
||||
__cfg80211_roamed(wdev, ev->rm.bssid,
|
||||
@ -672,7 +671,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE;
|
||||
wdev->wext.ps_timeout = 500;
|
||||
wdev->wext.ps_timeout = 100;
|
||||
if (rdev->ops->set_power_mgmt)
|
||||
if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
|
||||
wdev->wext.ps,
|
||||
@ -724,15 +723,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
/*
|
||||
* It is possible to get NETDEV_UNREGISTER
|
||||
* multiple times. To detect that, check
|
||||
* that the interface is still on the list
|
||||
* of registered interfaces, and only then
|
||||
* remove and clean it up.
|
||||
*/
|
||||
if (!list_empty(&wdev->list)) {
|
||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_init(&wdev->list);
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
mutex_destroy(&wdev->mtx);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
break;
|
||||
case NETDEV_PRE_UP:
|
||||
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
|
||||
|
@ -127,6 +127,11 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
|
||||
return container_of(pub, struct cfg80211_internal_bss, pub);
|
||||
}
|
||||
|
||||
static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss)
|
||||
{
|
||||
kref_get(&bss->ref);
|
||||
}
|
||||
|
||||
static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
|
||||
{
|
||||
atomic_inc(&bss->hold);
|
||||
@ -323,7 +328,8 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
||||
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev);
|
||||
u16 status, bool wextev,
|
||||
struct cfg80211_bss *bss);
|
||||
|
||||
/* SME */
|
||||
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
@ -61,7 +61,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
u8 *ie = mgmt->u.assoc_resp.variable;
|
||||
int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
|
||||
bool done;
|
||||
struct cfg80211_internal_bss *bss = NULL;
|
||||
|
||||
wdev_lock(wdev);
|
||||
|
||||
@ -69,22 +69,32 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
|
||||
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
|
||||
|
||||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
|
||||
status_code,
|
||||
status_code == WLAN_STATUS_SUCCESS);
|
||||
|
||||
if (status_code == WLAN_STATUS_SUCCESS) {
|
||||
for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) {
|
||||
if (wdev->auth_bsses[i] == wdev->current_bss) {
|
||||
cfg80211_unhold_bss(wdev->auth_bsses[i]);
|
||||
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
|
||||
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
||||
if (!wdev->auth_bsses[i])
|
||||
continue;
|
||||
if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
|
||||
ETH_ALEN) == 0) {
|
||||
bss = wdev->auth_bsses[i];
|
||||
wdev->auth_bsses[i] = NULL;
|
||||
done = true;
|
||||
/* additional reference to drop hold */
|
||||
cfg80211_ref_bss(bss);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(!done);
|
||||
WARN_ON(!bss);
|
||||
}
|
||||
|
||||
/* this consumes one bss reference (unless bss is NULL) */
|
||||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
|
||||
status_code,
|
||||
status_code == WLAN_STATUS_SUCCESS,
|
||||
bss ? &bss->pub : NULL);
|
||||
/* drop hold now, and also reference acquired above */
|
||||
if (bss) {
|
||||
cfg80211_unhold_bss(bss);
|
||||
cfg80211_put_bss(&bss->pub);
|
||||
}
|
||||
|
||||
wdev_unlock(wdev);
|
||||
@ -144,7 +154,7 @@ static void __cfg80211_send_deauth(struct net_device *dev,
|
||||
} else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
|
||||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false);
|
||||
false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,7 +251,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false);
|
||||
false, NULL);
|
||||
|
||||
for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
|
||||
if (wdev->authtry_bsses[i] &&
|
||||
@ -275,7 +285,7 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false);
|
||||
false, NULL);
|
||||
|
||||
for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
|
||||
if (wdev->auth_bsses[i] &&
|
||||
|
@ -62,6 +62,16 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
|
||||
*/
|
||||
static const struct ieee80211_regdomain *country_ie_regdomain;
|
||||
|
||||
/*
|
||||
* Protects static reg.c components:
|
||||
* - cfg80211_world_regdom
|
||||
* - cfg80211_regdom
|
||||
* - country_ie_regdomain
|
||||
* - last_request
|
||||
*/
|
||||
DEFINE_MUTEX(reg_mutex);
|
||||
#define assert_reg_lock() WARN_ON(!mutex_is_locked(®_mutex))
|
||||
|
||||
/* Used to queue up regulatory hints */
|
||||
static LIST_HEAD(reg_requests_list);
|
||||
static spinlock_t reg_requests_lock;
|
||||
@ -1293,7 +1303,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
assert_reg_lock();
|
||||
|
||||
sband = wiphy->bands[band];
|
||||
BUG_ON(chan_idx >= sband->n_channels);
|
||||
@ -1342,14 +1352,14 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
|
||||
enum ieee80211_band band;
|
||||
unsigned int bands_set = 0;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
handle_band_custom(wiphy, band, regd);
|
||||
bands_set++;
|
||||
}
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
/*
|
||||
* no point in calling this if it won't have any effect
|
||||
@ -1495,7 +1505,7 @@ static int ignore_request(struct wiphy *wiphy,
|
||||
* Returns zero if all went fine, %-EALREADY if a regulatory domain had
|
||||
* already been set or other standard error codes.
|
||||
*
|
||||
* Caller must hold &cfg80211_mutex
|
||||
* Caller must hold &cfg80211_mutex and ®_mutex
|
||||
*/
|
||||
static int __regulatory_hint(struct wiphy *wiphy,
|
||||
struct regulatory_request *pending_request)
|
||||
@ -1570,6 +1580,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
BUG_ON(!reg_request->alpha2);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
if (wiphy_idx_valid(reg_request->wiphy_idx))
|
||||
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
|
||||
@ -1585,6 +1596,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
|
||||
wiphy_update_regulatory(wiphy, reg_request->initiator);
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
}
|
||||
|
||||
@ -1613,6 +1625,10 @@ static void reg_process_pending_beacon_hints(void)
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct reg_beacon *pending_beacon, *tmp;
|
||||
|
||||
/*
|
||||
* No need to hold the reg_mutex here as we just touch wiphys
|
||||
* and do not read or access regulatory variables.
|
||||
*/
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* This goes through the _pending_ beacon list */
|
||||
@ -1734,12 +1750,13 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_hint);
|
||||
|
||||
/* Caller must hold reg_mutex */
|
||||
static bool reg_same_country_ie_hint(struct wiphy *wiphy,
|
||||
u32 country_ie_checksum)
|
||||
{
|
||||
struct wiphy *request_wiphy;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
assert_reg_lock();
|
||||
|
||||
if (unlikely(last_request->initiator !=
|
||||
NL80211_REGDOM_SET_BY_COUNTRY_IE))
|
||||
@ -1762,6 +1779,10 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
|
||||
* therefore cannot iterate over the rdev list here.
|
||||
*/
|
||||
void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len)
|
||||
@ -1772,12 +1793,10 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
if (unlikely(!last_request)) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return;
|
||||
}
|
||||
if (unlikely(!last_request))
|
||||
goto out;
|
||||
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
@ -1803,54 +1822,14 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
env = ENVIRON_OUTDOOR;
|
||||
|
||||
/*
|
||||
* We will run this for *every* beacon processed for the BSSID, so
|
||||
* we optimize an early check to exit out early if we don't have to
|
||||
* do anything
|
||||
* We will run this only upon a successful connection on cfg80211.
|
||||
* We leave conflict resolution to the workqueue, where can hold
|
||||
* cfg80211_mutex.
|
||||
*/
|
||||
if (likely(last_request->initiator ==
|
||||
NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
wiphy_idx_valid(last_request->wiphy_idx))) {
|
||||
struct cfg80211_registered_device *rdev_last_ie;
|
||||
|
||||
rdev_last_ie =
|
||||
cfg80211_rdev_by_wiphy_idx(last_request->wiphy_idx);
|
||||
|
||||
/*
|
||||
* Lets keep this simple -- we trust the first AP
|
||||
* after we intersect with CRDA
|
||||
*/
|
||||
if (likely(&rdev_last_ie->wiphy == wiphy)) {
|
||||
/*
|
||||
* Ignore IEs coming in on this wiphy with
|
||||
* the same alpha2 and environment cap
|
||||
*/
|
||||
if (likely(alpha2_equal(rdev_last_ie->country_ie_alpha2,
|
||||
alpha2) &&
|
||||
env == rdev_last_ie->env)) {
|
||||
wiphy_idx_valid(last_request->wiphy_idx)))
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* the wiphy moved on to another BSSID or the AP
|
||||
* was reconfigured. XXX: We need to deal with the
|
||||
* case where the user suspends and goes to goes
|
||||
* to another country, and then gets IEs from an
|
||||
* AP with different settings
|
||||
*/
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* Ignore IEs coming in on two separate wiphys with
|
||||
* the same alpha2 and environment cap
|
||||
*/
|
||||
if (likely(alpha2_equal(rdev_last_ie->country_ie_alpha2,
|
||||
alpha2) &&
|
||||
env == rdev_last_ie->env)) {
|
||||
goto out;
|
||||
}
|
||||
/* We could potentially intersect though */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
|
||||
if (!rd)
|
||||
@ -1885,7 +1864,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
request->country_ie_checksum = checksum;
|
||||
request->country_ie_env = env;
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
queue_regulatory_request(request);
|
||||
|
||||
@ -1894,9 +1873,8 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
free_rd_out:
|
||||
kfree(rd);
|
||||
out:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
mutex_unlock(®_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_hint_11d);
|
||||
|
||||
static bool freq_is_chan_12_13_14(u16 freq)
|
||||
{
|
||||
@ -2227,10 +2205,13 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
|
||||
assert_cfg80211_lock();
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
/* Note that this doesn't update the wiphys, this is done below */
|
||||
r = __set_regdom(rd);
|
||||
if (r) {
|
||||
kfree(rd);
|
||||
mutex_unlock(®_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -2245,6 +2226,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
|
||||
nl80211_send_reg_change_event(last_request);
|
||||
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -2255,16 +2238,20 @@ void reg_device_remove(struct wiphy *wiphy)
|
||||
|
||||
assert_cfg80211_lock();
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
kfree(wiphy->regd);
|
||||
|
||||
if (last_request)
|
||||
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
|
||||
|
||||
if (!request_wiphy || request_wiphy != wiphy)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
last_request->wiphy_idx = WIPHY_IDX_STALE;
|
||||
last_request->country_ie_env = ENVIRON_ANY;
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
}
|
||||
|
||||
int regulatory_init(void)
|
||||
@ -2325,6 +2312,7 @@ void regulatory_exit(void)
|
||||
cancel_work_sync(®_work);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
reset_regdomains();
|
||||
|
||||
@ -2363,5 +2351,6 @@ void regulatory_exit(void)
|
||||
}
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
}
|
||||
|
@ -36,4 +36,19 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *beacon_chan,
|
||||
gfp_t gfp);
|
||||
|
||||
/**
|
||||
* regulatory_hint_11d - hints a country IE as a regulatory domain
|
||||
* @wiphy: the wireless device giving the hint (used only for reporting
|
||||
* conflicts)
|
||||
* @country_ie: pointer to the country IE
|
||||
* @country_ie_len: length of the country IE
|
||||
*
|
||||
* We will intersect the rd with the what CRDA tells us should apply
|
||||
* for the alpha2 this country IE belongs to, this prevents APs from
|
||||
* sending us incorrect or outdated information against a country.
|
||||
*/
|
||||
void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len);
|
||||
|
||||
#endif /* __NET_WIRELESS_REG_H */
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include "nl80211.h"
|
||||
#include "reg.h"
|
||||
|
||||
struct cfg80211_conn {
|
||||
struct cfg80211_connect_params params;
|
||||
@ -182,7 +183,7 @@ void cfg80211_conn_work(struct work_struct *work)
|
||||
wdev->conn->params.bssid,
|
||||
NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false);
|
||||
false, NULL);
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
|
||||
@ -247,7 +248,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev)
|
||||
wdev->conn->params.bssid,
|
||||
NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false);
|
||||
false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,7 +306,7 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
|
||||
schedule_work(&rdev->conn_work);
|
||||
} else if (status_code != WLAN_STATUS_SUCCESS) {
|
||||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
|
||||
status_code, false);
|
||||
status_code, false, NULL);
|
||||
} else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
|
||||
wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
|
||||
wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
|
||||
@ -316,10 +317,11 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
|
||||
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev)
|
||||
u16 status, bool wextev,
|
||||
struct cfg80211_bss *bss)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss;
|
||||
u8 *country_ie;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
union iwreq_data wrqu;
|
||||
#endif
|
||||
@ -361,6 +363,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wdev->current_bss) {
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
cfg80211_put_bss(&wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
}
|
||||
|
||||
if (status == WLAN_STATUS_SUCCESS &&
|
||||
wdev->sme_state == CFG80211_SME_IDLE)
|
||||
goto success;
|
||||
@ -368,12 +376,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING)
|
||||
return;
|
||||
|
||||
if (wdev->current_bss) {
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
cfg80211_put_bss(&wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
}
|
||||
|
||||
if (wdev->conn)
|
||||
wdev->conn->state = CFG80211_CONN_IDLE;
|
||||
|
||||
@ -383,9 +385,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
wdev->conn = NULL;
|
||||
kfree(wdev->connect_keys);
|
||||
wdev->connect_keys = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
success:
|
||||
if (!bss)
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
WLAN_CAPABILITY_ESS,
|
||||
@ -397,9 +402,22 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
cfg80211_hold_bss(bss_from_pub(bss));
|
||||
wdev->current_bss = bss_from_pub(bss);
|
||||
|
||||
success:
|
||||
wdev->sme_state = CFG80211_SME_CONNECTED;
|
||||
cfg80211_upload_connect_keys(wdev);
|
||||
|
||||
country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
|
||||
|
||||
if (!country_ie)
|
||||
return;
|
||||
|
||||
/*
|
||||
* ieee80211_bss_get_ie() ensures we can access:
|
||||
* - country_ie + 2, the start of the country ie data, and
|
||||
* - and country_ie[1] which is the IE length
|
||||
*/
|
||||
regulatory_hint_11d(wdev->wiphy,
|
||||
country_ie + 2,
|
||||
country_ie[1]);
|
||||
}
|
||||
|
||||
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
@ -549,6 +567,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||
|
||||
wdev->current_bss = NULL;
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
wdev->ssid_len = 0;
|
||||
|
||||
if (wdev->conn) {
|
||||
kfree(wdev->conn->ie);
|
||||
@ -704,6 +723,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
wdev->conn = NULL;
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
wdev->connect_keys = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -768,6 +788,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
kfree(wdev->conn);
|
||||
wdev->conn = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -788,7 +809,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
else if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
wextev);
|
||||
wextev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1291,7 +1291,6 @@ static struct pernet_operations wext_pernet_ops = {
|
||||
static int __init wireless_nlevent_init(void)
|
||||
{
|
||||
return register_pernet_subsys(&wext_pernet_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(wireless_nlevent_init);
|
||||
|
Loading…
Reference in New Issue
Block a user