OSDN Git Service

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Sep 2010 19:52:34 +0000 (15:52 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Sep 2010 19:52:34 +0000 (15:52 -0400)
Conflicts:
drivers/net/wireless/ath/ath5k/base.c
net/mac80211/main.c

1  2 
MAINTAINERS
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/p54/txrx.c
net/mac80211/main.c
net/mac80211/rx.c
net/wireless/core.c
net/wireless/wext-core.c

diff --cc MAINTAINERS
Simple merge
@@@ -474,445 -740,310 +474,449 @@@ ath5k_setup_bands(struct ieee80211_hw *
        return 0;
  }
  
 -static int ath5k_pci_resume(struct device *dev)
 -{
 -      struct pci_dev *pdev = to_pci_dev(dev);
 -      struct ath5k_softc *sc = pci_get_drvdata(pdev);
 -
 -      /*
 -       * Suspend/Resume resets the PCI configuration space, so we have to
 -       * re-disable the RETRY_TIMEOUT register (0x41) to keep
 -       * PCI Tx retries from interfering with C3 CPU state
 -       */
 -      pci_write_config_byte(pdev, 0x41, 0);
 +/*
 + * Set/change channels. We always reset the chip.
 + * To accomplish this we must first cleanup any pending DMA,
 + * then restart stuff after a la  ath5k_init.
 + *
 + * Called with sc->lock.
 + */
 +static int
 +ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 +{
 +      ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
 +                "channel set, resetting (%u -> %u MHz)\n",
 +                sc->curchan->center_freq, chan->center_freq);
  
 -      ath5k_led_enable(sc);
 -      return 0;
 +      /*
 +       * To switch channels clear any pending DMA operations;
 +       * wait long enough for the RX fifo to drain, reset the
 +       * hardware at the new frequency, and then re-enable
 +       * the relevant bits of the h/w.
 +       */
 +      return ath5k_reset(sc, chan);
  }
 -#endif /* CONFIG_PM_SLEEP */
  
 +static void
 +ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
 +{
 +      sc->curmode = mode;
  
 -/***********************\
 -* Driver Initialization *
 -\***********************/
 +      if (mode == AR5K_MODE_11A) {
 +              sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
 +      } else {
 +              sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
 +      }
 +}
  
 -static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 +static void
 +ath5k_mode_setup(struct ath5k_softc *sc)
  {
 -      struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 -      struct ath5k_softc *sc = hw->priv;
 -      struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah);
 +      struct ath5k_hw *ah = sc->ah;
 +      u32 rfilt;
  
 -      return ath_reg_notifier_apply(wiphy, request, regulatory);
 +      /* configure rx filter */
 +      rfilt = sc->filter_flags;
 +      ath5k_hw_set_rx_filter(ah, rfilt);
 +
 +      if (ath5k_hw_hasbssidmask(ah))
 +              ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
 +
 +      /* configure operational mode */
 +      ath5k_hw_set_opmode(ah, sc->opmode);
 +
 +      ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
 +      ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
  }
  
 -static int
 -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 +static inline int
 +ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
  {
 -      struct ath5k_softc *sc = hw->priv;
 -      struct ath5k_hw *ah = sc->ah;
 -      struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
 -      u8 mac[ETH_ALEN] = {};
 -      int ret;
 +      int rix;
  
 -      ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
 +      /* return base rate on errors */
 +      if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES,
 +                      "hw_rix out of bounds: %x\n", hw_rix))
 +              return 0;
  
 -      /*
 -       * Check if the MAC has multi-rate retry support.
 -       * We do this by trying to setup a fake extended
 -       * descriptor.  MAC's that don't have support will
 -       * return false w/o doing anything.  MAC's that do
 -       * support it will return true w/o doing anything.
 -       */
 -      ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
 +      rix = sc->rate_idx[sc->curband->band][hw_rix];
 +      if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
 +              rix = 0;
  
 -      if (ret < 0)
 -              goto err;
 -      if (ret > 0)
 -              __set_bit(ATH_STAT_MRRETRY, sc->status);
 +      return rix;
 +}
  
 -      /*
 -       * Collect the channel list.  The 802.11 layer
 -       * is resposible for filtering this list based
 -       * on settings like the phy mode and regulatory
 -       * domain restrictions.
 -       */
 -      ret = ath5k_setup_bands(hw);
 -      if (ret) {
 -              ATH5K_ERR(sc, "can't get channels\n");
 -              goto err;
 -      }
 +/***************\
 +* Buffers setup *
 +\***************/
  
 -      /* NB: setup here so ath5k_rate_update is happy */
 -      if (test_bit(AR5K_MODE_11A, ah->ah_modes))
 -              ath5k_setcurmode(sc, AR5K_MODE_11A);
 -      else
 -              ath5k_setcurmode(sc, AR5K_MODE_11B);
 +static
 +struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
 +{
 +      struct ath_common *common = ath5k_hw_common(sc->ah);
 +      struct sk_buff *skb;
  
        /*
 -       * Allocate tx+rx descriptors and populate the lists.
 +       * Allocate buffer with headroom_needed space for the
 +       * fake physical layer header at the start.
         */
 -      ret = ath5k_desc_alloc(sc, pdev);
 -      if (ret) {
 -              ATH5K_ERR(sc, "can't allocate descriptors\n");
 -              goto err;
 -      }
 +      skb = ath_rxbuf_alloc(common,
 +                            common->rx_bufsize,
 +                            GFP_ATOMIC);
  
 -      /*
 -       * Allocate hardware transmit queues: one queue for
 -       * beacon frames and one data queue for each QoS
 -       * priority.  Note that hw functions handle reseting
 -       * these queues at the needed time.
 -       */
 -      ret = ath5k_beaconq_setup(ah);
 -      if (ret < 0) {
 -              ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
 -              goto err_desc;
 -      }
 -      sc->bhalq = ret;
 -      sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
 -      if (IS_ERR(sc->cabq)) {
 -              ATH5K_ERR(sc, "can't setup cab queue\n");
 -              ret = PTR_ERR(sc->cabq);
 -              goto err_bhal;
 +      if (!skb) {
 +              ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
 +                              common->rx_bufsize);
 +              return NULL;
        }
  
 -      sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
 -      if (IS_ERR(sc->txq)) {
 -              ATH5K_ERR(sc, "can't setup xmit queue\n");
 -              ret = PTR_ERR(sc->txq);
 -              goto err_queues;
 +      *skb_addr = pci_map_single(sc->pdev,
 +                                 skb->data, common->rx_bufsize,
 +                                 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;
 +}
  
 -      tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
 -      tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
 -      tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
 -      tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
 -      tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
 -
 -      INIT_WORK(&sc->reset_work, ath5k_reset_work);
 +static int
 +ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 +{
 +      struct ath5k_hw *ah = sc->ah;
 +      struct sk_buff *skb = bf->skb;
 +      struct ath5k_desc *ds;
 +      int ret;
  
 -      ret = ath5k_eeprom_read_mac(ah, mac);
 -      if (ret) {
 -              ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
 -                      sc->pdev->device);
 -              goto err_queues;
 +      if (!skb) {
 +              skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
 +              if (!skb)
 +                      return -ENOMEM;
 +              bf->skb = skb;
        }
  
 -      SET_IEEE80211_PERM_ADDR(hw, mac);
 -      /* All MAC address bits matter for ACKs */
 -      memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
 -      ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
 -
 -      regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
 -      ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
 +      /*
 +       * Setup descriptors.  For receive we always terminate
 +       * the descriptor list with a self-linked entry so we'll
 +       * not get overrun under high load (as can happen with a
 +       * 5212 when ANI processing enables PHY error frames).
 +       *
 +       * To ensure the last descriptor is self-linked we create
 +       * each descriptor as self-linked and add it to the end.  As
 +       * each additional descriptor is added the previous self-linked
 +       * entry is "fixed" naturally.  This should be safe even
 +       * if DMA is happening.  When processing RX interrupts we
 +       * never remove/process the last, self-linked, entry on the
 +       * descriptor list.  This ensures the hardware always has
 +       * someplace to write a new frame.
 +       */
 +      ds = bf->desc;
 +      ds->ds_link = bf->daddr;        /* link to self */
 +      ds->ds_data = bf->skbaddr;
 +      ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
        if (ret) {
 -              ATH5K_ERR(sc, "can't initialize regulatory system\n");
 -              goto err_queues;
 +              ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__);
 +              return ret;
        }
  
 -      ret = ieee80211_register_hw(hw);
 -      if (ret) {
 -              ATH5K_ERR(sc, "can't register ieee80211 hw\n");
 -              goto err_queues;
 -      }
 +      if (sc->rxlink != NULL)
 +              *sc->rxlink = bf->daddr;
 +      sc->rxlink = &ds->ds_link;
 +      return 0;
 +}
  
 -      if (!ath_is_world_regd(regulatory))
 -              regulatory_hint(hw->wiphy, regulatory->alpha2);
 +static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
 +{
 +      struct ieee80211_hdr *hdr;
 +      enum ath5k_pkt_type htype;
 +      __le16 fc;
  
 -      ath5k_init_leds(sc);
 +      hdr = (struct ieee80211_hdr *)skb->data;
 +      fc = hdr->frame_control;
  
 -      ath5k_sysfs_register(sc);
 +      if (ieee80211_is_beacon(fc))
 +              htype = AR5K_PKT_TYPE_BEACON;
 +      else if (ieee80211_is_probe_resp(fc))
 +              htype = AR5K_PKT_TYPE_PROBE_RESP;
 +      else if (ieee80211_is_atim(fc))
 +              htype = AR5K_PKT_TYPE_ATIM;
 +      else if (ieee80211_is_pspoll(fc))
 +              htype = AR5K_PKT_TYPE_PSPOLL;
 +      else
 +              htype = AR5K_PKT_TYPE_NORMAL;
  
 -      return 0;
 -err_queues:
 -      ath5k_txq_release(sc);
 -err_bhal:
 -      ath5k_hw_release_tx_queue(ah, sc->bhalq);
 -err_desc:
 -      ath5k_desc_free(sc, pdev);
 -err:
 -      return ret;
 +      return htype;
  }
  
 -static void
 -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 -{
 -      struct ath5k_softc *sc = hw->priv;
 +static int
 +ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 +                struct ath5k_txq *txq, int padsize)
 +{
 +      struct ath5k_hw *ah = sc->ah;
 +      struct ath5k_desc *ds = bf->desc;
 +      struct sk_buff *skb = bf->skb;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +      unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
 +      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;
  
 -      /*
 -       * NB: the order of these is important:
 -       * o call the 802.11 layer before detaching ath5k_hw to
 -       *   insure callbacks into the driver to delete global
 -       *   key cache entries can be handled
 -       * o reclaim the tx queue data structures after calling
 -       *   the 802.11 layer as we'll get called back to reclaim
 -       *   node state and potentially want to use them
 -       * o to cleanup the tx queues the hal is called, so detach
 -       *   it last
 -       * XXX: ??? detach ath5k_hw ???
 -       * Other than that, it's straightforward...
 -       */
 -      ieee80211_unregister_hw(hw);
 -      ath5k_desc_free(sc, pdev);
 -      ath5k_txq_release(sc);
 -      ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
 -      ath5k_unregister_leds(sc);
 +      flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
  
 -      ath5k_sysfs_unregister(sc);
 -      /*
 -       * NB: can't reclaim these until after ieee80211_ifdetach
 -       * returns because we'll get called back to reclaim node
 -       * state and potentially want to use them.
 -       */
 -}
 +      /* XXX endianness */
 +      bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
 +                      PCI_DMA_TODEVICE);
  
 +      rate = ieee80211_get_tx_rate(sc->hw, info);
