Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Sat, 14 Jun 2008 03:52:39 +0000 (20:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 14 Jun 2008 03:52:39 +0000 (20:52 -0700)
Conflicts:

drivers/net/smc911x.c

28 files changed:
1  2 
drivers/net/Kconfig
drivers/net/atlx/atl1.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/forcedeth.c
drivers/net/s2io.c
drivers/net/sfc/falcon.c
drivers/net/sky2.c
drivers/net/smc911x.c
drivers/net/smc911x.h
include/linux/pci_ids.h
include/linux/tcp.h
include/net/tcp.h
net/ipv4/fib_semantics.c
net/ipv4/syncookies.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_timer.c
net/ipv6/datagram.c
net/ipv6/ip6mr.c
net/ipv6/ipv6_sockglue.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/key/af_key.c
net/netfilter/nf_conntrack_core.c

diff --combined drivers/net/Kconfig
index 40eb24d6d7553df597a392d9a9692f6f22b6181f,f4182cfffe9d4c62c02b64b14d17d252a87dc6d7..20b5367f7e0baeab97f079d349cc73d040676b1a
@@@ -524,18 -524,6 +524,18 @@@ config STNI
  
          If unsure, say N.
  
 +config SH_ETH
 +      tristate "Renesas SuperH Ethernet support"
 +      depends on SUPERH && \
 +              (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712)
 +      select CRC32
 +      select MII
 +      select MDIO_BITBANG
 +      select PHYLIB
 +      help
 +        Renesas SuperH Ethernet device driver.
 +        This driver support SH7710 and SH7712.
 +
  config SUNLANCE
        tristate "Sun LANCE support"
        depends on SBUS
@@@ -967,7 -955,7 +967,7 @@@ config SMC911
        tristate "SMSC LAN911[5678] support"
        select CRC32
        select MII
 -      depends on ARCH_PXA || SH_MAGIC_PANEL_R2
 +      depends on ARCH_PXA || SUPERH
        help
          This is a driver for SMSC's LAN911x series of Ethernet chipsets
          including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@@ -1682,7 -1670,7 +1682,7 @@@ config SUNDANCE_MMI
  
  config TLAN
        tristate "TI ThunderLAN support"
 -      depends on NET_PCI && (PCI || EISA) && !64BIT
 +      depends on NET_PCI && (PCI || EISA)
        ---help---
          If you have a PCI Ethernet network card based on the ThunderLAN chip
          which is supported by this driver, say Y and read the
@@@ -2240,7 -2228,6 +2240,7 @@@ config VIA_VELOCIT
  config TIGON3
        tristate "Broadcom Tigon3 support"
        depends on PCI
 +      select PHYLIB
        help
          This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
  
@@@ -2296,19 -2283,6 +2296,19 @@@ config GELIC_WIRELES
          the driver automatically distinguishes the models, you can
          safely enable this option even if you have a wireless-less model.
  
 +config GELIC_WIRELESS_OLD_PSK_INTERFACE
 +       bool "PS3 Wireless private PSK interface (OBSOLETE)"
 +       depends on GELIC_WIRELESS
 +       help
 +          This option retains the obsolete private interface to pass
 +          the PSK from user space programs to the driver.  The PSK
 +          stands for 'Pre Shared Key' and is used for WPA[2]-PSK
 +          (WPA-Personal) environment.
 +          If WPA[2]-PSK is used and you need to use old programs that
 +          support only this old interface, say Y.  Otherwise N.
 +
 +          If unsure, say N.
 +
  config GIANFAR
        tristate "Gianfar Ethernet"
        depends on FSL_SOC
@@@ -2433,9 -2407,8 +2433,9 @@@ config CHELSIO_T1_NAP
  
  config CHELSIO_T3
        tristate "Chelsio Communications T3 10Gb Ethernet support"
 -      depends on PCI
 +      depends on PCI && INET
        select FW_LOADER
 +      select INET_LRO
        help
          This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
          adapters.
  
  config EHEA
        tristate "eHEA Ethernet support"
-       depends on IBMEBUS && INET && SPARSEMEM && MEMORY_HOTPLUG
+       depends on IBMEBUS && INET && SPARSEMEM
        select INET_LRO
        ---help---
          This driver supports the IBM pSeries eHEA ethernet adapter.
diff --combined drivers/net/atlx/atl1.c
index 32dc391e63ccaadb53017ddcda76582d96b3c792,99e0b4cdc56fad301c59b01a1d7ae701da789265..919ffb9bfa4ed01e6c4b692d0a9d21c99a1389c2
@@@ -636,22 -636,6 +636,6 @@@ static s32 atl1_phy_leave_power_saving(
        return atl1_write_phy_reg(hw, 30, 0);
  }
  
- /*
-  * Force the PHY into power saving mode using vendor magic.
-  */
- #ifdef CONFIG_PM
- static void atl1_phy_enter_power_saving(struct atl1_hw *hw)
- {
-       atl1_write_phy_reg(hw, MII_DBG_ADDR, 0);
-       atl1_write_phy_reg(hw, MII_DBG_DATA, 0x124E);
-       atl1_write_phy_reg(hw, MII_DBG_ADDR, 2);
-       atl1_write_phy_reg(hw, MII_DBG_DATA, 0x3000);
-       atl1_write_phy_reg(hw, MII_DBG_ADDR, 3);
-       atl1_write_phy_reg(hw, MII_DBG_DATA, 0);
- }
- #endif
  /*
   * Resets the PHY and make all config validate
   * hw - Struct containing variables accessed by shared code
@@@ -1876,8 -1860,7 +1860,8 @@@ static u16 atl1_alloc_rx_buffers(struc
  
                rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
  
 -              skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
 +              skb = netdev_alloc_skb(adapter->netdev,
 +                                     adapter->rx_buffer_len + NET_IP_ALIGN);
                if (unlikely(!skb)) {
                        /* Better luck next round */
                        adapter->net_stats.rx_dropped++;
@@@ -2861,7 -2844,6 +2845,6 @@@ disable_wol
        ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
        iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
        ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-       atl1_phy_enter_power_saving(hw);
        hw->phy_configured = false;
        pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
  exit:
diff --combined drivers/net/bnx2.c
index b32d22762b9bc9dfe603e83b366c9e0a273bc25e,367b6d462708af2d8fe06050ac076844b3b54c1b..2c52d2c7c4958594a0aa3b12fa1132ecc012e22d
@@@ -56,8 -56,8 +56,8 @@@
  
  #define DRV_MODULE_NAME               "bnx2"
  #define PFX DRV_MODULE_NAME   ": "
 -#define DRV_MODULE_VERSION    "1.7.5"
 -#define DRV_MODULE_RELDATE    "April 29, 2008"
 +#define DRV_MODULE_VERSION    "1.7.6"
 +#define DRV_MODULE_RELDATE    "May 16, 2008"
  
  #define RUN_AT(x) (jiffies + (x))
  
@@@ -1875,7 -1875,7 +1875,7 @@@ bnx2_setup_phy(struct bnx2 *bp, u8 port
  }
  
  static int
 -bnx2_init_5709s_phy(struct bnx2 *bp)
 +bnx2_init_5709s_phy(struct bnx2 *bp, int reset_phy)
  {
        u32 val;
  
        bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
  
        bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
 -      bnx2_reset_phy(bp);
 +      if (reset_phy)
 +              bnx2_reset_phy(bp);
  
        bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
  
  }
  
  static int
 -bnx2_init_5708s_phy(struct bnx2 *bp)
 +bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
  {
        u32 val;
  
 -      bnx2_reset_phy(bp);
 +      if (reset_phy)
 +              bnx2_reset_phy(bp);
  
        bp->mii_up1 = BCM5708S_UP1;
  
  }
  
  static int
 -bnx2_init_5706s_phy(struct bnx2 *bp)
 +bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
  {
 -      bnx2_reset_phy(bp);
 +      if (reset_phy)
 +              bnx2_reset_phy(bp);
  
        bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
  
  }
  
  static int
 -bnx2_init_copper_phy(struct bnx2 *bp)
 +bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
  {
        u32 val;
  
 -      bnx2_reset_phy(bp);
 +      if (reset_phy)
 +              bnx2_reset_phy(bp);
  
        if (bp->phy_flags & BNX2_PHY_FLAG_CRC_FIX) {
                bnx2_write_phy(bp, 0x18, 0x0c00);
  
  
  static int
 -bnx2_init_phy(struct bnx2 *bp)
 +bnx2_init_phy(struct bnx2 *bp, int reset_phy)
  {
        u32 val;
        int rc = 0;
  
        if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
                if (CHIP_NUM(bp) == CHIP_NUM_5706)
 -                      rc = bnx2_init_5706s_phy(bp);
 +                      rc = bnx2_init_5706s_phy(bp, reset_phy);
                else if (CHIP_NUM(bp) == CHIP_NUM_5708)
 -                      rc = bnx2_init_5708s_phy(bp);
 +                      rc = bnx2_init_5708s_phy(bp, reset_phy);
                else if (CHIP_NUM(bp) == CHIP_NUM_5709)
 -                      rc = bnx2_init_5709s_phy(bp);
 +                      rc = bnx2_init_5709s_phy(bp, reset_phy);
        }
        else {
 -              rc = bnx2_init_copper_phy(bp);
 +              rc = bnx2_init_copper_phy(bp, reset_phy);
        }
  
  setup_phy:
@@@ -2624,7 -2620,7 +2624,7 @@@ bnx2_reuse_rx_skb(struct bnx2 *bp, stru
  
        pci_dma_sync_single_for_device(bp->pdev,
                pci_unmap_addr(cons_rx_buf, mapping),
 -              bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
 +              BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
  
        bnapi->rx_prod_bseq += bp->rx_buf_use_size;
  
@@@ -2662,7 -2658,7 +2662,7 @@@ bnx2_rx_skb(struct bnx2 *bp, struct bnx
                return err;
        }
  
 -      skb_reserve(skb, bp->rx_offset);
 +      skb_reserve(skb, BNX2_RX_OFFSET);
        pci_unmap_single(bp->pdev, dma_addr, bp->rx_buf_use_size,
                         PCI_DMA_FROMDEVICE);
  
@@@ -2777,8 -2773,7 +2777,8 @@@ bnx2_rx_int(struct bnx2 *bp, struct bnx
                dma_addr = pci_unmap_addr(rx_buf, mapping);
  
                pci_dma_sync_single_for_cpu(bp->pdev, dma_addr,
 -                      bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
 +                      BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
 +                      PCI_DMA_FROMDEVICE);
  
                rx_hdr = (struct l2_fhdr *) skb->data;
                len = rx_hdr->l2_fhdr_pkt_len;
                        }
  
                        /* aligned copy */
 -                      skb_copy_from_linear_data_offset(skb, bp->rx_offset - 2,
 +                      skb_copy_from_linear_data_offset(skb,
 +                                                       BNX2_RX_OFFSET - 2,
                                      new_skb->data, len + 2);
                        skb_reserve(new_skb, 2);
                        skb_put(new_skb, len);
@@@ -3219,7 -3213,7 +3219,7 @@@ load_rv2p_fw(struct bnx2 *bp, __le32 *r
  }
  
  static int
 -load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 +load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg, struct fw_info *fw)
  {
        u32 offset;
        u32 val;
  static int
  bnx2_init_cpus(struct bnx2 *bp)
  {
 -      struct cpu_reg cpu_reg;
        struct fw_info *fw;
        int rc, rv2p_len;
        void *text, *rv2p;
        load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
  
        /* Initialize the RX Processor. */
 -      cpu_reg.mode = BNX2_RXP_CPU_MODE;
 -      cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
 -      cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA;
 -      cpu_reg.state = BNX2_RXP_CPU_STATE;
 -      cpu_reg.state_value_clear = 0xffffff;
 -      cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE;
 -      cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK;
 -      cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER;
 -      cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION;
 -      cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT;
 -      cpu_reg.spad_base = BNX2_RXP_SCRATCH;
 -      cpu_reg.mips_view_base = 0x8000000;
 -
        if (CHIP_NUM(bp) == CHIP_NUM_5709)
                fw = &bnx2_rxp_fw_09;
        else
                fw = &bnx2_rxp_fw_06;
  
        fw->text = text;
 -      rc = load_cpu_fw(bp, &cpu_reg, fw);
 +      rc = load_cpu_fw(bp, &cpu_reg_rxp, fw);
        if (rc)
                goto init_cpu_err;
  
        /* Initialize the TX Processor. */
 -      cpu_reg.mode = BNX2_TXP_CPU_MODE;
 -      cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
 -      cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA;
 -      cpu_reg.state = BNX2_TXP_CPU_STATE;
 -      cpu_reg.state_value_clear = 0xffffff;
 -      cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE;
 -      cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK;
 -      cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER;
 -      cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION;
 -      cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT;
 -      cpu_reg.spad_base = BNX2_TXP_SCRATCH;
 -      cpu_reg.mips_view_base = 0x8000000;
 -
        if (CHIP_NUM(bp) == CHIP_NUM_5709)
                fw = &bnx2_txp_fw_09;
        else
                fw = &bnx2_txp_fw_06;
  
        fw->text = text;
 -      rc = load_cpu_fw(bp, &cpu_reg, fw);
 +      rc = load_cpu_fw(bp, &cpu_reg_txp, fw);
        if (rc)
                goto init_cpu_err;
  
        /* Initialize the TX Patch-up Processor. */
 -      cpu_reg.mode = BNX2_TPAT_CPU_MODE;
 -      cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
 -      cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA;
 -      cpu_reg.state = BNX2_TPAT_CPU_STATE;
 -      cpu_reg.state_value_clear = 0xffffff;
 -      cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE;
 -      cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK;
 -      cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER;
 -      cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION;
 -      cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT;
 -      cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
 -      cpu_reg.mips_view_base = 0x8000000;
 -
        if (CHIP_NUM(bp) == CHIP_NUM_5709)
                fw = &bnx2_tpat_fw_09;
        else
                fw = &bnx2_tpat_fw_06;
  
        fw->text = text;
 -      rc = load_cpu_fw(bp, &cpu_reg, fw);
 +      rc = load_cpu_fw(bp, &cpu_reg_tpat, fw);
        if (rc)
                goto init_cpu_err;
  
        /* Initialize the Completion Processor. */
 -      cpu_reg.mode = BNX2_COM_CPU_MODE;
 -      cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
 -      cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA;
 -      cpu_reg.state = BNX2_COM_CPU_STATE;
 -      cpu_reg.state_value_clear = 0xffffff;
 -      cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE;
 -      cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK;
 -      cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER;
 -      cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION;
 -      cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT;
 -      cpu_reg.spad_base = BNX2_COM_SCRATCH;
 -      cpu_reg.mips_view_base = 0x8000000;
 -
        if (CHIP_NUM(bp) == CHIP_NUM_5709)
                fw = &bnx2_com_fw_09;
        else
                fw = &bnx2_com_fw_06;
  
        fw->text = text;
 -      rc = load_cpu_fw(bp, &cpu_reg, fw);
 +      rc = load_cpu_fw(bp, &cpu_reg_com, fw);
        if (rc)
                goto init_cpu_err;
  
        /* Initialize the Command Processor. */
 -      cpu_reg.mode = BNX2_CP_CPU_MODE;
 -      cpu_reg.mode_value_halt = BNX2_CP_CPU_MODE_SOFT_HALT;
 -      cpu_reg.mode_value_sstep = BNX2_CP_CPU_MODE_STEP_ENA;
 -      cpu_reg.state = BNX2_CP_CPU_STATE;
 -      cpu_reg.state_value_clear = 0xffffff;
 -      cpu_reg.gpr0 = BNX2_CP_CPU_REG_FILE;
 -      cpu_reg.evmask = BNX2_CP_CPU_EVENT_MASK;
 -      cpu_reg.pc = BNX2_CP_CPU_PROGRAM_COUNTER;
 -      cpu_reg.inst = BNX2_CP_CPU_INSTRUCTION;
 -      cpu_reg.bp = BNX2_CP_CPU_HW_BREAKPOINT;
 -      cpu_reg.spad_base = BNX2_CP_SCRATCH;
 -      cpu_reg.mips_view_base = 0x8000000;
 -
        if (CHIP_NUM(bp) == CHIP_NUM_5709)
                fw = &bnx2_cp_fw_09;
        else
                fw = &bnx2_cp_fw_06;
  
        fw->text = text;
 -      rc = load_cpu_fw(bp, &cpu_reg, fw);
 +      rc = load_cpu_fw(bp, &cpu_reg_cp, fw);
  
  init_cpu_err:
        vfree(text);
@@@ -4690,12 -4750,12 +4690,12 @@@ bnx2_set_rx_ring_size(struct bnx2 *bp, 
        u32 rx_size, rx_space, jumbo_size;
  
        /* 8 for CRC and VLAN */
 -      rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
 +      rx_size = bp->dev->mtu + ETH_HLEN + BNX2_RX_OFFSET + 8;
  
        rx_space = SKB_DATA_ALIGN(rx_size + BNX2_RX_ALIGN) + NET_SKB_PAD +
                sizeof(struct skb_shared_info);
  
 -      bp->rx_copy_thresh = RX_COPY_THRESH;
 +      bp->rx_copy_thresh = BNX2_RX_COPY_THRESH;
        bp->rx_pg_ring_size = 0;
        bp->rx_max_pg_ring = 0;
        bp->rx_max_pg_ring_idx = 0;
                bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
                                                        MAX_RX_PG_RINGS);
                bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
 -              rx_size = RX_COPY_THRESH + bp->rx_offset;
 +              rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET;
                bp->rx_copy_thresh = 0;
        }
  
        bp->rx_buf_use_size = rx_size;
        /* hw alignment */
        bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
 -      bp->rx_jumbo_thresh = rx_size - bp->rx_offset;
 +      bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET;
        bp->rx_ring_size = size;
        bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
        bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
@@@ -4813,7 -4873,7 +4813,7 @@@ bnx2_reset_nic(struct bnx2 *bp, u32 res
  }
  
  static int
 -bnx2_init_nic(struct bnx2 *bp)
 +bnx2_init_nic(struct bnx2 *bp, int reset_phy)
  {
        int rc;
  
                return rc;
  
        spin_lock_bh(&bp->phy_lock);
 -      bnx2_init_phy(bp);
 +      bnx2_init_phy(bp, reset_phy);
        bnx2_set_link(bp);
        if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
                bnx2_remote_phy_event(bp);
@@@ -5161,7 -5221,7 +5161,7 @@@ bnx2_run_loopback(struct bnx2 *bp, int 
        rx_skb = rx_buf->skb;
  
        rx_hdr = (struct l2_fhdr *) rx_skb->data;
 -      skb_reserve(rx_skb, bp->rx_offset);
 +      skb_reserve(rx_skb, BNX2_RX_OFFSET);
  
        pci_dma_sync_single_for_cpu(bp->pdev,
                pci_unmap_addr(rx_buf, mapping),
@@@ -5209,7 -5269,7 +5209,7 @@@ bnx2_test_loopback(struct bnx2 *bp
  
        bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
        spin_lock_bh(&bp->phy_lock);
 -      bnx2_init_phy(bp);
 +      bnx2_init_phy(bp, 1);
        spin_unlock_bh(&bp->phy_lock);
        if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK))
                rc |= BNX2_MAC_LOOPBACK_FAILED;
@@@ -5599,7 -5659,7 +5599,7 @@@ bnx2_open(struct net_device *dev
                return rc;
        }
  
 -      rc = bnx2_init_nic(bp);
 +      rc = bnx2_init_nic(bp, 1);
  
        if (rc) {
                bnx2_napi_disable(bp);
  
                        bnx2_setup_int_mode(bp, 1);
  
 -                      rc = bnx2_init_nic(bp);
 +                      rc = bnx2_init_nic(bp, 0);
  
                        if (!rc)
                                rc = bnx2_request_irq(bp);
@@@ -5664,14 -5724,12 +5664,12 @@@ bnx2_reset_task(struct work_struct *wor
        if (!netif_running(bp->dev))
                return;
  
-       bp->in_reset_task = 1;
        bnx2_netif_stop(bp);
  
 -      bnx2_init_nic(bp);
 +      bnx2_init_nic(bp, 1);
  
        atomic_set(&bp->intr_sem, 1);
        bnx2_netif_start(bp);
-       bp->in_reset_task = 0;
  }
  
  static void
@@@ -5847,12 -5905,7 +5845,7 @@@ bnx2_close(struct net_device *dev
        struct bnx2 *bp = netdev_priv(dev);
        u32 reset_code;
  
-       /* Calling flush_scheduled_work() may deadlock because
-        * linkwatch_event() may be on the workqueue and it will try to get
-        * the rtnl_lock which we are holding.
-        */
-       while (bp->in_reset_task)
-               msleep(1);
+       cancel_work_sync(&bp->reset_task);
  
        bnx2_disable_int_sync(bp);
        bnx2_napi_disable(bp);
@@@ -6361,7 -6414,7 +6354,7 @@@ bnx2_set_coalesce(struct net_device *de
  
        if (netif_running(bp->dev)) {
                bnx2_netif_stop(bp);
 -              bnx2_init_nic(bp);
 +              bnx2_init_nic(bp, 0);
                bnx2_netif_start(bp);
        }
  
@@@ -6404,7 -6457,7 +6397,7 @@@ bnx2_change_ring_size(struct bnx2 *bp, 
                rc = bnx2_alloc_mem(bp);
                if (rc)
                        return rc;
 -              bnx2_init_nic(bp);
 +              bnx2_init_nic(bp, 0);
                bnx2_netif_start(bp);
        }
        return 0;
@@@ -6672,7 -6725,7 +6665,7 @@@ bnx2_self_test(struct net_device *dev, 
                        bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
                }
                else {
 -                      bnx2_init_nic(bp);
 +                      bnx2_init_nic(bp, 1);
                        bnx2_netif_start(bp);
                }
  
@@@ -7055,7 -7108,6 +7048,7 @@@ bnx2_init_board(struct pci_dev *pdev, s
        }
  
        pci_set_master(pdev);
 +      pci_save_state(pdev);
  
        bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
        if (bp->pm_cap == 0) {
        bp->mac_addr[4] = (u8) (reg >> 8);
        bp->mac_addr[5] = (u8) reg;
  
 -      bp->rx_offset = sizeof(struct l2_fhdr) + 2;
 -
        bp->tx_ring_size = MAX_TX_DESC_CNT;
        bnx2_set_rx_ring_size(bp, 255);
  
@@@ -7558,97 -7612,11 +7551,97 @@@ bnx2_resume(struct pci_dev *pdev
  
        bnx2_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);
 -      bnx2_init_nic(bp);
 +      bnx2_init_nic(bp, 1);
        bnx2_netif_start(bp);
        return 0;
  }
  
 +/**
 + * bnx2_io_error_detected - called when PCI error is detected
 + * @pdev: Pointer to PCI device
 + * @state: The current pci connection state
 + *
 + * This function is called after a PCI bus error affecting
 + * this device has been detected.
 + */
 +static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
 +                                             pci_channel_state_t state)
 +{
 +      struct net_device *dev = pci_get_drvdata(pdev);
 +      struct bnx2 *bp = netdev_priv(dev);
 +
 +      rtnl_lock();
 +      netif_device_detach(dev);
 +
 +      if (netif_running(dev)) {
 +              bnx2_netif_stop(bp);
 +              del_timer_sync(&bp->timer);
 +              bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
 +      }
 +
 +      pci_disable_device(pdev);
 +      rtnl_unlock();
 +
 +      /* Request a slot slot reset. */
 +      return PCI_ERS_RESULT_NEED_RESET;
 +}
 +
 +/**
 + * bnx2_io_slot_reset - called after the pci bus has been reset.
 + * @pdev: Pointer to PCI device
 + *
 + * Restart the card from scratch, as if from a cold-boot.
 + */
 +static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
 +{
 +      struct net_device *dev = pci_get_drvdata(pdev);
 +      struct bnx2 *bp = netdev_priv(dev);
 +
 +      rtnl_lock();
 +      if (pci_enable_device(pdev)) {
 +              dev_err(&pdev->dev,
 +                      "Cannot re-enable PCI device after reset.\n");
 +              rtnl_unlock();
 +              return PCI_ERS_RESULT_DISCONNECT;
 +      }
 +      pci_set_master(pdev);
 +      pci_restore_state(pdev);
 +
 +      if (netif_running(dev)) {
 +              bnx2_set_power_state(bp, PCI_D0);
 +              bnx2_init_nic(bp, 1);
 +      }
 +
 +      rtnl_unlock();
 +      return PCI_ERS_RESULT_RECOVERED;
 +}
 +
 +/**
 + * bnx2_io_resume - called when traffic can start flowing again.
 + * @pdev: Pointer to PCI device
 + *
 + * This callback is called when the error recovery driver tells us that
 + * its OK to resume normal operation.
 + */
 +static void bnx2_io_resume(struct pci_dev *pdev)
 +{
 +      struct net_device *dev = pci_get_drvdata(pdev);
 +      struct bnx2 *bp = netdev_priv(dev);
 +
 +      rtnl_lock();
 +      if (netif_running(dev))
 +              bnx2_netif_start(bp);
 +
 +      netif_device_attach(dev);
 +      rtnl_unlock();
 +}
 +
 +static struct pci_error_handlers bnx2_err_handler = {
 +      .error_detected = bnx2_io_error_detected,
 +      .slot_reset     = bnx2_io_slot_reset,
 +      .resume         = bnx2_io_resume,
 +};
 +
  static struct pci_driver bnx2_pci_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = bnx2_pci_tbl,
        .remove         = __devexit_p(bnx2_remove_one),
        .suspend        = bnx2_suspend,
        .resume         = bnx2_resume,
 +      .err_handler    = &bnx2_err_handler,
  };
  
  static int __init bnx2_init(void)
diff --combined drivers/net/bnx2.h
index 16020a10bf42e79dfa0198f9ad4b37e222f4f423,2377cc13bf61afc14d7598eaa93cf78a691204a7..be7ccb5b77da54b1109e6d8c445c75d8f409995b
@@@ -309,7 -309,6 +309,7 @@@ struct l2_fhdr 
  #endif
  };
  
 +#define BNX2_RX_OFFSET                (sizeof(struct l2_fhdr) + 2)
  
  /*
   *  l2_context definition
  #define MAX_ETHERNET_PACKET_SIZE      1514
  #define MAX_ETHERNET_JUMBO_PACKET_SIZE        9014
  
 -#define RX_COPY_THRESH                        128
 +#define BNX2_RX_COPY_THRESH           128
  
  #define BNX2_MISC_ENABLE_DEFAULT      0x17ffffff
  
@@@ -6628,6 -6627,7 +6628,6 @@@ struct bnx2 
        struct                  vlan_group *vlgrp;
  #endif
  
 -      u32                     rx_offset;
        u32                     rx_buf_use_size;        /* useable size */
        u32                     rx_buf_size;            /* with alignment */
        u32                     rx_copy_thresh;
        int                     current_interval;
        struct                  timer_list timer;
        struct work_struct      reset_task;
-       int                     in_reset_task;
  
        /* Used to synchronize phy accesses. */
        spinlock_t              phy_lock;
diff --combined drivers/net/forcedeth.c
index e4d697894364cc247ec4413a627c9c66668d16eb,2cb2447632928a4fd4bc9972a9f375a96065c4ae..c980ce9719af6383d095593b26850f30b738e5a1
@@@ -426,7 -426,6 +426,7 @@@ union ring_type 
  #define NV_PCI_REGSZ_VER1             0x270
  #define NV_PCI_REGSZ_VER2             0x2d4
  #define NV_PCI_REGSZ_VER3             0x604
 +#define NV_PCI_REGSZ_MAX              0x604
  
  /* various timeout delays: all in usec */
  #define NV_TXRX_RESET_DELAY   4
@@@ -785,9 -784,6 +785,9 @@@ struct fe_priv 
  
        /* flow control */
        u32 pause_flags;
 +
 +      /* power saved state */
 +      u32 saved_config_space[NV_PCI_REGSZ_MAX/4];
  };
  
  /*
@@@ -3277,6 -3273,20 +3277,20 @@@ static void nv_link_irq(struct net_devi
        dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
  }
  
+ static void nv_msi_workaround(struct fe_priv *np)
+ {
+       /* Need to toggle the msi irq mask within the ethernet device,
+        * otherwise, future interrupts will not be detected.
+        */
+       if (np->msi_flags & NV_MSI_ENABLED) {
+               u8 __iomem *base = np->base;
+               writel(0, base + NvRegMSIIrqMask);
+               writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+       }
+ }
  static irqreturn_t nv_nic_irq(int foo, void *data)
  {
        struct net_device *dev = (struct net_device *) data;
                if (!(events & np->irqmask))
                        break;
  
+               nv_msi_workaround(np);
                spin_lock(&np->lock);
                nv_tx_done(dev);
                spin_unlock(&np->lock);
@@@ -3414,6 -3426,8 +3430,8 @@@ static irqreturn_t nv_nic_irq_optimized
                if (!(events & np->irqmask))
                        break;
  
+               nv_msi_workaround(np);
                spin_lock(&np->lock);
                nv_tx_done_optimized(dev, TX_WORK_PER_LOOP);
                spin_unlock(&np->lock);
@@@ -3754,6 -3768,8 +3772,8 @@@ static irqreturn_t nv_nic_irq_test(int 
        if (!(events & NVREG_IRQ_TIMER))
                return IRQ_RETVAL(0);
  
+       nv_msi_workaround(np);
        spin_lock(&np->lock);
        np->intr_test = 1;
        spin_unlock(&np->lock);
@@@ -5789,66 -5805,50 +5809,66 @@@ static int nv_suspend(struct pci_dev *p
  {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct fe_priv *np = netdev_priv(dev);
 +      u8 __iomem *base = get_hwbase(dev);
 +      int i;
  
 -      if (!netif_running(dev))
 -              goto out;
 -
 +      if (netif_running(dev)) {
 +              // Gross.
 +              nv_close(dev);
 +      }
        netif_device_detach(dev);
  
 -      // Gross.
 -      nv_close(dev);
 +      /* save non-pci configuration space */
 +      for (i = 0;i <= np->register_size/sizeof(u32); i++)
 +              np->saved_config_space[i] = readl(base + i*sizeof(u32));
  
        pci_save_state(pdev);
        pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled);
 +      pci_disable_device(pdev);
        pci_set_power_state(pdev, pci_choose_state(pdev, state));
 -out:
        return 0;
  }
  
  static int nv_resume(struct pci_dev *pdev)
  {
        struct net_device *dev = pci_get_drvdata(pdev);
 +      struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
 -      int rc = 0;
 -      u32 txreg;
 -
 -      if (!netif_running(dev))
 -              goto out;
 -
 -      netif_device_attach(dev);
 +      int i, rc = 0;
  
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 +      /* ack any pending wake events, disable PME */
        pci_enable_wake(pdev, PCI_D0, 0);
  
 -      /* restore mac address reverse flag */
 -      txreg = readl(base + NvRegTransmitPoll);
 -      txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV;
 -      writel(txreg, base + NvRegTransmitPoll);
 +      /* restore non-pci configuration space */
 +      for (i = 0;i <= np->register_size/sizeof(u32); i++)
 +              writel(np->saved_config_space[i], base+i*sizeof(u32));
  
 -      rc = nv_open(dev);
 -      nv_set_multicast(dev);
 -out:
 +      netif_device_attach(dev);
 +      if (netif_running(dev)) {
 +              rc = nv_open(dev);
 +              nv_set_multicast(dev);
 +      }
        return rc;
  }
 +
 +static void nv_shutdown(struct pci_dev *pdev)
 +{
 +      struct net_device *dev = pci_get_drvdata(pdev);
 +      struct fe_priv *np = netdev_priv(dev);
 +
 +      if (netif_running(dev))
 +              nv_close(dev);
 +
 +      pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
 +      pci_enable_wake(pdev, PCI_D3cold, np->wolenabled);
 +      pci_disable_device(pdev);
 +      pci_set_power_state(pdev, PCI_D3hot);
 +}
  #else
  #define nv_suspend NULL
 +#define nv_shutdown NULL
  #define nv_resume NULL
  #endif /* CONFIG_PM */
  
@@@ -6019,7 -6019,6 +6039,7 @@@ static struct pci_driver driver = 
        .remove         = __devexit_p(nv_remove),
        .suspend        = nv_suspend,
        .resume         = nv_resume,
 +      .shutdown       = nv_shutdown,
  };
  
  static int __init init_nic(void)
diff --combined drivers/net/s2io.c
index dcc953e57ab180b53ae47d9f5b114cf0e209c832,b5c1e663417d874aaba92270b2f765fe5cab8ee0..5694e894fc7a3d7dd2bb117c8f40299f68c2f282
@@@ -2566,7 -2566,7 +2566,7 @@@ static int fill_rx_buffers(struct ring_
                if (block_no)
                        rxd_index += (block_no * ring->rxd_count);
  
 -              if ((block_no == block_no1) && 
 +              if ((block_no == block_no1) &&
                        (off == ring->rx_curr_get_info.offset) &&
                        (rxdp->Host_Control)) {
                        DBG_PRINT(INTR_DBG, "%s: Get and Put",
                                first_rxdp->Control_1 |= RXD_OWN_XENA;
                        }
                        stats->mem_alloc_fail_cnt++;
 -                              
 +
                        return -ENOMEM ;
                }
                stats->mem_allocated += skb->truesize;
@@@ -2861,7 -2861,8 +2861,8 @@@ static int s2io_poll_msix(struct napi_s
        struct config_param *config;
        struct mac_info *mac_control;
        int pkts_processed = 0;
-       u8 *addr = NULL, val8 = 0;
+       u8 __iomem *addr = NULL;
+       u8 val8 = 0;
        struct s2io_nic *nic = dev->priv;
        struct XENA_dev_config __iomem *bar0 = nic->bar0;
        int budget_org = budget;
        if (pkts_processed < budget_org) {
                netif_rx_complete(dev, napi);
                /*Re Enable MSI-Rx Vector*/
-               addr = (u8 *)&bar0->xmsi_mask_reg;
+               addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
                addr += 7 - ring->ring_no;
                val8 = (ring->ring_no == 0) ? 0x3f : 0xbf;
                writeb(val8, addr);
@@@ -4364,9 -4365,10 +4365,10 @@@ static irqreturn_t s2io_msix_ring_handl
                return IRQ_HANDLED;
  
        if (sp->config.napi) {
-               u8 *addr = NULL, val8 = 0;
+               u8 __iomem *addr = NULL;
+               u8 val8 = 0;
  
-               addr = (u8 *)&bar0->xmsi_mask_reg;
+               addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
                addr += (7 - ring->ring_no);
                val8 = (ring->ring_no == 0) ? 0x7f : 0xff;
                writeb(val8, addr);
@@@ -6997,7 -6999,7 +6999,7 @@@ static  int rxd_owner_bit_reset(struct 
                                                       &skb,(u64 *)&temp0_64,
                                                       (u64 *)&temp1_64,
                                                       (u64 *)&temp2_64,
 -                                                      size) == ENOMEM) {
 +                                                      size) == -ENOMEM) {
                                        return 0;
                                }
  
diff --combined drivers/net/sfc/falcon.c
index 8cb57987905ec0c1c78bcee7d12dffb2da817698,790db89db3454cd8da3ef1feb873b27b781abd1b..630406e142e5c7aa799695a7006a0511f07f6098
@@@ -13,8 -13,6 +13,8 @@@
  #include <linux/pci.h>
  #include <linux/module.h>
  #include <linux/seq_file.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c-algo-bit.h>
  #include "net_driver.h"
  #include "bitfield.h"
  #include "efx.h"
   * struct falcon_nic_data - Falcon NIC state
   * @next_buffer_table: First available buffer table id
   * @pci_dev2: The secondary PCI device if present
 + * @i2c_data: Operations and state for I2C bit-bashing algorithm
   */
  struct falcon_nic_data {
        unsigned next_buffer_table;
        struct pci_dev *pci_dev2;
 +      struct i2c_algo_bit_data i2c_data;
  };
  
  /**************************************************************************
@@@ -179,57 -175,39 +179,57 @@@ static inline int falcon_event_present(
   *
   **************************************************************************
   */
 -static void falcon_setsdascl(struct efx_i2c_interface *i2c)
 +static void falcon_setsda(void *data, int state)
  {
 +      struct efx_nic *efx = (struct efx_nic *)data;
        efx_oword_t reg;
  
 -      falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
 -      EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, (i2c->scl ? 0 : 1));
 -      EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, (i2c->sda ? 0 : 1));
 -      falcon_write(i2c->efx, &reg, GPIO_CTL_REG_KER);
 +      falcon_read(efx, &reg, GPIO_CTL_REG_KER);
 +      EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, !state);
 +      falcon_write(efx, &reg, GPIO_CTL_REG_KER);
  }
  
 -static int falcon_getsda(struct efx_i2c_interface *i2c)
 +static void falcon_setscl(void *data, int state)
  {
 +      struct efx_nic *efx = (struct efx_nic *)data;
        efx_oword_t reg;
  
 -      falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
 +      falcon_read(efx, &reg, GPIO_CTL_REG_KER);
 +      EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, !state);
 +      falcon_write(efx, &reg, GPIO_CTL_REG_KER);
 +}
 +
 +static int falcon_getsda(void *data)
 +{
 +      struct efx_nic *efx = (struct efx_nic *)data;
 +      efx_oword_t reg;
 +
 +      falcon_read(efx, &reg, GPIO_CTL_REG_KER);
        return EFX_OWORD_FIELD(reg, GPIO3_IN);
  }
  
 -static int falcon_getscl(struct efx_i2c_interface *i2c)
 +static int falcon_getscl(void *data)
  {
 +      struct efx_nic *efx = (struct efx_nic *)data;
        efx_oword_t reg;
  
 -      falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
 -      return EFX_DWORD_FIELD(reg, GPIO0_IN);
 +      falcon_read(efx, &reg, GPIO_CTL_REG_KER);
 +      return EFX_OWORD_FIELD(reg, GPIO0_IN);
  }
  
 -static struct efx_i2c_bit_operations falcon_i2c_bit_operations = {
 -      .setsda         = falcon_setsdascl,
 -      .setscl         = falcon_setsdascl,
 +static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
 +      .setsda         = falcon_setsda,
 +      .setscl         = falcon_setscl,
        .getsda         = falcon_getsda,
        .getscl         = falcon_getscl,
 -      .udelay         = 100,
 -      .mdelay         = 10,
 +      .udelay         = 5,
 +      /*
 +       * This is the number of system clock ticks after which
 +       * i2c-algo-bit gives up waiting for SCL to become high.
 +       * It must be at least 2 since the first tick can happen
 +       * immediately after it starts waiting.
 +       */
 +      .timeout        = 2,
  };
  
  /**************************************************************************
@@@ -755,8 -733,10 +755,10 @@@ void falcon_fini_rx(struct efx_rx_queu
                        continue;
                break;
        }
-       if (rc)
+       if (rc) {
                EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue);
+               efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
+       }
  
        /* Remove RX descriptor ring from card */
        EFX_ZERO_OWORD(rx_desc_ptr);
@@@ -2425,6 -2405,12 +2427,6 @@@ int falcon_probe_nic(struct efx_nic *ef
        struct falcon_nic_data *nic_data;
        int rc;
  
 -      /* Initialise I2C interface state */
 -      efx->i2c.efx = efx;
 -      efx->i2c.op = &falcon_i2c_bit_operations;
 -      efx->i2c.sda = 1;
 -      efx->i2c.scl = 1;
 -
        /* Allocate storage for hardware specific data */
        nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
        efx->nic_data = nic_data;
        if (rc)
                goto fail5;
  
 +      /* Initialise I2C adapter */
 +      efx->i2c_adap.owner = THIS_MODULE;
 +      efx->i2c_adap.class = I2C_CLASS_HWMON;
 +      nic_data->i2c_data = falcon_i2c_bit_operations;
 +      nic_data->i2c_data.data = efx;
 +      efx->i2c_adap.algo_data = &nic_data->i2c_data;
 +      efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
 +      strcpy(efx->i2c_adap.name, "SFC4000 GPIO");
 +      rc = i2c_bit_add_bus(&efx->i2c_adap);
 +      if (rc)
 +              goto fail5;
 +
        return 0;
  
   fail5:
@@@ -2661,10 -2635,6 +2663,10 @@@ int falcon_init_nic(struct efx_nic *efx
  void falcon_remove_nic(struct efx_nic *efx)
  {
        struct falcon_nic_data *nic_data = efx->nic_data;
 +      int rc;
 +
 +      rc = i2c_del_adapter(&efx->i2c_adap);
 +      BUG_ON(rc);
  
        falcon_free_buffer(efx, &efx->irq_status);
  
diff --combined drivers/net/sky2.c
index c83406f4f2a7618afab72b2f7aaf488225bebc94,62436b3a18c6fdf1a4ef55a44fb3ee6d22a48633..7f1cfc48e1b2c94d5068cf1c694bb4b8f105c9c7
@@@ -284,86 -284,6 +284,86 @@@ static void sky2_power_aux(struct sky2_
                             PC_VAUX_ON | PC_VCC_OFF));
  }
  
 +static void sky2_power_state(struct sky2_hw *hw, pci_power_t state)
 +{
 +      u16 power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL);
 +      int pex = pci_find_capability(hw->pdev, PCI_CAP_ID_EXP);
 +      u32 reg;
 +
 +      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 +
 +      switch (state) {
 +      case PCI_D0:
 +              break;
 +
 +      case PCI_D1:
 +              power_control |= 1;
 +              break;
 +
 +      case PCI_D2:
 +              power_control |= 2;
 +              break;
 +
 +      case PCI_D3hot:
 +      case PCI_D3cold:
 +              power_control |= 3;
 +              if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
 +                      /* additional power saving measurements */
 +                      reg = sky2_pci_read32(hw, PCI_DEV_REG4);
 +
 +                      /* set gating core clock for LTSSM in L1 state */
 +                      reg |= P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) |
 +                              /* auto clock gated scheme controlled by CLKREQ */
 +                              P_ASPM_A1_MODE_SELECT |
 +                              /* enable Gate Root Core Clock */
 +                              P_CLK_GATE_ROOT_COR_ENA;
 +
 +                      if (pex && (hw->flags & SKY2_HW_CLK_POWER)) {
 +                              /* enable Clock Power Management (CLKREQ) */
 +                              u16 ctrl = sky2_pci_read16(hw, pex + PCI_EXP_DEVCTL);
 +
 +                              ctrl |= PCI_EXP_DEVCTL_AUX_PME;
 +                              sky2_pci_write16(hw, pex + PCI_EXP_DEVCTL, ctrl);
 +                      } else
 +                              /* force CLKREQ Enable in Our4 (A1b only) */
 +                              reg |= P_ASPM_FORCE_CLKREQ_ENA;
 +
 +                      /* set Mask Register for Release/Gate Clock */
 +                      sky2_pci_write32(hw, PCI_DEV_REG5,
 +                                       P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST |
 +                                       P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE |
 +                                       P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN);
 +              } else
 +                      sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_CLK_HALT);
 +
 +              /* put CPU into reset state */
 +              sky2_write8(hw,  B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_RESET);
 +              if (hw->chip_id == CHIP_ID_YUKON_SUPR && hw->chip_rev == CHIP_REV_YU_SU_A0)
 +                      /* put CPU into halt state */
 +                      sky2_write8(hw, B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_HALTED);
 +
 +              if (pex && !(hw->flags & SKY2_HW_RAM_BUFFER)) {
 +                      reg = sky2_pci_read32(hw, PCI_DEV_REG1);
 +                      /* force to PCIe L1 */
 +                      reg |= PCI_FORCE_PEX_L1;
 +                      sky2_pci_write32(hw, PCI_DEV_REG1, reg);
 +              }
 +              break;
 +
 +      default:
 +              dev_warn(&hw->pdev->dev, PFX "Invalid power state (%d) ",
 +                     state);
 +              return;
 +      }
 +
 +      power_control |= PCI_PM_CTRL_PME_ENABLE;
 +      /* Finally, set the new power state. */
 +      sky2_pci_write32(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
 +
 +      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 +      sky2_pci_read32(hw, B0_CTST);
 +}
 +
  static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
  {
        u16 reg;
@@@ -699,71 -619,28 +699,71 @@@ static void sky2_phy_init(struct sky2_h
                gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
  }
  
 -static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
 +static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
 +static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
 +
 +static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port)
  {
        u32 reg1;
 -      static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
 -      static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
  
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
        reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
 -      /* Turn on/off phy power saving */
 -      if (onoff)
 -              reg1 &= ~phy_power[port];
 -      else
 -              reg1 |= phy_power[port];
 +      reg1 &= ~phy_power[port];
  
 -      if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
 +      if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
                reg1 |= coma_mode[port];
  
        sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
        sky2_pci_read32(hw, PCI_DEV_REG1);
 +}
 +
 +static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
 +{
 +      u32 reg1;
 +      u16 ctrl;
 +
 +      /* release GPHY Control reset */
 +      sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
  
 -      udelay(100);
 +      /* release GMAC reset */
 +      sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
 +
 +      if (hw->flags & SKY2_HW_NEWER_PHY) {
 +              /* select page 2 to access MAC control register */
 +              gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
 +
 +              ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
 +              /* allow GMII Power Down */
 +              ctrl &= ~PHY_M_MAC_GMIF_PUP;
 +              gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
 +
 +              /* set page register back to 0 */
 +              gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
 +      }
 +
 +      /* setup General Purpose Control Register */
 +      gma_write16(hw, port, GM_GP_CTRL,
 +                  GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
 +
 +      if (hw->chip_id != CHIP_ID_YUKON_EC) {
 +              if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
 +                      ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
 +
 +                      /* enable Power Down */
 +                      ctrl |= PHY_M_PC_POW_D_ENA;
 +                      gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
 +              }
 +
 +              /* set IEEE compatible Power Down Mode (dev. #4.99) */
 +              gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN);
 +      }
 +
 +      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 +      reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
 +      reg1 |= phy_power[port];                /* set PHY to PowerDown/COMA Mode */
 +      sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
 +      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
  }
  
  /* Force a renegotiation */
@@@ -798,11 -675,8 +798,11 @@@ static void sky2_wol_init(struct sky2_p
  
        sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
        sky2->flow_mode = FC_NONE;
 -      sky2_phy_power(hw, port, 1);
 -      sky2_phy_reinit(sky2);
 +
 +      spin_lock_bh(&sky2->phy_lock);
 +      sky2_phy_power_up(hw, port);
 +      sky2_phy_init(hw, port);
 +      spin_unlock_bh(&sky2->phy_lock);
  
        sky2->flow_mode = save_mode;
        sky2->advertising = ctrl;
@@@ -907,7 -781,6 +907,7 @@@ static void sky2_mac_init(struct sky2_h
        sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
  
        spin_lock_bh(&sky2->phy_lock);
 +      sky2_phy_power_up(hw, port);
        sky2_phy_init(hw, port);
        spin_unlock_bh(&sky2->phy_lock);
  
@@@ -1512,6 -1385,8 +1512,6 @@@ static int sky2_up(struct net_device *d
        if (!sky2->rx_ring)
                goto err_out;
  
 -      sky2_phy_power(hw, port, 1);
 -
        sky2_mac_init(hw, port);
  
        /* Register is number of 4K blocks on internal RAM buffer. */
@@@ -1892,7 -1767,7 +1892,7 @@@ static int sky2_down(struct net_device 
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
  
 -      sky2_phy_power(hw, port, 0);
 +      sky2_phy_power_down(hw, port);
  
        netif_carrier_off(dev);
  
@@@ -2866,10 -2741,6 +2866,10 @@@ static int __devinit sky2_init(struct s
                hw->flags = SKY2_HW_GIGABIT
                        | SKY2_HW_NEWER_PHY
                        | SKY2_HW_ADV_POWER_CTL;
 +
 +              /* check for Rev. A1 dev 4200 */
 +              if (sky2_read16(hw, Q_ADDR(Q_XA1, Q_WM)) == 0)
 +                      hw->flags |= SKY2_HW_CLK_POWER;
                break;
  
        case CHIP_ID_YUKON_EX:
        if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
                hw->flags |= SKY2_HW_FIBRE_PHY;
  
 +      hw->pm_cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PM);
 +      if (hw->pm_cap == 0) {
 +              dev_err(&hw->pdev->dev, "cannot find PowerManagement capability\n");
 +              return -EIO;
 +      }
  
        hw->ports = 1;
        t8 = sky2_read8(hw, B2_Y2_HW_RES);
@@@ -3512,7 -3378,7 +3512,7 @@@ static void sky2_led(struct sky2_port *
  
                gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
        } else
 -              gm_phy_write(hw, port, PHY_MARV_LED_OVER, 
 +              gm_phy_write(hw, port, PHY_MARV_LED_OVER,
                                     PHY_M_LED_MO_DUP(mode) |
                                     PHY_M_LED_MO_10(mode) |
                                     PHY_M_LED_MO_100(mode) |
@@@ -4496,7 -4362,7 +4496,7 @@@ static int sky2_suspend(struct pci_dev 
  
        pci_save_state(pdev);
        pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
 -      pci_set_power_state(pdev, pci_choose_state(pdev, state));
 +      sky2_power_state(hw, pci_choose_state(pdev, state));
  
        return 0;
  }
@@@ -4509,7 -4375,9 +4509,7 @@@ static int sky2_resume(struct pci_dev *
        if (!hw)
                return 0;
  
 -      err = pci_set_power_state(pdev, PCI_D0);
 -      if (err)
 -              goto out;
 +      sky2_power_state(hw, PCI_D0);
  
        err = pci_restore_state(pdev);
        if (err)
                        if (err) {
                                printk(KERN_ERR PFX "%s: could not up: %d\n",
                                       dev->name, err);
+                               rtnl_lock();
                                dev_close(dev);
+                               rtnl_unlock();
                                goto out;
                        }
                }
@@@ -4577,7 -4447,8 +4579,7 @@@ static void sky2_shutdown(struct pci_de
        pci_enable_wake(pdev, PCI_D3cold, wol);
  
        pci_disable_device(pdev);
 -      pci_set_power_state(pdev, PCI_D3hot);
 -
 +      sky2_power_state(hw, PCI_D3hot);
  }
  
  static struct pci_driver sky2_driver = {
diff --combined drivers/net/smc911x.c
index fc605f276c0051aea2b29e746483f5cfd1404cdf,e2ee91a6ae7e063c8f302b0eaba1fd56eedc12ba..c5871624f972cd3c662e1ba81d22a6f61aabb003
@@@ -106,6 -106,55 +106,6 @@@ MODULE_ALIAS("platform:smc911x")
   */
  #define POWER_DOWN             1
  
 -
 -/* store this information for the driver.. */
 -struct smc911x_local {
 -      /*
 -       * If I have to wait until the DMA is finished and ready to reload a
 -       * packet, I will store the skbuff here. Then, the DMA will send it
 -       * out and free it.
 -       */
 -      struct sk_buff *pending_tx_skb;
 -
 -      /* version/revision of the SMC911x chip */
 -      u16 version;
 -      u16 revision;
 -
 -      /* FIFO sizes */
 -      int tx_fifo_kb;
 -      int tx_fifo_size;
 -      int rx_fifo_size;
 -      int afc_cfg;
 -
 -      /* Contains the current active receive/phy mode */
 -      int ctl_rfduplx;
 -      int ctl_rspeed;
 -
 -      u32 msg_enable;
 -      u32 phy_type;
 -      struct mii_if_info mii;
 -
 -      /* work queue */
 -      struct work_struct phy_configure;
 -
 -      int tx_throttle;
 -      spinlock_t lock;
 -
 -      struct net_device *netdev;
 -
 -#ifdef SMC_USE_DMA
 -      /* DMA needs the physical address of the chip */
 -      u_long physaddr;
 -      int rxdma;
 -      int txdma;
 -      int rxdma_active;
 -      int txdma_active;
 -      struct sk_buff *current_rx_skb;
 -      struct sk_buff *current_tx_skb;
 -      struct device *dev;
 -#endif
 -};
 -
  #if SMC_DEBUG > 0
  #define DBG(n, args...)                                \
        do {                                     \
@@@ -153,24 -202,24 +153,24 @@@ static void PRINT_PKT(u_char *buf, int 
  
  
  /* this enables an interrupt in the interrupt mask register */
 -#define SMC_ENABLE_INT(x) do {                                \
 +#define SMC_ENABLE_INT(lp, x) do {                    \
        unsigned int  __mask;                           \
        unsigned long __flags;                          \
        spin_lock_irqsave(&lp->lock, __flags);          \
 -      __mask = SMC_GET_INT_EN();                      \
 +      __mask = SMC_GET_INT_EN((lp));                  \
        __mask |= (x);                                  \
 -      SMC_SET_INT_EN(__mask);                         \
 +      SMC_SET_INT_EN((lp), __mask);                   \
        spin_unlock_irqrestore(&lp->lock, __flags);     \
  } while (0)
  
  /* this disables an interrupt from the interrupt mask register */
 -#define SMC_DISABLE_INT(x) do {                               \
 +#define SMC_DISABLE_INT(lp, x) do {                   \
        unsigned int  __mask;                           \
        unsigned long __flags;                          \
        spin_lock_irqsave(&lp->lock, __flags);          \
 -      __mask = SMC_GET_INT_EN();                      \
 +      __mask = SMC_GET_INT_EN((lp));                  \
        __mask &= ~(x);                                 \
 -      SMC_SET_INT_EN(__mask);                         \
 +      SMC_SET_INT_EN((lp), __mask);                   \
        spin_unlock_irqrestore(&lp->lock, __flags);     \
  } while (0)
  
   */
  static void smc911x_reset(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned int reg, timeout=0, resets=1;
        unsigned long flags;
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
        /*       Take out of PM setting first */
 -      if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) {
 +      if ((SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_) == 0) {
                /* Write to the bytetest will take out of powerdown */
 -              SMC_SET_BYTE_TEST(0);
 +              SMC_SET_BYTE_TEST(lp, 0);
                timeout=10;
                do {
                        udelay(10);
 -                      reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
 +                      reg = SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_;
                } while (--timeout && !reg);
                if (timeout == 0) {
                        PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
  
        /* Disable all interrupts */
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_SET_INT_EN(0);
 +      SMC_SET_INT_EN(lp, 0);
        spin_unlock_irqrestore(&lp->lock, flags);
  
        while (resets--) {
 -              SMC_SET_HW_CFG(HW_CFG_SRST_);
 +              SMC_SET_HW_CFG(lp, HW_CFG_SRST_);
                timeout=10;
                do {
                        udelay(10);
 -                      reg = SMC_GET_HW_CFG();
 +                      reg = SMC_GET_HW_CFG(lp);
                        /* If chip indicates reset timeout then try again */
                        if (reg & HW_CFG_SRST_TO_) {
                                PRINTK("%s: chip reset timeout, retrying...\n", dev->name);
  
        /* make sure EEPROM has finished loading before setting GPIO_CFG */
        timeout=1000;
 -      while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) {
 +      while ( timeout-- && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) {
                udelay(10);
        }
        if (timeout == 0){
        }
  
        /* Initialize interrupts */
 -      SMC_SET_INT_EN(0);
 -      SMC_ACK_INT(-1);
 +      SMC_SET_INT_EN(lp, 0);
 +      SMC_ACK_INT(lp, -1);
  
        /* Reset the FIFO level and flow control settings */
 -      SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16);
 +      SMC_SET_HW_CFG(lp, (lp->tx_fifo_kb & 0xF) << 16);
  //TODO: Figure out what appropriate pause time is
 -      SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_);
 -      SMC_SET_AFC_CFG(lp->afc_cfg);
 +      SMC_SET_FLOW(lp, FLOW_FCPT_ | FLOW_FCEN_);
 +      SMC_SET_AFC_CFG(lp, lp->afc_cfg);
  
  
        /* Set to LED outputs */
 -      SMC_SET_GPIO_CFG(0x70070000);
 +      SMC_SET_GPIO_CFG(lp, 0x70070000);
  
        /*
         * Deassert IRQ for 1*10us for edge type interrupts
         * and drive IRQ pin push-pull
         */
 -      SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
 +      SMC_SET_IRQ_CFG(lp, (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_);
  
        /* clear anything saved */
        if (lp->pending_tx_skb != NULL) {
   */
  static void smc911x_enable(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned mask, cfg, cr;
        unsigned long flags;
  
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
 -      SMC_SET_MAC_ADDR(dev->dev_addr);
 +      SMC_SET_MAC_ADDR(lp, dev->dev_addr);
  
        /* Enable TX */
 -      cfg = SMC_GET_HW_CFG();
 +      cfg = SMC_GET_HW_CFG(lp);
        cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF;
        cfg |= HW_CFG_SF_;
 -      SMC_SET_HW_CFG(cfg);
 -      SMC_SET_FIFO_TDA(0xFF);
 +      SMC_SET_HW_CFG(lp, cfg);
 +      SMC_SET_FIFO_TDA(lp, 0xFF);
        /* Update TX stats on every 64 packets received or every 1 sec */
 -      SMC_SET_FIFO_TSL(64);
 -      SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
 +      SMC_SET_FIFO_TSL(lp, 64);
 +      SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000);
  
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_GET_MAC_CR(cr);
 +      SMC_GET_MAC_CR(lp, cr);
        cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_;
 -      SMC_SET_MAC_CR(cr);
 -      SMC_SET_TX_CFG(TX_CFG_TX_ON_);
 +      SMC_SET_MAC_CR(lp, cr);
 +      SMC_SET_TX_CFG(lp, TX_CFG_TX_ON_);
        spin_unlock_irqrestore(&lp->lock, flags);
  
        /* Add 2 byte padding to start of packets */
 -      SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_);
 +      SMC_SET_RX_CFG(lp, (2<<8) & RX_CFG_RXDOFF_);
  
        /* Turn on receiver and enable RX */
        if (cr & MAC_CR_RXEN_)
                DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name);
  
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ );
 +      SMC_SET_MAC_CR(lp, cr | MAC_CR_RXEN_);
        spin_unlock_irqrestore(&lp->lock, flags);
  
        /* Interrupt on every received packet */
 -      SMC_SET_FIFO_RSA(0x01);
 -      SMC_SET_FIFO_RSL(0x00);
 +      SMC_SET_FIFO_RSA(lp, 0x01);
 +      SMC_SET_FIFO_RSL(lp, 0x00);
  
        /* now, enable interrupts */
        mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ |
        else {
                mask|=INT_EN_RDFO_EN_;
        }
 -      SMC_ENABLE_INT(mask);
 +      SMC_ENABLE_INT(lp, mask);
  }
  
  /*
   */
  static void smc911x_shutdown(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned cr;
        unsigned long flags;
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__);
  
        /* Disable IRQ's */
 -      SMC_SET_INT_EN(0);
 +      SMC_SET_INT_EN(lp, 0);
  
        /* Turn of Rx and TX */
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_GET_MAC_CR(cr);
 +      SMC_GET_MAC_CR(lp, cr);
        cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
 -      SMC_SET_MAC_CR(cr);
 -      SMC_SET_TX_CFG(TX_CFG_STOP_TX_);
 +      SMC_SET_MAC_CR(lp, cr);
 +      SMC_SET_TX_CFG(lp, TX_CFG_STOP_TX_);
        spin_unlock_irqrestore(&lp->lock, flags);
  }
  
  static inline void smc911x_drop_pkt(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        unsigned int fifo_count, timeout, reg;
  
        DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__);
 -      fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF;
 +      fifo_count = SMC_GET_RX_FIFO_INF(lp) & 0xFFFF;
        if (fifo_count <= 4) {
                /* Manually dump the packet data */
                while (fifo_count--)
 -                      SMC_GET_RX_FIFO();
 +                      SMC_GET_RX_FIFO(lp);
        } else   {
                /* Fast forward through the bad packet */
 -              SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_);
 +              SMC_SET_RX_DP_CTRL(lp, RX_DP_CTRL_FFWD_BUSY_);
                timeout=50;
                do {
                        udelay(10);
 -                      reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
 +                      reg = SMC_GET_RX_DP_CTRL(lp) & RX_DP_CTRL_FFWD_BUSY_;
                } while (--timeout && reg);
                if (timeout == 0) {
                        PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
   */
  static inline void     smc911x_rcv(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        unsigned int pkt_len, status;
        struct sk_buff *skb;
        unsigned char *data;
  
        DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n",
                dev->name, __FUNCTION__);
 -      status = SMC_GET_RX_STS_FIFO();
 +      status = SMC_GET_RX_STS_FIFO(lp);
        DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n",
                dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff);
        pkt_len = (status & RX_STS_PKT_LEN_) >> 16;
                skb_put(skb,pkt_len-4);
  #ifdef SMC_USE_DMA
                {
 -              struct smc911x_local *lp = netdev_priv(dev);
                unsigned int fifo;
                /* Lower the FIFO threshold if possible */
 -              fifo = SMC_GET_FIFO_INT();
 +              fifo = SMC_GET_FIFO_INT(lp);
                if (fifo & 0xFF) fifo--;
                DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n",
                        dev->name, fifo & 0xff);
 -              SMC_SET_FIFO_INT(fifo);
 +              SMC_SET_FIFO_INT(lp, fifo);
                /* Setup RX DMA */
 -              SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_));
 +              SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_));
                lp->rxdma_active = 1;
                lp->current_rx_skb = skb;
 -              SMC_PULL_DATA(data, (pkt_len+2+15) & ~15);
 +              SMC_PULL_DATA(lp, data, (pkt_len+2+15) & ~15);
                /* Packet processing deferred to DMA RX interrupt */
                }
  #else
 -              SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_));
 -              SMC_PULL_DATA(data, pkt_len+2+3);
 +              SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_));
 +              SMC_PULL_DATA(lp, data, pkt_len+2+3);
  
                DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name);
                PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
  static void smc911x_hardware_send_pkt(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        struct sk_buff *skb;
        unsigned int cmdA, cmdB, len;
        unsigned char *buf;
  
        DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n",
                 dev->name, len, len, buf, cmdA, cmdB);
 -      SMC_SET_TX_FIFO(cmdA);
 -      SMC_SET_TX_FIFO(cmdB);
 +      SMC_SET_TX_FIFO(lp, cmdA);
 +      SMC_SET_TX_FIFO(lp, cmdB);
  
        DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name);
        PRINT_PKT(buf, len <= 64 ? len : 64);
        /* Send pkt via PIO or DMA */
  #ifdef SMC_USE_DMA
        lp->current_tx_skb = skb;
 -      SMC_PUSH_DATA(buf, len);
 +      SMC_PUSH_DATA(lp, buf, len);
        /* DMA complete IRQ will free buffer and set jiffies */
  #else
 -      SMC_PUSH_DATA(buf, len);
 +      SMC_PUSH_DATA(lp, buf, len);
        dev->trans_start = jiffies;
        dev_kfree_skb(skb);
  #endif
                netif_wake_queue(dev);
        }
        spin_unlock_irqrestore(&lp->lock, flags);
 -      SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
 +      SMC_ENABLE_INT(lp, INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
  }
  
  /*
  static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        unsigned int free;
        unsigned long flags;
  
  
        BUG_ON(lp->pending_tx_skb != NULL);
  
 -      free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_;
 +      free = SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TDFREE_;
        DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free);
  
        /* Turn off the flow when running out of space in FIFO */
                        dev->name, free);
                spin_lock_irqsave(&lp->lock, flags);
                /* Reenable when at least 1 packet of size MTU present */
 -              SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
 +              SMC_SET_FIFO_TDA(lp, (SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
                lp->tx_throttle = 1;
                netif_stop_queue(dev);
                spin_unlock_irqrestore(&lp->lock, flags);
   */
  static void smc911x_tx(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned int tx_status;
  
                dev->name, __FUNCTION__);
  
        /* Collect the TX status */
 -      while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
 +      while (((SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
                DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n",
                        dev->name,
 -                      (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16);
 -              tx_status = SMC_GET_TX_STS_FIFO();
 +                      (SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16);
 +              tx_status = SMC_GET_TX_STS_FIFO(lp);
                dev->stats.tx_packets++;
                dev->stats.tx_bytes+=tx_status>>16;
                DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n",
  
  static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        unsigned int phydata;
  
 -      SMC_GET_MII(phyreg, phyaddr, phydata);
 +      SMC_GET_MII(lp, phyreg, phyaddr, phydata);
  
        DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n",
                __FUNCTION__, phyaddr, phyreg, phydata);
  static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg,
                        int phydata)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
  
        DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
                __FUNCTION__, phyaddr, phyreg, phydata);
  
 -      SMC_SET_MII(phyreg, phyaddr, phydata);
 +      SMC_SET_MII(lp, phyreg, phyaddr, phydata);
  }
  
  /*
   */
  static void smc911x_phy_detect(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        int phyaddr;
        unsigned int cfg, id1, id2;
        switch(lp->version) {
                case 0x115:
                case 0x117:
 -                      cfg = SMC_GET_HW_CFG();
 +                      cfg = SMC_GET_HW_CFG(lp);
                        if (cfg & HW_CFG_EXT_PHY_DET_) {
                                cfg &= ~HW_CFG_PHY_CLK_SEL_;
                                cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
 -                              SMC_SET_HW_CFG(cfg);
 +                              SMC_SET_HW_CFG(lp, cfg);
                                udelay(10); /* Wait for clocks to stop */
  
                                cfg |= HW_CFG_EXT_PHY_EN_;
 -                              SMC_SET_HW_CFG(cfg);
 +                              SMC_SET_HW_CFG(lp, cfg);
                                udelay(10); /* Wait for clocks to stop */
  
                                cfg &= ~HW_CFG_PHY_CLK_SEL_;
                                cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
 -                              SMC_SET_HW_CFG(cfg);
 +                              SMC_SET_HW_CFG(lp, cfg);
                                udelay(10); /* Wait for clocks to stop */
  
                                cfg |= HW_CFG_SMI_SEL_;
 -                              SMC_SET_HW_CFG(cfg);
 +                              SMC_SET_HW_CFG(lp, cfg);
  
                                for (phyaddr = 1; phyaddr < 32; ++phyaddr) {
  
                                        /* Read the PHY identifiers */
 -                                      SMC_GET_PHY_ID1(phyaddr & 31, id1);
 -                                      SMC_GET_PHY_ID2(phyaddr & 31, id2);
 +                                      SMC_GET_PHY_ID1(lp, phyaddr & 31, id1);
 +                                      SMC_GET_PHY_ID2(lp, phyaddr & 31, id2);
  
                                        /* Make sure it is a valid identifier */
                                        if (id1 != 0x0000 && id1 != 0xffff &&
                        }
                default:
                        /* Internal media only */
 -                      SMC_GET_PHY_ID1(1, id1);
 -                      SMC_GET_PHY_ID2(1, id2);
 +                      SMC_GET_PHY_ID1(lp, 1, id1);
 +                      SMC_GET_PHY_ID2(lp, 1, id2);
                        /* Save the PHY's address */
                        lp->mii.phy_id = 1;
                        lp->phy_type = id1 << 16 | id2;
  static int smc911x_phy_fixed(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int phyaddr = lp->mii.phy_id;
        int bmcr;
  
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
        /* Enter Link Disable state */
 -      SMC_GET_PHY_BMCR(phyaddr, bmcr);
 +      SMC_GET_PHY_BMCR(lp, phyaddr, bmcr);
        bmcr |= BMCR_PDOWN;
 -      SMC_SET_PHY_BMCR(phyaddr, bmcr);
 +      SMC_SET_PHY_BMCR(lp, phyaddr, bmcr);
  
        /*
         * Set our fixed capabilities
                bmcr |= BMCR_SPEED100;
  
        /* Write our capabilities to the phy control register */
 -      SMC_SET_PHY_BMCR(phyaddr, bmcr);
 +      SMC_SET_PHY_BMCR(lp, phyaddr, bmcr);
  
        /* Re-Configure the Receive/Phy Control register */
        bmcr &= ~BMCR_PDOWN;
 -      SMC_SET_PHY_BMCR(phyaddr, bmcr);
 +      SMC_SET_PHY_BMCR(lp, phyaddr, bmcr);
  
        return 1;
  }
  static int smc911x_phy_reset(struct net_device *dev, int phy)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int timeout;
        unsigned long flags;
        unsigned int reg;
        DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
  
        spin_lock_irqsave(&lp->lock, flags);
 -      reg = SMC_GET_PMT_CTRL();
 +      reg = SMC_GET_PMT_CTRL(lp);
        reg &= ~0xfffff030;
        reg |= PMT_CTRL_PHY_RST_;
 -      SMC_SET_PMT_CTRL(reg);
 +      SMC_SET_PMT_CTRL(lp, reg);
        spin_unlock_irqrestore(&lp->lock, flags);
        for (timeout = 2; timeout; timeout--) {
                msleep(50);
                spin_lock_irqsave(&lp->lock, flags);
 -              reg = SMC_GET_PMT_CTRL();
 +              reg = SMC_GET_PMT_CTRL(lp);
                spin_unlock_irqrestore(&lp->lock, flags);
                if (!(reg & PMT_CTRL_PHY_RST_)) {
                        /* extra delay required because the phy may
   */
  static void smc911x_phy_powerdown(struct net_device *dev, int phy)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        unsigned int bmcr;
  
        /* Enter Link Disable state */
 -      SMC_GET_PHY_BMCR(phy, bmcr);
 +      SMC_GET_PHY_BMCR(lp, phy, bmcr);
        bmcr |= BMCR_PDOWN;
 -      SMC_SET_PHY_BMCR(phy, bmcr);
 +      SMC_SET_PHY_BMCR(lp, phy, bmcr);
  }
  
  /*
  static void smc911x_phy_check_media(struct net_device *dev, int init)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int phyaddr = lp->mii.phy_id;
        unsigned int bmcr, cr;
  
  
        if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
                /* duplex state has changed */
 -              SMC_GET_PHY_BMCR(phyaddr, bmcr);
 -              SMC_GET_MAC_CR(cr);
 +              SMC_GET_PHY_BMCR(lp, phyaddr, bmcr);
 +              SMC_GET_MAC_CR(lp, cr);
                if (lp->mii.full_duplex) {
                        DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name);
                        bmcr |= BMCR_FULLDPLX;
                        bmcr &= ~BMCR_FULLDPLX;
                        cr &= ~MAC_CR_RCVOWN_;
                }
 -              SMC_SET_PHY_BMCR(phyaddr, bmcr);
 -              SMC_SET_MAC_CR(cr);
 +              SMC_SET_PHY_BMCR(lp, phyaddr, bmcr);
 +              SMC_SET_MAC_CR(lp, cr);
        }
  }
  
@@@ -886,6 -946,7 +886,6 @@@ static void smc911x_phy_configure(struc
        struct smc911x_local *lp = container_of(work, struct smc911x_local,
                                                phy_configure);
        struct net_device *dev = lp->netdev;
 -      unsigned long ioaddr = dev->base_addr;
        int phyaddr = lp->mii.phy_id;
        int my_phy_caps; /* My PHY capabilities */
        int my_ad_caps; /* My Advertised capabilities */
         * We should not be called if phy_type is zero.
         */
        if (lp->phy_type == 0)
-                goto smc911x_phy_configure_exit_nolock;
+               return;
  
        if (smc911x_phy_reset(dev, phyaddr)) {
                printk("%s: PHY reset timed out\n", dev->name);
-               goto smc911x_phy_configure_exit_nolock;
+               return;
        }
        spin_lock_irqsave(&lp->lock, flags);
  
         * Enable PHY Interrupts (for register 18)
         * Interrupts listed here are enabled
         */
 -      SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ |
 +      SMC_SET_PHY_INT_MASK(lp, phyaddr, PHY_INT_MASK_ENERGY_ON_ |
                 PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ |
                 PHY_INT_MASK_LINK_DOWN_);
  
        }
  
        /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
 -      SMC_GET_PHY_BMSR(phyaddr, my_phy_caps);
 +      SMC_GET_PHY_BMSR(lp, phyaddr, my_phy_caps);
        if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
                printk(KERN_INFO "Auto negotiation NOT supported\n");
                smc911x_phy_fixed(dev);
                my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
  
        /* Update our Auto-Neg Advertisement Register */
 -      SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps);
 +      SMC_SET_PHY_MII_ADV(lp, phyaddr, my_ad_caps);
        lp->mii.advertising = my_ad_caps;
  
        /*
         * the link does not come up.
         */
        udelay(10);
 -      SMC_GET_PHY_MII_ADV(phyaddr, status);
 +      SMC_GET_PHY_MII_ADV(lp, phyaddr, status);
  
        DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps);
        DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps);
  
        /* Restart auto-negotiation process in order to advertise my caps */
 -      SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
 +      SMC_SET_PHY_BMCR(lp, phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
  
        smc911x_phy_check_media(dev, 1);
  
  smc911x_phy_configure_exit:
        spin_unlock_irqrestore(&lp->lock, flags);
- smc911x_phy_configure_exit_nolock:
-       lp->work_pending = 0;
  }
  
  /*
  static void smc911x_phy_interrupt(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int phyaddr = lp->mii.phy_id;
        int status;
  
  
        smc911x_phy_check_media(dev, 0);
        /* read to clear status bits */
 -      SMC_GET_PHY_INT_SRC(phyaddr,status);
 +      SMC_GET_PHY_INT_SRC(lp, phyaddr,status);
        DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n",
                dev->name, status & 0xffff);
        DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n",
 -              dev->name, SMC_GET_AFC_CFG());
 +              dev->name, SMC_GET_AFC_CFG(lp));
  }
  
  /*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
  static irqreturn_t smc911x_interrupt(int irq, void *dev_id)
  {
        struct net_device *dev = dev_id;
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned int status, mask, timeout;
        unsigned int rx_overrun=0, cr, pkts;
        spin_lock_irqsave(&lp->lock, flags);
  
        /* Spurious interrupt check */
 -      if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
 +      if ((SMC_GET_IRQ_CFG(lp) & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
                (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
                spin_unlock_irqrestore(&lp->lock, flags);
                return IRQ_NONE;
        }
  
 -      mask = SMC_GET_INT_EN();
 -      SMC_SET_INT_EN(0);
 +      mask = SMC_GET_INT_EN(lp);
 +      SMC_SET_INT_EN(lp, 0);
  
        /* set a timeout value, so I don't stay here forever */
        timeout = 8;
  
  
        do {
 -              status = SMC_GET_INT();
 +              status = SMC_GET_INT(lp);
  
                DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n",
                        dev->name, status, mask, status & ~mask);
  
                /* Handle SW interrupt condition */
                if (status & INT_STS_SW_INT_) {
 -                      SMC_ACK_INT(INT_STS_SW_INT_);
 +                      SMC_ACK_INT(lp, INT_STS_SW_INT_);
                        mask &= ~INT_EN_SW_INT_EN_;
                }
                /* Handle various error conditions */
                if (status & INT_STS_RXE_) {
 -                      SMC_ACK_INT(INT_STS_RXE_);
 +                      SMC_ACK_INT(lp, INT_STS_RXE_);
                        dev->stats.rx_errors++;
                }
                if (status & INT_STS_RXDFH_INT_) {
 -                      SMC_ACK_INT(INT_STS_RXDFH_INT_);
 -                      dev->stats.rx_dropped+=SMC_GET_RX_DROP();
 +                      SMC_ACK_INT(lp, INT_STS_RXDFH_INT_);
 +                      dev->stats.rx_dropped+=SMC_GET_RX_DROP(lp);
                 }
                /* Undocumented interrupt-what is the right thing to do here? */
                if (status & INT_STS_RXDF_INT_) {
 -                      SMC_ACK_INT(INT_STS_RXDF_INT_);
 +                      SMC_ACK_INT(lp, INT_STS_RXDF_INT_);
                }
  
                /* Rx Data FIFO exceeds set level */
                if (status & INT_STS_RDFL_) {
                        if (IS_REV_A(lp->revision)) {
                                rx_overrun=1;
 -                              SMC_GET_MAC_CR(cr);
 +                              SMC_GET_MAC_CR(lp, cr);
                                cr &= ~MAC_CR_RXEN_;
 -                              SMC_SET_MAC_CR(cr);
 +                              SMC_SET_MAC_CR(lp, cr);
                                DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
                                dev->stats.rx_errors++;
                                dev->stats.rx_fifo_errors++;
                        }
 -                      SMC_ACK_INT(INT_STS_RDFL_);
 +                      SMC_ACK_INT(lp, INT_STS_RDFL_);
                }
                if (status & INT_STS_RDFO_) {
                        if (!IS_REV_A(lp->revision)) {
 -                              SMC_GET_MAC_CR(cr);
 +                              SMC_GET_MAC_CR(lp, cr);
                                cr &= ~MAC_CR_RXEN_;
 -                              SMC_SET_MAC_CR(cr);
 +                              SMC_SET_MAC_CR(lp, cr);
                                rx_overrun=1;
                                DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
                                dev->stats.rx_errors++;
                                dev->stats.rx_fifo_errors++;
                        }
 -                      SMC_ACK_INT(INT_STS_RDFO_);
 +                      SMC_ACK_INT(lp, INT_STS_RDFO_);
                }
                /* Handle receive condition */
                if ((status & INT_STS_RSFL_) || rx_overrun) {
                        unsigned int fifo;
                        DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name);
 -                      fifo = SMC_GET_RX_FIFO_INF();
 +                      fifo = SMC_GET_RX_FIFO_INF(lp);
                        pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16;
                        DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n",
                                dev->name, pkts, fifo & 0xFFFF );
                                        DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
                                                "%s: RX DMA active\n", dev->name);
                                        /* The DMA is already running so up the IRQ threshold */
 -                                      fifo = SMC_GET_FIFO_INT() & ~0xFF;
 +                                      fifo = SMC_GET_FIFO_INT(lp) & ~0xFF;
                                        fifo |= pkts & 0xFF;
                                        DBG(SMC_DEBUG_RX,
                                                "%s: Setting RX stat FIFO threshold to %d\n",
                                                dev->name, fifo & 0xff);
 -                                      SMC_SET_FIFO_INT(fifo);
 +                                      SMC_SET_FIFO_INT(lp, fifo);
                                } else
  #endif
                                smc911x_rcv(dev);
                        }
 -                      SMC_ACK_INT(INT_STS_RSFL_);
 +                      SMC_ACK_INT(lp, INT_STS_RSFL_);
                }
                /* Handle transmit FIFO available */
                if (status & INT_STS_TDFA_) {
                        DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name);
 -                      SMC_SET_FIFO_TDA(0xFF);
 +                      SMC_SET_FIFO_TDA(lp, 0xFF);
                        lp->tx_throttle = 0;
  #ifdef SMC_USE_DMA
                        if (!lp->txdma_active)
  #endif
                                netif_wake_queue(dev);
 -                      SMC_ACK_INT(INT_STS_TDFA_);
 +                      SMC_ACK_INT(lp, INT_STS_TDFA_);
                }
                /* Handle transmit done condition */
  #if 1
                if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) {
                        DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC,
                                "%s: Tx stat FIFO limit (%d) /GPT irq\n",
 -                              dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16);
 +                              dev->name, (SMC_GET_FIFO_INT(lp) & 0x00ff0000) >> 16);
                        smc911x_tx(dev);
 -                      SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
 -                      SMC_ACK_INT(INT_STS_TSFL_);
 -                      SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_);
 +                      SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000);
 +                      SMC_ACK_INT(lp, INT_STS_TSFL_);
 +                      SMC_ACK_INT(lp, INT_STS_TSFL_ | INT_STS_GPT_INT_);
                }
  #else
                if (status & INT_STS_TSFL_) {
                        DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, );
                        smc911x_tx(dev);
 -                      SMC_ACK_INT(INT_STS_TSFL_);
 +                      SMC_ACK_INT(lp, INT_STS_TSFL_);
                }
  
                if (status & INT_STS_GPT_INT_) {
                        DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n",
                                dev->name,
 -                              SMC_GET_IRQ_CFG(),
 -                              SMC_GET_FIFO_INT(),
 -                              SMC_GET_RX_CFG());
 +                              SMC_GET_IRQ_CFG(lp),
 +                              SMC_GET_FIFO_INT(lp),
 +                              SMC_GET_RX_CFG(lp));
                        DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x "
                                "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n",
                                dev->name,
 -                              (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16,
 -                              SMC_GET_RX_FIFO_INF() & 0xffff,
 -                              SMC_GET_RX_STS_FIFO_PEEK());
 -                      SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
 -                      SMC_ACK_INT(INT_STS_GPT_INT_);
 +                              (SMC_GET_RX_FIFO_INF(lp) & 0x00ff0000) >> 16,
 +                              SMC_GET_RX_FIFO_INF(lp) & 0xffff,
 +                              SMC_GET_RX_STS_FIFO_PEEK(lp));
 +                      SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000);
 +                      SMC_ACK_INT(lp, INT_STS_GPT_INT_);
                }
  #endif
  
                if (status & INT_STS_PHY_INT_) {
                        DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name);
                        smc911x_phy_interrupt(dev);
 -                      SMC_ACK_INT(INT_STS_PHY_INT_);
 +                      SMC_ACK_INT(lp, INT_STS_PHY_INT_);
                }
        } while (--timeout);
  
        /* restore mask state */
 -      SMC_SET_INT_EN(mask);
 +      SMC_SET_INT_EN(lp, mask);
  
        DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n",
                dev->name, 8-timeout);
