struct ieee80211_tx_queue_stats *stats);
  static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
  static void ath5k_reset_tsf(struct ieee80211_hw *hw);
- static int ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb);
 -static int ath5k_beacon_update(struct ieee80211_hw *hw,
++static int ath5k_beacon_update(struct ath5k_softc *sc,
+               struct sk_buff *skb);
+ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+               struct ieee80211_vif *vif,
+               struct ieee80211_bss_conf *bss_conf,
+               u32 changes);
  
  static struct ieee80211_ops ath5k_hw_ops = {
        .tx             = ath5k_tx,
                sc->opmode != NL80211_IFTYPE_MESH_POINT &&
                test_bit(ATH_STAT_PROMISC, sc->status))
                rfilt |= AR5K_RX_FILTER_PROM;
-       if (sc->opmode == NL80211_IFTYPE_STATION ||
+       if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
 -              sc->opmode == NL80211_IFTYPE_ADHOC) {
 +              sc->opmode == NL80211_IFTYPE_ADHOC ||
 +              sc->opmode == NL80211_IFTYPE_AP)
                rfilt |= AR5K_RX_FILTER_BEACON;
 -      }
 +      if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
 +              rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
 +                      AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
  
        /* Set filters */
 -      ath5k_hw_set_rx_filter(ah,rfilt);
 +      ath5k_hw_set_rx_filter(ah, rfilt);
  
        /* Set multicast bits */
        ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
                mmiowb();
        }
  
 -end:
        return ret;
  }
+ static void
+ set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ {
+       struct ath5k_softc *sc = hw->priv;
+       struct ath5k_hw *ah = sc->ah;
+       u32 rfilt;
+       rfilt = ath5k_hw_get_rx_filter(ah);
+       if (enable)
+               rfilt |= AR5K_RX_FILTER_BEACON;
+       else
+               rfilt &= ~AR5K_RX_FILTER_BEACON;
+       ath5k_hw_set_rx_filter(ah, rfilt);
+       sc->filter_flags = rfilt;
+ }
  
+ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_bss_conf *bss_conf,
+                                   u32 changes)
+ {
+       struct ath5k_softc *sc = hw->priv;
+       if (changes & BSS_CHANGED_ASSOC) {
+               mutex_lock(&sc->lock);
+               sc->assoc = bss_conf->assoc;
+               if (sc->opmode == NL80211_IFTYPE_STATION)
+                       set_beacon_filter(hw, sc->assoc);
+               mutex_unlock(&sc->lock);
+       }
+ }
 
  
                        bf->bf_mpdu = skb;
                        bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