++      if (!rate) {
++              ret = -EINVAL;
++              goto err_unmap;
++      }
  
 +      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;
  
 -/********************\
 -* Channel/mode setup *
 -\********************/
 +      pktlen = skb->len;
  
 -/*
 - * Convert IEEE channel number to MHz frequency.
 - */
 -static inline short
 -ath5k_ieee2mhz(short chan)
 -{
 -      if (chan <= 14 || chan >= 27)
 -              return ieee80211chan2mhz(chan);
 -      else
 -              return 2212 + chan * 20;
 -}
 +      /* FIXME: If we are in g mode and rate is a CCK rate
 +       * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
 +       * from tx power (value is in dB units already) */
 +      if (info->control.hw_key) {
 +              keyidx = info->control.hw_key->hw_key_idx;
 +              pktlen += info->control.hw_key->icv_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));
 +      }
 +      ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
 +              ieee80211_get_hdrlen_from_skb(skb), padsize,
 +              get_hw_packet_type(skb),
 +              (sc->power_level * 2),
 +              hw_rate,
 +              info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
 +              cts_rate, duration);
 +      if (ret)
 +              goto err_unmap;
  
 -/*
 - * Returns true for the channel numbers used without all_channels modparam.
 - */
 -static bool ath5k_is_standard_channel(short chan)
 -{
 -      return ((chan <= 14) ||
 -              /* UNII 1,2 */
 -              ((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
 -              /* midband */
 -              ((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
 -              /* UNII-3 */
 -              ((chan & 3) == 1 && chan >= 149 && chan <= 165));
 +      memset(mrr_rate, 0, sizeof(mrr_rate));
 +      memset(mrr_tries, 0, sizeof(mrr_tries));
 +      for (i = 0; i < 3; i++) {
 +              rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
 +              if (!rate)
 +                      break;
 +
 +              mrr_rate[i] = rate->hw_value;
 +              mrr_tries[i] = info->control.rates[i + 1].count;
 +      }
 +
 +      ath5k_hw_setup_mrr_tx_desc(ah, ds,
 +              mrr_rate[0], mrr_tries[0],
 +              mrr_rate[1], mrr_tries[1],
 +              mrr_rate[2], mrr_tries[2]);
 +
 +      ds->ds_link = 0;
 +      ds->ds_data = bf->skbaddr;
 +
 +      spin_lock_bh(&txq->lock);
 +      list_add_tail(&bf->list, &txq->q);
 +      txq->txq_len++;
 +      if (txq->link == NULL) /* is this first packet? */
 +              ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
 +      else /* no, so only link it */
 +              *txq->link = bf->daddr;
 +
 +      txq->link = &ds->ds_link;
 +      ath5k_hw_start_tx_dma(ah, txq->qnum);
 +      mmiowb();
 +      spin_unlock_bh(&txq->lock);
 +
 +      return 0;
 +err_unmap:
 +      pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
 +      return ret;
  }
  
 -static unsigned int
 -ath5k_copy_channels(struct ath5k_hw *ah,
 -              struct ieee80211_channel *channels,
 -              unsigned int mode,
 -              unsigned int max)
 +/*******************\
 +* Descriptors setup *
 +\*******************/
 +
 +static int
 +ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
  {
 -      unsigned int i, count, size, chfreq, freq, ch;
 +      struct ath5k_desc *ds;
 +      struct ath5k_buf *bf;
 +      dma_addr_t da;
 +      unsigned int i;
 +      int ret;
  
 -      if (!test_bit(mode, ah->ah_modes))
 -              return 0;
 +      /* allocate descriptors */
 +      sc->desc_len = sizeof(struct ath5k_desc) *
 +                      (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
 +      sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
 +      if (sc->desc == NULL) {
 +              ATH5K_ERR(sc, "can't allocate descriptors\n");
 +              ret = -ENOMEM;
 +              goto err;
 +      }
 +      ds = sc->desc;
 +      da = sc->desc_daddr;
 +      ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
 +              ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
  
 -      switch (mode) {
 -      case AR5K_MODE_11A:
 -      case AR5K_MODE_11A_TURBO:
 -              /* 1..220, but 2GHz frequencies are filtered by check_channel */
 -              size = 220 ;
 -              chfreq = CHANNEL_5GHZ;
 -              break;
 -      case AR5K_MODE_11B:
 -      case AR5K_MODE_11G:
 -      case AR5K_MODE_11G_TURBO:
 -              size = 26;
 -              chfreq = CHANNEL_2GHZ;
 -              break;
 -      default:
 -              ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
 -              return 0;
 +      bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
 +                      sizeof(struct ath5k_buf), GFP_KERNEL);
 +      if (bf == NULL) {
 +              ATH5K_ERR(sc, "can't allocate bufptr\n");
 +              ret = -ENOMEM;
 +              goto err_free;
        }
 +      sc->bufptr = bf;
  
 -      for (i = 0, count = 0; i < size && max > 0; i++) {
 -              ch = i + 1 ;
 -              freq = ath5k_ieee2mhz(ch);
 +      INIT_LIST_HEAD(&sc->rxbuf);
 +      for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
 +              bf->desc = ds;
 +              bf->daddr = da;
 +              list_add_tail(&bf->list, &sc->rxbuf);
 +      }
  
 -              /* Check if channel is supported by the chipset */
 -              if (!ath5k_channel_ok(ah, freq, chfreq))
 -                      continue;
 +      INIT_LIST_HEAD(&sc->txbuf);
 +      sc->txbuf_len = ATH_TXBUF;
 +      for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
 +                      da += sizeof(*ds)) {
 +              bf->desc = ds;
 +              bf->daddr = da;
 +              list_add_tail(&bf->list, &sc->txbuf);
 +      }
  
 -              if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
 -                      continue;
 +      /* beacon buffer */
 +      bf->desc = ds;
 +      bf->daddr = da;
 +      sc->bbuf = bf;
  
 -              /* Write channel info and increment counter */
 -              channels[count].center_freq = freq;
 -              channels[count].band = (chfreq == CHANNEL_2GHZ) ?
 -                      IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
 -              switch (mode) {
 -              case AR5K_MODE_11A:
 -              case AR5K_MODE_11G:
 -                      channels[count].hw_value = chfreq | CHANNEL_OFDM;
 -                      break;
 -              case AR5K_MODE_11A_TURBO:
 -              case AR5K_MODE_11G_TURBO:
 -                      channels[count].hw_value = chfreq |
 -                              CHANNEL_OFDM | CHANNEL_TURBO;
 -                      break;
 -              case AR5K_MODE_11B:
 -                      channels[count].hw_value = CHANNEL_B;
 -              }
 +      return 0;
 +err_free:
 +      pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
 +err:
 +      sc->desc = NULL;
 +      return ret;
 +}
  
 -              count++;
 -              max--;
 -      }
 +static void
 +ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
 +{
 +      struct ath5k_buf *bf;
 +
 +      ath5k_txbuf_free_skb(sc, sc->bbuf);
 +      list_for_each_entry(bf, &sc->txbuf, list)
 +              ath5k_txbuf_free_skb(sc, bf);
 +      list_for_each_entry(bf, &sc->rxbuf, list)
 +              ath5k_rxbuf_free_skb(sc, bf);
 +
 +      /* Free memory associated with all descriptors */
 +      pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
 +      sc->desc = NULL;
 +      sc->desc_daddr = 0;
 +
 +      kfree(sc->bufptr);
 +      sc->bufptr = NULL;
 +      sc->bbuf = NULL;
 +}
 +
 +
 +/**************\
 +* Queues setup *
 +\**************/
 +
 +static struct ath5k_txq *
 +ath5k_txq_setup(struct ath5k_softc *sc,
 +              int qtype, int subtype)
 +{
 +      struct ath5k_hw *ah = sc->ah;
 +      struct ath5k_txq *txq;
 +      struct ath5k_txq_info qi = {
 +              .tqi_subtype = subtype,
 +              /* XXX: default values not correct for B and XR channels,
 +               * but who cares? */
 +              .tqi_aifs = AR5K_TUNE_AIFS,
 +              .tqi_cw_min = AR5K_TUNE_CWMIN,
 +              .tqi_cw_max = AR5K_TUNE_CWMAX
 +      };
 +      int qnum;
  
 -      return count;
 +      /*
 +       * Enable interrupts only for EOL and DESC conditions.
 +       * We mark tx descriptors to receive a DESC interrupt
 +       * when a tx queue gets deep; otherwise we wait for the
 +       * EOL to reap descriptors.  Note that this is done to
 +       * reduce interrupt load and this only defers reaping
 +       * descriptors, never transmitting frames.  Aside from
 +       * reducing interrupts this also permits more concurrency.
 +       * The only potential downside is if the tx queue backs
 +       * up in which case the top half of the kernel may backup
 +       * due to a lack of tx descriptors.
 +       */
 +      qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
 +                              AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
 +      qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
 +      if (qnum < 0) {
 +              /*
 +               * NB: don't print a message, this happens
 +               * normally on parts with too few tx queues
 +               */
 +              return ERR_PTR(qnum);
 +      }
 +      if (qnum >= ARRAY_SIZE(sc->txqs)) {
 +              ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
 +                      qnum, ARRAY_SIZE(sc->txqs));
 +              ath5k_hw_release_tx_queue(ah, qnum);
 +              return ERR_PTR(-EINVAL);
 +      }
 +      txq = &sc->txqs[qnum];
 +      if (!txq->setup) {
 +              txq->qnum = qnum;
 +              txq->link = NULL;
 +              INIT_LIST_HEAD(&txq->q);
 +              spin_lock_init(&txq->lock);
 +              txq->setup = true;
 +              txq->txq_len = 0;
 +              txq->txq_poll_mark = false;
 +              txq->txq_stuck = 0;
 +      }
 +      return &sc->txqs[qnum];
  }
  
 -static void
 -ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
 +static int
 +ath5k_beaconq_setup(struct ath5k_hw *ah)
  {
 -      u8 i;
 -
 -      for (i = 0; i < AR5K_MAX_RATES; i++)
 -              sc->rate_idx[b->band][i] = -1;
 +      struct ath5k_txq_info qi = {
 +              /* XXX: default values not correct for B and XR channels,
 +               * but who cares? */
 +              .tqi_aifs = AR5K_TUNE_AIFS,
 +              .tqi_cw_min = AR5K_TUNE_CWMIN,
 +              .tqi_cw_max = AR5K_TUNE_CWMAX,
 +              /* NB: for dynamic turbo, don't enable any other interrupts */
 +              .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
 +      };
  
 -      for (i = 0; i < b->n_bitrates; i++) {
 -              sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
 -              if (b->bitrates[i].hw_value_short)
 -                      sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
 -      }
 +      return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
  }
  
  static int
Simple merge
@@@ -868,7 -732,12 +868,13 @@@ void ieee80211_unregister_hw(struct iee
  
        rtnl_unlock();
  
+       /*
+        * Now all work items will be gone, but the
+        * timer might still be armed, so delete it
+        */
+       del_timer_sync(&local->work_timer);
 +      cancel_work_sync(&local->restart_work);
        cancel_work_sync(&local->reconfig_filter);
  
        ieee80211_clear_tx_pending(local);
Simple merge
Simple merge
Simple merge