Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Wed, 5 Mar 2008 20:26:41 +0000 (12:26 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Mar 2008 20:26:41 +0000 (12:26 -0800)
Conflicts:

net/mac80211/rc80211_pid_algo.c

1  2 
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/libertas/cmdresp.c
drivers/net/wireless/p54common.c
drivers/net/wireless/p54common.h
net/core/neighbour.c
net/core/netpoll.c
net/ipv4/Kconfig
net/ipv4/ipconfig.c
net/ipv4/tcp_input.c
net/sctp/proc.c

@@@ -95,29 -95,28 +95,29 @@@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_
   * data in there. This data is the same for all devices, so we don't
   * get concurrency issues */
  #define RATETAB_ENT(_rateid, _flags) \
 -      {                                                       \
 -              .rate   = B43legacy_RATE_TO_100KBPS(_rateid),   \
 -              .val    = (_rateid),                            \
 -              .val2   = (_rateid),                            \
 -              .flags  = (_flags),                             \
 +      {                                                               \
 +              .bitrate        = B43legacy_RATE_TO_100KBPS(_rateid),   \
 +              .hw_value       = (_rateid),                            \
 +              .flags          = (_flags),                             \
        }
 +/*
 + * NOTE: When changing this, sync with xmit.c's
 + *     b43legacy_plcp_get_bitrate_idx_* functions!
 + */
  static struct ieee80211_rate __b43legacy_ratetable[] = {
 -      RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
 -      RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
 -      RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
 -      RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
 -      RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
 +      RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
 +      RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
 +      RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
 +      RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
 +      RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
  };
 -#define b43legacy_a_ratetable         (__b43legacy_ratetable + 4)
 -#define b43legacy_a_ratetable_size    8
  #define b43legacy_b_ratetable         (__b43legacy_ratetable + 0)
  #define b43legacy_b_ratetable_size    4
  #define b43legacy_g_ratetable         (__b43legacy_ratetable + 0)
  
  #define CHANTAB_ENT(_chanid, _freq) \
        {                                                       \
 -              .chan   = (_chanid),                            \
 -              .freq   = (_freq),                              \
 -              .val    = (_chanid),                            \
 -              .flag   = IEEE80211_CHAN_W_SCAN |               \
 -                        IEEE80211_CHAN_W_ACTIVE_SCAN |        \
 -                        IEEE80211_CHAN_W_IBSS,                \
 -              .power_level    = 0x0A,                         \
 -              .antenna_max    = 0xFF,                         \
 +              .center_freq    = (_freq),                      \
 +              .hw_value       = (_chanid),                    \
        }
  static struct ieee80211_channel b43legacy_bg_chantable[] = {
        CHANTAB_ENT(1, 2412),
        CHANTAB_ENT(13, 2472),
        CHANTAB_ENT(14, 2484),
  };
 -#define b43legacy_bg_chantable_size   ARRAY_SIZE(b43legacy_bg_chantable)
 +
 +static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
 +      .channels = b43legacy_bg_chantable,
 +      .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
 +      .bitrates = b43legacy_b_ratetable,
 +      .n_bitrates = b43legacy_b_ratetable_size,
 +};
 +
 +static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
 +      .channels = b43legacy_bg_chantable,
 +      .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
 +      .bitrates = b43legacy_g_ratetable,
 +      .n_bitrates = b43legacy_g_ratetable_size,
 +};
  
  static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
  static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
@@@ -805,8 -797,9 +805,8 @@@ static void b43legacy_generate_noise_sa
  {
        b43legacy_jssi_write(dev, 0x7F7F7F7F);
        b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 -                        b43legacy_read32(dev,
 -                        B43legacy_MMIO_MACCMD)
 -                        | (1 << 4));
 +                        b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
 +                        | B43legacy_MACCMD_BGNOISE);
        B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
                            dev->phy.channel);
  }
@@@ -895,18 -888,18 +895,18 @@@ static void handle_irq_tbtt_indication(
                if (1/*FIXME: the last PSpoll frame was sent successfully */)
                        b43legacy_power_saving_ctl_bits(dev, -1, -1);
        }
 -      dev->reg124_set_0x4 = 0;
        if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
 -              dev->reg124_set_0x4 = 1;
 +              dev->dfq_valid = 1;
  }
  
  static void handle_irq_atim_end(struct b43legacy_wldev *dev)
  {
 -      if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
 -              return;
 -      b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 -                        b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
 -                        | 0x4);
 +      if (dev->dfq_valid) {
 +              b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 +                                b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
 +                                | B43legacy_MACCMD_DFQ_VALID);
 +              dev->dfq_valid = 0;
 +      }
  }
  
  static void handle_irq_pmq(struct b43legacy_wldev *dev)