@@@ -1271,31 -1332,29 +1269,28 @@@ static void smc911x_poll_controller(str
  static void smc911x_timeout(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int status, mask;
        unsigned long flags;
  
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
        spin_lock_irqsave(&lp->lock, flags);
 -      status = SMC_GET_INT();
 -      mask = SMC_GET_INT_EN();
 +      status = SMC_GET_INT(lp);
 +      mask = SMC_GET_INT_EN(lp);
        spin_unlock_irqrestore(&lp->lock, flags);
        DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n",
                dev->name, status, mask);
  
        /* Dump the current TX FIFO contents and restart */
 -      mask = SMC_GET_TX_CFG();
 -      SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);
 +      mask = SMC_GET_TX_CFG(lp);
 +      SMC_SET_TX_CFG(lp, mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);
        /*
         * Reconfiguring the PHY doesn't seem like a bad idea here, but
         * smc911x_phy_configure() calls msleep() which calls schedule_timeout()
         * which calls schedule().       Hence we use a work queue.
         */
-       if (lp->phy_type != 0) {
-               if (schedule_work(&lp->phy_configure)) {
-                       lp->work_pending = 1;
-               }
-       }
+       if (lp->phy_type != 0)
+               schedule_work(&lp->phy_configure);
  
        /* We can accept TX packets again */
        dev->trans_start = jiffies;
  static void smc911x_set_multicast_list(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        unsigned int multicast_table[2];
        unsigned int mcr, update_multicast = 0;
        unsigned long flags;
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_GET_MAC_CR(mcr);
 +      SMC_GET_MAC_CR(lp, mcr);
        spin_unlock_irqrestore(&lp->lock, flags);
  
        if (dev->flags & IFF_PROMISC) {
        }
  
        spin_lock_irqsave(&lp->lock, flags);
 -      SMC_SET_MAC_CR(mcr);
 +      SMC_SET_MAC_CR(lp, mcr);
        if (update_multicast) {
                DBG(SMC_DEBUG_MISC,
                        "%s: update mcast hash table 0x%08x 0x%08x\n",
                        dev->name, multicast_table[0], multicast_table[1]);
 -              SMC_SET_HASHL(multicast_table[0]);
 -              SMC_SET_HASHH(multicast_table[1]);
 +              SMC_SET_HASHL(lp, multicast_table[0]);
 +              SMC_SET_HASHH(lp, multicast_table[1]);
        }
        spin_unlock_irqrestore(&lp->lock, flags);
  }
