]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'upstream-fixes'
authorJeff Garzik <jgarzik@pobox.com>
Tue, 4 Oct 2005 02:06:19 +0000 (22:06 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 4 Oct 2005 02:06:19 +0000 (22:06 -0400)
1  2 
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/ns83820.c
drivers/net/r8169.c
drivers/net/skge.c
drivers/net/wan/syncppp.c
include/linux/netdevice.h
net/ieee80211/ieee80211_module.c
net/ieee80211/ieee80211_tx.c

diff --combined drivers/net/Kconfig
index db8898100325bb7865fa06027e051900623628a7,2a908c4690a7cd41eae1793dec2d9c6daa2e9b41..018b11a7a4ce04c41c7ed14e3d24d179c4822243
@@@ -548,6 -548,14 +548,14 @@@ config SUNGE
          Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
          <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
  
+ config CASSINI
+       tristate "Sun Cassini support"
+       depends on NET_ETHERNET && PCI
+       select CRC32
+       help
+         Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
  config NET_VENDOR_3COM
        bool "3COM cards"
        depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
@@@ -2075,7 -2083,6 +2083,7 @@@ config SPIDER_NE
  config GIANFAR
        tristate "Gianfar Ethernet"
        depends on 85xx || 83xx
 +      select PHYLIB
        help
          This driver supports the Gigabit TSEC on the MPC85xx 
          family of chips, and the FEC on the 8540
@@@ -2236,20 -2243,6 +2244,20 @@@ config ISERIES_VET
        tristate "iSeries Virtual Ethernet driver support"
        depends on PPC_ISERIES
  
 +config RIONET
 +      tristate "RapidIO Ethernet over messaging driver support"
 +      depends on NETDEVICES && RAPIDIO
 +
 +config RIONET_TX_SIZE
 +      int "Number of outbound queue entries"
 +      depends on RIONET
 +      default "128"
 +
 +config RIONET_RX_SIZE
 +      int "Number of inbound queue entries"
 +      depends on RIONET
 +      default "128"
 +
  config FDDI
        bool "FDDI driver support"
        depends on (PCI || EISA)
diff --combined drivers/net/Makefile
index 39b17cb4f86e638da28abd7dc62b96643b8ee357,8aeec9f2495b5e712879b7735e95bf141ce49e05..4c9477cb212778bb021e821e52736547955b6e3e
@@@ -13,7 -13,7 +13,7 @@@ obj-$(CONFIG_CHELSIO_T1) += chelsio
  obj-$(CONFIG_BONDING) += bonding/
  obj-$(CONFIG_GIANFAR) += gianfar_driver.o
  
 -gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
 +gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
  
  #
  # link order important here
@@@ -28,6 -28,7 +28,7 @@@ obj-$(CONFIG_SUNQE) += sunqe.
  obj-$(CONFIG_SUNBMAC) += sunbmac.o
  obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
  obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
+ obj-$(CONFIG_CASSINI) += cassini.o
  
  obj-$(CONFIG_MACE) += mace.o
  obj-$(CONFIG_BMAC) += bmac.o
@@@ -63,7 -64,6 +64,7 @@@ obj-$(CONFIG_SKFP) += skfp
  obj-$(CONFIG_VIA_RHINE) += via-rhine.o
  obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
  obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 +obj-$(CONFIG_RIONET) += rionet.o
  
  #
  # end link order section
diff --combined drivers/net/ns83820.c
index ed72a23c85dd1b310936734f72e942a4c76dc109,1d123d2b53fdfb34923a8e8d20c253c5834c95e3..bc354a80c09963c703626512943e2382e64922ce
@@@ -584,7 -584,7 +584,7 @@@ static inline int ns83820_add_rx_skb(st
        return 0;
  }
  
- static inline int rx_refill(struct net_device *ndev, int gfp)
+ static inline int rx_refill(struct net_device *ndev, unsigned int gfp)
  {
        struct ns83820 *dev = PRIV(ndev);
        unsigned i;
@@@ -1632,7 -1632,8 +1632,7 @@@ static void ns83820_run_bist(struct net
                        timed_out = 1;
                        break;
                }
 -              set_current_state(TASK_UNINTERRUPTIBLE);
 -              schedule_timeout(1);
 +              schedule_timeout_uninterruptible(1);
        }
  
        if (status & fail)
diff --combined drivers/net/r8169.c
index 40c40eba258140506a64052a6cf638912a87715d,afb3f186b8843b96b4ad0214c18e40515a11b091..159b56a56ef49112fc5e58083c76a3066eb76958
@@@ -92,8 -92,7 +92,7 @@@ VERSION 2.2LK <2005/01/25
  #endif /* RTL8169_DEBUG */
  
  #define R8169_MSG_DEFAULT \
-       (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
-        NETIF_MSG_IFDOWN)
+       (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
  
  #define TX_BUFFS_AVAIL(tp) \
        (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
@@@ -1028,7 -1027,6 +1027,7 @@@ static struct ethtool_ops rtl8169_ethto
        .get_strings            = rtl8169_get_strings,
        .get_stats_count        = rtl8169_get_stats_count,
        .get_ethtool_stats      = rtl8169_get_ethtool_stats,
 +      .get_perm_addr          = ethtool_op_get_perm_addr,
  };
  
  static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@@ -1513,7 -1511,6 +1512,7 @@@ rtl8169_init_one(struct pci_dev *pdev, 
        /* Get MAC address.  FIXME: read EEPROM */
        for (i = 0; i < MAC_ADDR_LEN; i++)
                dev->dev_addr[i] = RTL_R8(MAC0 + i);
 +      memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
  
        dev->open = rtl8169_open;
        dev->hard_start_xmit = rtl8169_start_xmit;
diff --combined drivers/net/skge.c
index 189203c9533024b4d1e1d5827e25d80ec297d365,c2e6484ef138f6e0c8d7548fd340a61028c85c81..572f121b1f4edaf29533eba3d3c0bd7c7a4e959b
@@@ -730,7 -730,6 +730,7 @@@ static struct ethtool_ops skge_ethtool_
        .phys_id        = skge_phys_id,
        .get_stats_count = skge_get_stats_count,
        .get_ethtool_stats = skge_get_ethtool_stats,
 +      .get_perm_addr  = ethtool_op_get_perm_addr,
  };
  
  /*
@@@ -1644,6 -1643,22 +1644,22 @@@ static void yukon_reset(struct skge_hw 
                         | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
  }
  
+ /* Apparently, early versions of Yukon-Lite had wrong chip_id? */
+ static int is_yukon_lite_a0(struct skge_hw *hw)
+ {
+       u32 reg;
+       int ret;
+       if (hw->chip_id != CHIP_ID_YUKON)
+               return 0;
+       reg = skge_read32(hw, B2_FAR);
+       skge_write8(hw, B2_FAR + 3, 0xff);
+       ret = (skge_read8(hw, B2_FAR + 3) != 0);
+       skge_write32(hw, B2_FAR, reg);
+       return ret;
+ }
  static void yukon_mac_init(struct skge_hw *hw, int port)
  {
        struct skge_port *skge = netdev_priv(hw->dev[port]);
        /* Configure Rx MAC FIFO */
        skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
        reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
-       if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
+       /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+       if (is_yukon_lite_a0(hw))
                reg &= ~GMF_RX_F_FL_ON;
        skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
        skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
        /*
@@@ -2820,21 -2837,29 +2838,29 @@@ static void skge_netpoll(struct net_dev
  static int skge_set_mac_address(struct net_device *dev, void *p)
  {
        struct skge_port *skge = netdev_priv(dev);
-       struct sockaddr *addr = p;
-       int err = 0;
+       struct skge_hw *hw = skge->hw;
+       unsigned port = skge->port;
+       const struct sockaddr *addr = p;
  
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
  
-       skge_down(dev);
+       spin_lock_bh(&hw->phy_lock);
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-       memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8,
+       memcpy_toio(hw->regs + B2_MAC_1 + port*8,
                    dev->dev_addr, ETH_ALEN);
-       memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8,
+       memcpy_toio(hw->regs + B2_MAC_2 + port*8,
                    dev->dev_addr, ETH_ALEN);
-       if (dev->flags & IFF_UP)
-               err = skge_up(dev);
-       return err;
+       if (hw->chip_id == CHIP_ID_GENESIS)
+               xm_outaddr(hw, port, XM_SA, dev->dev_addr);
+       else {
+               gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
+               gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+       }
+       spin_unlock_bh(&hw->phy_lock);
+       return 0;
  }
  
  static const struct {
@@@ -3071,7 -3096,6 +3097,7 @@@ static struct net_device *skge_devinit(
  
        /* read the mac address */
        memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
 +      memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
  
        /* device is off until link detection */
        netif_carrier_off(dev);
index 3731b22f6757d673f3ecf10eaddb3dbb7de9c0b1,a6d3b55013a5106b379bd5bddf47b4e89f1ad3f4..2d1bba06a08512d5d0a5af5bb8283ee9f9493922
@@@ -221,7 -221,7 +221,7 @@@ static void sppp_clear_timeout(struct s
   *    here.
   */
   
 -void sppp_input (struct net_device *dev, struct sk_buff *skb)
 +static void sppp_input (struct net_device *dev, struct sk_buff *skb)
  {
        struct ppp_header *h;
        struct sppp *sp = (struct sppp *)sppp_of(dev);
@@@ -355,6 -355,8 +355,6 @@@ done
        return;
  }
  
 -EXPORT_SYMBOL(sppp_input);
 -
  /*
   *    Handle transmit packets.
   */
@@@ -767,7 -769,7 +767,7 @@@ static void sppp_cisco_input (struct sp
                u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
  #ifdef CONFIG_INET
                rcu_read_lock();
-               if ((in_dev = __in_dev_get(dev)) != NULL)
+               if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
                {
                        for (ifa=in_dev->ifa_list; ifa != NULL;
                                ifa=ifa->ifa_next) {
@@@ -988,7 -990,7 +988,7 @@@ EXPORT_SYMBOL(sppp_reopen)
   *    the mtu is out of range.
   */
   
 -int sppp_change_mtu(struct net_device *dev, int new_mtu)
 +static int sppp_change_mtu(struct net_device *dev, int new_mtu)
  {
        if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
                return -EINVAL;
        return 0;
  }
  
 -EXPORT_SYMBOL(sppp_change_mtu);
 -
  /**
   *    sppp_do_ioctl - Ioctl handler for ppp/hdlc
   *    @dev: Device subject to ioctl
@@@ -1452,7 -1456,7 +1452,7 @@@ static int sppp_rcv(struct sk_buff *skb
        return 0;
  }
  
 -struct packet_type sppp_packet_type = {
 +static struct packet_type sppp_packet_type = {
        .type   = __constant_htons(ETH_P_WAN_PPP),
        .func   = sppp_rcv,
  };
index 98c98e6cd4f370b0a997f5a790b1ab7477ded8d6,368e4c825ff1b5006adfe8a962083500a6776e0c..a9281b24c40b8bfa748899dad4c5e17574e4aaaf
@@@ -265,6 -265,8 +265,8 @@@ struct net_devic
         * the interface.
         */
        char                    name[IFNAMSIZ];
+       /* device name hash chain */
+       struct hlist_node       name_hlist;
  
        /*
         *      I/O specific fields
  
        /* ------- Fields preinitialized in Space.c finish here ------- */
  
+       /* Net device features */
+       unsigned long           features;
+ #define NETIF_F_SG            1       /* Scatter/gather IO. */
+ #define NETIF_F_IP_CSUM               2       /* Can checksum only TCP/UDP over IPv4. */
+ #define NETIF_F_NO_CSUM               4       /* Does not require checksum. F.e. loopack. */
+ #define NETIF_F_HW_CSUM               8       /* Can checksum all the packets. */
+ #define NETIF_F_HIGHDMA               32      /* Can DMA to high memory. */
+ #define NETIF_F_FRAGLIST      64      /* Scatter/gather IO. */
+ #define NETIF_F_HW_VLAN_TX    128     /* Transmit VLAN hw acceleration */
+ #define NETIF_F_HW_VLAN_RX    256     /* Receive VLAN hw acceleration */
+ #define NETIF_F_HW_VLAN_FILTER        512     /* Receive filtering on VLAN */
+ #define NETIF_F_VLAN_CHALLENGED       1024    /* Device cannot handle VLAN packets */
+ #define NETIF_F_TSO           2048    /* Can offload TCP/IP segmentation */
+ #define NETIF_F_LLTX          4096    /* LockLess TX */
        struct net_device       *next_sched;
  
        /* Interface index. Unique device identifier    */
         * will (read: may be cleaned up at will).
         */
  
-       /* These may be needed for future network-power-down code. */
-       unsigned long           trans_start;    /* Time (in jiffies) of last Tx */
-       unsigned long           last_rx;        /* Time of last Rx      */
  
        unsigned short          flags;  /* interface flags (a la BSD)   */
        unsigned short          gflags;
        unsigned                mtu;    /* interface MTU value          */
        unsigned short          type;   /* interface hardware type      */
        unsigned short          hard_header_len;        /* hardware hdr length  */
-       void                    *priv;  /* pointer to private data      */
  
        struct net_device       *master; /* Pointer to master device of a group,
                                          * which this device is member of.
                                          */
  
        /* Interface address info. */
-       unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
-       unsigned char           dev_addr[MAX_ADDR_LEN]; /* hw address   */
        unsigned char           perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
        unsigned char           addr_len;       /* hardware address length      */
        unsigned short          dev_id;         /* for shared network cards */
        int                     promiscuity;
        int                     allmulti;
  
-       int                     watchdog_timeo;
-       struct timer_list       watchdog_timer;
  
        /* Protocol specific pointers */
        
        void                    *ec_ptr;        /* Econet specific data */
        void                    *ax25_ptr;      /* AX.25 specific data */
  
-       struct list_head        poll_list;      /* Link to poll list    */
+ /*
+  * Cache line mostly used on receive path (including eth_type_trans())
+  */
+       struct list_head        poll_list ____cacheline_aligned_in_smp;
+                                       /* Link to poll list    */
+       int                     (*poll) (struct net_device *dev, int *quota);
        int                     quota;
        int                     weight;
+       unsigned long           last_rx;        /* Time of last Rx      */
+       /* Interface address info used in eth_type_trans() */
+       unsigned char           dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast 
+                                                       because most packets are unicast) */
+       unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
  
+ /*
+  * Cache line mostly used on queue transmit path (qdisc)
+  */
+       /* device queue lock */
+       spinlock_t              queue_lock ____cacheline_aligned_in_smp;
        struct Qdisc            *qdisc;
        struct Qdisc            *qdisc_sleeping;
-       struct Qdisc            *qdisc_ingress;
        struct list_head        qdisc_list;
        unsigned long           tx_queue_len;   /* Max frames per queue allowed */
  
        /* ingress path synchronizer */
        spinlock_t              ingress_lock;
+       struct Qdisc            *qdisc_ingress;
+ /*
+  * One part is mostly used on xmit path (device)
+  */
        /* hard_start_xmit synchronizer */
-       spinlock_t              xmit_lock;
+       spinlock_t              xmit_lock ____cacheline_aligned_in_smp;
        /* cpu id of processor entered to hard_start_xmit or -1,
           if nobody entered there.
         */
        int                     xmit_lock_owner;
-       /* device queue lock */
-       spinlock_t              queue_lock;
+       void                    *priv;  /* pointer to private data      */
+       int                     (*hard_start_xmit) (struct sk_buff *skb,
+                                                   struct net_device *dev);
+       /* These may be needed for future network-power-down code. */
+       unsigned long           trans_start;    /* Time (in jiffies) of last Tx */
+       int                     watchdog_timeo; /* used by dev_watchdog() */
+       struct timer_list       watchdog_timer;
+ /*
+  * refcnt is a very hot point, so align it on SMP
+  */
        /* Number of references to this device */
-       atomic_t                refcnt;
+       atomic_t                refcnt ____cacheline_aligned_in_smp;
        /* delayed register/unregister */
        struct list_head        todo_list;
-       /* device name hash chain */
-       struct hlist_node       name_hlist;
        /* device index hash chain */
        struct hlist_node       index_hlist;
  
               NETREG_RELEASED,         /* called free_netdev */
        } reg_state;
  
-       /* Net device features */
-       unsigned long           features;
- #define NETIF_F_SG            1       /* Scatter/gather IO. */
- #define NETIF_F_IP_CSUM               2       /* Can checksum only TCP/UDP over IPv4. */
- #define NETIF_F_NO_CSUM               4       /* Does not require checksum. F.e. loopack. */
- #define NETIF_F_HW_CSUM               8       /* Can checksum all the packets. */
- #define NETIF_F_HIGHDMA               32      /* Can DMA to high memory. */
- #define NETIF_F_FRAGLIST      64      /* Scatter/gather IO. */
- #define NETIF_F_HW_VLAN_TX    128     /* Transmit VLAN hw acceleration */
- #define NETIF_F_HW_VLAN_RX    256     /* Receive VLAN hw acceleration */
- #define NETIF_F_HW_VLAN_FILTER        512     /* Receive filtering on VLAN */
- #define NETIF_F_VLAN_CHALLENGED       1024    /* Device cannot handle VLAN packets */
- #define NETIF_F_TSO           2048    /* Can offload TCP/IP segmentation */
- #define NETIF_F_LLTX          4096    /* LockLess TX */
        /* Called after device is detached from network. */
        void                    (*uninit)(struct net_device *dev);
        /* Called after last user reference disappears. */
        /* Pointers to interface service routines.      */
        int                     (*open)(struct net_device *dev);
        int                     (*stop)(struct net_device *dev);
-       int                     (*hard_start_xmit) (struct sk_buff *skb,
-                                                   struct net_device *dev);
  #define HAVE_NETDEV_POLL
-       int                     (*poll) (struct net_device *dev, int *quota);
        int                     (*hard_header) (struct sk_buff *skb,
                                                struct net_device *dev,
                                                unsigned short type,
@@@ -852,9 -873,11 +873,9 @@@ static inline void netif_rx_complete(st
  
  static inline void netif_poll_disable(struct net_device *dev)
  {
 -      while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
 +      while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state))
                /* No hurry. */
 -              current->state = TASK_INTERRUPTIBLE;
 -              schedule_timeout(1);
 -      }
 +              schedule_timeout_interruptible(1);
  }
  
  static inline void netif_poll_enable(struct net_device *dev)
index 5714692e82b46d9fe9d9452a693aa994f0619d5a,6059e9e37123b711554c6e50a18daf8a5872c793..f66d792cd204b068976f7655e625cb4a21d99978
@@@ -1,6 -1,6 +1,6 @@@
  /*******************************************************************************
  
 -  Copyright(c) 2004 Intel Corporation. All rights reserved.
 +  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
  
    Portions of this file are based on the WEP enablement code provided by the
    Host AP project hostap-drivers v0.1.3
  
  #include <net/ieee80211.h>
  
 -MODULE_DESCRIPTION("802.11 data/management/control stack");
 -MODULE_AUTHOR
 -    ("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
 -MODULE_LICENSE("GPL");
 +#define DRV_DESCRIPTION "802.11 data/management/control stack"
 +#define DRV_NAME        "ieee80211"
 +#define DRV_VERSION   IEEE80211_VERSION
 +#define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
  
 -#define DRV_NAME "ieee80211"
 +MODULE_VERSION(DRV_VERSION);
 +MODULE_DESCRIPTION(DRV_DESCRIPTION);
 +MODULE_AUTHOR(DRV_COPYRIGHT);
 +MODULE_LICENSE("GPL");
  
  static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
  {
@@@ -129,34 -126,26 +129,34 @@@ struct net_device *alloc_ieee80211(int 
  
        /* Default fragmentation threshold is maximum payload size */
        ieee->fts = DEFAULT_FTS;
 +      ieee->rts = DEFAULT_FTS;
        ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
        ieee->open_wep = 1;
  
        /* Default to enabling full open WEP with host based encrypt/decrypt */
        ieee->host_encrypt = 1;
        ieee->host_decrypt = 1;
 +      ieee->host_mc_decrypt = 1;
 +
 +      /* Host fragementation in Open mode. Default is enabled.
 +       * Note: host fragmentation is always enabled if host encryption
 +       * is enabled. For cards can do hardware encryption, they must do
 +       * hardware fragmentation as well. So we don't need a variable
 +       * like host_enc_frag. */
 +      ieee->host_open_frag = 1;
        ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
  
        INIT_LIST_HEAD(&ieee->crypt_deinit_list);
        init_timer(&ieee->crypt_deinit_timer);
        ieee->crypt_deinit_timer.data = (unsigned long)ieee;
        ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
 +      ieee->crypt_quiesced = 0;
  
        spin_lock_init(&ieee->lock);
  
        ieee->wpa_enabled = 0;
 -      ieee->tkip_countermeasures = 0;
        ieee->drop_unencrypted = 0;
        ieee->privacy_invoked = 0;
 -      ieee->ieee802_1x = 1;
  
        return dev;
  
@@@ -172,7 -161,6 +172,7 @@@ void free_ieee80211(struct net_device *
  
        int i;
  
 +      ieee80211_crypt_quiescing(ieee);
        del_timer_sync(&ieee->crypt_deinit_timer);
        ieee80211_crypt_deinit_entries(ieee, 1);
  
@@@ -207,30 -195,42 +207,30 @@@ static int show_debug_level(char *page
  static int store_debug_level(struct file *file, const char __user * buffer,
                             unsigned long count, void *data)
  {
 -      char buf[] = "0x00000000";
 -      char *p = (char *)buf;
 +      char buf[] = "0x00000000\n";
 +      unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
        unsigned long val;
  
 -      if (count > sizeof(buf) - 1)
 -              count = sizeof(buf) - 1;
 -
 -      if (copy_from_user(buf, buffer, count))
 +      if (copy_from_user(buf, buffer, len))
                return count;
 -      buf[count] = 0;
 -      /*
 -       * what a FPOS...  What, sscanf(buf, "%i", &val) would be too
 -       * scary?
 -       */
 -      if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
 -              p++;
 -              if (p[0] == 'x' || p[0] == 'X')
 -                      p++;
 -              val = simple_strtoul(p, &p, 16);
 -      } else
 -              val = simple_strtoul(p, &p, 10);
 -      if (p == buf)
 +      buf[len] = 0;
 +      if (sscanf(buf, "%li", &val) != 1)
                printk(KERN_INFO DRV_NAME
                       ": %s is not in hex or decimal form.\n", buf);
        else
                ieee80211_debug_level = val;
  
 -      return strlen(buf);
 +      return strnlen(buf, len);
  }
 +#endif                                /* CONFIG_IEEE80211_DEBUG */
  
  static int __init ieee80211_init(void)
  {
 +#ifdef CONFIG_IEEE80211_DEBUG
        struct proc_dir_entry *e;
  
        ieee80211_debug_level = debug;
-       ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
+       ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
        if (ieee80211_proc == NULL) {
                IEEE80211_ERROR("Unable to create " DRV_NAME
                                " proc directory\n");
        e->read_proc = show_debug_level;
        e->write_proc = store_debug_level;
        e->data = NULL;
 +#endif                                /* CONFIG_IEEE80211_DEBUG */
 +
 +      printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
 +      printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
  
        return 0;
  }
  
  static void __exit ieee80211_exit(void)
  {
 +#ifdef CONFIG_IEEE80211_DEBUG
        if (ieee80211_proc) {
                remove_proc_entry("debug_level", ieee80211_proc);
                remove_proc_entry(DRV_NAME, proc_net);
                ieee80211_proc = NULL;
        }
 +#endif                                /* CONFIG_IEEE80211_DEBUG */
  }
  
 +#ifdef CONFIG_IEEE80211_DEBUG
  #include <linux/moduleparam.h>
  module_param(debug, int, 0444);
  MODULE_PARM_DESC(debug, "debug output mask");
 +#endif                                /* CONFIG_IEEE80211_DEBUG */
  
  module_exit(ieee80211_exit);
  module_init(ieee80211_init);
 -#endif
  
  const char *escape_essid(const char *essid, u8 essid_len)
  {
index 8d87897d7eb7ef218d483a90bb64606cdc557e91,f9153671168e7a5cae0432e0975a0b9b7f6780e5..e860777ab8d34cd4fa37cebfca694f40db1ac02f
@@@ -1,6 -1,6 +1,6 @@@
  /******************************************************************************
  
 -  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
 +  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms of version 2 of the GNU General Public License as
@@@ -128,7 -128,7 +128,7 @@@ payload of each frame is reduced to 49
  static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
  static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
  
 -static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
 +static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
  {
        struct ieee80211_snap_hdr *snap;
        u8 *oui;
@@@ -157,11 -157,31 +157,11 @@@ static inline int ieee80211_encrypt_fra
        struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
        int res;
  
 -#ifdef CONFIG_IEEE80211_CRYPT_TKIP
 -      struct ieee80211_hdr *header;
 -
 -      if (ieee->tkip_countermeasures &&
 -          crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
 -              header = (struct ieee80211_hdr *)frag->data;
 -              if (net_ratelimit()) {
 -                      printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
 -                             "TX packet to " MAC_FMT "\n",
 -                             ieee->dev->name, MAC_ARG(header->addr1));
 -              }
 -              return -1;
 -      }
 -#endif
        /* To encrypt, frame format is:
         * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
 -
 -      // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
 -      /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
 -       * call both MSDU and MPDU encryption functions from here. */
        atomic_inc(&crypt->refcnt);
        res = 0;
 -      if (crypt->ops->encrypt_msdu)
 -              res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
 -      if (res == 0 && crypt->ops->encrypt_mpdu)
 +      if (crypt->ops->encrypt_mpdu)
                res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
  
        atomic_dec(&crypt->refcnt);
@@@ -187,7 -207,7 +187,7 @@@ void ieee80211_txb_free(struct ieee8021
  }
  
  static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-                                                int gfp_mask)
+                                                unsigned int gfp_mask)
  {
        struct ieee80211_txb *txb;
        int i;
        return txb;
  }
  
 -/* SKBs are added to the ieee->tx_queue. */
 +/* Incoming skb is converted to a txb which consists of
 + * a block of 802.11 fragment packets (stored as skbs) */
  int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
  {
        struct ieee80211_device *ieee = netdev_priv(dev);
        struct ieee80211_txb *txb = NULL;
 -      struct ieee80211_hdr *frag_hdr;
 -      int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
 +      struct ieee80211_hdr_3addr *frag_hdr;
 +      int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
 +          rts_required;
        unsigned long flags;
        struct net_device_stats *stats = &ieee->stats;
 -      int ether_type, encrypt;
 +      int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
        int bytes, fc, hdr_len;
        struct sk_buff *skb_frag;
 -      struct ieee80211_hdr header = { /* Ensure zero initialized */
 +      struct ieee80211_hdr_3addr header = {   /* Ensure zero initialized */
                .duration_id = 0,
                .seq_ctl = 0
        };
        u8 dest[ETH_ALEN], src[ETH_ALEN];
 -
        struct ieee80211_crypt_data *crypt;
 +      int priority = skb->priority;
 +      int snapped = 0;
 +
 +      if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
 +              return NETDEV_TX_BUSY;
  
        spin_lock_irqsave(&ieee->lock, flags);
  
        crypt = ieee->crypt[ieee->tx_keyidx];
  
        encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
 -          ieee->host_encrypt && crypt && crypt->ops;
 +          ieee->sec.encrypt;
 +
 +      host_encrypt = ieee->host_encrypt && encrypt;
 +      host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
 +      host_build_iv = ieee->host_build_iv && encrypt;
  
        if (!encrypt && ieee->ieee802_1x &&
            ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
        }
  
        /* Save source and destination addresses */
 -      memcpy(&dest, skb->data, ETH_ALEN);
 -      memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
 +      memcpy(dest, skb->data, ETH_ALEN);
 +      memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
  
        /* Advance the SKB to the start of the payload */
        skb_pull(skb, sizeof(struct ethhdr));
        /* Determine total amount of storage required for TXB packets */
        bytes = skb->len + SNAP_SIZE + sizeof(u16);
  
 -      if (encrypt)
 +      if (host_encrypt)
                fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
                    IEEE80211_FCTL_PROTECTED;
        else
  
        if (ieee->iw_mode == IW_MODE_INFRA) {
                fc |= IEEE80211_FCTL_TODS;
 -              /* To DS: Addr1 = BSSID, Addr2 = SA,
 -                 Addr3 = DA */
 -              memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
 -              memcpy(&header.addr2, &src, ETH_ALEN);
 -              memcpy(&header.addr3, &dest, ETH_ALEN);
 +              /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
 +              memcpy(header.addr1, ieee->bssid, ETH_ALEN);
 +              memcpy(header.addr2, src, ETH_ALEN);
 +              memcpy(header.addr3, dest, ETH_ALEN);
        } else if (ieee->iw_mode == IW_MODE_ADHOC) {
 -              /* not From/To DS: Addr1 = DA, Addr2 = SA,
 -                 Addr3 = BSSID */
 -              memcpy(&header.addr1, dest, ETH_ALEN);
 -              memcpy(&header.addr2, src, ETH_ALEN);
 -              memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
 +              /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
 +              memcpy(header.addr1, dest, ETH_ALEN);
 +              memcpy(header.addr2, src, ETH_ALEN);
 +              memcpy(header.addr3, ieee->bssid, ETH_ALEN);
        }
        header.frame_ctl = cpu_to_le16(fc);
        hdr_len = IEEE80211_3ADDR_LEN;
  
 -      /* Determine fragmentation size based on destination (multicast
 -       * and broadcast are not fragmented) */
 -      if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
 -              frag_size = MAX_FRAG_THRESHOLD;
 -      else
 -              frag_size = ieee->fts;
 +      /* Encrypt msdu first on the whole data packet. */
 +      if ((host_encrypt || host_encrypt_msdu) &&
 +          crypt && crypt->ops && crypt->ops->encrypt_msdu) {
 +              int res = 0;
 +              int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
 +                  crypt->ops->extra_msdu_postfix_len;
 +              struct sk_buff *skb_new = dev_alloc_skb(len);
 +
 +              if (unlikely(!skb_new))
 +                      goto failed;
 +
 +              skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
 +              memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
 +              snapped = 1;
 +              ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
 +                                  ether_type);
 +              memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
 +              res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
 +              if (res < 0) {
 +                      IEEE80211_ERROR("msdu encryption failed\n");
 +                      dev_kfree_skb_any(skb_new);
 +                      goto failed;
 +              }
 +              dev_kfree_skb_any(skb);
 +              skb = skb_new;
 +              bytes += crypt->ops->extra_msdu_prefix_len +
 +                  crypt->ops->extra_msdu_postfix_len;
 +              skb_pull(skb, hdr_len);
 +      }
  
 -      /* Determine amount of payload per fragment.  Regardless of if
 -       * this stack is providing the full 802.11 header, one will
 -       * eventually be affixed to this fragment -- so we must account for
 -       * it when determining the amount of payload space. */
 -      bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
 -      if (ieee->config &
 -          (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 -              bytes_per_frag -= IEEE80211_FCS_LEN;
 -
 -      /* Each fragment may need to have room for encryptiong pre/postfix */
 -      if (encrypt)
 -              bytes_per_frag -= crypt->ops->extra_prefix_len +
 -                  crypt->ops->extra_postfix_len;
 -
 -      /* Number of fragments is the total bytes_per_frag /
 -       * payload_per_fragment */
 -      nr_frags = bytes / bytes_per_frag;
 -      bytes_last_frag = bytes % bytes_per_frag;
 -      if (bytes_last_frag)
 +      if (host_encrypt || ieee->host_open_frag) {
 +              /* Determine fragmentation size based on destination (multicast
 +               * and broadcast are not fragmented) */
 +              if (is_multicast_ether_addr(dest))
 +                      frag_size = MAX_FRAG_THRESHOLD;
 +              else
 +                      frag_size = ieee->fts;
 +
 +              /* Determine amount of payload per fragment.  Regardless of if
 +               * this stack is providing the full 802.11 header, one will
 +               * eventually be affixed to this fragment -- so we must account
 +               * for it when determining the amount of payload space. */
 +              bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
 +              if (ieee->config &
 +                  (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 +                      bytes_per_frag -= IEEE80211_FCS_LEN;
 +
 +              /* Each fragment may need to have room for encryptiong
 +               * pre/postfix */
 +              if (host_encrypt)
 +                      bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
 +                          crypt->ops->extra_mpdu_postfix_len;
 +
 +              /* Number of fragments is the total
 +               * bytes_per_frag / payload_per_fragment */
 +              nr_frags = bytes / bytes_per_frag;
 +              bytes_last_frag = bytes % bytes_per_frag;
 +              if (bytes_last_frag)
 +                      nr_frags++;
 +              else
 +                      bytes_last_frag = bytes_per_frag;
 +      } else {
 +              nr_frags = 1;
 +              bytes_per_frag = bytes_last_frag = bytes;
 +              frag_size = bytes + IEEE80211_3ADDR_LEN;
 +      }
 +
 +      rts_required = (frag_size > ieee->rts
 +                      && ieee->config & CFG_IEEE80211_RTS);
 +      if (rts_required)
                nr_frags++;
 -      else
 -              bytes_last_frag = bytes_per_frag;
  
        /* When we allocate the TXB we allocate enough space for the reserve
         * and full fragment bytes (bytes_per_frag doesn't include prefix,
                goto failed;
        }
        txb->encrypted = encrypt;
 -      txb->payload_size = bytes;
 +      if (host_encrypt)
 +              txb->payload_size = frag_size * (nr_frags - 1) +
 +                  bytes_last_frag;
 +      else
 +              txb->payload_size = bytes;
 +
 +      if (rts_required) {
 +              skb_frag = txb->fragments[0];
 +              frag_hdr =
 +                  (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
 +
 +              /*
 +               * Set header frame_ctl to the RTS.
 +               */
 +              header.frame_ctl =
 +                  cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
 +              memcpy(frag_hdr, &header, hdr_len);
  
 -      for (i = 0; i < nr_frags; i++) {
 +              /*
 +               * Restore header frame_ctl to the original data setting.
 +               */
 +              header.frame_ctl = cpu_to_le16(fc);
 +
 +              if (ieee->config &
 +                  (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 +                      skb_put(skb_frag, 4);
 +
 +              txb->rts_included = 1;
 +              i = 1;
 +      } else
 +              i = 0;
 +
 +      for (; i < nr_frags; i++) {
                skb_frag = txb->fragments[i];
  
 -              if (encrypt)
 -                      skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
 +              if (host_encrypt || host_build_iv)
 +                      skb_reserve(skb_frag,
 +                                  crypt->ops->extra_mpdu_prefix_len);
  
 -              frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
 +              frag_hdr =
 +                  (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
                memcpy(frag_hdr, &header, hdr_len);
  
                /* If this is not the last fragment, then add the MOREFRAGS
                        bytes = bytes_last_frag;
                }
  
 -              /* Put a SNAP header on the first fragment */
 -              if (i == 0) {
 -                      ieee80211_put_snap(skb_put
 -                                         (skb_frag, SNAP_SIZE + sizeof(u16)),
 -                                         ether_type);
 +              if (i == 0 && !snapped) {
 +                      ieee80211_copy_snap(skb_put
 +                                          (skb_frag, SNAP_SIZE + sizeof(u16)),
 +                                          ether_type);
                        bytes -= SNAP_SIZE + sizeof(u16);
                }
  
  
                /* Encryption routine will move the header forward in order
                 * to insert the IV between the header and the payload */
 -              if (encrypt)
 +              if (host_encrypt)
                        ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
 +              else if (host_build_iv) {
 +                      struct ieee80211_crypt_data *crypt;
 +
 +                      crypt = ieee->crypt[ieee->tx_keyidx];
 +                      atomic_inc(&crypt->refcnt);
 +                      if (crypt->ops->build_iv)
 +                              crypt->ops->build_iv(skb_frag, hdr_len,
 +                                                   crypt->priv);
 +                      atomic_dec(&crypt->refcnt);
 +              }
 +
                if (ieee->config &
                    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
                        skb_put(skb_frag, 4);
        dev_kfree_skb_any(skb);
  
        if (txb) {
 -              if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
 +              int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
 +              if (ret == 0) {
                        stats->tx_packets++;
                        stats->tx_bytes += txb->payload_size;
                        return 0;
                }
 +
 +              if (ret == NETDEV_TX_BUSY) {
 +                      printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
 +                             "driver should report queue full via "
 +                             "ieee_device->is_queue_full.\n",
 +                             ieee->dev->name);
 +              }
 +
                ieee80211_txb_free(txb);
        }
  
        netif_stop_queue(dev);
        stats->tx_errors++;
        return 1;
 +}
 +
 +/* Incoming 802.11 strucure is converted to a TXB
 + * a block of 802.11 fragment packets (stored as skbs) */
 +int ieee80211_tx_frame(struct ieee80211_device *ieee,
 +                     struct ieee80211_hdr *frame, int len)
 +{
 +      struct ieee80211_txb *txb = NULL;
 +      unsigned long flags;
 +      struct net_device_stats *stats = &ieee->stats;
 +      struct sk_buff *skb_frag;
 +      int priority = -1;
 +
 +      spin_lock_irqsave(&ieee->lock, flags);
  
 +      /* If there is no driver handler to take the TXB, dont' bother
 +       * creating it... */
 +      if (!ieee->hard_start_xmit) {
 +              printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
 +              goto success;
 +      }
 +
 +      if (unlikely(len < 24)) {
 +              printk(KERN_WARNING "%s: skb too small (%d).\n",
 +                     ieee->dev->name, len);
 +              goto success;
 +      }
 +
 +      /* When we allocate the TXB we allocate enough space for the reserve
 +       * and full fragment bytes (bytes_per_frag doesn't include prefix,
 +       * postfix, header, FCS, etc.) */
 +      txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
 +      if (unlikely(!txb)) {
 +              printk(KERN_WARNING "%s: Could not allocate TXB\n",
 +                     ieee->dev->name);
 +              goto failed;
 +      }
 +      txb->encrypted = 0;
 +      txb->payload_size = len;
 +
 +      skb_frag = txb->fragments[0];
 +
 +      memcpy(skb_put(skb_frag, len), frame, len);
 +
 +      if (ieee->config &
 +          (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 +              skb_put(skb_frag, 4);
 +
 +      success:
 +      spin_unlock_irqrestore(&ieee->lock, flags);
 +
 +      if (txb) {
 +              if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
 +                      stats->tx_packets++;
 +                      stats->tx_bytes += txb->payload_size;
 +                      return 0;
 +              }
 +              ieee80211_txb_free(txb);
 +      }
 +      return 0;
 +
 +      failed:
 +      spin_unlock_irqrestore(&ieee->lock, flags);
 +      stats->tx_errors++;
 +      return 1;
  }
  
 +EXPORT_SYMBOL(ieee80211_tx_frame);
  EXPORT_SYMBOL(ieee80211_txb_free);