@@@ -962,77 -955,32 +962,77 @@@ static void b43legacy_write_beacon_temp
                                            u16 ram_offset,
                                            u16 shm_size_offset, u8 rate)
  {
 -      int len;
 -      const u8 *data;
  
 -      B43legacy_WARN_ON(!dev->cached_beacon);
 -      len = min((size_t)dev->cached_beacon->len,
 +      unsigned int i, len, variable_len;
 +      const struct ieee80211_mgmt *bcn;
 +      const u8 *ie;
 +      bool tim_found = 0;
 +
 +      bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
 +      len = min((size_t)dev->wl->current_beacon->len,
                  0x200 - sizeof(struct b43legacy_plcp_hdr6));
 -      data = (const u8 *)(dev->cached_beacon->data);
 -      b43legacy_write_template_common(dev, data,
 -                                      len, ram_offset,
 +
 +      b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
                                        shm_size_offset, rate);
 +
 +      /* Find the position of the TIM and the DTIM_period value
 +       * and write them to SHM. */
 +      ie = bcn->u.beacon.variable;
 +      variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
 +      for (i = 0; i < variable_len - 2; ) {
 +              uint8_t ie_id, ie_len;
 +
 +              ie_id = ie[i];
 +              ie_len = ie[i + 1];
 +              if (ie_id == 5) {
 +                      u16 tim_position;
 +                      u16 dtim_period;
 +                      /* This is the TIM Information Element */
 +
 +                      /* Check whether the ie_len is in the beacon data range. */
 +                      if (variable_len < ie_len + 2 + i)
 +                              break;
 +                      /* A valid TIM is at least 4 bytes long. */
 +                      if (ie_len < 4)
 +                              break;
 +                      tim_found = 1;
 +
 +                      tim_position = sizeof(struct b43legacy_plcp_hdr6);
 +                      tim_position += offsetof(struct ieee80211_mgmt,
 +                                               u.beacon.variable);
 +                      tim_position += i;
 +
 +                      dtim_period = ie[i + 3];
 +
 +                      b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
 +                                      B43legacy_SHM_SH_TIMPOS, tim_position);
 +                      b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
 +                                      B43legacy_SHM_SH_DTIMP, dtim_period);
 +                      break;
 +              }
 +              i += ie_len + 2;
 +      }
 +      if (!tim_found) {
 +              b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
 +                            "beacon template packet. AP or IBSS operation "
 +                            "may be broken.\n");
 +      }
  }
  
  static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
                                            u16 shm_offset, u16 size,
 -                                          u8 rate)
 +                                          struct ieee80211_rate *rate)
  {
        struct b43legacy_plcp_hdr4 plcp;
        u32 tmp;
        __le16 dur;
  
        plcp.data = 0;
 -      b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
 +      b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
        dur = ieee80211_generic_frame_duration(dev->wl->hw,
                                               dev->wl->vif,
                                               size,
 -                                             B43legacy_RATE_TO_100KBPS(rate));
 +                                             rate);
        /* Write PLCP in two parts and timing for packet transfer */
        tmp = le32_to_cpu(plcp.data);
        b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
   * 2) Patching duration field
   * 3) Stripping TIM
   */
 -static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
 -                                       u16 *dest_size, u8 rate)
 +static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
 +                                             u16 *dest_size,
 +                                             struct ieee80211_rate *rate)
  {
        const u8 *src_data;
        u8 *dest_data;
 -      u16 src_size;
 -      u16 elem_size;
 -      u16 src_pos;
 -      u16 dest_pos;
 +      u16 src_size, elem_size, src_pos, dest_pos;
        __le16 dur;
        struct ieee80211_hdr *hdr;
 +      size_t ie_start;
 +
 +      src_size = dev->wl->current_beacon->len;
 +      src_data = (const u8 *)dev->wl->current_beacon->data;
  
 -      B43legacy_WARN_ON(!dev->cached_beacon);
 -      src_size = dev->cached_beacon->len;
 -      src_data = (const u8 *)dev->cached_beacon->data;
 +      /* Get the start offset of the variable IEs in the packet. */
 +      ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
 +      B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
 +                                             u.beacon.variable));
  
 -      if (unlikely(src_size < 0x24)) {
 -              b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
 -                     "invalid beacon\n");
 +      if (B43legacy_WARN_ON(src_size < ie_start))
                return NULL;
 -      }
  
        dest_data = kmalloc(src_size, GFP_ATOMIC);
        if (unlikely(!dest_data))
                return NULL;
  
 -      /* 0x24 is offset of first variable-len Information-Element
 -       * in beacon frame.
 -       */
 -      memcpy(dest_data, src_data, 0x24);
 -      src_pos = 0x24;
 -      dest_pos = 0x24;
 -      for (; src_pos < src_size - 2; src_pos += elem_size) {
 +      /* Copy the static data and all Information Elements, except the TIM. */
 +      memcpy(dest_data, src_data, ie_start);
 +      src_pos = ie_start;
 +      dest_pos = ie_start;
 +      for ( ; src_pos < src_size - 2; src_pos += elem_size) {
                elem_size = src_data[src_pos + 1] + 2;
 -              if (src_data[src_pos] != 0x05) { /* TIM */
 -                      memcpy(dest_data + dest_pos, src_data + src_pos,
 -                             elem_size);
 -                      dest_pos += elem_size;
 +              if (src_data[src_pos] == 5) {
 +                      /* This is the TIM. */
 +                      continue;
                }
 +              memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
 +              dest_pos += elem_size;
        }
        *dest_size = dest_pos;
        hdr = (struct ieee80211_hdr *)dest_data;
        dur = ieee80211_generic_frame_duration(dev->wl->hw,
                                               dev->wl->vif,
                                               *dest_size,
 -                                             B43legacy_RATE_TO_100KBPS(rate));
 +                                             rate);
        hdr->duration_id = dur;
  
        return dest_data;
  
  static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
                                                u16 ram_offset,
 -                                              u16 shm_size_offset, u8 rate)
 +                                              u16 shm_size_offset,
 +                                              struct ieee80211_rate *rate)
  {
 -      u8 *probe_resp_data;
 +      const u8 *probe_resp_data;
        u16 size;
  
 -      B43legacy_WARN_ON(!dev->cached_beacon);
 -      size = dev->cached_beacon->len;
 +      size = dev->wl->current_beacon->len;
        probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
        if (unlikely(!probe_resp_data))
                return;
         * all possible basic rates
         */
        b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
 -                                      B43legacy_CCK_RATE_1MB);
 +                                      &b43legacy_b_ratetable[0]);
        b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
 -                                      B43legacy_CCK_RATE_2MB);
 +                                      &b43legacy_b_ratetable[1]);
        b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
 -                                      B43legacy_CCK_RATE_5MB);
 +                                      &b43legacy_b_ratetable[2]);
        b43legacy_write_probe_resp_plcp(dev, 0x350, size,
 -                                      B43legacy_CCK_RATE_11MB);
 +                                      &b43legacy_b_ratetable[3]);
  
        size = min((size_t)size,
                   0x200 - sizeof(struct b43legacy_plcp_hdr6));
        b43legacy_write_template_common(dev, probe_resp_data,
                                        size, ram_offset,
 -                                      shm_size_offset, rate);
 +                                      shm_size_offset, rate->bitrate);
        kfree(probe_resp_data);
  }
  
 -static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
 -                                         struct sk_buff *beacon)
 -{
 -      if (dev->cached_beacon)
 -              kfree_skb(dev->cached_beacon);
 -      dev->cached_beacon = beacon;
 -
 -      return 0;
 -}
 -
 -static void b43legacy_update_templates(struct b43legacy_wldev *dev)
 -{
 -      u32 status;
 -
 -      B43legacy_WARN_ON(!dev->cached_beacon);
 -
 -      b43legacy_write_beacon_template(dev, 0x68, 0x18,
 -                                      B43legacy_CCK_RATE_1MB);
 -      b43legacy_write_beacon_template(dev, 0x468, 0x1A,
 -                                      B43legacy_CCK_RATE_1MB);
 -      b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
 -                                          B43legacy_CCK_RATE_11MB);
 -
 -      status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 -      status |= 0x03;
 -      b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
 -}
 -
 -static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
 -                                      struct sk_buff *beacon)
 +/* Asynchronously update the packet templates in template RAM.
 + * Locking: Requires wl->irq_lock to be locked. */
 +static void b43legacy_update_templates(struct b43legacy_wl *wl,
 +                                     struct sk_buff *beacon)
  {
 -      int err;
 +      /* This is the top half of the ansynchronous beacon update. The bottom
 +       * half is the beacon IRQ. Beacon update must be asynchronous to avoid
 +       * sending an invalid beacon. This can happen for example, if the
 +       * firmware transmits a beacon while we are updating it. */
  
 -      err = b43legacy_refresh_cached_beacon(dev, beacon);
 -      if (unlikely(err))
 -              return;
 -      b43legacy_update_templates(dev);
 +      if (wl->current_beacon)
 +              dev_kfree_skb_any(wl->current_beacon);
 +      wl->current_beacon = beacon;
 +      wl->beacon0_uploaded = 0;
 +      wl->beacon1_uploaded = 0;
  }
  
  static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