@@@ -1465,16 -1525,8 +1460,8 @@@ static int smc911x_close(struct net_dev
        if (lp->phy_type != 0) {
                /* We need to ensure that no calls to
                 * smc911x_phy_configure are pending.
-                * flush_scheduled_work() cannot be called because we
-                * are running with the netlink semaphore held (from
-                * devinet_ioctl()) and the pending work queue
-                * contains linkwatch_event() (scheduled by
-                * netif_carrier_off() above). linkwatch_event() also
-                * wants the netlink semaphore.
                 */
-               while (lp->work_pending)
-                       schedule();
+               cancel_work_sync(&lp->phy_configure);
                smc911x_phy_powerdown(dev, lp->mii.phy_id);
        }
  
@@@ -1493,6 -1545,7 +1480,6 @@@ static in
  smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
  {
        struct smc911x_local *lp = netdev_priv(dev);
 -      unsigned long ioaddr = dev->base_addr;
        int ret, status;
        unsigned long flags;
  
                else
                        cmd->transceiver = XCVR_EXTERNAL;
                cmd->port = 0;
 -              SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status);
 +              SMC_GET_PHY_SPECIAL(lp, lp->mii.phy_id, status);
                cmd->duplex =
                        (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ?
                                DUPLEX_FULL : DUPLEX_HALF;
@@@ -1601,6 -1654,7 +1588,6 @@@ static int smc911x_ethtool_getregslen(s
  static void smc911x_ethtool_getregs(struct net_device *dev,
                                                                                 struct ethtool_regs* regs, void *buf)
  {
 -      unsigned long ioaddr = dev->base_addr;
        struct smc911x_local *lp = netdev_priv(dev);
        unsigned long flags;
        u32 reg,i,j=0;
  
        regs->version = lp->version;
        for(i=ID_REV;i<=E2P_CMD;i+=4) {
 -              data[j++] = SMC_inl(ioaddr,i);
 +              data[j++] = SMC_inl(lp, i);
        }
        for(i=MAC_CR;i<=WUCSR;i++) {
                spin_lock_irqsave(&lp->lock, flags);
 -              SMC_GET_MAC_CSR(i, reg);
 +              SMC_GET_MAC_CSR(lp, i, reg);
                spin_unlock_irqrestore(&lp->lock, flags);
                data[j++] = reg;
        }
        for(i=0;i<=31;i++) {
                spin_lock_irqsave(&lp->lock, flags);
 -              SMC_GET_MII(i, lp->mii.phy_id, reg);
 +              SMC_GET_MII(lp, i, lp->mii.phy_id, reg);
                spin_unlock_irqrestore(&lp->lock, flags);
                data[j++] = reg & 0xFFFF;
        }
  
  static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        unsigned int timeout;
        int e2p_cmd;
  
 -      e2p_cmd = SMC_GET_E2P_CMD();
 +      e2p_cmd = SMC_GET_E2P_CMD(lp);
        for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) {
                if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) {
                        PRINTK("%s: %s timeout waiting for EEPROM to respond\n",
                        return -EFAULT;
                }
                mdelay(1);
 -              e2p_cmd = SMC_GET_E2P_CMD();
 +              e2p_cmd = SMC_GET_E2P_CMD(lp);
        }
        if (timeout == 0) {
                PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n",
  static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
                                                                                                        int cmd, int addr)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        int ret;
  
        if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
                return ret;
 -      SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ |
 +      SMC_SET_E2P_CMD(lp, E2P_CMD_EPC_BUSY_ |
                ((cmd) & (0x7<<28)) |
                ((addr) & 0xFF));
        return 0;
  static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
                                                                                                        u8 *data)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        int ret;
  
        if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
                return ret;
 -      *data = SMC_GET_E2P_DATA();
 +      *data = SMC_GET_E2P_DATA(lp);
        return 0;
  }
  
  static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
                                                                                                         u8 data)
  {
 -      unsigned long ioaddr = dev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(dev);
        int ret;
  
        if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
                return ret;
 -      SMC_SET_E2P_DATA(data);
 +      SMC_SET_E2P_DATA(lp, data);
        return 0;
  }
  