-                                        skb_end_pointer(skb) - skb->head,
+                                        sc->sc_rxbufsize,
                                         PCI_DMA_FROMDEVICE);
                        bf->bf_dmacontext = bf->bf_buf_addr;
 -                      ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
                }
                sc->sc_rxlink = NULL;
  
                        }
                }
  
 -              /* XXX: we do not support frames spanning
 -               * multiple descriptors */
 -              bf->bf_status |= ATH_BUFSTATUS_DONE;
 -
                skb = bf->bf_mpdu;
 -              if (skb == NULL) {              /* XXX ??? can this happen */
 -                      spin_unlock_bh(&sc->sc_rxbuflock);
 +              if (!skb)
                        continue;
 -              }
 -              /*
 -               * Now we know it's a completed frame, we can indicate the
 -               * frame. Remove the previous holding descriptor and leave
 -               * this one in the queue as the new holding descriptor.
 -               */
 -              if (bf_held) {
 -                      list_del(&bf_held->list);
 -                      bf_held->bf_status &= ~ATH_BUFSTATUS_STALE;
 -                      if (bf_held->bf_status & ATH_BUFSTATUS_FREE) {
 -                              list_add_tail(&bf_held->list, &sc->sc_rxbuf);
 -                              /* try to requeue this descriptor */
 -                              ath_rx_buf_link(sc, bf_held);
 -                      }
 -              }
  
 -              bf->bf_status |= ATH_BUFSTATUS_STALE;
 -              bf_held = bf;
                /*
 -               * Release the lock here in case ieee80211_input() return
 -               * the frame immediately by calling ath_rx_mpdu_requeue().
 +               * If we're asked to flush receive queue, directly
 +               * chain it back at the queue without processing it.
                 */
 -              spin_unlock_bh(&sc->sc_rxbuflock);
 +              if (flush)
 +                      goto requeue;
  
 -              if (flush) {
 -                      /*
 -                       * If we're asked to flush receive queue, directly
 -                       * chain it back at the queue without processing it.
 -                       */
 -                      goto rx_next;
 -              }
 +              if (!ds->ds_rxstat.rs_datalen)
 +                      goto requeue;
  
 -              hdr = (struct ieee80211_hdr *)skb->data;
 -              fc = hdr->frame_control;
 -              memset(&rx_status, 0, sizeof(struct ath_recv_status));
 +              /* The status portion of the descriptor could get corrupted. */
 +              if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
 +                      goto requeue;
  
 -              if (ds->ds_rxstat.rs_more) {
 -                      /*
 -                       * Frame spans multiple descriptors; this
 -                       * cannot happen yet as we don't support
 -                       * jumbograms.  If not in monitor mode,
 -                       * discard the frame.
 -                       */
 -#ifndef ERROR_FRAMES
 -                      /*
 -                       * Enable this if you want to see
 -                       * error frames in Monitor mode.
 -                       */
 -                      if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
 -                              goto rx_next;
 -#endif
 -                      /* fall thru for monitor mode handling... */
 -              } else if (ds->ds_rxstat.rs_status != 0) {
 -                      if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
 -                              rx_status.flags |= ATH_RX_FCS_ERROR;
 -                      if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
 -                              phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
 -                              goto rx_next;
 -                      }
 +              if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
 +                      goto requeue;
  
 -                      if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
 -                              /*
 -                               * Decrypt error. We only mark packet status
 -                               * here and always push up the frame up to let
 -                               * mac80211 handle the actual error case, be
 -                               * it no decryption key or real decryption
 -                               * error. This let us keep statistics there.
 -                               */
 -                              rx_status.flags |= ATH_RX_DECRYPT_ERROR;
 -                      } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
 -                              /*
 -                               * Demic error. We only mark frame status here
 -                               * and always push up the frame up to let
 -                               * mac80211 handle the actual error case. This
 -                               * let us keep statistics there. Hardware may
 -                               * post a false-positive MIC error.
 -                               */
 -                              if (ieee80211_is_ctl(fc))
 -                                      /*
 -                                       * Sometimes, we get invalid
 -                                       * MIC failures on valid control frames.
 -                                       * Remove these mic errors.
 -                                       */
 -                                      ds->ds_rxstat.rs_status &=
 -                                              ~ATH9K_RXERR_MIC;
 -                              else
 -                                      rx_status.flags |= ATH_RX_MIC_ERROR;
 -                      }
 -                      /*
 -                       * Reject error frames with the exception of
 -                       * decryption and MIC failures. For monitor mode,
 -                       * we also ignore the CRC error.
 -                       */
 -                      if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
 -                              if (ds->ds_rxstat.rs_status &
 -                                  ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
 -                                      ATH9K_RXERR_CRC))
 -                                      goto rx_next;
 -                      } else {
 -                              if (ds->ds_rxstat.rs_status &
 -                                  ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
 -                                      goto rx_next;
 -                              }
 -                      }
 -              }
 -              /*
 -               * The status portion of the descriptor could get corrupted.
 -               */
 -              if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
 -                      goto rx_next;
 -              /*
 -               * Sync and unmap the frame.  At this point we're
 -               * committed to passing the sk_buff somewhere so
 -               * clear buf_skb; this means a new sk_buff must be
 -               * allocated when the rx descriptor is setup again
 -               * to receive another frame.
 -               */
 -              skb_put(skb, ds->ds_rxstat.rs_datalen);
 -              skb->protocol = cpu_to_be16(ETH_P_CONTROL);
 -              rx_status.tsf = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
 -              rx_status.rateieee =
 -                      sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate;
 -              rx_status.rateKbps =
 -                      sc->sc_hwmap[ds->ds_rxstat.rs_rate].rateKbps;
 -              rx_status.ratecode = ds->ds_rxstat.rs_rate;
 -
 -              /* HT rate */
 -              if (rx_status.ratecode & 0x80) {
 -                      /* TODO - add table to avoid division */
 -                      if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) {
 -                              rx_status.flags |= ATH_RX_40MHZ;
 -                              rx_status.rateKbps =
 -                                      (rx_status.rateKbps * 27) / 13;
 -                      }
 -                      if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
 -                              rx_status.rateKbps =
 -                                      (rx_status.rateKbps * 10) / 9;
 -                      else
 -                              rx_status.flags |= ATH_RX_SHORT_GI;
 -              }
 +              /* Ensure we always have an skb to requeue once we are done
 +               * processing the current buffer's skb */
 +              requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
  
 -              /* sc_noise_floor is only available when the station
 -                 attaches to an AP, so we use a default value
 -                 if we are not yet attached. */
 -              rx_status.abs_rssi =
 -                      ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor;
 +              /* If there is no memory we ignore the current RX'd frame,
 +               * tell hardware it can give us a new frame using the old
 +               * skb and put it at the tail of the sc->sc_rxbuf list for
 +               * processing. */
 +              if (!requeue_skb)
 +                      goto requeue;
  
-               /* Sync and unmap the frame */
-               pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
-                                           skb_tailroom(skb),
+               pci_dma_sync_single_for_cpu(sc->pdev,
+                                           bf->bf_buf_addr,
+                                           sc->sc_rxbufsize,
                                            PCI_DMA_FROMDEVICE);
 -              pci_unmap_single(sc->pdev,
 -                               bf->bf_buf_addr,
 +              pci_unmap_single(sc->pdev, bf->bf_buf_addr,
                                 sc->sc_rxbufsize,
                                 PCI_DMA_FROMDEVICE);
  
 
  
  int proto_register(struct proto *prot, int alloc_slab)
  {
-       char *request_sock_slab_name = NULL;
-       char *timewait_sock_slab_name;
- 
        if (alloc_slab) {
                prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
 -                                             SLAB_HWCACHE_ALIGN, NULL);
 +                                      SLAB_HWCACHE_ALIGN | prot->slab_flags,
 +                                      NULL);
  
                if (prot->slab == NULL) {
                        printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
                if (prot->twsk_prot != NULL) {
                        static const char mask[] = "tw_sock_%s";
  
-                       timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+                       prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
  
-                       if (timewait_sock_slab_name == NULL)
+                       if (prot->twsk_prot->twsk_slab_name == NULL)
                                goto out_free_request_sock_slab;
  
-                       sprintf(timewait_sock_slab_name, mask, prot->name);
+                       sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name);
                        prot->twsk_prot->twsk_slab =
-                               kmem_cache_create(timewait_sock_slab_name,
+                               kmem_cache_create(prot->twsk_prot->twsk_slab_name,
                                                  prot->twsk_prot->twsk_obj_size,
 -                                                0, SLAB_HWCACHE_ALIGN,
 +                                                0,
 +                                                SLAB_HWCACHE_ALIGN |
 +                                                      prot->slab_flags,
                                                  NULL);
                        if (prot->twsk_prot->twsk_slab == NULL)
                                goto out_free_timewait_sock_slab_name;