@@@ -1191,37 -1162,38 +1191,37 @@@ static void b43legacy_set_beacon_int(st
  
  static void handle_irq_beacon(struct b43legacy_wldev *dev)
  {
 -      u32 status;
 +      struct b43legacy_wl *wl = dev->wl;
 +      u32 cmd;
  
 -      if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
 +      if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
                return;
  
 -      dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
 -      status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 -
 -      if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
 -              /* ACK beacon IRQ. */
 -              b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
 -                                B43legacy_IRQ_BEACON);
 -              dev->irq_savedstate |= B43legacy_IRQ_BEACON;
 -              if (dev->cached_beacon)
 -                      kfree_skb(dev->cached_beacon);
 -              dev->cached_beacon = NULL;
 -              return;
 -      }
 -      if (!(status & 0x1)) {
 -              b43legacy_write_beacon_template(dev, 0x68, 0x18,
 -                                              B43legacy_CCK_RATE_1MB);
 -              status |= 0x1;
 -              b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 -                                status);
 -      }
 -      if (!(status & 0x2)) {
 -              b43legacy_write_beacon_template(dev, 0x468, 0x1A,
 -                                              B43legacy_CCK_RATE_1MB);
 -              status |= 0x2;
 -              b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 -                                status);
 +      /* This is the bottom half of the asynchronous beacon update. */
 +
 +      cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 +      if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
 +              if (!wl->beacon0_uploaded) {
 +                      b43legacy_write_beacon_template(dev, 0x68,
 +                                                      B43legacy_SHM_SH_BTL0,
 +                                                      B43legacy_CCK_RATE_1MB);
 +                      b43legacy_write_probe_resp_template(dev, 0x268,
 +                                                          B43legacy_SHM_SH_PRTLEN,
 +                                                          &__b43legacy_ratetable[3]);
 +                      wl->beacon0_uploaded = 1;
 +              }
 +              cmd |= B43legacy_MACCMD_BEACON0_VALID;
 +      }
 +      if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
 +              if (!wl->beacon1_uploaded) {
 +                      b43legacy_write_beacon_template(dev, 0x468,
 +                                                      B43legacy_SHM_SH_BTL1,
 +                                                      B43legacy_CCK_RATE_1MB);
 +                      wl->beacon1_uploaded = 1;
 +              }
 +              cmd |= B43legacy_MACCMD_BEACON1_VALID;
        }
 +      b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
  }
  
  static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