@@@ -1749,9 -1803,8 +1736,9 @@@ static const struct ethtool_ops smc911x
   * This routine has a simple purpose -- make the SMC chip generate an
   * interrupt, so an auto-detect routine can detect it, and find the IRQ,
   */
 -static int __init smc911x_findirq(unsigned long ioaddr)
 +static int __init smc911x_findirq(struct net_device *dev)
  {
 +      struct smc911x_local *lp = netdev_priv(dev);
        int timeout = 20;
        unsigned long cookie;
  
         * Force a SW interrupt
         */
  
 -      SMC_SET_INT_EN(INT_EN_SW_INT_EN_);
 +      SMC_SET_INT_EN(lp, INT_EN_SW_INT_EN_);
  
        /*
         * Wait until positive that the interrupt has been generated
        do {
                int int_status;
                udelay(10);
 -              int_status = SMC_GET_INT_EN();
 +              int_status = SMC_GET_INT_EN(lp);
                if (int_status & INT_EN_SW_INT_EN_)
                         break;         /* got the interrupt */
        } while (--timeout);
         */
  
        /* and disable all interrupts again */
 -      SMC_SET_INT_EN(0);
 +      SMC_SET_INT_EN(lp, 0);
  
        /* and return what I found */
        return probe_irq_off(cookie);
   * o  actually GRAB the irq.
   * o  GRAB the region
   */
 -static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
 +static int __init smc911x_probe(struct net_device *dev)
  {
        struct smc911x_local *lp = netdev_priv(dev);
        int i, retval;
        unsigned int val, chip_id, revision;
        const char *version_string;
 +      unsigned long irq_flags;
  
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
  
        /* First, see if the endian word is recognized */
 -      val = SMC_GET_BYTE_TEST();
 +      val = SMC_GET_BYTE_TEST(lp);
        DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
        if (val != 0x87654321) {
                printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
         * recognize.   These might need to be added to later,
         * as future revisions could be added.
         */
 -      chip_id = SMC_GET_PN();
 +      chip_id = SMC_GET_PN(lp);
        DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id);
        for(i=0;chip_ids[i].id != 0; i++) {
                if (chip_ids[i].id == chip_id) break;
        }
        version_string = chip_ids[i].name;
  
 -      revision = SMC_GET_REV();
 +      revision = SMC_GET_REV(lp);
        DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision);
  
        /* At this point I'll assume that the chip is an SMC911x. */
        }
  
        /* fill in some of the fields */
 -      dev->base_addr = ioaddr;
        lp->version = chip_ids[i].id;
        lp->revision = revision;
        lp->tx_fifo_kb = tx_fifo_kb;
        spin_lock_init(&lp->lock);
  
        /* Get the MAC address */
 -      SMC_GET_MAC_ADDR(dev->dev_addr);
 +      SMC_GET_MAC_ADDR(lp, dev->dev_addr);
  
        /* now, reset the chip, and put it into a known state */
        smc911x_reset(dev);
  
                trials = 3;
                while (trials--) {
 -                      dev->irq = smc911x_findirq(ioaddr);
 +                      dev->irq = smc911x_findirq(dev);
                        if (dev->irq)
                                break;
                        /* kick the card and try again */
        lp->ctl_rfduplx = 1;
        lp->ctl_rspeed = 100;
  
 +#ifdef SMC_DYNAMIC_BUS_CONFIG
 +      irq_flags = lp->cfg.irq_flags;
 +#else
 +      irq_flags = IRQF_SHARED | SMC_IRQ_SENSE;
 +#endif
 +
        /* Grab the IRQ */
        retval = request_irq(dev->irq, &smc911x_interrupt,
 -                      IRQF_SHARED | SMC_IRQ_SENSE, dev->name, dev);
 +                           irq_flags, dev->name, dev);
        if (retval)
                goto err_out;
  
@@@ -2064,7 -2111,6 +2051,7 @@@ err_out
   */
  static int smc911x_drv_probe(struct platform_device *pdev)
  {
 +      struct smc91x_platdata *pd = pdev->dev.platform_data;
        struct net_device *ndev;
        struct resource *res;
        struct smc911x_local *lp;
        ndev->irq = platform_get_irq(pdev, 0);
        lp = netdev_priv(ndev);
        lp->netdev = ndev;
 +#ifdef SMC_DYNAMIC_BUS_CONFIG
 +      if (!pd) {
 +              ret = -EINVAL;
 +              goto release_both;
 +      }
 +      memcpy(&lp->cfg, pd, sizeof(lp->cfg));
 +#endif
  
        addr = ioremap(res->start, SMC911X_IO_EXTENT);
        if (!addr) {
        }
  
        platform_set_drvdata(pdev, ndev);
 -      ret = smc911x_probe(ndev, (unsigned long)addr);
 +      lp->base = addr;
 +      ndev->base_addr = res->start;
 +      ret = smc911x_probe(ndev);
        if (ret != 0) {
                platform_set_drvdata(pdev, NULL);
                iounmap(addr);
@@@ -2139,7 -2176,6 +2126,7 @@@ out
  static int smc911x_drv_remove(struct platform_device *pdev)
  {
        struct net_device *ndev = platform_get_drvdata(pdev);
 +      struct smc911x_local *lp = netdev_priv(ndev);
        struct resource *res;
  
        DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
  
  #ifdef SMC_USE_DMA
        {
 -              struct smc911x_local *lp = netdev_priv(ndev);
                if (lp->rxdma != -1) {
                        SMC_DMA_FREE(dev, lp->rxdma);
                }
                }
        }
  #endif
 -      iounmap((void *)ndev->base_addr);
 +      iounmap(lp->base);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, SMC911X_IO_EXTENT);
  
  static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state)
  {
        struct net_device *ndev = platform_get_drvdata(dev);
 -      unsigned long ioaddr = ndev->base_addr;
 +      struct smc911x_local *lp = netdev_priv(ndev);
  
        DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
        if (ndev) {
                        smc911x_shutdown(ndev);
  #if POWER_DOWN
                        /* Set D2 - Energy detect only setting */
 -                      SMC_SET_PMT_CTRL(2<<12);
 +                      SMC_SET_PMT_CTRL(lp, 2<<12);
  #endif
                }
        }
diff --combined drivers/net/smc911x.h
index 7cc7cd7e99cde913fb29ab39f7f1c817cccd74a8,7defa63b9c747efd1cda1ea902079c0124340cac..76c17c28fab4b271006f51163f6029784149c311
@@@ -29,7 -29,6 +29,7 @@@
  #ifndef _SMC911X_H_
  #define _SMC911X_H_
  
 +#include <linux/smc911x.h>
  /*
   * Use the DMA feature on PXA chips
   */
    #define SMC_USE_32BIT               1
    #define SMC_IRQ_SENSE               IRQF_TRIGGER_FALLING
  #elif defined(CONFIG_SH_MAGIC_PANEL_R2)
 -  #define SMC_USE_SH_DMA      0
    #define SMC_USE_16BIT               0
    #define SMC_USE_32BIT               1
    #define SMC_IRQ_SENSE               IRQF_TRIGGER_LOW
 +#else
 +/*
 + * Default configuration
 + */
 +
 +#define SMC_DYNAMIC_BUS_CONFIG
  #endif
  
-       int work_pending;
 +/* store this information for the driver.. */
 +struct smc911x_local {
 +      /*
 +       * If I have to wait until the DMA is finished and ready to reload a
 +       * packet, I will store the skbuff here. Then, the DMA will send it
 +       * out and free it.
 +       */
 +      struct sk_buff *pending_tx_skb;
 +
 +      /* version/revision of the SMC911x chip */
 +      u16 version;
 +      u16 revision;
 +
 +      /* FIFO sizes */
 +      int tx_fifo_kb;
 +      int tx_fifo_size;
 +      int rx_fifo_size;
 +      int afc_cfg;
 +
 +      /* Contains the current active receive/phy mode */
 +      int ctl_rfduplx;
 +      int ctl_rspeed;
 +
 +      u32 msg_enable;
 +      u32 phy_type;
 +      struct mii_if_info mii;
 +
 +      /* work queue */
 +      struct work_struct phy_configure;
 +
 +      int tx_throttle;
 +      spinlock_t lock;
 +
 +      struct net_device *netdev;
 +
 +#ifdef SMC_USE_DMA
 +      /* DMA needs the physical address of the chip */
 +      u_long physaddr;
 +      int rxdma;
 +      int txdma;
 +      int rxdma_active;
 +      int txdma_active;
 +      struct sk_buff *current_rx_skb;
 +      struct sk_buff *current_tx_skb;
 +      struct device *dev;
 +#endif
 +      void __iomem *base;
 +#ifdef SMC_DYNAMIC_BUS_CONFIG
 +      struct smc911x_platdata cfg;
 +#endif
 +};
  
  /*
   * Define the bus width specific IO macros
   */
  
 +#ifdef SMC_DYNAMIC_BUS_CONFIG
 +static inline unsigned int SMC_inl(struct smc911x_local *lp, int reg)
 +{
 +      void __iomem *ioaddr = lp->base + reg;
 +
 +      if (lp->cfg.flags & SMC911X_USE_32BIT)
 +              return readl(ioaddr);
 +
 +      if (lp->cfg.flags & SMC911X_USE_16BIT)
 +              return readw(ioaddr) | (readw(ioaddr + 2) << 16);
 +
 +      BUG();
 +}
 +
 +static inline void SMC_outl(unsigned int value, struct smc911x_local *lp,
 +                          int reg)
 +{
 +      void __iomem *ioaddr = lp->base + reg;
 +
 +      if (lp->cfg.flags & SMC911X_USE_32BIT) {
 +              writel(value, ioaddr);
 +              return;
 +      }
 +
 +      if (lp->cfg.flags & SMC911X_USE_16BIT) {
 +              writew(value & 0xffff, ioaddr);
 +              writew(value >> 16, ioaddr + 2);
 +              return;
 +      }
 +
 +      BUG();
 +}
 +
 +static inline void SMC_insl(struct smc911x_local *lp, int reg,
 +                            void *addr, unsigned int count)
 +{
 +      void __iomem *ioaddr = lp->base + reg;
 +
 +      if (lp->cfg.flags & SMC911X_USE_32BIT) {
 +              readsl(ioaddr, addr, count);
 +              return;
 +      }
 +
 +      if (lp->cfg.flags & SMC911X_USE_16BIT) {
 +              readsw(ioaddr, addr, count * 2);
 +              return;
 +      }
 +
 +      BUG();
 +}
 +
 +static inline void SMC_outsl(struct smc911x_local *lp, int reg,
 +                           void *addr, unsigned int count)
 +{
 +      void __iomem *ioaddr = lp->base + reg;
 +
 +      if (lp->cfg.flags & SMC911X_USE_32BIT) {
 +              writesl(ioaddr, addr, count);
 +              return;
 +      }
 +
 +      if (lp->cfg.flags & SMC911X_USE_16BIT) {
 +              writesw(ioaddr, addr, count * 2);
 +              return;
 +      }
 +
 +      BUG();
 +}
 +#else
  #if   SMC_USE_16BIT
 -#define SMC_inb(a, r)                  readb((a) + (r))
 -#define SMC_inw(a, r)                  readw((a) + (r))
 -#define SMC_inl(a, r)                  ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
 -#define SMC_outb(v, a, r)              writeb(v, (a) + (r))
 -#define SMC_outw(v, a, r)              writew(v, (a) + (r))
 -#define SMC_outl(v, a, r)                      \
 +#define SMC_inl(lp, r)                 ((readw((lp)->base + (r)) & 0xFFFF) + (readw((lp)->base + (r) + 2) << 16))
 +#define SMC_outl(v, lp, r)                     \
        do{                                      \
 -               writel(v & 0xFFFF, (a) + (r));  \
 -               writel(v >> 16, (a) + (r) + 2); \
 +               writew(v & 0xFFFF, (lp)->base + (r));   \
 +               writew(v >> 16, (lp)->base + (r) + 2); \
         } while (0)
 -#define SMC_insl(a, r, p, l)   readsw((short*)((a) + (r)), p, l*2)
 -#define SMC_outsl(a, r, p, l)  writesw((short*)((a) + (r)), p, l*2)
 +#define SMC_insl(lp, r, p, l)  readsw((short*)((lp)->base + (r)), p, l*2)
 +#define SMC_outsl(lp, r, p, l)         writesw((short*)((lp)->base + (r)), p, l*2)
  
  #elif SMC_USE_32BIT
 -#define SMC_inb(a, r)          readb((a) + (r))
 -#define SMC_inw(a, r)          readw((a) + (r))
 -#define SMC_inl(a, r)          readl((a) + (r))
 -#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
 -#define SMC_outl(v, a, r)      writel(v, (a) + (r))
 -#define SMC_insl(a, r, p, l)   readsl((int*)((a) + (r)), p, l)
 -#define SMC_outsl(a, r, p, l)  writesl((int*)((a) + (r)), p, l)
 +#define SMC_inl(lp, r)                 readl((lp)->base + (r))
 +#define SMC_outl(v, lp, r)     writel(v, (lp)->base + (r))
 +#define SMC_insl(lp, r, p, l)  readsl((int*)((lp)->base + (r)), p, l)
 +#define SMC_outsl(lp, r, p, l)         writesl((int*)((lp)->base + (r)), p, l)
  
  #endif /* SMC_USE_16BIT */
 -
 +#endif /* SMC_DYNAMIC_BUS_CONFIG */
  
  
  #ifdef SMC_USE_PXA_DMA
@@@ -230,22 -110,22 +229,22 @@@ static int rx_dmalen, tx_dmalen
  
  #ifdef SMC_insl
  #undef SMC_insl
 -#define SMC_insl(a, r, p, l) \
 -      smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
 +#define SMC_insl(lp, r, p, l) \
 +      smc_pxa_dma_insl(lp, lp->physaddr, r, lp->rxdma, p, l)
  
  static inline void
 -smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr,
 +smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
                int reg, int dma, u_char *buf, int len)
  {
        /* 64 bit alignment is required for memory to memory DMA */
        if ((long)buf & 4) {
 -              *((u32 *)buf) = SMC_inl(ioaddr, reg);
 +              *((u32 *)buf) = SMC_inl(lp, reg);
                buf += 4;
                len--;
        }
  
        len *= 4;
 -      rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
 +      rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE);
        rx_dmalen = len;
        DCSR(dma) = DCSR_NODESC;
        DTADR(dma) = rx_dmabuf;
  }
  #endif
  
 -#ifdef SMC_insw
 -#undef SMC_insw
 -#define SMC_insw(a, r, p, l) \
 -      smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
 -
 -static inline void
 -smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr,
 -              int reg, int dma, u_char *buf, int len)
 -{
 -      /* 64 bit alignment is required for memory to memory DMA */
 -      while ((long)buf & 6) {
 -              *((u16 *)buf) = SMC_inw(ioaddr, reg);
 -              buf += 2;
 -              len--;
 -      }
 -
 -      len *= 2;
 -      rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
 -      rx_dmalen = len;
 -      DCSR(dma) = DCSR_NODESC;
 -      DTADR(dma) = rx_dmabuf;
 -      DSADR(dma) = physaddr + reg;
 -      DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
 -              DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
 -      DCSR(dma) = DCSR_NODESC | DCSR_RUN;
 -}
 -#endif
 -
  #ifdef SMC_outsl
  #undef SMC_outsl
 -#define SMC_outsl(a, r, p, l) \
 -       smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
 +#define SMC_outsl(lp, r, p, l) \
 +       smc_pxa_dma_outsl(lp, lp->physaddr, r, lp->txdma, p, l)
  
  static inline void
 -smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr,
 +smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
                int reg, int dma, u_char *buf, int len)
  {
        /* 64 bit alignment is required for memory to memory DMA */
        if ((long)buf & 4) {
 -              SMC_outl(*((u32 *)buf), ioaddr, reg);
 +              SMC_outl(*((u32 *)buf), lp, reg);
                buf += 4;
                len--;
        }
  
        len *= 4;
 -      tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
 +      tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE);
        tx_dmalen = len;
        DCSR(dma) = DCSR_NODESC;
        DSADR(dma) = tx_dmabuf;
        DCSR(dma) = DCSR_NODESC | DCSR_RUN;
  }
  #endif
 -
 -#ifdef SMC_outsw
 -#undef SMC_outsw
 -#define SMC_outsw(a, r, p, l) \
 -      smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
 -
 -static inline void
 -smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr,
 -                int reg, int dma, u_char *buf, int len)
 -{
 -      /* 64 bit alignment is required for memory to memory DMA */
 -      while ((long)buf & 6) {
 -              SMC_outw(*((u16 *)buf), ioaddr, reg);
 -              buf += 2;
 -              len--;
 -      }
 -
 -      len *= 2;
 -      tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
 -      tx_dmalen = len;
 -      DCSR(dma) = DCSR_NODESC;
 -      DSADR(dma) = tx_dmabuf;
 -      DTADR(dma) = physaddr + reg;
 -      DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
 -              DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
 -      DCSR(dma) = DCSR_NODESC | DCSR_RUN;
 -}
 -#endif
 -
  #endif         /* SMC_USE_PXA_DMA */
  
  
