Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
@@ -232,13 +232,14 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_mc_list *mclist);
|
||||
static int ath5k_set_key(struct ieee80211_hw *hw,
|
||||
enum set_key_cmd cmd,
|
||||
const u8 *local_addr, const u8 *addr,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
static int ath5k_get_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_low_level_stats *stats);
|
||||
static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_queue_stats *stats);
|
||||
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
||||
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
|
||||
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
||||
static int ath5k_beacon_update(struct ath5k_softc *sc,
|
||||
struct sk_buff *skb);
|
||||
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
|
||||
.conf_tx = NULL,
|
||||
.get_tx_stats = ath5k_get_tx_stats,
|
||||
.get_tsf = ath5k_get_tsf,
|
||||
.set_tsf = ath5k_set_tsf,
|
||||
.reset_tsf = ath5k_reset_tsf,
|
||||
.bss_info_changed = ath5k_bss_info_changed,
|
||||
};
|
||||
@@ -347,9 +349,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
|
||||
}
|
||||
|
||||
/* Interrupt handling */
|
||||
static int ath5k_init(struct ath5k_softc *sc, bool is_resume);
|
||||
static int ath5k_init(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_locked(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc);
|
||||
static irqreturn_t ath5k_intr(int irq, void *dev_id);
|
||||
static void ath5k_tasklet_reset(unsigned long data);
|
||||
|
||||
@@ -653,8 +655,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
ath5k_led_off(sc);
|
||||
|
||||
ath5k_stop_hw(sc, true);
|
||||
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@@ -689,14 +689,9 @@ ath5k_pci_resume(struct pci_dev *pdev)
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
err = ath5k_init(sc, true);
|
||||
if (err)
|
||||
goto err_irq;
|
||||
ath5k_led_enable(sc);
|
||||
|
||||
return 0;
|
||||
err_irq:
|
||||
free_irq(pdev->irq, sc);
|
||||
|
||||
err_no_irq:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
@@ -1098,6 +1093,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
|
||||
* Buffers setup *
|
||||
\***************/
|
||||
|
||||
static
|
||||
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int off;
|
||||
|
||||
/*
|
||||
* Allocate buffer with headroom_needed space for the
|
||||
* fake physical layer header at the start.
|
||||
*/
|
||||
skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
|
||||
|
||||
if (!skb) {
|
||||
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
||||
sc->rxbufsize + sc->cachelsz - 1);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Cache-line-align. This is important (for the
|
||||
* 5210 at least) as not doing so causes bogus data
|
||||
* in rx'd frames.
|
||||
*/
|
||||
off = ((unsigned long)skb->data) % sc->cachelsz;
|
||||
if (off != 0)
|
||||
skb_reserve(skb, sc->cachelsz - off);
|
||||
|
||||
*skb_addr = pci_map_single(sc->pdev,
|
||||
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
|
||||
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
|
||||
dev_kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
{
|
||||
@@ -1105,37 +1136,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
struct sk_buff *skb = bf->skb;
|
||||
struct ath5k_desc *ds;
|
||||
|
||||
if (likely(skb == NULL)) {
|
||||
unsigned int off;
|
||||
|
||||
/*
|
||||
* Allocate buffer with headroom_needed space for the
|
||||
* fake physical layer header at the start.
|
||||
*/
|
||||
skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
|
||||
if (unlikely(skb == NULL)) {
|
||||
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
||||
sc->rxbufsize + sc->cachelsz - 1);
|
||||
if (!skb) {
|
||||
skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
/*
|
||||
* Cache-line-align. This is important (for the
|
||||
* 5210 at least) as not doing so causes bogus data
|
||||
* in rx'd frames.
|
||||
*/
|
||||
off = ((unsigned long)skb->data) % sc->cachelsz;
|
||||
if (off != 0)
|
||||
skb_reserve(skb, sc->cachelsz - off);
|
||||
|
||||
bf->skb = skb;
|
||||
bf->skbaddr = pci_map_single(sc->pdev,
|
||||
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
|
||||
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
|
||||
dev_kfree_skb(skb);
|
||||
bf->skb = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1178,6 +1183,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
struct ieee80211_rate *rate;
|
||||
unsigned int mrr_rate[3], mrr_tries[3];
|
||||
int i, ret;
|
||||
u16 hw_rate;
|
||||
u16 cts_rate = 0;
|
||||
u16 duration = 0;
|
||||
u8 rc_flags;
|
||||
|
||||
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
|
||||
|
||||
@@ -1185,11 +1194,30 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
rate = ieee80211_get_tx_rate(sc->hw, info);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
flags |= AR5K_TXDESC_NOACK;
|
||||
|
||||
rc_flags = info->control.rates[0].flags;
|
||||
hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
|
||||
rate->hw_value_short : rate->hw_value;
|
||||
|
||||
pktlen = skb->len;
|
||||
|
||||
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
flags |= AR5K_TXDESC_RTSENA;
|
||||
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
|
||||
duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
|
||||
sc->vif, pktlen, info));
|
||||
}
|
||||
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
flags |= AR5K_TXDESC_CTSENA;
|
||||
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
|
||||
duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
|
||||
sc->vif, pktlen, info));
|
||||
}
|
||||
|
||||
if (info->control.hw_key) {
|
||||
keyidx = info->control.hw_key->hw_key_idx;
|
||||
pktlen += info->control.hw_key->icv_len;
|
||||
@@ -1197,8 +1225,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
|
||||
(sc->power_level * 2),
|
||||
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
|
||||
info->control.rates[0].count, keyidx, 0, flags, 0, 0);
|
||||
hw_rate,
|
||||
info->control.rates[0].count, keyidx, 0, flags,
|
||||
cts_rate, duration);
|
||||
if (ret)
|
||||
goto err_unmap;
|
||||
|
||||
@@ -1664,7 +1693,8 @@ ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
struct ieee80211_rx_status rxs = {};
|
||||
struct ath5k_rx_status rs = {};
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb, *next_skb;
|
||||
dma_addr_t next_skb_addr;
|
||||
struct ath5k_softc *sc = (void *)data;
|
||||
struct ath5k_buf *bf, *bf_last;
|
||||
struct ath5k_desc *ds;
|
||||
@@ -1749,10 +1779,17 @@ ath5k_tasklet_rx(unsigned long data)
|
||||
goto next;
|
||||
}
|
||||
accept:
|
||||
next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
|
||||
|
||||
/*
|
||||
* If we can't replace bf->skb with a new skb under memory
|
||||
* pressure, just skip this packet
|
||||
*/
|
||||
if (!next_skb)
|
||||
goto next;
|
||||
|
||||
pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->skb = NULL;
|
||||
|
||||
skb_put(skb, rs.rs_datalen);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
@@ -1825,6 +1862,9 @@ accept:
|
||||
ath5k_check_ibss_tsf(sc, skb, &rxs);
|
||||
|
||||
__ieee80211_rx(sc->hw, skb, &rxs);
|
||||
|
||||
bf->skb = next_skb;
|
||||
bf->skbaddr = next_skb_addr;
|
||||
next:
|
||||
list_move_tail(&bf->list, &sc->rxbuf);
|
||||
} while (ath5k_rxbuf_setup(sc, bf) == 0);
|
||||
@@ -2207,18 +2247,13 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
||||
\********************/
|
||||
|
||||
static int
|
||||
ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
ath5k_init(struct ath5k_softc *sc)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
|
||||
if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
|
||||
goto out_ok;
|
||||
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
|
||||
|
||||
/*
|
||||
@@ -2250,15 +2285,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
|
||||
ath5k_hw_reset_key(ah, i);
|
||||
|
||||
__set_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
/* Set ack to be sent at low bit-rates */
|
||||
ath5k_hw_set_ack_bitrate_high(ah, false);
|
||||
|
||||
mod_timer(&sc->calib_tim, round_jiffies(jiffies +
|
||||
msecs_to_jiffies(ath5k_calinterval * 1000)));
|
||||
|
||||
out_ok:
|
||||
ret = 0;
|
||||
done:
|
||||
mmiowb();
|
||||
@@ -2313,7 +2345,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
|
||||
* stop is preempted).
|
||||
*/
|
||||
static int
|
||||
ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
|
||||
ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -2344,8 +2376,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
|
||||
}
|
||||
}
|
||||
ath5k_txbuf_free(sc, sc->bbuf);
|
||||
if (!is_suspend)
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
mmiowb();
|
||||
mutex_unlock(&sc->lock);
|
||||
@@ -2598,6 +2628,17 @@ ath5k_init_leds(struct ath5k_softc *sc)
|
||||
sc->led_pin = 1;
|
||||
sc->led_on = 1; /* active high */
|
||||
}
|
||||
/*
|
||||
* Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and
|
||||
* in emachines notebooks with AMBIT subsystem.
|
||||
*/
|
||||
if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN ||
|
||||
pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) {
|
||||
__set_bit(ATH_STAT_LEDSOFT, sc->status);
|
||||
sc->led_pin = 3;
|
||||
sc->led_on = 0; /* active low */
|
||||
}
|
||||
|
||||
if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
|
||||
goto out;
|
||||
|
||||
@@ -2745,12 +2786,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
|
||||
|
||||
static int ath5k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
return ath5k_init(hw->priv, false);
|
||||
return ath5k_init(hw->priv);
|
||||
}
|
||||
|
||||
static void ath5k_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
ath5k_stop_hw(hw->priv, false);
|
||||
ath5k_stop_hw(hw->priv);
|
||||
}
|
||||
|
||||
static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
@@ -2999,8 +3040,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
static int
|
||||
ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
const u8 *local_addr, const u8 *addr,
|
||||
struct ieee80211_key_conf *key)
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
int ret = 0;
|
||||
@@ -3023,7 +3064,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
|
||||
ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
|
||||
sta ? sta->addr : NULL);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "can't set the key\n");
|
||||
goto unlock;
|
||||
@@ -3082,6 +3124,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
|
||||
return ath5k_hw_get_tsf64(sc->ah);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
|
||||
ath5k_hw_set_tsf64(sc->ah, tsf);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_reset_tsf(struct ieee80211_hw *hw)
|
||||
{
|
||||
|
Reference in New Issue
Block a user