@@@ -2578,16 -2550,14 +2578,16 @@@ static int b43legacy_op_dev_config(stru
        antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
  
        mutex_lock(&wl->mutex);
 +      dev = wl->current_dev;
 +      phy = &dev->phy;
  
        /* Switch the PHY mode (if necessary). */
 -      switch (conf->phymode) {
 -      case MODE_IEEE80211B:
 -              new_phymode = B43legacy_PHYMODE_B;
 -              break;
 -      case MODE_IEEE80211G:
 -              new_phymode = B43legacy_PHYMODE_G;
 +      switch (conf->channel->band) {
 +      case IEEE80211_BAND_2GHZ:
 +              if (phy->type == B43legacy_PHYTYPE_B)
 +                      new_phymode = B43legacy_PHYMODE_B;
 +              else
 +                      new_phymode = B43legacy_PHYMODE_G;
                break;
        default:
                B43legacy_WARN_ON(1);
        err = b43legacy_switch_phymode(wl, new_phymode);
        if (err)
                goto out_unlock_mutex;
 -      dev = wl->current_dev;
 -      phy = &dev->phy;
  
        /* Disable IRQs while reconfiguring the device.
         * This makes it possible to drop the spinlock throughout
  
        /* Switch to the requested channel.
         * The firmware takes care of races with the TX handler. */
 -      if (conf->channel_val != phy->channel)
 -              b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
 +      if (conf->channel->hw_value != phy->channel)
 +              b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
  
        /* Enable/Disable ShortSlot timing. */
        if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
@@@ -2728,7 -2700,7 +2728,7 @@@ static int b43legacy_op_config_interfac
                        B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
                        b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
                        if (conf->beacon)
 -                              b43legacy_refresh_templates(dev, conf->beacon);
 +                              b43legacy_update_templates(wl, conf->beacon);
                }
                b43legacy_write_mac_bssid_templates(dev);
        }
@@@ -2946,7 -2918,7 +2946,7 @@@ static void setup_struct_phy_for_init(s
  static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
  {
        /* Flags */
 -      dev->reg124_set_0x4 = 0;
 +      dev->dfq_valid = 0;
  
        /* Stats */
        memset(&dev->stats, 0, sizeof(dev->stats));
@@@ -3041,11 -3013,6 +3041,11 @@@ static void b43legacy_wireless_core_exi
                kfree(phy->tssi2dbm);
        kfree(phy->lo_control);
        phy->lo_control = NULL;
 +      if (dev->wl->current_beacon) {
 +              dev_kfree_skb_any(dev->wl->current_beacon);
 +              dev->wl->current_beacon = NULL;
 +      }
 +
        ssb_device_disable(dev->dev, 0);
        ssb_bus_may_powerdown(dev->dev->bus);
  }
@@@ -3370,41 -3337,6 +3370,41 @@@ out_unlock
        return err;
  }
  
 +static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
 +                                     int aid, int set)
 +{
 +      struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 +      struct sk_buff *beacon;
 +      unsigned long flags;
 +
 +      /* We could modify the existing beacon and set the aid bit in the TIM
 +       * field, but that would probably require resizing and moving of data
 +       * within the beacon template. Simply request a new beacon and let
 +       * mac80211 do the hard work. */
 +      beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
 +      if (unlikely(!beacon))
 +              return -ENOMEM;
 +      spin_lock_irqsave(&wl->irq_lock, flags);
 +      b43legacy_update_templates(wl, beacon);
 +      spin_unlock_irqrestore(&wl->irq_lock, flags);
 +
 +      return 0;
 +}
 +
 +static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
 +                                         struct sk_buff *beacon,
 +                                         struct ieee80211_tx_control *ctl)
 +{
 +      struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&wl->irq_lock, flags);
 +      b43legacy_update_templates(wl, beacon);
 +      spin_unlock_irqrestore(&wl->irq_lock, flags);
 +
 +      return 0;
 +}
 +
  static const struct ieee80211_ops b43legacy_hw_ops = {
        .tx                     = b43legacy_op_tx,
        .conf_tx                = b43legacy_op_conf_tx,
        .start                  = b43legacy_op_start,
        .stop                   = b43legacy_op_stop,
        .set_retry_limit        = b43legacy_op_set_retry_limit,
 +      .set_tim                = b43legacy_op_beacon_set_tim,
 +      .beacon_update          = b43legacy_op_ibss_beacon_update,
  };
  
  /* Hard-reset the chip. Do not call this directly.
@@@ -3468,19 -3398,48 +3468,19 @@@ static int b43legacy_setup_modes(struc
                                 int have_gphy)
  {
        struct ieee80211_hw *hw = dev->wl->hw;
 -      struct ieee80211_hw_mode *mode;
        struct b43legacy_phy *phy = &dev->phy;
 -      int cnt = 0;
 -      int err;
  
        phy->possible_phymodes = 0;
 -      for (; 1; cnt++) {
 -              if (have_bphy) {
 -                      B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
 -                      mode = &phy->hwmodes[cnt];
 -
 -                      mode->mode = MODE_IEEE80211B;
 -                      mode->num_channels = b43legacy_bg_chantable_size;
 -                      mode->channels = b43legacy_bg_chantable;
 -                      mode->num_rates = b43legacy_b_ratetable_size;
 -                      mode->rates = b43legacy_b_ratetable;
 -                      err = ieee80211_register_hwmode(hw, mode);
 -                      if (err)
 -                              return err;
 -
 -                      phy->possible_phymodes |= B43legacy_PHYMODE_B;
 -                      have_bphy = 0;
 -                      continue;
 -              }
 -              if (have_gphy) {
 -                      B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
 -                      mode = &phy->hwmodes[cnt];
 -
 -                      mode->mode = MODE_IEEE80211G;
 -                      mode->num_channels = b43legacy_bg_chantable_size;
 -                      mode->channels = b43legacy_bg_chantable;
 -                      mode->num_rates = b43legacy_g_ratetable_size;
 -                      mode->rates = b43legacy_g_ratetable;
 -                      err = ieee80211_register_hwmode(hw, mode);
 -                      if (err)
 -                              return err;
 -
 -                      phy->possible_phymodes |= B43legacy_PHYMODE_G;
 -                      have_gphy = 0;
 -                      continue;
 -              }
 -              break;
 +      if (have_bphy) {
 +              hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 +                      &b43legacy_band_2GHz_BPHY;
 +              phy->possible_phymodes |= B43legacy_PHYMODE_B;
 +      }
 +
 +      if (have_gphy) {
 +              hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 +                      &b43legacy_band_2GHz_GPHY;
 +              phy->possible_phymodes |= B43legacy_PHYMODE_G;
        }
  
        return 0;
@@@ -3870,7 -3829,7 +3870,7 @@@ static void b43legacy_print_driverinfo(
  #ifdef CONFIG_B43LEGACY_DMA
        feat_dma = "D";
  #endif
-       printk(KERN_INFO "Broadcom 43xx driver loaded "
+       printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
               "[ Features: %s%s%s%s%s, Firmware-ID: "
               B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
               feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);
@@@ -74,7 -74,7 +74,7 @@@ void lbs_mac_event_disconnected(struct 
                lbs_deb_cmd("disconnected, so exit PS mode\n");
                lbs_ps_wakeup(priv, 0);
        }
 -      lbs_deb_leave(LBS_DEB_CMD);
 +      lbs_deb_leave(LBS_DEB_ASSOC);
  }
  
  /**
@@@ -562,19 -562,17 +562,17 @@@ int lbs_process_rx_command(struct lbs_p
        }
  
        resp = (void *)priv->upld_buf;
-       curcmd = le16_to_cpu(resp->command);
+       curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
        respcmd = le16_to_cpu(resp->command);
        result = le16_to_cpu(resp->result);
  
 -      lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
 +      lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
                     respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
 -      lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
 +      lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len);
  
-       if (resp->seqnum != resp->seqnum) {
+       if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
                lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
-                           le16_to_cpu(resp->seqnum), le16_to_cpu(resp->seqnum));
+                           le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
                spin_unlock_irqrestore(&priv->driver_lock, flags);
                ret = -1;
                goto done;
@@@ -27,46 -27,6 +27,46 @@@ MODULE_DESCRIPTION("Softmac Prism54 com
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("prism54common");
  
 +static struct ieee80211_rate p54_rates[] = {
 +      { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 +      { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 +      { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 +      { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 +      { .bitrate = 60, .hw_value = 4, },
 +      { .bitrate = 90, .hw_value = 5, },
 +      { .bitrate = 120, .hw_value = 6, },
 +      { .bitrate = 180, .hw_value = 7, },
 +      { .bitrate = 240, .hw_value = 8, },
 +      { .bitrate = 360, .hw_value = 9, },
 +      { .bitrate = 480, .hw_value = 10, },
 +      { .bitrate = 540, .hw_value = 11, },
 +};
 +
 +static struct ieee80211_channel p54_channels[] = {
 +      { .center_freq = 2412, .hw_value = 1, },
 +      { .center_freq = 2417, .hw_value = 2, },
 +      { .center_freq = 2422, .hw_value = 3, },
 +      { .center_freq = 2427, .hw_value = 4, },
 +      { .center_freq = 2432, .hw_value = 5, },
 +      { .center_freq = 2437, .hw_value = 6, },
 +      { .center_freq = 2442, .hw_value = 7, },
 +      { .center_freq = 2447, .hw_value = 8, },
 +      { .center_freq = 2452, .hw_value = 9, },
 +      { .center_freq = 2457, .hw_value = 10, },
 +      { .center_freq = 2462, .hw_value = 11, },
 +      { .center_freq = 2467, .hw_value = 12, },
 +      { .center_freq = 2472, .hw_value = 13, },
 +      { .center_freq = 2484, .hw_value = 14, },
 +};
 +
 +static struct ieee80211_supported_band band_2GHz = {
 +      .channels = p54_channels,
 +      .n_channels = ARRAY_SIZE(p54_channels),
 +      .bitrates = p54_rates,
 +      .n_bitrates = ARRAY_SIZE(p54_rates),
 +};
 +
 +
  void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
  {
        struct p54_common *priv = dev->priv;
@@@ -206,18 -166,23 +206,23 @@@ int p54_parse_eeprom(struct ieee80211_h
        struct p54_common *priv = dev->priv;
        struct eeprom_pda_wrap *wrap = NULL;
        struct pda_entry *entry;
-       int i = 0;
        unsigned int data_len, entry_len;
        void *tmp;
        int err;
+       u8 *end = (u8 *)eeprom + len;
  
        wrap = (struct eeprom_pda_wrap *) eeprom;
-       entry = (void *)wrap->data + wrap->len;
-       i += 2;
-       i += le16_to_cpu(entry->len)*2;
-       while (i < len) {
+       entry = (void *)wrap->data + le16_to_cpu(wrap->len);
+       /* verify that at least the entry length/code fits */
+       while ((u8 *)entry <= end - sizeof(*entry)) {
                entry_len = le16_to_cpu(entry->len);
                data_len = ((entry_len - 1) << 1);
+               /* abort if entry exceeds whole structure */
+               if ((u8 *)entry + sizeof(*entry) + data_len > end)
+                       break;
                switch (le16_to_cpu(entry->code)) {
                case PDR_MAC_ADDRESS:
                        SET_IEEE80211_PERM_ADDR(dev, entry->data);
                        priv->version = *(u8 *)(entry->data + 1);
                        break;
                case PDR_END:
-                       i = len;
+                       /* make it overrun */
+                       entry_len = len;
                        break;
 +              default:
 +                      printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
 +                              le16_to_cpu(entry->code));
 +                      break;
                }
  
                entry = (void *)entry + (entry_len + 1)*2;