@@@ -692,213 -629,213 +691,213 @@@ static const struct chip_id chip_ids[] 
   * capabilities.  Please use those and not the in/out primitives.
   */
  /* FIFO read/write macros */
 -#define SMC_PUSH_DATA(p, l)   SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 )
 -#define SMC_PULL_DATA(p, l)   SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 )
 -#define SMC_SET_TX_FIFO(x)    SMC_outl( x, ioaddr, TX_DATA_FIFO )
 -#define SMC_GET_RX_FIFO()     SMC_inl( ioaddr, RX_DATA_FIFO )
 +#define SMC_PUSH_DATA(lp, p, l)       SMC_outsl( lp, TX_DATA_FIFO, p, (l) >> 2 )
 +#define SMC_PULL_DATA(lp, p, l)       SMC_insl ( lp, RX_DATA_FIFO, p, (l) >> 2 )
 +#define SMC_SET_TX_FIFO(lp, x)        SMC_outl( x, lp, TX_DATA_FIFO )
 +#define SMC_GET_RX_FIFO(lp)   SMC_inl( lp, RX_DATA_FIFO )
  
  
  /* I/O mapped register read/write macros */
 -#define SMC_GET_TX_STS_FIFO()         SMC_inl( ioaddr, TX_STATUS_FIFO )
 -#define SMC_GET_RX_STS_FIFO()         SMC_inl( ioaddr, RX_STATUS_FIFO )
 -#define SMC_GET_RX_STS_FIFO_PEEK()    SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK )
 -#define SMC_GET_PN()                  (SMC_inl( ioaddr, ID_REV ) >> 16)
 -#define SMC_GET_REV()                 (SMC_inl( ioaddr, ID_REV ) & 0xFFFF)
 -#define SMC_GET_IRQ_CFG()             SMC_inl( ioaddr, INT_CFG )
 -#define SMC_SET_IRQ_CFG(x)            SMC_outl( x, ioaddr, INT_CFG )
 -#define SMC_GET_INT()                 SMC_inl( ioaddr, INT_STS )
 -#define SMC_ACK_INT(x)                        SMC_outl( x, ioaddr, INT_STS )
 -#define SMC_GET_INT_EN()              SMC_inl( ioaddr, INT_EN )
 -#define SMC_SET_INT_EN(x)             SMC_outl( x, ioaddr, INT_EN )
 -#define SMC_GET_BYTE_TEST()           SMC_inl( ioaddr, BYTE_TEST )
 -#define SMC_SET_BYTE_TEST(x)          SMC_outl( x, ioaddr, BYTE_TEST )
 -#define SMC_GET_FIFO_INT()            SMC_inl( ioaddr, FIFO_INT )
 -#define SMC_SET_FIFO_INT(x)           SMC_outl( x, ioaddr, FIFO_INT )
 -#define SMC_SET_FIFO_TDA(x)                                   \
 +#define SMC_GET_TX_STS_FIFO(lp)               SMC_inl( lp, TX_STATUS_FIFO )
 +#define SMC_GET_RX_STS_FIFO(lp)               SMC_inl( lp, RX_STATUS_FIFO )
 +#define SMC_GET_RX_STS_FIFO_PEEK(lp)  SMC_inl( lp, RX_STATUS_FIFO_PEEK )
 +#define SMC_GET_PN(lp)                        (SMC_inl( lp, ID_REV ) >> 16)
 +#define SMC_GET_REV(lp)                       (SMC_inl( lp, ID_REV ) & 0xFFFF)
 +#define SMC_GET_IRQ_CFG(lp)           SMC_inl( lp, INT_CFG )
 +#define SMC_SET_IRQ_CFG(lp, x)                SMC_outl( x, lp, INT_CFG )
 +#define SMC_GET_INT(lp)                       SMC_inl( lp, INT_STS )
 +#define SMC_ACK_INT(lp, x)                    SMC_outl( x, lp, INT_STS )
 +#define SMC_GET_INT_EN(lp)            SMC_inl( lp, INT_EN )
 +#define SMC_SET_INT_EN(lp, x)         SMC_outl( x, lp, INT_EN )
 +#define SMC_GET_BYTE_TEST(lp)         SMC_inl( lp, BYTE_TEST )
 +#define SMC_SET_BYTE_TEST(lp, x)              SMC_outl( x, lp, BYTE_TEST )
 +#define SMC_GET_FIFO_INT(lp)          SMC_inl( lp, FIFO_INT )
 +#define SMC_SET_FIFO_INT(lp, x)               SMC_outl( x, lp, FIFO_INT )
 +#define SMC_SET_FIFO_TDA(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
 -              __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24);      \
 -              SMC_SET_FIFO_INT( __mask | (x)<<24 );           \
 +              __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<24);  \
 +              SMC_SET_FIFO_INT( (lp), __mask | (x)<<24 );     \
                local_irq_restore(__flags);                     \
        } while (0)
 -#define SMC_SET_FIFO_TSL(x)                                   \
 +#define SMC_SET_FIFO_TSL(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
 -              __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16);      \
 -              SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \
 +              __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<16);  \
 +              SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<16));   \
                local_irq_restore(__flags);                     \
        } while (0)
 -#define SMC_SET_FIFO_RSA(x)                                   \
 +#define SMC_SET_FIFO_RSA(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
 -              __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8);       \
 -              SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8));  \
 +              __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<8);   \
 +              SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<8));    \
                local_irq_restore(__flags);                     \
        } while (0)
 -#define SMC_SET_FIFO_RSL(x)                                   \
 +#define SMC_SET_FIFO_RSL(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
 -              __mask = SMC_GET_FIFO_INT() & ~0xFF;            \
 -              SMC_SET_FIFO_INT( __mask | ((x) & 0xFF));       \
 +              __mask = SMC_GET_FIFO_INT((lp)) & ~0xFF;        \
 +              SMC_SET_FIFO_INT( (lp),__mask | ((x) & 0xFF));  \
                local_irq_restore(__flags);                     \
        } while (0)
 -#define SMC_GET_RX_CFG()              SMC_inl( ioaddr, RX_CFG )
 -#define SMC_SET_RX_CFG(x)             SMC_outl( x, ioaddr, RX_CFG )
 -#define SMC_GET_TX_CFG()              SMC_inl( ioaddr, TX_CFG )
 -#define SMC_SET_TX_CFG(x)             SMC_outl( x, ioaddr, TX_CFG )
 -#define SMC_GET_HW_CFG()              SMC_inl( ioaddr, HW_CFG )
 -#define SMC_SET_HW_CFG(x)             SMC_outl( x, ioaddr, HW_CFG )
 -#define SMC_GET_RX_DP_CTRL()          SMC_inl( ioaddr, RX_DP_CTRL )
 -#define SMC_SET_RX_DP_CTRL(x)         SMC_outl( x, ioaddr, RX_DP_CTRL )
 -#define SMC_GET_PMT_CTRL()            SMC_inl( ioaddr, PMT_CTRL )
 -#define SMC_SET_PMT_CTRL(x)           SMC_outl( x, ioaddr, PMT_CTRL )
 -#define SMC_GET_GPIO_CFG()            SMC_inl( ioaddr, GPIO_CFG )
 -#define SMC_SET_GPIO_CFG(x)           SMC_outl( x, ioaddr, GPIO_CFG )
 -#define SMC_GET_RX_FIFO_INF()         SMC_inl( ioaddr, RX_FIFO_INF )
 -#define SMC_SET_RX_FIFO_INF(x)                SMC_outl( x, ioaddr, RX_FIFO_INF )
 -#define SMC_GET_TX_FIFO_INF()         SMC_inl( ioaddr, TX_FIFO_INF )
 -#define SMC_SET_TX_FIFO_INF(x)                SMC_outl( x, ioaddr, TX_FIFO_INF )
 -#define SMC_GET_GPT_CFG()             SMC_inl( ioaddr, GPT_CFG )
 -#define SMC_SET_GPT_CFG(x)            SMC_outl( x, ioaddr, GPT_CFG )
 -#define SMC_GET_RX_DROP()             SMC_inl( ioaddr, RX_DROP )
 -#define SMC_SET_RX_DROP(x)            SMC_outl( x, ioaddr, RX_DROP )
 -#define SMC_GET_MAC_CMD()             SMC_inl( ioaddr, MAC_CSR_CMD )
 -#define SMC_SET_MAC_CMD(x)            SMC_outl( x, ioaddr, MAC_CSR_CMD )
 -#define SMC_GET_MAC_DATA()            SMC_inl( ioaddr, MAC_CSR_DATA )
 -#define SMC_SET_MAC_DATA(x)           SMC_outl( x, ioaddr, MAC_CSR_DATA )
 -#define SMC_GET_AFC_CFG()             SMC_inl( ioaddr, AFC_CFG )
 -#define SMC_SET_AFC_CFG(x)            SMC_outl( x, ioaddr, AFC_CFG )
 -#define SMC_GET_E2P_CMD()             SMC_inl( ioaddr, E2P_CMD )
 -#define SMC_SET_E2P_CMD(x)            SMC_outl( x, ioaddr, E2P_CMD )
 -#define SMC_GET_E2P_DATA()            SMC_inl( ioaddr, E2P_DATA )
 -#define SMC_SET_E2P_DATA(x)           SMC_outl( x, ioaddr, E2P_DATA )
 +#define SMC_GET_RX_CFG(lp)            SMC_inl( lp, RX_CFG )
 +#define SMC_SET_RX_CFG(lp, x)         SMC_outl( x, lp, RX_CFG )
 +#define SMC_GET_TX_CFG(lp)            SMC_inl( lp, TX_CFG )
 +#define SMC_SET_TX_CFG(lp, x)         SMC_outl( x, lp, TX_CFG )
 +#define SMC_GET_HW_CFG(lp)            SMC_inl( lp, HW_CFG )
 +#define SMC_SET_HW_CFG(lp, x)         SMC_outl( x, lp, HW_CFG )
 +#define SMC_GET_RX_DP_CTRL(lp)                SMC_inl( lp, RX_DP_CTRL )
 +#define SMC_SET_RX_DP_CTRL(lp, x)             SMC_outl( x, lp, RX_DP_CTRL )
 +#define SMC_GET_PMT_CTRL(lp)          SMC_inl( lp, PMT_CTRL )
 +#define SMC_SET_PMT_CTRL(lp, x)               SMC_outl( x, lp, PMT_CTRL )
 +#define SMC_GET_GPIO_CFG(lp)          SMC_inl( lp, GPIO_CFG )
 +#define SMC_SET_GPIO_CFG(lp, x)               SMC_outl( x, lp, GPIO_CFG )
 +#define SMC_GET_RX_FIFO_INF(lp)               SMC_inl( lp, RX_FIFO_INF )
 +#define SMC_SET_RX_FIFO_INF(lp, x)            SMC_outl( x, lp, RX_FIFO_INF )
 +#define SMC_GET_TX_FIFO_INF(lp)               SMC_inl( lp, TX_FIFO_INF )
 +#define SMC_SET_TX_FIFO_INF(lp, x)            SMC_outl( x, lp, TX_FIFO_INF )
 +#define SMC_GET_GPT_CFG(lp)           SMC_inl( lp, GPT_CFG )
 +#define SMC_SET_GPT_CFG(lp, x)                SMC_outl( x, lp, GPT_CFG )
 +#define SMC_GET_RX_DROP(lp)           SMC_inl( lp, RX_DROP )
 +#define SMC_SET_RX_DROP(lp, x)                SMC_outl( x, lp, RX_DROP )
 +#define SMC_GET_MAC_CMD(lp)           SMC_inl( lp, MAC_CSR_CMD )
 +#define SMC_SET_MAC_CMD(lp, x)                SMC_outl( x, lp, MAC_CSR_CMD )
 +#define SMC_GET_MAC_DATA(lp)          SMC_inl( lp, MAC_CSR_DATA )
 +#define SMC_SET_MAC_DATA(lp, x)               SMC_outl( x, lp, MAC_CSR_DATA )
 +#define SMC_GET_AFC_CFG(lp)           SMC_inl( lp, AFC_CFG )
 +#define SMC_SET_AFC_CFG(lp, x)                SMC_outl( x, lp, AFC_CFG )
 +#define SMC_GET_E2P_CMD(lp)           SMC_inl( lp, E2P_CMD )
 +#define SMC_SET_E2P_CMD(lp, x)                SMC_outl( x, lp, E2P_CMD )
 +#define SMC_GET_E2P_DATA(lp)          SMC_inl( lp, E2P_DATA )
 +#define SMC_SET_E2P_DATA(lp, x)               SMC_outl( x, lp, E2P_DATA )
  
  /* MAC register read/write macros */
 -#define SMC_GET_MAC_CSR(a,v)                                          \
 +#define SMC_GET_MAC_CSR(lp,a,v)                                               \
        do {                                                            \
 -              while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 -              SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ |                 \
 +              while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
 +              SMC_SET_MAC_CMD((lp),MAC_CSR_CMD_CSR_BUSY_ |            \
                        MAC_CSR_CMD_R_NOT_W_ | (a) );                   \
 -              while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 -              v = SMC_GET_MAC_DATA();                                 \
 +              while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
 +              v = SMC_GET_MAC_DATA((lp));                             \
        } while (0)
 -#define SMC_SET_MAC_CSR(a,v)                                          \
 +#define SMC_SET_MAC_CSR(lp,a,v)                                               \
        do {                                                            \
 -              while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 -              SMC_SET_MAC_DATA(v);                                    \
 -              SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) );          \
 -              while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 +              while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
 +              SMC_SET_MAC_DATA((lp), v);                              \
 +              SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_CSR_BUSY_ | (a) );    \
 +              while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
        } while (0)
 -#define SMC_GET_MAC_CR(x)     SMC_GET_MAC_CSR( MAC_CR, x )
 -#define SMC_SET_MAC_CR(x)     SMC_SET_MAC_CSR( MAC_CR, x )
 -#define SMC_GET_ADDRH(x)      SMC_GET_MAC_CSR( ADDRH, x )
 -#define SMC_SET_ADDRH(x)      SMC_SET_MAC_CSR( ADDRH, x )
 -#define SMC_GET_ADDRL(x)      SMC_GET_MAC_CSR( ADDRL, x )
 -#define SMC_SET_ADDRL(x)      SMC_SET_MAC_CSR( ADDRL, x )
 -#define SMC_GET_HASHH(x)      SMC_GET_MAC_CSR( HASHH, x )
 -#define SMC_SET_HASHH(x)      SMC_SET_MAC_CSR( HASHH, x )
 -#define SMC_GET_HASHL(x)      SMC_GET_MAC_CSR( HASHL, x )
 -#define SMC_SET_HASHL(x)      SMC_SET_MAC_CSR( HASHL, x )
 -#define SMC_GET_MII_ACC(x)    SMC_GET_MAC_CSR( MII_ACC, x )
 -#define SMC_SET_MII_ACC(x)    SMC_SET_MAC_CSR( MII_ACC, x )
 -#define SMC_GET_MII_DATA(x)   SMC_GET_MAC_CSR( MII_DATA, x )
 -#define SMC_SET_MII_DATA(x)   SMC_SET_MAC_CSR( MII_DATA, x )
 -#define SMC_GET_FLOW(x)               SMC_GET_MAC_CSR( FLOW, x )
 -#define SMC_SET_FLOW(x)               SMC_SET_MAC_CSR( FLOW, x )
 -#define SMC_GET_VLAN1(x)      SMC_GET_MAC_CSR( VLAN1, x )
 -#define SMC_SET_VLAN1(x)      SMC_SET_MAC_CSR( VLAN1, x )
 -#define SMC_GET_VLAN2(x)      SMC_GET_MAC_CSR( VLAN2, x )
 -#define SMC_SET_VLAN2(x)      SMC_SET_MAC_CSR( VLAN2, x )
 -#define SMC_SET_WUFF(x)               SMC_SET_MAC_CSR( WUFF, x )
 -#define SMC_GET_WUCSR(x)      SMC_GET_MAC_CSR( WUCSR, x )
 -#define SMC_SET_WUCSR(x)      SMC_SET_MAC_CSR( WUCSR, x )
 +#define SMC_GET_MAC_CR(lp, x) SMC_GET_MAC_CSR( (lp), MAC_CR, x )
 +#define SMC_SET_MAC_CR(lp, x) SMC_SET_MAC_CSR( (lp), MAC_CR, x )
 +#define SMC_GET_ADDRH(lp, x)  SMC_GET_MAC_CSR( (lp), ADDRH, x )
 +#define SMC_SET_ADDRH(lp, x)  SMC_SET_MAC_CSR( (lp), ADDRH, x )
 +#define SMC_GET_ADDRL(lp, x)  SMC_GET_MAC_CSR( (lp), ADDRL, x )
 +#define SMC_SET_ADDRL(lp, x)  SMC_SET_MAC_CSR( (lp), ADDRL, x )
 +#define SMC_GET_HASHH(lp, x)  SMC_GET_MAC_CSR( (lp), HASHH, x )
 +#define SMC_SET_HASHH(lp, x)  SMC_SET_MAC_CSR( (lp), HASHH, x )
 +#define SMC_GET_HASHL(lp, x)  SMC_GET_MAC_CSR( (lp), HASHL, x )
 +#define SMC_SET_HASHL(lp, x)  SMC_SET_MAC_CSR( (lp), HASHL, x )
 +#define SMC_GET_MII_ACC(lp, x)        SMC_GET_MAC_CSR( (lp), MII_ACC, x )
 +#define SMC_SET_MII_ACC(lp, x)        SMC_SET_MAC_CSR( (lp), MII_ACC, x )
 +#define SMC_GET_MII_DATA(lp, x)       SMC_GET_MAC_CSR( (lp), MII_DATA, x )
 +#define SMC_SET_MII_DATA(lp, x)       SMC_SET_MAC_CSR( (lp), MII_DATA, x )
 +#define SMC_GET_FLOW(lp, x)           SMC_GET_MAC_CSR( (lp), FLOW, x )
 +#define SMC_SET_FLOW(lp, x)           SMC_SET_MAC_CSR( (lp), FLOW, x )
 +#define SMC_GET_VLAN1(lp, x)  SMC_GET_MAC_CSR( (lp), VLAN1, x )
 +#define SMC_SET_VLAN1(lp, x)  SMC_SET_MAC_CSR( (lp), VLAN1, x )
 +#define SMC_GET_VLAN2(lp, x)  SMC_GET_MAC_CSR( (lp), VLAN2, x )
 +#define SMC_SET_VLAN2(lp, x)  SMC_SET_MAC_CSR( (lp), VLAN2, x )
 +#define SMC_SET_WUFF(lp, x)           SMC_SET_MAC_CSR( (lp), WUFF, x )
 +#define SMC_GET_WUCSR(lp, x)  SMC_GET_MAC_CSR( (lp), WUCSR, x )
 +#define SMC_SET_WUCSR(lp, x)  SMC_SET_MAC_CSR( (lp), WUCSR, x )
  
  /* PHY register read/write macros */
 -#define SMC_GET_MII(a,phy,v)                                  \
 +#define SMC_GET_MII(lp,a,phy,v)                                       \
        do {                                                    \
                u32 __v;                                        \
                do {                                            \
 -                      SMC_GET_MII_ACC(__v);                   \
 +                      SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
 -              SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
 +              SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \
                        MII_ACC_MII_BUSY_);                     \
                do {                                            \
 -                      SMC_GET_MII_ACC(__v);                   \
 +                      SMC_GET_MII_ACC( (lp), __v);                    \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
 -              SMC_GET_MII_DATA(v);                            \
 +              SMC_GET_MII_DATA((lp), v);                              \
        } while (0)
 -#define SMC_SET_MII(a,phy,v)                                  \
 +#define SMC_SET_MII(lp,a,phy,v)                                       \
        do {                                                    \
                u32 __v;                                        \
                do {                                            \
 -                      SMC_GET_MII_ACC(__v);                   \
 +                      SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
 -              SMC_SET_MII_DATA(v);                            \
 -              SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
 +              SMC_SET_MII_DATA((lp), v);                              \
 +              SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \
                        MII_ACC_MII_BUSY_        |              \
                        MII_ACC_MII_WRITE_  );                  \
                do {                                            \
 -                      SMC_GET_MII_ACC(__v);                   \
 +                      SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
        } while (0)
 -#define SMC_GET_PHY_BMCR(phy,x)               SMC_GET_MII( MII_BMCR, phy, x )
 -#define SMC_SET_PHY_BMCR(phy,x)               SMC_SET_MII( MII_BMCR, phy, x )
 -#define SMC_GET_PHY_BMSR(phy,x)               SMC_GET_MII( MII_BMSR, phy, x )
 -#define SMC_GET_PHY_ID1(phy,x)                SMC_GET_MII( MII_PHYSID1, phy, x )
 -#define SMC_GET_PHY_ID2(phy,x)                SMC_GET_MII( MII_PHYSID2, phy, x )
 -#define SMC_GET_PHY_MII_ADV(phy,x)    SMC_GET_MII( MII_ADVERTISE, phy, x )
 -#define SMC_SET_PHY_MII_ADV(phy,x)    SMC_SET_MII( MII_ADVERTISE, phy, x )
 -#define SMC_GET_PHY_MII_LPA(phy,x)    SMC_GET_MII( MII_LPA, phy, x )
 -#define SMC_SET_PHY_MII_LPA(phy,x)    SMC_SET_MII( MII_LPA, phy, x )
 -#define SMC_GET_PHY_CTRL_STS(phy,x)   SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x )
 -#define SMC_SET_PHY_CTRL_STS(phy,x)   SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x )
 -#define SMC_GET_PHY_INT_SRC(phy,x)    SMC_GET_MII( PHY_INT_SRC, phy, x )
 -#define SMC_SET_PHY_INT_SRC(phy,x)    SMC_SET_MII( PHY_INT_SRC, phy, x )
 -#define SMC_GET_PHY_INT_MASK(phy,x)   SMC_GET_MII( PHY_INT_MASK, phy, x )
 -#define SMC_SET_PHY_INT_MASK(phy,x)   SMC_SET_MII( PHY_INT_MASK, phy, x )
 -#define SMC_GET_PHY_SPECIAL(phy,x)    SMC_GET_MII( PHY_SPECIAL, phy, x )
 +#define SMC_GET_PHY_BMCR(lp,phy,x)            SMC_GET_MII( (lp), MII_BMCR, phy, x )
 +#define SMC_SET_PHY_BMCR(lp,phy,x)            SMC_SET_MII( (lp), MII_BMCR, phy, x )
 +#define SMC_GET_PHY_BMSR(lp,phy,x)            SMC_GET_MII( (lp), MII_BMSR, phy, x )
 +#define SMC_GET_PHY_ID1(lp,phy,x)             SMC_GET_MII( (lp), MII_PHYSID1, phy, x )
 +#define SMC_GET_PHY_ID2(lp,phy,x)             SMC_GET_MII( (lp), MII_PHYSID2, phy, x )
 +#define SMC_GET_PHY_MII_ADV(lp,phy,x) SMC_GET_MII( (lp), MII_ADVERTISE, phy, x )
 +#define SMC_SET_PHY_MII_ADV(lp,phy,x) SMC_SET_MII( (lp), MII_ADVERTISE, phy, x )
 +#define SMC_GET_PHY_MII_LPA(lp,phy,x) SMC_GET_MII( (lp), MII_LPA, phy, x )
 +#define SMC_SET_PHY_MII_LPA(lp,phy,x) SMC_SET_MII( (lp), MII_LPA, phy, x )
 +#define SMC_GET_PHY_CTRL_STS(lp,phy,x)        SMC_GET_MII( (lp), PHY_MODE_CTRL_STS, phy, x )
 +#define SMC_SET_PHY_CTRL_STS(lp,phy,x)        SMC_SET_MII( (lp), PHY_MODE_CTRL_STS, phy, x )
 +#define SMC_GET_PHY_INT_SRC(lp,phy,x) SMC_GET_MII( (lp), PHY_INT_SRC, phy, x )
 +#define SMC_SET_PHY_INT_SRC(lp,phy,x) SMC_SET_MII( (lp), PHY_INT_SRC, phy, x )
 +#define SMC_GET_PHY_INT_MASK(lp,phy,x)        SMC_GET_MII( (lp), PHY_INT_MASK, phy, x )
 +#define SMC_SET_PHY_INT_MASK(lp,phy,x)        SMC_SET_MII( (lp), PHY_INT_MASK, phy, x )
 +#define SMC_GET_PHY_SPECIAL(lp,phy,x) SMC_GET_MII( (lp), PHY_SPECIAL, phy, x )
  
  
  
  /* Misc read/write macros */
  
  #ifndef SMC_GET_MAC_ADDR
 -#define SMC_GET_MAC_ADDR(addr)                                        \
 +#define SMC_GET_MAC_ADDR(lp, addr)                            \
        do {                                                    \
                unsigned int __v;                               \
                                                                \
 -              SMC_GET_MAC_CSR(ADDRL, __v);                    \
 +              SMC_GET_MAC_CSR((lp), ADDRL, __v);                      \
                addr[0] = __v; addr[1] = __v >> 8;              \
                addr[2] = __v >> 16; addr[3] = __v >> 24;       \
 -              SMC_GET_MAC_CSR(ADDRH, __v);                    \
 +              SMC_GET_MAC_CSR((lp), ADDRH, __v);                      \
                addr[4] = __v; addr[5] = __v >> 8;              \
        } while (0)
  #endif
  
 -#define SMC_SET_MAC_ADDR(addr)                                        \
 +#define SMC_SET_MAC_ADDR(lp, addr)                            \
        do {                                                    \
 -               SMC_SET_MAC_CSR(ADDRL,                         \
 +               SMC_SET_MAC_CSR((lp), ADDRL,                           \
                                 addr[0] |                      \
                                (addr[1] << 8) |                \
                                (addr[2] << 16) |               \
                                (addr[3] << 24));               \
 -               SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\
 +               SMC_SET_MAC_CSR((lp), ADDRH, addr[4]|(addr[5] << 8));\
        } while (0)
  
  
 -#define SMC_WRITE_EEPROM_CMD(cmd, addr)                                       \
 +#define SMC_WRITE_EEPROM_CMD(lp, cmd, addr)                           \
        do {                                                            \
 -              while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 -              SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a );             \
 -              while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
 +              while (SMC_GET_E2P_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
 +              SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_R_NOT_W_ | a );               \
 +              while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
        } while (0)
  
  #endif         /* _SMC911X_H_ */
diff --combined include/linux/pci_ids.h
index 1bbb346066ddb99272c92a587a881629be0c6e41,eafc9d6d2b35183dab63c8293ad8eba9b2c2111b..caa000596b259c92c1fc783f04542bf274c9084c
  #define PCI_DEVICE_ID_HP_CISSA                0x3220
  #define PCI_DEVICE_ID_HP_CISSC                0x3230
  #define PCI_DEVICE_ID_HP_CISSD                0x3238
+ #define PCI_DEVICE_ID_HP_CISSE                0x323a
  #define PCI_DEVICE_ID_HP_ZX2_IOC      0x4031
  
  #define PCI_VENDOR_ID_PCTECH          0x1042
  #define PCI_DEVICE_ID_TIGON3_5787M    0x1693
  #define PCI_DEVICE_ID_TIGON3_5782     0x1696
  #define PCI_DEVICE_ID_TIGON3_5784     0x1698
 +#define PCI_DEVICE_ID_TIGON3_5785     0x1699
  #define PCI_DEVICE_ID_TIGON3_5786     0x169a
  #define PCI_DEVICE_ID_TIGON3_5787     0x169b
  #define PCI_DEVICE_ID_TIGON3_5788     0x169c
diff --combined include/linux/tcp.h
index 9881295f38570b8c4b6a98d56f517b564a97dc7d,b31b6b74aa28bf4e4dd3aa45d976e34c0c5f968d..07e79bdb9cdfdb68ee665e0e2948b8923d246081
@@@ -239,11 -239,6 +239,6 @@@ static inline struct tcp_request_sock *
        return (struct tcp_request_sock *)req;
  }
  
- struct tcp_deferred_accept_info {
-       struct sock *listen_sk;
-       struct request_sock *request;
- };
  struct tcp_sock {
        /* inet_connection_sock has to be the first member of tcp_sock */
        struct inet_connection_sock     inet_conn;
        u32     rcv_ssthresh;   /* Current window clamp                 */
  
        u32     frto_highmark;  /* snd_nxt when RTO occurred */
 -      u8      reordering;     /* Packet reordering metric.            */
 +      u16     advmss;         /* Advertised MSS                       */
        u8      frto_counter;   /* Number of new acks after RTO */
        u8      nonagle;        /* Disable Nagle algorithm?             */
 -      u8      keepalive_probes; /* num of allowed keep alive probes   */
  
  /* RTT measurement */
        u32     srtt;           /* smoothed round trip time << 3        */
  
        u32     packets_out;    /* Packets which are "in flight"        */
        u32     retrans_out;    /* Retransmitted packets out            */
 +
 +      u16     urg_data;       /* Saved octet of OOB data and control flags */
 +      u8      urg_mode;       /* In urgent mode               */
 +      u8      ecn_flags;      /* ECN status bits.                     */
  /*
   *      Options received (usually on last packet, some only on SYN packets).
   */
        u32     snd_cwnd_used;
        u32     snd_cwnd_stamp;
  
 -      struct sk_buff_head     out_of_order_queue; /* Out of order segments go here */
 -
        u32     rcv_wnd;        /* Current receiver window              */
        u32     write_seq;      /* Tail(+1) of data held in tcp send buffer */
        u32     pushed_seq;     /* Last pushed seq, required to talk to windows */
 +      u32     lost_out;       /* Lost packets                 */
 +      u32     sacked_out;     /* SACK'd packets                       */
 +      u32     fackets_out;    /* FACK'd packets                       */
 +      u32     tso_deferred;
 +      u32     bytes_acked;    /* Appropriate Byte Counting - RFC3465 */
  
 -/*    SACKs data      */
 +      /* from STCP, retrans queue hinting */
 +      struct sk_buff* lost_skb_hint;
 +      struct sk_buff *scoreboard_skb_hint;
 +      struct sk_buff *retransmit_skb_hint;
 +      struct sk_buff *forward_skb_hint;
 +
 +      struct sk_buff_head     out_of_order_queue; /* Out of order segments go here */
 +
 +      /* SACKs data, these 2 need to be together (see tcp_build_and_update_options) */
        struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
        struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
  
                                         * sacked_out > 0)
                                         */
  
 -      /* from STCP, retrans queue hinting */
 -      struct sk_buff* lost_skb_hint;
 -
 -      struct sk_buff *scoreboard_skb_hint;
 -      struct sk_buff *retransmit_skb_hint;
 -      struct sk_buff *forward_skb_hint;
 -
        int     lost_cnt_hint;
        int     retransmit_cnt_hint;
  
        u32     lost_retrans_low;       /* Sent seq after any rxmit (lowest) */
  
 -      u16     advmss;         /* Advertised MSS                       */
 +      u8      reordering;     /* Packet reordering metric.            */
 +      u8      keepalive_probes; /* num of allowed keep alive probes   */
        u32     prior_ssthresh; /* ssthresh saved at recovery start     */
 -      u32     lost_out;       /* Lost packets                 */
 -      u32     sacked_out;     /* SACK'd packets                       */
 -      u32     fackets_out;    /* FACK'd packets                       */
        u32     high_seq;       /* snd_nxt at onset of congestion       */
  
        u32     retrans_stamp;  /* Timestamp of the last retransmit,
                                 * the first SYN. */
        u32     undo_marker;    /* tracking retrans started here. */
        int     undo_retrans;   /* number of undoable retransmissions. */
 +      u32     total_retrans;  /* Total retransmits for entire connection */
 +
        u32     urg_seq;        /* Seq of received urgent pointer */
 -      u16     urg_data;       /* Saved octet of OOB data and control flags */
 -      u8      urg_mode;       /* In urgent mode               */
 -      u8      ecn_flags;      /* ECN status bits.                     */
        u32     snd_up;         /* Urgent pointer               */
  
 -      u32     total_retrans;  /* Total retransmits for entire connection */
 -      u32     bytes_acked;    /* Appropriate Byte Counting - RFC3465 */
 -
        unsigned int            keepalive_time;   /* time before keep alive takes place */
        unsigned int            keepalive_intvl;  /* time interval between keep alive probes */
 -      int                     linger2;
  
-       struct tcp_deferred_accept_info defer_tcp_accept;
        unsigned long last_synq_overflow; 
  
 -      u32     tso_deferred;
 -
  /* Receiver side RTT estimation */
        struct {
                u32     rtt;
  /* TCP MD5 Signagure Option information */
        struct tcp_md5sig_info  *md5sig_info;
  #endif
 +
 +      int                     linger2;
  };
  
  static inline struct tcp_sock *tcp_sk(const struct sock *sk)
diff --combined include/net/tcp.h
index 07005ebb47a731c74656c826ac640412b8d870ba,cf54034019d9eafee928bf10b4180cea2c091ed0..b5a1b9eb12e8e98e0ed5605bf53da56a90336ed6
@@@ -139,7 -139,6 +139,6 @@@ extern void tcp_time_wait(struct sock *
  #define MAX_TCP_KEEPINTVL     32767
  #define MAX_TCP_KEEPCNT               127
  #define MAX_TCP_SYNCNT                127
- #define MAX_TCP_ACCEPT_DEFERRED 65535
  
  #define TCP_SYNQ_INTERVAL     (HZ/5)  /* Period of SYNACK timer */
  
@@@ -399,8 -398,6 +398,8 @@@ extern void                        tcp_parse_options(struct 
                                                  struct tcp_options_received *opt_rx,
                                                  int estab);
  
 +extern u8                     *tcp_parse_md5sig_option(struct tcphdr *th);
 +
  /*
   *    TCP v4 functions exported for the inet6 API
   */
@@@ -435,7 -432,6 +434,6 @@@ extern struct sk_buff *            tcp_make_synac
  
  extern int                    tcp_disconnect(struct sock *sk, int flags);
  
- extern void                   tcp_unhash(struct sock *sk);
  
  /* From syncookies.c */
  extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
@@@ -1117,19 -1113,13 +1115,19 @@@ struct tcp_md5sig_pool 
  #define TCP_MD5SIG_MAXKEYS    (~(u32)0)       /* really?! */
  
  /* - functions */
 +extern int                    tcp_calc_md5_hash(char *md5_hash,
 +                                                struct tcp_md5sig_key *key,
 +                                                int bplen,
 +                                                struct tcphdr *th,
 +                                                unsigned int tcplen,
 +                                                struct tcp_md5sig_pool *hp);
 +
  extern int                    tcp_v4_calc_md5_hash(char *md5_hash,
                                                     struct tcp_md5sig_key *key,
                                                     struct sock *sk,
                                                     struct dst_entry *dst,
                                                     struct request_sock *req,
                                                     struct tcphdr *th,
 -                                                   int protocol,
                                                     unsigned int tcplen);
  extern struct tcp_md5sig_key  *tcp_v4_md5_lookup(struct sock *sk,
                                                   struct sock *addr_sk);
@@@ -1142,16 -1132,6 +1140,16 @@@ extern int                    tcp_v4_md5_do_add(struct s
  extern int                    tcp_v4_md5_do_del(struct sock *sk,
                                                  __be32 addr);
  
 +#ifdef CONFIG_TCP_MD5SIG
 +#define tcp_twsk_md5_key(twsk)        ((twsk)->tw_md5_keylen ?                 \
 +                               &(struct tcp_md5sig_key) {              \
 +                                      .key = (twsk)->tw_md5_key,       \
 +                                      .keylen = (twsk)->tw_md5_keylen, \
 +                              } : NULL)
 +#else
 +#define tcp_twsk_md5_key(twsk)        NULL
 +#endif
 +
  extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void);
  extern void                   tcp_free_md5sig_pool(void);
  
@@@ -1389,6 -1369,7 +1387,6 @@@ struct tcp_sock_af_ops 
                                                  struct dst_entry *dst,
                                                  struct request_sock *req,
                                                  struct tcphdr *th,
 -                                                int protocol,
                                                  unsigned int len);
        int                     (*md5_add) (struct sock *sk,
                                            struct sock *addr_sk,
diff --combined net/ipv4/fib_semantics.c
index 9335eba683c3beb1090295e092917853fcaf0f28,0d4d72827e4be08c4829ecea846b2a15e0d83e42..ded2ae34eab15017821063de974a8792d4474d0b
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            IPv4 Forwarding Information Base: semantics.
   *
 - * Version:   $Id: fib_semantics.c,v 1.19 2002/01/12 07:54:56 davem Exp $
 - *
   * Authors:   Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
   *
   *            This program is free software; you can redistribute it and/or
@@@ -958,7 -960,10 +958,10 @@@ int fib_dump_info(struct sk_buff *skb, 
        rtm->rtm_dst_len = dst_len;
        rtm->rtm_src_len = 0;
        rtm->rtm_tos = tos;
-       rtm->rtm_table = tb_id;
+       if (tb_id < 256)
+               rtm->rtm_table = tb_id;
+       else
+               rtm->rtm_table = RT_TABLE_COMPAT;
        NLA_PUT_U32(skb, RTA_TABLE, tb_id);
        rtm->rtm_type = type;
        rtm->rtm_flags = fi->fib_flags;
diff --combined net/ipv4/syncookies.c
index 6317d3c8dc0d5b92038413747e67b23e9b6853be,d182a2a2629135a8a76df80ee40e9e6542dd871b..fdde2ae07e24f38f1873cbea11f4dfcbd84aa3d8
@@@ -8,6 -8,8 +8,6 @@@
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
 - *
 - *  $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $
   */
  
  #include <linux/tcp.h>
@@@ -283,7 -285,7 +283,7 @@@ struct sock *cookie_v4_check(struct soc
                cookie_check_timestamp(&tcp_opt);
  
        ret = NULL;
-       req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */
+       req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */
        if (!req)
                goto out;
  
        ireq->rmt_port          = th->source;
        ireq->loc_addr          = ip_hdr(skb)->daddr;
        ireq->rmt_addr          = ip_hdr(skb)->saddr;
-       ireq->opt               = NULL;
        ireq->snd_wscale        = tcp_opt.snd_wscale;
        ireq->rcv_wscale        = tcp_opt.rcv_wscale;
        ireq->sack_ok           = tcp_opt.sack_ok;
diff --combined net/ipv4/tcp.c
index 6d30ca559c64d1bb10dc81698fac93f1ad36caa5,fc54a48fde1e6a6b07a157b1cc551427d226099b..cf0850c068f5488856a642e9bc588c3b8900c536
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            Implementation of the Transmission Control Protocol(TCP).
   *
 - * Version:   $Id: tcp.c,v 1.216 2002/02/01 22:01:04 davem Exp $
 - *
   * Authors:   Ross Biro
   *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *            Mark Evans, <evansmp@uhura.aston.ac.uk>
@@@ -2110,12 -2112,15 +2110,15 @@@ static int do_tcp_setsockopt(struct soc
                break;
  
        case TCP_DEFER_ACCEPT:
-               if (val < 0) {
-                       err = -EINVAL;
-               } else {
-                       if (val > MAX_TCP_ACCEPT_DEFERRED)
-                               val = MAX_TCP_ACCEPT_DEFERRED;
-                       icsk->icsk_accept_queue.rskq_defer_accept = val;
+               icsk->icsk_accept_queue.rskq_defer_accept = 0;
+               if (val > 0) {
+                       /* Translate value in seconds to number of
+                        * retransmits */
+                       while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
+                              val > ((TCP_TIMEOUT_INIT / HZ) <<
+                                      icsk->icsk_accept_queue.rskq_defer_accept))
+                               icsk->icsk_accept_queue.rskq_defer_accept++;
+                       icsk->icsk_accept_queue.rskq_defer_accept++;
                }
                break;
  
@@@ -2297,7 -2302,8 +2300,8 @@@ static int do_tcp_getsockopt(struct soc
                        val = (val ? : sysctl_tcp_fin_timeout) / HZ;
                break;
        case TCP_DEFER_ACCEPT:
-               val = icsk->icsk_accept_queue.rskq_defer_accept;
+               val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
+                       ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
                break;
        case TCP_WINDOW_CLAMP:
                val = tp->window_clamp;
@@@ -2457,76 -2463,6 +2461,76 @@@ static unsigned long tcp_md5sig_users
  static struct tcp_md5sig_pool **tcp_md5sig_pool;
  static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);
  
 +int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
 +                    int bplen,
 +                    struct tcphdr *th, unsigned int tcplen,
 +                    struct tcp_md5sig_pool *hp)
 +{
 +      struct scatterlist sg[4];
 +      __u16 data_len;
 +      int block = 0;
 +      __sum16 cksum;
 +      struct hash_desc *desc = &hp->md5_desc;
 +      int err;
 +      unsigned int nbytes = 0;
 +
 +      sg_init_table(sg, 4);
 +
 +      /* 1. The TCP pseudo-header */
 +      sg_set_buf(&sg[block++], &hp->md5_blk, bplen);
 +      nbytes += bplen;
 +
 +      /* 2. The TCP header, excluding options, and assuming a
 +       * checksum of zero
 +       */
 +      cksum = th->check;
 +      th->check = 0;
 +      sg_set_buf(&sg[block++], th, sizeof(*th));
 +      nbytes += sizeof(*th);
 +
 +      /* 3. The TCP segment data (if any) */
 +      data_len = tcplen - (th->doff << 2);
 +      if (data_len > 0) {
 +              u8 *data = (u8 *)th + (th->doff << 2);
 +              sg_set_buf(&sg[block++], data, data_len);
 +              nbytes += data_len;
 +      }
 +
 +      /* 4. an independently-specified key or password, known to both
 +       * TCPs and presumably connection-specific
 +       */
 +      sg_set_buf(&sg[block++], key->key, key->keylen);
 +      nbytes += key->keylen;
 +
 +      sg_mark_end(&sg[block - 1]);
 +
 +      /* Now store the hash into the packet */
 +      err = crypto_hash_init(desc);
 +      if (err) {
 +              if (net_ratelimit())
 +                      printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
 +              return -1;
 +      }
 +      err = crypto_hash_update(desc, sg, nbytes);
 +      if (err) {
 +              if (net_ratelimit())
 +                      printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
 +              return -1;
 +      }
 +      err = crypto_hash_final(desc, md5_hash);
 +      if (err) {
 +              if (net_ratelimit())
 +                      printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
 +              return -1;
 +      }
 +
 +      /* Reset header */
 +      th->check = cksum;
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(tcp_calc_md5_hash);
 +
  static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
  {
        int cpu;
diff --combined net/ipv4/tcp_input.c
index bc7f62e2792b4039e6b6f033696a0263f5cb1a8f,cad73b7dfef07798ddc0b8debba24c9aad94c53b..de30e70ff256335b8cbc8ec531e1a8c3433a76e5
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            Implementation of the Transmission Control Protocol(TCP).
   *
 - * Version:   $Id: tcp_input.c,v 1.243 2002/02/01 22:01:04 davem Exp $
 - *
   * Authors:   Ross Biro
   *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *            Mark Evans, <evansmp@uhura.aston.ac.uk>
@@@ -3448,43 -3450,6 +3448,43 @@@ static int tcp_fast_parse_options(struc
        return 1;
  }
  
 +#ifdef CONFIG_TCP_MD5SIG
 +/*
 + * Parse MD5 Signature option
 + */
 +u8 *tcp_parse_md5sig_option(struct tcphdr *th)
 +{
 +      int length = (th->doff << 2) - sizeof (*th);
 +      u8 *ptr = (u8*)(th + 1);
 +
 +      /* If the TCP option is too short, we can short cut */
 +      if (length < TCPOLEN_MD5SIG)
 +              return NULL;
 +
 +      while (length > 0) {
 +              int opcode = *ptr++;
 +              int opsize;
 +
 +              switch(opcode) {
 +              case TCPOPT_EOL:
 +                      return NULL;
 +              case TCPOPT_NOP:
 +                      length--;
 +                      continue;
 +              default:
 +                      opsize = *ptr++;
 +                      if (opsize < 2 || opsize > length)
 +                              return NULL;
 +                      if (opcode == TCPOPT_MD5SIG)
 +                              return ptr;
 +              }
 +              ptr += opsize - 2;
 +              length -= opsize;
 +      }
 +      return NULL;
 +}
 +#endif
 +
  static inline void tcp_store_ts_recent(struct tcp_sock *tp)
  {
        tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
@@@ -4576,49 -4541,6 +4576,6 @@@ static void tcp_urg(struct sock *sk, st
        }
  }
  
- static int tcp_defer_accept_check(struct sock *sk)
- {
-       struct tcp_sock *tp = tcp_sk(sk);
-       if (tp->defer_tcp_accept.request) {
-               int queued_data =  tp->rcv_nxt - tp->copied_seq;
-               int hasfin =  !skb_queue_empty(&sk->sk_receive_queue) ?
-                       tcp_hdr((struct sk_buff *)
-                               sk->sk_receive_queue.prev)->fin : 0;
-               if (queued_data && hasfin)
-                       queued_data--;
-               if (queued_data &&
-                   tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) {
-                       if (sock_flag(sk, SOCK_KEEPOPEN)) {
-                               inet_csk_reset_keepalive_timer(sk,
-                                                              keepalive_time_when(tp));
-                       } else {
-                               inet_csk_delete_keepalive_timer(sk);
-                       }
-                       inet_csk_reqsk_queue_add(
-                               tp->defer_tcp_accept.listen_sk,
-                               tp->defer_tcp_accept.request,
-                               sk);
-                       tp->defer_tcp_accept.listen_sk->sk_data_ready(
-                               tp->defer_tcp_accept.listen_sk, 0);
-                       sock_put(tp->defer_tcp_accept.listen_sk);
-                       sock_put(sk);
-                       tp->defer_tcp_accept.listen_sk = NULL;
-                       tp->defer_tcp_accept.request = NULL;
-               } else if (hasfin ||
-                          tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) {
-                       tcp_reset(sk);
-                       return -1;
-               }
-       }
-       return 0;
- }
  static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
  {
        struct tcp_sock *tp = tcp_sk(sk);
@@@ -4979,8 -4901,6 +4936,6 @@@ step5
  
        tcp_data_snd_check(sk);
        tcp_ack_snd_check(sk);
-       tcp_defer_accept_check(sk);
        return 0;
  
  csum_error:
@@@ -5502,9 -5422,6 +5457,9 @@@ EXPORT_SYMBOL(sysctl_tcp_ecn)
  EXPORT_SYMBOL(sysctl_tcp_reordering);
  EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
  EXPORT_SYMBOL(tcp_parse_options);
 +#ifdef CONFIG_TCP_MD5SIG
 +EXPORT_SYMBOL(tcp_parse_md5sig_option);
 +#endif
  EXPORT_SYMBOL(tcp_rcv_established);
  EXPORT_SYMBOL(tcp_rcv_state_process);
  EXPORT_SYMBOL(tcp_initialize_rcv_mss);
diff --combined net/ipv4/tcp_ipv4.c
index 9088d709725ea94fe3d3128508e2568adab30677,97a230026e13af4243e458a5a915c90561b8ac28..b219a7a7cd08bef35cb06fd43f80a36401f643d6
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            Implementation of the Transmission Control Protocol(TCP).
   *
 - * Version:   $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $
 - *
   *            IPv4 specific functions
   *
   *
@@@ -93,13 -95,8 +93,13 @@@ static struct tcp_md5sig_key *tcp_v4_md
                                                   __be32 addr);
  static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
                                   __be32 saddr, __be32 daddr,
 -                                 struct tcphdr *th, int protocol,
 -                                 unsigned int tcplen);
 +                                 struct tcphdr *th, unsigned int tcplen);
 +#else
 +static inline
 +struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
 +{
 +      return NULL;
 +}
  #endif
  
  struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
@@@ -589,7 -586,8 +589,7 @@@ static void tcp_v4_send_reset(struct so
                                        key,
                                        ip_hdr(skb)->daddr,
                                        ip_hdr(skb)->saddr,
 -                                      &rep.th, IPPROTO_TCP,
 -                                      arg.iov[0].iov_len);
 +                                      &rep.th, arg.iov[0].iov_len);
        }
  #endif
        arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
     outside socket context is ugly, certainly. What can I do?
   */
  
 -static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
 -                          struct sk_buff *skb, u32 seq, u32 ack,
 -                          u32 win, u32 ts)
 +static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
 +                          u32 win, u32 ts, int oif,
 +                          struct tcp_md5sig_key *key)
  {
        struct tcphdr *th = tcp_hdr(skb);
        struct {
                        ];
        } rep;
        struct ip_reply_arg arg;
 -#ifdef CONFIG_TCP_MD5SIG
 -      struct tcp_md5sig_key *key;
 -      struct tcp_md5sig_key tw_key;
 -#endif
  
        memset(&rep.th, 0, sizeof(struct tcphdr));
        memset(&arg, 0, sizeof(arg));
        rep.th.window  = htons(win);
  
  #ifdef CONFIG_TCP_MD5SIG
 -      /*
 -       * The SKB holds an imcoming packet, but may not have a valid ->sk
 -       * pointer. This is especially the case when we're dealing with a
 -       * TIME_WAIT ack, because the sk structure is long gone, and only
 -       * the tcp_timewait_sock remains. So the md5 key is stashed in that
 -       * structure, and we use it in preference.  I believe that (twsk ||
 -       * skb->sk) holds true, but we program defensively.
 -       */
 -      if (!twsk && skb->sk) {
 -              key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
 -      } else if (twsk && twsk->tw_md5_keylen) {
 -              tw_key.key = twsk->tw_md5_key;
 -              tw_key.keylen = twsk->tw_md5_keylen;
 -              key = &tw_key;
 -      } else
 -              key = NULL;
 -
        if (key) {
                int offset = (ts) ? 3 : 0;
  
                                        key,
                                        ip_hdr(skb)->daddr,
                                        ip_hdr(skb)->saddr,
 -                                      &rep.th, IPPROTO_TCP,
 -                                      arg.iov[0].iov_len);
 +                                      &rep.th, arg.iov[0].iov_len);
        }
  #endif
        arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
                                      ip_hdr(skb)->saddr, /* XXX */
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 -      if (twsk)
 -              arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
 +      if (oif)
 +              arg.bound_dev_if = oif;
  
        ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
                      &arg, arg.iov[0].iov_len);