-               i += 2;
-               i += entry_len*2;
        }
  
        if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
@@@ -352,10 -312,10 +356,10 @@@ static void p54_rx_data(struct ieee8021
        u16 freq = le16_to_cpu(hdr->freq);
  
        rx_status.ssi = hdr->rssi;
 -      rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
 -      rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
 +      /* XX correct? */
 +      rx_status.rate_idx = hdr->rate & 0xf;
        rx_status.freq = freq;
 -      rx_status.phymode = MODE_IEEE80211G;
 +      rx_status.band = IEEE80211_BAND_2GHZ;
        rx_status.antenna = hdr->antenna;
        rx_status.mactime = le64_to_cpu(hdr->timestamp);
        rx_status.flag |= RX_FLAG_TSFT;
@@@ -393,7 -353,7 +397,7 @@@ static void p54_rx_frame_sent(struct ie
        while (entry != (struct sk_buff *)&priv->tx_queue) {
                range = (struct memrecord *)&entry->cb;
                if (range->start_addr == addr) {
 -                      struct ieee80211_tx_status status = {{0}};
 +                      struct ieee80211_tx_status status;
                        struct p54_control_hdr *entry_hdr;
                        struct p54_tx_control_allocdata *entry_data;
                        int pad = 0;
                                kfree_skb(entry);
                                break;
                        }
 +                      memset(&status, 0, sizeof(status));
                        memcpy(&status.control, range->control,
                               sizeof(status.control));
                        kfree(range->control);
@@@ -592,9 -551,7 +596,9 @@@ static int p54_tx(struct ieee80211_hw *
        txhdr->padding2 = 0;
  
        /* TODO: add support for alternate retry TX rates */
 -      rate = control->tx_rate;
 +      rate = control->tx_rate->hw_value;
 +      if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
 +              rate |= 0x10;
        if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
                rate |= 0x40;
        else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
@@@ -764,12 -721,13 +768,12 @@@ static int p54_set_leds(struct ieee8021
        return 0;
  }
  
 -#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst)    \
 +#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop)    \
  do {                                                          \
        queue.aifs = cpu_to_le16(ai_fs);                        \
        queue.cwmin = cpu_to_le16(cw_min);                      \
        queue.cwmax = cpu_to_le16(cw_max);                      \
 -      queue.txop = (burst == 0) ?                             \
 -              0 : cpu_to_le16((burst * 100) / 32 + 1);        \
 +      queue.txop = cpu_to_le16(_txop);                        \
  } while(0)
  
  static void p54_init_vdcf(struct ieee80211_hw *dev)
  
        vdcf = (struct p54_tx_control_vdcf *) hdr->data;
  
 -      P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f);
 -      P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e);
 -      P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014);
 -      P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000);
 +      P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
 +      P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
 +      P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
 +      P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
  }
  
  static void p54_set_vdcf(struct ieee80211_hw *dev)
@@@ -895,7 -853,7 +899,7 @@@ static int p54_config(struct ieee80211_
  {
        int ret;
  
 -      ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
 +      ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
        p54_set_vdcf(dev);
        return ret;
  }
@@@ -943,7 -901,7 +947,7 @@@ static int p54_conf_tx(struct ieee80211
  
        if ((params) && !((queue < 0) || (queue > 4))) {
                P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
 -                      params->cw_min, params->cw_max, params->burst_time);
 +                      params->cw_min, params->cw_max, params->txop);
        } else
                return -EINVAL;
  
@@@ -990,6 -948,7 +994,6 @@@ struct ieee80211_hw *p54_init_common(si
  {
        struct ieee80211_hw *dev;
        struct p54_common *priv;
 -      int i;
  
        dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
        if (!dev)
        priv = dev->priv;
        priv->mode = IEEE80211_IF_TYPE_INVALID;
        skb_queue_head_init(&priv->tx_queue);
 -      memcpy(priv->channels, p54_channels, sizeof(p54_channels));
 -      memcpy(priv->rates, p54_rates, sizeof(p54_rates));
 -      priv->modes[1].mode = MODE_IEEE80211B;
 -      priv->modes[1].num_rates = 4;
 -      priv->modes[1].rates = priv->rates;
 -      priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
 -      priv->modes[1].channels = priv->channels;
 -      priv->modes[0].mode = MODE_IEEE80211G;
 -      priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
 -      priv->modes[0].rates = priv->rates;
 -      priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
 -      priv->modes[0].channels = priv->channels;
 +      dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
                    IEEE80211_HW_RX_INCLUDES_FCS;
        dev->channel_change_time = 1000;        /* TODO: find actual value */
  
        p54_init_vdcf(dev);
  
 -      for (i = 0; i < 2; i++) {
 -              if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
 -                      kfree(priv->cached_vdcf);
 -                      ieee80211_free_hw(dev);
 -                      return NULL;
 -              }
 -      }
 -
        return dev;
  }
  EXPORT_SYMBOL_GPL(p54_init_common);
@@@ -53,10 -53,10 +53,10 @@@ struct pda_entry 
  } __attribute__ ((packed));
  
  struct eeprom_pda_wrap {
-       u32 magic;
-       u16 pad;
-       u16 len;
-       u32 arm_opcode;
+       __le32 magic;
+       __le16 pad;
+       __le16 len;
+       __le32 arm_opcode;
        u8 data[0];
  } __attribute__ ((packed));
  
@@@ -251,4 -251,79 +251,4 @@@ struct p54_tx_control_vdcf 
        __le16 frameburst;
  } __attribute__ ((packed));
  
 -static const struct ieee80211_rate p54_rates[] = {
 -      { .rate = 10,
 -        .val = 0,
 -        .val2 = 0x10,
 -        .flags = IEEE80211_RATE_CCK_2 },
 -      { .rate = 20,
 -        .val = 1,
 -        .val2 = 0x11,
 -        .flags = IEEE80211_RATE_CCK_2 },
 -      { .rate = 55,
 -        .val = 2,
 -        .val2 = 0x12,
 -        .flags = IEEE80211_RATE_CCK_2 },
 -      { .rate = 110,
 -        .val = 3,
 -        .val2 = 0x13,
 -        .flags = IEEE80211_RATE_CCK_2 },
 -      { .rate = 60,
 -        .val = 4,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 90,
 -        .val = 5,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 120,
 -        .val = 6,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 180,
 -        .val = 7,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 240,
 -        .val = 8,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 360,
 -        .val = 9,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 480,
 -        .val = 10,
 -        .flags = IEEE80211_RATE_OFDM },
 -      { .rate = 540,
 -        .val = 11,
 -        .flags = IEEE80211_RATE_OFDM },
 -};
 -
 -// TODO: just generate this..
 -static const struct ieee80211_channel p54_channels[] = {
 -      { .chan = 1,
 -        .freq = 2412},
 -      { .chan = 2,
 -        .freq = 2417},
 -      { .chan = 3,
 -        .freq = 2422},
 -      { .chan = 4,
 -        .freq = 2427},
 -      { .chan = 5,
 -        .freq = 2432},
 -      { .chan = 6,
 -        .freq = 2437},
 -      { .chan = 7,
 -        .freq = 2442},
 -      { .chan = 8,
 -        .freq = 2447},
 -      { .chan = 9,
 -        .freq = 2452},
 -      { .chan = 10,
 -        .freq = 2457},
 -      { .chan = 11,
 -        .freq = 2462},
 -      { .chan = 12,
 -        .freq = 2467},
 -      { .chan = 13,
 -        .freq = 2472},
 -      { .chan = 14,
 -        .freq = 2484}
 -};
 -
  #endif /* PRISM54COMMON_H */