@@@ -682,12 -702,9 +682,12 @@@ static void tcp_v4_timewait_ack(struct 
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
  
 -      tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 +      tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 -                      tcptw->tw_ts_recent);
 +                      tcptw->tw_ts_recent,
 +                      tw->tw_bound_dev_if,
 +                      tcp_twsk_md5_key(tcptw)
 +                      );
  
        inet_twsk_put(tw);
  }
  static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
                                  struct request_sock *req)
  {
 -      tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
 +      tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1,
                        tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
 -                      req->ts_recent);
 +                      req->ts_recent,
 +                      0,
 +                      tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr));
  }
  
  /*
@@@ -991,12 -1006,18 +991,12 @@@ static int tcp_v4_parse_md5_keys(struc
  
  static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
                                   __be32 saddr, __be32 daddr,
 -                                 struct tcphdr *th, int protocol,
 +                                 struct tcphdr *th,
                                   unsigned int tcplen)
  {
 -      struct scatterlist sg[4];
 -      __u16 data_len;
 -      int block = 0;
 -      __sum16 old_checksum;
        struct tcp_md5sig_pool *hp;
        struct tcp4_pseudohdr *bp;
 -      struct hash_desc *desc;
        int err;
 -      unsigned int nbytes = 0;
  
        /*
         * Okay, so RFC2385 is turned on for this connection,
                goto clear_hash_noput;
  
        bp = &hp->md5_blk.ip4;
 -      desc = &hp->md5_desc;
  
        /*
 -       * 1. the TCP pseudo-header (in the order: source IP address,
 +       * The TCP pseudo-header (in the order: source IP address,
         * destination IP address, zero-padded protocol number, and
         * segment length)
         */
        bp->saddr = saddr;
        bp->daddr = daddr;
        bp->pad = 0;
 -      bp->protocol = protocol;
 +      bp->protocol = IPPROTO_TCP;
        bp->len = htons(tcplen);
  
 -      sg_init_table(sg, 4);
 -
 -      sg_set_buf(&sg[block++], bp, sizeof(*bp));
 -      nbytes += sizeof(*bp);
 -
 -      /* 2. the TCP header, excluding options, and assuming a
 -       * checksum of zero/
 -       */
 -      old_checksum = th->check;
 -      th->check = 0;
 -      sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
 -      nbytes += sizeof(struct tcphdr);
 -
 -      /* 3. the TCP segment data (if any) */
 -      data_len = tcplen - (th->doff << 2);
 -      if (data_len > 0) {
 -              unsigned char *data = (unsigned char *)th + (th->doff << 2);
 -              sg_set_buf(&sg[block++], data, data_len);
 -              nbytes += data_len;
 -      }
 -
 -      /* 4. an independently-specified key or password, known to both
 -       * TCPs and presumably connection-specific
 -       */
 -      sg_set_buf(&sg[block++], key->key, key->keylen);
 -      nbytes += key->keylen;
 -
 -      sg_mark_end(&sg[block - 1]);
 -
 -      /* Now store the Hash into the packet */
 -      err = crypto_hash_init(desc);
 -      if (err)
 -              goto clear_hash;
 -      err = crypto_hash_update(desc, sg, nbytes);
 -      if (err)
 -              goto clear_hash;
 -      err = crypto_hash_final(desc, md5_hash);
 +      err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
 +                              th, tcplen, hp);
        if (err)
                goto clear_hash;
  
 -      /* Reset header, and free up the crypto */
 +      /* Free up the crypto pool */
        tcp_put_md5sig_pool();
 -      th->check = old_checksum;
 -
  out:
        return 0;
  clear_hash:
@@@ -1040,7 -1099,7 +1040,7 @@@ int tcp_v4_calc_md5_hash(char *md5_hash
                         struct sock *sk,
                         struct dst_entry *dst,
                         struct request_sock *req,
 -                       struct tcphdr *th, int protocol,
 +                       struct tcphdr *th,
                         unsigned int tcplen)
  {
        __be32 saddr, daddr;
        }
        return tcp_v4_do_calc_md5_hash(md5_hash, key,
                                       saddr, daddr,
 -                                     th, protocol, tcplen);
 +                                     th, tcplen);
  }
  
  EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
@@@ -1075,12 -1134,52 +1075,12 @@@ static int tcp_v4_inbound_md5_hash(stru
        struct tcp_md5sig_key *hash_expected;
        const struct iphdr *iph = ip_hdr(skb);
        struct tcphdr *th = tcp_hdr(skb);
 -      int length = (th->doff << 2) - sizeof(struct tcphdr);
        int genhash;
 -      unsigned char *ptr;
        unsigned char newhash[16];
  
        hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
 +      hash_location = tcp_parse_md5sig_option(th);
  
 -      /*
 -       * If the TCP option length is less than the TCP_MD5SIG
 -       * option length, then we can shortcut
 -       */
 -      if (length < TCPOLEN_MD5SIG) {
 -              if (hash_expected)
 -                      return 1;
 -              else
 -                      return 0;
 -      }
 -
 -      /* Okay, we can't shortcut - we have to grub through the options */
 -      ptr = (unsigned char *)(th + 1);
 -      while (length > 0) {
 -              int opcode = *ptr++;
 -              int opsize;
 -
 -              switch (opcode) {
 -              case TCPOPT_EOL:
 -                      goto done_opts;
 -              case TCPOPT_NOP:
 -                      length--;
 -                      continue;
 -              default:
 -                      opsize = *ptr++;
 -                      if (opsize < 2)
 -                              goto done_opts;
 -                      if (opsize > length)
 -                              goto done_opts;
 -
 -                      if (opcode == TCPOPT_MD5SIG) {
 -                              hash_location = ptr;
 -                              goto done_opts;
 -                      }
 -              }
 -              ptr += opsize-2;
 -              length -= opsize;
 -      }
 -done_opts:
        /* We've parsed the options - do we have a hash? */
        if (!hash_expected && !hash_location)
                return 0;
        genhash = tcp_v4_do_calc_md5_hash(newhash,
                                          hash_expected,
                                          iph->saddr, iph->daddr,
 -                                        th, sk->sk_protocol,
 -                                        skb->len);
 +                                        th, skb->len);
  
        if (genhash || memcmp(hash_location, newhash, 16) != 0) {
                if (net_ratelimit()) {
@@@ -1185,7 -1285,7 +1185,7 @@@ int tcp_v4_conn_request(struct sock *sk
        if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
                goto drop;
  
-       req = reqsk_alloc(&tcp_request_sock_ops);
+       req = inet_reqsk_alloc(&tcp_request_sock_ops);
        if (!req)
                goto drop;
  
@@@ -1818,14 -1918,6 +1818,6 @@@ int tcp_v4_destroy_sock(struct sock *sk
                sk->sk_sndmsg_page = NULL;
        }
  
-       if (tp->defer_tcp_accept.request) {
-               reqsk_free(tp->defer_tcp_accept.request);
-               sock_put(tp->defer_tcp_accept.listen_sk);
-               sock_put(sk);
-               tp->defer_tcp_accept.listen_sk = NULL;
-               tp->defer_tcp_accept.request = NULL;
-       }
        atomic_dec(&tcp_sockets_allocated);
  
        return 0;
diff --combined net/ipv4/tcp_minisocks.c
index 1276cab85e3e50335e0c6f104227b17d322ec56e,8245247a6ceb732307569a9d4ab393e0de535c90..ea68a478fad62f699dbb85d9b5dcaa809415f496
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            Implementation of the Transmission Control Protocol(TCP).
   *
 - * Version:   $Id: tcp_minisocks.c,v 1.15 2002/02/01 22:01:04 davem Exp $
 - *
   * Authors:   Ross Biro
   *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *            Mark Evans, <evansmp@uhura.aston.ac.uk>
@@@ -569,8 -571,10 +569,10 @@@ struct sock *tcp_check_req(struct sock 
           does sequence test, SYN is truncated, and thus we consider
           it a bare ACK.
  
-          Both ends (listening sockets) accept the new incoming
-          connection and try to talk to each other. 8-)
+          If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
+          bare ACK.  Otherwise, we create an established connection.  Both
+          ends (listening sockets) accept the new incoming connection and try
+          to talk to each other. 8-)
  
           Note: This case is both harmless, and rare.  Possibility is about the
           same as us discovering intelligent life on another plant tomorrow.
                if (!(flg & TCP_FLAG_ACK))
                        return NULL;
  
+               /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
+               if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+                   TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+                       inet_rsk(req)->acked = 1;
+                       return NULL;
+               }
                /* OK, ACK is valid, create big socket and
                 * feed this segment to it. It will repeat all
                 * the tests. THIS SEGMENT MUST MOVE SOCKET TO
                inet_csk_reqsk_queue_unlink(sk, req, prev);
                inet_csk_reqsk_queue_removed(sk, req);
  
-               if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
-                   TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
-                       /* the accept queue handling is done is est recv slow
-                        * path so lets make sure to start there
-                        */
-                       tcp_sk(child)->pred_flags = 0;
-                       sock_hold(sk);
-                       sock_hold(child);
-                       tcp_sk(child)->defer_tcp_accept.listen_sk = sk;
-                       tcp_sk(child)->defer_tcp_accept.request = req;
-                       inet_csk_reset_keepalive_timer(child,
-                                                      inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ);
-               } else {
-                       inet_csk_reqsk_queue_add(sk, req, child);
-               }
+               inet_csk_reqsk_queue_add(sk, req, child);
                return child;
  
        listen_overflow:
diff --combined net/ipv4/tcp_timer.c
index e77e7ae0bf2c9c6be0651f1f0ac8fc95307bb567,63ed9d6830e7b80f77f3619168756742f6ef3bc9..3e358cbb1247c89fa9c81b3c560245bc21da16e6
@@@ -5,6 -5,8 +5,6 @@@
   *
   *            Implementation of the Transmission Control Protocol(TCP).
   *
 - * Version:   $Id: tcp_timer.c,v 1.88 2002/02/01 22:01:04 davem Exp $
 - *
   * Authors:   Ross Biro
   *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *            Mark Evans, <evansmp@uhura.aston.ac.uk>
@@@ -487,11 -489,6 +487,6 @@@ static void tcp_keepalive_timer (unsign
                goto death;
        }
  
-       if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) {
-               tcp_send_active_reset(sk, GFP_ATOMIC);
-               goto death;
-       }
        if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
                goto out;
  
diff --combined net/ipv6/datagram.c
index 8cdb6b65ee96bb499a7231c2f2972d2e16db4312,0f0f94a40335e7a24a68181f1791d164d49cd3e2..f7b535dec860ea2ee29dca14581610e443b6042b
@@@ -5,6 -5,8 +5,6 @@@
   *    Authors:
   *    Pedro Roque             <roque@di.fc.ul.pt>
   *
 - *    $Id: datagram.c,v 1.24 2002/02/01 22:01:04 davem Exp $
 - *
   *    This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
@@@ -703,6 -705,11 +703,11 @@@ int datagram_send_ctl(struct net *net
                        }
  
                        *hlimit = *(int *)CMSG_DATA(cmsg);
+                       if (*hlimit < -1 || *hlimit > 0xff) {
+                               err = -EINVAL;
+                               goto exit_f;
+                       }
                        break;
  
                case IPV6_TCLASS:
diff --combined net/ipv6/ip6mr.c
index 0b11b378d89a1b7fa710aeba2aaa7cebae061f5b,14796181e8b5fed428042d5e8e9816237c6f6724..90e763073dc5fdebf09b4fd538594118c8215ec7
@@@ -197,7 -197,7 +197,7 @@@ static int ip6mr_vif_seq_show(struct se
                const char *name = vif->dev ? vif->dev->name : "none";
  
                seq_printf(seq,
-                          "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X\n",
+                          "%2td %-10s %8ld %7ld  %8ld %7ld %05X\n",
                           vif - vif6_table,
                           name, vif->bytes_in, vif->pkt_in,
                           vif->bytes_out, vif->pkt_out,
@@@ -388,8 -388,8 +388,8 @@@ static int pim6_rcv(struct sk_buff *skb
        skb->ip_summed = 0;
        skb->pkt_type = PACKET_HOST;
        dst_release(skb->dst);
 -      ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len;
 -      ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++;
 +      reg_dev->stats.rx_bytes += skb->len;
 +      reg_dev->stats.rx_packets++;
        skb->dst = NULL;
        nf_reset(skb);
        netif_rx(skb);
@@@ -409,20 -409,26 +409,20 @@@ static struct inet6_protocol pim6_proto
  static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
  {
        read_lock(&mrt_lock);
 -      ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len;
 -      ((struct net_device_stats *)netdev_priv(dev))->tx_packets++;
 +      dev->stats.tx_bytes += skb->len;
 +      dev->stats.tx_packets++;
        ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT);
        read_unlock(&mrt_lock);
        kfree_skb(skb);
        return 0;
  }
  
 -static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
 -{
 -      return (struct net_device_stats *)netdev_priv(dev);
 -}
 -
  static void reg_vif_setup(struct net_device *dev)
  {
        dev->type               = ARPHRD_PIMREG;
        dev->mtu                = 1500 - sizeof(struct ipv6hdr) - 8;
        dev->flags              = IFF_NOARP;
        dev->hard_start_xmit    = reg_vif_xmit;
 -      dev->get_stats          = reg_vif_get_stats;
        dev->destructor         = free_netdev;
  }
  
@@@ -430,7 -436,9 +430,7 @@@ static struct net_device *ip6mr_reg_vif
  {
        struct net_device *dev;
  
 -      dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg",
 -                         reg_vif_setup);
 -
 +      dev = alloc_netdev(0, "pim6reg", reg_vif_setup);
        if (dev == NULL)
                return NULL;
  
@@@ -1240,7 -1248,7 +1240,7 @@@ int ip6_mroute_setsockopt(struct sock *
  
  #endif
        /*
 -       *      Spurious command, or MRT_VERSION which you cannot
 +       *      Spurious command, or MRT6_VERSION which you cannot
         *      set.
         */
        default:
@@@ -1369,8 -1377,8 +1369,8 @@@ static int ip6mr_forward2(struct sk_buf
        if (vif->flags & MIFF_REGISTER) {
                vif->pkt_out++;
                vif->bytes_out += skb->len;
 -              ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len;
 -              ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++;
 +              vif->dev->stats.tx_bytes += skb->len;
 +              vif->dev->stats.tx_packets++;
                ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT);
                kfree_skb(skb);
                return 0;
diff --combined net/ipv6/ipv6_sockglue.c
index 237ebbb9383ba28cfddff91a22535703a83da6e4,c042ce19bd141f04982820b0b7375f5c0e148fad..a9988841172af06fbd6ec6f4e754bbc51cda30f9
@@@ -7,6 -7,8 +7,6 @@@
   *
   *    Based on linux/net/ipv4/ip_sockglue.c
   *
 - *    $Id: ipv6_sockglue.c,v 1.41 2002/02/01 22:01:04 davem Exp $
 - *
   *    This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
@@@ -65,7 -67,7 +65,7 @@@ int ip6_ra_control(struct sock *sk, in
  
        /* RA packet may be delivered ONLY to IPPROTO_RAW socket */
        if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW)
-               return -EINVAL;
+               return -ENOPROTOOPT;
  
        new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
  
@@@ -444,7 -446,7 +444,7 @@@ done
  
        case IPV6_MULTICAST_HOPS:
                if (sk->sk_type == SOCK_STREAM)
-                       goto e_inval;
+                       break;
                if (optlen < sizeof(int))
                        goto e_inval;
                if (val > 255 || val < -1)
        case IPV6_MULTICAST_LOOP:
                if (optlen < sizeof(int))
                        goto e_inval;
+               if (val != valbool)
+                       goto e_inval;
                np->mc_loop = valbool;
                retv = 0;
                break;
  
        case IPV6_MULTICAST_IF:
                if (sk->sk_type == SOCK_STREAM)
-                       goto e_inval;
+                       break;
                if (optlen < sizeof(int))
                        goto e_inval;
  
@@@ -858,7 -862,7 +860,7 @@@ static int do_ipv6_getsockopt(struct so
                if (sk->sk_protocol != IPPROTO_UDP &&
                    sk->sk_protocol != IPPROTO_UDPLITE &&
                    sk->sk_protocol != IPPROTO_TCP)
-                       return -EINVAL;
+                       return -ENOPROTOOPT;
                if (sk->sk_state != TCP_ESTABLISHED)
                        return -ENOTCONN;
                val = sk->sk_family;
                        return -EINVAL;
                if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0)))
                        return -EFAULT;
+               if (gsf.gf_group.ss_family != AF_INET6)
+                       return -EADDRNOTAVAIL;
                lock_sock(sk);
                err = ip6_mc_msfget(sk, &gsf,
                        (struct group_filter __user *)optval, optlen);
diff --combined net/ipv6/raw.c
index e03c1898ab2e3cdc52ddd9ac5d12fa98b0c0a6b9,3aee12310d946e8bb882b929c89c991791ff1d85..70a57e45bf0ef8eddf2b03cac00df7b7b0b61f71
@@@ -7,6 -7,8 +7,6 @@@
   *
   *    Adapted from linux/net/ipv4/raw.c
   *
 - *    $Id: raw.c,v 1.51 2002/02/01 22:01:04 davem Exp $
 - *
   *    Fixes:
   *    Hideaki YOSHIFUJI       :       sin6_scope_id support
   *    YOSHIFUJI,H.@USAGI      :       raw checksum (RFC2292(bis) compliance)
@@@ -1167,7 -1169,8 +1167,8 @@@ static int raw6_destroy(struct sock *sk
        lock_sock(sk);
        ip6_flush_pending_frames(sk);
        release_sock(sk);
-       return 0;
+       return inet6_destroy_sock(sk);
  }
  
  static int rawv6_init_sk(struct sock *sk)
@@@ -1198,7 -1201,6 +1199,6 @@@ struct proto rawv6_prot = 
        .disconnect        = udp_disconnect,
        .ioctl             = rawv6_ioctl,
        .init              = rawv6_init_sk,
-       .destroy           = inet6_destroy_sock,
        .setsockopt        = rawv6_setsockopt,
        .getsockopt        = rawv6_getsockopt,
        .sendmsg           = rawv6_sendmsg,
diff --combined net/ipv6/route.c
index edae81319b515dc1280e98a97b727ce9d0459841,d1f3e19b06c79ade99a6b34eb385ee15753c6c77..efe036aa3dd1bbb02384d893b185768720c67695
@@@ -5,6 -5,8 +5,6 @@@
   *    Authors:
   *    Pedro Roque             <roque@di.fc.ul.pt>
   *
 - *    $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $
 - *
   *    This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
@@@ -2194,8 -2196,12 +2194,12 @@@ static int rt6_fill_node(struct sk_buf
  
        NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
  
-       expires = (rt->rt6i_flags & RTF_EXPIRES) ?
-                       rt->rt6i_expires - jiffies : 0;
+       if (!(rt->rt6i_flags & RTF_EXPIRES))
+               expires = 0;
+       else if (rt->rt6i_expires - jiffies < INT_MAX)
+               expires = rt->rt6i_expires - jiffies;
+       else
+               expires = INT_MAX;
  
        if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
                               expires, rt->u.dst.error) < 0)
diff --combined net/ipv6/tcp_ipv6.c
index 3fe736bead963f9c7168f20f9b7794420146fe7e,cb46749d4c326a3e7133537b70ed3cccce82eb9d..ebed5d3adb82069f080e71692edc039cd93959c6
@@@ -5,6 -5,8 +5,6 @@@
   *    Authors:
   *    Pedro Roque             <roque@di.fc.ul.pt>
   *
 - *    $Id: tcp_ipv6.c,v 1.144 2002/02/01 22:01:04 davem Exp $
 - *
   *    Based on:
   *    linux/net/ipv4/tcp.c
   *    linux/net/ipv4/tcp_input.c
@@@ -80,12 -82,6 +80,12 @@@ static struct inet_connection_sock_af_o
  #ifdef CONFIG_TCP_MD5SIG
  static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
  static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
 +#else
 +static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
 +                                                 struct in6_addr *addr)
 +{
 +      return NULL;
 +}
  #endif
  
  static void tcp_v6_hash(struct sock *sk)
@@@ -740,34 -736,78 +740,34 @@@ static int tcp_v6_parse_md5_keys (struc
  static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
                                   struct in6_addr *saddr,
                                   struct in6_addr *daddr,
 -                                 struct tcphdr *th, int protocol,
 -                                 unsigned int tcplen)
 +                                 struct tcphdr *th, unsigned int tcplen)
  {
 -      struct scatterlist sg[4];
 -      __u16 data_len;
 -      int block = 0;
 -      __sum16 cksum;
        struct tcp_md5sig_pool *hp;
        struct tcp6_pseudohdr *bp;
 -      struct hash_desc *desc;
        int err;
 -      unsigned int nbytes = 0;
  
        hp = tcp_get_md5sig_pool();
        if (!hp) {
                printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
                goto clear_hash_noput;
        }
 +
        bp = &hp->md5_blk.ip6;
 -      desc = &hp->md5_desc;
  
        /* 1. TCP pseudo-header (RFC2460) */
        ipv6_addr_copy(&bp->saddr, saddr);
        ipv6_addr_copy(&bp->daddr, daddr);
        bp->len = htonl(tcplen);
 -      bp->protocol = htonl(protocol);
 -
 -      sg_init_table(sg, 4);
 +      bp->protocol = htonl(IPPROTO_TCP);
  
 -      sg_set_buf(&sg[block++], bp, sizeof(*bp));
 -      nbytes += sizeof(*bp);
 +      err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
 +                              th, tcplen, hp);
  
 -      /* 2. TCP header, excluding options */
 -      cksum = th->check;
 -      th->check = 0;
 -      sg_set_buf(&sg[block++], th, sizeof(*th));
 -      nbytes += sizeof(*th);
 -
 -      /* 3. TCP segment data (if any) */
 -      data_len = tcplen - (th->doff << 2);
 -      if (data_len > 0) {
 -              u8 *data = (u8 *)th + (th->doff << 2);
 -              sg_set_buf(&sg[block++], data, data_len);
 -              nbytes += data_len;
 -      }
 -
 -      /* 4. shared key */
 -      sg_set_buf(&sg[block++], key->key, key->keylen);
 -      nbytes += key->keylen;
 -
 -      sg_mark_end(&sg[block - 1]);
 -
 -      /* Now store the hash into the packet */
 -      err = crypto_hash_init(desc);
 -      if (err) {
 -              printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
 -              goto clear_hash;
 -      }
 -      err = crypto_hash_update(desc, sg, nbytes);
 -      if (err) {
 -              printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
 -              goto clear_hash;
 -      }
 -      err = crypto_hash_final(desc, md5_hash);
 -      if (err) {
 -              printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
 +      if (err)
                goto clear_hash;
 -      }
  
 -      /* Reset header, and free up the crypto */
 +      /* Free up the crypto pool */
        tcp_put_md5sig_pool();
 -      th->check = cksum;
  out:
        return 0;
  clear_hash:
@@@ -781,7 -821,8 +781,7 @@@ static int tcp_v6_calc_md5_hash(char *m
                                struct sock *sk,
                                struct dst_entry *dst,
                                struct request_sock *req,
 -                              struct tcphdr *th, int protocol,
 -                              unsigned int tcplen)
 +                              struct tcphdr *th, unsigned int tcplen)
  {
        struct in6_addr *saddr, *daddr;
  
        }
        return tcp_v6_do_calc_md5_hash(md5_hash, key,
                                       saddr, daddr,
 -                                     th, protocol, tcplen);
 +                                     th, tcplen);
  }
  
  static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
        struct tcp_md5sig_key *hash_expected;
        struct ipv6hdr *ip6h = ipv6_hdr(skb);
        struct tcphdr *th = tcp_hdr(skb);
 -      int length = (th->doff << 2) - sizeof (*th);
        int genhash;
 -      u8 *ptr;
        u8 newhash[16];
  
        hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
 +      hash_location = tcp_parse_md5sig_option(th);
  
 -      /* If the TCP option is too short, we can short cut */
 -      if (length < TCPOLEN_MD5SIG)
 -              return hash_expected ? 1 : 0;
 -
 -      /* parse options */
 -      ptr = (u8*)(th + 1);
 -      while (length > 0) {
 -              int opcode = *ptr++;
 -              int opsize;
 -
 -              switch(opcode) {
 -              case TCPOPT_EOL:
 -                      goto done_opts;
 -              case TCPOPT_NOP:
 -                      length--;
 -                      continue;
 -              default:
 -                      opsize = *ptr++;
 -                      if (opsize < 2 || opsize > length)
 -                              goto done_opts;
 -                      if (opcode == TCPOPT_MD5SIG) {
 -                              hash_location = ptr;
 -                              goto done_opts;
 -                      }
 -              }
 -              ptr += opsize - 2;
 -              length -= opsize;
 -      }
 -
 -done_opts:
        /* do we have a hash as expected? */
        if (!hash_expected) {
                if (!hash_location)
        genhash = tcp_v6_do_calc_md5_hash(newhash,
                                          hash_expected,
                                          &ip6h->saddr, &ip6h->daddr,
 -                                        th, sk->sk_protocol,
 -                                        skb->len);
 +                                        th, skb->len);
        if (genhash || memcmp(hash_location, newhash, 16) != 0) {
                if (net_ratelimit()) {
                        printk(KERN_INFO "MD5 Hash %s for "
@@@ -978,7 -1051,7 +978,7 @@@ static void tcp_v6_send_reset(struct so
                tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key,
                                        &ipv6_hdr(skb)->daddr,
                                        &ipv6_hdr(skb)->saddr,
 -                                      t1, IPPROTO_TCP, tot_len);
 +                                      t1, tot_len);
        }
  #endif
  
        kfree_skb(buff);
  }
  
 -static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
 -                          struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
 +static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
 +                          struct tcp_md5sig_key *key)
  {
        struct tcphdr *th = tcp_hdr(skb), *t1;
        struct sk_buff *buff;
        struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        __be32 *topt;
 -#ifdef CONFIG_TCP_MD5SIG
 -      struct tcp_md5sig_key *key;
 -      struct tcp_md5sig_key tw_key;
 -#endif
 -
 -#ifdef CONFIG_TCP_MD5SIG
 -      if (!tw && skb->sk) {
 -              key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr);
 -      } else if (tw && tw->tw_md5_keylen) {
 -              tw_key.key = tw->tw_md5_key;
 -              tw_key.keylen = tw->tw_md5_keylen;
 -              key = &tw_key;
 -      } else {
 -              key = NULL;
 -      }
 -#endif
  
        if (ts)
                tot_len += TCPOLEN_TSTAMP_ALIGNED;
                tcp_v6_do_calc_md5_hash((__u8 *)topt, key,
                                        &ipv6_hdr(skb)->daddr,
                                        &ipv6_hdr(skb)->saddr,
 -                                      t1, IPPROTO_TCP, tot_len);
 +                                      t1, tot_len);
        }
  #endif
  
@@@ -1104,17 -1193,16 +1104,17 @@@ static void tcp_v6_timewait_ack(struct 
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
  
 -      tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 +      tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 -                      tcptw->tw_ts_recent);
 +                      tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw));
  
        inet_twsk_put(tw);
  }
  
  static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
  {
 -      tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
 +      tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
 +                      tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr));
  }
  
  
@@@ -1211,7 -1299,6 +1211,6 @@@ static int tcp_v6_conn_request(struct s
        treq = inet6_rsk(req);
        ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr);
        ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr);
-       treq->pktopts = NULL;
        if (!want_cookie)
                TCP_ECN_create_request(req, tcp_hdr(skb));
  