diff --combined net/core/neighbour.c
@@@ -839,7 -839,7 +839,7 @@@ static void neigh_timer_handler(unsigne
                struct sk_buff *skb = skb_peek(&neigh->arp_queue);
                /* keep skb alive even if arp_queue overflows */
                if (skb)
-                       skb_get(skb);
+                       skb = skb_copy(skb, GFP_ATOMIC);
                write_unlock(&neigh->lock);
                neigh->ops->solicit(neigh, skb);
                atomic_inc(&neigh->probes);
@@@ -1284,7 -1284,9 +1284,7 @@@ static inline struct neigh_parms *looku
        struct neigh_parms *p;
  
        for (p = &tbl->parms; p; p = p->next) {
 -              if (p->net != net)
 -                      continue;
 -              if ((p->dev && p->dev->ifindex == ifindex) ||
 +              if ((p->dev && p->dev->ifindex == ifindex && p->net == net) ||
                    (!p->dev && !ifindex))
                        return p;
        }
@@@ -2739,8 -2741,7 +2739,8 @@@ int neigh_sysctl_register(struct net_de
        neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
        neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id;
  
 -      t->sysctl_header = register_sysctl_paths(neigh_path, t->neigh_vars);
 +      t->sysctl_header =
 +              register_net_sysctl_table(p->net, neigh_path, t->neigh_vars);
        if (!t->sysctl_header)
                goto free_procname;
  
diff --combined net/core/netpoll.c
@@@ -39,6 -39,8 +39,8 @@@ static struct sk_buff_head skb_pool
  static atomic_t trapped;
  
  #define USEC_PER_POLL 50
+ #define NETPOLL_RX_ENABLED  1
+ #define NETPOLL_RX_DROP     2
  
  #define MAX_SKB_SIZE \
                (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
@@@ -126,11 -128,13 +128,13 @@@ static int poll_one_napi(struct netpoll
        if (!test_bit(NAPI_STATE_SCHED, &napi->state))
                return budget;
  
+       npinfo->rx_flags |= NETPOLL_RX_DROP;
        atomic_inc(&trapped);
  
        work = napi->poll(napi, budget);
  
        atomic_dec(&trapped);
+       npinfo->rx_flags &= ~NETPOLL_RX_DROP;
  
        return budget - work;
  }
@@@ -384,7 -388,9 +388,7 @@@ static void arp_reply(struct sk_buff *s
        if (skb->dev->flags & IFF_NOARP)
                return;
  
 -      if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
 -                               (2 * skb->dev->addr_len) +
 -                               (2 * sizeof(u32)))))
 +      if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
                return;
  
        skb_reset_network_header(skb);
            ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
                return;
  
 -      size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
 +      size = arp_hdr_len(skb->dev);
        send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
                            LL_RESERVED_SPACE(np->dev));
  
@@@ -470,7 -476,7 +474,7 @@@ int __netpoll_rx(struct sk_buff *skb
        if (skb->dev->type != ARPHRD_ETHER)
                goto out;
  
-       /* if receive ARP during middle of NAPI poll, then queue */
+       /* check if netpoll clients need ARP */
        if (skb->protocol == htons(ETH_P_ARP) &&
            atomic_read(&trapped)) {
                skb_queue_tail(&npi->arp_tx, skb);
        return 1;
  
  out:
-       /* If packet received while already in poll then just
-        * silently drop.
-        */
        if (atomic_read(&trapped)) {
                kfree_skb(skb);
                return 1;
@@@ -673,6 -676,7 +674,7 @@@ int netpoll_setup(struct netpoll *np
                        goto release;
                }
  
+               npinfo->rx_flags = 0;
                npinfo->rx_np = NULL;
  
                spin_lock_init(&npinfo->rx_lock);
  
        if (np->rx_hook) {
                spin_lock_irqsave(&npinfo->rx_lock, flags);
+               npinfo->rx_flags |= NETPOLL_RX_ENABLED;
                npinfo->rx_np = np;
                spin_unlock_irqrestore(&npinfo->rx_lock, flags);
        }
@@@ -795,6 -800,7 +798,7 @@@ void netpoll_cleanup(struct netpoll *np
                        if (npinfo->rx_np == np) {
                                spin_lock_irqsave(&npinfo->rx_lock, flags);
                                npinfo->rx_np = NULL;
+                               npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
                                spin_unlock_irqrestore(&npinfo->rx_lock, flags);
                        }
  
diff --combined net/ipv4/Kconfig
@@@ -343,7 -343,7 +343,7 @@@ config INET_ES
        tristate "IP: ESP transformation"
        select XFRM
        select CRYPTO
-       select CRYPTO_AEAD
+       select CRYPTO_AUTHENC
        select CRYPTO_HMAC
        select CRYPTO_MD5
        select CRYPTO_CBC
@@@ -632,15 -632,5 +632,15 @@@ config TCP_MD5SI
  
          If unsure, say N.
  
 +config IP_UDPLITE
 +      bool "IP: UDP-Lite Protocol (RFC 3828)"
 +      default n
 +      ---help---
 +        UDP-Lite (RFC 3828) is a UDP-like protocol with variable-length
 +        checksum.  Read <file:Documentation/networking/udplite.txt> for
 +        details.
 +
 +        If unsure, say N.
 +
  source "net/ipv4/ipvs/Kconfig"
  
diff --combined net/ipv4/ipconfig.c
@@@ -291,7 -291,7 +291,7 @@@ static int __init ic_dev_ioctl(unsigne
  
        mm_segment_t oldfs = get_fs();
        set_fs(get_ds());
 -      res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
 +      res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
        set_fs(oldfs);
        return res;
  }
@@@ -459,7 -459,10 +459,7 @@@ ic_rarp_recv(struct sk_buff *skb, struc
        if (rarp->ar_pro != htons(ETH_P_IP))
                goto drop;
  
 -      if (!pskb_may_pull(skb,
 -                         sizeof(struct arphdr) +
 -                         (2 * dev->addr_len) +
 -                         (2 * 4)))
 +      if (!pskb_may_pull(skb, arp_hdr_len(dev)))
                goto drop;
  
        /* OK, it is all there and looks valid, process... */
@@@ -750,9 -753,9 +750,9 @@@ static void __init ic_bootp_send_if(str
                printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
                b->htype = dev->type; /* can cause undefined behavior */
        }
+       /* server_ip and your_ip address are both already zero per RFC2131 */
        b->hlen = dev->addr_len;
-       b->your_ip = NONE;
-       b->server_ip = NONE;
        memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
        b->secs = htons(jiffies_diff / HZ);
        b->xid = d->xid;
diff --combined net/ipv4/tcp_input.c
@@@ -1367,7 -1367,7 +1367,7 @@@ static struct sk_buff *tcp_sacktag_walk
   * a normal way
   */
  static struct sk_buff *tcp_sacktag_skip(struct sk_buff *skb, struct sock *sk,
-                                       u32 skip_to_seq)
+                                       u32 skip_to_seq, int *fack_count)
  {
        tcp_for_write_queue_from(skb, sk) {
                if (skb == tcp_send_head(sk))
  
                if (!before(TCP_SKB_CB(skb)->end_seq, skip_to_seq))
                        break;
+               *fack_count += tcp_skb_pcount(skb);
        }
        return skb;
  }
@@@ -1390,7 -1392,7 +1392,7 @@@ static struct sk_buff *tcp_maybe_skippi
                return skb;
  
        if (before(next_dup->start_seq, skip_to_seq)) {
-               skb = tcp_sacktag_skip(skb, sk, next_dup->start_seq);
+               skb = tcp_sacktag_skip(skb, sk, next_dup->start_seq, fack_count);
                tcp_sacktag_walk(skb, sk, NULL,
                                 next_dup->start_seq, next_dup->end_seq,
                                 1, fack_count, reord, flag);
@@@ -1537,7 -1539,8 +1539,8 @@@ tcp_sacktag_write_queue(struct sock *sk
  
                        /* Head todo? */
                        if (before(start_seq, cache->start_seq)) {
-                               skb = tcp_sacktag_skip(skb, sk, start_seq);
+                               skb = tcp_sacktag_skip(skb, sk, start_seq,
+                                                      &fack_count);
                                skb = tcp_sacktag_walk(skb, sk, next_dup,
                                                       start_seq,
                                                       cache->start_seq,
                                goto walk;
                        }
  
-                       skb = tcp_sacktag_skip(skb, sk, cache->end_seq);
+                       skb = tcp_sacktag_skip(skb, sk, cache->end_seq,
+                                              &fack_count);
                        /* Check overlap against next cached too (past this one already) */
                        cache++;
                        continue;
                                break;
                        fack_count = tp->fackets_out;
                }
-               skb = tcp_sacktag_skip(skb, sk, start_seq);
+               skb = tcp_sacktag_skip(skb, sk, start_seq, &fack_count);
  
  walk:
                skb = tcp_sacktag_walk(skb, sk, next_dup, start_seq, end_seq,
@@@ -5326,7 -5330,6 +5330,7 @@@ discard
  
  EXPORT_SYMBOL(sysctl_tcp_ecn);
  EXPORT_SYMBOL(sysctl_tcp_reordering);
 +EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
  EXPORT_SYMBOL(tcp_parse_options);
  EXPORT_SYMBOL(tcp_rcv_established);
  EXPORT_SYMBOL(tcp_rcv_state_process);
diff --combined net/sctp/proc.c
@@@ -256,12 -256,10 +256,10 @@@ int __init sctp_eps_proc_init(void
  {
        struct proc_dir_entry *p;
  
-       p = create_proc_entry("eps", S_IRUGO, proc_net_sctp);
+       p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops);
        if (!p)
                return -ENOMEM;
  
-       p->proc_fops = &sctp_eps_seq_fops;
        return 0;
  }
  
@@@ -281,10 -279,8 +279,10 @@@ static void * sctp_assocs_seq_start(str
                *pos = 0;
  
        if (*pos == 0)
 -              seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 -                              "RPORT LADDRS <-> RADDRS\n");
 +              seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT "
 +                              "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 +                              "RPORT LADDRS <-> RADDRS "
 +                              "HBINT INS OUTS MAXRT T1X T2X RTXC\n");
  
        return (void *)pos;
  }
@@@ -323,21 -319,15 +321,21 @@@ static int sctp_assocs_seq_show(struct 
                assoc = sctp_assoc(epb);
                sk = epb->sk;
                seq_printf(seq,
 -                         "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
 +                         "%8p %8p %-3d %-3d %-2d %-4d "
 +                         "%4d %8d %8d %7d %5lu %-5d %5d "
 +                         "%8lu %5d %5d %4d %4d %4d %8d ",
                           assoc, sk, sctp_sk(sk)->type, sk->sk_state,
 -                         assoc->state, hash, assoc->assoc_id,
 +                         assoc->state, hash,
 +                         assoc->assoc_id,
                           assoc->sndbuf_used,
                           atomic_read(&assoc->rmem_alloc),
                           sock_i_uid(sk), sock_i_ino(sk),
                           epb->bind_addr.port,
 -                         assoc->peer.port);
 -
 +                         assoc->peer.port,
 +                         assoc->hbinterval, assoc->c.sinit_max_instreams,
 +                         assoc->c.sinit_num_ostreams, assoc->max_retrans,
 +                         assoc->init_retries, assoc->shutdown_retries,
 +                         assoc->rtx_data_chunks);
                seq_printf(seq, " ");
                sctp_seq_dump_local_addrs(seq, epb);
                seq_printf(seq, "<-> ");
@@@ -375,12 -365,11 +373,11 @@@ int __init sctp_assocs_proc_init(void
  {
        struct proc_dir_entry *p;
  
-       p = create_proc_entry("assocs", S_IRUGO, proc_net_sctp);
+       p = proc_create("assocs", S_IRUGO, proc_net_sctp,
+                       &sctp_assocs_seq_fops);
        if (!p)
                return -ENOMEM;
  
-       p->proc_fops = &sctp_assocs_seq_fops;
        return 0;
  }