diff --combined net/key/af_key.c
index 841af9f2d5e0d5d341ac077d44d459a9a1946fcd,7470e367272b6059751eca446c7fc1f0d08edc13..f0fc46c8038d0632bca9fb3b031af5b908f1ff2d
@@@ -579,43 -579,25 +579,43 @@@ static uint8_t pfkey_proto_from_xfrm(ui
        return (proto ? proto : IPSEC_PROTO_ANY);
  }
  
 -static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr,
 -                                   xfrm_address_t *xaddr)
 +static inline int pfkey_sockaddr_len(sa_family_t family)
  {
 -      switch (((struct sockaddr*)(addr + 1))->sa_family) {
 +      switch (family) {
 +      case AF_INET:
 +              return sizeof(struct sockaddr_in);
 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +      case AF_INET6:
 +              return sizeof(struct sockaddr_in6);
 +#endif
 +      }
 +      return 0;
 +}
 +
 +static
 +int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr)
 +{
 +      switch (sa->sa_family) {
        case AF_INET:
                xaddr->a4 =
 -                      ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr;
 +                      ((struct sockaddr_in *)sa)->sin_addr.s_addr;
                return AF_INET;
  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
                memcpy(xaddr->a6,
 -                     &((struct sockaddr_in6 *)(addr + 1))->sin6_addr,
 +                     &((struct sockaddr_in6 *)sa)->sin6_addr,
                       sizeof(struct in6_addr));
                return AF_INET6;
  #endif
 -      default:
 -              return 0;
        }
 -      /* NOTREACHED */
 +      return 0;
 +}
 +
 +static
 +int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr)
 +{
 +      return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1),
 +                                    xaddr);
  }
  
  static struct  xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs)
  }
  
  #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
 +
  static int
  pfkey_sockaddr_size(sa_family_t family)
  {
 -      switch (family) {
 -      case AF_INET:
 -              return PFKEY_ALIGN8(sizeof(struct sockaddr_in));
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      case AF_INET6:
 -              return PFKEY_ALIGN8(sizeof(struct sockaddr_in6));
 -#endif
 -      default:
 -              return 0;
 -      }
 -      /* NOTREACHED */
 +      return PFKEY_ALIGN8(pfkey_sockaddr_len(family));
  }
  
  static inline int pfkey_mode_from_xfrm(int mode)
@@@ -696,36 -687,6 +696,36 @@@ static inline int pfkey_mode_to_xfrm(in
        }
  }
  
 +static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port,
 +                                     struct sockaddr *sa,
 +                                     unsigned short family)
 +{
 +      switch (family) {
 +      case AF_INET:
 +          {
 +              struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 +              sin->sin_family = AF_INET;
 +              sin->sin_port = port;
 +              sin->sin_addr.s_addr = xaddr->a4;
 +              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 +              return 32;
 +          }
 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +      case AF_INET6:
 +          {
 +              struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
 +              sin6->sin6_family = AF_INET6;
 +              sin6->sin6_port = port;
 +              sin6->sin6_flowinfo = 0;
 +              ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6);
 +              sin6->sin6_scope_id = 0;
 +              return 128;
 +          }
 +#endif
 +      }
 +      return 0;
 +}
 +
  static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
                                              int add_keys, int hsc)
  {
        struct sadb_address *addr;
        struct sadb_key *key;
        struct sadb_x_sa2 *sa2;
 -      struct sockaddr_in *sin;
        struct sadb_x_sec_ctx *sec_ctx;
        struct xfrm_sec_ctx *xfrm_ctx;
        int ctx_size = 0;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
        int size;
        int auth_key_size = 0;
        int encrypt_key_size = 0;
        }
  
        /* identity & sensitivity */
 -
 -      if ((x->props.family == AF_INET &&
 -           x->sel.saddr.a4 != x->props.saddr.a4)
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -          || (x->props.family == AF_INET6 &&
 -              memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr)))
 -#endif
 -              )
 +      if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, x->props.family))
                size += sizeof(struct sadb_address) + sockaddr_size;
  
        if (add_keys) {
           protocol's number." - RFC2367 */
        addr->sadb_address_proto = 0;
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              addr->sadb_address_prefixlen = 32;
  
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = x->props.saddr.a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 -
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr, x->props.saddr.a6,
 -                     sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(&x->props.saddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
                BUG();
  
        /* dst address */
                        sizeof(uint64_t);
        addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
        addr->sadb_address_proto = 0;
 -      addr->sadb_address_prefixlen = 32; /* XXX */
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = x->id.daddr.a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
  
 -              if (x->sel.saddr.a4 != x->props.saddr.a4) {
 -                      addr = (struct sadb_address*) skb_put(skb,
 -                              sizeof(struct sadb_address)+sockaddr_size);
 -                      addr->sadb_address_len =
 -                              (sizeof(struct sadb_address)+sockaddr_size)/
 -                              sizeof(uint64_t);
 -                      addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
 -                      addr->sadb_address_proto =
 -                              pfkey_proto_from_xfrm(x->sel.proto);
 -                      addr->sadb_address_prefixlen = x->sel.prefixlen_s;
 -                      addr->sadb_address_reserved = 0;
 -
 -                      sin = (struct sockaddr_in *) (addr + 1);
 -                      sin->sin_family = AF_INET;
 -                      sin->sin_addr.s_addr = x->sel.saddr.a4;
 -                      sin->sin_port = x->sel.sport;
 -                      memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -              }
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(&x->id.daddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
 +              BUG();
  
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr, x->id.daddr.a6, sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 +      if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr,
 +                        x->props.family)) {
 +              addr = (struct sadb_address*) skb_put(skb,
 +                      sizeof(struct sadb_address)+sockaddr_size);
 +              addr->sadb_address_len =
 +                      (sizeof(struct sadb_address)+sockaddr_size)/
 +                      sizeof(uint64_t);
 +              addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
 +              addr->sadb_address_proto =
 +                      pfkey_proto_from_xfrm(x->sel.proto);
 +              addr->sadb_address_prefixlen = x->sel.prefixlen_s;
 +              addr->sadb_address_reserved = 0;
  
 -              if (memcmp (x->sel.saddr.a6, x->props.saddr.a6,
 -                          sizeof(struct in6_addr))) {
 -                      addr = (struct sadb_address *) skb_put(skb,
 -                              sizeof(struct sadb_address)+sockaddr_size);
 -                      addr->sadb_address_len =
 -                              (sizeof(struct sadb_address)+sockaddr_size)/
 -                              sizeof(uint64_t);
 -                      addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
 -                      addr->sadb_address_proto =
 -                              pfkey_proto_from_xfrm(x->sel.proto);
 -                      addr->sadb_address_prefixlen = x->sel.prefixlen_s;
 -                      addr->sadb_address_reserved = 0;
 -
 -                      sin6 = (struct sockaddr_in6 *) (addr + 1);
 -                      sin6->sin6_family = AF_INET6;
 -                      sin6->sin6_port = x->sel.sport;
 -                      sin6->sin6_flowinfo = 0;
 -                      memcpy(&sin6->sin6_addr, x->sel.saddr.a6,
 -                             sizeof(struct in6_addr));
 -                      sin6->sin6_scope_id = 0;
 -              }
 +              pfkey_sockaddr_fill(&x->sel.saddr, x->sel.sport,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
        }
 -#endif
 -      else
 -              BUG();
  
        /* auth key */
        if (add_keys && auth_key_size) {
@@@ -1826,6 -1853,10 +1826,6 @@@ static in
  parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
  {
        struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
 -      struct sockaddr_in *sin;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
        int mode;
  
        if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
  
        /* addresses present only in tunnel mode */
        if (t->mode == XFRM_MODE_TUNNEL) {
 -              struct sockaddr *sa;
 -              sa = (struct sockaddr *)(rq+1);
 -              switch(sa->sa_family) {
 -              case AF_INET:
 -                      sin = (struct sockaddr_in*)sa;
 -                      t->saddr.a4 = sin->sin_addr.s_addr;
 -                      sin++;
 -                      if (sin->sin_family != AF_INET)
 -                              return -EINVAL;
 -                      t->id.daddr.a4 = sin->sin_addr.s_addr;
 -                      break;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -              case AF_INET6:
 -                      sin6 = (struct sockaddr_in6*)sa;
 -                      memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
 -                      sin6++;
 -                      if (sin6->sin6_family != AF_INET6)
 -                              return -EINVAL;
 -                      memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
 -                      break;
 -#endif
 -              default:
 +              u8 *sa = (u8 *) (rq + 1);
 +              int family, socklen;
 +
 +              family = pfkey_sockaddr_extract((struct sockaddr *)sa,
 +                                              &t->saddr);
 +              if (!family)
                        return -EINVAL;
 -              }
 -              t->encap_family = sa->sa_family;
 +
 +              socklen = pfkey_sockaddr_len(family);
 +              if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
 +                                         &t->id.daddr) != family)
 +                      return -EINVAL;
 +              t->encap_family = family;
        } else
                t->encap_family = xp->family;
  
@@@ -1909,7 -1952,9 +1909,7 @@@ static int pfkey_xfrm_policy2msg_size(s
  
        for (i=0; i<xp->xfrm_nr; i++) {
                t = xp->xfrm_vec + i;
 -              socklen += (t->encap_family == AF_INET ?
 -                          sizeof(struct sockaddr_in) :
 -                          sizeof(struct sockaddr_in6));
 +              socklen += pfkey_sockaddr_len(t->encap_family);
        }
  
        return sizeof(struct sadb_msg) +
@@@ -1942,12 -1987,18 +1942,12 @@@ static int pfkey_xfrm_policy2msg(struc
        struct sadb_address *addr;
        struct sadb_lifetime *lifetime;
        struct sadb_x_policy *pol;
 -      struct sockaddr_in   *sin;
        struct sadb_x_sec_ctx *sec_ctx;
        struct xfrm_sec_ctx *xfrm_ctx;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6  *sin6;
 -#endif
        int i;
        int size;
        int sockaddr_size = pfkey_sockaddr_size(xp->family);
 -      int socklen = (xp->family == AF_INET ?
 -                     sizeof(struct sockaddr_in) :
 -                     sizeof(struct sockaddr_in6));
 +      int socklen = pfkey_sockaddr_len(xp->family);
  
        size = pfkey_xfrm_policy2msg_size(xp);
  
        addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
        addr->sadb_address_prefixlen = xp->selector.prefixlen_s;
        addr->sadb_address_reserved = 0;
 -      /* src address */
 -      if (xp->family == AF_INET) {
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = xp->selector.saddr.a4;
 -              sin->sin_port = xp->selector.sport;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (xp->family == AF_INET6) {
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = xp->selector.sport;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr, xp->selector.saddr.a6,
 -                     sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      if (!pfkey_sockaddr_fill(&xp->selector.saddr,
 +                               xp->selector.sport,
 +                               (struct sockaddr *) (addr + 1),
 +                               xp->family))
                BUG();
  
        /* dst address */
        addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
        addr->sadb_address_prefixlen = xp->selector.prefixlen_d;
        addr->sadb_address_reserved = 0;
 -      if (xp->family == AF_INET) {
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = xp->selector.daddr.a4;
 -              sin->sin_port = xp->selector.dport;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (xp->family == AF_INET6) {
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = xp->selector.dport;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr, xp->selector.daddr.a6,
 -                     sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 -              BUG();
 +
 +      pfkey_sockaddr_fill(&xp->selector.daddr, xp->selector.dport,
 +                          (struct sockaddr *) (addr + 1),
 +                          xp->family);
  
        /* hard time */
        lifetime = (struct sadb_lifetime *)  skb_put(skb,
                int mode;
  
                req_size = sizeof(struct sadb_x_ipsecrequest);
 -              if (t->mode == XFRM_MODE_TUNNEL)
 -                      req_size += ((t->encap_family == AF_INET ?
 -                                   sizeof(struct sockaddr_in) :
 -                                   sizeof(struct sockaddr_in6)) * 2);
 -              else
 +              if (t->mode == XFRM_MODE_TUNNEL) {
 +                      socklen = pfkey_sockaddr_len(t->encap_family);
 +                      req_size += socklen * 2;
 +              } else {
                        size -= 2*socklen;
 +                      socklen = 0;
 +              }
                rq = (void*)skb_put(skb, req_size);
                pol->sadb_x_policy_len += req_size/8;
                memset(rq, 0, sizeof(*rq));
                if (t->optional)
                        rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
                rq->sadb_x_ipsecrequest_reqid = t->reqid;
 +
                if (t->mode == XFRM_MODE_TUNNEL) {
 -                      switch (t->encap_family) {
 -                      case AF_INET:
 -                              sin = (void*)(rq+1);
 -                              sin->sin_family = AF_INET;
 -                              sin->sin_addr.s_addr = t->saddr.a4;
 -                              sin->sin_port = 0;
 -                              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -                              sin++;
 -                              sin->sin_family = AF_INET;
 -                              sin->sin_addr.s_addr = t->id.daddr.a4;
 -                              sin->sin_port = 0;
 -                              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -                              break;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -                      case AF_INET6:
 -                              sin6 = (void*)(rq+1);
 -                              sin6->sin6_family = AF_INET6;
 -                              sin6->sin6_port = 0;
 -                              sin6->sin6_flowinfo = 0;
 -                              memcpy(&sin6->sin6_addr, t->saddr.a6,
 -                                     sizeof(struct in6_addr));
 -                              sin6->sin6_scope_id = 0;
 -
 -                              sin6++;
 -                              sin6->sin6_family = AF_INET6;
 -                              sin6->sin6_port = 0;
 -                              sin6->sin6_flowinfo = 0;
 -                              memcpy(&sin6->sin6_addr, t->id.daddr.a6,
 -                                     sizeof(struct in6_addr));
 -                              sin6->sin6_scope_id = 0;
 -                              break;
 -#endif
 -                      default:
 -                              break;
 -                      }
 +                      u8 *sa = (void *)(rq + 1);
 +                      pfkey_sockaddr_fill(&t->saddr, 0,
 +                                          (struct sockaddr *)sa,
 +                                          t->encap_family);
 +                      pfkey_sockaddr_fill(&t->id.daddr, 0,
 +                                          (struct sockaddr *) (sa + socklen),
 +                                          t->encap_family);
                }
        }
  
  #ifdef CONFIG_NET_KEY_MIGRATE
  static int pfkey_sockaddr_pair_size(sa_family_t family)
  {
 -      switch (family) {
 -      case AF_INET:
 -              return PFKEY_ALIGN8(sizeof(struct sockaddr_in) * 2);
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      case AF_INET6:
 -              return PFKEY_ALIGN8(sizeof(struct sockaddr_in6) * 2);
 -#endif
 -      default:
 -              return 0;
 -      }
 -      /* NOTREACHED */
 +      return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
  }
  
  static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq,
                               xfrm_address_t *saddr, xfrm_address_t *daddr,
                               u16 *family)
  {
 -      struct sockaddr *sa = (struct sockaddr *)(rq + 1);
 +      u8 *sa = (u8 *) (rq + 1);
 +      int af, socklen;
 +
        if (rq->sadb_x_ipsecrequest_len <
 -          pfkey_sockaddr_pair_size(sa->sa_family))
 +          pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family))
                return -EINVAL;
  
 -      switch (sa->sa_family) {
 -      case AF_INET:
 -              {
 -                      struct sockaddr_in *sin;
 -                      sin = (struct sockaddr_in *)sa;
 -                      if ((sin+1)->sin_family != AF_INET)
 -                              return -EINVAL;
 -                      memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4));
 -                      sin++;
 -                      memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4));
 -                      *family = AF_INET;
 -                      break;
 -              }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      case AF_INET6:
 -              {
 -                      struct sockaddr_in6 *sin6;
 -                      sin6 = (struct sockaddr_in6 *)sa;
 -                      if ((sin6+1)->sin6_family != AF_INET6)
 -                              return -EINVAL;
 -                      memcpy(&saddr->a6, &sin6->sin6_addr,
 -                             sizeof(saddr->a6));
 -                      sin6++;
 -                      memcpy(&daddr->a6, &sin6->sin6_addr,
 -                             sizeof(daddr->a6));
 -                      *family = AF_INET6;
 -                      break;
 -              }
 -#endif
 -      default:
 +      af = pfkey_sockaddr_extract((struct sockaddr *) sa,
 +                                  saddr);
 +      if (!af)
                return -EINVAL;
 -      }
  
 +      socklen = pfkey_sockaddr_len(af);
 +      if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen),
 +                                 daddr) != af)
 +              return -EINVAL;
 +
 +      *family = af;
        return 0;
  }
  
@@@ -2891,6 -3030,9 +2891,9 @@@ static int key_notify_sa_expire(struct 
  
  static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
  {
+       if (atomic_read(&pfkey_socks_nr) == 0)
+               return 0;
        switch (c->event) {
        case XFRM_MSG_EXPIRE:
                return key_notify_sa_expire(x, c);
@@@ -2952,6 -3094,10 +2955,6 @@@ static int pfkey_send_acquire(struct xf
        struct sadb_msg *hdr;
        struct sadb_address *addr;
        struct sadb_x_policy *pol;
 -      struct sockaddr_in *sin;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
        int sockaddr_size;
        int size;
        struct sadb_x_sec_ctx *sec_ctx;
        addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
        addr->sadb_address_proto = 0;
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              addr->sadb_address_prefixlen = 32;
 -
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = x->props.saddr.a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 -
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr,
 -                     x->props.saddr.a6, sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(&x->props.saddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
                BUG();
  
        /* dst address */
        addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
        addr->sadb_address_proto = 0;
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              addr->sadb_address_prefixlen = 32;
 -
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = x->id.daddr.a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 -
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr,
 -                     x->id.daddr.a6, sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(&x->id.daddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
                BUG();
  
        pol = (struct sadb_x_policy *)  skb_put(skb, sizeof(struct sadb_x_policy));
@@@ -3146,6 -3328,10 +3149,6 @@@ static int pfkey_send_new_mapping(struc
        struct sadb_sa *sa;
        struct sadb_address *addr;
        struct sadb_x_nat_t_port *n_port;
 -      struct sockaddr_in *sin;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
        int sockaddr_size;
        int size;
        __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0);
        addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
        addr->sadb_address_proto = 0;
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              addr->sadb_address_prefixlen = 32;
 -
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = x->props.saddr.a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 -
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr,
 -                     x->props.saddr.a6, sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(&x->props.saddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
                BUG();
  
        /* NAT_T_SPORT (old port) */
        addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
        addr->sadb_address_proto = 0;
        addr->sadb_address_reserved = 0;
 -      if (x->props.family == AF_INET) {
 -              addr->sadb_address_prefixlen = 32;
 -
 -              sin = (struct sockaddr_in *) (addr + 1);
 -              sin->sin_family = AF_INET;
 -              sin->sin_addr.s_addr = ipaddr->a4;
 -              sin->sin_port = 0;
 -              memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -      }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      else if (x->props.family == AF_INET6) {
 -              addr->sadb_address_prefixlen = 128;
 -
 -              sin6 = (struct sockaddr_in6 *) (addr + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              memcpy(&sin6->sin6_addr, &ipaddr->a6, sizeof(struct in6_addr));
 -              sin6->sin6_scope_id = 0;
 -      }
 -#endif
 -      else
 +      addr->sadb_address_prefixlen =
 +              pfkey_sockaddr_fill(ipaddr, 0,
 +                                  (struct sockaddr *) (addr + 1),
 +                                  x->props.family);
 +      if (!addr->sadb_address_prefixlen)
                BUG();
  
        /* NAT_T_DPORT (new port) */
@@@ -3254,6 -3475,10 +3257,6 @@@ static int set_sadb_address(struct sk_b
                            struct xfrm_selector *sel)
  {
        struct sadb_address *addr;
 -      struct sockaddr_in *sin;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
        addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize);
        addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8;
        addr->sadb_address_exttype = type;
  
        switch (type) {
        case SADB_EXT_ADDRESS_SRC:
 -              if (sel->family == AF_INET) {
 -                      addr->sadb_address_prefixlen = sel->prefixlen_s;
 -                      sin = (struct sockaddr_in *)(addr + 1);
 -                      sin->sin_family = AF_INET;
 -                      memcpy(&sin->sin_addr.s_addr, &sel->saddr,
 -                             sizeof(sin->sin_addr.s_addr));
 -                      sin->sin_port = 0;
 -                      memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -              }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -              else if (sel->family == AF_INET6) {
 -                      addr->sadb_address_prefixlen = sel->prefixlen_s;
 -                      sin6 = (struct sockaddr_in6 *)(addr + 1);
 -                      sin6->sin6_family = AF_INET6;
 -                      sin6->sin6_port = 0;
 -                      sin6->sin6_flowinfo = 0;
 -                      sin6->sin6_scope_id = 0;
 -                      memcpy(&sin6->sin6_addr.s6_addr, &sel->saddr,
 -                             sizeof(sin6->sin6_addr.s6_addr));
 -              }
 -#endif
 +              addr->sadb_address_prefixlen = sel->prefixlen_s;
 +              pfkey_sockaddr_fill(&sel->saddr, 0,
 +                                  (struct sockaddr *)(addr + 1),
 +                                  sel->family);
                break;
        case SADB_EXT_ADDRESS_DST:
 -              if (sel->family == AF_INET) {
 -                      addr->sadb_address_prefixlen = sel->prefixlen_d;
 -                      sin = (struct sockaddr_in *)(addr + 1);
 -                      sin->sin_family = AF_INET;
 -                      memcpy(&sin->sin_addr.s_addr, &sel->daddr,
 -                             sizeof(sin->sin_addr.s_addr));
 -                      sin->sin_port = 0;
 -                      memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 -              }
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -              else if (sel->family == AF_INET6) {
 -                      addr->sadb_address_prefixlen = sel->prefixlen_d;
 -                      sin6 = (struct sockaddr_in6 *)(addr + 1);
 -                      sin6->sin6_family = AF_INET6;
 -                      sin6->sin6_port = 0;
 -                      sin6->sin6_flowinfo = 0;
 -                      sin6->sin6_scope_id = 0;
 -                      memcpy(&sin6->sin6_addr.s6_addr, &sel->daddr,
 -                             sizeof(sin6->sin6_addr.s6_addr));
 -              }
 -#endif
 +              addr->sadb_address_prefixlen = sel->prefixlen_d;
 +              pfkey_sockaddr_fill(&sel->daddr, 0,
 +                                  (struct sockaddr *)(addr + 1),
 +                                  sel->family);
                break;
        default:
                return -EINVAL;
@@@ -3286,8 -3545,10 +3289,8 @@@ static int set_ipsecrequest(struct sk_b
                            xfrm_address_t *src, xfrm_address_t *dst)
  {
        struct sadb_x_ipsecrequest *rq;
 -      struct sockaddr_in *sin;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      struct sockaddr_in6 *sin6;
 -#endif
 +      u8 *sa;
 +      int socklen = pfkey_sockaddr_len(family);
        int size_req;
  
        size_req = sizeof(struct sadb_x_ipsecrequest) +
        rq->sadb_x_ipsecrequest_level = level;
        rq->sadb_x_ipsecrequest_reqid = reqid;
  
 -      switch (family) {
 -      case AF_INET:
 -              sin = (struct sockaddr_in *)(rq + 1);
 -              sin->sin_family = AF_INET;
 -              memcpy(&sin->sin_addr.s_addr, src,
 -                     sizeof(sin->sin_addr.s_addr));
 -              sin++;
 -              sin->sin_family = AF_INET;
 -              memcpy(&sin->sin_addr.s_addr, dst,
 -                     sizeof(sin->sin_addr.s_addr));
 -              break;
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 -      case AF_INET6:
 -              sin6 = (struct sockaddr_in6 *)(rq + 1);
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              sin6->sin6_scope_id = 0;
 -              memcpy(&sin6->sin6_addr.s6_addr, src,
 -                     sizeof(sin6->sin6_addr.s6_addr));
 -              sin6++;
 -              sin6->sin6_family = AF_INET6;
 -              sin6->sin6_port = 0;
 -              sin6->sin6_flowinfo = 0;
 -              sin6->sin6_scope_id = 0;
 -              memcpy(&sin6->sin6_addr.s6_addr, dst,
 -                     sizeof(sin6->sin6_addr.s6_addr));
 -              break;
 -#endif
 -      default:
 +      sa = (u8 *) (rq + 1);
 +      if (!pfkey_sockaddr_fill(src, 0, (struct sockaddr *)sa, family) ||
 +          !pfkey_sockaddr_fill(dst, 0, (struct sockaddr *)(sa + socklen), family))
                return -EINVAL;
 -      }
  
        return 0;
  }
index e6d645221d5c1c0bd32faf843a7ff677b793293f,662c1ccfee262c8047974205c75dca631df51c96..f27c99246a4cce80a46f65ce809ea01c982883d8
@@@ -196,8 -196,6 +196,6 @@@ destroy_conntrack(struct nf_conntrack *
        if (l4proto && l4proto->destroy)
                l4proto->destroy(ct);
  
-       nf_ct_ext_destroy(ct);
        rcu_read_unlock();
  
        spin_lock_bh(&nf_conntrack_lock);
@@@ -520,6 -518,7 +518,7 @@@ static void nf_conntrack_free_rcu(struc
  
  void nf_conntrack_free(struct nf_conn *ct)
  {
+       nf_ct_ext_destroy(ct);
        call_rcu(&ct->rcu, nf_conntrack_free_rcu);
  }
  EXPORT_SYMBOL_GPL(nf_conntrack_free);
@@@ -848,25 -847,6 +847,25 @@@ acct
  }
  EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
  
 +void __nf_ct_kill_acct(struct nf_conn *ct,
 +              enum ip_conntrack_info ctinfo,
 +              const struct sk_buff *skb,
 +              int do_acct)
 +{
 +#ifdef CONFIG_NF_CT_ACCT
 +      if (do_acct) {
 +              spin_lock_bh(&nf_conntrack_lock);
 +              ct->counters[CTINFO2DIR(ctinfo)].packets++;
 +              ct->counters[CTINFO2DIR(ctinfo)].bytes +=
 +                      skb->len - skb_network_offset(skb);
 +              spin_unlock_bh(&nf_conntrack_lock);
 +      }
 +#endif
 +      if (del_timer(&ct->timeout))
 +              ct->timeout.function((unsigned long)ct);
 +}
 +EXPORT_SYMBOL_GPL(__nf_ct_kill_acct);
 +
  #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
  
  #include <linux/netfilter/nfnetlink.h>