]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master'
authorJeff Garzik <jgarzik@pobox.com>
Thu, 20 Oct 2005 14:06:09 +0000 (10:06 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Thu, 20 Oct 2005 14:06:09 +0000 (10:06 -0400)
145 files changed:
Documentation/networking/bonding.txt
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/au1000_eth.c
drivers/net/b44.c
drivers/net/b44.h
drivers/net/bonding/bond_main.c
drivers/net/declance.c
drivers/net/e100.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_param.c
drivers/net/epic100.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/gianfar.h
drivers/net/gianfar_ethtool.c
drivers/net/gianfar_mii.c [new file with mode: 0644]
drivers/net/gianfar_mii.h [new file with mode: 0644]
drivers/net/gianfar_phy.c [deleted file]
drivers/net/gianfar_phy.h [deleted file]
drivers/net/hamradio/Kconfig
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/mkiss.h [deleted file]
drivers/net/hp100.c
drivers/net/irda/stir4200.c
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_main.c
drivers/net/lne390.c
drivers/net/mii.c
drivers/net/mipsnet.c [new file with mode: 0644]
drivers/net/mipsnet.h [new file with mode: 0644]
drivers/net/ne.c
drivers/net/ne2k-pci.c
drivers/net/ns83820.c
drivers/net/pcnet32.c
drivers/net/phy/Kconfig
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/r8169.c
drivers/net/rionet.c [new file with mode: 0644]
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sb1250-mac.c
drivers/net/sgiseeq.c
drivers/net/skge.c
drivers/net/sundance.c
drivers/net/tokenring/ibmtr.c
drivers/net/tokenring/olympic.c
drivers/net/tokenring/tms380tr.c
drivers/net/tulip/de2104x.c
drivers/net/typhoon.c
drivers/net/via-rhine.c
drivers/net/wan/cosa.c
drivers/net/wan/cycx_drv.c
drivers/net/wan/cycx_main.c
drivers/net/wan/cycx_x25.c
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/lmc/lmc_debug.c
drivers/net/wan/lmc/lmc_media.c
drivers/net/wan/pc300.h
drivers/net/wan/pc300_drv.c
drivers/net/wan/pc300_tty.c
drivers/net/wan/sdla.c
drivers/net/wan/sdla_fr.c
drivers/net/wan/sdla_x25.c
drivers/net/wan/sdladrv.c
drivers/net/wan/syncppp.c
drivers/net/wireless/airo.c
drivers/net/wireless/airport.c
drivers/net/wireless/atmel.c
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes.h
drivers/net/wireless/hostap/hostap.c
drivers/net/wireless/hostap/hostap_80211_rx.c
drivers/net/wireless/hostap/hostap_80211_tx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_ap.h
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/hostap/hostap_wlan.h
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2100.h
drivers/net/wireless/ipw2200.c
drivers/net/wireless/ipw2200.h
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/orinoco_nortel.c
drivers/net/wireless/orinoco_pci.c
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_tmd.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_dev.h
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/spectrum_cs.c
drivers/net/wireless/wavelan.c
drivers/net/wireless/wavelan.p.h
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wavelan_cs.p.h
drivers/net/wireless/wl3501.h
drivers/s390/net/qeth.h
drivers/s390/net/qeth_fs.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_mpc.c
drivers/s390/net/qeth_mpc.h
drivers/s390/net/qeth_sys.c
include/asm-mips/sgi/hpc3.h
include/linux/cyclomx.h
include/linux/cycx_drv.h
include/linux/ibmtr.h
include/linux/if_arp.h
include/linux/mii.h
include/linux/netdevice.h
include/linux/sdladrv.h
include/linux/wanpipe.h
include/net/ieee80211.h
include/net/ieee80211_crypt.h
include/net/ieee80211_radiotap.h [new file with mode: 0644]
include/net/syncppp.h
net/ieee80211/Makefile
net/ieee80211/ieee80211_crypt.c
net/ieee80211/ieee80211_crypt_ccmp.c
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_crypt_wep.c
net/ieee80211/ieee80211_geo.c [new file with mode: 0644]
net/ieee80211/ieee80211_module.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_tx.c
net/ieee80211/ieee80211_wx.c

index a55f0f95b171a3bbe80b5e19c535a2707e957f64..b0fe41da007bf847e8ae2da4c4b2b840461d9353 100644 (file)
@@ -777,7 +777,7 @@ doing so is the same as described in the "Configuring Multiple Bonds
 Manually" section, below.
 
        NOTE: It has been observed that some Red Hat supplied kernels
-are apparently unable to rename modules at load time (the "-obonding1"
+are apparently unable to rename modules at load time (the "-o bond1"
 part).  Attempts to pass that option to modprobe will produce an
 "Operation not permitted" error.  This has been reported on some
 Fedora Core kernels, and has been seen on RHEL 4 as well.  On kernels
@@ -883,7 +883,8 @@ the above does not work, and the second bonding instance never sees
 its options.  In that case, the second options line can be substituted
 as follows:
 
-install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
+install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
+       mode=balance-alb miimon=50
 
        This may be repeated any number of times, specifying a new and
 unique name in place of bond1 for each subsequent instance.
index bc537440ca025931124c278d81f66a3d742cabf6..f822cd3025ff07b154e48e7cd2d226e21f4f6898 100644 (file)
@@ -1027,8 +1027,7 @@ static void cp_reset_hw (struct cp_private *cp)
                if (!(cpr8(Cmd) & CmdReset))
                        return;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(10);
+               schedule_timeout_uninterruptible(10);
        }
 
        printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1575,6 +1574,7 @@ static struct ethtool_ops cp_ethtool_ops = {
        .set_wol                = cp_set_wol,
        .get_strings            = cp_get_strings,
        .get_ethtool_stats      = cp_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1773,6 +1773,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        for (i = 0; i < 3; i++)
                ((u16 *) (dev->dev_addr))[i] =
                    le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        dev->open = cp_open;
        dev->stop = cp_close;
index 4c2cf7bbd252927c40a018bb8d69b0e3c26b900e..30bee11c48bd2d8364ac8f8e93abe47c5467593e 100644 (file)
@@ -552,7 +552,8 @@ const static struct {
 
        { "RTL-8100B/8139D",
          HW_REVID(1, 1, 1, 0, 1, 0, 1),
-         HasLWake,
+         HasHltClk /* XXX undocumented? */
+       | HasLWake,
        },
 
        { "RTL-8101",
@@ -970,6 +971,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        for (i = 0; i < 3; i++)
                ((u16 *) (dev->dev_addr))[i] =
                    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        /* The Rtl8139-specific entries in the device structure. */
        dev->open = rtl8139_open;
@@ -2465,6 +2467,7 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
        .get_strings            = rtl8139_get_strings,
        .get_stats_count        = rtl8139_get_stats_count,
        .get_ethtool_stats      = rtl8139_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
index c748b0e1641921b195d5df144ae0addba10eb3b3..5148d47492a0c1b90eb225826ff85ea0a0c046f9 100644 (file)
@@ -475,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
          the moment only acceleration of IPv4 is supported.  This option
          enables offloading for checksums on transmit.  If unsure, say Y.
 
+config MIPS_SIM_NET
+       tristate "MIPS simulator Network device (EXPERIMENTAL)"
+       depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
+       help
+         The MIPSNET device is a simple Ethernet network device which is
+         emulated by the MIPS Simulator.
+         If you are not using a MIPSsim or are unsure, say N.
+
 config SGI_O2MACE_ETH
        tristate "SGI O2 MACE Fast Ethernet support"
        depends on NET_ETHERNET && SGI_IP32=y
@@ -2083,6 +2091,7 @@ config SPIDER_NET
 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
@@ -2243,6 +2252,20 @@ config ISERIES_VETH
        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)
index 8aeec9f2495b5e712879b7735e95bf141ce49e05..1a84e0435f64b52d022aaa3f3ebd4efca0f62f4a 100644 (file)
@@ -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
@@ -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
@@ -166,6 +167,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
 obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
 obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
index c82b9cd1c9246c1b1660a059757fd0764912ee5b..78506911d6566d96efdadf6464b828ebd4d3d6cb 100644 (file)
@@ -151,13 +151,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
        SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
        SUPPORTED_Autoneg
 
-static char *phy_link[] = 
-{      "unknown", 
-       "10Base2", "10BaseT", 
-       "AUI",
-       "100BaseT", "100BaseTX", "100BaseFX"
-};
-
 int bcm_5201_init(struct net_device *dev, int phy_addr)
 {
        s16 data;
@@ -785,6 +778,7 @@ static struct mii_chip_info {
        {"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
        {"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
        {"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+       {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
        {"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
        {"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
        {"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
@@ -1045,7 +1039,7 @@ found:
 #endif
 
        if (aup->mii->chip_info == NULL) {
-               printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+               printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
                                dev->name);
                return -1;
        }
@@ -1546,6 +1540,9 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
                printk(KERN_ERR "%s: out of memory\n", dev->name);
                goto err_out;
        }
+       aup->mii->next = NULL;
+       aup->mii->chip_info = NULL;
+       aup->mii->status = 0;
        aup->mii->mii_control_reg = 0;
        aup->mii->mii_data_reg = 0;
 
index 94939f570f78988e7c54c9dbcab685ca59385253..282ebd15f0115ae659b74a7b9e902631fa1640e6 100644 (file)
@@ -106,6 +106,29 @@ static int b44_poll(struct net_device *dev, int *budget);
 static void b44_poll_controller(struct net_device *dev);
 #endif
 
+static int dma_desc_align_mask;
+static int dma_desc_sync_size;
+
+static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
+                                                dma_addr_t dma_base,
+                                                unsigned long offset,
+                                                enum dma_data_direction dir)
+{
+       dma_sync_single_range_for_device(&pdev->dev, dma_base,
+                                        offset & dma_desc_align_mask,
+                                        dma_desc_sync_size, dir);
+}
+
+static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
+                                             dma_addr_t dma_base,
+                                             unsigned long offset,
+                                             enum dma_data_direction dir)
+{
+       dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
+                                     offset & dma_desc_align_mask,
+                                     dma_desc_sync_size, dir);
+}
+
 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
 {
        return readl(bp->regs + reg);
@@ -668,6 +691,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        dp->ctrl = cpu_to_le32(ctrl);
        dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
 
+       if (bp->flags & B44_FLAG_RX_RING_HACK)
+               b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+                                            dest_idx * sizeof(dp),
+                                            DMA_BIDIRECTIONAL);
+
        return RX_PKT_BUF_SZ;
 }
 
@@ -692,6 +720,11 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        pci_unmap_addr_set(dest_map, mapping,
                           pci_unmap_addr(src_map, mapping));
 
+       if (bp->flags & B44_FLAG_RX_RING_HACK)
+               b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
+                                         src_idx * sizeof(src_desc),
+                                         DMA_BIDIRECTIONAL);
+
        ctrl = src_desc->ctrl;
        if (dest_idx == (B44_RX_RING_SIZE - 1))
                ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -700,8 +733,14 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
 
        dest_desc->ctrl = ctrl;
        dest_desc->addr = src_desc->addr;
+
        src_map->skb = NULL;
 
+       if (bp->flags & B44_FLAG_RX_RING_HACK)
+               b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+                                            dest_idx * sizeof(dest_desc),
+                                            DMA_BIDIRECTIONAL);
+
        pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
                                       RX_PKT_BUF_SZ,
                                       PCI_DMA_FROMDEVICE);
@@ -959,6 +998,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
        bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
 
+       if (bp->flags & B44_FLAG_TX_RING_HACK)
+               b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
+                                            entry * sizeof(bp->tx_ring[0]),
+                                            DMA_TO_DEVICE);
+
        entry = NEXT_TX(entry);
 
        bp->tx_prod = entry;
@@ -1064,6 +1108,16 @@ static void b44_init_rings(struct b44 *bp)
        memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
        memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
 
+       if (bp->flags & B44_FLAG_RX_RING_HACK)
+               dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
+                                          DMA_TABLE_BYTES,
+                                          PCI_DMA_BIDIRECTIONAL);
+
+       if (bp->flags & B44_FLAG_TX_RING_HACK)
+               dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
+                                          DMA_TABLE_BYTES,
+                                          PCI_DMA_TODEVICE);
+
        for (i = 0; i < bp->rx_pending; i++) {
                if (b44_alloc_rx_skb(bp, -1, i) < 0)
                        break;
@@ -1085,14 +1139,28 @@ static void b44_free_consistent(struct b44 *bp)
                bp->tx_buffers = NULL;
        }
        if (bp->rx_ring) {
-               pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-                                   bp->rx_ring, bp->rx_ring_dma);
+               if (bp->flags & B44_FLAG_RX_RING_HACK) {
+                       dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
+                                        DMA_TABLE_BYTES,
+                                        DMA_BIDIRECTIONAL);
+                       kfree(bp->rx_ring);
+               } else
+                       pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+                                           bp->rx_ring, bp->rx_ring_dma);
                bp->rx_ring = NULL;
+               bp->flags &= ~B44_FLAG_RX_RING_HACK;
        }
        if (bp->tx_ring) {
-               pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-                                   bp->tx_ring, bp->tx_ring_dma);
+               if (bp->flags & B44_FLAG_TX_RING_HACK) {
+                       dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
+                                        DMA_TABLE_BYTES,
+                                        DMA_TO_DEVICE);
+                       kfree(bp->tx_ring);
+               } else
+                       pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+                                           bp->tx_ring, bp->tx_ring_dma);
                bp->tx_ring = NULL;
+               bp->flags &= ~B44_FLAG_TX_RING_HACK;
        }
 }
 
@@ -1118,12 +1186,56 @@ static int b44_alloc_consistent(struct b44 *bp)
 
        size = DMA_TABLE_BYTES;
        bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
-       if (!bp->rx_ring)
-               goto out_err;
+       if (!bp->rx_ring) {
+               /* Allocation may have failed due to pci_alloc_consistent
+                  insisting on use of GFP_DMA, which is more restrictive
+                  than necessary...  */
+               struct dma_desc *rx_ring;
+               dma_addr_t rx_ring_dma;
+
+               if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+                       goto out_err;
+
+               memset(rx_ring, 0, size);
+               rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
+                                            DMA_TABLE_BYTES,
+                                            DMA_BIDIRECTIONAL);
+
+               if (rx_ring_dma + size > B44_DMA_MASK) {
+                       kfree(rx_ring);
+                       goto out_err;
+               }
+
+               bp->rx_ring = rx_ring;
+               bp->rx_ring_dma = rx_ring_dma;
+               bp->flags |= B44_FLAG_RX_RING_HACK;
+       }
 
        bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
-       if (!bp->tx_ring)
-               goto out_err;
+       if (!bp->tx_ring) {
+               /* Allocation may have failed due to pci_alloc_consistent
+                  insisting on use of GFP_DMA, which is more restrictive
+                  than necessary...  */
+               struct dma_desc *tx_ring;
+               dma_addr_t tx_ring_dma;
+
+               if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+                       goto out_err;
+
+               memset(tx_ring, 0, size);
+               tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
+                                            DMA_TABLE_BYTES,
+                                            DMA_TO_DEVICE);
+
+               if (tx_ring_dma + size > B44_DMA_MASK) {
+                       kfree(tx_ring);
+                       goto out_err;
+               }
+
+               bp->tx_ring = tx_ring;
+               bp->tx_ring_dma = tx_ring_dma;
+               bp->flags |= B44_FLAG_TX_RING_HACK;
+       }
 
        return 0;
 
@@ -1676,6 +1788,7 @@ static struct ethtool_ops b44_ethtool_ops = {
        .set_pauseparam         = b44_set_pauseparam,
        .get_msglevel           = b44_get_msglevel,
        .set_msglevel           = b44_set_msglevel,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1718,6 +1831,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
        bp->dev->dev_addr[3] = eeprom[80];
        bp->dev->dev_addr[4] = eeprom[83];
        bp->dev->dev_addr[5] = eeprom[82];
+       memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
 
        bp->phy_addr = eeprom[90] & 0x1f;
 
@@ -1971,6 +2085,12 @@ static struct pci_driver b44_driver = {
 
 static int __init b44_init(void)
 {
+       unsigned int dma_desc_align_size = dma_get_cache_alignment();
+
+       /* Setup paramaters for syncing RX/TX DMA descriptors */
+       dma_desc_align_mask = ~(dma_desc_align_size - 1);
+       dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+
        return pci_module_init(&b44_driver);
 }
 
index 11c40a2e71c70a416e75a6d9c4f3c69579c50ddc..593cb0ad4100c6c68d43346f17922061dc0d0759 100644 (file)
@@ -400,6 +400,8 @@ struct b44 {
 #define B44_FLAG_ADV_100HALF   0x04000000
 #define B44_FLAG_ADV_100FULL   0x08000000
 #define B44_FLAG_INTERNAL_PHY  0x10000000
+#define B44_FLAG_RX_RING_HACK  0x20000000
+#define B44_FLAG_TX_RING_HACK  0x40000000
 
        u32                     rx_offset;
 
index f264ff162979f5eec2efecae262f3a21fe399588..8032126fd5891845ecee2ba19de06a28f312ddbb 100644 (file)
@@ -4241,6 +4241,43 @@ out:
        return 0;
 }
 
+static void bond_activebackup_xmit_copy(struct sk_buff *skb,
+                                        struct bonding *bond,
+                                        struct slave *slave)
+{
+       struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
+       struct ethhdr *eth_data;
+       u8 *hwaddr;
+       int res;
+
+       if (!skb2) {
+               printk(KERN_ERR DRV_NAME ": Error: "
+                      "bond_activebackup_xmit_copy(): skb_copy() failed\n");
+               return;
+       }
+
+       skb2->mac.raw = (unsigned char *)skb2->data;
+       eth_data = eth_hdr(skb2);
+
+       /* Pick an appropriate source MAC address
+        *      -- use slave's perm MAC addr, unless used by bond
+        *      -- otherwise, borrow active slave's perm MAC addr
+        *         since that will not be used
+        */
+       hwaddr = slave->perm_hwaddr;
+       if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
+               hwaddr = bond->curr_active_slave->perm_hwaddr;
+
+       /* Set source MAC address appropriately */
+       memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
+
+       res = bond_dev_queue_xmit(bond, skb2, slave->dev);
+       if (res)
+               dev_kfree_skb(skb2);
+
+       return;
+}
+
 /*
  * in active-backup mode, we know that bond->curr_active_slave is always valid if
  * the bond has a usable interface.
@@ -4257,10 +4294,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
                goto out;
        }
 
-       if (bond->curr_active_slave) { /* one usable interface */
-               res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+       if (!bond->curr_active_slave)
+               goto out;
+
+       /* Xmit IGMP frames on all slaves to ensure rapid fail-over
+          for multicast traffic on snooping switches */
+       if (skb->protocol == __constant_htons(ETH_P_IP) &&
+           skb->nh.iph->protocol == IPPROTO_IGMP) {
+               struct slave *slave, *active_slave;
+               int i;
+
+               active_slave = bond->curr_active_slave;
+               bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
+                                           active_slave->prev)
+                       if (IS_UP(slave->dev) &&
+                           (slave->link == BOND_LINK_UP))
+                               bond_activebackup_xmit_copy(skb, bond, slave);
        }
 
+       res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+
 out:
        if (res) {
                /* no suitable interface, frame not sent */
index 521c83137bf67f61e275cacdd0553cc1af9feaa2..f130bdab3fd319f06a1fac0101737d5149b381f2 100644 (file)
@@ -5,7 +5,7 @@
  *
  *      adopted from sunlance.c by Richard van den Berg
  *
- *      Copyright (C) 2002, 2003  Maciej W. Rozycki
+ *      Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
  *
  *      additional sources:
  *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
 #include <linux/string.h>
 
 #include <asm/addrspace.h>
+#include <asm/system.h>
+
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/kn01.h>
 #include <asm/dec/machtype.h>
+#include <asm/dec/system.h>
 #include <asm/dec/tc.h>
-#include <asm/system.h>
 
 static char version[] __devinitdata =
 "declance.c: v0.009 by Linux MIPS DECstation task force\n";
@@ -79,10 +81,6 @@ MODULE_LICENSE("GPL");
 #define PMAD_LANCE 2
 #define PMAX_LANCE 3
 
-#ifndef CONFIG_TC
-unsigned long system_base;
-unsigned long dmaptr;
-#endif
 
 #define LE_CSR0 0
 #define LE_CSR1 1
@@ -237,7 +235,7 @@ struct lance_init_block {
 /*
  * This works *only* for the ring descriptors
  */
-#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
+#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
 
 struct lance_private {
        struct net_device *next;
@@ -697,12 +695,13 @@ out:
        spin_unlock(&lp->lock);
 }
 
-static void lance_dma_merr_int(const int irq, void *dev_id,
-                               struct pt_regs *regs)
+static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
+                                     struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
 
        printk("%s: DMA error\n", dev->name);
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t
@@ -1026,10 +1025,6 @@ static int __init dec_lance_init(const int type, const int slot)
        unsigned long esar_base;
        unsigned char *esar;
 
-#ifndef CONFIG_TC
-       system_base = KN01_LANCE_BASE;
-#endif
-
        if (dec_lance_debug && version_printed++ == 0)
                printk(version);
 
@@ -1062,16 +1057,16 @@ static int __init dec_lance_init(const int type, const int slot)
        switch (type) {
 #ifdef CONFIG_TC
        case ASIC_LANCE:
-               dev->base_addr = system_base + IOASIC_LANCE;
+               dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
 
                /* buffer space for the on-board LANCE shared memory */
                /*
                 * FIXME: ugly hack!
                 */
-               dev->mem_start = KSEG1ADDR(0x00020000);
+               dev->mem_start = CKSEG1ADDR(0x00020000);
                dev->mem_end = dev->mem_start + 0x00020000;
                dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-               esar_base = system_base + IOASIC_ESAR;
+               esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
 
                /* Workaround crash with booting KN04 2.1k from Disk */
                memset((void *)dev->mem_start, 0,
@@ -1101,14 +1096,14 @@ static int __init dec_lance_init(const int type, const int slot)
                /* Setup I/O ASIC LANCE DMA.  */
                lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
                ioasic_write(IO_REG_LANCE_DMA_P,
-                            PHYSADDR(dev->mem_start) << 3);
+                            CPHYSADDR(dev->mem_start) << 3);
 
                break;
 
        case PMAD_LANCE:
                claim_tc_card(slot);
 
-               dev->mem_start = get_tc_base_addr(slot);
+               dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
                dev->base_addr = dev->mem_start + 0x100000;
                dev->irq = get_tc_irq_nr(slot);
                esar_base = dev->mem_start + 0x1c0002;
@@ -1137,9 +1132,9 @@ static int __init dec_lance_init(const int type, const int slot)
 
        case PMAX_LANCE:
                dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-               dev->base_addr = KN01_LANCE_BASE;
-               dev->mem_start = KN01_LANCE_BASE + 0x01000000;
-               esar_base = KN01_RTC_BASE + 1;
+               dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
+               dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+               esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
                lp->dma_irq = -1;
 
                /*
index 40887f09b681ac8253e9faaa54c2c41aadb5c480..eb169a8e877316022c272bee1972bd3f02d92901 100644 (file)
@@ -2201,6 +2201,7 @@ static struct ethtool_ops e100_ethtool_ops = {
        .phys_id                = e100_phys_id,
        .get_stats_count        = e100_get_stats_count,
        .get_ethtool_stats      = e100_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -2351,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        e100_phy_init(nic);
 
        memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
-       if(!is_valid_ether_addr(netdev->dev_addr)) {
+       memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
+       if(!is_valid_ether_addr(netdev->perm_addr)) {
                DPRINTK(PROBE, ERR, "Invalid MAC address from "
                        "EEPROM, aborting.\n");
                err = -EAGAIN;
index 092757bc721f0ade1821465d73bedba39348ee89..3f653a93e1bc78dc9ab7e730bdc9490cac4f5650 100644 (file)
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
 
 #define BAR_0          0
 #define BAR_1          1
@@ -165,10 +169,33 @@ struct e1000_buffer {
        uint16_t next_to_watch;
 };
 
-struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
-struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
+
+struct e1000_tx_ring {
+       /* pointer to the descriptor ring memory */
+       void *desc;
+       /* physical address of the descriptor ring */
+       dma_addr_t dma;
+       /* length of descriptor ring in bytes */
+       unsigned int size;
+       /* number of descriptors in the ring */
+       unsigned int count;
+       /* next descriptor to associate a buffer with */
+       unsigned int next_to_use;
+       /* next descriptor to check for DD status bit */
+       unsigned int next_to_clean;
+       /* array of buffer information structs */
+       struct e1000_buffer *buffer_info;
+
+       struct e1000_buffer previous_buffer_info;
+       spinlock_t tx_lock;
+       uint16_t tdh;
+       uint16_t tdt;
+       uint64_t pkt;
+};
 
-struct e1000_desc_ring {
+struct e1000_rx_ring {
        /* pointer to the descriptor ring memory */
        void *desc;
        /* physical address of the descriptor ring */
@@ -186,6 +213,10 @@ struct e1000_desc_ring {
        /* arrays of page information for packet split */
        struct e1000_ps_page *ps_page;
        struct e1000_ps_page_dma *ps_page_dma;
+
+       uint16_t rdh;
+       uint16_t rdt;
+       uint64_t pkt;
 };
 
 #define E1000_DESC_UNUSED(R) \
@@ -227,9 +258,10 @@ struct e1000_adapter {
        unsigned long led_status;
 
        /* TX */
-       struct e1000_desc_ring tx_ring;
-       struct e1000_buffer previous_buffer_info;
-       spinlock_t tx_lock;
+       struct e1000_tx_ring *tx_ring;      /* One per active queue */
+#ifdef CONFIG_E1000_MQ
+       struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
+#endif
        uint32_t txd_cmd;
        uint32_t tx_int_delay;
        uint32_t tx_abs_int_delay;
@@ -246,19 +278,33 @@ struct e1000_adapter {
 
        /* RX */
 #ifdef CONFIG_E1000_NAPI
-       boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
-                         int work_to_do);
+       boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+                              struct e1000_rx_ring *rx_ring,
+                              int *work_done, int work_to_do);
 #else
-       boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+       boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+                              struct e1000_rx_ring *rx_ring);
 #endif
-       void (*alloc_rx_buf) (struct e1000_adapter *adapter);
-       struct e1000_desc_ring rx_ring;
+       void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rx_ring);
+       struct e1000_rx_ring *rx_ring;      /* One per active queue */
+#ifdef CONFIG_E1000_NAPI
+       struct net_device *polling_netdev;  /* One per active queue */
+#endif
+#ifdef CONFIG_E1000_MQ
+       struct net_device **cpu_netdev;     /* per-cpu */
+       struct call_async_data_struct rx_sched_call_data;
+       int cpu_for_queue[4];
+#endif
+       int num_queues;
+
        uint64_t hw_csum_err;
        uint64_t hw_csum_good;
+       uint64_t rx_hdr_split;
        uint32_t rx_int_delay;
        uint32_t rx_abs_int_delay;
        boolean_t rx_csum;
-       boolean_t rx_ps;
+       unsigned int rx_ps_pages;
        uint32_t gorcl;
        uint64_t gorcl_old;
        uint16_t rx_ps_bsize0;
@@ -278,8 +324,8 @@ struct e1000_adapter {
        struct e1000_phy_stats phy_stats;
 
        uint32_t test_icr;
-       struct e1000_desc_ring test_tx_ring;
-       struct e1000_desc_ring test_rx_ring;
+       struct e1000_tx_ring test_tx_ring;
+       struct e1000_rx_ring test_rx_ring;
 
 
        int msg_enable;
index f133ff0b0b947c6ad6a76635ff5f159f6cad83bd..6b9acc7f94a32e12770fc4a3946d0876c8a5af11 100644 (file)
@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
 extern void e1000_down(struct e1000_adapter *adapter);
 extern void e1000_reset(struct e1000_adapter *adapter);
 extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_update_stats(struct e1000_adapter *adapter);
 
 struct e1000_stats {
@@ -91,7 +91,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
        { "rx_long_byte_count", E1000_STAT(stats.gorcl) },
        { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-       { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+       { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+       { "rx_header_split", E1000_STAT(rx_hdr_split) },
 };
 #define E1000_STATS_LEN        \
        sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -546,8 +547,10 @@ e1000_set_eeprom(struct net_device *netdev,
        ret_val = e1000_write_eeprom(hw, first_word,
                                     last_word - first_word + 1, eeprom_buff);
 
-       /* Update the checksum over the first part of the EEPROM if needed */
-       if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
+       /* Update the checksum over the first part of the EEPROM if needed 
+        * and flush shadow RAM for 82573 conrollers */
+       if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || 
+                               (hw->mac_type == e1000_82573)))
                e1000_update_eeprom_checksum(hw);
 
        kfree(eeprom_buff);
@@ -576,8 +579,8 @@ e1000_get_ringparam(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        e1000_mac_type mac_type = adapter->hw.mac_type;
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+       struct e1000_tx_ring *txdr = adapter->tx_ring;
+       struct e1000_rx_ring *rxdr = adapter->rx_ring;
 
        ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
                E1000_MAX_82544_RXD;
@@ -597,20 +600,40 @@ e1000_set_ringparam(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        e1000_mac_type mac_type = adapter->hw.mac_type;
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->rx_ring;
-       struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
-       int err;
+       struct e1000_tx_ring *txdr, *tx_old, *tx_new;
+       struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
+       int i, err, tx_ring_size, rx_ring_size;
+
+       tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+       rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+
+       if (netif_running(adapter->netdev))
+               e1000_down(adapter);
 
        tx_old = adapter->tx_ring;
        rx_old = adapter->rx_ring;
 
+       adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
+       if (!adapter->tx_ring) {
+               err = -ENOMEM;
+               goto err_setup_rx;
+       }
+       memset(adapter->tx_ring, 0, tx_ring_size);
+
+       adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
+       if (!adapter->rx_ring) {
+               kfree(adapter->tx_ring);
+               err = -ENOMEM;
+               goto err_setup_rx;
+       }
+       memset(adapter->rx_ring, 0, rx_ring_size);
+
+       txdr = adapter->tx_ring;
+       rxdr = adapter->rx_ring;
+
        if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       if(netif_running(adapter->netdev))
-               e1000_down(adapter);
-
        rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
        rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
                E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -621,11 +644,16 @@ e1000_set_ringparam(struct net_device *netdev,
                E1000_MAX_TXD : E1000_MAX_82544_TXD));
        E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
 
+       for (i = 0; i < adapter->num_queues; i++) {
+               txdr[i].count = txdr->count;
+               rxdr[i].count = rxdr->count;
+       }
+
        if(netif_running(adapter->netdev)) {
                /* Try to get new resources before deleting old */
-               if((err = e1000_setup_rx_resources(adapter)))
+               if ((err = e1000_setup_all_rx_resources(adapter)))
                        goto err_setup_rx;
-               if((err = e1000_setup_tx_resources(adapter)))
+               if ((err = e1000_setup_all_tx_resources(adapter)))
                        goto err_setup_tx;
 
                /* save the new, restore the old in order to free it,
@@ -635,8 +663,10 @@ e1000_set_ringparam(struct net_device *netdev,
                tx_new = adapter->tx_ring;
                adapter->rx_ring = rx_old;
                adapter->tx_ring = tx_old;
-               e1000_free_rx_resources(adapter);
-               e1000_free_tx_resources(adapter);
+               e1000_free_all_rx_resources(adapter);
+               e1000_free_all_tx_resources(adapter);
+               kfree(tx_old);
+               kfree(rx_old);
                adapter->rx_ring = rx_new;
                adapter->tx_ring = tx_new;
                if((err = e1000_up(adapter)))
@@ -645,7 +675,7 @@ e1000_set_ringparam(struct net_device *netdev,
 
        return 0;
 err_setup_tx:
-       e1000_free_rx_resources(adapter);
+       e1000_free_all_rx_resources(adapter);
 err_setup_rx:
        adapter->rx_ring = rx_old;
        adapter->tx_ring = tx_old;
@@ -696,6 +726,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
         * Some bits that get toggled are ignored.
         */
         switch (adapter->hw.mac_type) {
+       /* there are several bits on newer hardware that are r/w */
+       case e1000_82571:
+       case e1000_82572:
+               toggle = 0x7FFFF3FF;
+               break;
        case e1000_82573:
                toggle = 0x7FFFF033;
                break;
@@ -898,8 +933,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 static void
 e1000_free_desc_rings(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int i;
 
@@ -941,8 +976,8 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
 static int
 e1000_setup_desc_rings(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        uint32_t rctl;
        int size, i, ret_val;
@@ -1245,6 +1280,8 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
        case e1000_82541_rev_2:
        case e1000_82547:
        case e1000_82547_rev_2:
+       case e1000_82571:
+       case e1000_82572:
        case e1000_82573:
                return e1000_integrated_phy_loopback(adapter);
                break;
@@ -1340,8 +1377,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 static int
 e1000_run_loopback_test(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int i, j, k, l, lc, good_cnt, ret_val=0;
        unsigned long time;
@@ -1509,6 +1546,7 @@ e1000_diag_test(struct net_device *netdev,
                data[2] = 0;
                data[3] = 0;
        }
+       msleep_interruptible(4 * 1000);
 }
 
 static void
@@ -1625,7 +1663,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
        if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
                data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
 
-       if(adapter->hw.mac_type < e1000_82573) {
+       if(adapter->hw.mac_type < e1000_82571) {
                if(!adapter->blink_timer.function) {
                        init_timer(&adapter->blink_timer);
                        adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1739,6 +1777,7 @@ struct ethtool_ops e1000_ethtool_ops = {
        .phys_id                = e1000_phys_id,
        .get_stats_count        = e1000_get_stats_count,
        .get_ethtool_stats      = e1000_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 void e1000_set_ethtool_ops(struct net_device *netdev)
index 045f5426ab9a68c6af41690f450839d77dca0110..8fc876da43b43fafb5c0f6f7455856da013b68f0 100644 (file)
@@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
 
 static const
 uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
-    { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
-      22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
-      32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
-      43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
-      57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
-      73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
-      91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
-      108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+    { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+      0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+      6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+      21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
+      40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
+      60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
+      83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
+      104, 109, 114, 118, 121, 124};
 
 
 /******************************************************************************
@@ -286,7 +286,6 @@ e1000_set_mac_type(struct e1000_hw *hw)
     case E1000_DEV_ID_82546GB_FIBER:
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82546GB_PCIE:
-    case E1000_DEV_ID_82546GB_QUAD_COPPER:
         hw->mac_type = e1000_82546_rev_3;
         break;
     case E1000_DEV_ID_82541EI:
@@ -305,8 +304,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
     case E1000_DEV_ID_82547GI:
         hw->mac_type = e1000_82547_rev_2;
         break;
+    case E1000_DEV_ID_82571EB_COPPER:
+    case E1000_DEV_ID_82571EB_FIBER:
+    case E1000_DEV_ID_82571EB_SERDES:
+            hw->mac_type = e1000_82571;
+        break;
+    case E1000_DEV_ID_82572EI_COPPER:
+    case E1000_DEV_ID_82572EI_FIBER:
+    case E1000_DEV_ID_82572EI_SERDES:
+        hw->mac_type = e1000_82572;
+        break;
     case E1000_DEV_ID_82573E:
     case E1000_DEV_ID_82573E_IAMT:
+    case E1000_DEV_ID_82573L:
         hw->mac_type = e1000_82573;
         break;
     default:
@@ -315,6 +325,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
     }
 
     switch(hw->mac_type) {
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         hw->eeprom_semaphore_present = TRUE;
         /* fall through */
@@ -351,6 +363,8 @@ e1000_set_media_type(struct e1000_hw *hw)
     switch (hw->device_id) {
     case E1000_DEV_ID_82545GM_SERDES:
     case E1000_DEV_ID_82546GB_SERDES:
+    case E1000_DEV_ID_82571EB_SERDES:
+    case E1000_DEV_ID_82572EI_SERDES:
         hw->media_type = e1000_media_type_internal_serdes;
         break;
     default:
@@ -523,6 +537,8 @@ e1000_reset_hw(struct e1000_hw *hw)
             E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
             E1000_WRITE_FLUSH(hw);
             /* fall through */
+        case e1000_82571:
+        case e1000_82572:
             ret_val = e1000_get_auto_rd_done(hw);
             if(ret_val)
                 /* We don't want to continue accessing MAC registers. */
@@ -683,6 +699,9 @@ e1000_init_hw(struct e1000_hw *hw)
         switch (hw->mac_type) {
         default:
             break;
+        case e1000_82571:
+        case e1000_82572:
+            ctrl |= (1 << 22);
         case e1000_82573:
             ctrl |= E1000_TXDCTL_COUNT_DESC;
             break;
@@ -694,6 +713,26 @@ e1000_init_hw(struct e1000_hw *hw)
         e1000_enable_tx_pkt_filtering(hw); 
     }
 
+    switch (hw->mac_type) {
+    default:
+        break;
+    case e1000_82571:
+    case e1000_82572:
+        ctrl = E1000_READ_REG(hw, TXDCTL1);
+        ctrl &= ~E1000_TXDCTL_WTHRESH;
+        ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
+        ctrl |= (1 << 22);
+        E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+        break;
+    }
+
+
+
+    if (hw->mac_type == e1000_82573) {
+        uint32_t gcr = E1000_READ_REG(hw, GCR);
+        gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+        E1000_WRITE_REG(hw, GCR, gcr);
+    }
 
     /* Clear all of the statistics registers (clear on read).  It is
      * important that we do this after we have tried to establish link
@@ -878,6 +917,14 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_setup_fiber_serdes_link");
 
+    /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
+     * until explicitly turned off or a power cycle is performed.  A read to
+     * the register does not indicate its status.  Therefore, we ensure
+     * loopback mode is disabled during initialization.
+     */
+    if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
+        E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+
     /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
      * set when the optics detect a signal. On older adapters, it will be
      * cleared when there is a signal.  This applies to fiber media only.
@@ -2943,6 +2990,8 @@ e1000_phy_reset(struct e1000_hw *hw)
 
     switch (hw->mac_type) {
     case e1000_82541_rev_2:
+    case e1000_82571:
+    case e1000_82572:
         ret_val = e1000_phy_hw_reset(hw);
         if(ret_val)
             return ret_val;
@@ -2981,6 +3030,16 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_detect_gig_phy");
 
+    /* The 82571 firmware may still be configuring the PHY.  In this
+     * case, we cannot access the PHY until the configuration is done.  So
+     * we explicitly set the PHY values. */
+    if(hw->mac_type == e1000_82571 ||
+       hw->mac_type == e1000_82572) {
+        hw->phy_id = IGP01E1000_I_PHY_ID;
+        hw->phy_type = e1000_phy_igp_2;
+        return E1000_SUCCESS;
+    }
+
     /* Read the PHY ID Registers to identify which PHY is onboard. */
     ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
     if(ret_val)
@@ -3334,6 +3393,21 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
         eeprom->use_eerd = FALSE;
         eeprom->use_eewr = FALSE;
         break;
+    case e1000_82571:
+    case e1000_82572:
+        eeprom->type = e1000_eeprom_spi;
+        eeprom->opcode_bits = 8;
+        eeprom->delay_usec = 1;
+        if (eecd & E1000_EECD_ADDR_BITS) {
+            eeprom->page_size = 32;
+            eeprom->address_bits = 16;
+        } else {
+            eeprom->page_size = 8;
+            eeprom->address_bits = 8;
+        }
+        eeprom->use_eerd = FALSE;
+        eeprom->use_eewr = FALSE;
+        break;
     case e1000_82573:
         eeprom->type = e1000_eeprom_spi;
         eeprom->opcode_bits = 8;
@@ -3543,25 +3617,26 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
     eecd = E1000_READ_REG(hw, EECD);
 
     if (hw->mac_type != e1000_82573) {
-    /* Request EEPROM Access */
-    if(hw->mac_type > e1000_82544) {
-        eecd |= E1000_EECD_REQ;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        eecd = E1000_READ_REG(hw, EECD);
-        while((!(eecd & E1000_EECD_GNT)) &&
-              (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
-            i++;
-            udelay(5);
-            eecd = E1000_READ_REG(hw, EECD);
-        }
-        if(!(eecd & E1000_EECD_GNT)) {
-            eecd &= ~E1000_EECD_REQ;
+        /* Request EEPROM Access */
+        if(hw->mac_type > e1000_82544) {
+            eecd |= E1000_EECD_REQ;
             E1000_WRITE_REG(hw, EECD, eecd);
-            DEBUGOUT("Could not acquire EEPROM grant\n");
-            return -E1000_ERR_EEPROM;
+            eecd = E1000_READ_REG(hw, EECD);
+            while((!(eecd & E1000_EECD_GNT)) &&
+                  (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+                i++;
+                udelay(5);
+                eecd = E1000_READ_REG(hw, EECD);
+            }
+            if(!(eecd & E1000_EECD_GNT)) {
+                eecd &= ~E1000_EECD_REQ;
+                E1000_WRITE_REG(hw, EECD, eecd);
+                DEBUGOUT("Could not acquire EEPROM grant\n");
+                e1000_put_hw_eeprom_semaphore(hw);
+                return -E1000_ERR_EEPROM;
+            }
         }
     }
-    }
 
     /* Setup EEPROM for Read/Write */
 
@@ -4064,7 +4139,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
         return -E1000_ERR_EEPROM;
     }
 
-    /* 82573 reads only through eerd */
+    /* 82573 writes only through eewr */
     if(eeprom->use_eewr == TRUE)
         return e1000_write_eeprom_eewr(hw, offset, words, data);
 
@@ -4353,9 +4428,16 @@ e1000_read_mac_addr(struct e1000_hw * hw)
         hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
         hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
     }
-    if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
-       (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
+    switch (hw->mac_type) {
+    default:
+        break;
+    case e1000_82546:
+    case e1000_82546_rev_3:
+    case e1000_82571:
+        if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
+        break;
+    }
 
     for(i = 0; i < NODE_ADDRESS_SIZE; i++)
         hw->mac_addr[i] = hw->perm_mac_addr[i];
@@ -4385,6 +4467,12 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
     e1000_rar_set(hw, hw->mac_addr, 0);
 
     rar_num = E1000_RAR_ENTRIES;
+
+    /* Reserve a spot for the Locally Administered Address to work around
+     * an 82571 issue in which a reset on one port will reload the MAC on
+     * the other port. */
+    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+        rar_num -= 1;
     /* Zero out the other 15 receive addresses. */
     DEBUGOUT("Clearing RAR[1-15]\n");
     for(i = 1; i < rar_num; i++) {
@@ -4427,6 +4515,12 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
     /* Clear RAR[1-15] */
     DEBUGOUT(" Clearing RAR[1-15]\n");
     num_rar_entry = E1000_RAR_ENTRIES;
+    /* Reserve a spot for the Locally Administered Address to work around
+     * an 82571 issue in which a reset on one port will reload the MAC on
+     * the other port. */
+    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+        num_rar_entry -= 1;
+
     for(i = rar_used_count; i < num_rar_entry; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
         E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -4984,7 +5078,6 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
     temp = E1000_READ_REG(hw, ICTXQEC);
     temp = E1000_READ_REG(hw, ICTXQMTC);
     temp = E1000_READ_REG(hw, ICRXDMTC);
-
 }
 
 /******************************************************************************
@@ -5151,6 +5244,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
         hw->bus_speed = e1000_bus_speed_unknown;
         hw->bus_width = e1000_bus_width_unknown;
         break;
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         hw->bus_type = e1000_bus_type_pci_express;
         hw->bus_speed = e1000_bus_speed_2500;
@@ -5250,6 +5345,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
     int32_t ret_val;
     uint16_t agc_value = 0;
     uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+    uint16_t max_agc = 0;
     uint16_t i, phy_data;
     uint16_t cable_length;
 
@@ -5338,6 +5434,40 @@ e1000_get_cable_length(struct e1000_hw *hw,
                        IGP01E1000_AGC_RANGE) : 0;
         *max_length = e1000_igp_cable_length_table[agc_value] +
                       IGP01E1000_AGC_RANGE;
+    } else if (hw->phy_type == e1000_phy_igp_2) {
+        uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+                                                         {IGP02E1000_PHY_AGC_A,
+                                                          IGP02E1000_PHY_AGC_B,
+                                                          IGP02E1000_PHY_AGC_C,
+                                                          IGP02E1000_PHY_AGC_D};
+        /* Read the AGC registers for all channels */
+        for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
+            ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+            if (ret_val)
+                return ret_val;
+
+           /* Getting bits 15:9, which represent the combination of course and
+             * fine gain values.  The result is a number that can be put into
+             * the lookup table to obtain the approximate cable length. */
+            cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+                      IGP02E1000_AGC_LENGTH_MASK;
+
+            /* Remove min & max AGC values from calculation. */
+            if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
+                min_agc = cur_agc;
+           if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
+                max_agc = cur_agc;
+
+            agc_value += e1000_igp_2_cable_length_table[cur_agc];
+        }
+
+        agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
+        agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
+
+        /* Calculate cable length with the error range of +/- 10 meters. */
+        *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+                       (agc_value - IGP02E1000_AGC_RANGE) : 0;
+        *max_length = agc_value + IGP02E1000_AGC_RANGE;
     }
 
     return E1000_SUCCESS;
@@ -6465,6 +6595,8 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
     default:
         msec_delay(5);
         break;
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         while(timeout) {
             if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
@@ -6494,10 +6626,31 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
 int32_t
 e1000_get_phy_cfg_done(struct e1000_hw *hw)
 {
+    int32_t timeout = PHY_CFG_TIMEOUT;
+    uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
+
     DEBUGFUNC("e1000_get_phy_cfg_done");
 
-    /* Simply wait for 10ms */
-    msec_delay(10);
+    switch (hw->mac_type) {
+    default:
+        msec_delay(10);
+        break;
+    case e1000_82571:
+    case e1000_82572:
+        while (timeout) {
+            if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+                break;
+            else
+                msec_delay(1);
+            timeout--;
+        }
+
+        if (!timeout) {
+            DEBUGOUT("MNG configuration cycle has not completed.\n");
+            return -E1000_ERR_RESET;
+        }
+        break;
+    }
 
     return E1000_SUCCESS;
 }
@@ -6569,8 +6722,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
         return;
 
     swsm = E1000_READ_REG(hw, SWSM);
-    /* Release both semaphores. */
-    swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+        swsm &= ~(E1000_SWSM_SWESMBI);
     E1000_WRITE_REG(hw, SWSM, swsm);
 }
 
@@ -6606,6 +6758,8 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
      * if this is the case.  We read FWSM to determine the manageability mode.
      */
     switch (hw->mac_type) {
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         fwsm = E1000_READ_REG(hw, FWSM);
         if((fwsm & E1000_FWSM_MODE_MASK) != 0)
index 51c2b3a18b6f385f9c86698b7840cf70838025a0..4f2c196dc314cd68d79b9297e0b352c1118fa786 100644 (file)
@@ -57,6 +57,8 @@ typedef enum {
     e1000_82541_rev_2,
     e1000_82547,
     e1000_82547_rev_2,
+    e1000_82571,
+    e1000_82572,
     e1000_82573,
     e1000_num_macs
 } e1000_mac_type;
@@ -478,10 +480,16 @@ uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
 #define E1000_DEV_ID_82547EI             0x1019
+#define E1000_DEV_ID_82571EB_COPPER      0x105E
+#define E1000_DEV_ID_82571EB_FIBER       0x105F
+#define E1000_DEV_ID_82571EB_SERDES      0x1060
+#define E1000_DEV_ID_82572EI_COPPER      0x107D
+#define E1000_DEV_ID_82572EI_FIBER       0x107E
+#define E1000_DEV_ID_82572EI_SERDES      0x107F
 #define E1000_DEV_ID_82573E              0x108B
 #define E1000_DEV_ID_82573E_IAMT         0x108C
+#define E1000_DEV_ID_82573L              0x109A
 
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -833,6 +841,8 @@ struct e1000_ffvt_entry {
 #define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 #define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 
+#define E1000_DISABLE_SERDES_LOOPBACK   0x0400
+
 /* Register Set. (82543, 82544)
  *
  * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
@@ -853,6 +863,7 @@ struct e1000_ffvt_entry {
 #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
 #define E1000_FLA      0x0001C  /* Flash Access - RW */
 #define E1000_MDIC     0x00020  /* MDI Control - RW */
+#define E1000_SCTL     0x00024  /* SerDes Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
@@ -864,6 +875,12 @@ struct e1000_ffvt_entry {
 #define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
 #define E1000_IAM      0x000E0  /* Interrupt Acknowledge Auto Mask */
 #define E1000_RCTL     0x00100  /* RX Control - RW */
+#define E1000_RDTR1    0x02820  /* RX Delay Timer (1) - RW */
+#define E1000_RDBAL1   0x02900  /* RX Descriptor Base Address Low (1) - RW */
+#define E1000_RDBAH1   0x02904  /* RX Descriptor Base Address High (1) - RW */
+#define E1000_RDLEN1   0x02908  /* RX Descriptor Length (1) - RW */
+#define E1000_RDH1     0x02910  /* RX Descriptor Head (1) - RW */
+#define E1000_RDT1     0x02918  /* RX Descriptor Tail (1) - RW */
 #define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
 #define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
 #define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
@@ -895,6 +912,12 @@ struct e1000_ffvt_entry {
 #define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
 #define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
 #define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
+#define E1000_RDBAL0   E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
+#define E1000_RDBAH0   E1000_RDBAH /* RX Desc Base Address High (0) - RW */
+#define E1000_RDLEN0   E1000_RDLEN /* RX Desc Length (0) - RW */
+#define E1000_RDH0     E1000_RDH   /* RX Desc Head (0) - RW */
+#define E1000_RDT0     E1000_RDT   /* RX Desc Tail (0) - RW */
+#define E1000_RDTR0    E1000_RDTR  /* RX Delay Timer (0) - RW */
 #define E1000_RXDCTL   0x02828  /* RX Descriptor Control - RW */
 #define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
 #define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
@@ -980,15 +1003,15 @@ struct e1000_ffvt_entry {
 #define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
 #define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
 #define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC       0x4100  /* Interrupt Assertion Count */
-#define E1000_ICRXPTC   0x4104  /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC   0x4108  /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC   0x410C  /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC   0x4110  /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC   0x4118  /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC  0x411C  /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC  0x4120  /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC    0x4124  /* Interrupt Cause Receiver Overrun Count */
+#define E1000_IAC      0x04100  /* Interrupt Assertion Count */
+#define E1000_ICRXPTC  0x04104  /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC  0x04108  /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC  0x0410C  /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC  0x04110  /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC  0x04118  /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C  /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x04120  /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC   0x04124  /* Interrupt Cause Receiver Overrun Count */
 #define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
 #define E1000_RFCTL    0x05008  /* Receive Filter Control*/
 #define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
@@ -1018,6 +1041,14 @@ struct e1000_ffvt_entry {
 #define E1000_FWSM      0x05B54 /* FW Semaphore */
 #define E1000_FFLT_DBG  0x05F04 /* Debug Register */
 #define E1000_HICR      0x08F00 /* Host Inteface Control */
+
+/* RSS registers */
+#define E1000_CPUVEC    0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC      0x05818 /* Multiple Receive Control - RW */
+#define E1000_RETA      0x05C00 /* Redirection Table - RW Array */
+#define E1000_RSSRK     0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RSSIM     0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR     0x05868 /* RSS Interrupt Request */
 /* Register Set (82542)
  *
  * Some of the 82542 registers are located at different offsets than they are
@@ -1032,6 +1063,7 @@ struct e1000_ffvt_entry {
 #define E1000_82542_CTRL_EXT E1000_CTRL_EXT
 #define E1000_82542_FLA      E1000_FLA
 #define E1000_82542_MDIC     E1000_MDIC
+#define E1000_82542_SCTL     E1000_SCTL
 #define E1000_82542_FCAL     E1000_FCAL
 #define E1000_82542_FCAH     E1000_FCAH
 #define E1000_82542_FCT      E1000_FCT
@@ -1049,6 +1081,18 @@ struct e1000_ffvt_entry {
 #define E1000_82542_RDLEN    0x00118
 #define E1000_82542_RDH      0x00120
 #define E1000_82542_RDT      0x00128
+#define E1000_82542_RDTR0    E1000_82542_RDTR
+#define E1000_82542_RDBAL0   E1000_82542_RDBAL
+#define E1000_82542_RDBAH0   E1000_82542_RDBAH
+#define E1000_82542_RDLEN0   E1000_82542_RDLEN
+#define E1000_82542_RDH0     E1000_82542_RDH
+#define E1000_82542_RDT0     E1000_82542_RDT
+#define E1000_82542_RDTR1    0x00130
+#define E1000_82542_RDBAL1   0x00138
+#define E1000_82542_RDBAH1   0x0013C
+#define E1000_82542_RDLEN1   0x00140
+#define E1000_82542_RDH1     0x00148
+#define E1000_82542_RDT1     0x00150
 #define E1000_82542_FCRTH    0x00160
 #define E1000_82542_FCRTL    0x00168
 #define E1000_82542_FCTTV    E1000_FCTTV
@@ -1197,6 +1241,13 @@ struct e1000_ffvt_entry {
 #define E1000_82542_ICRXOC      E1000_ICRXOC
 #define E1000_82542_HICR        E1000_HICR
 
+#define E1000_82542_CPUVEC      E1000_CPUVEC
+#define E1000_82542_MRQC        E1000_MRQC
+#define E1000_82542_RETA        E1000_RETA
+#define E1000_82542_RSSRK       E1000_RSSRK
+#define E1000_82542_RSSIM       E1000_RSSIM
+#define E1000_82542_RSSIR       E1000_RSSIR
+
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
     uint64_t crcerrs;
@@ -1336,6 +1387,7 @@ struct e1000_hw {
     boolean_t serdes_link_down;
     boolean_t tbi_compatibility_en;
     boolean_t tbi_compatibility_on;
+    boolean_t laa_is_present;
     boolean_t phy_reset_disable;
     boolean_t fc_send_xon;
     boolean_t fc_strict_ieee;
@@ -1374,6 +1426,7 @@ struct e1000_hw {
 #define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
 #define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
+#define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
 #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
@@ -1491,6 +1544,8 @@ struct e1000_hw {
 #define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
 #define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
 #define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
+#define E1000_CTRL_EXT_CANC           0x04000000  /* Interrupt delay cancellation */
+#define E1000_CTRL_EXT_DRV_LOAD       0x10000000  /* Driver loaded bit for FW */
 #define E1000_CTRL_EXT_IAME           0x08000000  /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000  /* Clear Interrupt timers after IMS clear */
 
@@ -1524,6 +1579,7 @@ struct e1000_hw {
 #define E1000_LEDCTL_LED2_BLINK           0x00800000
 #define E1000_LEDCTL_LED3_MODE_MASK       0x0F000000
 #define E1000_LEDCTL_LED3_MODE_SHIFT      24
+#define E1000_LEDCTL_LED3_BLINK_RATE      0x20000000
 #define E1000_LEDCTL_LED3_IVRT            0x40000000
 #define E1000_LEDCTL_LED3_BLINK           0x80000000
 
@@ -1784,6 +1840,16 @@ struct e1000_hw {
 #define E1000_RXCSUM_IPPCSE    0x00001000   /* IP payload checksum enable */
 #define E1000_RXCSUM_PCSD      0x00002000   /* packet checksum disabled */
 
+/* Multiple Receive Queue Control */
+#define E1000_MRQC_ENABLE_MASK              0x00000003
+#define E1000_MRQC_ENABLE_RSS_2Q            0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT           0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK           0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP       0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4           0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP       0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX        0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6           0x00100000
 
 /* Definitions for power management and wakeup registers */
 /* Wake Up Control */
@@ -1928,6 +1994,7 @@ struct e1000_host_command_info {
 #define E1000_MDALIGN          4096
 
 #define E1000_GCR_BEM32                 0x00400000
+#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
 #define E1000_FACTPS_LAN0_VALID                     0x00000004
@@ -1980,6 +2047,7 @@ struct e1000_host_command_info {
 /* EEPROM Word Offsets */
 #define EEPROM_COMPAT                 0x0003
 #define EEPROM_ID_LED_SETTINGS        0x0004
+#define EEPROM_VERSION                0x0005
 #define EEPROM_SERDES_AMPLITUDE       0x0006 /* For SERDES output amplitude adjustment. */
 #define EEPROM_PHY_CLASS_WORD         0x0007
 #define EEPROM_INIT_CONTROL1_REG      0x000A
@@ -1990,6 +2058,8 @@ struct e1000_host_command_info {
 #define EEPROM_FLASH_VERSION          0x0032
 #define EEPROM_CHECKSUM_REG           0x003F
 
+#define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */
+
 /* Word definitions for ID LED Settings */
 #define ID_LED_RESERVED_0000 0x0000
 #define ID_LED_RESERVED_FFFF 0xFFFF
@@ -2108,6 +2178,8 @@ struct e1000_host_command_info {
 #define E1000_PBA_22K 0x0016
 #define E1000_PBA_24K 0x0018
 #define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_38K 0x0026
 #define E1000_PBA_40K 0x0028
 #define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
 
@@ -2592,11 +2664,11 @@ struct e1000_host_command_info {
 
 /* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
 #define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
 
 /* The precision error of the cable length is +/- 10 meters */
 #define IGP01E1000_AGC_RANGE    10
-#define IGP02E1000_AGC_RANGE    10
+#define IGP02E1000_AGC_RANGE    15
 
 /* IGP01E1000 PCS Initialization register */
 /* bits 3:6 in the PCS registers stores the channels polarity */
index ee687c902a20be52d0bdf95ef4fc58b03f5317a3..6b72f6acdd54eca353552cba53c111bff4efb66d 100644 (file)
@@ -43,7 +43,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION            "6.0.60-k2"DRIVERNAPI
+#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
@@ -80,6 +80,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
        INTEL_E1000_ETHERNET_DEVICE(0x1026),
        INTEL_E1000_ETHERNET_DEVICE(0x1027),
        INTEL_E1000_ETHERNET_DEVICE(0x1028),
+       INTEL_E1000_ETHERNET_DEVICE(0x105E),
+       INTEL_E1000_ETHERNET_DEVICE(0x105F),
+       INTEL_E1000_ETHERNET_DEVICE(0x1060),
        INTEL_E1000_ETHERNET_DEVICE(0x1075),
        INTEL_E1000_ETHERNET_DEVICE(0x1076),
        INTEL_E1000_ETHERNET_DEVICE(0x1077),
@@ -88,10 +91,13 @@ static struct pci_device_id e1000_pci_tbl[] = {
        INTEL_E1000_ETHERNET_DEVICE(0x107A),
        INTEL_E1000_ETHERNET_DEVICE(0x107B),
        INTEL_E1000_ETHERNET_DEVICE(0x107C),
+       INTEL_E1000_ETHERNET_DEVICE(0x107D),
+       INTEL_E1000_ETHERNET_DEVICE(0x107E),
+       INTEL_E1000_ETHERNET_DEVICE(0x107F),
        INTEL_E1000_ETHERNET_DEVICE(0x108A),
        INTEL_E1000_ETHERNET_DEVICE(0x108B),
        INTEL_E1000_ETHERNET_DEVICE(0x108C),
-       INTEL_E1000_ETHERNET_DEVICE(0x1099),
+       INTEL_E1000_ETHERNET_DEVICE(0x109A),
        /* required last entry */
        {0,}
 };
@@ -102,10 +108,18 @@ int e1000_up(struct e1000_adapter *adapter);
 void e1000_down(struct e1000_adapter *adapter);
 void e1000_reset(struct e1000_adapter *adapter);
 int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+                             struct e1000_tx_ring *txdr);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rxdr);
+void e1000_free_tx_resources(struct e1000_adapter *adapter,
+                             struct e1000_tx_ring *tx_ring);
+void e1000_free_rx_resources(struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rx_ring);
 void e1000_update_stats(struct e1000_adapter *adapter);
 
 /* Local Function Prototypes */
@@ -114,14 +128,22 @@ static int e1000_init_module(void);
 static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void __devexit e1000_remove(struct pci_dev *pdev);
+static int e1000_alloc_queues(struct e1000_adapter *adapter);
+#ifdef CONFIG_E1000_MQ
+static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
+#endif
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
 static int e1000_close(struct net_device *netdev);
 static void e1000_configure_tx(struct e1000_adapter *adapter);
 static void e1000_configure_rx(struct e1000_adapter *adapter);
 static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+                                struct e1000_tx_ring *tx_ring);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+                                struct e1000_rx_ring *rx_ring);
 static void e1000_set_multi(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
 static void e1000_watchdog(unsigned long data);
@@ -132,19 +154,26 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_tx_ring *tx_ring);
 #ifdef CONFIG_E1000_NAPI
-static int e1000_clean(struct net_device *netdev, int *budget);
+static int e1000_clean(struct net_device *poll_dev, int *budget);
 static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_rx_ring *rx_ring,
                                     int *work_done, int work_to_do);
 static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                                       struct e1000_rx_ring *rx_ring,
                                        int *work_done, int work_to_do);
 #else
-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_rx_ring *rx_ring);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                                       struct e1000_rx_ring *rx_ring);
 #endif
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+                                   struct e1000_rx_ring *rx_ring);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+                                      struct e1000_rx_ring *rx_ring);
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
                           int cmd);
@@ -172,6 +201,11 @@ static int e1000_resume(struct pci_dev *pdev);
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+#ifdef CONFIG_E1000_MQ
+/* for multiple Rx queues */
+void e1000_rx_schedule(void *data);
+#endif
+
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -289,7 +323,7 @@ int
 e1000_up(struct e1000_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       int err;
+       int i, err;
 
        /* hardware has been reset, we need to reload some things */
 
@@ -308,7 +342,8 @@ e1000_up(struct e1000_adapter *adapter)
        e1000_configure_tx(adapter);
        e1000_setup_rctl(adapter);
        e1000_configure_rx(adapter);
-       adapter->alloc_rx_buf(adapter);
+       for (i = 0; i < adapter->num_queues; i++)
+               adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
 
 #ifdef CONFIG_PCI_MSI
        if(adapter->hw.mac_type > e1000_82547_rev_2) {
@@ -344,6 +379,9 @@ e1000_down(struct e1000_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
 
        e1000_irq_disable(adapter);
+#ifdef CONFIG_E1000_MQ
+       while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
+#endif
        free_irq(adapter->pdev->irq, netdev);
 #ifdef CONFIG_PCI_MSI
        if(adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -363,11 +401,10 @@ e1000_down(struct e1000_adapter *adapter)
        netif_stop_queue(netdev);
 
        e1000_reset(adapter);
-       e1000_clean_tx_ring(adapter);
-       e1000_clean_rx_ring(adapter);
+       e1000_clean_all_tx_rings(adapter);
+       e1000_clean_all_rx_rings(adapter);
 
-       /* If WoL is not enabled
-        * and management mode is not IAMT
+       /* If WoL is not enabled and management mode is not IAMT
         * Power down the PHY so no link is implied when interface is down */
        if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
           adapter->hw.media_type == e1000_media_type_copper &&
@@ -398,6 +435,10 @@ e1000_reset(struct e1000_adapter *adapter)
        case e1000_82547_rev_2:
                pba = E1000_PBA_30K;
                break;
+       case e1000_82571:
+       case e1000_82572:
+               pba = E1000_PBA_38K;
+               break;
        case e1000_82573:
                pba = E1000_PBA_12K;
                break;
@@ -475,6 +516,7 @@ e1000_probe(struct pci_dev *pdev,
        struct net_device *netdev;
        struct e1000_adapter *adapter;
        unsigned long mmio_start, mmio_len;
+       uint32_t ctrl_ext;
        uint32_t swsm;
 
        static int cards_found = 0;
@@ -614,8 +656,9 @@ e1000_probe(struct pci_dev *pdev,
        if(e1000_read_mac_addr(&adapter->hw))
                DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
        memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+       memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
 
-       if(!is_valid_ether_addr(netdev->dev_addr)) {
+       if(!is_valid_ether_addr(netdev->perm_addr)) {
                DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
                err = -EIO;
                goto err_eeprom;
@@ -687,6 +730,12 @@ e1000_probe(struct pci_dev *pdev,
 
        /* Let firmware know the driver has taken over */
        switch(adapter->hw.mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+               E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+                               ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+               break;
        case e1000_82573:
                swsm = E1000_READ_REG(&adapter->hw, SWSM);
                E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -731,7 +780,11 @@ e1000_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
+       uint32_t ctrl_ext;
        uint32_t manc, swsm;
+#ifdef CONFIG_E1000_NAPI
+       int i;
+#endif
 
        flush_scheduled_work();
 
@@ -745,6 +798,12 @@ e1000_remove(struct pci_dev *pdev)
        }
 
        switch(adapter->hw.mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+               E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+                               ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+               break;
        case e1000_82573:
                swsm = E1000_READ_REG(&adapter->hw, SWSM);
                E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -756,13 +815,27 @@ e1000_remove(struct pci_dev *pdev)
        }
 
        unregister_netdev(netdev);
+#ifdef CONFIG_E1000_NAPI
+       for (i = 0; i < adapter->num_queues; i++)
+               __dev_put(&adapter->polling_netdev[i]);
+#endif
 
        if(!e1000_check_phy_reset_block(&adapter->hw))
                e1000_phy_hw_reset(&adapter->hw);
 
+       kfree(adapter->tx_ring);
+       kfree(adapter->rx_ring);
+#ifdef CONFIG_E1000_NAPI
+       kfree(adapter->polling_netdev);
+#endif
+
        iounmap(adapter->hw.hw_addr);
        pci_release_regions(pdev);
 
+#ifdef CONFIG_E1000_MQ
+       free_percpu(adapter->cpu_netdev);
+       free_percpu(adapter->cpu_tx_ring);
+#endif
        free_netdev(netdev);
 
        pci_disable_device(pdev);
@@ -783,6 +856,9 @@ e1000_sw_init(struct e1000_adapter *adapter)
        struct e1000_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
+#ifdef CONFIG_E1000_NAPI
+       int i;
+#endif
 
        /* PCI config space info */
 
@@ -840,13 +916,122 @@ e1000_sw_init(struct e1000_adapter *adapter)
                hw->master_slave = E1000_MASTER_SLAVE;
        }
 
+#ifdef CONFIG_E1000_MQ
+       /* Number of supported queues */
+       switch (hw->mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               adapter->num_queues = 2;
+               break;
+       default:
+               adapter->num_queues = 1;
+               break;
+       }
+       adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+#else
+       adapter->num_queues = 1;
+#endif
+
+       if (e1000_alloc_queues(adapter)) {
+               DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+               return -ENOMEM;
+       }
+
+#ifdef CONFIG_E1000_NAPI
+       for (i = 0; i < adapter->num_queues; i++) {
+               adapter->polling_netdev[i].priv = adapter;
+               adapter->polling_netdev[i].poll = &e1000_clean;
+               adapter->polling_netdev[i].weight = 64;
+               dev_hold(&adapter->polling_netdev[i]);
+               set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+       }
+#endif
+
+#ifdef CONFIG_E1000_MQ
+       e1000_setup_queue_mapping(adapter);
+#endif
+
        atomic_set(&adapter->irq_sem, 1);
        spin_lock_init(&adapter->stats_lock);
-       spin_lock_init(&adapter->tx_lock);
 
        return 0;
 }
 
+/**
+ * e1000_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time.  The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+
+static int __devinit
+e1000_alloc_queues(struct e1000_adapter *adapter)
+{
+       int size;
+
+       size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+       adapter->tx_ring = kmalloc(size, GFP_KERNEL);
+       if (!adapter->tx_ring)
+               return -ENOMEM;
+       memset(adapter->tx_ring, 0, size);
+
+       size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+       adapter->rx_ring = kmalloc(size, GFP_KERNEL);
+       if (!adapter->rx_ring) {
+               kfree(adapter->tx_ring);
+               return -ENOMEM;
+       }
+       memset(adapter->rx_ring, 0, size);
+
+#ifdef CONFIG_E1000_NAPI
+       size = sizeof(struct net_device) * adapter->num_queues;
+       adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
+       if (!adapter->polling_netdev) {
+               kfree(adapter->tx_ring);
+               kfree(adapter->rx_ring);
+               return -ENOMEM;
+       }
+       memset(adapter->polling_netdev, 0, size);
+#endif
+
+       return E1000_SUCCESS;
+}
+
+#ifdef CONFIG_E1000_MQ
+static void __devinit
+e1000_setup_queue_mapping(struct e1000_adapter *adapter)
+{
+       int i, cpu;
+
+       adapter->rx_sched_call_data.func = e1000_rx_schedule;
+       adapter->rx_sched_call_data.info = adapter->netdev;
+       cpus_clear(adapter->rx_sched_call_data.cpumask);
+
+       adapter->cpu_netdev = alloc_percpu(struct net_device *);
+       adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+
+       lock_cpu_hotplug();
+       i = 0;
+       for_each_online_cpu(cpu) {
+               *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+               /* This is incomplete because we'd like to assign separate
+                * physical cpus to these netdev polling structures and
+                * avoid saturating a subset of cpus.
+                */
+               if (i < adapter->num_queues) {
+                       *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
+                       adapter->cpu_for_queue[i] = cpu;
+               } else
+                       *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
+
+               i++;
+       }
+       unlock_cpu_hotplug();
+}
+#endif
+
 /**
  * e1000_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -868,12 +1053,12 @@ e1000_open(struct net_device *netdev)
 
        /* allocate transmit descriptors */
 
-       if((err = e1000_setup_tx_resources(adapter)))
+       if ((err = e1000_setup_all_tx_resources(adapter)))
                goto err_setup_tx;
 
        /* allocate receive descriptors */
 
-       if((err = e1000_setup_rx_resources(adapter)))
+       if ((err = e1000_setup_all_rx_resources(adapter)))
                goto err_setup_rx;
 
        if((err = e1000_up(adapter)))
@@ -887,9 +1072,9 @@ e1000_open(struct net_device *netdev)
        return E1000_SUCCESS;
 
 err_up:
-       e1000_free_rx_resources(adapter);
+       e1000_free_all_rx_resources(adapter);
 err_setup_rx:
-       e1000_free_tx_resources(adapter);
+       e1000_free_all_tx_resources(adapter);
 err_setup_tx:
        e1000_reset(adapter);
 
@@ -915,8 +1100,8 @@ e1000_close(struct net_device *netdev)
 
        e1000_down(adapter);
 
-       e1000_free_tx_resources(adapter);
-       e1000_free_rx_resources(adapter);
+       e1000_free_all_tx_resources(adapter);
+       e1000_free_all_rx_resources(adapter);
 
        if((adapter->hw.mng_cookie.status &
                          E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
@@ -951,14 +1136,15 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
 /**
  * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
  * @adapter: board private structure
+ * @txdr:    tx descriptor ring (for a specific queue) to setup
  *
  * Return 0 on success, negative on failure
  **/
 
 int
-e1000_setup_tx_resources(struct e1000_adapter *adapter)
+e1000_setup_tx_resources(struct e1000_adapter *adapter,
+                         struct e1000_tx_ring *txdr)
 {
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int size;
 
@@ -970,6 +1156,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
                return -ENOMEM;
        }
        memset(txdr->buffer_info, 0, size);
+       memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
 
        /* round up to nearest 4K */
 
@@ -1018,10 +1205,40 @@ setup_tx_desc_die:
 
        txdr->next_to_use = 0;
        txdr->next_to_clean = 0;
+       spin_lock_init(&txdr->tx_lock);
 
        return 0;
 }
 
+/**
+ * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
+ *                               (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+{
+       int i, err = 0;
+
+       for (i = 0; i < adapter->num_queues; i++) {
+               err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+               if (err) {
+                       DPRINTK(PROBE, ERR,
+                               "Allocation for Tx Queue %u failed\n", i);
+                       break;
+               }
+       }
+
+       return err;
+}
+
 /**
  * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
  * @adapter: board private structure
@@ -1032,23 +1249,43 @@ setup_tx_desc_die:
 static void
 e1000_configure_tx(struct e1000_adapter *adapter)
 {
-       uint64_t tdba = adapter->tx_ring.dma;
-       uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
-       uint32_t tctl, tipg;
-
-       E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
-       E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
-
-       E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
+       uint64_t tdba;
+       struct e1000_hw *hw = &adapter->hw;
+       uint32_t tdlen, tctl, tipg, tarc;
 
        /* Setup the HW Tx Head and Tail descriptor pointers */
 
-       E1000_WRITE_REG(&adapter->hw, TDH, 0);
-       E1000_WRITE_REG(&adapter->hw, TDT, 0);
+       switch (adapter->num_queues) {
+       case 2:
+               tdba = adapter->tx_ring[1].dma;
+               tdlen = adapter->tx_ring[1].count *
+                       sizeof(struct e1000_tx_desc);
+               E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
+               E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
+               E1000_WRITE_REG(hw, TDLEN1, tdlen);
+               E1000_WRITE_REG(hw, TDH1, 0);
+               E1000_WRITE_REG(hw, TDT1, 0);
+               adapter->tx_ring[1].tdh = E1000_TDH1;
+               adapter->tx_ring[1].tdt = E1000_TDT1;
+               /* Fall Through */
+       case 1:
+       default:
+               tdba = adapter->tx_ring[0].dma;
+               tdlen = adapter->tx_ring[0].count *
+                       sizeof(struct e1000_tx_desc);
+               E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+               E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+               E1000_WRITE_REG(hw, TDLEN, tdlen);
+               E1000_WRITE_REG(hw, TDH, 0);
+               E1000_WRITE_REG(hw, TDT, 0);
+               adapter->tx_ring[0].tdh = E1000_TDH;
+               adapter->tx_ring[0].tdt = E1000_TDT;
+               break;
+       }
 
        /* Set the default values for the Tx Inter Packet Gap timer */
 
-       switch (adapter->hw.mac_type) {
+       switch (hw->mac_type) {
        case e1000_82542_rev2_0:
        case e1000_82542_rev2_1:
                tipg = DEFAULT_82542_TIPG_IPGT;
@@ -1056,67 +1293,81 @@ e1000_configure_tx(struct e1000_adapter *adapter)
                tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
                break;
        default:
-               if(adapter->hw.media_type == e1000_media_type_fiber ||
-                  adapter->hw.media_type == e1000_media_type_internal_serdes)
+               if (hw->media_type == e1000_media_type_fiber ||
+                   hw->media_type == e1000_media_type_internal_serdes)
                        tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
                else
                        tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
                tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
                tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
        }
-       E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
+       E1000_WRITE_REG(hw, TIPG, tipg);
 
        /* Set the Tx Interrupt Delay register */
 
-       E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
-       if(adapter->hw.mac_type >= e1000_82540)
-               E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay);
+       E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+       if (hw->mac_type >= e1000_82540)
+               E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
 
        /* Program the Transmit Control Register */
 
-       tctl = E1000_READ_REG(&adapter->hw, TCTL);
+       tctl = E1000_READ_REG(hw, TCTL);
 
        tctl &= ~E1000_TCTL_CT;
-       tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
+       tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
                (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
 
-       E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+       E1000_WRITE_REG(hw, TCTL, tctl);
 
-       e1000_config_collision_dist(&adapter->hw);
+       if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
+               tarc = E1000_READ_REG(hw, TARC0);
+               tarc |= ((1 << 25) | (1 << 21));
+               E1000_WRITE_REG(hw, TARC0, tarc);
+               tarc = E1000_READ_REG(hw, TARC1);
+               tarc |= (1 << 25);
+               if (tctl & E1000_TCTL_MULR)
+                       tarc &= ~(1 << 28);
+               else
+                       tarc |= (1 << 28);
+               E1000_WRITE_REG(hw, TARC1, tarc);
+       }
+
+       e1000_config_collision_dist(hw);
 
        /* Setup Transmit Descriptor Settings for eop descriptor */
        adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
                E1000_TXD_CMD_IFCS;
 
-       if(adapter->hw.mac_type < e1000_82543)
+       if (hw->mac_type < e1000_82543)
                adapter->txd_cmd |= E1000_TXD_CMD_RPS;
        else
                adapter->txd_cmd |= E1000_TXD_CMD_RS;
 
        /* Cache if we're 82544 running in PCI-X because we'll
         * need this to apply a workaround later in the send path. */
-       if(adapter->hw.mac_type == e1000_82544 &&
-          adapter->hw.bus_type == e1000_bus_type_pcix)
+       if (hw->mac_type == e1000_82544 &&
+           hw->bus_type == e1000_bus_type_pcix)
                adapter->pcix_82544 = 1;
 }
 
 /**
  * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
  * @adapter: board private structure
+ * @rxdr:    rx descriptor ring (for a specific queue) to setup
  *
  * Returns 0 on success, negative on failure
  **/
 
 int
-e1000_setup_rx_resources(struct e1000_adapter *adapter)
+e1000_setup_rx_resources(struct e1000_adapter *adapter,
+                         struct e1000_rx_ring *rxdr)
 {
-       struct e1000_desc_ring *rxdr = &adapter->rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int size, desc_len;
 
        size = sizeof(struct e1000_buffer) * rxdr->count;
        rxdr->buffer_info = vmalloc(size);
-       if(!rxdr->buffer_info) {
+       if (!rxdr->buffer_info) {
                DPRINTK(PROBE, ERR,
                "Unable to allocate memory for the receive descriptor ring\n");
                return -ENOMEM;
@@ -1156,13 +1407,13 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
 
        rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
-       if(!rxdr->desc) {
+       if (!rxdr->desc) {
+               DPRINTK(PROBE, ERR,
+               "Unable to allocate memory for the receive descriptor ring\n");
 setup_rx_desc_die:
                vfree(rxdr->buffer_info);
                kfree(rxdr->ps_page);
                kfree(rxdr->ps_page_dma);
-               DPRINTK(PROBE, ERR,
-               "Unable to allocate memory for the receive descriptor ring\n");
                return -ENOMEM;
        }
 
@@ -1174,9 +1425,12 @@ setup_rx_desc_die:
                                     "at %p\n", rxdr->size, rxdr->desc);
                /* Try again, without freeing the previous */
                rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
-               if(!rxdr->desc) {
                /* Failed allocation, critical failure */
+               if (!rxdr->desc) {
                        pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+                       DPRINTK(PROBE, ERR,
+                               "Unable to allocate memory "
+                               "for the receive descriptor ring\n");
                        goto setup_rx_desc_die;
                }
 
@@ -1188,10 +1442,7 @@ setup_rx_desc_die:
                        DPRINTK(PROBE, ERR,
                                "Unable to allocate aligned memory "
                                "for the receive descriptor ring\n");
-                       vfree(rxdr->buffer_info);
-                       kfree(rxdr->ps_page);
-                       kfree(rxdr->ps_page_dma);
-                       return -ENOMEM;
+                       goto setup_rx_desc_die;
                } else {
                        /* Free old allocation, new allocation was successful */
                        pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
@@ -1205,16 +1456,49 @@ setup_rx_desc_die:
        return 0;
 }
 
+/**
+ * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
+ *                               (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+{
+       int i, err = 0;
+
+       for (i = 0; i < adapter->num_queues; i++) {
+               err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+               if (err) {
+                       DPRINTK(PROBE, ERR,
+                               "Allocation for Rx Queue %u failed\n", i);
+                       break;
+               }
+       }
+
+       return err;
+}
+
 /**
  * e1000_setup_rctl - configure the receive control registers
  * @adapter: Board private structure
  **/
-
+#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+                       (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
 static void
 e1000_setup_rctl(struct e1000_adapter *adapter)
 {
        uint32_t rctl, rfctl;
        uint32_t psrctl = 0;
+#ifdef CONFIG_E1000_PACKET_SPLIT
+       uint32_t pages = 0;
+#endif
 
        rctl = E1000_READ_REG(&adapter->hw, RCTL);
 
@@ -1235,7 +1519,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                rctl |= E1000_RCTL_LPE;
 
        /* Setup buffer sizes */
-       if(adapter->hw.mac_type == e1000_82573) {
+       if(adapter->hw.mac_type >= e1000_82571) {
                /* We can now specify buffers in 1K increments.
                 * BSIZE and BSEX are ignored in this case. */
                rctl |= adapter->rx_buffer_len << 0x11;
@@ -1268,11 +1552,14 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
         * followed by the page buffers.  Therefore, skb->data is
         * sized to hold the largest protocol header.
         */
-       adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2) 
-                         && (adapter->netdev->mtu 
-                             < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+       pages = PAGE_USE_COUNT(adapter->netdev->mtu);
+       if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) &&
+           PAGE_SIZE <= 16384)
+               adapter->rx_ps_pages = pages;
+       else
+               adapter->rx_ps_pages = 0;
 #endif
-       if(adapter->rx_ps) {
+       if (adapter->rx_ps_pages) {
                /* Configure extra packet-split registers */
                rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
                rfctl |= E1000_RFCTL_EXTEN;
@@ -1284,12 +1571,19 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                
                psrctl |= adapter->rx_ps_bsize0 >>
                        E1000_PSRCTL_BSIZE0_SHIFT;
-               psrctl |= PAGE_SIZE >>
-                       E1000_PSRCTL_BSIZE1_SHIFT;
-               psrctl |= PAGE_SIZE <<
-                       E1000_PSRCTL_BSIZE2_SHIFT;
-               psrctl |= PAGE_SIZE <<
-                       E1000_PSRCTL_BSIZE3_SHIFT;
+
+               switch (adapter->rx_ps_pages) {
+               case 3:
+                       psrctl |= PAGE_SIZE <<
+                               E1000_PSRCTL_BSIZE3_SHIFT;
+               case 2:
+                       psrctl |= PAGE_SIZE <<
+                               E1000_PSRCTL_BSIZE2_SHIFT;
+               case 1:
+                       psrctl |= PAGE_SIZE >>
+                               E1000_PSRCTL_BSIZE1_SHIFT;
+                       break;
+               }
 
                E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
        }
@@ -1307,91 +1601,181 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
 static void
 e1000_configure_rx(struct e1000_adapter *adapter)
 {
-       uint64_t rdba = adapter->rx_ring.dma;
-       uint32_t rdlen, rctl, rxcsum;
+       uint64_t rdba;
+       struct e1000_hw *hw = &adapter->hw;
+       uint32_t rdlen, rctl, rxcsum, ctrl_ext;
+#ifdef CONFIG_E1000_MQ
+       uint32_t reta, mrqc;
+       int i;
+#endif
 
-       if(adapter->rx_ps) {
-               rdlen = adapter->rx_ring.count *
+       if (adapter->rx_ps_pages) {
+               rdlen = adapter->rx_ring[0].count *
                        sizeof(union e1000_rx_desc_packet_split);
                adapter->clean_rx = e1000_clean_rx_irq_ps;
                adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
        } else {
-               rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+               rdlen = adapter->rx_ring[0].count *
+                       sizeof(struct e1000_rx_desc);
                adapter->clean_rx = e1000_clean_rx_irq;
                adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
        }
 
        /* disable receives while setting up the descriptors */
-       rctl = E1000_READ_REG(&adapter->hw, RCTL);
-       E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+       rctl = E1000_READ_REG(hw, RCTL);
+       E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
 
        /* set the Receive Delay Timer Register */
-       E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+       E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
 
-       if(adapter->hw.mac_type >= e1000_82540) {
-               E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
+       if (hw->mac_type >= e1000_82540) {
+               E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
                if(adapter->itr > 1)
-                       E1000_WRITE_REG(&adapter->hw, ITR,
+                       E1000_WRITE_REG(hw, ITR,
                                1000000000 / (adapter->itr * 256));
        }
 
-       /* Setup the Base and Length of the Rx Descriptor Ring */
-       E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
-       E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
+       if (hw->mac_type >= e1000_82571) {
+               /* Reset delay timers after every interrupt */
+               ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+               ctrl_ext |= E1000_CTRL_EXT_CANC;
+               E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       /* Setup the HW Rx Head and Tail Descriptor Pointers and
+        * the Base and Length of the Rx Descriptor Ring */
+       switch (adapter->num_queues) {
+#ifdef CONFIG_E1000_MQ
+       case 2:
+               rdba = adapter->rx_ring[1].dma;
+               E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
+               E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
+               E1000_WRITE_REG(hw, RDLEN1, rdlen);
+               E1000_WRITE_REG(hw, RDH1, 0);
+               E1000_WRITE_REG(hw, RDT1, 0);
+               adapter->rx_ring[1].rdh = E1000_RDH1;
+               adapter->rx_ring[1].rdt = E1000_RDT1;
+               /* Fall Through */
+#endif
+       case 1:
+       default:
+               rdba = adapter->rx_ring[0].dma;
+               E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+               E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+               E1000_WRITE_REG(hw, RDLEN, rdlen);
+               E1000_WRITE_REG(hw, RDH, 0);
+               E1000_WRITE_REG(hw, RDT, 0);
+               adapter->rx_ring[0].rdh = E1000_RDH;
+               adapter->rx_ring[0].rdt = E1000_RDT;
+               break;
+       }
+
+#ifdef CONFIG_E1000_MQ
+       if (adapter->num_queues > 1) {
+               uint32_t random[10];
+
+               get_random_bytes(&random[0], 40);
+
+               if (hw->mac_type <= e1000_82572) {
+                       E1000_WRITE_REG(hw, RSSIR, 0);
+                       E1000_WRITE_REG(hw, RSSIM, 0);
+               }
+
+               switch (adapter->num_queues) {
+               case 2:
+               default:
+                       reta = 0x00800080;
+                       mrqc = E1000_MRQC_ENABLE_RSS_2Q;
+                       break;
+               }
+
+               /* Fill out redirection table */
+               for (i = 0; i < 32; i++)
+                       E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
+               /* Fill out hash function seeds */
+               for (i = 0; i < 10; i++)
+                       E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
+
+               mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+                        E1000_MRQC_RSS_FIELD_IPV4_TCP);
+               E1000_WRITE_REG(hw, MRQC, mrqc);
+       }
 
-       E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
+       /* Multiqueue and packet checksumming are mutually exclusive. */
+       if (hw->mac_type >= e1000_82571) {
+               rxcsum = E1000_READ_REG(hw, RXCSUM);
+               rxcsum |= E1000_RXCSUM_PCSD;
+               E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+       }
 
-       /* Setup the HW Rx Head and Tail Descriptor Pointers */
-       E1000_WRITE_REG(&adapter->hw, RDH, 0);
-       E1000_WRITE_REG(&adapter->hw, RDT, 0);
+#else
 
        /* Enable 82543 Receive Checksum Offload for TCP and UDP */
-       if(adapter->hw.mac_type >= e1000_82543) {
-               rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
+       if (hw->mac_type >= e1000_82543) {
+               rxcsum = E1000_READ_REG(hw, RXCSUM);
                if(adapter->rx_csum == TRUE) {
                        rxcsum |= E1000_RXCSUM_TUOFL;
 
-                       /* Enable 82573 IPv4 payload checksum for UDP fragments
+                       /* Enable 82571 IPv4 payload checksum for UDP fragments
                         * Must be used in conjunction with packet-split. */
-                       if((adapter->hw.mac_type > e1000_82547_rev_2) && 
-                          (adapter->rx_ps)) {
+                       if ((hw->mac_type >= e1000_82571) && 
+                          (adapter->rx_ps_pages)) {
                                rxcsum |= E1000_RXCSUM_IPPCSE;
                        }
                } else {
                        rxcsum &= ~E1000_RXCSUM_TUOFL;
                        /* don't need to clear IPPCSE as it defaults to 0 */
                }
-               E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
+               E1000_WRITE_REG(hw, RXCSUM, rxcsum);
        }
+#endif /* CONFIG_E1000_MQ */
 
-       if (adapter->hw.mac_type == e1000_82573)
-               E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+       if (hw->mac_type == e1000_82573)
+               E1000_WRITE_REG(hw, ERT, 0x0100);
 
        /* Enable Receives */
-       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+       E1000_WRITE_REG(hw, RCTL, rctl);
 }
 
 /**
- * e1000_free_tx_resources - Free Tx Resources
+ * e1000_free_tx_resources - Free Tx Resources per Queue
  * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring for a specific queue
  *
  * Free all transmit software resources
  **/
 
 void
-e1000_free_tx_resources(struct e1000_adapter *adapter)
+e1000_free_tx_resources(struct e1000_adapter *adapter,
+                        struct e1000_tx_ring *tx_ring)
 {
        struct pci_dev *pdev = adapter->pdev;
 
-       e1000_clean_tx_ring(adapter);
+       e1000_clean_tx_ring(adapter, tx_ring);
+
+       vfree(tx_ring->buffer_info);
+       tx_ring->buffer_info = NULL;
 
-       vfree(adapter->tx_ring.buffer_info);
-       adapter->tx_ring.buffer_info = NULL;
+       pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+
+       tx_ring->desc = NULL;
+}
 
-       pci_free_consistent(pdev, adapter->tx_ring.size,
-                           adapter->tx_ring.desc, adapter->tx_ring.dma);
+/**
+ * e1000_free_all_tx_resources - Free Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+void
+e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+{
+       int i;
 
-       adapter->tx_ring.desc = NULL;
+       for (i = 0; i < adapter->num_queues; i++)
+               e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
 static inline void
@@ -1414,21 +1798,22 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
 /**
  * e1000_clean_tx_ring - Free Tx Buffers
  * @adapter: board private structure
+ * @tx_ring: ring to be cleaned
  **/
 
 static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter)
+e1000_clean_tx_ring(struct e1000_adapter *adapter,
+                    struct e1000_tx_ring *tx_ring)
 {
-       struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
        struct e1000_buffer *buffer_info;
        unsigned long size;
        unsigned int i;
 
        /* Free all the Tx ring sk_buffs */
 
-       if (likely(adapter->previous_buffer_info.skb != NULL)) {
+       if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
                e1000_unmap_and_free_tx_resource(adapter,
-                               &adapter->previous_buffer_info);
+                               &tx_ring->previous_buffer_info);
        }
 
        for(i = 0; i < tx_ring->count; i++) {
@@ -1446,24 +1831,39 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
        tx_ring->next_to_use = 0;
        tx_ring->next_to_clean = 0;
 
-       E1000_WRITE_REG(&adapter->hw, TDH, 0);
-       E1000_WRITE_REG(&adapter->hw, TDT, 0);
+       writel(0, adapter->hw.hw_addr + tx_ring->tdh);
+       writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+}
+
+/**
+ * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->num_queues; i++)
+               e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
 }
 
 /**
  * e1000_free_rx_resources - Free Rx Resources
  * @adapter: board private structure
+ * @rx_ring: ring to clean the resources from
  *
  * Free all receive software resources
  **/
 
 void
-e1000_free_rx_resources(struct e1000_adapter *adapter)
+e1000_free_rx_resources(struct e1000_adapter *adapter,
+                        struct e1000_rx_ring *rx_ring)
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        struct pci_dev *pdev = adapter->pdev;
 
-       e1000_clean_rx_ring(adapter);
+       e1000_clean_rx_ring(adapter, rx_ring);
 
        vfree(rx_ring->buffer_info);
        rx_ring->buffer_info = NULL;
@@ -1478,14 +1878,31 @@ e1000_free_rx_resources(struct e1000_adapter *adapter)
 }
 
 /**
- * e1000_clean_rx_ring - Free Rx Buffers
+ * e1000_free_all_rx_resources - Free Rx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->num_queues; i++)
+               e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
+}
+
+/**
+ * e1000_clean_rx_ring - Free Rx Buffers per Queue
  * @adapter: board private structure
+ * @rx_ring: ring to free buffers from
  **/
 
 static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter)
+e1000_clean_rx_ring(struct e1000_adapter *adapter,
+                    struct e1000_rx_ring *rx_ring)
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        struct e1000_buffer *buffer_info;
        struct e1000_ps_page *ps_page;
        struct e1000_ps_page_dma *ps_page_dma;
@@ -1508,7 +1925,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
                        dev_kfree_skb(buffer_info->skb);
                        buffer_info->skb = NULL;
 
-                       for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+                       for(j = 0; j < adapter->rx_ps_pages; j++) {
                                if(!ps_page->ps_page[j]) break;
                                pci_unmap_single(pdev,
                                                 ps_page_dma->ps_page_dma[j],
@@ -1534,8 +1951,22 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
 
-       E1000_WRITE_REG(&adapter->hw, RDH, 0);
-       E1000_WRITE_REG(&adapter->hw, RDT, 0);
+       writel(0, adapter->hw.hw_addr + rx_ring->rdh);
+       writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+}
+
+/**
+ * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->num_queues; i++)
+               e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
 }
 
 /* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1556,7 +1987,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
        mdelay(5);
 
        if(netif_running(netdev))
-               e1000_clean_rx_ring(adapter);
+               e1000_clean_all_rx_rings(adapter);
 }
 
 static void
@@ -1576,7 +2007,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
 
        if(netif_running(netdev)) {
                e1000_configure_rx(adapter);
-               e1000_alloc_rx_buffers(adapter);
+               e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
        }
 }
 
@@ -1607,6 +2038,22 @@ e1000_set_mac(struct net_device *netdev, void *p)
 
        e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
 
+       /* With 82571 controllers, LAA may be overwritten (with the default)
+        * due to controller reset from the other port. */
+       if (adapter->hw.mac_type == e1000_82571) {
+               /* activate the work around */
+               adapter->hw.laa_is_present = 1;
+
+               /* Hold a copy of the LAA in RAR[14] This is done so that 
+                * between the time RAR[0] gets clobbered  and the time it 
+                * gets fixed (in e1000_watchdog), the actual LAA is in one 
+                * of the RARs and no incoming packets directed to this port
+                * are dropped. Eventaully the LAA will be in RAR[0] and 
+                * RAR[14] */
+               e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 
+                                       E1000_RAR_ENTRIES - 1);
+       }
+
        if(adapter->hw.mac_type == e1000_82542_rev2_0)
                e1000_leave_82542_rst(adapter);
 
@@ -1629,12 +2076,13 @@ e1000_set_multi(struct net_device *netdev)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
        struct dev_mc_list *mc_ptr;
-       unsigned long flags;
        uint32_t rctl;
        uint32_t hash_value;
-       int i;
+       int i, rar_entries = E1000_RAR_ENTRIES;
 
-       spin_lock_irqsave(&adapter->tx_lock, flags);
+       /* reserve RAR[14] for LAA over-write work-around */
+       if (adapter->hw.mac_type == e1000_82571)
+               rar_entries--;
 
        /* Check for Promiscuous and All Multicast modes */
 
@@ -1659,11 +2107,12 @@ e1000_set_multi(struct net_device *netdev)
        /* load the first 14 multicast address into the exact filters 1-14
         * RAR 0 is used for the station MAC adddress
         * if there are not 14 addresses, go ahead and clear the filters
+        * -- with 82571 controllers only 0-13 entries are filled here
         */
        mc_ptr = netdev->mc_list;
 
-       for(i = 1; i < E1000_RAR_ENTRIES; i++) {
-               if(mc_ptr) {
+       for(i = 1; i < rar_entries; i++) {
+               if (mc_ptr) {
                        e1000_rar_set(hw, mc_ptr->dmi_addr, i);
                        mc_ptr = mc_ptr->next;
                } else {
@@ -1686,8 +2135,6 @@ e1000_set_multi(struct net_device *netdev)
 
        if(hw->mac_type == e1000_82542_rev2_0)
                e1000_leave_82542_rst(adapter);
-
-       spin_unlock_irqrestore(&adapter->tx_lock, flags);
 }
 
 /* Need to wait a few seconds after link up to get diagnostic information from
@@ -1759,7 +2206,7 @@ static void
 e1000_watchdog_task(struct e1000_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
+       struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
        uint32_t link;
 
        e1000_check_for_link(&adapter->hw);
@@ -1818,8 +2265,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 
        e1000_update_adaptive(&adapter->hw);
 
-       if(!netif_carrier_ok(netdev)) {
-               if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
+       if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+               if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
                        /* We've lost link, so the controller stops DMA,
                         * but we've got queued Tx work that's never going
                         * to get done, so reset controller to flush Tx.
@@ -1847,6 +2294,11 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
        /* Force detection of hung controller every watchdog period */
        adapter->detect_tx_hung = TRUE;
 
+       /* With 82571 controllers, LAA may be overwritten due to controller 
+        * reset from the other port. Set the appropriate LAA in RAR[0] */
+       if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
+               e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+
        /* Reset the timer */
        mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
@@ -1859,7 +2311,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 #define E1000_TX_FLAGS_VLAN_SHIFT      16
 
 static inline int
-e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+          struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
        struct e1000_context_desc *context_desc;
@@ -1910,8 +2363,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
                cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
                               E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
 
-               i = adapter->tx_ring.next_to_use;
-               context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+               i = tx_ring->next_to_use;
+               context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
 
                context_desc->lower_setup.ip_fields.ipcss  = ipcss;
                context_desc->lower_setup.ip_fields.ipcso  = ipcso;
@@ -1923,8 +2376,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
                context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
                context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
-               if(++i == adapter->tx_ring.count) i = 0;
-               adapter->tx_ring.next_to_use = i;
+               if (++i == tx_ring->count) i = 0;
+               tx_ring->next_to_use = i;
 
                return 1;
        }
@@ -1934,7 +2387,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 }
 
 static inline boolean_t
-e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+              struct sk_buff *skb)
 {
        struct e1000_context_desc *context_desc;
        unsigned int i;
@@ -1943,8 +2397,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
        if(likely(skb->ip_summed == CHECKSUM_HW)) {
                css = skb->h.raw - skb->data;
 
-               i = adapter->tx_ring.next_to_use;
-               context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+               i = tx_ring->next_to_use;
+               context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
 
                context_desc->upper_setup.tcp_fields.tucss = css;
                context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
@@ -1952,8 +2406,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
                context_desc->tcp_seg_setup.data = 0;
                context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
-               if(unlikely(++i == adapter->tx_ring.count)) i = 0;
-               adapter->tx_ring.next_to_use = i;
+               if (unlikely(++i == tx_ring->count)) i = 0;
+               tx_ring->next_to_use = i;
 
                return TRUE;
        }
@@ -1965,11 +2419,10 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
 #define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
 
 static inline int
-e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
-       unsigned int first, unsigned int max_per_txd,
-       unsigned int nr_frags, unsigned int mss)
+e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+             struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
+             unsigned int nr_frags, unsigned int mss)
 {
-       struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
        struct e1000_buffer *buffer_info;
        unsigned int len = skb->len;
        unsigned int offset = 0, size, count = 0, i;
@@ -2065,9 +2518,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 }
 
 static inline void
-e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
+e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+               int tx_flags, int count)
 {
-       struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
        struct e1000_tx_desc *tx_desc = NULL;
        struct e1000_buffer *buffer_info;
        uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -2113,7 +2566,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
        wmb();
 
        tx_ring->next_to_use = i;
-       E1000_WRITE_REG(&adapter->hw, TDT, i);
+       writel(i, adapter->hw.hw_addr + tx_ring->tdt);
 }
 
 /**
@@ -2206,6 +2659,7 @@ static int
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
+       struct e1000_tx_ring *tx_ring;
        unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
        unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
        unsigned int tx_flags = 0;
@@ -2218,7 +2672,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int f;
        len -= skb->data_len;
 
-       if(unlikely(skb->len <= 0)) {
+#ifdef CONFIG_E1000_MQ
+       tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#else
+       tx_ring = adapter->tx_ring;
+#endif
+
+       if (unlikely(skb->len <= 0)) {
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
@@ -2262,21 +2722,42 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if(adapter->pcix_82544)
                count += nr_frags;
 
-       local_irq_save(flags); 
-       if (!spin_trylock(&adapter->tx_lock)) { 
-               /* Collision - tell upper layer to requeue */ 
-               local_irq_restore(flags); 
-               return NETDEV_TX_LOCKED; 
-       } 
+#ifdef NETIF_F_TSO
+       /* TSO Workaround for 82571/2 Controllers -- if skb->data
+        * points to just header, pull a few bytes of payload from 
+        * frags into skb->data */
+       if (skb_shinfo(skb)->tso_size) {
+               uint8_t hdr_len;
+               hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+               if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && 
+                       (adapter->hw.mac_type == e1000_82571 ||
+                       adapter->hw.mac_type == e1000_82572)) {
+                       unsigned int pull_size;
+                       pull_size = min((unsigned int)4, skb->data_len);
+                       if (!__pskb_pull_tail(skb, pull_size)) {
+                               printk(KERN_ERR "__pskb_pull_tail failed.\n");
+                               dev_kfree_skb_any(skb);
+                               return -EFAULT;
+                       }
+               }
+       }
+#endif
+
        if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
                e1000_transfer_dhcp_info(adapter, skb);
 
+       local_irq_save(flags);
+       if (!spin_trylock(&tx_ring->tx_lock)) {
+               /* Collision - tell upper layer to requeue */
+               local_irq_restore(flags);
+               return NETDEV_TX_LOCKED;
+       }
 
        /* need: count + 2 desc gap to keep tail from touching
         * head, otherwise try next time */
-       if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
+       if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
                netif_stop_queue(netdev);
-               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+               spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
                return NETDEV_TX_BUSY;
        }
 
@@ -2284,7 +2765,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
                        netif_stop_queue(netdev);
                        mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
-                       spin_unlock_irqrestore(&adapter->tx_lock, flags);
+                       spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
                        return NETDEV_TX_BUSY;
                }
        }
@@ -2294,37 +2775,37 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
        }
 
-       first = adapter->tx_ring.next_to_use;
+       first = tx_ring->next_to_use;
        
-       tso = e1000_tso(adapter, skb);
+       tso = e1000_tso(adapter, tx_ring, skb);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
-               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+               spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
                return NETDEV_TX_OK;
        }
 
        if (likely(tso))
                tx_flags |= E1000_TX_FLAGS_TSO;
-       else if(likely(e1000_tx_csum(adapter, skb)))
+       else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
                tx_flags |= E1000_TX_FLAGS_CSUM;
 
        /* Old method was to assume IPv4 packet by default if TSO was enabled.
-        * 82573 hardware supports TSO capabilities for IPv6 as well...
+        * 82571 hardware supports TSO capabilities for IPv6 as well...
         * no longer assume, we must. */
-       if(likely(skb->protocol == ntohs(ETH_P_IP)))
+       if (likely(skb->protocol == ntohs(ETH_P_IP)))
                tx_flags |= E1000_TX_FLAGS_IPV4;
 
-       e1000_tx_queue(adapter,
-               e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
-               tx_flags);
+       e1000_tx_queue(adapter, tx_ring, tx_flags,
+                      e1000_tx_map(adapter, tx_ring, skb, first,
+                                   max_per_txd, nr_frags, mss));
 
        netdev->trans_start = jiffies;
 
        /* Make sure there is space in the ring for the next send. */
-       if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
+       if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
                netif_stop_queue(netdev);
 
-       spin_unlock_irqrestore(&adapter->tx_lock, flags);
+       spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
        return NETDEV_TX_OK;
 }
 
@@ -2388,9 +2869,18 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
                        return -EINVAL;
        }
 
-#define MAX_STD_JUMBO_FRAME_SIZE 9216
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
        /* might want this to be bigger enum check... */
-       if (adapter->hw.mac_type == e1000_82573 &&
+       /* 82571 controllers limit jumbo frame size to 10500 bytes */
+       if ((adapter->hw.mac_type == e1000_82571 || 
+            adapter->hw.mac_type == e1000_82572) &&
+           max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+               DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
+                                   "on 82571 and 82572 controllers.\n");
+               return -EINVAL;
+       }
+
+       if(adapter->hw.mac_type == e1000_82573 &&
            max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
                DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
                                    "on 82573\n");
@@ -2578,6 +3068,29 @@ e1000_update_stats(struct e1000_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
+#ifdef CONFIG_E1000_MQ
+void
+e1000_rx_schedule(void *data)
+{
+       struct net_device *poll_dev, *netdev = data;
+       struct e1000_adapter *adapter = netdev->priv;
+       int this_cpu = get_cpu();
+
+       poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
+       if (poll_dev == NULL) {
+               put_cpu();
+               return;
+       }
+
+       if (likely(netif_rx_schedule_prep(poll_dev)))
+               __netif_rx_schedule(poll_dev);
+       else
+               e1000_irq_enable(adapter);
+
+       put_cpu();
+}
+#endif
+
 /**
  * e1000_intr - Interrupt Handler
  * @irq: interrupt number
@@ -2592,8 +3105,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
        uint32_t icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
-       unsigned int i;
+#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+       int i;
 #endif
 
        if(unlikely(!icr))
@@ -2605,17 +3118,31 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
        }
 
 #ifdef CONFIG_E1000_NAPI
-       if(likely(netif_rx_schedule_prep(netdev))) {
-
-               /* Disable interrupts and register for poll. The flush 
-                 of the posted write is intentionally left out.
-               */
-
-               atomic_inc(&adapter->irq_sem);
-               E1000_WRITE_REG(hw, IMC, ~0);
-               __netif_rx_schedule(netdev);
+       atomic_inc(&adapter->irq_sem);
+       E1000_WRITE_REG(hw, IMC, ~0);
+       E1000_WRITE_FLUSH(hw);
+#ifdef CONFIG_E1000_MQ
+       if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
+               cpu_set(adapter->cpu_for_queue[0],
+                       adapter->rx_sched_call_data.cpumask);
+               for (i = 1; i < adapter->num_queues; i++) {
+                       cpu_set(adapter->cpu_for_queue[i],
+                               adapter->rx_sched_call_data.cpumask);
+                       atomic_inc(&adapter->irq_sem);
+               }
+               atomic_set(&adapter->rx_sched_call_data.count, i);
+               smp_call_async_mask(&adapter->rx_sched_call_data);
+       } else {
+               printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
        }
-#else
+#else /* if !CONFIG_E1000_MQ */
+       if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
+               __netif_rx_schedule(&adapter->polling_netdev[0]);
+       else
+               e1000_irq_enable(adapter);
+#endif /* CONFIG_E1000_MQ */
+
+#else /* if !CONFIG_E1000_NAPI */
        /* Writing IMC and IMS is needed for 82547.
           Due to Hub Link bus being occupied, an interrupt
           de-assertion message is not able to be sent.
@@ -2632,13 +3159,14 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
        }
 
        for(i = 0; i < E1000_MAX_INTR; i++)
-               if(unlikely(!adapter->clean_rx(adapter) &
-                  !e1000_clean_tx_irq(adapter)))
+               if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+                  !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
                        break;
 
        if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
                e1000_irq_enable(adapter);
-#endif
+
+#endif /* CONFIG_E1000_NAPI */
 
        return IRQ_HANDLED;
 }
@@ -2650,22 +3178,37 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
  **/
 
 static int
-e1000_clean(struct net_device *netdev, int *budget)
+e1000_clean(struct net_device *poll_dev, int *budget)
 {
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-       int work_to_do = min(*budget, netdev->quota);
-       int tx_cleaned;
-       int work_done = 0;
+       struct e1000_adapter *adapter;
+       int work_to_do = min(*budget, poll_dev->quota);
+       int tx_cleaned, i = 0, work_done = 0;
 
-       tx_cleaned = e1000_clean_tx_irq(adapter);
-       adapter->clean_rx(adapter, &work_done, work_to_do);
+       /* Must NOT use netdev_priv macro here. */
+       adapter = poll_dev->priv;
+
+       /* Keep link state information with original netdev */
+       if (!netif_carrier_ok(adapter->netdev))
+               goto quit_polling;
+
+       while (poll_dev != &adapter->polling_netdev[i]) {
+               i++;
+               if (unlikely(i == adapter->num_queues))
+                       BUG();
+       }
+
+       tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+       adapter->clean_rx(adapter, &adapter->rx_ring[i],
+                         &work_done, work_to_do);
 
        *budget -= work_done;
-       netdev->quota -= work_done;
+       poll_dev->quota -= work_done;
        
-       if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
        /* If no Tx and not enough Rx work done, exit the polling mode */
-               netif_rx_complete(netdev);
+       if((!tx_cleaned && (work_done == 0)) ||
+          !netif_running(adapter->netdev)) {
+quit_polling:
+               netif_rx_complete(poll_dev);
                e1000_irq_enable(adapter);
                return 0;
        }
@@ -2680,9 +3223,9 @@ e1000_clean(struct net_device *netdev, int *budget)
  **/
 
 static boolean_t
-e1000_clean_tx_irq(struct e1000_adapter *adapter)
+e1000_clean_tx_irq(struct e1000_adapter *adapter,
+                   struct e1000_tx_ring *tx_ring)
 {
-       struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
        struct net_device *netdev = adapter->netdev;
        struct e1000_tx_desc *tx_desc, *eop_desc;
        struct e1000_buffer *buffer_info;
@@ -2693,12 +3236,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
        eop = tx_ring->buffer_info[i].next_to_watch;
        eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
-       while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+       while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
                /* Premature writeback of Tx descriptors clear (free buffers
                 * and unmap pci_mapping) previous_buffer_info */
-               if (likely(adapter->previous_buffer_info.skb != NULL)) {
+               if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
                        e1000_unmap_and_free_tx_resource(adapter,
-                                       &adapter->previous_buffer_info);
+                                       &tx_ring->previous_buffer_info);
                }
 
                for(cleaned = FALSE; !cleaned; ) {
@@ -2714,7 +3257,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 #ifdef NETIF_F_TSO
                        } else {
                                if (cleaned) {
-                                       memcpy(&adapter->previous_buffer_info,
+                                       memcpy(&tx_ring->previous_buffer_info,
                                               buffer_info,
                                               sizeof(struct e1000_buffer));
                                        memset(buffer_info, 0,
@@ -2732,6 +3275,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 
                        if(unlikely(++i == tx_ring->count)) i = 0;
                }
+
+               tx_ring->pkt++;
                
                eop = tx_ring->buffer_info[i].next_to_watch;
                eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -2739,15 +3284,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 
        tx_ring->next_to_clean = i;
 
-       spin_lock(&adapter->tx_lock);
+       spin_lock(&tx_ring->tx_lock);
 
        if(unlikely(cleaned && netif_queue_stopped(netdev) &&
                    netif_carrier_ok(netdev)))
                netif_wake_queue(netdev);
 
-       spin_unlock(&adapter->tx_lock);
-       if(adapter->detect_tx_hung) {
+       spin_unlock(&tx_ring->tx_lock);
 
+       if (adapter->detect_tx_hung) {
                /* Detect a transmit hang in hardware, this serializes the
                 * check with the clearing of time_stamp and movement of i */
                adapter->detect_tx_hung = FALSE;
@@ -2771,8 +3316,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
                                        "  next_to_watch        <%x>\n"
                                        "  jiffies              <%lx>\n"
                                        "  next_to_watch.status <%x>\n",
-                               E1000_READ_REG(&adapter->hw, TDH),
-                               E1000_READ_REG(&adapter->hw, TDT),
+                               readl(adapter->hw.hw_addr + tx_ring->tdh),
+                               readl(adapter->hw.hw_addr + tx_ring->tdt),
                                tx_ring->next_to_use,
                                i,
                                (unsigned long long)tx_ring->buffer_info[i].dma,
@@ -2784,12 +3329,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
                }
        }
 #ifdef NETIF_F_TSO
-
-       if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-           time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
+       if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+           time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
                e1000_unmap_and_free_tx_resource(
-                   adapter, &adapter->previous_buffer_info);
-
+                   adapter, &tx_ring->previous_buffer_info);
 #endif
        return cleaned;
 }
@@ -2852,13 +3395,14 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
 
 static boolean_t
 #ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
-                   int work_to_do)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                   struct e1000_rx_ring *rx_ring,
+                   int *work_done, int work_to_do)
 #else
-e1000_clean_rx_irq(struct e1000_adapter *adapter)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                   struct e1000_rx_ring *rx_ring)
 #endif
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_rx_desc *rx_desc;
@@ -2944,6 +3488,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
                }
 #endif /* CONFIG_E1000_NAPI */
                netdev->last_rx = jiffies;
+               rx_ring->pkt++;
 
 next_desc:
                rx_desc->status = 0;
@@ -2953,7 +3498,7 @@ next_desc:
                rx_desc = E1000_RX_DESC(*rx_ring, i);
        }
        rx_ring->next_to_clean = i;
-       adapter->alloc_rx_buf(adapter);
+       adapter->alloc_rx_buf(adapter, rx_ring);
 
        return cleaned;
 }
@@ -2965,13 +3510,14 @@ next_desc:
 
 static boolean_t
 #ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
-                      int work_to_do)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                      struct e1000_rx_ring *rx_ring,
+                      int *work_done, int work_to_do)
 #else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                      struct e1000_rx_ring *rx_ring)
 #endif
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        union e1000_rx_desc_packet_split *rx_desc;
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
@@ -3027,7 +3573,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
                /* Good Receive */
                skb_put(skb, length);
 
-               for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+               for(j = 0; j < adapter->rx_ps_pages; j++) {
                        if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
                                break;
 
@@ -3048,11 +3594,13 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
                                  rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
                skb->protocol = eth_type_trans(skb, netdev);
 
-#ifdef HAVE_RX_ZERO_COPY
                if(likely(rx_desc->wb.upper.header_status &
-                         E1000_RXDPS_HDRSTAT_HDRSP))
+                         E1000_RXDPS_HDRSTAT_HDRSP)) {
+                       adapter->rx_hdr_split++;
+#ifdef HAVE_RX_ZERO_COPY
                        skb_shinfo(skb)->zero_copy = TRUE;
 #endif
+               }
 #ifdef CONFIG_E1000_NAPI
                if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
                        vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -3071,6 +3619,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
                }
 #endif /* CONFIG_E1000_NAPI */
                netdev->last_rx = jiffies;
+               rx_ring->pkt++;
 
 next_desc:
                rx_desc->wb.middle.status_error &= ~0xFF;
@@ -3081,7 +3630,7 @@ next_desc:
                staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
        }
        rx_ring->next_to_clean = i;
-       adapter->alloc_rx_buf(adapter);
+       adapter->alloc_rx_buf(adapter, rx_ring);
 
        return cleaned;
 }
@@ -3092,9 +3641,9 @@ next_desc:
  **/
 
 static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+                       struct e1000_rx_ring *rx_ring)
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_rx_desc *rx_desc;
@@ -3178,7 +3727,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
                         * applicable for weak-ordered memory model archs,
                         * such as IA-64). */
                        wmb();
-                       E1000_WRITE_REG(&adapter->hw, RDT, i);
+                       writel(i, adapter->hw.hw_addr + rx_ring->rdt);
                }
 
                if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3194,9 +3743,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
  **/
 
 static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+                          struct e1000_rx_ring *rx_ring)
 {
-       struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        union e1000_rx_desc_packet_split *rx_desc;
@@ -3215,22 +3764,26 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
                rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
 
                for(j = 0; j < PS_PAGE_BUFFERS; j++) {
-                       if(unlikely(!ps_page->ps_page[j])) {
-                               ps_page->ps_page[j] =
-                                       alloc_page(GFP_ATOMIC);
-                               if(unlikely(!ps_page->ps_page[j]))
-                                       goto no_buffers;
-                               ps_page_dma->ps_page_dma[j] =
-                                       pci_map_page(pdev,
-                                                    ps_page->ps_page[j],
-                                                    0, PAGE_SIZE,
-                                                    PCI_DMA_FROMDEVICE);
-                       }
-                       /* Refresh the desc even if buffer_addrs didn't
-                        * change because each write-back erases this info.
-                        */
-                       rx_desc->read.buffer_addr[j+1] =
-                               cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+                       if (j < adapter->rx_ps_pages) {
+                               if (likely(!ps_page->ps_page[j])) {
+                                       ps_page->ps_page[j] =
+                                               alloc_page(GFP_ATOMIC);
+                                       if (unlikely(!ps_page->ps_page[j]))
+                                               goto no_buffers;
+                                       ps_page_dma->ps_page_dma[j] =
+                                               pci_map_page(pdev,
+                                                           ps_page->ps_page[j],
+                                                           0, PAGE_SIZE,
+                                                           PCI_DMA_FROMDEVICE);
+                               }
+                               /* Refresh the desc even if buffer_addrs didn't
+                                * change because each write-back erases 
+                                * this info.
+                                */
+                               rx_desc->read.buffer_addr[j+1] =
+                                    cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+                       } else
+                               rx_desc->read.buffer_addr[j+1] = ~0;
                }
 
                skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
@@ -3264,7 +3817,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
                         * descriptors are 32 bytes...so we increment tail
                         * twice as much.
                         */
-                       E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+                       writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
                }
 
                if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3715,6 +4268,12 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
        }
 
        switch(adapter->hw.mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+               E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+                               ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+               break;
        case e1000_82573:
                swsm = E1000_READ_REG(&adapter->hw, SWSM);
                E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3737,6 +4296,7 @@ e1000_resume(struct pci_dev *pdev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        uint32_t manc, ret_val, swsm;
+       uint32_t ctrl_ext;
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
@@ -3762,6 +4322,12 @@ e1000_resume(struct pci_dev *pdev)
        }
 
        switch(adapter->hw.mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+               E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+                               ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+               break;
        case e1000_82573:
                swsm = E1000_READ_REG(&adapter->hw, SWSM);
                E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3786,7 +4352,7 @@ e1000_netpoll(struct net_device *netdev)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        disable_irq(adapter->pdev->irq);
        e1000_intr(adapter->pdev->irq, netdev, NULL);
-       e1000_clean_tx_irq(adapter);
+       e1000_clean_tx_irq(adapter, adapter->tx_ring);
        enable_irq(adapter->pdev->irq);
 }
 #endif
index 676247f9f1cca054967d604547f005d1340b5eee..38695d5b46377ca035cff87e47fd32c9d5f69015 100644 (file)
@@ -306,7 +306,8 @@ e1000_check_options(struct e1000_adapter *adapter)
                        .def  = E1000_DEFAULT_TXD,
                        .arg  = { .r = { .min = E1000_MIN_TXD }}
                };
-               struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+               struct e1000_tx_ring *tx_ring = adapter->tx_ring;
+               int i;
                e1000_mac_type mac_type = adapter->hw.mac_type;
                opt.arg.r.max = mac_type < e1000_82544 ?
                        E1000_MAX_TXD : E1000_MAX_82544_TXD;
@@ -319,6 +320,8 @@ e1000_check_options(struct e1000_adapter *adapter)
                } else {
                        tx_ring->count = opt.def;
                }
+               for (i = 0; i < adapter->num_queues; i++)
+                       tx_ring[i].count = tx_ring->count;
        }
        { /* Receive Descriptor Count */
                struct e1000_option opt = {
@@ -329,7 +332,8 @@ e1000_check_options(struct e1000_adapter *adapter)
                        .def  = E1000_DEFAULT_RXD,
                        .arg  = { .r = { .min = E1000_MIN_RXD }}
                };
-               struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+               struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+               int i;
                e1000_mac_type mac_type = adapter->hw.mac_type;
                opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
                        E1000_MAX_82544_RXD;
@@ -342,6 +346,8 @@ e1000_check_options(struct e1000_adapter *adapter)
                } else {
                        rx_ring->count = opt.def;
                }
+               for (i = 0; i < adapter->num_queues; i++)
+                       rx_ring[i].count = rx_ring->count;
        }
        { /* Checksum Offload Enable/Disable */
                struct e1000_option opt = {
index 87f522738bfcb718b63526450844f696bd750181..f119ec4e89ea3702e22f15f3dfda948e61f9bad3 100644 (file)
@@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
 static int epic_poll(struct net_device *dev, int *budget)
 {
        struct epic_private *ep = dev->priv;
-       int work_done, orig_budget;
+       int work_done = 0, orig_budget;
        long ioaddr = dev->base_addr;
 
        orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
@@ -1343,7 +1343,7 @@ rx_action:
 
        epic_tx(dev, ep);
 
-       work_done = epic_rx(dev, *budget);
+       work_done += epic_rx(dev, *budget);
 
        epic_rx_err(dev, ep);
 
index d6eefdb71c174889b6491635121fe33f9b789594..e5f480203675f31c00d0087f7af0ff4321dc6043 100644 (file)
@@ -95,6 +95,7 @@
  *                        of nv_remove
  *      0.42: 06 Aug 2005: Fix lack of link speed initialization
  *                        in the second (and later) nv_open call
+ *      0.43: 10 Aug 2005: Add support for tx checksum.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION              "0.41"
+#define FORCEDETH_VERSION              "0.43"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
 #define DEV_NEED_LINKTIMER     0x0002  /* poll link settings. Relies on the timer irq */
 #define DEV_HAS_LARGEDESC      0x0004  /* device supports jumbo frames and needs packet format 2 */
 #define DEV_HAS_HIGH_DMA        0x0008  /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM        0x0010  /* device supports tx and rx checksum offloads */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -241,6 +243,9 @@ enum {
 #define NVREG_TXRXCTL_IDLE     0x0008
 #define NVREG_TXRXCTL_RESET    0x0010
 #define NVREG_TXRXCTL_RXCHECK  0x0400
+#define NVREG_TXRXCTL_DESC_1   0
+#define NVREG_TXRXCTL_DESC_2   0x02100
+#define NVREG_TXRXCTL_DESC_3   0x02200
        NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR            0x0001
 #define NVREG_MIISTAT_LINKCHANGE       0x0008
@@ -335,6 +340,8 @@ typedef union _ring_type {
 /* error and valid are the same for both */
 #define NV_TX2_ERROR           (1<<30)
 #define NV_TX2_VALID           (1<<31)
+#define NV_TX2_CHECKSUM_L3     (1<<27)
+#define NV_TX2_CHECKSUM_L4     (1<<26)
 
 #define NV_RX_DESCRIPTORVALID  (1<<16)
 #define NV_RX_MISSEDFRAME      (1<<17)
@@ -417,14 +424,14 @@ typedef union _ring_type {
 
 /* 
  * desc_ver values:
- * This field has two purposes:
- * - Newer nics uses a different ring layout. The layout is selected by
- *   comparing np->desc_ver with DESC_VER_xy.
- * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ * The nic supports three different descriptor types:
+ * - DESC_VER_1: Original
+ * - DESC_VER_2: support for jumbo frames.
+ * - DESC_VER_3: 64-bit format.
  */
-#define DESC_VER_1     0x0
-#define DESC_VER_2     (0x02100|NVREG_TXRXCTL_RXCHECK)
-#define DESC_VER_3      (0x02200|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_1     1
+#define DESC_VER_2     2
+#define DESC_VER_3     3
 
 /* PHY defines */
 #define PHY_OUI_MARVELL        0x5043
@@ -491,6 +498,7 @@ struct fe_priv {
        u32 orig_mac[2];
        u32 irqmask;
        u32 desc_ver;
+       u32 txrxctl_bits;
 
        void __iomem *base;
 
@@ -786,10 +794,10 @@ static void nv_txrx_reset(struct net_device *dev)
        u8 __iomem *base = get_hwbase(dev);
 
        dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
-       writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
+       writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
        pci_push(base);
        udelay(NV_TXRX_RESET_DELAY);
-       writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
+       writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
        pci_push(base);
 }
 
@@ -961,6 +969,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct fe_priv *np = get_nvpriv(dev);
        int nr = np->next_tx % TX_RING;
+       u32 tx_checksum = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
 
        np->tx_skbuff[nr] = skb;
        np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
@@ -976,10 +985,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irq(&np->lock);
        wmb();
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-               np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+               np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags | tx_checksum);
        else
-               np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
-       dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
+               np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags | tx_checksum);
+       dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission\n",
                                dev->name, np->next_tx);
        {
                int j;
@@ -997,7 +1006,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
                netif_stop_queue(dev);
        spin_unlock_irq(&np->lock);
-       writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+       writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
        pci_push(get_hwbase(dev));
        return 0;
 }
@@ -1408,7 +1417,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
                        base + NvRegRingSizes);
                pci_push(base);
-               writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+               writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
                pci_push(base);
 
                /* restart rx engine */
@@ -2065,6 +2074,7 @@ static struct ethtool_ops ops = {
        .get_regs_len = nv_get_regs_len,
        .get_regs = nv_get_regs,
        .nway_reset = nv_nway_reset,
+       .get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 static int nv_open(struct net_device *dev)
@@ -2114,9 +2124,9 @@ static int nv_open(struct net_device *dev)
        /* 5) continue setup */
        writel(np->linkspeed, base + NvRegLinkSpeed);
        writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
-       writel(np->desc_ver, base + NvRegTxRxControl);
+       writel(np->txrxctl_bits, base + NvRegTxRxControl);
        pci_push(base);
-       writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
+       writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
        reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
                        NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
                        KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
@@ -2314,18 +2324,26 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
                                        pci_name(pci_dev));
                }
+               np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
        } else if (id->driver_data & DEV_HAS_LARGEDESC) {
                /* packet format 2: supports jumbo frames */
                np->desc_ver = DESC_VER_2;
+               np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
        } else {
                /* original packet format */
                np->desc_ver = DESC_VER_1;
+               np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
        }
 
        np->pkt_limit = NV_PKTLIMIT_1;
        if (id->driver_data & DEV_HAS_LARGEDESC)
                np->pkt_limit = NV_PKTLIMIT_2;
 
+       if (id->driver_data & DEV_HAS_CHECKSUM) {
+               np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+               dev->features |= NETIF_F_HW_CSUM;
+       }
+
        err = -ENOMEM;
        np->base = ioremap(addr, NV_PCI_REGSZ);
        if (!np->base)
@@ -2377,8 +2395,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
        dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
        dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-       if (!is_valid_ether_addr(dev->dev_addr)) {
+       if (!is_valid_ether_addr(dev->perm_addr)) {
                /*
                 * Bad mac address. At least one bios sets the mac address
                 * to 01:23:45:67:89:ab
@@ -2525,35 +2544,35 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* nForce3 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
        },
        {       /* nForce3 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
        },
        {       /* nForce3 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
        },
        {       /* nForce3 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
        },
        {       /* CK804 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {       /* CK804 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP04 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP04 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP51 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
@@ -2565,11 +2584,11 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
        },
        {0,},
 };
index 6518334b92801a41745718b09a74805e3e7b8004..ae5a2ed3b2640336a656087596206d2e462ee73e 100644 (file)
  *  define the configuration needed by the board are defined in a
  *  board structure in arch/ppc/platforms (though I do not
  *  discount the possibility that other architectures could one
- *  day be supported.  One assumption the driver currently makes
- *  is that the PHY is configured in such a way to advertise all
- *  capabilities.  This is a sensible default, and on certain
- *  PHYs, changing this default encounters substantial errata
- *  issues.  Future versions may remove this requirement, but for
- *  now, it is best for the firmware to ensure this is the case.
+ *  day be supported.
  *
  *  The Gianfar Ethernet Controller uses a ring of buffer
  *  descriptors.  The beginning is indicated by a register
@@ -47,7 +42,7 @@
  *  corresponding bit in the IMASK register is also set (if
  *  interrupt coalescing is active, then the interrupt may not
  *  happen immediately, but will wait until either a set number
- *  of frames or amount of time have passed.).  In NAPI, the
+ *  of frames or amount of time have passed).  In NAPI, the
  *  interrupt handler will signal there is work to be done, and
  *  exit.  Without NAPI, the packet(s) will be handled
  *  immediately.  Both methods will start at the last known empty
@@ -75,6 +70,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
 #define SKB_ALLOC_TIMEOUT 1000000
 #endif
 
 const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
 
-int startup_gfar(struct net_device *dev);
 static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void gfar_timeout(struct net_device *dev);
@@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct net_device *dev);
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct device *device);
 static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
 #ifdef CONFIG_GFAR_NAPI
@@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *dev, int *budget);
 #endif
 int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
 static void gfar_vlan_rx_register(struct net_device *netdev,
                                struct vlan_group *grp);
 static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *priv)
        else
                return 0;
 }
+
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
 static int gfar_probe(struct device *device)
 {
        u32 tempval;
@@ -175,7 +170,7 @@ static int gfar_probe(struct device *device)
 
        einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
 
-       if (einfo == NULL) {
+       if (NULL == einfo) {
                printk(KERN_ERR "gfar %d: Missing additional data!\n",
                       pdev->id);
 
@@ -185,7 +180,7 @@ static int gfar_probe(struct device *device)
        /* Create an ethernet device instance */
        dev = alloc_etherdev(sizeof (*priv));
 
-       if (dev == NULL)
+       if (NULL == dev)
                return -ENOMEM;
 
        priv = netdev_priv(dev);
@@ -207,20 +202,11 @@ static int gfar_probe(struct device *device)
        priv->regs = (struct gfar *)
                ioremap(r->start, sizeof (struct gfar));
 
-       if (priv->regs == NULL) {
+       if (NULL == priv->regs) {
                err = -ENOMEM;
                goto regs_fail;
        }
 
-       /* Set the PHY base address */
-       priv->phyregs = (struct gfar *)
-           ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
-       if (priv->phyregs == NULL) {
-               err = -ENOMEM;
-               goto phy_regs_fail;
-       }
-
        spin_lock_init(&priv->lock);
 
        dev_set_drvdata(device, dev);
@@ -386,12 +372,10 @@ static int gfar_probe(struct device *device)
        return 0;
 
 register_fail:
-       iounmap((void *) priv->phyregs);
-phy_regs_fail:
        iounmap((void *) priv->regs);
 regs_fail:
        free_netdev(dev);
-       return -ENOMEM;
+       return err;
 }
 
 static int gfar_remove(struct device *device)
@@ -402,108 +386,41 @@ static int gfar_remove(struct device *device)
        dev_set_drvdata(device, NULL);
 
        iounmap((void *) priv->regs);
-       iounmap((void *) priv->phyregs);
        free_netdev(dev);
 
        return 0;
 }
 
 
-/* Configure the PHY for dev.
- * returns 0 if success.  -1 if failure
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
  */
 static int init_phy(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       struct phy_info *curphy;
-       unsigned int timeout = PHY_INIT_TIMEOUT;
-       struct gfar *phyregs = priv->phyregs;
-       struct gfar_mii_info *mii_info;
-       int err;
+       uint gigabit_support =
+               priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+               SUPPORTED_1000baseT_Full : 0;
+       struct phy_device *phydev;
 
        priv->oldlink = 0;
        priv->oldspeed = 0;
        priv->oldduplex = -1;
 
-       mii_info = kmalloc(sizeof(struct gfar_mii_info),
-                       GFP_KERNEL);
-
-       if(NULL == mii_info) {
-               if (netif_msg_ifup(priv))
-                       printk(KERN_ERR "%s: Could not allocate mii_info\n",
-                                       dev->name);
-               return -ENOMEM;
-       }
-
-       mii_info->speed = SPEED_1000;
-       mii_info->duplex = DUPLEX_FULL;
-       mii_info->pause = 0;
-       mii_info->link = 1;
-
-       mii_info->advertising = (ADVERTISED_10baseT_Half |
-                       ADVERTISED_10baseT_Full |
-                       ADVERTISED_100baseT_Half |
-                       ADVERTISED_100baseT_Full |
-                       ADVERTISED_1000baseT_Full);
-       mii_info->autoneg = 1;
+       phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
 
-       spin_lock_init(&mii_info->mdio_lock);
-
-       mii_info->mii_id = priv->einfo->phyid;
-
-       mii_info->dev = dev;
-
-       mii_info->mdio_read = &read_phy_reg;
-       mii_info->mdio_write = &write_phy_reg;
-
-       priv->mii_info = mii_info;
-
-       /* Reset the management interface */
-       gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
-       /* Setup the MII Mgmt clock speed */
-       gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
-       /* Wait until the bus is free */
-       while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
-                       timeout--)
-               cpu_relax();
-
-       if(timeout <= 0) {
-               printk(KERN_ERR "%s: The MII Bus is stuck!\n",
-                               dev->name);
-               err = -1;
-               goto bus_fail;
-       }
-
-       /* get info for this PHY */
-       curphy = get_phy_info(priv->mii_info);
-
-       if (curphy == NULL) {
-               if (netif_msg_ifup(priv))
-                       printk(KERN_ERR "%s: No PHY found\n", dev->name);
-               err = -1;
-               goto no_phy;
+       if (IS_ERR(phydev)) {
+               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+               return PTR_ERR(phydev);
        }
 
-       mii_info->phyinfo = curphy;
+       /* Remove any features not supported by the controller */
+       phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+       phydev->advertising = phydev->supported;
 
-       /* Run the commands which initialize the PHY */
-       if(curphy->init) {
-               err = curphy->init(priv->mii_info);
-
-               if (err)
-                       goto phy_init_fail;
-       }
+       priv->phydev = phydev;
 
        return 0;
-
-phy_init_fail:
-no_phy:
-bus_fail:
-       kfree(mii_info);
-
-       return err;
 }
 
 static void init_registers(struct net_device *dev)
@@ -603,24 +520,13 @@ void stop_gfar(struct net_device *dev)
        struct gfar *regs = priv->regs;
        unsigned long flags;
 
+       phy_stop(priv->phydev);
+
        /* Lock it down */
        spin_lock_irqsave(&priv->lock, flags);
 
-       /* Tell the kernel the link is down */
-       priv->mii_info->link = 0;
-       adjust_link(dev);
-
        gfar_halt(dev);
 
-       if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-               /* Clear any pending interrupts */
-               mii_clear_phy_interrupt(priv->mii_info);
-
-               /* Disable PHY Interrupts */
-               mii_configure_phy_interrupt(priv->mii_info,
-                               MII_INTERRUPT_DISABLED);
-       }
-
        spin_unlock_irqrestore(&priv->lock, flags);
 
        /* Free the IRQs */
@@ -629,13 +535,7 @@ void stop_gfar(struct net_device *dev)
                free_irq(priv->interruptTransmit, dev);
                free_irq(priv->interruptReceive, dev);
        } else {
-               free_irq(priv->interruptTransmit, dev);
-       }
-
-       if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-               free_irq(priv->einfo->interruptPHY, dev);
-       } else {
-               del_timer_sync(&priv->phy_info_timer);
+               free_irq(priv->interruptTransmit, dev);
        }
 
        free_skb_resources(priv);
@@ -649,7 +549,7 @@ void stop_gfar(struct net_device *dev)
 
 /* If there are any tx skbs or rx skbs still around, free them.
  * Then free tx_skbuff and rx_skbuff */
-void free_skb_resources(struct gfar_private *priv)
+static void free_skb_resources(struct gfar_private *priv)
 {
        struct rxbd8 *rxbdp;
        struct txbd8 *txbdp;
@@ -770,7 +670,7 @@ int startup_gfar(struct net_device *dev)
            (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
                                        priv->tx_ring_size, GFP_KERNEL);
 
-       if (priv->tx_skbuff == NULL) {
+       if (NULL == priv->tx_skbuff) {
                if (netif_msg_ifup(priv))
                        printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
                                        dev->name);
@@ -785,7 +685,7 @@ int startup_gfar(struct net_device *dev)
            (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
                                        priv->rx_ring_size, GFP_KERNEL);
 
-       if (priv->rx_skbuff == NULL) {
+       if (NULL == priv->rx_skbuff) {
                if (netif_msg_ifup(priv))
                        printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
                                        dev->name);
@@ -879,13 +779,7 @@ int startup_gfar(struct net_device *dev)
                }
        }
 
-       /* Set up the PHY change work queue */
-       INIT_WORK(&priv->tq, gfar_phy_change, dev);
-
-       init_timer(&priv->phy_info_timer);
-       priv->phy_info_timer.function = &gfar_phy_startup_timer;
-       priv->phy_info_timer.data = (unsigned long) priv->mii_info;
-       mod_timer(&priv->phy_info_timer, jiffies + HZ);
+       phy_start(priv->phydev);
 
        /* Configure the coalescing support */
        if (priv->txcoalescing)
@@ -933,11 +827,6 @@ tx_skb_fail:
                        priv->tx_bd_base,
                        gfar_read(&regs->tbase0));
 
-       if (priv->mii_info->phyinfo->close)
-               priv->mii_info->phyinfo->close(priv->mii_info);
-
-       kfree(priv->mii_info);
-
        return err;
 }
 
@@ -1035,7 +924,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
        txbdp->status &= TXBD_WRAP;
 
        /* Set up checksumming */
-       if ((dev->features & NETIF_F_IP_CSUM) 
+       if ((dev->features & NETIF_F_IP_CSUM)
                        && (CHECKSUM_HW == skb->ip_summed)) {
                fcb = gfar_add_fcb(skb, txbdp);
                gfar_tx_checksum(skb, fcb);
@@ -1103,11 +992,9 @@ static int gfar_close(struct net_device *dev)
        struct gfar_private *priv = netdev_priv(dev);
        stop_gfar(dev);
 
-       /* Shutdown the PHY */
-       if (priv->mii_info->phyinfo->close)
-               priv->mii_info->phyinfo->close(priv->mii_info);
-
-       kfree(priv->mii_info);
+       /* Disconnect from the PHY */
+       phy_disconnect(priv->phydev);
+       priv->phydev = NULL;
 
        netif_stop_queue(dev);
 
@@ -1343,7 +1230,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
        while ((!skb) && timeout--)
                skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
-       if (skb == NULL)
+       if (NULL == skb)
                return NULL;
 
        /* We need the data buffer to be aligned properly.  We will reserve
@@ -1490,7 +1377,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
        struct gfar_private *priv = netdev_priv(dev);
        struct rxfcb *fcb = NULL;
 
-       if (skb == NULL) {
+       if (NULL == skb) {
                if (netif_msg_rx_err(priv))
                        printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
                priv->stats.rx_dropped++;
@@ -1718,131 +1605,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct gfar_private *priv = netdev_priv(dev);
-
-       /* Clear the interrupt */
-       mii_clear_phy_interrupt(priv->mii_info);
-
-       /* Disable PHY interrupts */
-       mii_configure_phy_interrupt(priv->mii_info,
-                       MII_INTERRUPT_DISABLED);
-
-       /* Schedule the phy change */
-       schedule_work(&priv->tq);
-
-       return IRQ_HANDLED;
-}
-
-/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void gfar_phy_change(void *data)
-{
-       struct net_device *dev = (struct net_device *) data;
-       struct gfar_private *priv = netdev_priv(dev);
-       int result = 0;
-
-       /* Delay to give the PHY a chance to change the
-        * register state */
-       msleep(1);
-
-       /* Update the link, speed, duplex */
-       result = priv->mii_info->phyinfo->read_status(priv->mii_info);
-
-       /* Adjust the known status as long as the link
-        * isn't still coming up */
-       if((0 == result) || (priv->mii_info->link == 0))
-               adjust_link(dev);
-
-       /* Reenable interrupts, if needed */
-       if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
-               mii_configure_phy_interrupt(priv->mii_info,
-                               MII_INTERRUPT_ENABLED);
-}
-
-/* Called every so often on systems that don't interrupt
- * the core for PHY changes */
-static void gfar_phy_timer(unsigned long data)
-{
-       struct net_device *dev = (struct net_device *) data;
-       struct gfar_private *priv = netdev_priv(dev);
-
-       schedule_work(&priv->tq);
-
-       mod_timer(&priv->phy_info_timer, jiffies +
-                       GFAR_PHY_CHANGE_TIME * HZ);
-}
-
-/* Keep trying aneg for some time
- * If, after GFAR_AN_TIMEOUT seconds, it has not
- * finished, we switch to forced.
- * Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
- * using gfar_phy_timer to check status */
-static void gfar_phy_startup_timer(unsigned long data)
-{
-       int result;
-       static int secondary = GFAR_AN_TIMEOUT;
-       struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
-       struct gfar_private *priv = netdev_priv(mii_info->dev);
-
-       /* Configure the Auto-negotiation */
-       result = mii_info->phyinfo->config_aneg(mii_info);
-
-       /* If autonegotiation failed to start, and
-        * we haven't timed out, reset the timer, and return */
-       if (result && secondary--) {
-               mod_timer(&priv->phy_info_timer, jiffies + HZ);
-               return;
-       } else if (result) {
-               /* Couldn't start autonegotiation.
-                * Try switching to forced */
-               mii_info->autoneg = 0;
-               result = mii_info->phyinfo->config_aneg(mii_info);
-
-               /* Forcing failed!  Give up */
-               if(result) {
-                       if (netif_msg_link(priv))
-                               printk(KERN_ERR "%s: Forcing failed!\n",
-                                               mii_info->dev->name);
-                       return;
-               }
-       }
-
-       /* Kill the timer so it can be restarted */
-       del_timer_sync(&priv->phy_info_timer);
-
-       /* Grab the PHY interrupt, if necessary/possible */
-       if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-               if (request_irq(priv->einfo->interruptPHY,
-                                       phy_interrupt,
-                                       SA_SHIRQ,
-                                       "phy_interrupt",
-                                       mii_info->dev) < 0) {
-                       if (netif_msg_intr(priv))
-                               printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
-                                               mii_info->dev->name,
-                                       priv->einfo->interruptPHY);
-               } else {
-                       mii_configure_phy_interrupt(priv->mii_info,
-                                       MII_INTERRUPT_ENABLED);
-                       return;
-               }
-       }
-
-       /* Start the timer again, this time in order to
-        * handle a change in status */
-       init_timer(&priv->phy_info_timer);
-       priv->phy_info_timer.function = &gfar_phy_timer;
-       priv->phy_info_timer.data = (unsigned long) mii_info->dev;
-       mod_timer(&priv->phy_info_timer, jiffies +
-                       GFAR_PHY_CHANGE_TIME * HZ);
-}
-
 /* Called every time the controller might need to be made
  * aware of new link state.  The PHY code conveys this
- * information through variables in the priv structure, and this
+ * information through variables in the phydev structure, and this
  * function converts those variables into the appropriate
  * register values, and can bring down the device if needed.
  */
@@ -1850,84 +1615,68 @@ static void adjust_link(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
        struct gfar *regs = priv->regs;
-       u32 tempval;
-       struct gfar_mii_info *mii_info = priv->mii_info;
+       unsigned long flags;
+       struct phy_device *phydev = priv->phydev;
+       int new_state = 0;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (phydev->link) {
+               u32 tempval = gfar_read(&regs->maccfg2);
 
-       if (mii_info->link) {
                /* Now we make sure that we can be in full duplex mode.
                 * If not, we operate in half-duplex mode. */
-               if (mii_info->duplex != priv->oldduplex) {
-                       if (!(mii_info->duplex)) {
-                               tempval = gfar_read(&regs->maccfg2);
+               if (phydev->duplex != priv->oldduplex) {
+                       new_state = 1;
+                       if (!(phydev->duplex))
                                tempval &= ~(MACCFG2_FULL_DUPLEX);
-                               gfar_write(&regs->maccfg2, tempval);
-
-                               if (netif_msg_link(priv))
-                                       printk(KERN_INFO "%s: Half Duplex\n",
-                                                       dev->name);
-                       } else {
-                               tempval = gfar_read(&regs->maccfg2);
+                       else
                                tempval |= MACCFG2_FULL_DUPLEX;
-                               gfar_write(&regs->maccfg2, tempval);
 
-                               if (netif_msg_link(priv))
-                                       printk(KERN_INFO "%s: Full Duplex\n",
-                                                       dev->name);
-                       }
-
-                       priv->oldduplex = mii_info->duplex;
+                       priv->oldduplex = phydev->duplex;
                }
 
-               if (mii_info->speed != priv->oldspeed) {
-                       switch (mii_info->speed) {
+               if (phydev->speed != priv->oldspeed) {
+                       new_state = 1;
+                       switch (phydev->speed) {
                        case 1000:
-                               tempval = gfar_read(&regs->maccfg2);
                                tempval =
                                    ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
-                               gfar_write(&regs->maccfg2, tempval);
                                break;
                        case 100:
                        case 10:
-                               tempval = gfar_read(&regs->maccfg2);
                                tempval =
                                    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
-                               gfar_write(&regs->maccfg2, tempval);
                                break;
                        default:
                                if (netif_msg_link(priv))
                                        printk(KERN_WARNING
-                                                       "%s: Ack!  Speed (%d) is not 10/100/1000!\n",
-                                                       dev->name, mii_info->speed);
+                                               "%s: Ack!  Speed (%d) is not 10/100/1000!\n",
+                                               dev->name, phydev->speed);
                                break;
                        }
 
-                       if (netif_msg_link(priv))
-                               printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
-                                               mii_info->speed);
-
-                       priv->oldspeed = mii_info->speed;
+                       priv->oldspeed = phydev->speed;
                }
 
+               gfar_write(&regs->maccfg2, tempval);
+
                if (!priv->oldlink) {
-                       if (netif_msg_link(priv))
-                               printk(KERN_INFO "%s: Link is up\n", dev->name);
+                       new_state = 1;
                        priv->oldlink = 1;
-                       netif_carrier_on(dev);
                        netif_schedule(dev);
                }
-       } else {
-               if (priv->oldlink) {
-                       if (netif_msg_link(priv))
-                               printk(KERN_INFO "%s: Link is down\n",
-                                               dev->name);
-                       priv->oldlink = 0;
-                       priv->oldspeed = 0;
-                       priv->oldduplex = -1;
-                       netif_carrier_off(dev);
-               }
+       } else if (priv->oldlink) {
+               new_state = 1;
+               priv->oldlink = 0;
+               priv->oldspeed = 0;
+               priv->oldduplex = -1;
        }
-}
 
+       if (new_state && netif_msg_link(priv))
+               phy_print_status(phydev);
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
 
 /* Update the hash table based on the current list of multicast
  * addresses we subscribe to.  Also, change the promiscuity of
@@ -2122,12 +1871,23 @@ static struct device_driver gfar_driver = {
 
 static int __init gfar_init(void)
 {
-       return driver_register(&gfar_driver);
+       int err = gfar_mdio_init();
+
+       if (err)
+               return err;
+
+       err = driver_register(&gfar_driver);
+
+       if (err)
+               gfar_mdio_exit();
+       
+       return err;
 }
 
 static void __exit gfar_exit(void)
 {
        driver_unregister(&gfar_driver);
+       gfar_mdio_exit();
 }
 
 module_init(gfar_init);
index 28af087d9fbba24d0005fd66c34f765005565610..c77ca6c0d04a6d651c0e3d37ca749146b5e9bc5c 100644 (file)
@@ -17,7 +17,6 @@
  *
  *  Still left to do:
  *      -Add support for module parameters
- *     -Add support for ethtool -s
  *     -Add patch for ethtool phys id
  */
 #ifndef __GIANFAR_H
@@ -37,7 +36,8 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
-#include <linux/fsl_devices.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -48,7 +48,8 @@
 #include <linux/workqueue.h>
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
-#include "gianfar_phy.h"
+#include <linux/fsl_devices.h>
+#include "gianfar_mii.h"
 
 /* The maximum number of packets to be handled in one call of gfar_poll */
 #define GFAR_DEV_WEIGHT 64
@@ -73,7 +74,7 @@
 #define PHY_INIT_TIMEOUT 100000
 #define GFAR_PHY_CHANGE_TIME 2
 
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
 #define DRV_NAME "gfar-enet"
 extern const char gfar_driver_name[];
 extern const char gfar_driver_version[];
@@ -578,12 +579,7 @@ struct gfar {
        u32     hafdup;         /* 0x.50c - Half Duplex Register */
        u32     maxfrm;         /* 0x.510 - Maximum Frame Length Register */
        u8      res18[12];
-       u32     miimcfg;        /* 0x.520 - MII Management Configuration Register */
-       u32     miimcom;        /* 0x.524 - MII Management Command Register */
-       u32     miimadd;        /* 0x.528 - MII Management Address Register */
-       u32     miimcon;        /* 0x.52c - MII Management Control Register */
-       u32     miimstat;       /* 0x.530 - MII Management Status Register */
-       u32     miimind;        /* 0x.534 - MII Management Indicator Register */
+       u8      gfar_mii_regs[24];      /* See gianfar_phy.h */
        u8      res19[4];
        u32     ifstat;         /* 0x.53c - Interface Status Register */
        u32     macstnaddr1;    /* 0x.540 - Station Address Part 1 Register */
@@ -688,9 +684,6 @@ struct gfar_private {
        struct gfar *regs;      /* Pointer to the GFAR memory mapped Registers */
        u32 *hash_regs[16];
        int hash_width;
-       struct gfar *phyregs;
-       struct work_struct tq;
-       struct timer_list phy_info_timer;
        struct net_device_stats stats; /* linux network statistics */
        struct gfar_extra_stats extra_stats;
        spinlock_t lock;
@@ -710,7 +703,8 @@ struct gfar_private {
        unsigned int interruptError;
        struct gianfar_platform_data *einfo;
 
-       struct gfar_mii_info *mii_info;
+       struct phy_device *phydev;
+       struct mii_bus *mii_bus;
        int oldspeed;
        int oldduplex;
        int oldlink;
@@ -732,4 +726,12 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
 
 extern struct ethtool_ops *gfar_op_array[];
 
+extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_halt(struct net_device *dev);
+extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
+               int enable, u32 regnum, u32 read);
+void gfar_setup_stashing(struct net_device *dev);
+
 #endif /* __GIANFAR_H */
index a451de629197b13e1204f59b2707fef1d425e91d..68e3578e76133b8783b5dcfa1db03367c5e0d9ac 100644 (file)
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include "gianfar.h"
 
 #define is_power_of_2(x)        ((x) != 0 && (((x) & ((x) - 1)) == 0))
 
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
 extern void gfar_start(struct net_device *dev);
 extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 
+#define GFAR_MAX_COAL_USECS 0xffff
+#define GFAR_MAX_COAL_FRAMES 0xff
 static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
                     u64 * buf);
 static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
@@ -182,38 +183,32 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
        drvinfo->eedump_len = 0;
 }
 
+
+static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       struct phy_device *phydev = priv->phydev;
+
+       if (NULL == phydev)
+               return -ENODEV;
+
+       return phy_ethtool_sset(phydev, cmd);
+}
+
+
 /* Return the current settings in the ethtool_cmd structure */
 static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       uint gigabit_support = 
-               priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
-                       SUPPORTED_1000baseT_Full : 0;
-       uint gigabit_advert = 
-               priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
-                       ADVERTISED_1000baseT_Full: 0;
-
-       cmd->supported = (SUPPORTED_10baseT_Half
-                         | SUPPORTED_100baseT_Half
-                         | SUPPORTED_100baseT_Full
-                         | gigabit_support | SUPPORTED_Autoneg);
-
-       /* For now, we always advertise everything */
-       cmd->advertising = (ADVERTISED_10baseT_Half
-                           | ADVERTISED_100baseT_Half
-                           | ADVERTISED_100baseT_Full
-                           | gigabit_advert | ADVERTISED_Autoneg);
-
-       cmd->speed = priv->mii_info->speed;
-       cmd->duplex = priv->mii_info->duplex;
-       cmd->port = PORT_MII;
-       cmd->phy_address = priv->mii_info->mii_id;
-       cmd->transceiver = XCVR_EXTERNAL;
-       cmd->autoneg = AUTONEG_ENABLE;
+       struct phy_device *phydev = priv->phydev;
+
+       if (NULL == phydev)
+               return -ENODEV;
+       
        cmd->maxtxpkt = priv->txcount;
        cmd->maxrxpkt = priv->rxcount;
 
-       return 0;
+       return phy_ethtool_gset(phydev, cmd);
 }
 
 /* Return the length of the register structure */
@@ -241,14 +236,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
        unsigned int count;
 
        /* The timer is different, depending on the interface speed */
-       switch (priv->mii_info->speed) {
-       case 1000:
+       switch (priv->phydev->speed) {
+       case SPEED_1000:
                count = GFAR_GBIT_TIME;
                break;
-       case 100:
+       case SPEED_100:
                count = GFAR_100_TIME;
                break;
-       case 10:
+       case SPEED_10:
        default:
                count = GFAR_10_TIME;
                break;
@@ -265,14 +260,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
        unsigned int count;
 
        /* The timer is different, depending on the interface speed */
-       switch (priv->mii_info->speed) {
-       case 1000:
+       switch (priv->phydev->speed) {
+       case SPEED_1000:
                count = GFAR_GBIT_TIME;
                break;
-       case 100:
+       case SPEED_100:
                count = GFAR_100_TIME;
                break;
-       case 10:
+       case SPEED_10:
        default:
                count = GFAR_10_TIME;
                break;
@@ -292,6 +287,9 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
        if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
                return -EOPNOTSUPP;
 
+       if (NULL == priv->phydev)
+               return -ENODEV;
+
        cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
        cvals->rx_max_coalesced_frames = priv->rxcount;
 
@@ -348,6 +346,22 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
        else
                priv->rxcoalescing = 1;
 
+       if (NULL == priv->phydev)
+               return -ENODEV;
+
+       /* Check the bounds of the values */
+       if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+               pr_info("Coalescing is limited to %d microseconds\n",
+                               GFAR_MAX_COAL_USECS);
+               return -EINVAL;
+       }
+
+       if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+               pr_info("Coalescing is limited to %d frames\n",
+                               GFAR_MAX_COAL_FRAMES);
+               return -EINVAL;
+       }
+
        priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
        priv->rxcount = cvals->rx_max_coalesced_frames;
 
@@ -358,6 +372,19 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
        else
                priv->txcoalescing = 1;
 
+       /* Check the bounds of the values */
+       if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+               pr_info("Coalescing is limited to %d microseconds\n",
+                               GFAR_MAX_COAL_USECS);
+               return -EINVAL;
+       }
+
+       if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+               pr_info("Coalescing is limited to %d frames\n",
+                               GFAR_MAX_COAL_FRAMES);
+               return -EINVAL;
+       }
+
        priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
        priv->txcount = cvals->tx_max_coalesced_frames;
 
@@ -536,6 +563,7 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
 
 struct ethtool_ops gfar_ethtool_ops = {
        .get_settings = gfar_gsettings,
+       .set_settings = gfar_ssettings,
        .get_drvinfo = gfar_gdrvinfo,
        .get_regs_len = gfar_reglen,
        .get_regs = gfar_get_regs,
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
new file mode 100644 (file)
index 0000000..1eca1db
--- /dev/null
@@ -0,0 +1,219 @@
+/* 
+ * drivers/net/gianfar_mii.c
+ *
+ * Gianfar Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <asm/ocp.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "gianfar.h"
+#include "gianfar_mii.h"
+
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+       struct gfar_mii *regs = bus->priv;
+
+       /* Set the PHY address and the register address we want to write */
+       gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+       /* Write out the value we want */
+       gfar_write(&regs->miimcon, value);
+
+       /* Wait for the transaction to finish */
+       while (gfar_read(&regs->miimind) & MIIMIND_BUSY)
+               cpu_relax();
+
+       return 0;
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+       struct gfar_mii *regs = bus->priv;
+       u16 value;
+
+       /* Set the PHY address and the register address we want to read */
+       gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+       /* Clear miimcom, and then initiate a read */
+       gfar_write(&regs->miimcom, 0);
+       gfar_write(&regs->miimcom, MII_READ_COMMAND);
+
+       /* Wait for the transaction to finish */
+       while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+               cpu_relax();
+
+       /* Grab the value of the register from miimstat */
+       value = gfar_read(&regs->miimstat);
+
+       return value;
+}
+
+
+/* Reset the MIIM registers, and wait for the bus to free */
+int gfar_mdio_reset(struct mii_bus *bus)
+{
+       struct gfar_mii *regs = bus->priv;
+       unsigned int timeout = PHY_INIT_TIMEOUT;
+
+       spin_lock_bh(&bus->mdio_lock);
+
+       /* Reset the management interface */
+       gfar_write(&regs->miimcfg, MIIMCFG_RESET);
+
+       /* Setup the MII Mgmt clock speed */
+       gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+       /* Wait until the bus is free */
+       while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) &&
+                       timeout--)
+               cpu_relax();
+
+       spin_unlock_bh(&bus->mdio_lock);
+
+       if(timeout <= 0) {
+               printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+                               bus->name);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+
+int gfar_mdio_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct gianfar_mdio_data *pdata;
+       struct gfar_mii *regs;
+       struct mii_bus *new_bus;
+       int err = 0;
+
+       if (NULL == dev)
+               return -EINVAL;
+
+       new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus)
+               return -ENOMEM;
+
+       new_bus->name = "Gianfar MII Bus",
+       new_bus->read = &gfar_mdio_read,
+       new_bus->write = &gfar_mdio_write,
+       new_bus->reset = &gfar_mdio_reset,
+       new_bus->id = pdev->id;
+
+       pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+       if (NULL == pdata) {
+               printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+               return -ENODEV;
+       }
+
+       /* Set the PHY base address */
+       regs = (struct gfar_mii *) ioremap(pdata->paddr, 
+                       sizeof (struct gfar_mii));
+
+       if (NULL == regs) {
+               err = -ENOMEM;
+               goto reg_map_fail;
+       }
+
+       new_bus->priv = regs;
+
+       new_bus->irq = pdata->irq;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       err = mdiobus_register(new_bus);
+
+       if (0 != err) {
+               printk (KERN_ERR "%s: Cannot register as MDIO bus\n", 
+                               new_bus->name);
+               goto bus_register_fail;
+       }
+
+       return 0;
+
+bus_register_fail:
+       iounmap((void *) regs);
+reg_map_fail:
+       kfree(new_bus);
+
+       return err;
+}
+
+
+int gfar_mdio_remove(struct device *dev)
+{
+       struct mii_bus *bus = dev_get_drvdata(dev);
+
+       mdiobus_unregister(bus);
+
+       dev_set_drvdata(dev, NULL);
+
+       iounmap((void *) (&bus->priv));
+       bus->priv = NULL;
+       kfree(bus);
+
+       return 0;
+}
+
+static struct device_driver gianfar_mdio_driver = {
+       .name = "fsl-gianfar_mdio",
+       .bus = &platform_bus_type,
+       .probe = gfar_mdio_probe,
+       .remove = gfar_mdio_remove,
+};
+
+int __init gfar_mdio_init(void)
+{
+       return driver_register(&gianfar_mdio_driver);
+}
+
+void __exit gfar_mdio_exit(void)
+{
+       driver_unregister(&gianfar_mdio_driver);
+}
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
new file mode 100644 (file)
index 0000000..56e5665
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+ * drivers/net/gianfar_mii.h
+ *
+ * Gianfar Ethernet Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller in the Gianfar register space
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __GIANFAR_MII_H
+#define __GIANFAR_MII_H
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define MII_READ_COMMAND       0x00000001
+
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+               | SUPPORTED_100baseT_Half \
+               | SUPPORTED_100baseT_Full \
+               | SUPPORTED_Autoneg \
+               | SUPPORTED_MII)
+
+struct gfar_mii {
+       u32     miimcfg;        /* 0x.520 - MII Management Config Register */
+       u32     miimcom;        /* 0x.524 - MII Management Command Register */
+       u32     miimadd;        /* 0x.528 - MII Management Address Register */
+       u32     miimcon;        /* 0x.52c - MII Management Control Register */
+       u32     miimstat;       /* 0x.530 - MII Management Status Register */
+       u32     miimind;        /* 0x.534 - MII Management Indicator Register */
+};
+
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int __init gfar_mdio_init(void);
+void __exit gfar_mdio_exit(void);
+#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
deleted file mode 100644 (file)
index 7c965f2..0000000
+++ /dev/null
@@ -1,661 +0,0 @@
-/* 
- * drivers/net/gianfar_phy.c
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-
-#include "gianfar.h"
-#include "gianfar_phy.h"
-
-static void config_genmii_advert(struct gfar_mii_info *mii_info);
-static void genmii_setup_forced(struct gfar_mii_info *mii_info);
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
-static int gbit_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_update_link(struct gfar_mii_info *mii_info);
-static int genmii_read_status(struct gfar_mii_info *mii_info);
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns.  All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
-{
-       struct gfar_private *priv = netdev_priv(dev);
-       struct gfar *regbase = priv->phyregs;
-
-       /* Set the PHY address and the register address we want to write */
-       gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
-       /* Write out the value we want */
-       gfar_write(&regbase->miimcon, value);
-
-       /* Wait for the transaction to finish */
-       while (gfar_read(&regbase->miimind) & MIIMIND_BUSY)
-               cpu_relax();
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value.  Clears miimcom first.  All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
-{
-       struct gfar_private *priv = netdev_priv(dev);
-       struct gfar *regbase = priv->phyregs;
-       u16 value;
-
-       /* Set the PHY address and the register address we want to read */
-       gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
-       /* Clear miimcom, and then initiate a read */
-       gfar_write(&regbase->miimcom, 0);
-       gfar_write(&regbase->miimcom, MII_READ_COMMAND);
-
-       /* Wait for the transaction to finish */
-       while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
-               cpu_relax();
-
-       /* Grab the value of the register from miimstat */
-       value = gfar_read(&regbase->miimstat);
-
-       return value;
-}
-
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
-{
-       if(mii_info->phyinfo->ack_interrupt)
-               mii_info->phyinfo->ack_interrupt(mii_info);
-}
-
-
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
-{
-       mii_info->interrupts = interrupts;
-       if(mii_info->phyinfo->config_intr)
-               mii_info->phyinfo->config_intr(mii_info);
-}
-
-
-/* Writes MII_ADVERTISE with the appropriate values, after
- * sanitizing advertise to make sure only supported features
- * are advertised 
- */
-static void config_genmii_advert(struct gfar_mii_info *mii_info)
-{
-       u32 advertise;
-       u16 adv;
-
-       /* Only allow advertising what this PHY supports */
-       mii_info->advertising &= mii_info->phyinfo->features;
-       advertise = mii_info->advertising;
-
-       /* Setup standard advertisement */
-       adv = phy_read(mii_info, MII_ADVERTISE);
-       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-       if (advertise & ADVERTISED_10baseT_Half)
-               adv |= ADVERTISE_10HALF;
-       if (advertise & ADVERTISED_10baseT_Full)
-               adv |= ADVERTISE_10FULL;
-       if (advertise & ADVERTISED_100baseT_Half)
-               adv |= ADVERTISE_100HALF;
-       if (advertise & ADVERTISED_100baseT_Full)
-               adv |= ADVERTISE_100FULL;
-       phy_write(mii_info, MII_ADVERTISE, adv);
-}
-
-static void genmii_setup_forced(struct gfar_mii_info *mii_info)
-{
-       u16 ctrl;
-       u32 features = mii_info->phyinfo->features;
-       
-       ctrl = phy_read(mii_info, MII_BMCR);
-
-       ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
-       ctrl |= BMCR_RESET;
-
-       switch(mii_info->speed) {
-               case SPEED_1000:
-                       if(features & (SUPPORTED_1000baseT_Half
-                                               | SUPPORTED_1000baseT_Full)) {
-                               ctrl |= BMCR_SPEED1000;
-                               break;
-                       }
-                       mii_info->speed = SPEED_100;
-               case SPEED_100:
-                       if (features & (SUPPORTED_100baseT_Half
-                                               | SUPPORTED_100baseT_Full)) {
-                               ctrl |= BMCR_SPEED100;
-                               break;
-                       }
-                       mii_info->speed = SPEED_10;
-               case SPEED_10:
-                       if (features & (SUPPORTED_10baseT_Half
-                                               | SUPPORTED_10baseT_Full))
-                               break;
-               default: /* Unsupported speed! */
-                       printk(KERN_ERR "%s: Bad speed!\n", 
-                                       mii_info->dev->name);
-                       break;
-       }
-
-       phy_write(mii_info, MII_BMCR, ctrl);
-}
-
-
-/* Enable and Restart Autonegotiation */
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
-{
-       u16 ctl;
-
-       ctl = phy_read(mii_info, MII_BMCR);
-       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-       phy_write(mii_info, MII_BMCR, ctl);
-}
-
-
-static int gbit_config_aneg(struct gfar_mii_info *mii_info)
-{
-       u16 adv;
-       u32 advertise;
-
-       if(mii_info->autoneg) {
-               /* Configure the ADVERTISE register */
-               config_genmii_advert(mii_info);
-               advertise = mii_info->advertising;
-
-               adv = phy_read(mii_info, MII_1000BASETCONTROL);
-               adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
-                               MII_1000BASETCONTROL_HALFDUPLEXCAP);
-               if (advertise & SUPPORTED_1000baseT_Half)
-                       adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
-               if (advertise & SUPPORTED_1000baseT_Full)
-                       adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
-               phy_write(mii_info, MII_1000BASETCONTROL, adv);
-
-               /* Start/Restart aneg */
-               genmii_restart_aneg(mii_info);
-       } else
-               genmii_setup_forced(mii_info);
-
-       return 0;
-}
-
-static int marvell_config_aneg(struct gfar_mii_info *mii_info)
-{
-       /* The Marvell PHY has an errata which requires
-        * that certain registers get written in order
-        * to restart autonegotiation */
-       phy_write(mii_info, MII_BMCR, BMCR_RESET);
-
-       phy_write(mii_info, 0x1d, 0x1f);
-       phy_write(mii_info, 0x1e, 0x200c);
-       phy_write(mii_info, 0x1d, 0x5);
-       phy_write(mii_info, 0x1e, 0);
-       phy_write(mii_info, 0x1e, 0x100);
-
-       gbit_config_aneg(mii_info);
-
-       return 0;
-}
-static int genmii_config_aneg(struct gfar_mii_info *mii_info)
-{
-       if (mii_info->autoneg) {
-               config_genmii_advert(mii_info);
-               genmii_restart_aneg(mii_info);
-       } else
-               genmii_setup_forced(mii_info);
-
-       return 0;
-}
-
-
-static int genmii_update_link(struct gfar_mii_info *mii_info)
-{
-       u16 status;
-
-       /* Do a fake read */
-       phy_read(mii_info, MII_BMSR);
-
-       /* Read link and autonegotiation status */
-       status = phy_read(mii_info, MII_BMSR);
-       if ((status & BMSR_LSTATUS) == 0)
-               mii_info->link = 0;
-       else
-               mii_info->link = 1;
-
-       /* If we are autonegotiating, and not done, 
-        * return an error */
-       if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
-               return -EAGAIN;
-
-       return 0;
-}
-
-static int genmii_read_status(struct gfar_mii_info *mii_info)
-{
-       u16 status;
-       int err;
-
-       /* Update the link, but return if there
-        * was an error */
-       err = genmii_update_link(mii_info);
-       if (err)
-               return err;
-
-       if (mii_info->autoneg) {
-               status = phy_read(mii_info, MII_LPA);
-
-               if (status & (LPA_10FULL | LPA_100FULL))
-                       mii_info->duplex = DUPLEX_FULL;
-               else
-                       mii_info->duplex = DUPLEX_HALF;
-               if (status & (LPA_100FULL | LPA_100HALF))
-                       mii_info->speed = SPEED_100;
-               else
-                       mii_info->speed = SPEED_10;
-               mii_info->pause = 0;
-       }
-       /* On non-aneg, we assume what we put in BMCR is the speed,
-        * though magic-aneg shouldn't prevent this case from occurring
-        */
-
-       return 0;
-}
-static int marvell_read_status(struct gfar_mii_info *mii_info)
-{
-       u16 status;
-       int err;
-
-       /* Update the link, but return if there
-        * was an error */
-       err = genmii_update_link(mii_info);
-       if (err)
-               return err;
-
-       /* If the link is up, read the speed and duplex */
-       /* If we aren't autonegotiating, assume speeds 
-        * are as set */
-       if (mii_info->autoneg && mii_info->link) {
-               int speed;
-               status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
-
-#if 0
-               /* If speed and duplex aren't resolved,
-                * return an error.  Isn't this handled
-                * by checking aneg?
-                */
-               if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
-                       return -EAGAIN;
-#endif
-
-               /* Get the duplexity */
-               if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
-                       mii_info->duplex = DUPLEX_FULL;
-               else
-                       mii_info->duplex = DUPLEX_HALF;
-
-               /* Get the speed */
-               speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
-               switch(speed) {
-                       case MII_M1011_PHY_SPEC_STATUS_1000:
-                               mii_info->speed = SPEED_1000;
-                               break;
-                       case MII_M1011_PHY_SPEC_STATUS_100:
-                               mii_info->speed = SPEED_100;
-                               break;
-                       default:
-                               mii_info->speed = SPEED_10;
-                               break;
-               }
-               mii_info->pause = 0;
-       }
-
-       return 0;
-}
-
-
-static int cis820x_read_status(struct gfar_mii_info *mii_info)
-{
-       u16 status;
-       int err;
-
-       /* Update the link, but return if there
-        * was an error */
-       err = genmii_update_link(mii_info);
-       if (err)
-               return err;
-
-       /* If the link is up, read the speed and duplex */
-       /* If we aren't autonegotiating, assume speeds 
-        * are as set */
-       if (mii_info->autoneg && mii_info->link) {
-               int speed;
-
-               status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
-               if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
-                       mii_info->duplex = DUPLEX_FULL;
-               else
-                       mii_info->duplex = DUPLEX_HALF;
-
-               speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
-
-               switch (speed) {
-               case MII_CIS8201_AUXCONSTAT_GBIT:
-                       mii_info->speed = SPEED_1000;
-                       break;
-               case MII_CIS8201_AUXCONSTAT_100:
-                       mii_info->speed = SPEED_100;
-                       break;
-               default:
-                       mii_info->speed = SPEED_10;
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-       /* Clear the interrupts by reading the reg */
-       phy_read(mii_info, MII_M1011_IEVENT);
-
-       return 0;
-}
-
-static int marvell_config_intr(struct gfar_mii_info *mii_info)
-{
-       if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
-               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
-       else
-               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
-
-       return 0;
-}
-
-static int cis820x_init(struct gfar_mii_info *mii_info)
-{
-       phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, 
-                       MII_CIS8201_AUXCONSTAT_INIT);
-       phy_write(mii_info, MII_CIS8201_EXT_CON1,
-                       MII_CIS8201_EXTCON1_INIT);
-
-       return 0;
-}
-
-static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-       phy_read(mii_info, MII_CIS8201_ISTAT);
-
-       return 0;
-}
-
-static int cis820x_config_intr(struct gfar_mii_info *mii_info)
-{
-       if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
-               phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
-       else
-               phy_write(mii_info, MII_CIS8201_IMASK, 0);
-
-       return 0;
-}
-
-#define DM9161_DELAY 10
-
-static int dm9161_read_status(struct gfar_mii_info *mii_info)
-{
-       u16 status;
-       int err;
-
-       /* Update the link, but return if there
-        * was an error */
-       err = genmii_update_link(mii_info);
-       if (err)
-               return err;
-
-       /* If the link is up, read the speed and duplex */
-       /* If we aren't autonegotiating, assume speeds 
-        * are as set */
-       if (mii_info->autoneg && mii_info->link) {
-               status = phy_read(mii_info, MII_DM9161_SCSR);
-               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
-                       mii_info->speed = SPEED_100;
-               else
-                       mii_info->speed = SPEED_10;
-
-               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
-                       mii_info->duplex = DUPLEX_FULL;
-               else
-                       mii_info->duplex = DUPLEX_HALF;
-       }
-
-       return 0;
-}
-
-
-static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
-{
-       struct dm9161_private *priv = mii_info->priv;
-
-       if(0 == priv->resetdone)
-               return -EAGAIN;
-
-       return 0;
-}
-
-static void dm9161_timer(unsigned long data)
-{
-       struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
-       struct dm9161_private *priv = mii_info->priv;
-       u16 status = phy_read(mii_info, MII_BMSR);
-
-       if (status & BMSR_ANEGCOMPLETE) {
-               priv->resetdone = 1;
-       } else
-               mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-}
-
-static int dm9161_init(struct gfar_mii_info *mii_info)
-{
-       struct dm9161_private *priv;
-
-       /* Allocate the private data structure */
-       priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
-
-       if (NULL == priv)
-               return -ENOMEM;
-
-       mii_info->priv = priv;
-
-       /* Reset is not done yet */
-       priv->resetdone = 0;
-
-       /* Isolate the PHY */
-       phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
-
-       /* Do not bypass the scrambler/descrambler */
-       phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
-
-       /* Clear 10BTCSR to default */
-       phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
-
-       /* Reconnect the PHY, and enable Autonegotiation */
-       phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
-
-       /* Start a timer for DM9161_DELAY seconds to wait
-        * for the PHY to be ready */
-       init_timer(&priv->timer);
-       priv->timer.function = &dm9161_timer;
-       priv->timer.data = (unsigned long) mii_info;
-       mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-
-       return 0;
-}
-
-static void dm9161_close(struct gfar_mii_info *mii_info)
-{
-       struct dm9161_private *priv = mii_info->priv;
-
-       del_timer_sync(&priv->timer);
-       kfree(priv);
-}
-
-#if 0
-static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-       phy_read(mii_info, MII_DM9161_INTR);
-
-       return 0;
-}
-#endif
-
-/* Cicada 820x */
-static struct phy_info phy_info_cis820x = {
-       0x000fc440,
-       "Cicada Cis8204",
-       0x000fffc0,
-       .features       = MII_GBIT_FEATURES,
-       .init           = &cis820x_init,
-       .config_aneg    = &gbit_config_aneg,
-       .read_status    = &cis820x_read_status,
-       .ack_interrupt  = &cis820x_ack_interrupt,
-       .config_intr    = &cis820x_config_intr,
-};
-
-static struct phy_info phy_info_dm9161 = {
-       .phy_id         = 0x0181b880,
-       .name           = "Davicom DM9161E",
-       .phy_id_mask    = 0x0ffffff0,
-       .init           = dm9161_init,
-       .config_aneg    = dm9161_config_aneg,
-       .read_status    = dm9161_read_status,
-       .close          = dm9161_close,
-};
-
-static struct phy_info phy_info_marvell = {
-       .phy_id         = 0x01410c00,
-       .phy_id_mask    = 0xffffff00,
-       .name           = "Marvell 88E1101/88E1111",
-       .features       = MII_GBIT_FEATURES,
-       .config_aneg    = &marvell_config_aneg,
-       .read_status    = &marvell_read_status,
-       .ack_interrupt  = &marvell_ack_interrupt,
-       .config_intr    = &marvell_config_intr,
-};
-
-static struct phy_info phy_info_genmii= {
-       .phy_id         = 0x00000000,
-       .phy_id_mask    = 0x00000000,
-       .name           = "Generic MII",
-       .features       = MII_BASIC_FEATURES,
-       .config_aneg    = genmii_config_aneg,
-       .read_status    = genmii_read_status,
-};
-
-static struct phy_info *phy_info[] = {
-       &phy_info_cis820x,
-       &phy_info_marvell,
-       &phy_info_dm9161,
-       &phy_info_genmii,
-       NULL
-};
-
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
-{
-       u16 retval;
-       unsigned long flags;
-
-       spin_lock_irqsave(&mii_info->mdio_lock, flags);
-       retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
-       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
-       return retval;
-}
-
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&mii_info->mdio_lock, flags);
-       mii_info->mdio_write(mii_info->dev, 
-                       mii_info->mii_id, 
-                       regnum, val);
-       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
-/* Use the PHY ID registers to determine what type of PHY is attached
- * to device dev.  return a struct phy_info structure describing that PHY
- */
-struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
-{
-       u16 phy_reg;
-       u32 phy_ID;
-       int i;
-       struct phy_info *theInfo = NULL;
-       struct net_device *dev = mii_info->dev;
-
-       /* Grab the bits from PHYIR1, and put them in the upper half */
-       phy_reg = phy_read(mii_info, MII_PHYSID1);
-       phy_ID = (phy_reg & 0xffff) << 16;
-
-       /* Grab the bits from PHYIR2, and put them in the lower half */
-       phy_reg = phy_read(mii_info, MII_PHYSID2);
-       phy_ID |= (phy_reg & 0xffff);
-
-       /* loop through all the known PHY types, and find one that */
-       /* matches the ID we read from the PHY. */
-       for (i = 0; phy_info[i]; i++)
-               if (phy_info[i]->phy_id == 
-                               (phy_ID & phy_info[i]->phy_id_mask)) {
-                       theInfo = phy_info[i];
-                       break;
-               }
-
-       /* This shouldn't happen, as we have generic PHY support */
-       if (theInfo == NULL) {
-               printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
-               return NULL;
-       } else {
-               printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
-                      phy_ID);
-       }
-
-       return theInfo;
-}
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
deleted file mode 100644 (file)
index 1e9b3ab..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* 
- * drivers/net/gianfar_phy.h
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY            0x00000001
-#define MIIMIND_NOTVALID        0x00000004
-
-#define GFAR_AN_TIMEOUT         2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL                   0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP     0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP     0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1           0x17
-#define MII_CIS8201_EXTCON1_INIT       0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK              0x19
-#define MII_CIS8201_IMASK_IEN          0x8000
-#define MII_CIS8201_IMASK_SPEED        0x4000
-#define MII_CIS8201_IMASK_LINK         0x2000
-#define MII_CIS8201_IMASK_DUPLEX       0x1000
-#define MII_CIS8201_IMASK_MASK         0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT              0x1a
-#define MII_CIS8201_ISTAT_STATUS       0x8000
-#define MII_CIS8201_ISTAT_SPEED        0x4000
-#define MII_CIS8201_ISTAT_LINK         0x2000
-#define MII_CIS8201_ISTAT_DUPLEX       0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT        0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
-#define MII_CIS8201_AUXCONSTAT_100     0x0008
-                                                                                
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS              0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000         0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100          0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK     0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX   0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED     0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK         0x0400
-
-#define MII_M1011_IEVENT               0x13
-#define MII_M1011_IEVENT_CLEAR         0x0000
-
-#define MII_M1011_IMASK                        0x12
-#define MII_M1011_IMASK_INIT           0x6400
-#define MII_M1011_IMASK_CLEAR          0x0000
-
-#define MII_DM9161_SCR         0x10
-#define MII_DM9161_SCR_INIT    0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR        0x11
-#define MII_DM9161_SCSR_100F   0x8000
-#define MII_DM9161_SCSR_100H   0x4000
-#define MII_DM9161_SCSR_10F    0x2000
-#define MII_DM9161_SCSR_10H    0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR        0x15
-#define MII_DM9161_INTR_PEND           0x8000
-#define MII_DM9161_INTR_DPLX_MASK      0x0800
-#define MII_DM9161_INTR_SPD_MASK       0x0400
-#define MII_DM9161_INTR_LINK_MASK      0x0200
-#define MII_DM9161_INTR_MASK           0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE    0x0010
-#define MII_DM9161_INTR_SPD_CHANGE     0x0008
-#define MII_DM9161_INTR_LINK_CHANGE    0x0004
-#define MII_DM9161_INTR_INIT           0x0000
-#define MII_DM9161_INTR_STOP   \
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR     0x12
-#define MII_DM9161_10BTCSR_INIT        0x7800
-
-#define MII_BASIC_FEATURES     (SUPPORTED_10baseT_Half | \
-                                SUPPORTED_10baseT_Full | \
-                                SUPPORTED_100baseT_Half | \
-                                SUPPORTED_100baseT_Full | \
-                                SUPPORTED_Autoneg | \
-                                SUPPORTED_TP | \
-                                SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES      (MII_BASIC_FEATURES | \
-                                SUPPORTED_1000baseT_Half | \
-                                SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND       0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
-       /* Information about the PHY type */
-       /* And management functions */
-       struct phy_info *phyinfo;
-
-       /* forced speed & duplex (no autoneg)
-        * partner speed & duplex & pause (autoneg)
-        */
-       int speed;
-       int duplex;
-       int pause;
-
-       /* The most recently read link state */
-       int link;
-
-       /* Enabled Interrupts */
-       u32 interrupts;
-
-       u32 advertising;
-       int autoneg;
-       int mii_id;
-
-       /* private data pointer */
-       /* For use by PHYs to maintain extra state */
-       void *priv;
-
-       /* Provided by host chip */
-       struct net_device *dev;
-
-       /* A lock to ensure that only one thing can read/write
-        * the MDIO bus at a time */
-       spinlock_t mdio_lock;
-
-       /* Provided by ethernet driver */
-       int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
-       void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
-       u32 phy_id;
-       char *name;
-       unsigned int phy_id_mask;
-       u32 features;
-
-       /* Called to initialize the PHY */
-       int (*init)(struct gfar_mii_info *mii_info);
-
-       /* Called to suspend the PHY for power */
-       int (*suspend)(struct gfar_mii_info *mii_info);
-
-       /* Reconfigures autonegotiation (or disables it) */
-       int (*config_aneg)(struct gfar_mii_info *mii_info);
-
-       /* Determines the negotiated speed and duplex */
-       int (*read_status)(struct gfar_mii_info *mii_info);
-
-       /* Clears any pending interrupts */
-       int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
-       /* Enables or disables interrupts */
-       int (*config_intr)(struct gfar_mii_info *mii_info);
-
-       /* Clears up any memory if needed */
-       void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
-       struct timer_list timer;
-       int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
index de087cd609d98fcf916c638187ed0df9b0e9eb59..896aa02000d73079fc1ebda3b222c90cdfe3531e 100644 (file)
@@ -1,6 +1,7 @@
 config MKISS
        tristate "Serial port KISS driver"
        depends on AX25
+       select CRC16
        ---help---
          KISS is a protocol used for the exchange of data between a computer
          and a Terminal Node Controller (a small embedded system commonly
index 1756f0ed54ccc7a43de7613896f090d38c98f365..cb43a9d28774fa8886dbfed420cc69c13312df74 100644 (file)
@@ -144,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
 {
        struct bpqdev *bpq;
 
-       list_for_each_entry(bpq, &bpq_devices, bpq_list) {
+       list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
                if (bpq->ethdev == dev)
                        return bpq->axdev;
        }
@@ -399,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
        if (*pos == 0)
                return SEQ_START_TOKEN;
        
-       list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
+       list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
                if (i == *pos)
                        return bpqdev;
        }
@@ -418,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                p = ((struct bpqdev *)v)->bpq_list.next;
 
        return (p == &bpq_devices) ? NULL 
-               : list_entry(p, struct bpqdev, bpq_list);
+               : rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
 }
 
 static void bpq_seq_stop(struct seq_file *seq, void *v)
@@ -561,8 +561,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
        if (!dev_is_ethdev(dev))
                return NOTIFY_DONE;
 
-       rcu_read_lock();
-
        switch (event) {
        case NETDEV_UP:         /* new ethernet device -> new BPQ interface */
                if (bpq_get_ax25_dev(dev) == NULL)
@@ -581,7 +579,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
        default:
                break;
        }
-       rcu_read_unlock();
 
        return NOTIFY_DONE;
 }
index d9fe64b46f4bf4bc1505bee23f2e8e92c86fa772..85d6dc005be0f016aa2b64af184778de4641a37d 100644 (file)
  *
  * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
  * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
+ * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
  */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/system.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
+#include <linux/crc16.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
 #include <net/ax25.h>
 
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#endif
-
 #define AX_MTU         236
 
 /* SLIP/KISS protocol characters. */
@@ -80,9 +76,13 @@ struct mkiss {
 
        int             mode;
         int            crcmode;        /* MW: for FlexNet, SMACK etc.  */
-#define CRC_MODE_NONE   0
-#define CRC_MODE_FLEX   1
-#define CRC_MODE_SMACK  2
+       int             crcauto;        /* CRC auto mode */
+
+#define CRC_MODE_NONE          0
+#define CRC_MODE_FLEX          1
+#define CRC_MODE_SMACK         2
+#define CRC_MODE_FLEX_TEST     3
+#define CRC_MODE_SMACK_TEST    4
 
        atomic_t                refcnt;
        struct semaphore        dead_sem;
@@ -151,6 +151,21 @@ static int check_crc_flex(unsigned char *cp, int size)
        return 0;
 }
 
+static int check_crc_16(unsigned char *cp, int size)
+{
+       unsigned short crc = 0x0000;
+
+       if (size < 3)
+               return -1;
+
+       crc = crc16(0, cp, size);
+
+       if (crc != 0x0000)
+               return -1;
+
+       return 0;
+}
+
 /*
  * Standard encapsulation
  */
@@ -237,19 +252,42 @@ static void ax_bump(struct mkiss *ax)
 
        spin_lock_bh(&ax->buflock);
        if (ax->rbuff[0] > 0x0f) {
-               if (ax->rbuff[0] & 0x20) {
-                       ax->crcmode = CRC_MODE_FLEX;
+               if (ax->rbuff[0] & 0x80) {
+                       if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
+                               ax->stats.rx_errors++;
+                               spin_unlock_bh(&ax->buflock);
+
+                               return;
+                       }
+                       if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
+                               printk(KERN_INFO
+                                      "mkiss: %s: Switchting to crc-smack\n",
+                                      ax->dev->name);
+                               ax->crcmode = CRC_MODE_SMACK;
+                       }
+                       ax->rcount -= 2;
+                       *ax->rbuff &= ~0x80;
+               } else if (ax->rbuff[0] & 0x20)  {
                        if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-                               ax->stats.rx_errors++;
+                               ax->stats.rx_errors++;
+                               spin_unlock_bh(&ax->buflock);
                                return;
                        }
+                       if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
+                               printk(KERN_INFO
+                                      "mkiss: %s: Switchting to crc-flexnet\n",
+                                      ax->dev->name);
+                               ax->crcmode = CRC_MODE_FLEX;
+                       }
                        ax->rcount -= 2;
-                        /* dl9sau bugfix: the trailling two bytes flexnet crc
-                         * will not be passed to the kernel. thus we have
-                         * to correct the kissparm signature, because it
-                         * indicates a crc but there's none
+
+                       /*
+                        * dl9sau bugfix: the trailling two bytes flexnet crc
+                        * will not be passed to the kernel. thus we have to
+                        * correct the kissparm signature, because it indicates
+                        * a crc but there's none
                         */
-                        *ax->rbuff &= ~0x20;
+                       *ax->rbuff &= ~0x20;
                }
        }
        spin_unlock_bh(&ax->buflock);
@@ -417,20 +455,69 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
        p = icp;
 
        spin_lock_bh(&ax->buflock);
-        switch (ax->crcmode) {
-                unsigned short crc;
+       if ((*p & 0x0f) != 0) {
+               /* Configuration Command (kissparms(1).
+                * Protocol spec says: never append CRC.
+                * This fixes a very old bug in the linux
+                * kiss driver. -- dl9sau */
+               switch (*p & 0xff) {
+               case 0x85:
+                       /* command from userspace especially for us,
+                        * not for delivery to the tnc */
+                       if (len > 1) {
+                               int cmd = (p[1] & 0xff);
+                               switch(cmd) {
+                               case 3:
+                                 ax->crcmode = CRC_MODE_SMACK;
+                                 break;
+                               case 2:
+                                 ax->crcmode = CRC_MODE_FLEX;
+                                 break;
+                               case 1:
+                                 ax->crcmode = CRC_MODE_NONE;
+                                 break;
+                               case 0:
+                               default:
+                                 ax->crcmode = CRC_MODE_SMACK_TEST;
+                                 cmd = 0;
+                               }
+                               ax->crcauto = (cmd ? 0 : 1);
+                               printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
+                       }
+                       spin_unlock_bh(&ax->buflock);
+                       netif_start_queue(dev);
 
-       case CRC_MODE_FLEX:
-                *p |= 0x20;
-                crc = calc_crc_flex(p, len);
-                count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
-                break;
+                       return;
+               default:
+                       count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+               }
+       } else {
+               unsigned short crc;
+               switch (ax->crcmode) {
+               case CRC_MODE_SMACK_TEST:
+                       ax->crcmode  = CRC_MODE_FLEX_TEST;
+                       printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
+                       // fall through
+               case CRC_MODE_SMACK:
+                       *p |= 0x80;
+                       crc = swab16(crc16(0, p, len));
+                       count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+                       break;
+               case CRC_MODE_FLEX_TEST:
+                       ax->crcmode = CRC_MODE_NONE;
+                       printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
+                       // fall through
+               case CRC_MODE_FLEX:
+                       *p |= 0x20;
+                       crc = calc_crc_flex(p, len);
+                       count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+                       break;
+
+               default:
+                       count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+               }
+       }
 
-       default:
-                count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
-                break;
-       }
-       
        set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
        actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
        ax->stats.tx_packets++;
@@ -439,8 +526,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
        ax->dev->trans_start = jiffies;
        ax->xleft = count - actual;
        ax->xhead = ax->xbuff + actual;
-
-       spin_unlock_bh(&ax->buflock);
 }
 
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -622,7 +707,7 @@ static void ax_setup(struct net_device *dev)
  * best way to fix this is to use a rwlock in the tty struct, but for now we
  * use a single global rwlock for all ttys in ppp line discipline.
  */
-static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(disc_data_lock);
 
 static struct mkiss *mkiss_get(struct tty_struct *tty)
 {
@@ -643,6 +728,8 @@ static void mkiss_put(struct mkiss *ax)
                up(&ax->dead_sem);
 }
 
+static int crc_force = 0;      /* Can be overridden with insmod */
+
 static int mkiss_open(struct tty_struct *tty)
 {
        struct net_device *dev;
@@ -682,6 +769,33 @@ static int mkiss_open(struct tty_struct *tty)
        if (register_netdev(dev))
                goto out_free_buffers;
 
+       /* after register_netdev() - because else printk smashes the kernel */
+       switch (crc_force) {
+       case 3:
+               ax->crcmode  = CRC_MODE_SMACK;
+               printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
+                      ax->dev->name);
+               break;
+       case 2:
+               ax->crcmode  = CRC_MODE_FLEX;
+               printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
+                      ax->dev->name);
+               break;
+       case 1:
+               ax->crcmode  = CRC_MODE_NONE;
+               printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
+                      ax->dev->name);
+               break;
+       case 0:
+               /* fall through */
+       default:
+               crc_force = 0;
+               printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
+                      ax->dev->name);
+               ax->crcmode  = CRC_MODE_SMACK_TEST;
+       }
+       ax->crcauto = (crc_force ? 0 : 1);
+
        netif_start_queue(dev);
 
        /* Done.  We have linked the TTY line to a channel. */
@@ -765,7 +879,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
 
        case SIOCSIFHWADDR: {
                char addr[AX25_ADDR_LEN];
-printk(KERN_INFO "In SIOCSIFHWADDR");
 
                if (copy_from_user(&addr,
                                   (void __user *) arg, AX25_ADDR_LEN)) {
@@ -864,6 +977,7 @@ out:
 }
 
 static struct tty_ldisc ax_ldisc = {
+       .owner          = THIS_MODULE,
        .magic          = TTY_LDISC_MAGIC,
        .name           = "mkiss",
        .open           = mkiss_open,
@@ -904,6 +1018,8 @@ static void __exit mkiss_exit_driver(void)
 
 MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
 MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
+MODULE_PARM(crc_force, "i");
+MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_AX25);
 
diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
deleted file mode 100644 (file)
index 4ab7004..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
- *     Defines for the Multi-KISS driver.
- ****************************************************************************/
-
-#define AX25_MAXDEV    16              /* MAX number of AX25 channels;
-                                          This can be overridden with
-                                          insmod -oax25_maxdev=nnn     */
-#define AX_MTU         236     
-
-/* SLIP/KISS protocol characters. */
-#define END             0300           /* indicates end of frame       */
-#define ESC             0333           /* indicates byte stuffing      */
-#define ESC_END         0334           /* ESC ESC_END means END 'data' */
-#define ESC_ESC         0335           /* ESC ESC_ESC means ESC 'data' */
-
-struct ax_disp {
-       int                magic;
-
-       /* Various fields. */
-       struct tty_struct  *tty;                /* ptr to TTY structure         */
-       struct net_device      *dev;            /* easy for intr handling       */
-
-       /* These are pointers to the malloc()ed frame buffers. */
-       unsigned char      *rbuff;              /* receiver buffer              */
-       int                rcount;              /* received chars counter       */
-       unsigned char      *xbuff;              /* transmitter buffer           */
-       unsigned char      *xhead;              /* pointer to next byte to XMIT */
-       int                xleft;               /* bytes left in XMIT queue     */
-
-       /* SLIP interface statistics. */
-       unsigned long      rx_packets;          /* inbound frames counter       */
-       unsigned long      tx_packets;          /* outbound frames counter      */
-       unsigned long      rx_bytes;            /* inbound bytes counter        */
-       unsigned long      tx_bytes;            /* outbound bytes counter       */
-       unsigned long      rx_errors;           /* Parity, etc. errors          */
-       unsigned long      tx_errors;           /* Planned stuff                */
-       unsigned long      rx_dropped;          /* No memory for skb            */
-       unsigned long      tx_dropped;          /* When MTU change              */
-       unsigned long      rx_over_errors;      /* Frame bigger then SLIP buf.  */
-
-       /* Detailed SLIP statistics. */
-       int                 mtu;                /* Our mtu (to spot changes!)   */
-       int                 buffsize;           /* Max buffers sizes            */
-
-
-       unsigned long   flags;          /* Flag values/ mode etc        */
-                                       /* long req'd: used by set_bit --RR */
-#define AXF_INUSE      0               /* Channel in use               */
-#define AXF_ESCAPE     1               /* ESC received                 */
-#define AXF_ERROR      2               /* Parity, etc. error           */
-#define AXF_KEEPTEST   3               /* Keepalive test flag          */
-#define AXF_OUTWAIT    4               /* is outpacket was flag        */
-
-       int                 mode;
-        int                 crcmode;    /* MW: for FlexNet, SMACK etc.  */ 
-#define CRC_MODE_NONE   0
-#define CRC_MODE_FLEX   1
-#define CRC_MODE_SMACK  2
-       spinlock_t          buflock;    /* lock for rbuf and xbuf */
-};
-
-#define AX25_MAGIC             0x5316
index cf0ac6fda1a1741390486e2168271cf3fc4ba554..b71fab6e34f4268e0dc53ad9d675cac3f998309a 100644 (file)
@@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net_device *dev)
        do {
                if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
                        break;
-               if (!in_interrupt()) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               if (!in_interrupt())
+                       schedule_timeout_interruptible(1);
        } while (time_after(time, jiffies));
 
        if (time_after_eq(jiffies, time))       /* no signal->no logout */
@@ -2536,10 +2534,8 @@ static int hp100_down_vg_link(struct net_device *dev)
        do {
                if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
                        break;
-               if (!in_interrupt()) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               if (!in_interrupt())
+                       schedule_timeout_interruptible(1);
        } while (time_after(time, jiffies));
 
 #ifdef HP100_DEBUG
@@ -2577,10 +2573,8 @@ static int hp100_down_vg_link(struct net_device *dev)
                do {
                        if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
                                break;
-                       if (!in_interrupt()) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       if (!in_interrupt())
+                               schedule_timeout_interruptible(1);
                } while (time_after(time, jiffies));
 
                hp100_orb(HP100_AUTO_MODE, MAC_CFG_3);  /* Autosel back on */
@@ -2591,10 +2585,8 @@ static int hp100_down_vg_link(struct net_device *dev)
        do {
                if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
                        break;
-               if (!in_interrupt()) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               if (!in_interrupt())
+                       schedule_timeout_interruptible(1);
        } while (time_after(time, jiffies));
 
        if (time_before_eq(time, jiffies)) {
@@ -2606,10 +2598,8 @@ static int hp100_down_vg_link(struct net_device *dev)
 
        time = jiffies + (2 * HZ);      /* This seems to take a while.... */
        do {
-               if (!in_interrupt()) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               if (!in_interrupt())
+                       schedule_timeout_interruptible(1);
        } while (time_after(time, jiffies));
 
        return 0;
@@ -2659,10 +2649,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
                do {
                        if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
                                break;
-                       if (!in_interrupt()) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       if (!in_interrupt())
+                               schedule_timeout_interruptible(1);
                } while (time_after(time, jiffies));
 
                /* Start an addressed training and optionally request promiscuous port */
@@ -2697,10 +2685,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
                do {
                        if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
                                break;
-                       if (!in_interrupt()) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       if (!in_interrupt())
+                               schedule_timeout_interruptible(1);
                } while (time_before(jiffies, time));
 
                if (time_after_eq(jiffies, time)) {
@@ -2723,10 +2709,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
 #endif
                                        break;
                                }
-                               if (!in_interrupt()) {
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                                       schedule_timeout(1);
-                               }
+                               if (!in_interrupt())
+                                       schedule_timeout_interruptible(1);
                        } while (time_after(time, jiffies));
                }
 
index 15f207323d97043b124dd6282835447804abf5aa..3961a754e920e37e8a1b310670edcdb48549a46c 100644 (file)
@@ -678,10 +678,9 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
                return;
 
        ticks = us / (1000000 / HZ);
-       if (ticks > 0) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1 + ticks);
-       } else
+       if (ticks > 0)
+               schedule_timeout_interruptible(1 + ticks);
+       else
                udelay(us);
 }
 
index 9d026ed77ddd4250660ad117d76c2e319e6d3eda..04e47189d830105a848d6b6db71c8dd26f625de9 100644 (file)
@@ -645,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
 
        mod_timer(&adapter->blink_timer, jiffies);
 
-       set_current_state(TASK_INTERRUPTIBLE);
-       if(data)
-               schedule_timeout(data * HZ);
+       if (data)
+               schedule_timeout_interruptible(data * HZ);
        else
-               schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+               schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
 
        del_timer_sync(&adapter->blink_timer);
        ixgb_led_off(&adapter->hw);
@@ -723,6 +722,7 @@ struct ethtool_ops ixgb_ethtool_ops = {
        .phys_id = ixgb_phys_id,
        .get_stats_count = ixgb_get_stats_count,
        .get_ethtool_stats = ixgb_get_ethtool_stats,
+       .get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
index 89d6d69be382a3d625892823d8859cbae8237908..176680cb153e8b114797f4e6a8bad2f1837c678c 100644 (file)
@@ -460,8 +460,9 @@ ixgb_probe(struct pci_dev *pdev,
        }
 
        ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+       memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
-       if(!is_valid_ether_addr(netdev->dev_addr)) {
+       if(!is_valid_ether_addr(netdev->perm_addr)) {
                err = -EIO;
                goto err_eeprom;
        }
index 27f0d8ac4c40d99a869e2cd297007dbeeb487d0e..309d254842cf2f85ab2d0ea7653b98d4132b7248 100644 (file)
@@ -298,7 +298,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
        return 0;
 unmap:
        if (ei_status.reg0)
-               iounmap((void *)dev->mem_start);
+               iounmap(ei_status.mem);
 cleanup:
        free_irq(dev->irq, dev);
        return ret;
index c33cb3dc942b713f993f7ae75f5bede82c5cacc9..e42aa797f08b88ca9f9b71a065e1dab90d4047cd 100644 (file)
@@ -207,6 +207,20 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
        return 0;
 }
 
+int mii_check_gmii_support(struct mii_if_info *mii)
+{
+       int reg;
+
+       reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+       if (reg & BMSR_ESTATEN) {
+               reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
+               if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
+                       return 1;
+       }
+
+       return 0;
+}
+
 int mii_link_ok (struct mii_if_info *mii)
 {
        /* first, a dummy read, needed to latch some MII phys */
@@ -394,5 +408,6 @@ EXPORT_SYMBOL(mii_ethtool_gset);
 EXPORT_SYMBOL(mii_ethtool_sset);
 EXPORT_SYMBOL(mii_check_link);
 EXPORT_SYMBOL(mii_check_media);
+EXPORT_SYMBOL(mii_check_gmii_support);
 EXPORT_SYMBOL(generic_mii_ioctl);
 
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
new file mode 100644 (file)
index 0000000..f79f7ee
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include <asm/mips-boards/simint.h>
+
+#include "mipsnet.h"           /* actual device IO mapping */
+
+#define MIPSNET_VERSION "2005-06-20"
+
+#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
+
+struct mipsnet_priv {
+       struct net_device_stats stats;
+};
+
+static struct platform_device *mips_plat_dev;
+
+static char mipsnet_string[] = "mipsnet";
+
+/*
+ * Copy data from the MIPSNET rx data port
+ */
+static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
+                       int len)
+{
+       uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+       if (available_len < len)
+               return -EFAULT;
+
+       for (; len > 0; len--, kdata++) {
+               *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
+       }
+
+       return inl(mipsnet_reg_address(dev, rxDataCount));
+}
+
+static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
+       struct sk_buff *skb)
+{
+       int count_to_go = skb->len;
+       char *buf_ptr = skb->data;
+       struct mipsnet_priv *mp = netdev_priv(dev);
+
+       pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
+                dev->name, __FUNCTION__, skb->len);
+
+       outl(skb->len, mipsnet_reg_address(dev, txDataCount));
+
+       pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
+                dev->name, __FUNCTION__, skb->len);
+
+       for (; count_to_go; buf_ptr++, count_to_go--) {
+               outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
+       }
+
+       mp->stats.tx_packets++;
+       mp->stats.tx_bytes += skb->len;
+
+       return skb->len;
+}
+
+static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       pr_debug("%s:%s(): transmitting %d bytes\n",
+                dev->name, __FUNCTION__, skb->len);
+
+       /* Only one packet at a time. Once TXDONE interrupt is serviced, the
+        * queue will be restarted.
+        */
+       netif_stop_queue(dev);
+       mipsnet_put_todevice(dev, skb);
+
+       return 0;
+}
+
+static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+{
+       struct sk_buff *skb;
+       size_t len = count;
+       struct mipsnet_priv *mp = netdev_priv(dev);
+
+       if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+               mp->stats.rx_dropped++;
+               return -ENOMEM;
+       }
+
+       skb_reserve(skb, 2);
+       if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+               return -EFAULT;
+
+       skb->dev = dev;
+       skb->protocol = eth_type_trans(skb, dev);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+       pr_debug("%s:%s(): pushing RXed data to kernel\n",
+                dev->name, __FUNCTION__);
+       netif_rx(skb);
+
+       mp->stats.rx_packets++;
+       mp->stats.rx_bytes += len;
+
+       return count;
+}
+
+static irqreturn_t
+mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+
+       irqreturn_t retval = IRQ_NONE;
+       uint64_t interruptFlags;
+
+       if (irq == dev->irq) {
+               pr_debug("%s:%s(): irq %d for device\n",
+                        dev->name, __FUNCTION__, irq);
+
+               retval = IRQ_HANDLED;
+
+               interruptFlags =
+                   inl(mipsnet_reg_address(dev, interruptControl));
+               pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
+                        __FUNCTION__, interruptFlags);
+
+               if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+                       pr_debug("%s:%s(): got TXDone\n",
+                                dev->name, __FUNCTION__);
+                       outl(MIPSNET_INTCTL_TXDONE,
+                            mipsnet_reg_address(dev, interruptControl));
+                       // only one packet at a time, we are done.
+                       netif_wake_queue(dev);
+               } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
+                       pr_debug("%s:%s(): got RX data\n",
+                                dev->name, __FUNCTION__);
+                       mipsnet_get_fromdev(dev,
+                                   inl(mipsnet_reg_address(dev, rxDataCount)));
+                       pr_debug("%s:%s(): clearing RX int\n",
+                                dev->name, __FUNCTION__);
+                       outl(MIPSNET_INTCTL_RXDONE,
+                            mipsnet_reg_address(dev, interruptControl));
+
+               } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+                       pr_debug("%s:%s(): got test interrupt\n",
+                                dev->name, __FUNCTION__);
+                       // TESTBIT is cleared on read.
+                       //    And takes effect after a write with 0
+                       outl(0, mipsnet_reg_address(dev, interruptControl));
+               } else {
+                       pr_debug("%s:%s(): no valid fags 0x%016llx\n",
+                                dev->name, __FUNCTION__, interruptFlags);
+                       // Maybe shared IRQ, just ignore, no clearing.
+                       retval = IRQ_NONE;
+               }
+
+       } else {
+               printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
+                      dev->name, __FUNCTION__, irq);
+               retval = IRQ_NONE;
+       }
+       return retval;
+}                              //mipsnet_interrupt()
+
+static int mipsnet_open(struct net_device *dev)
+{
+       int err;
+       pr_debug("%s: mipsnet_open\n", dev->name);
+
+       err = request_irq(dev->irq, &mipsnet_interrupt,
+                         SA_SHIRQ, dev->name, (void *) dev);
+
+       if (err) {
+               pr_debug("%s: %s(): can't get irq %d\n",
+                        dev->name, __FUNCTION__, dev->irq);
+               release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+               return err;
+       }
+
+       pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
+                dev->name, __FUNCTION__, dev->base_addr, dev->irq);
+
+
+       netif_start_queue(dev);
+
+       // test interrupt handler
+       outl(MIPSNET_INTCTL_TESTBIT,
+            mipsnet_reg_address(dev, interruptControl));
+
+
+       return 0;
+}
+
+static int mipsnet_close(struct net_device *dev)
+{
+       pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
+       netif_stop_queue(dev);
+       return 0;
+}
+
+static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
+{
+       struct mipsnet_priv *mp = netdev_priv(dev);
+
+       return &mp->stats;
+}
+
+static void mipsnet_set_mclist(struct net_device *dev)
+{
+       // we don't do anything
+       return;
+}
+
+static int __init mipsnet_probe(struct device *dev)
+{
+       struct net_device *netdev;
+       int err;
+
+       netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
+       if (!netdev) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       dev_set_drvdata(dev, netdev);
+
+       netdev->open                    = mipsnet_open;
+       netdev->stop                    = mipsnet_close;
+       netdev->hard_start_xmit         = mipsnet_xmit;
+       netdev->get_stats               = mipsnet_get_stats;
+       netdev->set_multicast_list      = mipsnet_set_mclist;
+
+       /*
+        * TODO: probe for these or load them from PARAM
+        */
+       netdev->base_addr = 0x4200;
+       netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+                     inl(mipsnet_reg_address(netdev, interruptInfo));
+
+       // Get the io region now, get irq on open()
+       if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
+               pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
+                        "for dev is not availble.\n", netdev->name,
+                        __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
+               err = -EBUSY;
+               goto out_free_netdev;
+       }
+
+       /*
+        * Lacking any better mechanism to allocate a MAC address we use a
+        * random one ...
+        */
+       random_ether_addr(netdev->dev_addr);
+
+       err = register_netdev(netdev);
+       if (err) {
+               printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
+               goto out_free_region;
+       }
+
+       return 0;
+
+out_free_region:
+       release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
+
+out_free_netdev:
+       free_netdev(netdev);
+
+out:
+       return err;
+}
+
+static int __devexit mipsnet_device_remove(struct device *device)
+{
+       struct net_device *dev = dev_get_drvdata(device);
+
+       unregister_netdev(dev);
+       release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+       free_netdev(dev);
+       dev_set_drvdata(device, NULL);
+
+       return 0;
+}
+
+static struct device_driver mipsnet_driver = {
+       .name   = mipsnet_string,
+       .bus    = &platform_bus_type,
+       .probe  = mipsnet_probe,
+       .remove = __devexit_p(mipsnet_device_remove),
+};
+
+static void mipsnet_platform_release(struct device *device)
+{
+       struct platform_device *pldev;
+
+       /* free device */
+       pldev = to_platform_device(device);
+       kfree(pldev);
+}
+
+static int __init mipsnet_init_module(void)
+{
+       struct platform_device *pldev;
+       int err;
+
+       printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
+              "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
+
+       if (driver_register(&mipsnet_driver)) {
+               printk(KERN_ERR "Driver registration failed\n");
+               err = -ENODEV;
+               goto out;
+       }
+
+        if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto out_unregister_driver;
+       }
+
+       memset (pldev, 0, sizeof (*pldev));
+       pldev->name             = mipsnet_string;
+       pldev->id               = 0;
+       pldev->dev.release      = mipsnet_platform_release;
+
+       if (platform_device_register(pldev)) {
+               err = -ENODEV;
+               goto out_free_pldev;
+       }
+
+        if (!pldev->dev.driver) {
+               /*
+                * The driver was not bound to this device, there was
+                 * no hardware at this address. Unregister it, as the
+                * release fuction will take care of freeing the
+                * allocated structure
+                */
+               platform_device_unregister (pldev);
+       }
+
+       mips_plat_dev           = pldev;
+
+       return 0;
+
+out_free_pldev:
+       kfree(pldev);
+
+out_unregister_driver:
+       driver_unregister(&mipsnet_driver);
+out:
+       return err;
+}
+
+static void __exit mipsnet_exit_module(void)
+{
+       pr_debug("MIPSNet Ethernet driver exiting\n");
+
+       driver_unregister(&mipsnet_driver);
+}
+
+module_init(mipsnet_init_module);
+module_exit(mipsnet_exit_module);
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
new file mode 100644 (file)
index 0000000..8785359
--- /dev/null
@@ -0,0 +1,127 @@
+//
+// <COPYRIGHT CLASS="1B" YEAR="2005">
+// Unpublished work (c) MIPS Technologies, Inc.  All rights reserved.
+// Unpublished rights reserved under the copyright laws of the U.S.A. and
+//  other countries.
+//
+// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
+// FOR INTERNAL USE ONLY.
+//
+// Under no circumstances (contract or otherwise) may this information be
+// disclosed to, or copied, modified or used by anyone other than employees
+// or contractors of MIPS Technologies having a need to know.
+// </COPYRIGHT>
+//
+//++
+// File: MIPS_Net.h
+//
+// Description:
+//   The definition of the emulated MIPSNET device's interface.
+//
+// Notes: This include file needs to work from a Linux device drivers.
+//
+//--
+//
+
+#ifndef __MIPSNET_H
+#define __MIPSNET_H
+
+/*
+ *  Id of this Net device, as seen by the core.
+ */
+#define MIPS_NET_DEV_ID ((uint64_t)           \
+                            ((uint64_t)'M'<< 0)| \
+                            ((uint64_t)'I'<< 8)| \
+                            ((uint64_t)'P'<<16)| \
+                            ((uint64_t)'S'<<24)| \
+                            ((uint64_t)'N'<<32)| \
+                            ((uint64_t)'E'<<40)| \
+                            ((uint64_t)'T'<<48)| \
+                            ((uint64_t)'0'<<56))
+
+/*
+ * Net status/control block as seen by sw in the core.
+ * (Why not use bit fields? can't be bothered with cross-platform struct
+ *  packing.)
+ */
+typedef struct _net_control_block {
+       /// dev info for probing
+       ///  reads as MIPSNET%d where %d is some form of version
+       uint64_t devId;         /*0x00 */
+
+       /*
+        * read only busy flag.
+        * Set and cleared by the Net Device to indicate that an rx or a tx
+        * is in progress.
+        */
+       uint32_t busy;          /*0x08 */
+
+       /*
+        * Set by the Net Device.
+        * The device will set it once data has been received.
+        * The value is the number of bytes that should be read from
+        * rxDataBuffer.  The value will decrease till 0 until all the data
+        * from rxDataBuffer has been read.
+        */
+       uint32_t rxDataCount;   /*0x0c */
+#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
+
+       /*
+        * Settable from the MIPS core, cleared by the Net Device.
+        * The core should set the number of bytes it wants to send,
+        *   then it should write those bytes of data to txDataBuffer.
+        * The device will clear txDataCount has been processed (not necessarily sent).
+        */
+       uint32_t txDataCount;   /*0x10 */
+
+       /*
+        * Interrupt control
+        *
+        * Used to clear the interrupted generated by this dev.
+        * Write a 1 to clear the interrupt. (except bit31).
+        *
+        * Bit0 is set if it was a tx-done interrupt.
+        * Bit1 is set when new rx-data is available.
+        *      Until this bit is cleared there will be no other RXs.
+        *
+        * Bit31 is used for testing, it clears after a read.
+        *    Writing 1 to this bit will cause an interrupt to be generated.
+        *    To clear the test interrupt, write 0 to this register.
+        */
+       uint32_t interruptControl;      /*0x14 */
+#define MIPSNET_INTCTL_TXDONE     ((uint32_t)(1<< 0))
+#define MIPSNET_INTCTL_RXDONE     ((uint32_t)(1<< 1))
+#define MIPSNET_INTCTL_TESTBIT    ((uint32_t)(1<<31))
+#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
+
+       /*
+        * Readonly core-specific interrupt info for the device to signal the core.
+        * The meaning of the contents of this field might change.
+        */
+       /*###\todo: the whole memIntf interrupt scheme is messy: the device should have
+        *  no control what so ever of what VPE/register set is being used.
+        *  The MemIntf should only expose interrupt lines, and something in the
+        *  config should be responsible for the line<->core/vpe bindings.
+        */
+       uint32_t interruptInfo; /*0x18 */
+
+       /*
+        *  This is where the received data is read out.
+        *  There is more data to read until rxDataReady is 0.
+        *  Only 1 byte at this regs offset is used.
+        */
+       uint32_t rxDataBuffer;  /*0x1c */
+
+       /*
+        * This is where the data to transmit is written.
+        * Data should be written for the amount specified in the txDataCount register.
+        *  Only 1 byte at this regs offset is used.
+        */
+       uint32_t txDataBuffer;  /*0x20 */
+} MIPS_T_NetControl;
+
+#define MIPSNET_IO_EXTENT 0x40 /* being generous */
+
+#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+
+#endif /* __MIPSNET_H */
index d209a1556b2ebcb355a0110759c6c74190864123..0de8fdd2aa86f338fa026e7c308cb3ca6be2b13c 100644 (file)
@@ -54,6 +54,10 @@ static const char version2[] =
 #include <asm/system.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+#include <asm/tx4938/rbtx4938.h>
+#endif
+
 #include "8390.h"
 
 #define DRV_NAME "ne"
@@ -111,6 +115,9 @@ bad_clone_list[] __initdata = {
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+    {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+#endif
     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
     {NULL,}
 };
@@ -226,6 +233,10 @@ struct net_device * __init ne_probe(int unit)
        sprintf(dev->name, "eth%d", unit);
        netdev_boot_setup_check(dev);
 
+#ifdef CONFIG_TOSHIBA_RBTX4938
+       dev->base_addr = 0x07f20280;
+       dev->irq = RBTX4938_RTL_8019_IRQ;
+#endif
        err = do_ne_probe(dev);
        if (err)
                goto out;
@@ -506,6 +517,10 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        ei_status.name = name;
        ei_status.tx_start_page = start_page;
        ei_status.stop_page = stop_page;
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+       wordlength = 1;
+#endif
+
 #ifdef CONFIG_PLAT_OAKS32R
        ei_status.word16 = 0;
 #else
index f1c01ac2910239206fc892516057ef4bf85bb0c3..e531a4eedfeee3fd046beb4c7df5e3cb03be0da8 100644 (file)
@@ -372,6 +372,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
                printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
                dev->dev_addr[i] = SA_prom[i];
        }
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        return 0;
 
@@ -637,6 +638,7 @@ static struct ethtool_ops ne2k_pci_ethtool_ops = {
        .get_drvinfo            = ne2k_pci_get_drvinfo,
        .get_tx_csum            = ethtool_op_get_tx_csum,
        .get_sg                 = ethtool_op_get_sg,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
index e4811b42a6b7fe39ff8b3d1dee28f075403901e6..a3c3fc9c0d8a8ec241b452dde7f4aba968b3bb1d 100644 (file)
@@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
                        timed_out = 1;
                        break;
                }
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
        }
 
        if (status & fail)
index 113b68099216b4aeac8af443d690e21cd1c15cb4..70fe81a89df958ab72b540924383a164a0a56c00 100644 (file)
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME       "pcnet32"
-#define DRV_VERSION    "1.30j"
-#define DRV_RELDATE    "29.04.2005"
+#define DRV_VERSION    "1.31a"
+#define DRV_RELDATE    "12.Sep.2005"
 #define PFX            DRV_NAME ": "
 
 static const char *version =
@@ -257,6 +257,9 @@ static int homepna[MAX_UNITS];
  * v1.30h  24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
  * v1.30i  28 Jun 2004 Don Fry change to use module_param.
  * v1.30j  29 Apr 2005 Don Fry fix skb/map leak with loopback test.
+ * v1.31   02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
+ * v1.31a  12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
+ *        to allow loopback test to work unchanged.
  */
 
 
@@ -266,17 +269,17 @@ static int homepna[MAX_UNITS];
  * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
  */
 #ifndef PCNET32_LOG_TX_BUFFERS
-#define PCNET32_LOG_TX_BUFFERS 4
-#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_TX_BUFFERS         4
+#define PCNET32_LOG_RX_BUFFERS         5
+#define PCNET32_LOG_MAX_TX_BUFFERS     9       /* 2^9 == 512 */
+#define PCNET32_LOG_MAX_RX_BUFFERS     9
 #endif
 
 #define TX_RING_SIZE           (1 << (PCNET32_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK       (TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS       ((PCNET32_LOG_TX_BUFFERS) << 12)
+#define TX_MAX_RING_SIZE       (1 << (PCNET32_LOG_MAX_TX_BUFFERS))
 
 #define RX_RING_SIZE           (1 << (PCNET32_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK       (RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS       ((PCNET32_LOG_RX_BUFFERS) << 4)
+#define RX_MAX_RING_SIZE       (1 << (PCNET32_LOG_MAX_RX_BUFFERS))
 
 #define PKT_BUF_SZ             1544
 
@@ -334,14 +337,14 @@ struct pcnet32_access {
 };
 
 /*
- * The first three fields of pcnet32_private are read by the ethernet device
- * so we allocate the structure should be allocated by pci_alloc_consistent().
+ * The first field of pcnet32_private is read by the ethernet device
+ * so the structure should be allocated using pci_alloc_consistent().
  */
 struct pcnet32_private {
-    /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
-    struct pcnet32_rx_head    rx_ring[RX_RING_SIZE];
-    struct pcnet32_tx_head    tx_ring[TX_RING_SIZE];
     struct pcnet32_init_block init_block;
+    /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+    struct pcnet32_rx_head    *rx_ring;
+    struct pcnet32_tx_head    *tx_ring;
     dma_addr_t         dma_addr;       /* DMA address of beginning of this
                                           object, returned by
                                           pci_alloc_consistent */
@@ -349,13 +352,21 @@ struct pcnet32_private {
                                           structure */
     const char         *name;
     /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-    struct sk_buff     *tx_skbuff[TX_RING_SIZE];
-    struct sk_buff     *rx_skbuff[RX_RING_SIZE];
-    dma_addr_t         tx_dma_addr[TX_RING_SIZE];
-    dma_addr_t         rx_dma_addr[RX_RING_SIZE];
+    struct sk_buff     **tx_skbuff;
+    struct sk_buff     **rx_skbuff;
+    dma_addr_t         *tx_dma_addr;
+    dma_addr_t         *rx_dma_addr;
     struct pcnet32_access      a;
     spinlock_t         lock;           /* Guard lock */
     unsigned int       cur_rx, cur_tx; /* The next free ring entry */
+    unsigned int       rx_ring_size;   /* current rx ring size */
+    unsigned int       tx_ring_size;   /* current tx ring size */
+    unsigned int       rx_mod_mask;    /* rx ring modular mask */
+    unsigned int       tx_mod_mask;    /* tx ring modular mask */
+    unsigned short     rx_len_bits;
+    unsigned short     tx_len_bits;
+    dma_addr_t         rx_ring_dma_addr;
+    dma_addr_t         tx_ring_dma_addr;
     unsigned int       dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
     struct net_device_stats stats;
     char               tx_full;
@@ -397,6 +408,9 @@ static int pcnet32_get_regs_len(struct net_device *dev);
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        void *ptr);
 static void pcnet32_purge_tx_ring(struct net_device *dev);
+static int pcnet32_alloc_ring(struct net_device *dev);
+static void pcnet32_free_ring(struct net_device *dev);
+
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -613,10 +627,62 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
 {
     struct pcnet32_private *lp = dev->priv;
 
-    ering->tx_max_pending = TX_RING_SIZE - 1;
-    ering->tx_pending = lp->cur_tx - lp->dirty_tx;
-    ering->rx_max_pending = RX_RING_SIZE - 1;
-    ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+    ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
+    ering->tx_pending = lp->tx_ring_size - 1;
+    ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
+    ering->rx_pending = lp->rx_ring_size - 1;
+}
+
+static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int i;
+
+    if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+       return -EINVAL;
+
+    if (netif_running(dev))
+       pcnet32_close(dev);
+
+    spin_lock_irqsave(&lp->lock, flags);
+    pcnet32_free_ring(dev);
+    lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
+    lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
+
+    /* set the minimum ring size to 4, to allow the loopback test to work
+     * unchanged.
+     */
+    for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+       if (lp->tx_ring_size <= (1 << i))
+           break;
+    }
+    lp->tx_ring_size = (1 << i);
+    lp->tx_mod_mask = lp->tx_ring_size - 1;
+    lp->tx_len_bits = (i << 12);
+
+    for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+       if (lp->rx_ring_size <= (1 << i))
+           break;
+    }
+    lp->rx_ring_size = (1 << i);
+    lp->rx_mod_mask = lp->rx_ring_size - 1;
+    lp->rx_len_bits = (i << 4);
+
+    if (pcnet32_alloc_ring(dev)) {
+       pcnet32_free_ring(dev);
+       return -ENOMEM;
+    }
+
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    if (pcnet32_debug & NETIF_MSG_DRV)
+       printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
+
+    if (netif_running(dev))
+       pcnet32_open(dev);
+
+    return 0;
 }
 
 static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -948,6 +1014,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
     .nway_reset                = pcnet32_nway_reset,
     .get_link          = pcnet32_get_link,
     .get_ringparam     = pcnet32_get_ringparam,
+    .set_ringparam     = pcnet32_set_ringparam,
     .get_tx_csum       = ethtool_op_get_tx_csum,
     .get_sg            = ethtool_op_get_sg,
     .get_tso           = ethtool_op_get_tso,
@@ -957,6 +1024,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
     .phys_id           = pcnet32_phys_id,
     .get_regs_len      = pcnet32_get_regs_len,
     .get_regs          = pcnet32_get_regs,
+    .get_perm_addr     = ethtool_op_get_perm_addr,
 };
 
 /* only probes for non-PCI devices, the rest are handled by
@@ -1185,9 +1253,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
            memcpy(dev->dev_addr, promaddr, 6);
        }
     }
+    memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
     /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
-    if (!is_valid_ether_addr(dev->dev_addr))
+    if (!is_valid_ether_addr(dev->perm_addr))
        memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
 
     if (pcnet32_debug & NETIF_MSG_PROBE) {
@@ -1239,6 +1308,12 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
     dev->priv = lp;
     lp->name = chipname;
     lp->shared_irq = shared;
+    lp->tx_ring_size = TX_RING_SIZE;           /* default tx ring size */
+    lp->rx_ring_size = RX_RING_SIZE;           /* default rx ring size */
+    lp->tx_mod_mask = lp->tx_ring_size - 1;
+    lp->rx_mod_mask = lp->rx_ring_size - 1;
+    lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
+    lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
     lp->mii_if.full_duplex = fdx;
     lp->mii_if.phy_id_mask = 0x1f;
     lp->mii_if.reg_num_mask = 0x1f;
@@ -1265,21 +1340,23 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
     }
     lp->a = *a;
 
+    if (pcnet32_alloc_ring(dev)) {
+       ret = -ENOMEM;
+       goto err_free_ring;
+    }
     /* detect special T1/E1 WAN card by checking for MAC address */
     if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
            && dev->dev_addr[2] == 0x75)
        lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
 
     lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
-    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+    lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
     for (i = 0; i < 6; i++)
        lp->init_block.phys_addr[i] = dev->dev_addr[i];
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
-           offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
-           offsetof(struct pcnet32_private, tx_ring));
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
 
     /* switch pcnet32 to 32bit mode */
     a->write_bcr(ioaddr, 20, 2);
@@ -1310,7 +1387,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
            if (pcnet32_debug & NETIF_MSG_PROBE)
                printk(", failed to detect IRQ line.\n");
            ret = -ENODEV;
-           goto err_free_consistent;
+           goto err_free_ring;
        }
        if (pcnet32_debug & NETIF_MSG_PROBE)
            printk(", probed IRQ %d.\n", dev->irq);
@@ -1341,7 +1418,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 
     /* Fill in the generic fields of the device structure. */
     if (register_netdev(dev))
-       goto err_free_consistent;
+       goto err_free_ring;
 
     if (pdev) {
        pci_set_drvdata(pdev, dev);
@@ -1359,6 +1436,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 
     return 0;
 
+err_free_ring:
+    pcnet32_free_ring(dev);
 err_free_consistent:
     pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
 err_free_netdev:
@@ -1369,6 +1448,86 @@ err_release_region:
 }
 
 
+static int pcnet32_alloc_ring(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+
+    if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+       &lp->tx_ring_dma_addr)) == NULL) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+       return -ENOMEM;
+    }
+
+    if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+       &lp->rx_ring_dma_addr)) == NULL) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+       return -ENOMEM;
+    }
+
+    if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Memory allocation failed.\n");
+       return -ENOMEM;
+    }
+    memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
+
+    if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Memory allocation failed.\n");
+       return -ENOMEM;
+    }
+    memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
+
+    if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Memory allocation failed.\n");
+       return -ENOMEM;
+    }
+    memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
+
+    if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
+       if (pcnet32_debug & NETIF_MSG_DRV)
+           printk(KERN_ERR PFX "Memory allocation failed.\n");
+       return -ENOMEM;
+    }
+    memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
+
+    return 0;
+}
+
+
+static void pcnet32_free_ring(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+
+    kfree(lp->tx_skbuff);
+    lp->tx_skbuff = NULL;
+
+    kfree(lp->rx_skbuff);
+    lp->rx_skbuff = NULL;
+
+    kfree(lp->tx_dma_addr);
+    lp->tx_dma_addr = NULL;
+
+    kfree(lp->rx_dma_addr);
+    lp->rx_dma_addr = NULL;
+
+    if (lp->tx_ring) {
+       pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+               lp->tx_ring, lp->tx_ring_dma_addr);
+       lp->tx_ring = NULL;
+    }
+
+    if (lp->rx_ring) {
+       pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+               lp->rx_ring, lp->rx_ring_dma_addr);
+       lp->rx_ring = NULL;
+    }
+}
+
+
 static int
 pcnet32_open(struct net_device *dev)
 {
@@ -1400,8 +1559,8 @@ pcnet32_open(struct net_device *dev)
     if (netif_msg_ifup(lp))
        printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
               dev->name, dev->irq,
-              (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
-              (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
+              (u32) (lp->tx_ring_dma_addr),
+              (u32) (lp->rx_ring_dma_addr),
               (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
 
     /* set/reset autoselect bit */
@@ -1521,7 +1680,7 @@ pcnet32_open(struct net_device *dev)
 
 err_free_ring:
     /* free any allocated skbuffs */
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
        lp->rx_ring[i].status = 0;
        if (lp->rx_skbuff[i]) {
            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
@@ -1531,6 +1690,9 @@ err_free_ring:
        lp->rx_skbuff[i] = NULL;
        lp->rx_dma_addr[i] = 0;
     }
+
+    pcnet32_free_ring(dev);
+
     /*
      * Switch back to 16bit mode to avoid problems with dumb
      * DOS packet driver after a warm reboot
@@ -1562,7 +1724,7 @@ pcnet32_purge_tx_ring(struct net_device *dev)
     struct pcnet32_private *lp = dev->priv;
     int i;
 
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
        lp->tx_ring[i].status = 0;      /* CPU owns buffer */
        wmb();  /* Make sure adapter sees owner change */
        if (lp->tx_skbuff[i]) {
@@ -1587,7 +1749,7 @@ pcnet32_init_ring(struct net_device *dev)
     lp->cur_rx = lp->cur_tx = 0;
     lp->dirty_rx = lp->dirty_tx = 0;
 
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
        struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
        if (rx_skbuff == NULL) {
            if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
@@ -1611,20 +1773,18 @@ pcnet32_init_ring(struct net_device *dev)
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
      * the upper ownership bit. */
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
        lp->tx_ring[i].status = 0;      /* CPU owns buffer */
        wmb();  /* Make sure adapter sees owner change */
        lp->tx_ring[i].base = 0;
        lp->tx_dma_addr[i] = 0;
     }
 
-    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+    lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
     for (i = 0; i < 6; i++)
        lp->init_block.phys_addr[i] = dev->dev_addr[i];
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
-           offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
-           offsetof(struct pcnet32_private, tx_ring));
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
     wmb();     /* Make sure all changes are visible */
     return 0;
 }
@@ -1682,13 +1842,13 @@ pcnet32_tx_timeout (struct net_device *dev)
        printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
           lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
           lp->cur_rx);
-       for (i = 0 ; i < RX_RING_SIZE; i++)
+       for (i = 0 ; i < lp->rx_ring_size; i++)
        printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
               le32_to_cpu(lp->rx_ring[i].base),
               (-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
               le32_to_cpu(lp->rx_ring[i].msg_length),
               le16_to_cpu(lp->rx_ring[i].status));
-       for (i = 0 ; i < TX_RING_SIZE; i++)
+       for (i = 0 ; i < lp->tx_ring_size; i++)
        printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
               le32_to_cpu(lp->tx_ring[i].base),
               (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
@@ -1729,7 +1889,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
     /* Fill in a Tx ring entry */
 
     /* Mask to ring buffer boundary. */
-    entry = lp->cur_tx & TX_RING_MOD_MASK;
+    entry = lp->cur_tx & lp->tx_mod_mask;
 
     /* Caution: the write order is important here, set the status
      * with the "ownership" bits last. */
@@ -1753,7 +1913,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
     dev->trans_start = jiffies;
 
-    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
+    if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
        lp->tx_full = 1;
        netif_stop_queue(dev);
     }
@@ -1806,7 +1966,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
            int delta;
 
            while (dirty_tx != lp->cur_tx) {
-               int entry = dirty_tx & TX_RING_MOD_MASK;
+               int entry = dirty_tx & lp->tx_mod_mask;
                int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 
                if (status < 0)
@@ -1864,18 +2024,18 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                dirty_tx++;
            }
 
-           delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
-           if (delta > TX_RING_SIZE) {
+           delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+           if (delta > lp->tx_ring_size) {
                if (netif_msg_drv(lp))
                    printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
                            dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
-               dirty_tx += TX_RING_SIZE;
-               delta -= TX_RING_SIZE;
+               dirty_tx += lp->tx_ring_size;
+               delta -= lp->tx_ring_size;
            }
 
            if (lp->tx_full &&
                netif_queue_stopped(dev) &&
-               delta < TX_RING_SIZE - 2) {
+               delta < lp->tx_ring_size - 2) {
                /* The ring is no longer full, clear tbusy. */
                lp->tx_full = 0;
                netif_wake_queue (dev);
@@ -1932,8 +2092,8 @@ static int
 pcnet32_rx(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
-    int entry = lp->cur_rx & RX_RING_MOD_MASK;
-    int boguscnt = RX_RING_SIZE / 2;
+    int entry = lp->cur_rx & lp->rx_mod_mask;
+    int boguscnt = lp->rx_ring_size / 2;
 
     /* If we own the next entry, it's a new packet. Send it up. */
     while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
@@ -1998,12 +2158,12 @@ pcnet32_rx(struct net_device *dev)
                    if (netif_msg_drv(lp))
                        printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
                                dev->name);
-                   for (i = 0; i < RX_RING_SIZE; i++)
+                   for (i = 0; i < lp->rx_ring_size; i++)
                        if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
-                                   & RX_RING_MOD_MASK].status) < 0)
+                                   & lp->rx_mod_mask].status) < 0)
                            break;
 
-                   if (i > RX_RING_SIZE -2) {
+                   if (i > lp->rx_ring_size -2) {
                        lp->stats.rx_dropped++;
                        lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
                        wmb();  /* Make sure adapter sees owner change */
@@ -2041,7 +2201,7 @@ pcnet32_rx(struct net_device *dev)
        lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
        wmb(); /* Make sure owner changes after all others are visible */
        lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
-       entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+       entry = (++lp->cur_rx) & lp->rx_mod_mask;
        if (--boguscnt <= 0) break;     /* don't stay in loop forever */
     }
 
@@ -2084,7 +2244,7 @@ pcnet32_close(struct net_device *dev)
     spin_lock_irqsave(&lp->lock, flags);
 
     /* free all allocated skbuffs */
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
        lp->rx_ring[i].status = 0;
        wmb();          /* Make sure adapter sees owner change */
        if (lp->rx_skbuff[i]) {
@@ -2096,7 +2256,7 @@ pcnet32_close(struct net_device *dev)
        lp->rx_dma_addr[i] = 0;
     }
 
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
        lp->tx_ring[i].status = 0;      /* CPU owns buffer */
        wmb();          /* Make sure adapter sees owner change */
        if (lp->tx_skbuff[i]) {
@@ -2265,6 +2425,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
        struct pcnet32_private *lp = dev->priv;
 
        unregister_netdev(dev);
+       pcnet32_free_ring(dev);
        release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
        pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
        free_netdev(dev);
@@ -2340,6 +2501,7 @@ static void __exit pcnet32_cleanup_module(void)
        struct pcnet32_private *lp = pcnet32_dev->priv;
        next_dev = lp->next;
        unregister_netdev(pcnet32_dev);
+       pcnet32_free_ring(pcnet32_dev);
        release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
        pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
        free_netdev(pcnet32_dev);
index 14f4de1a8180289db3f05ca5395c3a93d6df0296..c782a6329805713493f930681176d3e8a32d8c47 100644 (file)
@@ -12,14 +12,6 @@ config PHYLIB
          devices.  This option provides infrastructure for
          managing PHY devices.
 
-config PHYCONTROL
-       bool "  Support for automatically handling PHY state changes"
-       depends on PHYLIB
-       help
-         Adds code to perform all the work for keeping PHY link
-         state (speed/duplex/etc) up-to-date.  Also handles
-         interrupts.
-
 comment "MII PHY device drivers"
        depends on PHYLIB
 
index d9e11f93bf3a34c54560dc724d56ce71b85d8141..9209da9dde0da9738d662e7a8167ae2136f2d831 100644 (file)
@@ -242,10 +242,6 @@ EXPORT_SYMBOL(phy_sanitize_settings);
  *   choose the next best ones from the ones selected, so we don't
  *   care if ethtool tries to give us bad values
  *
- * A note about the PHYCONTROL Layer.  If you turn off
- * CONFIG_PHYCONTROL, you will need to read the PHY status
- * registers after this function completes, and update your
- * controller manually.
  */
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
 {
@@ -380,7 +376,6 @@ int phy_start_aneg(struct phy_device *phydev)
 
        err = phydev->drv->config_aneg(phydev);
 
-#ifdef CONFIG_PHYCONTROL
        if (err < 0)
                goto out_unlock;
 
@@ -395,14 +390,12 @@ int phy_start_aneg(struct phy_device *phydev)
        }
 
 out_unlock:
-#endif
        spin_unlock(&phydev->lock);
        return err;
 }
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-#ifdef CONFIG_PHYCONTROL
 static void phy_change(void *data);
 static void phy_timer(unsigned long data);
 
@@ -868,4 +861,3 @@ static void phy_timer(unsigned long data)
        mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
 }
 
-#endif /* CONFIG_PHYCONTROL */
index 33f7bdb5857c8d97cef75cde5fdb69de33830771..6da1aa0706a1441ba227829ec529bd98089cf0a9 100644 (file)
@@ -101,7 +101,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
        return dev;
 }
 
-#ifdef CONFIG_PHYCONTROL
 /* phy_prepare_link:
  *
  * description: Tells the PHY infrastructure to handle the
@@ -160,8 +159,6 @@ void phy_disconnect(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_disconnect);
 
-#endif /* CONFIG_PHYCONTROL */
-
 /* phy_attach:
  *
  *   description: Called by drivers to attach to a particular PHY
index afb3f186b8843b96b4ad0214c18e40515a11b091..159b56a56ef49112fc5e58083c76a3066eb76958 100644 (file)
@@ -1027,6 +1027,7 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
        .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,
@@ -1511,6 +1512,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* 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 --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644 (file)
index 0000000..12cde06
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME        "rionet"
+#define DRV_VERSION     "0.2"
+#define DRV_AUTHOR      "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC        "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL \
+                       (NETIF_MSG_DRV          | \
+                        NETIF_MSG_LINK         | \
+                        NETIF_MSG_RX_ERR       | \
+                        NETIF_MSG_TX_ERR)
+
+#define RIONET_DOORBELL_JOIN   0x1000
+#define RIONET_DOORBELL_LEAVE  0x1001
+
+#define RIONET_MAILBOX         0
+
+#define RIONET_TX_RING_SIZE    CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE    CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+       struct rio_mport *mport;
+       struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+       struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+       struct net_device_stats stats;
+       int rx_slot;
+       int tx_slot;
+       int tx_cnt;
+       int ack_slot;
+       spinlock_t lock;
+       spinlock_t tx_lock;
+       u32 msg_enable;
+};
+
+struct rionet_peer {
+       struct list_head node;
+       struct rio_dev *rdev;
+       struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops)               \
+                       ((pef & RIO_PEF_INB_MBOX) &&            \
+                        (pef & RIO_PEF_INB_DOORBELL) &&        \
+                        (src_ops & RIO_SRC_OPS_DOORBELL) &&    \
+                        (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+       is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x)    (*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x)   (*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+       struct rionet_private *rnet = ndev->priv;
+       return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+       int i;
+       int error = 0;
+       struct rionet_private *rnet = ndev->priv;
+       void *data;
+
+       i = rnet->rx_slot;
+
+       do {
+               if (!rnet->rx_skb[i])
+                       continue;
+
+               if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+                       break;
+
+               rnet->rx_skb[i]->data = data;
+               skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+               rnet->rx_skb[i]->dev = ndev;
+               rnet->rx_skb[i]->protocol =
+                   eth_type_trans(rnet->rx_skb[i], ndev);
+               error = netif_rx(rnet->rx_skb[i]);
+
+               if (error == NET_RX_DROP) {
+                       rnet->stats.rx_dropped++;
+               } else if (error == NET_RX_BAD) {
+                       if (netif_msg_rx_err(rnet))
+                               printk(KERN_WARNING "%s: bad rx packet\n",
+                                      DRV_NAME);
+                       rnet->stats.rx_errors++;
+               } else {
+                       rnet->stats.rx_packets++;
+                       rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+               }
+
+       } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+       return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+       int i;
+       struct rionet_private *rnet = ndev->priv;
+
+       i = rnet->rx_slot;
+       do {
+               rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+               if (!rnet->rx_skb[i])
+                       break;
+
+               rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+                                  rnet->rx_skb[i]->data);
+       } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+       rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+                              struct rio_dev *rdev)
+{
+       struct rionet_private *rnet = ndev->priv;
+
+       rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+       rnet->tx_skb[rnet->tx_slot] = skb;
+
+       rnet->stats.tx_packets++;
+       rnet->stats.tx_bytes += skb->len;
+
+       if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+               netif_stop_queue(ndev);
+
+       ++rnet->tx_slot;
+       rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+
+       if (netif_msg_tx_queued(rnet))
+               printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+                      (u32) skb, skb->len);
+
+       return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       int i;
+       struct rionet_private *rnet = ndev->priv;
+       struct ethhdr *eth = (struct ethhdr *)skb->data;
+       u16 destid;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (!spin_trylock(&rnet->tx_lock)) {
+               local_irq_restore(flags);
+               return NETDEV_TX_LOCKED;
+       }
+
+       if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+               netif_stop_queue(ndev);
+               spin_unlock_irqrestore(&rnet->tx_lock, flags);
+               printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+                      ndev->name);
+               return NETDEV_TX_BUSY;
+       }
+
+       if (eth->h_dest[0] & 0x01) {
+               for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+                       if (rionet_active[i])
+                               rionet_queue_tx_msg(skb, ndev,
+                                                   rionet_active[i]);
+       } else if (RIONET_MAC_MATCH(eth->h_dest)) {
+               destid = RIONET_GET_DESTID(eth->h_dest);
+               if (rionet_active[destid])
+                       rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+       }
+
+       spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+       return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
+                              u16 info)
+{
+       struct net_device *ndev = dev_id;
+       struct rionet_private *rnet = ndev->priv;
+       struct rionet_peer *peer;
+
+       if (netif_msg_intr(rnet))
+               printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+                      DRV_NAME, sid, tid, info);
+       if (info == RIONET_DOORBELL_JOIN) {
+               if (!rionet_active[sid]) {
+                       list_for_each_entry(peer, &rionet_peers, node) {
+                               if (peer->rdev->destid == sid)
+                                       rionet_active[sid] = peer->rdev;
+                       }
+                       rio_mport_send_doorbell(mport, sid,
+                                               RIONET_DOORBELL_JOIN);
+               }
+       } else if (info == RIONET_DOORBELL_LEAVE) {
+               rionet_active[sid] = NULL;
+       } else {
+               if (netif_msg_intr(rnet))
+                       printk(KERN_WARNING "%s: unhandled doorbell\n",
+                              DRV_NAME);
+       }
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+       int n;
+       struct net_device *ndev = dev_id;
+       struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+       if (netif_msg_intr(rnet))
+               printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+                      DRV_NAME, mbox, slot);
+
+       spin_lock(&rnet->lock);
+       if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+               rionet_rx_fill(ndev, n);
+       spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+       struct net_device *ndev = dev_id;
+       struct rionet_private *rnet = ndev->priv;
+
+       spin_lock(&rnet->lock);
+
+       if (netif_msg_intr(rnet))
+               printk(KERN_INFO
+                      "%s: outbound message event, mbox %d slot %d\n",
+                      DRV_NAME, mbox, slot);
+
+       while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+               /* dma unmap single */
+               dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+               rnet->tx_skb[rnet->ack_slot] = NULL;
+               ++rnet->ack_slot;
+               rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+               rnet->tx_cnt--;
+       }
+
+       if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+               netif_wake_queue(ndev);
+
+       spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+       int i, rc = 0;
+       struct rionet_peer *peer, *tmp;
+       u32 pwdcsr;
+       struct rionet_private *rnet = ndev->priv;
+
+       if (netif_msg_ifup(rnet))
+               printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+       if ((rc = rio_request_inb_dbell(rnet->mport,
+                                       (void *)ndev,
+                                       RIONET_DOORBELL_JOIN,
+                                       RIONET_DOORBELL_LEAVE,
+                                       rionet_dbell_event)) < 0)
+               goto out;
+
+       if ((rc = rio_request_inb_mbox(rnet->mport,
+                                      (void *)ndev,
+                                      RIONET_MAILBOX,
+                                      RIONET_RX_RING_SIZE,
+                                      rionet_inb_msg_event)) < 0)
+               goto out;
+
+       if ((rc = rio_request_outb_mbox(rnet->mport,
+                                       (void *)ndev,
+                                       RIONET_MAILBOX,
+                                       RIONET_TX_RING_SIZE,
+                                       rionet_outb_msg_event)) < 0)
+               goto out;
+
+       /* Initialize inbound message ring */
+       for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+               rnet->rx_skb[i] = NULL;
+       rnet->rx_slot = 0;
+       rionet_rx_fill(ndev, 0);
+
+       rnet->tx_slot = 0;
+       rnet->tx_cnt = 0;
+       rnet->ack_slot = 0;
+
+       netif_carrier_on(ndev);
+       netif_start_queue(ndev);
+
+       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+               if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+                                                        RIONET_DOORBELL_JOIN,
+                                                        RIONET_DOORBELL_LEAVE)))
+               {
+                       printk(KERN_ERR "%s: error requesting doorbells\n",
+                              DRV_NAME);
+                       continue;
+               }
+
+               /*
+                * If device has initialized inbound doorbells,
+                * send a join message
+                */
+               rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+               if (pwdcsr & RIO_DOORBELL_AVAIL)
+                       rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+       }
+
+      out:
+       return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+       struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+       struct rionet_peer *peer, *tmp;
+       int i;
+
+       if (netif_msg_ifup(rnet))
+               printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+       netif_stop_queue(ndev);
+       netif_carrier_off(ndev);
+
+       for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+               if (rnet->rx_skb[i])
+                       kfree_skb(rnet->rx_skb[i]);
+
+       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+               if (rionet_active[peer->rdev->destid]) {
+                       rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+                       rionet_active[peer->rdev->destid] = NULL;
+               }
+               rio_release_outb_dbell(peer->rdev, peer->res);
+       }
+
+       rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+                             RIONET_DOORBELL_LEAVE);
+       rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+       rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+       return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+       struct net_device *ndev = NULL;
+       struct rionet_peer *peer, *tmp;
+
+       unregister_netdev(ndev);
+       kfree(ndev);
+
+       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+               list_del(&peer->node);
+               kfree(peer);
+       }
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+                              struct ethtool_drvinfo *info)
+{
+       struct rionet_private *rnet = ndev->priv;
+
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       strcpy(info->fw_version, "n/a");
+       strcpy(info->bus_info, rnet->mport->name);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+       struct rionet_private *rnet = ndev->priv;
+
+       return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+       struct rionet_private *rnet = ndev->priv;
+
+       rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+       .get_drvinfo = rionet_get_drvinfo,
+       .get_msglevel = rionet_get_msglevel,
+       .set_msglevel = rionet_set_msglevel,
+       .get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+       int rc = 0;
+       struct net_device *ndev = NULL;
+       struct rionet_private *rnet;
+       u16 device_id;
+
+       /* Allocate our net_device structure */
+       ndev = alloc_etherdev(sizeof(struct rionet_private));
+       if (ndev == NULL) {
+               printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+                      DRV_NAME);
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       /* Set up private area */
+       rnet = (struct rionet_private *)ndev->priv;
+       rnet->mport = mport;
+
+       /* Set the default MAC address */
+       device_id = rio_local_get_device_id(mport);
+       ndev->dev_addr[0] = 0x00;
+       ndev->dev_addr[1] = 0x01;
+       ndev->dev_addr[2] = 0x00;
+       ndev->dev_addr[3] = 0x01;
+       ndev->dev_addr[4] = device_id >> 8;
+       ndev->dev_addr[5] = device_id & 0xff;
+
+       /* Fill in the driver function table */
+       ndev->open = &rionet_open;
+       ndev->hard_start_xmit = &rionet_start_xmit;
+       ndev->stop = &rionet_close;
+       ndev->get_stats = &rionet_stats;
+       ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+       ndev->features = NETIF_F_LLTX;
+       SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+       SET_MODULE_OWNER(ndev);
+
+       spin_lock_init(&rnet->lock);
+       spin_lock_init(&rnet->tx_lock);
+
+       rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+       rc = register_netdev(ndev);
+       if (rc != 0)
+               goto out;
+
+       printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+              ndev->name,
+              DRV_NAME,
+              DRV_DESC,
+              DRV_VERSION,
+              ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+              ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+      out:
+       return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+       int rc = -ENODEV;
+       u32 lpef, lsrc_ops, ldst_ops;
+       struct rionet_peer *peer;
+
+       /* If local device is not rionet capable, give up quickly */
+       if (!rionet_capable)
+               goto out;
+
+       /*
+        * First time through, make sure local device is rionet
+        * capable, setup netdev,  and set flags so this is skipped
+        * on later probes
+        */
+       if (!rionet_check) {
+               rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+               rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+                                        &lsrc_ops);
+               rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+                                        &ldst_ops);
+               if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+                       printk(KERN_ERR
+                              "%s: local device is not network capable\n",
+                              DRV_NAME);
+                       rionet_check = 1;
+                       rionet_capable = 0;
+                       goto out;
+               }
+
+               rc = rionet_setup_netdev(rdev->net->hport);
+               rionet_check = 1;
+       }
+
+       /*
+        * If the remote device has mailbox/doorbell capabilities,
+        * add it to the peer list.
+        */
+       if (dev_rionet_capable(rdev)) {
+               if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+               peer->rdev = rdev;
+               list_add_tail(&peer->node, &rionet_peers);
+       }
+
+      out:
+       return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+       {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+       .name = "rionet",
+       .id_table = rionet_id_table,
+       .probe = rionet_probe,
+       .remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+       return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+       rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
index 7cefe5507b9e128bef1f621aeb29837105c254cf..00179bc3437fccea29fa780d9df5da4233d1f886 100644 (file)
@@ -814,6 +814,17 @@ typedef struct _XENA_dev_config {
        u64 rxgxs_ber_0;        /* CHANGED */
        u64 rxgxs_ber_1;        /* CHANGED */
 
+       u64 spi_control;
+#define SPI_CONTROL_KEY(key)           vBIT(key,0,4)
+#define SPI_CONTROL_BYTECNT(cnt)       vBIT(cnt,29,3)
+#define SPI_CONTROL_CMD(cmd)           vBIT(cmd,32,8)
+#define SPI_CONTROL_ADDR(addr)         vBIT(addr,40,24)
+#define SPI_CONTROL_SEL1               BIT(4)
+#define SPI_CONTROL_REQ                        BIT(7)
+#define SPI_CONTROL_NACK               BIT(5)
+#define SPI_CONTROL_DONE               BIT(6)
+       u64 spi_data;
+#define SPI_DATA_WRITE(data,len)       vBIT(data,0,len)
 } XENA_dev_config_t;
 
 #define XENA_REG_SPACE sizeof(XENA_dev_config_t)
index dd451e099a4c46bd650dbc1696c40f7fae3468f6..d303d162974f9caedf905bd603c583a8b6c538b9 100644 (file)
 #include "s2io.h"
 #include "s2io-regs.h"
 
+#define DRV_VERSION "Version 2.0.9.1"
+
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = "Version 2.0.8.1";
+static char s2io_driver_version[] = DRV_VERSION;
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -307,6 +309,8 @@ static unsigned int indicate_max_pkts;
 #endif
 /* Frequency of Rx desc syncs expressed as power of 2 */
 static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
 
 /*
  * S2IO device table.
@@ -1396,8 +1400,13 @@ static int init_nic(struct s2io_nic *nic)
                writeq(val64, &bar0->rti_data1_mem);
 
                val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-                   RTI_DATA2_MEM_RX_UFC_B(0x2) |
-                   RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
+                   RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+               if (nic->intr_type == MSI_X)
+                   val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+                               RTI_DATA2_MEM_RX_UFC_D(0x40));
+               else
+                   val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+                               RTI_DATA2_MEM_RX_UFC_D(0x80));
                writeq(val64, &bar0->rti_data2_mem);
 
                for (i = 0; i < config->rx_ring_num; i++) {
@@ -1507,17 +1516,15 @@ static int init_nic(struct s2io_nic *nic)
 #define LINK_UP_DOWN_INTERRUPT         1
 #define MAC_RMAC_ERR_TIMER             2
 
-#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
-#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
-#else
 int s2io_link_fault_indication(nic_t *nic)
 {
+       if (nic->intr_type != INTA)
+               return MAC_RMAC_ERR_TIMER;
        if (nic->device_type == XFRAME_II_DEVICE)
                return LINK_UP_DOWN_INTERRUPT;
        else
                return MAC_RMAC_ERR_TIMER;
 }
-#endif
 
 /**
  *  en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1941,11 +1948,14 @@ static int start_nic(struct s2io_nic *nic)
        }
 
        /*  Enable select interrupts */
-       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-       interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-       interruptible |= TX_MAC_INTR | RX_MAC_INTR;
-
-       en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+       if (nic->intr_type != INTA)
+               en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+       else {
+               interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+               interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+               interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+               en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+       }
 
        /*
         * With some switches, link might be already up at this point.
@@ -2633,11 +2643,11 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
                        err = txdlp->Control_1 & TXD_T_CODE;
                        if ((err >> 48) == 0xA) {
                                DBG_PRINT(TX_DBG, "TxD returned due \
-                                               to loss of link\n");
+to loss of link\n");
                        }
                        else {
                                DBG_PRINT(ERR_DBG, "***TxD error \
-                                               %llx\n", err);
+%llx\n", err);
                        }
                }
 
@@ -2854,6 +2864,9 @@ void s2io_reset(nic_t * sp)
        /* Set swapper to enable I/O register access */
        s2io_set_swapper(sp);
 
+       /* Restore the MSIX table entries from local variables */
+       restore_xmsi_data(sp);
+
        /* Clear certain PCI/PCI-X fields after reset */
        if (sp->device_type == XFRAME_II_DEVICE) {
                /* Clear parity err detect bit */
@@ -2983,8 +2996,9 @@ int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_RXD_W_FE |
                 SWAPPER_CTRL_RXF_W_FE |
                 SWAPPER_CTRL_XMSI_FE |
-                SWAPPER_CTRL_XMSI_SE |
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+       if (sp->intr_type == INTA)
+               val64 |= SWAPPER_CTRL_XMSI_SE;
        writeq(val64, &bar0->swapper_ctrl);
 #else
        /*
@@ -3005,8 +3019,9 @@ int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_RXD_W_SE |
                 SWAPPER_CTRL_RXF_W_FE |
                 SWAPPER_CTRL_XMSI_FE |
-                SWAPPER_CTRL_XMSI_SE |
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+       if (sp->intr_type == INTA)
+               val64 |= SWAPPER_CTRL_XMSI_SE;
        writeq(val64, &bar0->swapper_ctrl);
 #endif
        val64 = readq(&bar0->swapper_ctrl);
@@ -3028,6 +3043,201 @@ int s2io_set_swapper(nic_t * sp)
        return SUCCESS;
 }
 
+int wait_for_msix_trans(nic_t *nic, int i)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64;
+       int ret = 0, cnt = 0;
+
+       do {
+               val64 = readq(&bar0->xmsi_access);
+               if (!(val64 & BIT(15)))
+                       break;
+               mdelay(1);
+               cnt++;
+       } while(cnt < 5);
+       if (cnt == 5) {
+               DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+void restore_xmsi_data(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64;
+       int i;
+
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
+               writeq(nic->msix_info[i].data, &bar0->xmsi_data);
+               val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+               writeq(val64, &bar0->xmsi_access);
+               if (wait_for_msix_trans(nic, i)) {
+                       DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+                       continue;
+               }
+       }
+}
+
+void store_xmsi_data(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64, addr, data;
+       int i;
+
+       /* Store and display */
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               val64 = (BIT(15) | vBIT(i, 26, 6));
+               writeq(val64, &bar0->xmsi_access);
+               if (wait_for_msix_trans(nic, i)) {
+                       DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+                       continue;
+               }
+               addr = readq(&bar0->xmsi_address);
+               data = readq(&bar0->xmsi_data);
+               if (addr && data) {
+                       nic->msix_info[i].addr = addr;
+                       nic->msix_info[i].data = data;
+               }
+       }
+}
+
+int s2io_enable_msi(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u16 msi_ctrl, msg_val;
+       struct config_param *config = &nic->config;
+       struct net_device *dev = nic->dev;
+       u64 val64, tx_mat, rx_mat;
+       int i, err;
+
+       val64 = readq(&bar0->pic_control);
+       val64 &= ~BIT(1);
+       writeq(val64, &bar0->pic_control);
+
+       err = pci_enable_msi(nic->pdev);
+       if (err) {
+               DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
+                         nic->dev->name);
+               return err;
+       }
+
+       /*
+        * Enable MSI and use MSI-1 in stead of the standard MSI-0
+        * for interrupt handling.
+        */
+       pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+       msg_val ^= 0x1;
+       pci_write_config_word(nic->pdev, 0x4c, msg_val);
+       pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+
+       pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
+       msi_ctrl |= 0x10;
+       pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
+
+       /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
+       tx_mat = readq(&bar0->tx_mat0_n[0]);
+       for (i=0; i<config->tx_fifo_num; i++) {
+               tx_mat |= TX_MAT_SET(i, 1);
+       }
+       writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+       rx_mat = readq(&bar0->rx_mat);
+       for (i=0; i<config->rx_ring_num; i++) {
+               rx_mat |= RX_MAT_SET(i, 1);
+       }
+       writeq(rx_mat, &bar0->rx_mat);
+
+       dev->irq = nic->pdev->irq;
+       return 0;
+}
+
+int s2io_enable_msi_x(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 tx_mat, rx_mat;
+       u16 msi_control; /* Temp variable */
+       int ret, i, j, msix_indx = 1;
+
+       nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+                              GFP_KERNEL);
+       if (nic->entries == NULL) {
+               DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+       memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+
+       nic->s2io_entries =
+               kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+                                  GFP_KERNEL);
+       if (nic->s2io_entries == NULL) {
+               DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+               kfree(nic->entries);
+               return -ENOMEM;
+       }
+       memset(nic->s2io_entries, 0,
+              MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+               nic->entries[i].entry = i;
+               nic->s2io_entries[i].entry = i;
+               nic->s2io_entries[i].arg = NULL;
+               nic->s2io_entries[i].in_use = 0;
+       }
+
+       tx_mat = readq(&bar0->tx_mat0_n[0]);
+       for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
+               tx_mat |= TX_MAT_SET(i, msix_indx);
+               nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
+               nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
+               nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+       }
+       writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+       if (!nic->config.bimodal) {
+               rx_mat = readq(&bar0->rx_mat);
+               for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+                       rx_mat |= RX_MAT_SET(j, msix_indx);
+                       nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+                       nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+                       nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+               }
+               writeq(rx_mat, &bar0->rx_mat);
+       } else {
+               tx_mat = readq(&bar0->tx_mat0_n[7]);
+               for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+                       tx_mat |= TX_MAT_SET(i, msix_indx);
+                       nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+                       nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+                       nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+               }
+               writeq(tx_mat, &bar0->tx_mat0_n[7]);
+       }
+
+       ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+       if (ret) {
+               DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+               kfree(nic->entries);
+               kfree(nic->s2io_entries);
+               nic->entries = NULL;
+               nic->s2io_entries = NULL;
+               return -ENOMEM;
+       }
+
+       /*
+        * To enable MSI-X, MSI also needs to be enabled, due to a bug
+        * in the herc NIC. (Temp change, needs to be removed later)
+        */
+       pci_read_config_word(nic->pdev, 0x42, &msi_control);
+       msi_control |= 0x1; /* Enable MSI */
+       pci_write_config_word(nic->pdev, 0x42, msi_control);
+
+       return 0;
+}
+
 /* ********************************************************* *
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
@@ -3048,6 +3258,8 @@ int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
+       int i;
+       u16 msi_control; /* Temp variable */
 
        /*
         * Make sure you have link off by default every time
@@ -3064,13 +3276,55 @@ int s2io_open(struct net_device *dev)
                goto hw_init_failed;
        }
 
+       /* Store the values of the MSIX table in the nic_t structure */
+       store_xmsi_data(sp);
+
        /* After proper initialization of H/W, register ISR */
-       err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
-                         sp->name, dev);
-       if (err) {
-               DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
-                         dev->name);
-               goto isr_registration_failed;
+       if (sp->intr_type == MSI) {
+               err = request_irq((int) sp->pdev->irq, s2io_msi_handle, 
+                       SA_SHIRQ, sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+                       goto isr_registration_failed;
+               }
+       }
+       if (sp->intr_type == MSI_X) {
+               for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+                       if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+                               sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_fifo_handle, 0, sp->desc1,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
+                                                       sp->msix_info[i].addr);
+                       } else {
+                               sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_ring_handle, 0, sp->desc2,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
+                                                       sp->msix_info[i].addr);
+                       }
+                       if (err) {
+                               DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+                               DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+                               goto isr_registration_failed;
+                       }
+                       sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+               }
+       }
+       if (sp->intr_type == INTA) {
+               err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+                               sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+                                 dev->name);
+                       goto isr_registration_failed;
+               }
        }
 
        if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -3083,11 +3337,37 @@ int s2io_open(struct net_device *dev)
        return 0;
 
 setting_mac_address_failed:
-       free_irq(sp->pdev->irq, dev);
+       if (sp->intr_type != MSI_X)
+               free_irq(sp->pdev->irq, dev);
 isr_registration_failed:
        del_timer_sync(&sp->alarm_timer);
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                               MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_disable_msix(sp->pdev);
+
+                       /* Temp */
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+               }
+       }
+       else if (sp->intr_type == MSI)
+               pci_disable_msi(sp->pdev);
        s2io_reset(sp);
 hw_init_failed:
+       if (sp->intr_type == MSI_X) {
+               if (sp->entries)
+                       kfree(sp->entries);
+               if (sp->s2io_entries)
+                       kfree(sp->s2io_entries);
+       }
        return err;
 }
 
@@ -3107,12 +3387,35 @@ hw_init_failed:
 int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
+       int i;
+       u16 msi_control;
+
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
-       free_irq(sp->pdev->irq, dev);
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                                       MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+                       pci_disable_msix(sp->pdev);
+               }
+       }
+       else {
+               free_irq(sp->pdev->irq, dev);
+               if (sp->intr_type == MSI)
+                       pci_disable_msi(sp->pdev);
+       }       
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
 }
@@ -3278,6 +3581,104 @@ s2io_alarm_handle(unsigned long data)
        mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
+static irqreturn_t
+s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       nic_t *sp = dev->priv;
+       int i;
+       int ret;
+       mac_info_t *mac_control;
+       struct config_param *config;
+
+       atomic_inc(&sp->isr_cnt);
+       mac_control = &sp->mac_control;
+       config = &sp->config;
+       DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
+
+       /* If Intr is because of Rx Traffic */
+       for (i = 0; i < config->rx_ring_num; i++)
+               rx_intr_handler(&mac_control->rings[i]);
+
+       /* If Intr is because of Tx Traffic */
+       for (i = 0; i < config->tx_fifo_num; i++)
+               tx_intr_handler(&mac_control->fifos[i]);
+
+       /*
+        * If the Rx buffer count is below the panic threshold then
+        * reallocate the buffers from the interrupt handler itself,
+        * else schedule a tasklet to reallocate the buffers.
+        */
+       for (i = 0; i < config->rx_ring_num; i++) {
+               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+               int level = rx_buffer_level(sp, rxb_size, i);
+
+               if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                         dev->name);
+                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                               clear_bit(0, (&sp->tasklet_status));
+                               atomic_dec(&sp->isr_cnt);
+                               return IRQ_HANDLED;
+                       }
+                       clear_bit(0, (&sp->tasklet_status));
+               } else if (level == LOW) {
+                       tasklet_schedule(&sp->task);
+               }
+       }
+
+       atomic_dec(&sp->isr_cnt);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       ring_info_t *ring = (ring_info_t *)dev_id;
+       nic_t *sp = ring->nic;
+       int rxb_size, level, rng_n;
+
+       atomic_inc(&sp->isr_cnt);
+       rx_intr_handler(ring);
+
+       rng_n = ring->ring_no;
+       rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+       level = rx_buffer_level(sp, rxb_size, rng_n);
+
+       if ((level == PANIC) && (!TASKLET_IN_USE)) {
+               int ret;
+               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+               DBG_PRINT(INTR_DBG, "PANIC levels\n");
+               if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+                       DBG_PRINT(ERR_DBG, "Out of memory in %s",
+                                 __FUNCTION__);
+                       clear_bit(0, (&sp->tasklet_status));
+                       return IRQ_HANDLED;
+               }
+               clear_bit(0, (&sp->tasklet_status));
+       } else if (level == LOW) {
+               tasklet_schedule(&sp->task);
+       }
+       atomic_dec(&sp->isr_cnt);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+       fifo_info_t *fifo = (fifo_info_t *)dev_id;
+       nic_t *sp = fifo->nic;
+
+       atomic_inc(&sp->isr_cnt);
+       tx_intr_handler(fifo);
+       atomic_dec(&sp->isr_cnt);
+       return IRQ_HANDLED;
+}
+
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3778,11 +4179,10 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 {
        nic_t *sp = dev->priv;
 
-       strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
-       strncpy(info->version, s2io_driver_version,
-               sizeof(s2io_driver_version));
-       strncpy(info->fw_version, "", 32);
-       strncpy(info->bus_info, pci_name(sp->pdev), 32);
+       strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
+       strncpy(info->version, s2io_driver_version, sizeof(info->version));
+       strncpy(info->fw_version, "", sizeof(info->fw_version));
+       strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
        info->regdump_len = XENA_REG_SPACE;
        info->eedump_len = XENA_EEPROM_SPACE;
        info->testinfo_len = S2IO_TEST_LEN;
@@ -3978,29 +4378,53 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
  */
 
 #define S2IO_DEV_ID            5
-static int read_eeprom(nic_t * sp, int off, u32 * data)
+static int read_eeprom(nic_t * sp, int off, u64 * data)
 {
        int ret = -1;
        u32 exit_cnt = 0;
        u64 val64;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-       val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-           I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
-           I2C_CONTROL_CNTL_START;
-       SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+                   I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+                   I2C_CONTROL_CNTL_START;
+               SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
-       while (exit_cnt < 5) {
-               val64 = readq(&bar0->i2c_control);
-               if (I2C_CONTROL_CNTL_END(val64)) {
-                       *data = I2C_CONTROL_GET_DATA(val64);
-                       ret = 0;
-                       break;
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->i2c_control);
+                       if (I2C_CONTROL_CNTL_END(val64)) {
+                               *data = I2C_CONTROL_GET_DATA(val64);
+                               ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
                }
-               msleep(50);
-               exit_cnt++;
        }
 
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+                       SPI_CONTROL_BYTECNT(0x3) | 
+                       SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               val64 |= SPI_CONTROL_REQ;
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->spi_control);
+                       if (val64 & SPI_CONTROL_NACK) {
+                               ret = 1;
+                               break;
+                       } else if (val64 & SPI_CONTROL_DONE) {
+                               *data = readq(&bar0->spi_data);
+                               *data &= 0xffffff;
+                               ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
+               }
+       }
        return ret;
 }
 
@@ -4019,28 +4443,53 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
  *  0 on success, -1 on failure.
  */
 
-static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
 {
        int exit_cnt = 0, ret = -1;
        u64 val64;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-       val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-           I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
-           I2C_CONTROL_CNTL_START;
-       SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+                   I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
+                   I2C_CONTROL_CNTL_START;
+               SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->i2c_control);
+                       if (I2C_CONTROL_CNTL_END(val64)) {
+                               if (!(val64 & I2C_CONTROL_NACK))
+                                       ret = 0;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
+               }
+       }
 
-       while (exit_cnt < 5) {
-               val64 = readq(&bar0->i2c_control);
-               if (I2C_CONTROL_CNTL_END(val64)) {
-                       if (!(val64 & I2C_CONTROL_NACK))
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               int write_cnt = (cnt == 8) ? 0 : cnt;
+               writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+
+               val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+                       SPI_CONTROL_BYTECNT(write_cnt) | 
+                       SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               val64 |= SPI_CONTROL_REQ;
+               SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+               while (exit_cnt < 5) {
+                       val64 = readq(&bar0->spi_control);
+                       if (val64 & SPI_CONTROL_NACK) {
+                               ret = 1;
+                               break;
+                       } else if (val64 & SPI_CONTROL_DONE) {
                                ret = 0;
-                       break;
+                               break;
+                       }
+                       msleep(50);
+                       exit_cnt++;
                }
-               msleep(50);
-               exit_cnt++;
        }
-
        return ret;
 }
 
@@ -4060,7 +4509,8 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
 static int s2io_ethtool_geeprom(struct net_device *dev,
                         struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
-       u32 data, i, valid;
+       u32 i, valid;
+       u64 data;
        nic_t *sp = dev->priv;
 
        eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -4098,7 +4548,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
                                u8 * data_buf)
 {
        int len = eeprom->len, cnt = 0;
-       u32 valid = 0, data;
+       u64 valid = 0, data;
        nic_t *sp = dev->priv;
 
        if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -4146,7 +4596,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
 static int s2io_register_test(nic_t * sp, uint64_t * data)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       u64 val64 = 0;
+       u64 val64 = 0, exp_val;
        int fail = 0;
 
        val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -4162,7 +4612,11 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
        }
 
        val64 = readq(&bar0->rx_queue_cfg);
-       if (val64 != 0x0808080808080808ULL) {
+       if (sp->device_type == XFRAME_II_DEVICE)
+               exp_val = 0x0404040404040404ULL;
+       else
+               exp_val = 0x0808080808080808ULL;
+       if (val64 != exp_val) {
                fail = 1;
                DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
        }
@@ -4190,7 +4644,7 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
        }
 
        *data = fail;
-       return 0;
+       return fail;
 }
 
 /**
@@ -4209,58 +4663,83 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
 static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 {
        int fail = 0;
-       u32 ret_data;
+       u64 ret_data, org_4F0, org_7F0;
+       u8 saved_4F0 = 0, saved_7F0 = 0;
+       struct net_device *dev = sp->dev;
 
        /* Test Write Error at offset 0 */
-       if (!write_eeprom(sp, 0, 0, 3))
-               fail = 1;
+       /* Note that SPI interface allows write access to all areas
+        * of EEPROM. Hence doing all negative testing only for Xframe I.
+        */
+       if (sp->device_type == XFRAME_I_DEVICE)
+               if (!write_eeprom(sp, 0, 0, 3))
+                       fail = 1;
+
+       /* Save current values at offsets 0x4F0 and 0x7F0 */
+       if (!read_eeprom(sp, 0x4F0, &org_4F0))
+               saved_4F0 = 1;
+       if (!read_eeprom(sp, 0x7F0, &org_7F0))
+               saved_7F0 = 1;
 
        /* Test Write at offset 4f0 */
-       if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
+       if (write_eeprom(sp, 0x4F0, 0x012345, 3))
                fail = 1;
        if (read_eeprom(sp, 0x4F0, &ret_data))
                fail = 1;
 
-       if (ret_data != 0x01234567)
+       if (ret_data != 0x012345) {
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
                fail = 1;
+       }
 
        /* Reset the EEPROM data go FFFF */
-       write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
+       write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
 
        /* Test Write Request Error at offset 0x7c */
-       if (!write_eeprom(sp, 0x07C, 0, 3))
-               fail = 1;
+       if (sp->device_type == XFRAME_I_DEVICE)
+               if (!write_eeprom(sp, 0x07C, 0, 3))
+                       fail = 1;
 
-       /* Test Write Request at offset 0x7fc */
-       if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
+       /* Test Write Request at offset 0x7f0 */
+       if (write_eeprom(sp, 0x7F0, 0x012345, 3))
                fail = 1;
-       if (read_eeprom(sp, 0x7FC, &ret_data))
+       if (read_eeprom(sp, 0x7F0, &ret_data))
                fail = 1;
 
-       if (ret_data != 0x01234567)
+       if (ret_data != 0x012345) {
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
                fail = 1;
+       }
 
        /* Reset the EEPROM data go FFFF */
-       write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+       write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
 
-       /* Test Write Error at offset 0x80 */
-       if (!write_eeprom(sp, 0x080, 0, 3))
-               fail = 1;
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               /* Test Write Error at offset 0x80 */
+               if (!write_eeprom(sp, 0x080, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 0xfc */
-       if (!write_eeprom(sp, 0x0FC, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 0xfc */
+               if (!write_eeprom(sp, 0x0FC, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 0x100 */
-       if (!write_eeprom(sp, 0x100, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 0x100 */
+               if (!write_eeprom(sp, 0x100, 0, 3))
+                       fail = 1;
 
-       /* Test Write Error at offset 4ec */
-       if (!write_eeprom(sp, 0x4EC, 0, 3))
-               fail = 1;
+               /* Test Write Error at offset 4ec */
+               if (!write_eeprom(sp, 0x4EC, 0, 3))
+                       fail = 1;
+       }
+
+       /* Restore values at offsets 0x4F0 and 0x7F0 */
+       if (saved_4F0)
+               write_eeprom(sp, 0x4F0, org_4F0, 3);
+       if (saved_7F0)
+               write_eeprom(sp, 0x7F0, org_7F0, 3);
 
        *data = fail;
-       return 0;
+       return fail;
 }
 
 /**
@@ -4342,7 +4821,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
-       int cnt, iteration = 0, test_pass = 0;
+       int cnt, iteration = 0, test_fail = 0;
 
        val64 = readq(&bar0->adapter_control);
        val64 &= ~ADAPTER_ECC_EN;
@@ -4350,7 +4829,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
 
        val64 = readq(&bar0->mc_rldram_test_ctrl);
        val64 |= MC_RLDRAM_TEST_MODE;
-       writeq(val64, &bar0->mc_rldram_test_ctrl);
+       SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
        val64 = readq(&bar0->mc_rldram_mrs);
        val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -4378,17 +4857,12 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                }
                writeq(val64, &bar0->mc_rldram_test_d2);
 
-               val64 = (u64) (0x0000003fffff0000ULL);
+               val64 = (u64) (0x0000003ffffe0100ULL);
                writeq(val64, &bar0->mc_rldram_test_add);
 
-
-               val64 = MC_RLDRAM_TEST_MODE;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-               val64 |=
-                   MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
-                   MC_RLDRAM_TEST_GO;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
+               val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+                       MC_RLDRAM_TEST_GO;
+               SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
                for (cnt = 0; cnt < 5; cnt++) {
                        val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4400,11 +4874,8 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                if (cnt == 5)
                        break;
 
-               val64 = MC_RLDRAM_TEST_MODE;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-               val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
-               writeq(val64, &bar0->mc_rldram_test_ctrl);
+               val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+               SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
                for (cnt = 0; cnt < 5; cnt++) {
                        val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4417,18 +4888,18 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
                        break;
 
                val64 = readq(&bar0->mc_rldram_test_ctrl);
-               if (val64 & MC_RLDRAM_TEST_PASS)
-                       test_pass = 1;
+               if (!(val64 & MC_RLDRAM_TEST_PASS))
+                       test_fail = 1;
 
                iteration++;
        }
 
-       if (!test_pass)
-               *data = 1;
-       else
-               *data = 0;
+       *data = test_fail;
 
-       return 0;
+       /* Bring the adapter out of test mode */
+       SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+
+       return test_fail;
 }
 
 /**
@@ -4932,7 +5403,7 @@ static void s2io_card_down(nic_t * sp)
 
 static int s2io_card_up(nic_t * sp)
 {
-       int i, ret;
+       int i, ret = 0;
        mac_info_t *mac_control;
        struct config_param *config;
        struct net_device *dev = (struct net_device *) sp->dev;
@@ -4944,6 +5415,15 @@ static int s2io_card_up(nic_t * sp)
                return -ENODEV;
        }
 
+       if (sp->intr_type == MSI)
+               ret = s2io_enable_msi(sp);
+       else if (sp->intr_type == MSI_X)
+               ret = s2io_enable_msi_x(sp);
+       if (ret) {
+               DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+               sp->intr_type = INTA;
+       }
+
        /*
         * Initializing the Rx buffers. For now we are considering only 1
         * Rx ring and initializing buffers into 30 Rx blocks
@@ -5228,6 +5708,8 @@ static void s2io_init_pci(nic_t * sp)
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
 module_param(tx_fifo_num, int, 0);
 module_param(rx_ring_num, int, 0);
 module_param_array(tx_fifo_len, uint, NULL, 0);
@@ -5245,6 +5727,7 @@ module_param(bimodal, bool, 0);
 module_param(indicate_max_pkts, int, 0);
 #endif
 module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
 
 /**
  *  s2io_init_nic - Initialization of the adapter .
@@ -5274,9 +5757,16 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        mac_info_t *mac_control;
        struct config_param *config;
        int mode;
+       u8 dev_intr_type = intr_type;
 
 #ifdef CONFIG_S2IO_NAPI
-       DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+       if (dev_intr_type != INTA) {
+               DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
+       else
+               DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
 #endif
 
        if ((ret = pci_enable_device(pdev))) {
@@ -5303,10 +5793,35 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                return -ENOMEM;
        }
 
-       if (pci_request_regions(pdev, s2io_driver_name)) {
-               DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
-                   pci_disable_device(pdev);
-               return -ENODEV;
+       if ((dev_intr_type == MSI_X) && 
+                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+               DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
+       if (dev_intr_type != MSI_X) {
+               if (pci_request_regions(pdev, s2io_driver_name)) {
+                       DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+                           pci_disable_device(pdev);
+                       return -ENODEV;
+               }
+       }
+       else {
+               if (!(request_mem_region(pci_resource_start(pdev, 0),
+                                pci_resource_len(pdev, 0), s2io_driver_name))) {
+                       DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
+                       pci_disable_device(pdev);
+                       return -ENODEV;
+               }
+               if (!(request_mem_region(pci_resource_start(pdev, 2),
+                                pci_resource_len(pdev, 2), s2io_driver_name))) {
+                       DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
+                       release_mem_region(pci_resource_start(pdev, 0),
+                                   pci_resource_len(pdev, 0));
+                       pci_disable_device(pdev);
+                       return -ENODEV;
+               }
        }
 
        dev = alloc_etherdev(sizeof(nic_t));
@@ -5329,6 +5844,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        sp->pdev = pdev;
        sp->high_dma_flag = dma_flag;
        sp->device_enabled_once = FALSE;
+       sp->intr_type = dev_intr_type;
 
        if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
                (pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -5336,6 +5852,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        else
                sp->device_type = XFRAME_I_DEVICE;
 
+               
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
 
@@ -5571,12 +6088,23 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        if (sp->device_type & XFRAME_II_DEVICE) {
                DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
                          dev->name);
-               DBG_PRINT(ERR_DBG, "(rev %d), %s",
+               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
                                get_xena_rev_id(sp->pdev),
                                s2io_driver_version);
 #ifdef CONFIG_2BUFF_MODE
                DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
 #endif
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
 
                DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
                DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -5595,12 +6123,23 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        } else {
                DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
                          dev->name);
-               DBG_PRINT(ERR_DBG, "(rev %d), %s",
+               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
                                        get_xena_rev_id(sp->pdev),
                                        s2io_driver_version);
 #ifdef CONFIG_2BUFF_MODE
                DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
 #endif
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
                DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
                DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
                          sp->def_mac_addr[0].mac_addr[0],
@@ -5644,7 +6183,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
       mem_alloc_failed:
        free_shared_mem(sp);
        pci_disable_device(pdev);
-       pci_release_regions(pdev);
+       if (dev_intr_type != MSI_X)
+               pci_release_regions(pdev);
+       else {
+               release_mem_region(pci_resource_start(pdev, 0),
+                       pci_resource_len(pdev, 0));
+               release_mem_region(pci_resource_start(pdev, 2),
+                       pci_resource_len(pdev, 2));
+       }
        pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
 
@@ -5678,7 +6224,14 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
        iounmap(sp->bar0);
        iounmap(sp->bar1);
        pci_disable_device(pdev);
-       pci_release_regions(pdev);
+       if (sp->intr_type != MSI_X)
+               pci_release_regions(pdev);
+       else {
+               release_mem_region(pci_resource_start(pdev, 0),
+                       pci_resource_len(pdev, 0));
+               release_mem_region(pci_resource_start(pdev, 2),
+                       pci_resource_len(pdev, 2));
+       }
        pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
 }
index 89151cb5218132414efae178eddb05f6f0515d26..1cc24b56760e1fe1773eb48cbcdecefdb27cc451 100644 (file)
@@ -652,6 +652,30 @@ typedef struct {
 #define SMALL_BLK_CNT  30
 #define LARGE_BLK_CNT  100
 
+/*
+ * Structure to keep track of the MSI-X vectors and the corresponding
+ * argument registered against each vector
+ */
+#define MAX_REQUESTED_MSI_X    17
+struct s2io_msix_entry
+{
+       u16 vector;
+       u16 entry;
+       void *arg;
+
+       u8 type;
+#define        MSIX_FIFO_TYPE  1
+#define        MSIX_RING_TYPE  2
+
+       u8 in_use;
+#define MSIX_REGISTERED_SUCCESS        0xAA
+};
+
+struct msix_info_st {
+       u64 addr;
+       u64 data;
+};
+
 /* Structure representing one instance of the NIC */
 struct s2io_nic {
 #ifdef CONFIG_S2IO_NAPI
@@ -719,13 +743,8 @@ struct s2io_nic {
         *  a schedule task that will set the correct Link state once the
         *  NIC's PHY has stabilized after a state change.
         */
-#ifdef INIT_TQUEUE
-       struct tq_struct rst_timer_task;
-       struct tq_struct set_link_task;
-#else
        struct work_struct rst_timer_task;
        struct work_struct set_link_task;
-#endif
 
        /* Flag that can be used to turn on or turn off the Rx checksum
         * offload feature.
@@ -748,10 +767,23 @@ struct s2io_nic {
        atomic_t card_state;
        volatile unsigned long link_state;
        struct vlan_group *vlgrp;
+#define MSIX_FLG                0xA5
+       struct msix_entry *entries;
+       struct s2io_msix_entry *s2io_entries;
+       char desc1[35];
+       char desc2[35];
+
+       struct msix_info_st msix_info[0x3f];
+
 #define XFRAME_I_DEVICE                1
 #define XFRAME_II_DEVICE       2
        u8 device_type;
 
+#define INTA   0
+#define MSI    1
+#define MSI_X  2
+       u8 intr_type;
+
        spinlock_t      rx_lock;
        atomic_t        isr_cnt;
 };
@@ -886,6 +918,13 @@ static int s2io_poll(struct net_device *dev, int *budget);
 static void s2io_init_pci(nic_t * sp);
 int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
 static void s2io_alarm_handle(unsigned long data);
+static int s2io_enable_msi(nic_t *nic);
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
+int s2io_enable_msi_x(nic_t *nic);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
@@ -894,4 +933,5 @@ int s2io_set_swapper(nic_t * sp);
 static void s2io_card_down(nic_t *nic);
 static int s2io_card_up(nic_t *nic);
 int get_xena_rev_id(struct pci_dev *pdev);
+void restore_xmsi_data(nic_t *nic);
 #endif                         /* _S2IO_H */
index 7abd55a4fb21fecf9e0e6204fafb490117ca464a..d4c8ecdfa4a7912eef4f5ee313bcca6cb0cca751 100644 (file)
@@ -10,7 +10,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -118,8 +118,6 @@ MODULE_PARM_DESC(int_timeout, "Timeout value");
  ********************************************************************* */
 
 
-typedef unsigned long sbmac_port_t;
-
 typedef enum { sbmac_speed_auto, sbmac_speed_10,
               sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
 
@@ -129,7 +127,7 @@ typedef enum { sbmac_duplex_auto, sbmac_duplex_half,
 typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
               sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
 
-typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, 
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
               sbmac_state_broken } sbmac_state_t;
 
 
@@ -144,17 +142,13 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
 
 #define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
 
-#define SBMAC_READCSR(t)       __raw_readq((unsigned long)t)
-#define SBMAC_WRITECSR(t,v)    __raw_writeq(v, (unsigned long)t)
-
 #define SBMAC_MAX_TXDESCR      32
 #define SBMAC_MAX_RXDESCR      32
 
 #define ETHER_ALIGN    2
 #define ETHER_ADDR_LEN 6
-#define ENET_PACKET_SIZE       1518 
-/*#define ENET_PACKET_SIZE     9216 */ 
+#define ENET_PACKET_SIZE       1518
+/*#define ENET_PACKET_SIZE     9216 */
 
 /**********************************************************************
  *  DMA Descriptor structure
@@ -172,12 +166,12 @@ typedef unsigned long paddr_t;
  ********************************************************************* */
 
 typedef struct sbmacdma_s {
-       
-       /* 
+
+       /*
         * This stuff is used to identify the channel and the registers
         * associated with it.
         */
-       
+
        struct sbmac_softc *sbdma_eth;          /* back pointer to associated MAC */
        int              sbdma_channel; /* channel number */
        int              sbdma_txdir;       /* direction (1=transmit) */
@@ -187,21 +181,21 @@ typedef struct sbmacdma_s {
        int              sbdma_int_timeout; /* # usec rx/tx interrupt */
 #endif
 
-       sbmac_port_t     sbdma_config0; /* DMA config register 0 */
-       sbmac_port_t     sbdma_config1; /* DMA config register 1 */
-       sbmac_port_t     sbdma_dscrbase;        /* Descriptor base address */
-       sbmac_port_t     sbdma_dscrcnt;     /* Descriptor count register */
-       sbmac_port_t     sbdma_curdscr; /* current descriptor address */
-       
+       volatile void __iomem *sbdma_config0;   /* DMA config register 0 */
+       volatile void __iomem *sbdma_config1;   /* DMA config register 1 */
+       volatile void __iomem *sbdma_dscrbase;  /* Descriptor base address */
+       volatile void __iomem *sbdma_dscrcnt;     /* Descriptor count register */
+       volatile void __iomem *sbdma_curdscr;   /* current descriptor address */
+
        /*
         * This stuff is for maintenance of the ring
         */
-       
+
        sbdmadscr_t     *sbdma_dscrtable;       /* base of descriptor table */
        sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */
-       
+
        struct sk_buff **sbdma_ctxtable;    /* context table, one per descr */
-       
+
        paddr_t          sbdma_dscrtable_phys; /* and also the phys addr */
        sbdmadscr_t     *sbdma_addptr;  /* next dscr for sw to add */
        sbdmadscr_t     *sbdma_remptr;  /* next dscr for sw to remove */
@@ -213,15 +207,15 @@ typedef struct sbmacdma_s {
  ********************************************************************* */
 
 struct sbmac_softc {
-       
+
        /*
         * Linux-specific things
         */
-       
+
        struct net_device *sbm_dev;             /* pointer to linux device */
        spinlock_t sbm_lock;            /* spin lock */
        struct timer_list sbm_timer;            /* for monitoring MII */
-       struct net_device_stats sbm_stats; 
+       struct net_device_stats sbm_stats;
        int sbm_devflags;                       /* current device flags */
 
        int          sbm_phy_oldbmsr;
@@ -229,31 +223,31 @@ struct sbmac_softc {
        int          sbm_phy_oldk1stsr;
        int          sbm_phy_oldlinkstat;
        int sbm_buffersize;
-       
+
        unsigned char sbm_phys[2];
-       
+
        /*
         * Controller-specific things
         */
-       
-       unsigned long   sbm_base;          /* MAC's base address */
+
+       volatile void __iomem *sbm_base;          /* MAC's base address */
        sbmac_state_t    sbm_state;         /* current state */
-       
-       sbmac_port_t     sbm_macenable; /* MAC Enable Register */
-       sbmac_port_t     sbm_maccfg;    /* MAC Configuration Register */
-       sbmac_port_t     sbm_fifocfg;   /* FIFO configuration register */
-       sbmac_port_t     sbm_framecfg;  /* Frame configuration register */
-       sbmac_port_t     sbm_rxfilter;  /* receive filter register */
-       sbmac_port_t     sbm_isr;               /* Interrupt status register */
-       sbmac_port_t     sbm_imr;               /* Interrupt mask register */
-       sbmac_port_t     sbm_mdio;              /* MDIO register */
-       
+
+       volatile void __iomem   *sbm_macenable; /* MAC Enable Register */
+       volatile void __iomem   *sbm_maccfg;    /* MAC Configuration Register */
+       volatile void __iomem   *sbm_fifocfg;   /* FIFO configuration register */
+       volatile void __iomem   *sbm_framecfg;  /* Frame configuration register */
+       volatile void __iomem   *sbm_rxfilter;  /* receive filter register */
+       volatile void __iomem   *sbm_isr;       /* Interrupt status register */
+       volatile void __iomem   *sbm_imr;       /* Interrupt mask register */
+       volatile void __iomem   *sbm_mdio;      /* MDIO register */
+
        sbmac_speed_t    sbm_speed;             /* current speed */
        sbmac_duplex_t   sbm_duplex;    /* current duplex */
        sbmac_fc_t       sbm_fc;                /* current flow control setting */
-       
+
        unsigned char    sbm_hwaddr[ETHER_ADDR_LEN];
-       
+
        sbmacdma_t       sbm_txdma;             /* for now, only use channel 0 */
        sbmacdma_t       sbm_rxdma;
        int              rx_hw_checksum;
@@ -450,13 +444,13 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
 
 /**********************************************************************
  *  SBMAC_MII_SYNC(s)
- *  
+ *
  *  Synchronize with the MII - send a pattern of bits to the MII
  *  that will guarantee that it is ready to accept a command.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -467,25 +461,25 @@ static void sbmac_mii_sync(struct sbmac_softc *s)
        uint64_t bits;
        int mac_mdio_genc;
 
-       mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-       
+       mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
        bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
-       
-       SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-       
+
+       __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
        for (cnt = 0; cnt < 32; cnt++) {
-               SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
-               SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+               __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+               __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
        }
 }
 
 /**********************************************************************
  *  SBMAC_MII_SENDDATA(s,data,bitcnt)
- *  
+ *
  *  Send some bits to the MII.  The bits to be sent are right-
  *  justified in the 'data' parameter.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
  *        data - data to send
  *        bitcnt - number of bits to send
@@ -498,20 +492,20 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
        unsigned int curmask;
        int mac_mdio_genc;
 
-       mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-       
+       mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
        bits = M_MAC_MDIO_DIR_OUTPUT;
-       SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-       
+       __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
        curmask = 1 << (bitcnt - 1);
-       
+
        for (i = 0; i < bitcnt; i++) {
                if (data & curmask)
                        bits |= M_MAC_MDIO_OUT;
                else bits &= ~M_MAC_MDIO_OUT;
-               SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-               SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
-               SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+               __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+               __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+               __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
                curmask >>= 1;
        }
 }
@@ -520,14 +514,14 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
 
 /**********************************************************************
  *  SBMAC_MII_READ(s,phyaddr,regidx)
- *  
+ *
  *  Read a PHY register.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
  *        phyaddr - PHY's address
  *        regidx = index of register to read
- *        
+ *
  *  Return value:
  *        value read, or 0 if an error occurred.
  ********************************************************************* */
@@ -543,9 +537,9 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
         * Synchronize ourselves so that the PHY knows the next
         * thing coming down is a command
         */
-       
+
        sbmac_mii_sync(s);
-       
+
        /*
         * Send the data to the PHY.  The sequence is
         * a "start" command (2 bits)
@@ -553,59 +547,55 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
         * the PHY addr (5 bits)
         * the register index (5 bits)
         */
-       
+
        sbmac_mii_senddata(s,MII_COMMAND_START, 2);
        sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
        sbmac_mii_senddata(s,phyaddr, 5);
        sbmac_mii_senddata(s,regidx, 5);
-       
-       mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-       
-       /* 
+
+       mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
+       /*
         * Switch the port around without a clock transition.
         */
-       SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-       
+       __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
        /*
         * Send out a clock pulse to signal we want the status
         */
-       
-       SBMAC_WRITECSR(s->sbm_mdio,
-                      M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
-       SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-       
-       /* 
+
+       __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+       __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
+       /*
         * If an error occurred, the PHY will signal '1' back
         */
-       error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
-       
-       /* 
+       error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
+
+       /*
         * Issue an 'idle' clock pulse, but keep the direction
         * the same.
         */
-       SBMAC_WRITECSR(s->sbm_mdio,
-                      M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
-       SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-       
+       __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+       __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
        regval = 0;
-       
+
        for (idx = 0; idx < 16; idx++) {
                regval <<= 1;
-               
+
                if (error == 0) {
-                       if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
+                       if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
                                regval |= 1;
                }
-               
-               SBMAC_WRITECSR(s->sbm_mdio,
-                              M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc);
-               SBMAC_WRITECSR(s->sbm_mdio,
-                              M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
+               __raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+               __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
        }
-       
+
        /* Switch back to output */
-       SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
-       
+       __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+
        if (error == 0)
                return regval;
        return 0;
@@ -614,15 +604,15 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
 
 /**********************************************************************
  *  SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
- *  
+ *
  *  Write a value to a PHY register.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
  *        phyaddr - PHY to use
  *        regidx - register within the PHY
  *        regval - data to write to register
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -633,7 +623,7 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
        int mac_mdio_genc;
 
        sbmac_mii_sync(s);
-       
+
        sbmac_mii_senddata(s,MII_COMMAND_START,2);
        sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
        sbmac_mii_senddata(s,phyaddr, 5);
@@ -641,27 +631,27 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
        sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
        sbmac_mii_senddata(s,regval,16);
 
-       mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+       mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
 
-       SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
+       __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
 }
 
 
 
 /**********************************************************************
  *  SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
- *  
+ *
  *  Initialize a DMA channel context.  Since there are potentially
  *  eight DMA channels per MAC, it's nice to do this in a standard
- *  way.  
- *  
- *  Input parameters: 
+ *  way.
+ *
+ *  Input parameters:
  *        d - sbmacdma_t structure (DMA channel context)
  *        s - sbmac_softc structure (pointer to a MAC)
  *        chan - channel number (0..1 right now)
  *        txrx - Identifies DMA_TX or DMA_RX for channel direction
  *      maxdescr - number of descriptors
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -672,101 +662,87 @@ static void sbdma_initctx(sbmacdma_t *d,
                          int txrx,
                          int maxdescr)
 {
-       /* 
-        * Save away interesting stuff in the structure 
+       /*
+        * Save away interesting stuff in the structure
         */
-       
+
        d->sbdma_eth       = s;
        d->sbdma_channel   = chan;
        d->sbdma_txdir     = txrx;
-       
+
 #if 0
        /* RMON clearing */
        s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
 #endif
 
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
-       SBMAC_WRITECSR(IOADDR(
-       A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
-
-       /* 
-        * initialize register pointers 
-        */
-       
-       d->sbdma_config0 = 
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
+       __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
+
+       /*
+        * initialize register pointers
+        */
+
+       d->sbdma_config0 =
                s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
-       d->sbdma_config1 = 
+       d->sbdma_config1 =
                s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
-       d->sbdma_dscrbase = 
+       d->sbdma_dscrbase =
                s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
-       d->sbdma_dscrcnt = 
+       d->sbdma_dscrcnt =
                s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
-       d->sbdma_curdscr =      
+       d->sbdma_curdscr =
                s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
-       
+
        /*
         * Allocate memory for the ring
         */
-       
+
        d->sbdma_maxdescr = maxdescr;
-       
-       d->sbdma_dscrtable = (sbdmadscr_t *) 
-               kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
-       
+
+       d->sbdma_dscrtable = (sbdmadscr_t *)
+               kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
+
+       /*
+        * The descriptor table must be aligned to at least 16 bytes or the
+        * MAC will corrupt it.
+        */
+       d->sbdma_dscrtable = (sbdmadscr_t *)
+               ALIGN((unsigned long)d->sbdma_dscrtable, sizeof(sbdmadscr_t));
+
        memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
-       
+
        d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
-       
+
        d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
-       
+
        /*
         * And context table
         */
-       
-       d->sbdma_ctxtable = (struct sk_buff **) 
+
+       d->sbdma_ctxtable = (struct sk_buff **)
                kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
-       
+
        memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
-       
+
 #ifdef CONFIG_SBMAC_COALESCE
        /*
         * Setup Rx/Tx DMA coalescing defaults
@@ -777,7 +753,7 @@ static void sbdma_initctx(sbmacdma_t *d,
        } else {
                d->sbdma_int_pktcnt = 1;
        }
-       
+
        if ( int_timeout ) {
                d->sbdma_int_timeout = int_timeout;
        } else {
@@ -789,13 +765,13 @@ static void sbdma_initctx(sbmacdma_t *d,
 
 /**********************************************************************
  *  SBDMA_CHANNEL_START(d)
- *  
+ *
  *  Initialize the hardware registers for a DMA channel.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d - DMA channel to init (context must be previously init'd
  *         rxtx - DMA_RX or DMA_TX depending on what type of channel
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -805,24 +781,21 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
        /*
         * Turn on the DMA channel
         */
-       
+
 #ifdef CONFIG_SBMAC_COALESCE
-       SBMAC_WRITECSR(d->sbdma_config1,
-                      V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
-                      0);
-       SBMAC_WRITECSR(d->sbdma_config0,
-                      M_DMA_EOP_INT_EN |
+       __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+                      0, d->sbdma_config1);
+       __raw_writeq(M_DMA_EOP_INT_EN |
                       V_DMA_RINGSZ(d->sbdma_maxdescr) |
                       V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
-                      0);
+                      0, d->sbdma_config0);
 #else
-       SBMAC_WRITECSR(d->sbdma_config1,0);
-       SBMAC_WRITECSR(d->sbdma_config0,
-                      V_DMA_RINGSZ(d->sbdma_maxdescr) |
-                      0);
+       __raw_writeq(0, d->sbdma_config1);
+       __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
+                      0, d->sbdma_config0);
 #endif
 
-       SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+       __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
 
        /*
         * Initialize ring pointers
@@ -834,12 +807,12 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
 
 /**********************************************************************
  *  SBDMA_CHANNEL_STOP(d)
- *  
+ *
  *  Initialize the hardware registers for a DMA channel.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d - DMA channel to init (context must be previously init'd
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -849,44 +822,44 @@ static void sbdma_channel_stop(sbmacdma_t *d)
        /*
         * Turn off the DMA channel
         */
-       
-       SBMAC_WRITECSR(d->sbdma_config1,0);
-       
-       SBMAC_WRITECSR(d->sbdma_dscrbase,0);
-       
-       SBMAC_WRITECSR(d->sbdma_config0,0);
-       
+
+       __raw_writeq(0, d->sbdma_config1);
+
+       __raw_writeq(0, d->sbdma_dscrbase);
+
+       __raw_writeq(0, d->sbdma_config0);
+
        /*
         * Zero ring pointers
         */
-       
-       d->sbdma_addptr = 0;
-       d->sbdma_remptr = 0;
+
+       d->sbdma_addptr = NULL;
+       d->sbdma_remptr = NULL;
 }
 
 static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
 {
        unsigned long addr;
        unsigned long newaddr;
-       
+
        addr = (unsigned long) skb->data;
-       
+
        newaddr = (addr + power2 - 1) & ~(power2 - 1);
-       
+
        skb_reserve(skb,newaddr-addr+offset);
 }
 
 
 /**********************************************************************
  *  SBDMA_ADD_RCVBUFFER(d,sb)
- *  
+ *
  *  Add a buffer to the specified DMA channel.   For receive channels,
  *  this queues a buffer for inbound packets.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d - DMA channel descriptor
  *        sb - sk_buff to add, or NULL if we should allocate one
- *        
+ *
  *  Return value:
  *        0 if buffer could not be added (ring is full)
  *        1 if buffer added successfully
@@ -899,24 +872,24 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
        sbdmadscr_t *nextdsc;
        struct sk_buff *sb_new = NULL;
        int pktsize = ENET_PACKET_SIZE;
-       
+
        /* get pointer to our current place in the ring */
-       
+
        dsc = d->sbdma_addptr;
        nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-       
+
        /*
         * figure out if the ring is full - if the next descriptor
         * is the same as the one that we're going to remove from
         * the ring, the ring is full
         */
-       
+
        if (nextdsc == d->sbdma_remptr) {
                return -ENOSPC;
        }
 
-       /* 
-        * Allocate a sk_buff if we don't already have one.  
+       /*
+        * Allocate a sk_buff if we don't already have one.
         * If we do have an sk_buff, reset it so that it's empty.
         *
         * Note: sk_buffs don't seem to be guaranteed to have any sort
@@ -925,7 +898,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
         *
         *    1. the data does not start in the middle of a cache line.
         *    2. The data does not end in the middle of a cache line
-        *    3. The buffer can be aligned such that the IP addresses are 
+        *    3. The buffer can be aligned such that the IP addresses are
         *       naturally aligned.
         *
         *  Remember, the SOCs MAC writes whole cache lines at a time,
@@ -933,7 +906,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
         *  data portion starts in the middle of a cache line, the SOC
         *  DMA will trash the beginning (and ending) portions.
         */
-       
+
        if (sb == NULL) {
                sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
                if (sb_new == NULL) {
@@ -949,23 +922,22 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
        }
        else {
                sb_new = sb;
-               /* 
+               /*
                 * nothing special to reinit buffer, it's already aligned
                 * and sb->data already points to a good place.
                 */
        }
-       
+
        /*
-        * fill in the descriptor 
+        * fill in the descriptor
         */
-       
+
 #ifdef CONFIG_SBMAC_COALESCE
        /*
         * Do not interrupt per DMA transfer.
         */
        dsc->dscr_a = virt_to_phys(sb_new->data) |
-               V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
-               0;
+               V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
 #else
        dsc->dscr_a = virt_to_phys(sb_new->data) |
                V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
@@ -974,38 +946,38 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
 
        /* receiving: no options */
        dsc->dscr_b = 0;
-       
+
        /*
-        * fill in the context 
+        * fill in the context
         */
-       
+
        d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
-       
-       /* 
-        * point at next packet 
+
+       /*
+        * point at next packet
         */
-       
+
        d->sbdma_addptr = nextdsc;
-       
-       /* 
+
+       /*
         * Give the buffer to the DMA engine.
         */
-       
-       SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-       
+
+       __raw_writeq(1, d->sbdma_dscrcnt);
+
        return 0;                                       /* we did it */
 }
 
 /**********************************************************************
  *  SBDMA_ADD_TXBUFFER(d,sb)
- *  
+ *
  *  Add a transmit buffer to the specified DMA channel, causing a
  *  transmit to start.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d - DMA channel descriptor
  *        sb - sk_buff to add
- *        
+ *
  *  Return value:
  *        0 transmit queued successfully
  *        otherwise error code
@@ -1019,70 +991,70 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
        uint64_t phys;
        uint64_t ncb;
        int length;
-       
+
        /* get pointer to our current place in the ring */
-       
+
        dsc = d->sbdma_addptr;
        nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-       
+
        /*
         * figure out if the ring is full - if the next descriptor
         * is the same as the one that we're going to remove from
         * the ring, the ring is full
         */
-       
+
        if (nextdsc == d->sbdma_remptr) {
                return -ENOSPC;
        }
-       
+
        /*
         * Under Linux, it's not necessary to copy/coalesce buffers
         * like it is on NetBSD.  We think they're all contiguous,
         * but that may not be true for GBE.
         */
-       
+
        length = sb->len;
-       
+
        /*
         * fill in the descriptor.  Note that the number of cache
         * blocks in the descriptor is the number of blocks
         * *spanned*, so we need to add in the offset (if any)
         * while doing the calculation.
         */
-       
+
        phys = virt_to_phys(sb->data);
        ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
 
-       dsc->dscr_a = phys | 
+       dsc->dscr_a = phys |
                V_DMA_DSCRA_A_SIZE(ncb) |
 #ifndef CONFIG_SBMAC_COALESCE
                M_DMA_DSCRA_INTERRUPT |
 #endif
                M_DMA_ETHTX_SOP;
-       
+
        /* transmitting: set outbound options and length */
 
        dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
                V_DMA_DSCRB_PKT_SIZE(length);
-       
+
        /*
-        * fill in the context 
+        * fill in the context
         */
-       
+
        d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
-       
-       /* 
-        * point at next packet 
+
+       /*
+        * point at next packet
         */
-       
+
        d->sbdma_addptr = nextdsc;
-       
-       /* 
+
+       /*
         * Give the buffer to the DMA engine.
         */
-       
-       SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-       
+
+       __raw_writeq(1, d->sbdma_dscrcnt);
+
        return 0;                                       /* we did it */
 }
 
@@ -1091,12 +1063,12 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
 
 /**********************************************************************
  *  SBDMA_EMPTYRING(d)
- *  
+ *
  *  Free all allocated sk_buffs on the specified DMA channel;
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d  - DMA channel
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1105,7 +1077,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
 {
        int idx;
        struct sk_buff *sb;
-       
+
        for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
                sb = d->sbdma_ctxtable[idx];
                if (sb) {
@@ -1118,13 +1090,13 @@ static void sbdma_emptyring(sbmacdma_t *d)
 
 /**********************************************************************
  *  SBDMA_FILLRING(d)
- *  
+ *
  *  Fill the specified DMA channel (must be receive channel)
  *  with sk_buffs
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        d - DMA channel
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1132,7 +1104,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
 static void sbdma_fillring(sbmacdma_t *d)
 {
        int idx;
-       
+
        for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
                if (sbdma_add_rcvbuffer(d,NULL) != 0)
                        break;
@@ -1142,16 +1114,16 @@ static void sbdma_fillring(sbmacdma_t *d)
 
 /**********************************************************************
  *  SBDMA_RX_PROCESS(sc,d)
- *  
- *  Process "completed" receive buffers on the specified DMA channel.  
+ *
+ *  Process "completed" receive buffers on the specified DMA channel.
  *  Note that this isn't really ideal for priority channels, since
- *  it processes all of the packets on a given channel before 
- *  returning. 
+ *  it processes all of the packets on a given channel before
+ *  returning.
  *
- *  Input parameters: 
+ *  Input parameters:
  *        sc - softc structure
  *        d - DMA channel context
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1163,56 +1135,56 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
        sbdmadscr_t *dsc;
        struct sk_buff *sb;
        int len;
-       
+
        for (;;) {
-               /* 
+               /*
                 * figure out where we are (as an index) and where
                 * the hardware is (also as an index)
                 *
-                * This could be done faster if (for example) the 
+                * This could be done faster if (for example) the
                 * descriptor table was page-aligned and contiguous in
                 * both virtual and physical memory -- you could then
                 * just compare the low-order bits of the virtual address
                 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
                 */
-               
+
                curidx = d->sbdma_remptr - d->sbdma_dscrtable;
-               hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+               hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
                                d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
-               
+
                /*
                 * If they're the same, that means we've processed all
                 * of the descriptors up to (but not including) the one that
                 * the hardware is working on right now.
                 */
-               
+
                if (curidx == hwidx)
                        break;
-               
+
                /*
                 * Otherwise, get the packet's sk_buff ptr back
                 */
-               
+
                dsc = &(d->sbdma_dscrtable[curidx]);
                sb = d->sbdma_ctxtable[curidx];
                d->sbdma_ctxtable[curidx] = NULL;
-               
+
                len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
-               
+
                /*
                 * Check packet status.  If good, process it.
                 * If not, silently drop it and put it back on the
                 * receive ring.
                 */
-               
+
                if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
-                       
+
                        /*
                         * Add a new buffer to replace the old one.  If we fail
                         * to allocate a buffer, we're going to drop this
                         * packet and put it right back on the receive ring.
                         */
-                       
+
                        if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
                                sc->sbm_stats.rx_dropped++;
                                sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
@@ -1221,7 +1193,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
                                 * Set length into the packet
                                 */
                                skb_put(sb,len);
-                               
+
                                /*
                                 * Buffer has been replaced on the
                                 * receive ring.  Pass the buffer to
@@ -1240,7 +1212,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
                                                sb->ip_summed = CHECKSUM_NONE;
                                        }
                                }
-                               
+
                                netif_rx(sb);
                        }
                } else {
@@ -1251,14 +1223,14 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
                        sc->sbm_stats.rx_errors++;
                        sbdma_add_rcvbuffer(d,sb);
                }
-               
-               
-               /* 
+
+
+               /*
                 * .. and advance to the next buffer.
                 */
-               
+
                d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-               
+
        }
 }
 
@@ -1266,17 +1238,17 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
 
 /**********************************************************************
  *  SBDMA_TX_PROCESS(sc,d)
- *  
- *  Process "completed" transmit buffers on the specified DMA channel.  
+ *
+ *  Process "completed" transmit buffers on the specified DMA channel.
  *  This is normally called within the interrupt service routine.
  *  Note that this isn't really ideal for priority channels, since
- *  it processes all of the packets on a given channel before 
- *  returning. 
+ *  it processes all of the packets on a given channel before
+ *  returning.
  *
- *  Input parameters: 
+ *  Input parameters:
  *      sc - softc structure
  *        d - DMA channel context
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1290,21 +1262,21 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
        unsigned long flags;
 
        spin_lock_irqsave(&(sc->sbm_lock), flags);
-       
+
        for (;;) {
-               /* 
+               /*
                 * figure out where we are (as an index) and where
                 * the hardware is (also as an index)
                 *
-                * This could be done faster if (for example) the 
+                * This could be done faster if (for example) the
                 * descriptor table was page-aligned and contiguous in
                 * both virtual and physical memory -- you could then
                 * just compare the low-order bits of the virtual address
                 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
                 */
-               
+
                curidx = d->sbdma_remptr - d->sbdma_dscrtable;
-               hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+               hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
                                d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
 
                /*
@@ -1312,75 +1284,75 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
                 * of the descriptors up to (but not including) the one that
                 * the hardware is working on right now.
                 */
-               
+
                if (curidx == hwidx)
                        break;
-               
+
                /*
                 * Otherwise, get the packet's sk_buff ptr back
                 */
-               
+
                dsc = &(d->sbdma_dscrtable[curidx]);
                sb = d->sbdma_ctxtable[curidx];
                d->sbdma_ctxtable[curidx] = NULL;
-               
+
                /*
                 * Stats
                 */
-               
+
                sc->sbm_stats.tx_bytes += sb->len;
                sc->sbm_stats.tx_packets++;
-               
+
                /*
                 * for transmits, we just free buffers.
                 */
-               
+
                dev_kfree_skb_irq(sb);
-               
-               /* 
+
+               /*
                 * .. and advance to the next buffer.
                 */
 
                d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-               
+
        }
-       
+
        /*
         * Decide if we should wake up the protocol or not.
         * Other drivers seem to do this when we reach a low
         * watermark on the transmit queue.
         */
-       
+
        netif_wake_queue(d->sbdma_eth->sbm_dev);
-       
+
        spin_unlock_irqrestore(&(sc->sbm_lock), flags);
-       
+
 }
 
 
 
 /**********************************************************************
  *  SBMAC_INITCTX(s)
- *  
+ *
  *  Initialize an Ethernet context structure - this is called
  *  once per MAC on the 1250.  Memory is allocated here, so don't
  *  call it again from inside the ioctl routines that bring the
  *  interface up/down
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac context structure
- *        
+ *
  *  Return value:
  *        0
  ********************************************************************* */
 
 static int sbmac_initctx(struct sbmac_softc *s)
 {
-       
-       /* 
-        * figure out the addresses of some ports 
+
+       /*
+        * figure out the addresses of some ports
         */
-       
+
        s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
        s->sbm_maccfg    = s->sbm_base + R_MAC_CFG;
        s->sbm_fifocfg   = s->sbm_base + R_MAC_THRSH_CFG;
@@ -1397,29 +1369,29 @@ static int sbmac_initctx(struct sbmac_softc *s)
        s->sbm_phy_oldanlpar = 0;
        s->sbm_phy_oldk1stsr = 0;
        s->sbm_phy_oldlinkstat = 0;
-       
+
        /*
         * Initialize the DMA channels.  Right now, only one per MAC is used
         * Note: Only do this _once_, as it allocates memory from the kernel!
         */
-       
+
        sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
        sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-       
+
        /*
         * initial state is OFF
         */
-       
+
        s->sbm_state = sbmac_state_off;
-       
+
        /*
         * Initial speed is (XXX TEMP) 10MBit/s HDX no FC
         */
-       
+
        s->sbm_speed = sbmac_speed_10;
        s->sbm_duplex = sbmac_duplex_half;
        s->sbm_fc = sbmac_fc_disabled;
-       
+
        return 0;
 }
 
@@ -1430,7 +1402,7 @@ static void sbdma_uninitctx(struct sbmacdma_s *d)
                kfree(d->sbdma_dscrtable);
                d->sbdma_dscrtable = NULL;
        }
-       
+
        if (d->sbdma_ctxtable) {
                kfree(d->sbdma_ctxtable);
                d->sbdma_ctxtable = NULL;
@@ -1447,12 +1419,12 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
 
 /**********************************************************************
  *  SBMAC_CHANNEL_START(s)
- *  
+ *
  *  Start packet processing on this MAC.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1460,49 +1432,49 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
 static void sbmac_channel_start(struct sbmac_softc *s)
 {
        uint64_t reg;
-       sbmac_port_t port;
+       volatile void __iomem *port;
        uint64_t cfg,fifo,framecfg;
        int idx, th_value;
-       
+
        /*
         * Don't do this if running
         */
 
        if (s->sbm_state == sbmac_state_on)
                return;
-       
+
        /*
         * Bring the controller out of reset, but leave it off.
         */
-       
-       SBMAC_WRITECSR(s->sbm_macenable,0);
-       
+
+       __raw_writeq(0, s->sbm_macenable);
+
        /*
         * Ignore all received packets
         */
-       
-       SBMAC_WRITECSR(s->sbm_rxfilter,0);
-       
-       /* 
+
+       __raw_writeq(0, s->sbm_rxfilter);
+
+       /*
         * Calculate values for various control registers.
         */
-       
+
        cfg = M_MAC_RETRY_EN |
-               M_MAC_TX_HOLD_SOP_EN | 
+               M_MAC_TX_HOLD_SOP_EN |
                V_MAC_TX_PAUSE_CNT_16K |
                M_MAC_AP_STAT_EN |
                M_MAC_FAST_SYNC |
                M_MAC_SS_EN |
                0;
-       
-       /* 
+
+       /*
         * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
         * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
         * Use a larger RD_THRSH for gigabit
         */
-       if (periph_rev >= 2) 
+       if (periph_rev >= 2)
                th_value = 64;
-       else 
+       else
                th_value = 28;
 
        fifo = V_MAC_TX_WR_THRSH(4) |   /* Must be '4' or '8' */
@@ -1520,51 +1492,51 @@ static void sbmac_channel_start(struct sbmac_softc *s)
                V_MAC_BACKOFF_SEL(1);
 
        /*
-        * Clear out the hash address map 
+        * Clear out the hash address map
         */
-       
+
        port = s->sbm_base + R_MAC_HASH_BASE;
        for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
-               SBMAC_WRITECSR(port,0);
+               __raw_writeq(0, port);
                port += sizeof(uint64_t);
        }
-       
+
        /*
         * Clear out the exact-match table
         */
-       
+
        port = s->sbm_base + R_MAC_ADDR_BASE;
        for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
-               SBMAC_WRITECSR(port,0);
+               __raw_writeq(0, port);
                port += sizeof(uint64_t);
        }
-       
+
        /*
         * Clear out the DMA Channel mapping table registers
         */
-       
+
        port = s->sbm_base + R_MAC_CHUP0_BASE;
        for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
-               SBMAC_WRITECSR(port,0);
+               __raw_writeq(0, port);
                port += sizeof(uint64_t);
        }
 
 
        port = s->sbm_base + R_MAC_CHLO0_BASE;
        for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
-               SBMAC_WRITECSR(port,0);
+               __raw_writeq(0, port);
                port += sizeof(uint64_t);
        }
-       
+
        /*
         * Program the hardware address.  It goes into the hardware-address
         * register as well as the first filter register.
         */
-       
+
        reg = sbmac_addr2reg(s->sbm_hwaddr);
-       
+
        port = s->sbm_base + R_MAC_ADDR_BASE;
-       SBMAC_WRITECSR(port,reg);
+       __raw_writeq(reg, port);
        port = s->sbm_base + R_MAC_ETHERNET_ADDR;
 
 #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -1573,108 +1545,105 @@ static void sbmac_channel_start(struct sbmac_softc *s)
         * destination address in the R_MAC_ETHERNET_ADDR register.
         * Set the value to zero.
         */
-       SBMAC_WRITECSR(port,0);
+       __raw_writeq(0, port);
 #else
-       SBMAC_WRITECSR(port,reg);
+       __raw_writeq(reg, port);
 #endif
-       
+
        /*
         * Set the receive filter for no packets, and write values
         * to the various config registers
         */
-       
-       SBMAC_WRITECSR(s->sbm_rxfilter,0);
-       SBMAC_WRITECSR(s->sbm_imr,0);
-       SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
-       SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
-       SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-       
+
+       __raw_writeq(0, s->sbm_rxfilter);
+       __raw_writeq(0, s->sbm_imr);
+       __raw_writeq(framecfg, s->sbm_framecfg);
+       __raw_writeq(fifo, s->sbm_fifocfg);
+       __raw_writeq(cfg, s->sbm_maccfg);
+
        /*
         * Initialize DMA channels (rings should be ok now)
         */
-       
+
        sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
        sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
-       
+
        /*
         * Configure the speed, duplex, and flow control
         */
 
        sbmac_set_speed(s,s->sbm_speed);
        sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
-       
+
        /*
         * Fill the receive ring
         */
-       
+
        sbdma_fillring(&(s->sbm_rxdma));
-       
-       /* 
+
+       /*
         * Turn on the rest of the bits in the enable register
-        */      
-       
-       SBMAC_WRITECSR(s->sbm_macenable,
-                      M_MAC_RXDMA_EN0 |
+        */
+
+       __raw_writeq(M_MAC_RXDMA_EN0 |
                       M_MAC_TXDMA_EN0 |
                       M_MAC_RX_ENABLE |
-                      M_MAC_TX_ENABLE);
-       
-       
+                      M_MAC_TX_ENABLE, s->sbm_macenable);
+
+
 
 
 #ifdef CONFIG_SBMAC_COALESCE
        /*
         * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
         */
-       SBMAC_WRITECSR(s->sbm_imr,
-                      ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
-                      ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+       __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+                      ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
 #else
        /*
         * Accept any kind of interrupt on TX and RX DMA channel 0
         */
-       SBMAC_WRITECSR(s->sbm_imr,
-                      (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
-                      (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+       __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+                      (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
 #endif
-       
-       /* 
-        * Enable receiving unicasts and broadcasts 
+
+       /*
+        * Enable receiving unicasts and broadcasts
         */
-       
-       SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
-       
+
+       __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
+
        /*
-        * we're running now. 
+        * we're running now.
         */
-       
+
        s->sbm_state = sbmac_state_on;
-       
-       /* 
-        * Program multicast addresses 
+
+       /*
+        * Program multicast addresses
         */
-       
+
        sbmac_setmulti(s);
-       
-       /* 
-        * If channel was in promiscuous mode before, turn that on 
+
+       /*
+        * If channel was in promiscuous mode before, turn that on
         */
-       
+
        if (s->sbm_devflags & IFF_PROMISC) {
                sbmac_promiscuous_mode(s,1);
        }
-       
+
 }
 
 
 /**********************************************************************
  *  SBMAC_CHANNEL_STOP(s)
- *  
+ *
  *  Stop packet processing on this MAC.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1682,49 +1651,49 @@ static void sbmac_channel_start(struct sbmac_softc *s)
 static void sbmac_channel_stop(struct sbmac_softc *s)
 {
        /* don't do this if already stopped */
-       
+
        if (s->sbm_state == sbmac_state_off)
                return;
-       
+
        /* don't accept any packets, disable all interrupts */
-       
-       SBMAC_WRITECSR(s->sbm_rxfilter,0);
-       SBMAC_WRITECSR(s->sbm_imr,0);
-       
+
+       __raw_writeq(0, s->sbm_rxfilter);
+       __raw_writeq(0, s->sbm_imr);
+
        /* Turn off ticker */
-       
+
        /* XXX */
-       
+
        /* turn off receiver and transmitter */
-       
-       SBMAC_WRITECSR(s->sbm_macenable,0);
-       
+
+       __raw_writeq(0, s->sbm_macenable);
+
        /* We're stopped now. */
-       
+
        s->sbm_state = sbmac_state_off;
-       
+
        /*
         * Stop DMA channels (rings should be ok now)
         */
-       
+
        sbdma_channel_stop(&(s->sbm_rxdma));
        sbdma_channel_stop(&(s->sbm_txdma));
-       
+
        /* Empty the receive and transmit rings */
-       
+
        sbdma_emptyring(&(s->sbm_rxdma));
        sbdma_emptyring(&(s->sbm_txdma));
-       
+
 }
 
 /**********************************************************************
  *  SBMAC_SET_CHANNEL_STATE(state)
- *  
+ *
  *  Set the channel's state ON or OFF
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        state - new state
- *        
+ *
  *  Return value:
  *        old state
  ********************************************************************* */
@@ -1732,43 +1701,43 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
                                             sbmac_state_t state)
 {
        sbmac_state_t oldstate = sc->sbm_state;
-       
+
        /*
         * If same as previous state, return
         */
-       
+
        if (state == oldstate) {
                return oldstate;
        }
-       
+
        /*
-        * If new state is ON, turn channel on 
+        * If new state is ON, turn channel on
         */
-       
+
        if (state == sbmac_state_on) {
                sbmac_channel_start(sc);
        }
        else {
                sbmac_channel_stop(sc);
        }
-       
+
        /*
         * Return previous state
         */
-       
+
        return oldstate;
 }
 
 
 /**********************************************************************
  *  SBMAC_PROMISCUOUS_MODE(sc,onoff)
- *  
+ *
  *  Turn on or off promiscuous mode
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        sc - softc
  *      onoff - 1 to turn on, 0 to turn off
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1776,30 +1745,30 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
 static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
 {
        uint64_t reg;
-       
+
        if (sc->sbm_state != sbmac_state_on)
                return;
-       
+
        if (onoff) {
-               reg = SBMAC_READCSR(sc->sbm_rxfilter);
+               reg = __raw_readq(sc->sbm_rxfilter);
                reg |= M_MAC_ALLPKT_EN;
-               SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-       }       
+               __raw_writeq(reg, sc->sbm_rxfilter);
+       }
        else {
-               reg = SBMAC_READCSR(sc->sbm_rxfilter);
+               reg = __raw_readq(sc->sbm_rxfilter);
                reg &= ~M_MAC_ALLPKT_EN;
-               SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+               __raw_writeq(reg, sc->sbm_rxfilter);
        }
 }
 
 /**********************************************************************
  *  SBMAC_SETIPHDR_OFFSET(sc,onoff)
- *  
+ *
  *  Set the iphdr offset as 15 assuming ethernet encapsulation
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        sc - softc
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -1807,12 +1776,12 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
 static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
 {
        uint64_t reg;
-       
+
        /* Hard code the off set to 15 for now */
-       reg = SBMAC_READCSR(sc->sbm_rxfilter);
+       reg = __raw_readq(sc->sbm_rxfilter);
        reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
-       SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-       
+       __raw_writeq(reg, sc->sbm_rxfilter);
+
        /* read system identification to determine revision */
        if (periph_rev >= 2) {
                sc->rx_hw_checksum = ENABLE;
@@ -1824,13 +1793,13 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
 
 /**********************************************************************
  *  SBMAC_ADDR2REG(ptr)
- *  
+ *
  *  Convert six bytes into the 64-bit register value that
  *  we typically write into the SBMAC's address/mcast registers
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        ptr - pointer to 6 bytes
- *        
+ *
  *  Return value:
  *        register value
  ********************************************************************* */
@@ -1838,35 +1807,35 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
 static uint64_t sbmac_addr2reg(unsigned char *ptr)
 {
        uint64_t reg = 0;
-       
+
        ptr += 6;
-       
-       reg |= (uint64_t) *(--ptr); 
+
+       reg |= (uint64_t) *(--ptr);
        reg <<= 8;
-       reg |= (uint64_t) *(--ptr); 
+       reg |= (uint64_t) *(--ptr);
        reg <<= 8;
-       reg |= (uint64_t) *(--ptr); 
+       reg |= (uint64_t) *(--ptr);
        reg <<= 8;
-       reg |= (uint64_t) *(--ptr); 
+       reg |= (uint64_t) *(--ptr);
        reg <<= 8;
-       reg |= (uint64_t) *(--ptr); 
+       reg |= (uint64_t) *(--ptr);
        reg <<= 8;
-       reg |= (uint64_t) *(--ptr); 
-       
+       reg |= (uint64_t) *(--ptr);
+
        return reg;
 }
 
 
 /**********************************************************************
  *  SBMAC_SET_SPEED(s,speed)
- *  
+ *
  *  Configure LAN speed for the specified MAC.
  *  Warning: must be called when MAC is off!
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
  *        speed - speed to set MAC to (see sbmac_speed_t enum)
- *        
+ *
  *  Return value:
  *        1 if successful
  *      0 indicates invalid parameters
@@ -1880,31 +1849,31 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
        /*
         * Save new current values
         */
-       
+
        s->sbm_speed = speed;
-       
+
        if (s->sbm_state == sbmac_state_on)
                return 0;       /* save for next restart */
 
        /*
-        * Read current register values 
+        * Read current register values
         */
-       
-       cfg = SBMAC_READCSR(s->sbm_maccfg);
-       framecfg = SBMAC_READCSR(s->sbm_framecfg);
-       
+
+       cfg = __raw_readq(s->sbm_maccfg);
+       framecfg = __raw_readq(s->sbm_framecfg);
+
        /*
         * Mask out the stuff we want to change
         */
-       
+
        cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
        framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
                      M_MAC_SLOT_SIZE);
-       
+
        /*
         * Now add in the new bits
         */
-       
+
        switch (speed) {
        case sbmac_speed_10:
                framecfg |= V_MAC_IFG_RX_10 |
@@ -1913,7 +1882,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
                        V_MAC_SLOT_SIZE_10;
                cfg |= V_MAC_SPEED_SEL_10MBPS;
                break;
-               
+
        case sbmac_speed_100:
                framecfg |= V_MAC_IFG_RX_100 |
                        V_MAC_IFG_TX_100 |
@@ -1921,7 +1890,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
                        V_MAC_SLOT_SIZE_100;
                cfg |= V_MAC_SPEED_SEL_100MBPS ;
                break;
-               
+
        case sbmac_speed_1000:
                framecfg |= V_MAC_IFG_RX_1000 |
                        V_MAC_IFG_TX_1000 |
@@ -1929,34 +1898,34 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
                        V_MAC_SLOT_SIZE_1000;
                cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
                break;
-               
+
        case sbmac_speed_auto:          /* XXX not implemented */
                /* fall through */
        default:
                return 0;
        }
-       
+
        /*
-        * Send the bits back to the hardware 
+        * Send the bits back to the hardware
         */
-       
-       SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
-       SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-       
+
+       __raw_writeq(framecfg, s->sbm_framecfg);
+       __raw_writeq(cfg, s->sbm_maccfg);
+
        return 1;
 }
 
 /**********************************************************************
  *  SBMAC_SET_DUPLEX(s,duplex,fc)
- *  
+ *
  *  Set Ethernet duplex and flow control options for this MAC
  *  Warning: must be called when MAC is off!
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        s - sbmac structure
  *        duplex - duplex setting (see sbmac_duplex_t)
  *        fc - flow control setting (see sbmac_fc_t)
- *        
+ *
  *  Return value:
  *        1 if ok
  *        0 if an invalid parameter combination was specified
@@ -1965,67 +1934,67 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
 static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
 {
        uint64_t cfg;
-       
+
        /*
         * Save new current values
         */
-       
+
        s->sbm_duplex = duplex;
        s->sbm_fc = fc;
-       
+
        if (s->sbm_state == sbmac_state_on)
                return 0;       /* save for next restart */
-       
+
        /*
-        * Read current register values 
+        * Read current register values
         */
-       
-       cfg = SBMAC_READCSR(s->sbm_maccfg);
-       
+
+       cfg = __raw_readq(s->sbm_maccfg);
+
        /*
         * Mask off the stuff we're about to change
         */
-       
+
        cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
-       
-       
+
+
        switch (duplex) {
        case sbmac_duplex_half:
                switch (fc) {
                case sbmac_fc_disabled:
                        cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
                        break;
-                       
+
                case sbmac_fc_collision:
                        cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
                        break;
-                       
+
                case sbmac_fc_carrier:
                        cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
                        break;
-                       
+
                case sbmac_fc_auto:             /* XXX not implemented */
-                       /* fall through */                                         
+                       /* fall through */
                case sbmac_fc_frame:            /* not valid in half duplex */
                default:                        /* invalid selection */
                        return 0;
                }
                break;
-               
+
        case sbmac_duplex_full:
                switch (fc) {
                case sbmac_fc_disabled:
                        cfg |= V_MAC_FC_CMD_DISABLED;
                        break;
-                       
+
                case sbmac_fc_frame:
                        cfg |= V_MAC_FC_CMD_ENABLED;
                        break;
-                       
+
                case sbmac_fc_collision:        /* not valid in full duplex */
                case sbmac_fc_carrier:          /* not valid in full duplex */
                case sbmac_fc_auto:             /* XXX not implemented */
-                       /* fall through */                                         
+                       /* fall through */
                default:
                        return 0;
                }
@@ -2034,13 +2003,13 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
                /* XXX not implemented */
                break;
        }
-       
+
        /*
-        * Send the bits back to the hardware 
+        * Send the bits back to the hardware
         */
-       
-       SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-       
+
+       __raw_writeq(cfg, s->sbm_maccfg);
+
        return 1;
 }
 
@@ -2049,12 +2018,12 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
 
 /**********************************************************************
  *  SBMAC_INTR()
- *  
+ *
  *  Interrupt handler for MAC interrupts
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        MAC structure
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -2066,27 +2035,27 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
        int handled = 0;
 
        for (;;) {
-               
+
                /*
                 * Read the ISR (this clears the bits in the real
                 * register, except for counter addr)
                 */
-               
-               isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
-               
+
+               isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
+
                if (isr == 0)
                        break;
 
                handled = 1;
-               
+
                /*
                 * Transmits on channel 0
                 */
-               
+
                if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
                        sbdma_tx_process(sc,&(sc->sbm_txdma));
                }
-               
+
                /*
                 * Receives on channel 0
                 */
@@ -2106,8 +2075,8 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
                 * EOP_SEEN here takes care of this case.
                 * (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
                 */
-                
-               
+
+
                if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
                        sbdma_rx_process(sc,&(sc->sbm_rxdma));
                }
@@ -2118,29 +2087,29 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
 
 /**********************************************************************
  *  SBMAC_START_TX(skb,dev)
- *  
- *  Start output on the specified interface.  Basically, we 
+ *
+ *  Start output on the specified interface.  Basically, we
  *  queue as many buffers as we can until the ring fills up, or
  *  we run off the end of the queue, whichever comes first.
- *  
- *  Input parameters: 
- *        
- *        
+ *
+ *  Input parameters:
+ *
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
 static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct sbmac_softc *sc = netdev_priv(dev);
-       
+
        /* lock eth irq */
        spin_lock_irq (&sc->sbm_lock);
-       
+
        /*
-        * Put the buffer on the transmit ring.  If we 
+        * Put the buffer on the transmit ring.  If we
         * don't have room, stop the queue.
         */
-       
+
        if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
                /* XXX save skb that we could not send */
                netif_stop_queue(dev);
@@ -2148,24 +2117,24 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
 
                return 1;
        }
-       
+
        dev->trans_start = jiffies;
-       
+
        spin_unlock_irq (&sc->sbm_lock);
-       
+
        return 0;
 }
 
 /**********************************************************************
  *  SBMAC_SETMULTI(sc)
- *  
+ *
  *  Reprogram the multicast table into the hardware, given
  *  the list of multicasts associated with the interface
  *  structure.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        sc - softc
- *        
+ *
  *  Return value:
  *        nothing
  ********************************************************************* */
@@ -2173,75 +2142,75 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
 static void sbmac_setmulti(struct sbmac_softc *sc)
 {
        uint64_t reg;
-       sbmac_port_t port;
+       volatile void __iomem *port;
        int idx;
        struct dev_mc_list *mclist;
        struct net_device *dev = sc->sbm_dev;
-       
-       /* 
+
+       /*
         * Clear out entire multicast table.  We do this by nuking
         * the entire hash table and all the direct matches except
-        * the first one, which is used for our station address 
+        * the first one, which is used for our station address
         */
-       
+
        for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
                port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
-               SBMAC_WRITECSR(port,0); 
+               __raw_writeq(0, port);
        }
-       
+
        for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
                port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
-               SBMAC_WRITECSR(port,0); 
+               __raw_writeq(0, port);
        }
-       
+
        /*
         * Clear the filter to say we don't want any multicasts.
         */
-       
-       reg = SBMAC_READCSR(sc->sbm_rxfilter);
+
+       reg = __raw_readq(sc->sbm_rxfilter);
        reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
-       SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-       
+       __raw_writeq(reg, sc->sbm_rxfilter);
+
        if (dev->flags & IFF_ALLMULTI) {
-               /* 
-                * Enable ALL multicasts.  Do this by inverting the 
-                * multicast enable bit. 
+               /*
+                * Enable ALL multicasts.  Do this by inverting the
+                * multicast enable bit.
                 */
-               reg = SBMAC_READCSR(sc->sbm_rxfilter);
+               reg = __raw_readq(sc->sbm_rxfilter);
                reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
-               SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+               __raw_writeq(reg, sc->sbm_rxfilter);
                return;
        }
-       
 
-       /* 
+
+       /*
         * Progam new multicast entries.  For now, only use the
         * perfect filter.  In the future we'll need to use the
         * hash filter if the perfect filter overflows
         */
-       
+
        /* XXX only using perfect filter for now, need to use hash
         * XXX if the table overflows */
-       
+
        idx = 1;                /* skip station address */
        mclist = dev->mc_list;
        while (mclist && (idx < MAC_ADDR_COUNT)) {
                reg = sbmac_addr2reg(mclist->dmi_addr);
                port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
-               SBMAC_WRITECSR(port,reg);
+               __raw_writeq(reg, port);
                idx++;
                mclist = mclist->next;
        }
-       
-       /*      
+
+       /*
         * Enable the "accept multicast bits" if we programmed at least one
-        * multicast. 
+        * multicast.
         */
-       
+
        if (idx > 1) {
-               reg = SBMAC_READCSR(sc->sbm_rxfilter);
+               reg = __raw_readq(sc->sbm_rxfilter);
                reg |= M_MAC_MCAST_EN;
-               SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+               __raw_writeq(reg, sc->sbm_rxfilter);
        }
 }
 
@@ -2250,12 +2219,12 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
 #if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
 /**********************************************************************
  *  SBMAC_PARSE_XDIGIT(str)
- *  
+ *
  *  Parse a hex digit, returning its value
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        str - character
- *        
+ *
  *  Return value:
  *        hex value, or -1 if invalid
  ********************************************************************* */
@@ -2263,7 +2232,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
 static int sbmac_parse_xdigit(char str)
 {
        int digit;
-       
+
        if ((str >= '0') && (str <= '9'))
                digit = str - '0';
        else if ((str >= 'a') && (str <= 'f'))
@@ -2272,20 +2241,20 @@ static int sbmac_parse_xdigit(char str)
                digit = str - 'A' + 10;
        else
                return -1;
-       
+
        return digit;
 }
 
 /**********************************************************************
  *  SBMAC_PARSE_HWADDR(str,hwaddr)
- *  
+ *
  *  Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
  *  Ethernet address.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        str - string
  *        hwaddr - pointer to hardware address
- *        
+ *
  *  Return value:
  *        0 if ok, else -1
  ********************************************************************* */
@@ -2294,7 +2263,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
 {
        int digit1,digit2;
        int idx = 6;
-       
+
        while (*str && (idx > 0)) {
                digit1 = sbmac_parse_xdigit(*str);
                if (digit1 < 0)
@@ -2302,7 +2271,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
                str++;
                if (!*str)
                        return -1;
-               
+
                if ((*str == ':') || (*str == '-')) {
                        digit2 = digit1;
                        digit1 = 0;
@@ -2313,10 +2282,10 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
                                return -1;
                        str++;
                }
-               
+
                *hwaddr++ = (digit1 << 4) | digit2;
                idx--;
-               
+
                if (*str == '-')
                        str++;
                if (*str == ':')
@@ -2337,12 +2306,12 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
 
 /**********************************************************************
  *  SBMAC_INIT(dev)
- *  
+ *
  *  Attach routine - init hardware and hook ourselves into linux
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *        dev - net_device structure
- *        
+ *
  *  Return value:
  *        status
  ********************************************************************* */
@@ -2354,53 +2323,53 @@ static int sbmac_init(struct net_device *dev, int idx)
        uint64_t ea_reg;
        int i;
        int err;
-       
+
        sc = netdev_priv(dev);
-       
+
        /* Determine controller base address */
-       
+
        sc->sbm_base = IOADDR(dev->base_addr);
        sc->sbm_dev = dev;
        sc->sbe_idx = idx;
-       
+
        eaddr = sc->sbm_hwaddr;
-       
-       /* 
+
+       /*
         * Read the ethernet address.  The firwmare left this programmed
         * for us in the ethernet address register for each mac.
         */
-       
-       ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
-       SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
+
+       ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+       __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
        for (i = 0; i < 6; i++) {
                eaddr[i] = (uint8_t) (ea_reg & 0xFF);
                ea_reg >>= 8;
        }
-       
+
        for (i = 0; i < 6; i++) {
                dev->dev_addr[i] = eaddr[i];
        }
-       
-       
+
+
        /*
-        * Init packet size 
+        * Init packet size
         */
-       
+
        sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
 
-       /* 
+       /*
         * Initialize context (get pointers to registers and stuff), then
         * allocate the memory for the descriptor tables.
         */
-       
+
        sbmac_initctx(sc);
-       
+
        /*
         * Set up Linux device callins
         */
-       
+
        spin_lock_init(&(sc->sbm_lock));
-       
+
        dev->open               = sbmac_open;
        dev->hard_start_xmit    = sbmac_start_tx;
        dev->stop               = sbmac_close;
@@ -2419,7 +2388,7 @@ static int sbmac_init(struct net_device *dev, int idx)
        if (err)
                goto out_uninit;
 
-       if (periph_rev >= 2) {
+       if (sc->rx_hw_checksum == ENABLE) {
                printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
                        sc->sbm_dev->name);
        }
@@ -2430,10 +2399,10 @@ static int sbmac_init(struct net_device *dev, int idx)
         * was being displayed)
         */
        printk(KERN_INFO
-              "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
+              "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
               dev->name, dev->base_addr,
               eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
-       
+
 
        return 0;
 
@@ -2447,51 +2416,51 @@ out_uninit:
 static int sbmac_open(struct net_device *dev)
 {
        struct sbmac_softc *sc = netdev_priv(dev);
-       
+
        if (debug > 1) {
                printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
        }
-       
-       /* 
+
+       /*
         * map/route interrupt (clear status first, in case something
         * weird is pending; we haven't initialized the mac registers
         * yet)
         */
 
-       SBMAC_READCSR(sc->sbm_isr);
+       __raw_readq(sc->sbm_isr);
        if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
                return -EBUSY;
 
        /*
-        * Configure default speed 
+        * Configure default speed
         */
 
        sbmac_mii_poll(sc,noisy_mii);
-       
+
        /*
         * Turn on the channel
         */
 
        sbmac_set_channel_state(sc,sbmac_state_on);
-       
+
        /*
         * XXX Station address is in dev->dev_addr
         */
-       
+
        if (dev->if_port == 0)
-               dev->if_port = 0; 
-       
+               dev->if_port = 0;
+
        netif_start_queue(dev);
-       
+
        sbmac_set_rx_mode(dev);
-       
+
        /* Set the timer to check for link beat. */
        init_timer(&sc->sbm_timer);
        sc->sbm_timer.expires = jiffies + 2 * HZ/100;
        sc->sbm_timer.data = (unsigned long)dev;
        sc->sbm_timer.function = &sbmac_timer;
        add_timer(&sc->sbm_timer);
-       
+
        return 0;
 }
 
@@ -2609,20 +2578,20 @@ static void sbmac_timer(unsigned long data)
        int mii_status;
 
        spin_lock_irq (&sc->sbm_lock);
-       
+
        /* make IFF_RUNNING follow the MII status bit "Link established" */
        mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
-       
+
        if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
                sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
                if (mii_status & BMSR_LINKSTAT) {
                        netif_carrier_on(dev);
                }
                else {
-                       netif_carrier_off(dev); 
+                       netif_carrier_off(dev);
                }
        }
-       
+
        /*
         * Poll the PHY to see what speed we should be running at
         */
@@ -2640,9 +2609,9 @@ static void sbmac_timer(unsigned long data)
                        sbmac_channel_start(sc);
                }
        }
-       
+
        spin_unlock_irq (&sc->sbm_lock);
-       
+
        sc->sbm_timer.expires = jiffies + next_tick;
        add_timer(&sc->sbm_timer);
 }
@@ -2651,13 +2620,13 @@ static void sbmac_timer(unsigned long data)
 static void sbmac_tx_timeout (struct net_device *dev)
 {
        struct sbmac_softc *sc = netdev_priv(dev);
-       
+
        spin_lock_irq (&sc->sbm_lock);
-       
-       
+
+
        dev->trans_start = jiffies;
        sc->sbm_stats.tx_errors++;
-       
+
        spin_unlock_irq (&sc->sbm_lock);
 
        printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
@@ -2670,13 +2639,13 @@ static struct net_device_stats *sbmac_get_stats(struct net_device *dev)
 {
        struct sbmac_softc *sc = netdev_priv(dev);
        unsigned long flags;
-       
+
        spin_lock_irqsave(&sc->sbm_lock, flags);
-       
+
        /* XXX update other stats here */
-       
+
        spin_unlock_irqrestore(&sc->sbm_lock, flags);
-       
+
        return &sc->sbm_stats;
 }
 
@@ -2693,8 +2662,8 @@ static void sbmac_set_rx_mode(struct net_device *dev)
                /*
                 * Promiscuous changed.
                 */
-               
-               if (dev->flags & IFF_PROMISC) { 
+
+               if (dev->flags & IFF_PROMISC) {
                        /* Unconditionally log net taps. */
                        msg_flag = 1;
                        sbmac_promiscuous_mode(sc,1);
@@ -2705,18 +2674,18 @@ static void sbmac_set_rx_mode(struct net_device *dev)
                }
        }
        spin_unlock_irqrestore(&sc->sbm_lock, flags);
-       
+
        if (msg_flag) {
                printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
                       dev->name,(msg_flag==1)?"en":"dis");
        }
-       
+
        /*
         * Program the multicasts.  Do this every time.
         */
-       
+
        sbmac_setmulti(sc);
-       
+
 }
 
 static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2725,10 +2694,10 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        u16 *data = (u16 *)&rq->ifr_ifru;
        unsigned long flags;
        int retval;
-       
+
        spin_lock_irqsave(&sc->sbm_lock, flags);
        retval = 0;
-       
+
        switch(cmd) {
        case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
                data[0] = sc->sbm_phys[0] & 0x1f;
@@ -2750,7 +2719,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        default:
                retval = -EOPNOTSUPP;
        }
-       
+
        spin_unlock_irqrestore(&sc->sbm_lock, flags);
        return retval;
 }
@@ -2781,7 +2750,7 @@ static int sbmac_close(struct net_device *dev)
 
        sbdma_emptyring(&(sc->sbm_txdma));
        sbdma_emptyring(&(sc->sbm_rxdma));
-       
+
        return 0;
 }
 
@@ -2793,13 +2762,13 @@ sbmac_setup_hwaddr(int chan,char *addr)
 {
        uint8_t eaddr[6];
        uint64_t val;
-       sbmac_port_t port;
+       unsigned long port;
 
        port = A_MAC_CHANNEL_BASE(chan);
        sbmac_parse_hwaddr(addr,eaddr);
        val = sbmac_addr2reg(eaddr);
-       SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val);
-       val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+       __raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
+       val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
 }
 #endif
 
@@ -2810,9 +2779,9 @@ sbmac_init_module(void)
 {
        int idx;
        struct net_device *dev;
-       sbmac_port_t port;
+       unsigned long port;
        int chip_max_units;
-       
+
        /*
         * For bringup when not using the firmware, we can pre-fill
         * the MAC addresses using the environment variables
@@ -2858,13 +2827,13 @@ sbmac_init_module(void)
 
                port = A_MAC_CHANNEL_BASE(idx);
 
-               /*      
+               /*
                 * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
                 * value for us by the firmware if we're going to use this MAC.
                 * If we find a zero, skip this MAC.
                 */
 
-               sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+               sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
                if (sbmac_orig_hwaddr[idx] == 0) {
                        printk(KERN_DEBUG "sbmac: not configuring MAC at "
                               "%lx\n", port);
@@ -2876,7 +2845,7 @@ sbmac_init_module(void)
                 */
 
                dev = alloc_etherdev(sizeof(struct sbmac_softc));
-               if (!dev) 
+               if (!dev)
                        return -ENOMEM; /* return ENOMEM */
 
                printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
@@ -2886,8 +2855,7 @@ sbmac_init_module(void)
                dev->mem_end = 0;
                if (sbmac_init(dev, idx)) {
                        port = A_MAC_CHANNEL_BASE(idx);
-                       SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
-                                      sbmac_orig_hwaddr[idx]);
+                       __raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
                        free_netdev(dev);
                        continue;
                }
index 9bc3b1c0dd6a27e280650b5ff99d382baf5adc6f..a4614df38a903a53207507485eeec9a5486f50ae 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "sgiseeq.h"
 
-static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
-
 static char *sgiseeqstr = "SGI Seeq8003";
 
 /*
@@ -113,9 +111,9 @@ static struct net_device *root_sgiseeq_dev;
 
 static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
 {
-       hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
+       hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
        udelay(20);
-       hregs->rx_reset = 0;
+       hregs->reset = 0;
 }
 
 static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
@@ -252,7 +250,6 @@ void sgiseeq_dump_rings(void)
 
 #define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
 #define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
-#define RDMACFG_INIT    (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
 
 static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
                     struct sgiseeq_regs *sregs)
@@ -274,8 +271,6 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
                sregs->tstat = TSTAT_INIT_SEEQ;
        }
 
-       hregs->rx_dconfig |= RDMACFG_INIT;
-
        hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
        hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
 
@@ -446,7 +441,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
        spin_lock(&sp->tx_lock);
 
        /* Ack the IRQ and set software state. */
-       hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
+       hregs->reset = HPC3_ERST_CLRIRQ;
 
        /* Always check for received packets. */
        sgiseeq_rx(dev, sp, hregs, sregs);
@@ -493,11 +488,13 @@ static int sgiseeq_close(struct net_device *dev)
 {
        struct sgiseeq_private *sp = netdev_priv(dev);
        struct sgiseeq_regs *sregs = sp->sregs;
+       unsigned int irq = dev->irq;
 
        netif_stop_queue(dev);
 
        /* Shutdown the Seeq. */
        reset_hpc3_and_seeq(sp->hregs, sregs);
+       free_irq(irq, dev);
 
        return 0;
 }
@@ -644,7 +641,7 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
 
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-static int sgiseeq_init(struct hpc3_regs* regs, int irq)
+static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
 {
        struct sgiseeq_init_block *sr;
        struct sgiseeq_private *sp;
@@ -680,8 +677,8 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
        gpriv = sp;
        gdev = dev;
 #endif
-       sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
-       sp->hregs = &hpc3c0->ethregs;
+       sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
+       sp->hregs = &hpcregs->ethregs;
        sp->name = sgiseeqstr;
        sp->mode = SEEQ_RCMD_RBCAST;
 
@@ -698,6 +695,11 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
        setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
        setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
 
+       /* Setup PIO and DMA transfer timing */
+       sp->hregs->pconfig = 0x161;
+       sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
+                            HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
+
        /* Reset the chip. */
        hpc3_eth_reset(sp->hregs);
 
@@ -724,7 +726,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
                goto err_out_free_page;
        }
 
-       printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
+       printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
        for (i = 0; i < 6; i++)
                printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 
@@ -734,7 +736,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
        return 0;
 
 err_out_free_page:
-       free_page((unsigned long) sp);
+       free_page((unsigned long) sp->srings);
 err_out_free_dev:
        kfree(dev);
 
@@ -744,8 +746,6 @@ err_out:
 
 static int __init sgiseeq_probe(void)
 {
-       printk(version);
-
        /* On board adapter on 1st HPC is always present */
        return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
 }
@@ -754,15 +754,12 @@ static void __exit sgiseeq_exit(void)
 {
        struct net_device *next, *dev;
        struct sgiseeq_private *sp;
-       int irq;
 
        for (dev = root_sgiseeq_dev; dev; dev = next) {
                sp = (struct sgiseeq_private *) netdev_priv(dev);
                next = sp->next_module;
-               irq = dev->irq;
                unregister_netdev(dev);
-               free_irq(irq, dev);
-               free_page((unsigned long) sp);
+               free_page((unsigned long) sp->srings);
                free_netdev(dev);
        }
 }
@@ -770,4 +767,6 @@ static void __exit sgiseeq_exit(void)
 module_init(sgiseeq_probe);
 module_exit(sgiseeq_exit);
 
+MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
 MODULE_LICENSE("GPL");
index c2e6484ef138f6e0c8d7548fd340a61028c85c81..572f121b1f4edaf29533eba3d3c0bd7c7a4e959b 100644 (file)
@@ -730,6 +730,7 @@ static struct ethtool_ops skge_ethtool_ops = {
        .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,
 };
 
 /*
@@ -3096,6 +3097,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        /* 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 d500a5771dbc5c05f5f03428b71f58e21b96530f..5de0554fd7c67e7503d75d150bed0dc73348c553 100644 (file)
@@ -518,6 +518,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
 #else
        int bar = 1;
 #endif
+       int phy, phy_idx = 0;
 
 
 /* when built into the kernel, we only print version if device is found */
@@ -549,6 +550,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        for (i = 0; i < 3; i++)
                ((u16 *)dev->dev_addr)[i] =
                        le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        dev->base_addr = (unsigned long)ioaddr;
        dev->irq = irq;
@@ -605,33 +607,31 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
                        printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
-       if (1) {
-               int phy, phy_idx = 0;
-               np->phys[0] = 1;                /* Default setting */
-               np->mii_preamble_required++;
-               for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-                       int mii_status = mdio_read(dev, phy, MII_BMSR);
-                       if (mii_status != 0xffff  &&  mii_status != 0x0000) {
-                               np->phys[phy_idx++] = phy;
-                               np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
-                               if ((mii_status & 0x0040) == 0)
-                                       np->mii_preamble_required++;
-                               printk(KERN_INFO "%s: MII PHY found at address %d, status "
-                                          "0x%4.4x advertising %4.4x.\n",
-                                          dev->name, phy, mii_status, np->mii_if.advertising);
-                       }
-               }
-               np->mii_preamble_required--;
-
-               if (phy_idx == 0) {
-                       printk(KERN_INFO "%s: No MII transceiver found, aborting.  ASIC status %x\n",
-                                  dev->name, ioread32(ioaddr + ASICCtrl));
-                       goto err_out_unregister;
+       np->phys[0] = 1;                /* Default setting */
+       np->mii_preamble_required++;
+       for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
+               int mii_status = mdio_read(dev, phy, MII_BMSR);
+               int phyx = phy & 0x1f;
+               if (mii_status != 0xffff  &&  mii_status != 0x0000) {
+                       np->phys[phy_idx++] = phyx;
+                       np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
+                       if ((mii_status & 0x0040) == 0)
+                               np->mii_preamble_required++;
+                       printk(KERN_INFO "%s: MII PHY found at address %d, status "
+                                  "0x%4.4x advertising %4.4x.\n",
+                                  dev->name, phyx, mii_status, np->mii_if.advertising);
                }
+       }
+       np->mii_preamble_required--;
 
-               np->mii_if.phy_id = np->phys[0];
+       if (phy_idx == 0) {
+               printk(KERN_INFO "%s: No MII transceiver found, aborting.  ASIC status %x\n",
+                          dev->name, ioread32(ioaddr + ASICCtrl));
+               goto err_out_unregister;
        }
 
+       np->mii_if.phy_id = np->phys[0];
+
        /* Parse override configuration */
        np->an_enable = 1;
        if (card_idx < MAX_UNITS) {
@@ -692,7 +692,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        /* Reset the chip to erase previous misconfiguration. */
        if (netif_msg_hw(np))
                printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
-       iowrite16(0x007f, ioaddr + ASICCtrl + 2);
+       iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
        if (netif_msg_hw(np))
                printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
 
@@ -1619,6 +1619,7 @@ static struct ethtool_ops ethtool_ops = {
        .get_link = get_link,
        .get_msglevel = get_msglevel,
        .set_msglevel = set_msglevel,
+       .get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
index 32057e65808bdafe5a9ed826800eb1f7e1ff747e..9f491563944e917efc754b3d9c59645cefbc24a6 100644 (file)
@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct net_device *dev)
        if (dev->base_addr) {
                outb(0,dev->base_addr+ADAPTRESET);
                
-               schedule_timeout(TR_RST_TIME); /* wait 50ms */
+               schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
 
                outb(0,dev->base_addr+ADAPTRESETREL);
        }
@@ -854,8 +854,7 @@ static int tok_init_card(struct net_device *dev)
        writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
        outb(0, PIOaddr + ADAPTRESET);
 
-       current->state=TASK_UNINTERRUPTIBLE;
-       schedule_timeout(TR_RST_TIME); /* wait 50ms */
+       schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
 
        outb(0, PIOaddr + ADAPTRESETREL);
 #ifdef ENABLE_PAGING
@@ -903,8 +902,8 @@ static int tok_open(struct net_device *dev)
                        DPRINTK("Adapter is up and running\n");
                        return 0;
                }
-               current->state=TASK_INTERRUPTIBLE;
-               i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
+               i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
+                                                       /* wait 30 seconds */
                if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
        }
        outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
index 9e7923192a49f0f01e6f7ffef375da1351938203..05477d24fd49c5359d9989062ad2bd4688d228c1 100644 (file)
@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_device *dev)
 
        while(olympic_priv->srb_queued) {
 
-               t = schedule_timeout(60*HZ); 
+               t = schedule_timeout_interruptible(60*HZ);
 
                if(signal_pending(current))     {            
                        printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
index 2e39bf1f74620f88cf5d03fce1a71ac0f1e107fb..c1925590a0e110e431a0434901349f47d27f1384 100644 (file)
@@ -1243,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
        
        tmp = jiffies + time/(1000000/HZ);
        do {
-               current->state          = TASK_INTERRUPTIBLE;
-               tmp = schedule_timeout(tmp);
+               tmp = schedule_timeout_interruptible(tmp);
        } while(time_after(tmp, jiffies));
 #else
        udelay(time);
index a22d00198e4d6b5cde5b46ebff6cb1e569e6f68e..6b8eee8f7bfd1ddc611498812a59ac7eb8f1976b 100644 (file)
@@ -1787,10 +1787,15 @@ static void __init de21041_get_srom_info (struct de_private *de)
        /* DEC now has a specification but early board makers
           just put the address in the first EEPROM locations. */
        /* This does  memcmp(eedata, eedata+16, 8) */
+
+#ifndef CONFIG_MIPS_COBALT
+
        for (i = 0; i < 8; i ++)
                if (ee_data[i] != ee_data[16+i])
                        sa_offset = 20;
 
+#endif
+
        /* store MAC address */
        for (i = 0; i < 6; i ++)
                de->dev->dev_addr[i] = ee_data[i + sa_offset];
index ecfa6f8805ce0ef050448e777e68364b7d50a32e..4c76cb794bfbb48ad0a5c4954cd85ee8324156ee 100644 (file)
@@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
                           TYPHOON_STATUS_WAITING_FOR_HOST)
                                goto out;
 
-                       if(wait_type == WaitSleep) {
-                               set_current_state(TASK_UNINTERRUPTIBLE);
-                               schedule_timeout(1);
-                       } else
+                       if(wait_type == WaitSleep)
+                               schedule_timeout_uninterruptible(1);
+                       else
                                udelay(TYPHOON_UDELAY);
                }
 
index fc7738ffbfffeb1ffd17c7724426169b65531372..2418715892833608e91147ffd169dde1a2f86566 100644 (file)
@@ -490,6 +490,8 @@ struct rhine_private {
        u8 tx_thresh, rx_thresh;
 
        struct mii_if_info mii_if;
+       struct work_struct tx_timeout_task;
+       struct work_struct check_media_task;
        void __iomem *base;
 };
 
@@ -497,6 +499,8 @@ static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
 static void rhine_tx_timeout(struct net_device *dev);
+static void rhine_tx_timeout_task(struct net_device *dev);
+static void rhine_check_media_task(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static void rhine_tx(struct net_device *dev);
@@ -814,8 +818,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-       if (!is_valid_ether_addr(dev->dev_addr)) {
+       if (!is_valid_ether_addr(dev->perm_addr)) {
                rc = -EIO;
                printk(KERN_ERR "Invalid MAC address\n");
                goto err_out_unmap;
@@ -850,6 +855,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
+       INIT_WORK(&rp->tx_timeout_task,
+                 (void (*)(void *))rhine_tx_timeout_task, dev);
+
+       INIT_WORK(&rp->check_media_task,
+                 (void (*)(void *))rhine_check_media_task, dev);
+
        /* dev->name not defined before register_netdev()! */
        rc = register_netdev(dev);
        if (rc)
@@ -1076,6 +1087,11 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
                   ioaddr + ChipCmd1);
 }
 
+static void rhine_check_media_task(struct net_device *dev)
+{
+       rhine_check_media(dev, 0);
+}
+
 static void init_registers(struct net_device *dev)
 {
        struct rhine_private *rp = netdev_priv(dev);
@@ -1129,8 +1145,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
        if (quirks & rqRhineI) {
                iowrite8(0x01, ioaddr + MIIRegAddr);    // MII_BMSR
 
-               /* Can be called from ISR. Evil. */
-               mdelay(1);
+               /* Do not call from ISR! */
+               msleep(1);
 
                /* 0x80 must be set immediately before turning it off */
                iowrite8(0x80, ioaddr + MIICmd);
@@ -1218,6 +1234,16 @@ static int rhine_open(struct net_device *dev)
 }
 
 static void rhine_tx_timeout(struct net_device *dev)
+{
+       struct rhine_private *rp = netdev_priv(dev);
+
+       /*
+        * Move bulk of work outside of interrupt context
+        */
+       schedule_work(&rp->tx_timeout_task);
+}
+
+static void rhine_tx_timeout_task(struct net_device *dev)
 {
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
@@ -1625,7 +1651,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
        spin_lock(&rp->lock);
 
        if (intr_status & IntrLinkChange)
-               rhine_check_media(dev, 0);
+               schedule_work(&rp->check_media_task);
        if (intr_status & IntrStatsMax) {
                rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
                rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1829,6 +1855,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
        .set_wol                = rhine_set_wol,
        .get_sg                 = ethtool_op_get_sg,
        .get_tx_csum            = ethtool_op_get_tx_csum,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1872,6 +1899,9 @@ static int rhine_close(struct net_device *dev)
        spin_unlock_irq(&rp->lock);
 
        free_irq(rp->pdev->irq, dev);
+
+       flush_scheduled_work();
+
        free_rbufs(dev);
        free_tbufs(dev);
        free_ring(dev);
index 7ff814fd65d0826596261f76448911b4579efe2e..ae9e897c255ec04576d1c58b28fde673bdc4be55 100644 (file)
@@ -1617,8 +1617,7 @@ static int get_wait_data(struct cosa_data *cosa)
                        return r;
                }
                /* sleep if not ready to read */
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
        }
        printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
                cosa_getstatus(cosa));
@@ -1644,8 +1643,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
                }
 #if 0
                /* sleep if not ready to read */
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
 #endif
        }
        printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
index 9e56fc346ba4f72b53e0031167803165bf0dde1d..e6d005726aadea2875fca2e747cee73aaa9225db 100644 (file)
@@ -109,7 +109,7 @@ static long cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };
  *             < 0     error.
  * Context:    process */
 
-int __init cycx_drv_init(void)
+static int __init cycx_drv_init(void)
 {
        printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
                         copyright);
@@ -119,7 +119,7 @@ int __init cycx_drv_init(void)
 
 /* Module 'remove' entry point.
  * o release all remaining system resources */
-void cycx_drv_cleanup(void)
+static void cycx_drv_cleanup(void)
 {
 }
 
@@ -184,8 +184,7 @@ int cycx_down(struct cycx_hw *hw)
 }
 
 /* Enable interrupt generation.  */
-EXPORT_SYMBOL(cycx_inten);
-void cycx_inten(struct cycx_hw *hw)
+static void cycx_inten(struct cycx_hw *hw)
 {
        writeb(0, hw->dpmbase);
 }
index 7b48064364dc7896440ab70b6d61d498789a57ce..430b1f630fb4a71147992411b3ad0eb71e997ad6 100644 (file)
@@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_array; /* adapter data space */
  *             < 0     error.
  * Context:    process
  */
-int __init cycx_init(void)
+static int __init cycx_init(void)
 {
        int cnt, err = -ENOMEM;
 
index 02d57c0b4243ac8ab61e4db9a3eb3e6e90d66d82..a631d1c2fa148a7191ac775baab2f2c4a82fe12b 100644 (file)
@@ -78,6 +78,7 @@
 
 #define CYCLOMX_X25_DEBUG 1
 
+#include <linux/ctype.h>       /* isdigit() */
 #include <linux/errno.h>       /* return codes */
 #include <linux/if_arp.h>       /* ARPHRD_HWX25 */
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
@@ -418,7 +419,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
 
                /* Set channel timeouts (default if not specified) */
                chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
-       } else if (is_digit(conf->addr[0])) {   /* PVC */
+       } else if (isdigit(conf->addr[0])) {    /* PVC */
                s16 lcn = dec_to_uint(conf->addr, 0);
 
                if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
@@ -1531,7 +1532,7 @@ static unsigned dec_to_uint(u8 *str, int len)
        if (!len)
                len = strlen(str);
 
-       for (; len && is_digit(*str); ++str, --len)
+       for (; len && isdigit(*str); ++str, --len)
                val = (val * 10) + (*str - (unsigned) '0');
 
        return val;
index 520a77a798e25482ee52852fa97d17edfc7e2191..2f61a47b4716947d331dca4a5e2ee2d311c05d15 100644 (file)
@@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv,
        return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
 }
 
-int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
-               const char *msg)
+static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
+                      struct net_device *dev, const char *msg)
 {
        int ret = 0;
 
@@ -466,8 +466,9 @@ int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
        return ret;
 }
 
-void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
-                   char *msg)
+static void dscc4_tx_print(struct net_device *dev,
+                          struct dscc4_dev_priv *dpriv,
+                          char *msg)
 {
        printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
               dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
@@ -507,7 +508,8 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv)
        }
 }
 
-inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
+                                struct net_device *dev)
 {
        unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
        struct RxFD *rx_fd = dpriv->rx_fd + dirty;
@@ -542,8 +544,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
                               msg, i);
                        goto done;
                }
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(10);
+               schedule_timeout_uninterruptible(10);
                rmb();
        } while (++i > 0);
        printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
@@ -588,8 +589,7 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
                    (dpriv->iqtx[cur] & Xpr))
                        break;
                smp_rmb();
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(10);
+               schedule_timeout_uninterruptible(10);
        } while (++i > 0);
 
        return (i >= 0 ) ? i : -EAGAIN;
@@ -1035,8 +1035,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
        /* Flush posted writes */
        readl(ioaddr + GSTAR);
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(10);
+       schedule_timeout_uninterruptible(10);
 
        for (i = 0; i < 16; i++)
                pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
@@ -1894,7 +1893,7 @@ try:
  * It failed and locked solid. Thus the introduction of a dummy skb.
  * Problem is acknowledged in errata sheet DS5. Joy :o/
  */
-struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
 {
        struct sk_buff *skb;
 
index 2c83cca34b8698cc269a0feda4def2b5a5d00c9d..7981a2c7906e0522aa3a34c4cd9ba7f6c84637fc 100644 (file)
@@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
 /*
  * Modules parameters and associated varaibles
  */
-int fst_txq_low = FST_LOW_WATER_MARK;
-int fst_txq_high = FST_HIGH_WATER_MARK;
-int fst_max_reads = 7;
-int fst_excluded_cards = 0;
-int fst_excluded_list[FST_MAX_CARDS];
+static int fst_txq_low = FST_LOW_WATER_MARK;
+static int fst_txq_high = FST_HIGH_WATER_MARK;
+static int fst_max_reads = 7;
+static int fst_excluded_cards = 0;
+static int fst_excluded_list[FST_MAX_CARDS];
 
 module_param(fst_txq_low, int, 0);
 module_param(fst_txq_high, int, 0);
@@ -572,13 +572,13 @@ static void do_bottom_half_rx(struct fst_card_info *card);
 static void fst_process_tx_work_q(unsigned long work_q);
 static void fst_process_int_work_q(unsigned long work_q);
 
-DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
 
-struct fst_card_info *fst_card_array[FST_MAX_CARDS];
-spinlock_t fst_work_q_lock;
-u64 fst_work_txq;
-u64 fst_work_intq;
+static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+static spinlock_t fst_work_q_lock;
+static u64 fst_work_txq;
+static u64 fst_work_intq;
 
 static void
 fst_q_work_item(u64 * queue, int card_index)
@@ -980,8 +980,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
        /* Wait for any previous command to complete */
        while (mbval > NAK) {
                spin_unlock_irqrestore(&card->card_lock, flags);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
                spin_lock_irqsave(&card->card_lock, flags);
 
                if (++safety > 2000) {
@@ -1498,7 +1497,7 @@ do_bottom_half_rx(struct fst_card_info *card)
  *      The interrupt service routine
  *      Dev_id is our fst_card_info pointer
  */
-irqreturn_t
+static irqreturn_t
 fst_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct fst_card_info *card;
index a5d6891c9d4c3959fcb895d8dc1a2500a8eb6200..e1601d35dceddf133379a57155ca9472294b2eac 100644 (file)
@@ -330,7 +330,7 @@ static int pvc_close(struct net_device *dev)
 
 
 
-int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        pvc_device *pvc = dev_to_pvc(dev);
        fr_proto_pvc_info info;
index 9dccd9546a17b829b0816866d627d9d25c7bd0c5..3b94352b0d03178b31cdf5d364beaffd062c0390 100644 (file)
@@ -8,10 +8,10 @@
 /*
  * Prints out len, max to 80 octets using printk, 20 per line
  */
-void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
-{
 #ifdef DEBUG
 #ifdef LMC_PACKET_LOG
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
   int iNewLine = 1;
   char str[80], *pstr;
   
@@ -43,26 +43,24 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
     }
   sprintf(pstr, "\n");
   printk(str);
+}
 #endif
 #endif
-}
 
 #ifdef DEBUG
 u_int32_t lmcEventLogIndex = 0;
 u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#endif
 
 void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
 {
-#ifdef DEBUG
   lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
   lmcEventLogBuf[lmcEventLogIndex++] = arg2;
   lmcEventLogBuf[lmcEventLogIndex++] = arg3;
   lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
 
   lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
-#endif
 }
+#endif  /*  DEBUG  */
 
 void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
index f55ce76b00edd4545fe826f6844b338acd1cc46d..af8b55fdd9d98008bfe040b895ae734bfafb088b 100644 (file)
   * of the GNU General Public License version 2, incorporated herein by reference.
   */
 
-/*
- * For lack of a better place, put the SSI cable stuff here.
- */
-char *lmc_t1_cables[] = {
-  "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
-  "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
-};
-
 /*
  * protocol independent method.
  */
index 73401b0f01517ca8bb533acdfae0b05d6a175a70..2024b26b99e6e2728945af0c553455cb1bdaef9a 100644 (file)
@@ -472,24 +472,8 @@ enum pc300_loopback_cmds {
 
 #ifdef __KERNEL__
 /* Function Prototypes */
-int dma_buf_write(pc300_t *, int, ucchar *, int);
-int dma_buf_read(pc300_t *, int, struct sk_buff *);
 void tx_dma_start(pc300_t *, int);
-void rx_dma_start(pc300_t *, int);
-void tx_dma_stop(pc300_t *, int);
-void rx_dma_stop(pc300_t *, int);
-int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(struct net_device *);
-void cpc_sca_status(pc300_t *, int);
-int cpc_change_mtu(struct net_device *, int);
-int cpc_ioctl(struct net_device *, struct ifreq *, int);
-int ch_config(pc300dev_t *);
-int rx_config(pc300dev_t *);
-int tx_config(pc300dev_t *);
-void cpc_opench(pc300dev_t *);
-void cpc_closech(pc300dev_t *);
 int cpc_open(struct net_device *dev);
-int cpc_close(struct net_device *dev);
 int cpc_set_media(hdlc_device *, int);
 #endif /* __KERNEL__ */
 
index 3e7753b1071759f147851c69ed38e0317d13f994..a3e65d1bc19bbcddda71bd74f2ec707a6a0bf5f1 100644 (file)
@@ -291,6 +291,7 @@ static uclong detect_ram(pc300_t *);
 static void plx_init(pc300_t *);
 static void cpc_trace(struct net_device *, struct sk_buff *, char);
 static int cpc_attach(struct net_device *, unsigned short, unsigned short);
+static int cpc_close(struct net_device *dev);
 
 #ifdef CONFIG_PC300_MLPPP
 void cpc_tty_init(pc300dev_t * dev);
@@ -437,7 +438,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
        printk("\n");
 }
 
-int dma_get_rx_frame_size(pc300_t * card, int ch)
+static int dma_get_rx_frame_size(pc300_t * card, int ch)
 {
        volatile pcsca_bd_t __iomem *ptdescr;
        ucshort first_bd = card->chan[ch].rx_first_bd;
@@ -462,7 +463,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
  * dma_buf_write: writes a frame to the Tx DMA buffers
  * NOTE: this function writes one frame at a time.
  */
-int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
+static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 {
        int i, nchar;
        volatile pcsca_bd_t __iomem *ptdescr;
@@ -503,7 +504,7 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
  * dma_buf_read: reads a frame from the Rx DMA buffers
  * NOTE: this function reads one frame at a time.
  */
-int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 {
        int nchar;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -560,7 +561,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
        return (rcvd);
 }
 
-void tx_dma_stop(pc300_t * card, int ch)
+static void tx_dma_stop(pc300_t * card, int ch)
 {
        void __iomem *scabase = card->hw.scabase;
        ucchar drr_ena_bit = 1 << (5 + 2 * ch);
@@ -571,7 +572,7 @@ void tx_dma_stop(pc300_t * card, int ch)
        cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
 }
 
-void rx_dma_stop(pc300_t * card, int ch)
+static void rx_dma_stop(pc300_t * card, int ch)
 {
        void __iomem *scabase = card->hw.scabase;
        ucchar drr_ena_bit = 1 << (4 + 2 * ch);
@@ -582,7 +583,7 @@ void rx_dma_stop(pc300_t * card, int ch)
        cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
 }
 
-void rx_dma_start(pc300_t * card, int ch)
+static void rx_dma_start(pc300_t * card, int ch)
 {
        void __iomem *scabase = card->hw.scabase;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -607,7 +608,7 @@ void rx_dma_start(pc300_t * card, int ch)
 /*************************/
 /***   FALC Routines   ***/
 /*************************/
-void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
+static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
 {
        void __iomem *falcbase = card->hw.falcbase;
        unsigned long i = 0;
@@ -622,7 +623,7 @@ void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
        cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
 }
 
-void falc_intr_enable(pc300_t * card, int ch)
+static void falc_intr_enable(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -672,7 +673,7 @@ void falc_intr_enable(pc300_t * card, int ch)
        }
 }
 
-void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 {
        void __iomem *falcbase = card->hw.falcbase;
        ucchar tshf = card->chan[ch].falc.offset;
@@ -688,7 +689,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
                        (0x80 >> (timeslot & 0x07)));
 }
 
-void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
 {
        void __iomem *falcbase = card->hw.falcbase;
        ucchar tshf = card->chan[ch].falc.offset;
@@ -704,7 +705,7 @@ void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
                   ~(0x80 >> (timeslot & 0x07)));
 }
 
-void falc_close_all_timeslots(pc300_t * card, int ch)
+static void falc_close_all_timeslots(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -726,7 +727,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
        }
 }
 
-void falc_open_all_timeslots(pc300_t * card, int ch)
+static void falc_open_all_timeslots(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -758,7 +759,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
        }
 }
 
-void falc_init_timeslot(pc300_t * card, int ch)
+static void falc_init_timeslot(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -776,7 +777,7 @@ void falc_init_timeslot(pc300_t * card, int ch)
        }
 }
 
-void falc_enable_comm(pc300_t * card, int ch)
+static void falc_enable_comm(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
@@ -792,7 +793,7 @@ void falc_enable_comm(pc300_t * card, int ch)
                   ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
 }
 
-void falc_disable_comm(pc300_t * card, int ch)
+static void falc_disable_comm(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
@@ -806,7 +807,7 @@ void falc_disable_comm(pc300_t * card, int ch)
                   ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
 }
 
-void falc_init_t1(pc300_t * card, int ch)
+static void falc_init_t1(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -975,7 +976,7 @@ void falc_init_t1(pc300_t * card, int ch)
        falc_close_all_timeslots(card, ch);
 }
 
-void falc_init_e1(pc300_t * card, int ch)
+static void falc_init_e1(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1155,7 +1156,7 @@ void falc_init_e1(pc300_t * card, int ch)
        falc_close_all_timeslots(card, ch);
 }
 
-void falc_init_hdlc(pc300_t * card, int ch)
+static void falc_init_hdlc(pc300_t * card, int ch)
 {
        void __iomem *falcbase = card->hw.falcbase;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -1181,7 +1182,7 @@ void falc_init_hdlc(pc300_t * card, int ch)
        falc_intr_enable(card, ch);
 }
 
-void te_config(pc300_t * card, int ch)
+static void te_config(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1241,7 +1242,7 @@ void te_config(pc300_t * card, int ch)
        CPC_UNLOCK(card, flags);
 }
 
-void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1397,7 +1398,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
        }
 }
 
-void falc_update_stats(pc300_t * card, int ch)
+static void falc_update_stats(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1450,7 +1451,7 @@ void falc_update_stats(pc300_t * card, int ch)
  *             the synchronizer and then sent to the system interface.
  *----------------------------------------------------------------------------
  */
-void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1495,7 +1496,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
  *             coding must be identical.
  *----------------------------------------------------------------------------
  */
-void falc_local_loop(pc300_t * card, int ch, int loop_on)
+static void falc_local_loop(pc300_t * card, int ch, int loop_on)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1522,7 +1523,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
  *             looped. They are originated by the FALC-LH transmitter.
  *----------------------------------------------------------------------------
  */
-void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1576,7 +1577,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
  * Description:        Turns XLU bit off in the proper register
  *----------------------------------------------------------------------------
  */
-void turn_off_xlu(pc300_t * card, int ch)
+static void turn_off_xlu(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1597,7 +1598,7 @@ void turn_off_xlu(pc300_t * card, int ch)
  * Description: Turns XLD bit off in the proper register
  *----------------------------------------------------------------------------
  */
-void turn_off_xld(pc300_t * card, int ch)
+static void turn_off_xld(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1619,7 +1620,7 @@ void turn_off_xld(pc300_t * card, int ch)
  *             to generate a LOOP activation code over a T1/E1 line.
  *----------------------------------------------------------------------------
  */
-void falc_generate_loop_up_code(pc300_t * card, int ch)
+static void falc_generate_loop_up_code(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1652,7 +1653,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
  *             to generate a LOOP deactivation code over a T1/E1 line.
  *----------------------------------------------------------------------------
  */
-void falc_generate_loop_down_code(pc300_t * card, int ch)
+static void falc_generate_loop_down_code(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1682,7 +1683,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
  *             it on the reception side.
  *----------------------------------------------------------------------------
  */
-void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1729,7 +1730,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
  * Description:        This routine returns the bit error counter value
  *----------------------------------------------------------------------------
  */
-ucshort falc_pattern_test_error(pc300_t * card, int ch)
+static ucshort falc_pattern_test_error(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1769,7 +1770,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
        netif_rx(skb);
 }
 
-void cpc_tx_timeout(struct net_device *dev)
+static void cpc_tx_timeout(struct net_device *dev)
 {
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1797,7 +1798,7 @@ void cpc_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
-int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1880,7 +1881,7 @@ int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-void cpc_net_rx(struct net_device *dev)
+static void cpc_net_rx(struct net_device *dev)
 {
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -2403,7 +2404,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-void cpc_sca_status(pc300_t * card, int ch)
+static void cpc_sca_status(pc300_t * card, int ch)
 {
        ucchar ilar;
        void __iomem *scabase = card->hw.scabase;
@@ -2495,7 +2496,7 @@ void cpc_sca_status(pc300_t * card, int ch)
        }
 }
 
-void cpc_falc_status(pc300_t * card, int ch)
+static void cpc_falc_status(pc300_t * card, int ch)
 {
        pc300ch_t *chan = &card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
@@ -2523,7 +2524,7 @@ void cpc_falc_status(pc300_t * card, int ch)
        CPC_UNLOCK(card, flags);
 }
 
-int cpc_change_mtu(struct net_device *dev, int new_mtu)
+static int cpc_change_mtu(struct net_device *dev, int new_mtu)
 {
        if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
                return -EINVAL;
@@ -2531,7 +2532,7 @@ int cpc_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
@@ -2856,7 +2857,7 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
        }
 }
 
-int ch_config(pc300dev_t * d)
+static int ch_config(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -3004,7 +3005,7 @@ int ch_config(pc300dev_t * d)
        return 0;
 }
 
-int rx_config(pc300dev_t * d)
+static int rx_config(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3035,7 +3036,7 @@ int rx_config(pc300dev_t * d)
        return 0;
 }
 
-int tx_config(pc300dev_t * d)
+static int tx_config(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3098,7 +3099,7 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding,
        return 0;
 }
 
-void cpc_opench(pc300dev_t * d)
+static void cpc_opench(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3116,7 +3117,7 @@ void cpc_opench(pc300dev_t * d)
                   cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
 }
 
-void cpc_closech(pc300dev_t * d)
+static void cpc_closech(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3173,7 +3174,7 @@ int cpc_open(struct net_device *dev)
        return 0;
 }
 
-int cpc_close(struct net_device *dev)
+static int cpc_close(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
index 8454bf6caaa70136f6106869a30a8f61899c0002..52f26b9c69d245e9aa090e374964f04d5895f7b0 100644 (file)
@@ -112,10 +112,10 @@ typedef   struct _st_cpc_tty_area {
 static struct tty_driver serial_drv;
 
 /* local variables */
-st_cpc_tty_area        cpc_tty_area[CPC_TTY_NPORTS];
+static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
 
-int cpc_tty_cnt=0;     /* number of intrfaces configured with MLPPP */
-int cpc_tty_unreg_flag = 0;
+static int cpc_tty_cnt = 0;    /* number of intrfaces configured with MLPPP */
+static int cpc_tty_unreg_flag = 0;
 
 /* TTY functions prototype */
 static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
@@ -132,9 +132,9 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
 static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
 static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
 
-int pc300_tiocmset(struct tty_struct *, struct file *,
-                       unsigned int, unsigned int);
-int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, struct file *,
+                         unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *, struct file *);
 
 /* functions called by PC300 driver */
 void cpc_tty_init(pc300dev_t *dev);
@@ -538,8 +538,8 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
        return(0); 
 } 
 
-int pc300_tiocmset(struct tty_struct *tty, struct file *file,
-                       unsigned int set, unsigned int clear)
+static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+                         unsigned int set, unsigned int clear)
 {
        st_cpc_tty_area    *cpc_tty; 
 
@@ -565,7 +565,7 @@ int pc300_tiocmset(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
-int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
 {
        unsigned int result;
        unsigned char status;
index 3ac9a45b20fae7da4de35a3a4ae8055f90ee2501..036adc4f8ba7e85dab072fb7595cbe8f57e1e8d5 100644 (file)
@@ -182,7 +182,7 @@ static char sdla_byte(struct net_device *dev, int addr)
        return(byte);
 }
 
-void sdla_stop(struct net_device *dev)
+static void sdla_stop(struct net_device *dev)
 {
        struct frad_local *flp;
 
@@ -209,7 +209,7 @@ void sdla_stop(struct net_device *dev)
        }
 }
 
-void sdla_start(struct net_device *dev)
+static void sdla_start(struct net_device *dev)
 {
        struct frad_local *flp;
 
@@ -247,7 +247,7 @@ void sdla_start(struct net_device *dev)
  *
  ***************************************************/
 
-int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
 {
        unsigned long start, done, now;
        char          resp, *temp;
@@ -505,7 +505,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
 
 static int sdla_reconfig(struct net_device *dev);
 
-int sdla_activate(struct net_device *slave, struct net_device *master)
+static int sdla_activate(struct net_device *slave, struct net_device *master)
 {
        struct frad_local *flp;
        int i;
@@ -527,7 +527,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
        return(0);
 }
 
-int sdla_deactivate(struct net_device *slave, struct net_device *master)
+static int sdla_deactivate(struct net_device *slave, struct net_device *master)
 {
        struct frad_local *flp;
        int               i;
@@ -549,7 +549,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
        return(0);
 }
 
-int sdla_assoc(struct net_device *slave, struct net_device *master)
+static int sdla_assoc(struct net_device *slave, struct net_device *master)
 {
        struct frad_local *flp;
        int               i;
@@ -585,7 +585,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
        return(0);
 }
 
-int sdla_deassoc(struct net_device *slave, struct net_device *master)
+static int sdla_deassoc(struct net_device *slave, struct net_device *master)
 {
        struct frad_local *flp;
        int               i;
@@ -613,7 +613,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
        return(0);
 }
 
-int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
+static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
 {
        struct frad_local *flp;
        struct dlci_local *dlp;
@@ -1324,7 +1324,7 @@ NOTE:  This is rather a useless action right now, as the
        return(0);
 }
 
-int sdla_change_mtu(struct net_device *dev, int new_mtu)
+static int sdla_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct frad_local *flp;
 
@@ -1337,7 +1337,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
        return(-EOPNOTSUPP);
 }
 
-int sdla_set_config(struct net_device *dev, struct ifmap *map)
+static int sdla_set_config(struct net_device *dev, struct ifmap *map)
 {
        struct frad_local *flp;
        int               i;
index 0497dbdb8631fe379c7f952dc2c50ee7c21bd814..7f1ce9d4333e8fc440b957b532f96ca0318ed4d8 100644 (file)
@@ -822,7 +822,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
        chan->card = card;
 
        /* verify media address */
-       if (is_digit(conf->addr[0])) {
+       if (isdigit(conf->addr[0])) {
 
                dlci = dec_to_uint(conf->addr, 0);
 
@@ -3456,7 +3456,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
        if (!len) 
                len = strlen(str);
 
-       for (val = 0; len && is_digit(*str); ++str, --len)
+       for (val = 0; len && isdigit(*str); ++str, --len)
                val = (val * 10) + (*str - (unsigned)'0');
 
        return val;
index 8a95d61a2f8ff0fa3b980990c13f2f32be00dd25..63f846d6f3a6dd87592db1ac4fd09e0a67a22f83 100644 (file)
@@ -957,7 +957,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
                chan->hold_timeout = (conf->hold_timeout) ? 
                                        conf->hold_timeout : 10;
 
-       }else if (is_digit(conf->addr[0])){     /* PVC */
+       }else if (isdigit(conf->addr[0])){      /* PVC */
                int lcn = dec_to_uint(conf->addr, 0);
 
                if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
@@ -3875,7 +3875,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
        if (!len) 
                len = strlen(str);
 
-       for (val = 0; len && is_digit(*str); ++str, --len)
+       for (val = 0; len && isdigit(*str); ++str, --len)
                val = (val * 10) + (*str - (unsigned)'0');
        
        return val;
@@ -3896,9 +3896,9 @@ static unsigned int hex_to_uint (unsigned char* str, int len)
        for (val = 0; len; ++str, --len)
        {
                ch = *str;
-               if (is_digit(ch))
+               if (isdigit(ch))
                        val = (val << 4) + (ch - (unsigned)'0');
-               else if (is_hex_digit(ch))
+               else if (isxdigit(ch))
                        val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
                else break;
        }
index c8bc6da57a418b2b62fb18c9ccfa3c06dcea362c..7c2cf2e76300c4f7fce69777653da0742bfdb8d7 100644 (file)
@@ -642,9 +642,7 @@ int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
  * Enable interrupt generation.
  */
 
-EXPORT_SYMBOL(sdla_inten);
-
-int sdla_inten (sdlahw_t* hw)
+static int sdla_inten (sdlahw_t* hw)
 {
        unsigned port = hw->port;
        int tmp, i;
@@ -698,8 +696,7 @@ int sdla_inten (sdlahw_t* hw)
  * Disable interrupt generation.
  */
 
-EXPORT_SYMBOL(sdla_intde);
-
+#if 0
 int sdla_intde (sdlahw_t* hw)
 {
        unsigned port = hw->port;
@@ -748,14 +745,13 @@ int sdla_intde (sdlahw_t* hw)
        }
        return 0;
 }
+#endif  /*  0  */
 
 /*============================================================================
  * Acknowledge SDLA hardware interrupt.
  */
 
-EXPORT_SYMBOL(sdla_intack);
-
-int sdla_intack (sdlahw_t* hw)
+static int sdla_intack (sdlahw_t* hw)
 {
        unsigned port = hw->port;
        int tmp;
@@ -827,8 +823,7 @@ void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
  * Generate an interrupt to adapter's CPU.
  */
 
-EXPORT_SYMBOL(sdla_intr);
-
+#if 0
 int sdla_intr (sdlahw_t* hw)
 {
        unsigned port = hw->port;
@@ -863,6 +858,7 @@ int sdla_intr (sdlahw_t* hw)
        }
        return 0;
 }
+#endif  /*  0  */
 
 /*============================================================================
  * Execute Adapter Command.
index a6d3b55013a5106b379bd5bddf47b4e89f1ad3f4..2d1bba06a08512d5d0a5af5bb8283ee9f9493922 100644 (file)
@@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sppp *p)
  *     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,8 +355,6 @@ done:
        return;
 }
 
-EXPORT_SYMBOL(sppp_input);
-
 /*
  *     Handle transmit packets.
  */
@@ -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;
@@ -998,8 +996,6 @@ int sppp_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-EXPORT_SYMBOL(sppp_change_mtu);
-
 /**
  *     sppp_do_ioctl - Ioctl handler for ppp/hdlc
  *     @dev: Device subject to ioctl
@@ -1456,7 +1452,7 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t
        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 06998c2240d9f167096426a582ec588bebbce7fc..cb429e783749ab2e02f14af9e4cdcdae63c1e6b6 100644 (file)
@@ -1046,7 +1046,6 @@ static WifiCtlHdr wifictlhdr8023 = {
        }
 };
 
-#ifdef WIRELESS_EXT
 // Frequency list (map channels to frequencies)
 static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
                                2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1067,7 +1066,6 @@ typedef struct wep_key_t {
 
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def     airo_handler_def;
-#endif /* WIRELESS_EXT */
 
 static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
 
@@ -1110,10 +1108,8 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
 static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
 static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
 #ifdef CISCO_EXT
 static int readrids(struct net_device *dev, aironet_ioctl *comp);
 static int writerids(struct net_device *dev, aironet_ioctl *comp);
@@ -1187,12 +1183,10 @@ struct airo_info {
                int fid;
        } xmit, xmit11;
        struct net_device *wifidev;
-#ifdef WIRELESS_EXT
        struct iw_statistics    wstats;         // wireless stats
        unsigned long           scan_timestamp; /* Time started to scan */
        struct iw_spy_data      spy_data;
        struct iw_public_data   wireless_data;
-#endif /* WIRELESS_EXT */
 #ifdef MICSUPPORT
        /* MIC stuff */
        struct crypto_tfm       *tfm;
@@ -2527,7 +2521,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        unsigned long mem_start, mem_len, aux_start, aux_len;
        int rc = -1;
        int i;
-       unsigned char *busaddroff,*vpackoff;
+       dma_addr_t busaddroff;
+       unsigned char *vpackoff;
        unsigned char __iomem *pciaddroff;
 
        mem_start = pci_resource_start(pci, 1);
@@ -2570,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        /*
         * Setup descriptor RX, TX, CONFIG
         */
-       busaddroff = (unsigned char *)ai->shared_dma;
+       busaddroff = ai->shared_dma;
        pciaddroff = ai->pciaux + AUX_OFFSET;
        vpackoff   = ai->shared;
 
@@ -2579,7 +2574,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
                ai->rxfids[i].pending = 0;
                ai->rxfids[i].card_ram_off = pciaddroff;
                ai->rxfids[i].virtual_host_addr = vpackoff;
-               ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+               ai->rxfids[i].rx_desc.host_addr = busaddroff;
                ai->rxfids[i].rx_desc.valid = 1;
                ai->rxfids[i].rx_desc.len = PKTSIZE;
                ai->rxfids[i].rx_desc.rdy = 0;
@@ -2594,7 +2589,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
                ai->txfids[i].card_ram_off = pciaddroff;
                ai->txfids[i].virtual_host_addr = vpackoff;
                ai->txfids[i].tx_desc.valid = 1;
-               ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+               ai->txfids[i].tx_desc.host_addr = busaddroff;
                memcpy(ai->txfids[i].virtual_host_addr,
                        &wifictlhdr8023, sizeof(wifictlhdr8023));
 
@@ -2607,8 +2602,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        /* Rid descriptor setup */
        ai->config_desc.card_ram_off = pciaddroff;
        ai->config_desc.virtual_host_addr = vpackoff;
-       ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
-       ai->ridbus = (dma_addr_t)busaddroff;
+       ai->config_desc.rid_desc.host_addr = busaddroff;
+       ai->ridbus = busaddroff;
        ai->config_desc.rid_desc.rid = 0;
        ai->config_desc.rid_desc.len = RIDSIZE;
        ai->config_desc.rid_desc.valid = 1;
@@ -2647,9 +2642,7 @@ static void wifi_setup(struct net_device *dev)
        dev->get_stats = &airo_get_stats;
        dev->set_mac_address = &airo_set_mac_address;
        dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
        dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
        dev->change_mtu = &airo_change_mtu;
        dev->open = &airo_open;
        dev->stop = &airo_close;
@@ -2675,9 +2668,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
        dev->priv = ethdev->priv;
        dev->irq = ethdev->irq;
        dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
        dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
        memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
        err = register_netdev(dev);
        if (err<0) {
@@ -2755,11 +2746,9 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        dev->set_multicast_list = &airo_set_multicast_list;
        dev->set_mac_address = &airo_set_mac_address;
        dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
        dev->wireless_handlers = &airo_handler_def;
        ai->wireless_data.spy_data = &ai->spy_data;
        dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
        dev->change_mtu = &airo_change_mtu;
        dev->open = &airo_open;
        dev->stop = &airo_close;
@@ -5515,12 +5504,13 @@ static int airo_pci_resume(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct airo_info *ai = dev->priv;
        Resp rsp;
+       pci_power_t prev_state = pdev->current_state;
 
-       pci_set_power_state(pdev, 0);
+       pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
+       pci_enable_wake(pdev, PCI_D0, 0);
 
-       if (ai->power.event > 1) {
+       if (prev_state != PCI_D1) {
                reset_card(dev, 0);
                mpi_init_descriptors(ai);
                setup_card(ai, dev->dev_addr, 0);
@@ -5598,7 +5588,6 @@ static void __exit airo_cleanup_module( void )
        remove_proc_entry("aironet", proc_root_driver);
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Initial Wireless Extension code for Aironet driver by :
  *     Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
@@ -7107,8 +7096,6 @@ static const struct iw_handler_def        airo_handler_def =
        .get_wireless_stats = airo_get_wireless_stats,
 };
 
-#endif /* WIRELESS_EXT */
-
 /*
  * This defines the configuration part of the Wireless Extensions
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7187,7 +7174,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return rc;
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Get the Wireless stats out of the driver
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7260,7 +7246,6 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 
        return &local->wstats;
 }
-#endif /* WIRELESS_EXT */
 
 #ifdef CISCO_EXT
 /*
index 9d496703c4650dec63a23689bfc44e814436ec50..7b321f7cf358d05b3656dfce2e918daa373ce39b 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/current.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
+#include <linux/delay.h>
 #include <asm/pmac_feature.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
 
 #include "orinoco.h"
 
index 587869d86eeea1ea195137619db5ec316bd4f774..d57011028b7279ef576191c006fd392027c16802 100644 (file)
@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
 static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
 static void atmel_command_irq(struct atmel_private *priv);
 static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
                                   u16 frame_len, u8 rssi);
 static void atmel_management_timer(u_long a);
 static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
 static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
                                            u8 *body, int body_len);
 
 static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
 static int start_tx (struct sk_buff *skb, struct net_device *dev)
 {
        struct atmel_private *priv = netdev_priv(dev);
-       struct ieee80211_hdr header;
+       struct ieee80211_hdr_4addr header;
        unsigned long flags;
        u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
        u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
 }
 
 static void atmel_transmit_management_frame(struct atmel_private *priv, 
-                                           struct ieee80211_hdr *header,
+                                           struct ieee80211_hdr_4addr *header,
                                            u8 *body, int body_len)
 {
        u16 buff;
@@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
        tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
 }
        
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
                         u16 msdu_size, u16 rx_packet_loc, u32 crc)
 {
        /* fast path: unfragmented packet copy directly into skbuf */
@@ -990,7 +990,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
        return (crc ^ 0xffffffff) == netcrc;
 }
 
-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
                         u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
 {
        u8 mac4[6]; 
@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *heade
 static void rx_done_irq(struct atmel_private *priv)
 {
        int i;
-       struct ieee80211_hdr header;
+       struct ieee80211_hdr_4addr header;
        
        for (i = 0; 
             atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -2650,7 +2650,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
  
 static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
 {
-       struct ieee80211_hdr header;
+       struct ieee80211_hdr_4addr header;
        struct auth_body auth;
        
        header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); 
@@ -2688,7 +2688,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 {
        u8 *ssid_el_p;
        int bodysize;
-       struct ieee80211_hdr header;
+       struct ieee80211_hdr_4addr header;
        struct ass_req_format {
                u16 capability;
                u16 listen_interval; 
@@ -2738,7 +2738,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
        atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
 }
 
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
 {
        if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
                return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2788,7 +2788,7 @@ static int retrieve_bss(struct atmel_private *priv)
 }
 
 
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
                           u16 capability, u16 beacon_period, u8 channel, u8 rssi, 
                           u8 ssid_len, u8 *ssid, int is_beacon)
 {
@@ -3072,7 +3072,7 @@ static void atmel_smooth_qual(struct atmel_private *priv)
 }
 
 /* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
                      u16 frame_len, u8 rssi)
 {
        u16 subtype;
index 21c3d0d227e62e9572cdcf56ae3c6527688974fa..eba0d9d2b7c53015bc96c4f909e6e728faf2e52e 100644 (file)
  */
 
 #include <linux/config.h>
-
 #include <linux/module.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/net.h>
-#include <asm/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
 
 #include "hermes.h"
 
index 8c9e874c9118c494a74a42979e45c1c8f68030c0..ad28e32943608af5351fc805fb10e5aa3254ed27 100644 (file)
@@ -30,9 +30,8 @@
  * access to the hermes_t structure, and to the hardware
 */
 
-#include <linux/delay.h>
 #include <linux/if_ether.h>
-#include <asm/byteorder.h>
+#include <asm/io.h>
 
 /*
  * Limits and constants
 #define        HERMES_RXSTAT_WMP               (0x6000)        /* Wavelan-II Management Protocol frame */
 
 struct hermes_tx_descriptor {
-       u16 status;
-       u16 reserved1;
-       u16 reserved2;
-       u32 sw_support;
+       __le16 status;
+       __le16 reserved1;
+       __le16 reserved2;
+       __le32 sw_support;
        u8 retry_count;
        u8 tx_rate;
-       u16 tx_control; 
+       __le16 tx_control;      
 } __attribute__ ((packed));
 
 #define HERMES_TXSTAT_RETRYERR         (0x0001)
@@ -222,60 +221,60 @@ struct hermes_tx_descriptor {
 #define HERMES_INQ_SEC_STAT_AGERE      (0xF202)
 
 struct hermes_tallies_frame {
-       u16 TxUnicastFrames;
-       u16 TxMulticastFrames;
-       u16 TxFragments;
-       u16 TxUnicastOctets;
-       u16 TxMulticastOctets;
-       u16 TxDeferredTransmissions;
-       u16 TxSingleRetryFrames;
-       u16 TxMultipleRetryFrames;
-       u16 TxRetryLimitExceeded;
-       u16 TxDiscards;
-       u16 RxUnicastFrames;
-       u16 RxMulticastFrames;
-       u16 RxFragments;
-       u16 RxUnicastOctets;
-       u16 RxMulticastOctets;
-       u16 RxFCSErrors;
-       u16 RxDiscards_NoBuffer;
-       u16 TxDiscardsWrongSA;
-       u16 RxWEPUndecryptable;
-       u16 RxMsgInMsgFragments;
-       u16 RxMsgInBadMsgFragments;
+       __le16 TxUnicastFrames;
+       __le16 TxMulticastFrames;
+       __le16 TxFragments;
+       __le16 TxUnicastOctets;
+       __le16 TxMulticastOctets;
+       __le16 TxDeferredTransmissions;
+       __le16 TxSingleRetryFrames;
+       __le16 TxMultipleRetryFrames;
+       __le16 TxRetryLimitExceeded;
+       __le16 TxDiscards;
+       __le16 RxUnicastFrames;
+       __le16 RxMulticastFrames;
+       __le16 RxFragments;
+       __le16 RxUnicastOctets;
+       __le16 RxMulticastOctets;
+       __le16 RxFCSErrors;
+       __le16 RxDiscards_NoBuffer;
+       __le16 TxDiscardsWrongSA;
+       __le16 RxWEPUndecryptable;
+       __le16 RxMsgInMsgFragments;
+       __le16 RxMsgInBadMsgFragments;
        /* Those last are probably not available in very old firmwares */
-       u16 RxDiscards_WEPICVError;
-       u16 RxDiscards_WEPExcluded;
+       __le16 RxDiscards_WEPICVError;
+       __le16 RxDiscards_WEPExcluded;
 } __attribute__ ((packed));
 
 /* Grabbed from wlan-ng - Thanks Mark... - Jean II
  * This is the result of a scan inquiry command */
 /* Structure describing info about an Access Point */
 struct prism2_scan_apinfo {
-       u16 channel;            /* Channel where the AP sits */
-       u16 noise;              /* Noise level */
-       u16 level;              /* Signal level */
+       __le16 channel;         /* Channel where the AP sits */
+       __le16 noise;           /* Noise level */
+       __le16 level;           /* Signal level */
        u8 bssid[ETH_ALEN];     /* MAC address of the Access Point */
-       u16 beacon_interv;      /* Beacon interval */
-       u16 capabilities;       /* Capabilities */
-       u16 essid_len;          /* ESSID length */
+       __le16 beacon_interv;   /* Beacon interval */
+       __le16 capabilities;    /* Capabilities */
+       __le16 essid_len;       /* ESSID length */
        u8 essid[32];           /* ESSID of the network */
        u8 rates[10];           /* Bit rate supported */
-       u16 proberesp_rate;     /* Data rate of the response frame */
-       u16 atim;               /* ATIM window time, Kus (hostscan only) */
+       __le16 proberesp_rate;  /* Data rate of the response frame */
+       __le16 atim;            /* ATIM window time, Kus (hostscan only) */
 } __attribute__ ((packed));
 
 /* Same stuff for the Lucent/Agere card.
  * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
 struct agere_scan_apinfo {
-       u16 channel;            /* Channel where the AP sits */
-       u16 noise;              /* Noise level */
-       u16 level;              /* Signal level */
+       __le16 channel;         /* Channel where the AP sits */
+       __le16 noise;           /* Noise level */
+       __le16 level;           /* Signal level */
        u8 bssid[ETH_ALEN];     /* MAC address of the Access Point */
-       u16 beacon_interv;      /* Beacon interval */
-       u16 capabilities;       /* Capabilities */
+       __le16 beacon_interv;   /* Beacon interval */
+       __le16 capabilities;    /* Capabilities */
        /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
-       u16 essid_len;          /* ESSID length */
+       __le16 essid_len;       /* ESSID length */
        u8 essid[32];           /* ESSID of the network */
 } __attribute__ ((packed));
 
@@ -283,16 +282,16 @@ struct agere_scan_apinfo {
 struct symbol_scan_apinfo {
        u8 channel;             /* Channel where the AP sits */
        u8 unknown1;            /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
-       u16 noise;              /* Noise level */
-       u16 level;              /* Signal level */
+       __le16 noise;           /* Noise level */
+       __le16 level;           /* Signal level */
        u8 bssid[ETH_ALEN];     /* MAC address of the Access Point */
-       u16 beacon_interv;      /* Beacon interval */
-       u16 capabilities;       /* Capabilities */
+       __le16 beacon_interv;   /* Beacon interval */
+       __le16 capabilities;    /* Capabilities */
        /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
-       u16 essid_len;          /* ESSID length */
+       __le16 essid_len;       /* ESSID length */
        u8 essid[32];           /* ESSID of the network */
-       u16 rates[5];           /* Bit rate supported */
-       u16 basic_rates;        /* Basic rates bitmask */
+       __le16 rates[5];        /* Bit rate supported */
+       __le16 basic_rates;     /* Basic rates bitmask */
        u8 unknown2[6];         /* Always FF:FF:FF:FF:00:00 */
        u8 unknown3[8];         /* Always 0, appeared in f/w 3.91-68 */
 } __attribute__ ((packed));
@@ -312,7 +311,7 @@ union hermes_scan_info {
 #define HERMES_LINKSTATUS_ASSOC_FAILED    (0x0006)
   
 struct hermes_linkstatus {
-       u16 linkstatus;         /* Link status */
+       __le16 linkstatus;         /* Link status */
 } __attribute__ ((packed));
 
 struct hermes_response {
@@ -321,8 +320,8 @@ struct hermes_response {
 
 /* "ID" structure - used for ESSID and station nickname */
 struct hermes_idstring {
-       u16 len;
-       u16 val[16];
+       __le16 len;
+       __le16 val[16];
 } __attribute__ ((packed));
 
 struct hermes_multicast {
@@ -447,7 +446,7 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
 
 static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 {
-       u16 rec;
+       __le16 rec;
        int err;
 
        err = HERMES_READ_RECORD(hw, bap, rid, &rec);
@@ -457,7 +456,7 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 
 static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
 {
-       u16 rec = cpu_to_le16(word);
+       __le16 rec = cpu_to_le16(word);
        return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
 }
 
index e7f5821b49429c3e05470a0c377d0aca788a87de..6a96cd9f2685c7d8d962ba7f9ef5de47c4896d23 100644 (file)
@@ -716,9 +716,6 @@ static int prism2_close(struct net_device *dev)
                hostap_deauth_all_stas(dev, local->ap, 1);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-       if (local->func->dev_close && local->func->dev_close(local))
-               return 0;
-
        if (dev == local->dev) {
                local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
        }
@@ -766,9 +763,6 @@ static int prism2_open(struct net_device *dev)
            local->hw_downloading)
                return -ENODEV;
 
-       if (local->func->dev_open && local->func->dev_open(local))
-               return 1;
-
        if (!try_module_get(local->hw_module))
                return -ENODEV;
        local->num_dev_open++;
index b0501243b175f99090f2b7321cb15ba77be4b8bd..ffac50899454353b324d52a2593fbb281ab05d23 100644 (file)
@@ -6,10 +6,10 @@
 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
                          struct hostap_80211_rx_status *rx_stats)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
               "jiffies=%ld\n",
@@ -51,7 +51,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
        int hdrlen, phdrlen, head_need, tail_need;
        u16 fc;
        int prism_header, ret;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        iface = netdev_priv(dev);
        local = iface->local;
@@ -70,7 +70,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
                phdrlen = 0;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
@@ -215,7 +215,7 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *
-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
 {
        struct sk_buff *skb = NULL;
        u16 sc;
@@ -229,7 +229,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
        if (frag == 0) {
                /* Reserve enough space to fit maximum frame length */
                skb = dev_alloc_skb(local->dev->mtu +
-                                   sizeof(struct ieee80211_hdr) +
+                                   sizeof(struct ieee80211_hdr_4addr) +
                                    8 /* LLC */ +
                                    2 /* alignment */ +
                                    8 /* WEP */ + ETH_ALEN /* WDS */);
@@ -267,7 +267,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
 
 /* Called only as a tasklet (software IRQ) */
 static int prism2_frag_cache_invalidate(local_info_t *local,
-                                       struct ieee80211_hdr *hdr)
+                                       struct ieee80211_hdr_4addr *hdr)
 {
        u16 sc;
        unsigned int seq;
@@ -441,7 +441,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
                     u16 stype)
 {
        if (local->iw_mode == IW_MODE_MASTER) {
-               hostap_update_sta_ps(local, (struct ieee80211_hdr *)
+               hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
                                     skb->data);
        }
 
@@ -520,7 +520,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
 
 
 static inline int
-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
                    u16 fc, struct net_device **wds)
 {
        /* FIX: is this really supposed to accept WDS frames only in Master
@@ -579,13 +579,13 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
 {
        struct net_device *dev = local->dev;
        u16 fc, ethertype;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u8 *pos;
 
        if (skb->len < 24)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        /* check that the frame is unicast frame to us */
@@ -619,13 +619,13 @@ static inline int
 hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
                        struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
        if (local->tkip_countermeasures &&
@@ -658,13 +658,13 @@ static inline int
 hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
                             int keyidx, struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
        atomic_inc(&crypt->refcnt);
@@ -689,7 +689,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
 {
        struct hostap_interface *iface;
        local_info_t *local;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        size_t hdrlen;
        u16 fc, type, stype, sc;
        struct net_device *wds = NULL;
@@ -716,7 +716,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
        dev = local->ddev;
        iface = netdev_priv(dev);
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        stats = hostap_get_stats(dev);
 
        if (skb->len < 10)
@@ -737,7 +737,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
                struct iw_quality wstats;
                wstats.level = rx_stats->signal;
                wstats.noise = rx_stats->noise;
-               wstats.updated = 6;     /* No qual value */
+               wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
+                       | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
                /* Update spy records */
                wireless_spy_update(dev, hdr->addr2, &wstats);
        }
@@ -889,7 +890,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
        if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
            (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
                goto rx_dropped;
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        /* skb: hdr + (possibly fragmented) plaintext payload */
 
@@ -941,7 +942,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
                /* this was the last fragment and the frame will be
                 * delivered, so remove skb from fragment cache */
                skb = frag_skb;
-               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr = (struct ieee80211_hdr_4addr *) skb->data;
                prism2_frag_cache_invalidate(local, hdr);
        }
 
@@ -952,7 +953,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
            hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
                goto rx_dropped;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
                if (local->ieee_802_1x &&
                    hostap_is_eapol_frame(local, skb)) {
index 6358015f65260d8fc9921ab185d42e9e5aa82f2b..9d24f8a38ac525843772b41143db514a9f686ecc 100644 (file)
@@ -1,9 +1,9 @@
 void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
               name, skb->len, jiffies);
@@ -41,7 +41,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct hostap_interface *iface;
        local_info_t *local;
        int need_headroom, need_tailroom = 0;
-       struct ieee80211_hdr hdr;
+       struct ieee80211_hdr_4addr hdr;
        u16 fc, ethertype = 0;
        enum {
                WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
@@ -244,7 +244,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct hostap_interface *iface;
        local_info_t *local;
        struct hostap_skb_tx_data *meta;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
 
        iface = netdev_priv(dev);
@@ -266,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
        meta->iface = iface;
 
        if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
-               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr = (struct ieee80211_hdr_4addr *) skb->data;
                fc = le16_to_cpu(hdr->frame_ctl);
                if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
                    WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
@@ -289,7 +289,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
 {
        struct hostap_interface *iface;
        local_info_t *local;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
        int hdr_len, res;
 
@@ -303,7 +303,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
 
        if (local->tkip_countermeasures &&
            crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr = (struct ieee80211_hdr_4addr *) skb->data;
                if (net_ratelimit()) {
                        printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
                               "TX packet to " MACSTR "\n",
@@ -317,15 +317,15 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
        if (skb == NULL)
                return NULL;
 
-       if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
-            skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
-           pskb_expand_head(skb, crypt->ops->extra_prefix_len,
-                            crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
+       if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
+            skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
+           pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
+                            crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
                kfree_skb(skb);
                return NULL;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        hdr_len = hostap_80211_get_hdrlen(fc);
 
@@ -360,7 +360,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
        ap_tx_ret tx_ret;
        struct hostap_skb_tx_data *meta;
        int no_encrypt = 0;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        iface = netdev_priv(dev);
        local = iface->local;
@@ -403,7 +403,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tx_ret = hostap_handle_sta_tx(local, &tx);
        skb = tx.skb;
        meta = (struct hostap_skb_tx_data *) skb->cb;
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        switch (tx_ret) {
        case AP_TX_CONTINUE:
index 930cef8367f2a2ffa983bf9c10fa28a56ec6377d..9da94ab7f05f87e24eec2816ca5094e894906d01 100644 (file)
@@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
 {
        struct ap_data *ap = data;
        u16 fc;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        if (!ap->local->hostapd || !ap->local->apdev) {
                dev_kfree_skb(skb);
                return;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        /* Pass the TX callback frame to the hostapd; use 802.11 header version
@@ -623,7 +623,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
 {
        struct ap_data *ap = data;
        struct net_device *dev = ap->local->dev;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc, *pos, auth_alg, auth_transaction, status;
        struct sta_info *sta = NULL;
        char *txt = NULL;
@@ -633,7 +633,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
                return;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
            WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
@@ -692,7 +692,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
 {
        struct ap_data *ap = data;
        struct net_device *dev = ap->local->dev;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc, *pos, status;
        struct sta_info *sta = NULL;
        char *txt = NULL;
@@ -702,7 +702,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
                return;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
            (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
@@ -757,12 +757,12 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
 static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
 {
        struct ap_data *ap = data;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        struct sta_info *sta;
 
        if (skb->len < 24)
                goto fail;
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        if (ok) {
                spin_lock(&ap->sta_table_lock);
                sta = ap_get_sta(ap, hdr->addr1);
@@ -918,7 +918,7 @@ static void prism2_send_mgmt(struct net_device *dev,
 {
        struct hostap_interface *iface;
        local_info_t *local;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
        struct sk_buff *skb;
        struct hostap_skb_tx_data *meta;
@@ -944,7 +944,7 @@ static void prism2_send_mgmt(struct net_device *dev,
 
        fc = type_subtype;
        hdrlen = hostap_80211_get_hdrlen(fc);
-       hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
+       hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
        if (body)
                memcpy(skb_put(skb, body_len), body, body_len);
 
@@ -1256,14 +1256,14 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
        }
 
        skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
-                           ap->crypt->extra_prefix_len +
-                           ap->crypt->extra_postfix_len);
+                           ap->crypt->extra_mpdu_prefix_len +
+                           ap->crypt->extra_mpdu_postfix_len);
        if (skb == NULL) {
                kfree(tmpbuf);
                return NULL;
        }
 
-       skb_reserve(skb, ap->crypt->extra_prefix_len);
+       skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
        memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
               WLAN_AUTH_CHALLENGE_LEN);
        if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
@@ -1272,7 +1272,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
                return NULL;
        }
 
-       memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
+       memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
               WLAN_AUTH_CHALLENGE_LEN);
        dev_kfree_skb(skb);
 
@@ -1285,7 +1285,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
                          struct hostap_80211_rx_status *rx_stats)
 {
        struct net_device *dev = local->dev;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
        size_t hdrlen;
        struct ap_data *ap = local->ap;
        char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
@@ -1498,7 +1498,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
                         struct hostap_80211_rx_status *rx_stats, int reassoc)
 {
        struct net_device *dev = local->dev;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
        char body[12], *p, *lpos;
        int len, left;
        u16 *pos;
@@ -1705,7 +1705,7 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
                          struct hostap_80211_rx_status *rx_stats)
 {
        struct net_device *dev = local->dev;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
        char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
        int len;
        u16 reason_code, *pos;
@@ -1746,7 +1746,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
                            struct hostap_80211_rx_status *rx_stats)
 {
        struct net_device *dev = local->dev;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
        char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
        int len;
        u16 reason_code, *pos;
@@ -1784,7 +1784,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
 
 /* Called only as a scheduled task for pending AP frames. */
 static void ap_handle_data_nullfunc(local_info_t *local,
-                                   struct ieee80211_hdr *hdr)
+                                   struct ieee80211_hdr_4addr *hdr)
 {
        struct net_device *dev = local->dev;
 
@@ -1801,7 +1801,7 @@ static void ap_handle_data_nullfunc(local_info_t *local,
 
 /* Called only as a scheduled task for pending AP frames. */
 static void ap_handle_dropped_data(local_info_t *local,
-                                  struct ieee80211_hdr *hdr)
+                                  struct ieee80211_hdr_4addr *hdr)
 {
        struct net_device *dev = local->dev;
        struct sta_info *sta;
@@ -1860,7 +1860,7 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
 
 /* Called only as a scheduled task for pending AP frames. */
 static void handle_pspoll(local_info_t *local,
-                         struct ieee80211_hdr *hdr,
+                         struct ieee80211_hdr_4addr *hdr,
                          struct hostap_80211_rx_status *rx_stats)
 {
        struct net_device *dev = local->dev;
@@ -1979,7 +1979,7 @@ static void handle_wds_oper_queue(void *data)
 static void handle_beacon(local_info_t *local, struct sk_buff *skb,
                          struct hostap_80211_rx_status *rx_stats)
 {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
        char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
        int len, left;
        u16 *pos, beacon_int, capability;
@@ -2137,11 +2137,11 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
        struct net_device *dev = local->dev;
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
        u16 fc, type, stype;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        /* FIX: should give skb->len to handler functions and check that the
         * buffer is long enough */
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        type = WLAN_FC_GET_TYPE(fc);
        stype = WLAN_FC_GET_STYPE(fc);
@@ -2258,7 +2258,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
        struct hostap_interface *iface;
        local_info_t *local;
        u16 fc;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        iface = netdev_priv(dev);
        local = iface->local;
@@ -2268,7 +2268,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
 
        local->stats.rx_packets++;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
@@ -2289,7 +2289,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
 static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
 {
        struct sk_buff *skb;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        struct hostap_80211_rx_status rx_stats;
 
        if (skb_queue_empty(&sta->tx_buf))
@@ -2302,7 +2302,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
                return;
        }
 
-       hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
+       hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
 
        /* Generate a fake pspoll frame to start packet delivery */
        hdr->frame_ctl = __constant_cpu_to_le16(
@@ -2349,7 +2349,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
                qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
                qual[count].updated = sta->last_rx_updated;
 
-               sta->last_rx_updated = 0;
+               sta->last_rx_updated = IW_QUAL_DBM;
 
                count++;
                if (count >= buf_size)
@@ -2467,7 +2467,7 @@ static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
                }
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-               sta->last_rx_updated = 0;
+               sta->last_rx_updated = IW_QUAL_DBM;
 
                /* To be continued, we should make good use of IWEVCUSTOM */
        }
@@ -2685,7 +2685,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
        struct sta_info *sta = NULL;
        struct sk_buff *skb = tx->skb;
        int set_tim, ret;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        struct hostap_skb_tx_data *meta;
 
        meta = (struct hostap_skb_tx_data *) skb->cb;
@@ -2694,7 +2694,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
            meta->iface->type == HOSTAP_INTERFACE_STA)
                goto out;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        if (hdr->addr1[0] & 0x01) {
                /* broadcast/multicast frame - no AP related processing */
@@ -2821,10 +2821,10 @@ void hostap_handle_sta_release(void *ptr)
 void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
 {
        struct sta_info *sta;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        struct hostap_skb_tx_data *meta;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        meta = (struct hostap_skb_tx_data *) skb->cb;
 
        spin_lock(&local->ap->sta_table_lock);
@@ -2892,7 +2892,7 @@ static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
 
 /* Called only as a tasklet (software IRQ). Called for each RX frame to update
  * STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
 {
        struct sta_info *sta;
        u16 fc;
@@ -2925,12 +2925,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
        int ret;
        struct sta_info *sta;
        u16 fc, type, stype;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        if (local->ap == NULL)
                return AP_RX_CONTINUE;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        fc = le16_to_cpu(hdr->frame_ctl);
        type = WLAN_FC_GET_TYPE(fc);
@@ -3058,7 +3058,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
 
 /* Called only as a tasklet (software IRQ) */
 int hostap_handle_sta_crypto(local_info_t *local,
-                            struct ieee80211_hdr *hdr,
+                            struct ieee80211_hdr_4addr *hdr,
                             struct ieee80211_crypt_data **crypt,
                             void **sta_ptr)
 {
@@ -3160,7 +3160,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
 
 /* Called only as a tasklet (software IRQ) */
 int hostap_update_rx_stats(struct ap_data *ap,
-                          struct ieee80211_hdr *hdr,
+                          struct ieee80211_hdr_4addr *hdr,
                           struct hostap_80211_rx_status *rx_stats)
 {
        struct sta_info *sta;
@@ -3174,7 +3174,7 @@ int hostap_update_rx_stats(struct ap_data *ap,
                sta->last_rx_silence = rx_stats->noise;
                sta->last_rx_signal = rx_stats->signal;
                sta->last_rx_rate = rx_stats->rate;
-               sta->last_rx_updated = 7;
+               sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
                if (rx_stats->rate == 10)
                        sta->rx_count[0]++;
                else if (rx_stats->rate == 20)
index 816a52bcea8f7adc71078a1a0bca50a18b40f29d..6d00df69c2e3e9f57f28af33a8af725aebb8bae9 100644 (file)
@@ -233,7 +233,7 @@ struct hostap_tx_data {
 ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
 void hostap_handle_sta_release(void *ptr);
 void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
 typedef enum {
        AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
 } ap_rx_ret;
@@ -241,13 +241,13 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
                               struct sk_buff *skb,
                               struct hostap_80211_rx_status *rx_stats,
                               int wds);
-int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
                             struct ieee80211_crypt_data **crypt,
                             void **sta_ptr);
 int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
 int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
 int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
-int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
                           struct hostap_80211_rx_status *rx_stats);
 void hostap_update_rates(local_info_t *local);
 void hostap_add_wds_links(local_info_t *local);
index faa83badf0a1b5e5897566b2be057583ca4d26a9..2643976a66775f559936b4fd0ce84672d96342d2 100644 (file)
@@ -492,42 +492,10 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 }
 
 
-static int prism2_pccard_dev_open(local_info_t *local)
-{
-       struct hostap_cs_priv *hw_priv = local->hw_priv;
-       hw_priv->link->open++;
-       return 0;
-}
-
-
-static int prism2_pccard_dev_close(local_info_t *local)
-{
-       struct hostap_cs_priv *hw_priv;
-
-       if (local == NULL || local->hw_priv == NULL)
-               return 1;
-       hw_priv = local->hw_priv;
-       if (hw_priv->link == NULL)
-               return 1;
-
-       if (!hw_priv->link->open) {
-               printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
-                      "link not open?!\n", local->dev->name);
-               return 1;
-       }
-
-       hw_priv->link->open--;
-
-       return 0;
-}
-
-
 static struct prism2_helper_functions prism2_pccard_funcs =
 {
        .card_present   = prism2_pccard_card_present,
        .cor_sreset     = prism2_pccard_cor_sreset,
-       .dev_open       = prism2_pccard_dev_open,
-       .dev_close      = prism2_pccard_dev_close,
        .genesis_reset  = prism2_pccard_genesis_reset,
        .hw_type        = HOSTAP_HW_PCCARD,
 };
@@ -597,13 +565,14 @@ static void prism2_detach(dev_link_t *link)
        *linkp = link->next;
        /* release net devices */
        if (link->priv) {
+               struct hostap_cs_priv *hw_priv;
                struct net_device *dev;
                struct hostap_interface *iface;
                dev = link->priv;
                iface = netdev_priv(dev);
-               kfree(iface->local->hw_priv);
-               iface->local->hw_priv = NULL;
+               hw_priv = iface->local->hw_priv;
                prism2_free_local_data(dev);
+               kfree(hw_priv);
        }
        kfree(link);
 }
@@ -883,6 +852,13 @@ static int prism2_event(event_t event, int priority,
 {
        dev_link_t *link = args->client_data;
        struct net_device *dev = (struct net_device *) link->priv;
+       int dev_open = 0;
+
+       if (link->state & DEV_CONFIG) {
+               struct hostap_interface *iface = netdev_priv(dev);
+               if (iface && iface->local)
+                       dev_open = iface->local->num_dev_open > 0;
+       }
 
        switch (event) {
        case CS_EVENT_CARD_INSERTION:
@@ -911,7 +887,7 @@ static int prism2_event(event_t event, int priority,
        case CS_EVENT_RESET_PHYSICAL:
                PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
                if (link->state & DEV_CONFIG) {
-                       if (link->open) {
+                       if (dev_open) {
                                netif_stop_queue(dev);
                                netif_device_detach(dev);
                        }
@@ -931,8 +907,8 @@ static int prism2_event(event_t event, int priority,
                        pcmcia_request_configuration(link->handle,
                                                     &link->conf);
                        prism2_hw_shutdown(dev, 1);
-                       prism2_hw_config(dev, link->open ? 0 : 1);
-                       if (link->open) {
+                       prism2_hw_config(dev, dev_open ? 0 : 1);
+                       if (dev_open) {
                                netif_device_attach(dev);
                                netif_start_queue(dev);
                        }
index e533a663deda5ebc3fd00df476237d9dda5311ce..59fc15572395cc50a4e8f56b2643afd6800f43d1 100644 (file)
@@ -3322,6 +3322,18 @@ static void prism2_free_local_data(struct net_device *dev)
        iface = netdev_priv(dev);
        local = iface->local;
 
+       /* Unregister all netdevs before freeing local data. */
+       list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+               iface = list_entry(ptr, struct hostap_interface, list);
+               if (iface->type == HOSTAP_INTERFACE_MASTER) {
+                       /* special handling for this interface below */
+                       continue;
+               }
+               hostap_remove_interface(iface->dev, 0, 1);
+       }
+
+       unregister_netdev(local->dev);
+
        flush_scheduled_work();
 
        if (timer_pending(&local->crypt_deinit_timer))
@@ -3382,15 +3394,6 @@ static void prism2_free_local_data(struct net_device *dev)
        prism2_download_free_data(local->dl_sec);
 #endif /* PRISM2_DOWNLOAD_SUPPORT */
 
-       list_for_each_safe(ptr, n, &local->hostap_interfaces) {
-               iface = list_entry(ptr, struct hostap_interface, list);
-               if (iface->type == HOSTAP_INTERFACE_MASTER) {
-                       /* special handling for this interface below */
-                       continue;
-               }
-               hostap_remove_interface(iface->dev, 0, 1);
-       }
-
        prism2_clear_set_tim_queue(local);
 
        list_for_each_safe(ptr, n, &local->bss_list) {
@@ -3403,7 +3406,6 @@ static void prism2_free_local_data(struct net_device *dev)
        kfree(local->last_scan_results);
        kfree(local->generic_elem);
 
-       unregister_netdev(local->dev);
        free_netdev(local->dev);
 }
 
index e720369a3515595b1a35129b92be19f0a578325c..53f5246c40aa3bb7bc00eaf80e015a54a7718ec4 100644 (file)
@@ -50,7 +50,8 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
 #endif /* in_atomic */
 
                if (update && prism2_update_comms_qual(dev) == 0)
-                       wstats->qual.updated = 7;
+                       wstats->qual.updated = IW_QUAL_ALL_UPDATED |
+                               IW_QUAL_DBM;
 
                wstats->qual.qual = local->comms_qual;
                wstats->qual.level = local->avg_signal;
@@ -59,7 +60,7 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
                wstats->qual.qual = 0;
                wstats->qual.level = 0;
                wstats->qual.noise = 0;
-               wstats->qual.updated = 0;
+               wstats->qual.updated = IW_QUAL_ALL_INVALID;
        }
 
        return wstats;
@@ -1827,13 +1828,6 @@ static char * __prism2_translate_scan(local_info_t *local,
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
        memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
-       /* FIX:
-        * I do not know how this is possible, but iwe_stream_add_event
-        * seems to re-order memcpy execution so that len is set only
-        * after copying.. Pre-setting len here "fixes" this, but real
-        * problems should be solved (after which these iwe.len
-        * settings could be removed from this function). */
-       iwe.len = IW_EV_ADDR_LEN;
        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
                                          IW_EV_ADDR_LEN);
 
@@ -1843,7 +1837,6 @@ static char * __prism2_translate_scan(local_info_t *local,
        iwe.cmd = SIOCGIWESSID;
        iwe.u.data.length = ssid_len;
        iwe.u.data.flags = 1;
-       iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
        current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
 
        memset(&iwe, 0, sizeof(iwe));
@@ -1859,7 +1852,6 @@ static char * __prism2_translate_scan(local_info_t *local,
                        iwe.u.mode = IW_MODE_MASTER;
                else
                        iwe.u.mode = IW_MODE_ADHOC;
-               iwe.len = IW_EV_UINT_LEN;
                current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
                                                  IW_EV_UINT_LEN);
        }
@@ -1877,7 +1869,6 @@ static char * __prism2_translate_scan(local_info_t *local,
        if (chan > 0) {
                iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
                iwe.u.freq.e = 1;
-               iwe.len = IW_EV_FREQ_LEN;
                current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
                                                  IW_EV_FREQ_LEN);
        }
@@ -1894,7 +1885,10 @@ static char * __prism2_translate_scan(local_info_t *local,
                        iwe.u.qual.noise =
                                HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
                }
-               iwe.len = IW_EV_QUAL_LEN;
+               iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
+                       | IW_QUAL_NOISE_UPDATED
+                       | IW_QUAL_QUAL_INVALID
+                       | IW_QUAL_DBM;
                current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
                                                  IW_EV_QUAL_LEN);
        }
@@ -1906,7 +1900,6 @@ static char * __prism2_translate_scan(local_info_t *local,
        else
                iwe.u.data.flags = IW_ENCODE_DISABLED;
        iwe.u.data.length = 0;
-       iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
        current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
 
        /* TODO: add SuppRates into BSS table */
@@ -1930,7 +1923,7 @@ static char * __prism2_translate_scan(local_info_t *local,
        }
 
        /* TODO: add BeaconInt,resp_rate,atim into BSS table */
-       buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
+       buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
        if (buf && scan) {
                memset(&iwe, 0, sizeof(iwe));
                iwe.cmd = IWEVCUSTOM;
index 025f8cdb55663758d5329163084965c0403ed0db..da0c80fb941cab99dac9d2c93cf0105010f90abd 100644 (file)
@@ -59,11 +59,13 @@ static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
 static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
 {
        struct hostap_interface *iface;
+       struct hostap_pci_priv *hw_priv;
        local_info_t *local;
        unsigned long flags;
 
        iface = netdev_priv(dev);
        local = iface->local;
+       hw_priv = local->hw_priv;
 
        spin_lock_irqsave(&local->lock, flags);
        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
@@ -74,12 +76,14 @@ static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
 static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
 {
        struct hostap_interface *iface;
+       struct hostap_pci_priv *hw_priv;
        local_info_t *local;
        unsigned long flags;
        u8 v;
 
        iface = netdev_priv(dev);
        local = iface->local;
+       hw_priv = local->hw_priv;
 
        spin_lock_irqsave(&local->lock, flags);
        v = readb(hw_priv->mem_start + a);
@@ -91,11 +95,13 @@ static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
 static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
 {
        struct hostap_interface *iface;
+       struct hostap_pci_priv *hw_priv;
        local_info_t *local;
        unsigned long flags;
 
        iface = netdev_priv(dev);
        local = iface->local;
+       hw_priv = local->hw_priv;
 
        spin_lock_irqsave(&local->lock, flags);
        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
@@ -106,12 +112,14 @@ static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
 static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
 {
        struct hostap_interface *iface;
+       struct hostap_pci_priv *hw_priv;
        local_info_t *local;
        unsigned long flags;
        u16 v;
 
        iface = netdev_priv(dev);
        local = iface->local;
+       hw_priv = local->hw_priv;
 
        spin_lock_irqsave(&local->lock, flags);
        v = readw(hw_priv->mem_start + a);
@@ -277,8 +285,6 @@ static struct prism2_helper_functions prism2_pci_funcs =
 {
        .card_present   = NULL,
        .cor_sreset     = prism2_pci_cor_sreset,
-       .dev_open       = NULL,
-       .dev_close      = NULL,
        .genesis_reset  = prism2_pci_genesis_reset,
        .hw_type        = HOSTAP_HW_PCI,
 };
@@ -352,8 +358,6 @@ static int prism2_pci_probe(struct pci_dev *pdev,
        return hostap_hw_ready(dev);
 
  fail:
-       kfree(hw_priv);
-
        if (irq_registered && dev)
                free_irq(dev->irq, dev);
 
@@ -364,10 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
 
  err_out_disable:
        pci_disable_device(pdev);
-       kfree(hw_priv);
-       if (local)
-               local->hw_priv = NULL;
        prism2_free_local_data(dev);
+       kfree(hw_priv);
 
        return -ENODEV;
 }
@@ -392,9 +394,8 @@ static void prism2_pci_remove(struct pci_dev *pdev)
                free_irq(dev->irq, dev);
 
        mem_start = hw_priv->mem_start;
-       kfree(hw_priv);
-       iface->local->hw_priv = NULL;
        prism2_free_local_data(dev);
+       kfree(hw_priv);
 
        iounmap(mem_start);
 
@@ -441,7 +442,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
 MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
 
 static struct pci_driver prism2_pci_drv_id = {
-       .name           = "prism2_pci",
+       .name           = "hostap_pci",
        .id_table       = prism2_pci_id_table,
        .probe          = prism2_pci_probe,
        .remove         = prism2_pci_remove,
index 474ef83d813e876cbe1fa026ac9d851f828475e7..78d67b408b2f9423080bd276ba4bfc78644164a7 100644 (file)
@@ -328,8 +328,6 @@ static struct prism2_helper_functions prism2_plx_funcs =
 {
        .card_present   = NULL,
        .cor_sreset     = prism2_plx_cor_sreset,
-       .dev_open       = NULL,
-       .dev_close      = NULL,
        .genesis_reset  = prism2_plx_genesis_reset,
        .hw_type        = HOSTAP_HW_PLX,
 };
@@ -570,10 +568,8 @@ static int prism2_plx_probe(struct pci_dev *pdev,
        return hostap_hw_ready(dev);
 
  fail:
-       kfree(hw_priv);
-       if (local)
-               local->hw_priv = NULL;
        prism2_free_local_data(dev);
+       kfree(hw_priv);
 
        if (irq_registered && dev)
                free_irq(dev->irq, dev);
@@ -606,9 +602,8 @@ static void prism2_plx_remove(struct pci_dev *pdev)
        if (dev->irq)
                free_irq(dev->irq, dev);
 
-       kfree(iface->local->hw_priv);
-       iface->local->hw_priv = NULL;
        prism2_free_local_data(dev);
+       kfree(hw_priv);
        pci_disable_device(pdev);
 }
 
@@ -616,7 +611,7 @@ static void prism2_plx_remove(struct pci_dev *pdev)
 MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
 
 static struct pci_driver prism2_plx_drv_id = {
-       .name           = "prism2_plx",
+       .name           = "hostap_plx",
        .id_table       = prism2_plx_id_table,
        .probe          = prism2_plx_probe,
        .remove         = prism2_plx_remove,
index cc061e1560d39c7150f4770f063f89207f752f14..cfd8015594921a849dd00215d4190ca381b8cd91 100644 (file)
@@ -552,8 +552,6 @@ struct prism2_helper_functions {
         * (hostap_{cs,plx,pci}.c */
        int (*card_present)(local_info_t *local);
        void (*cor_sreset)(local_info_t *local);
-       int (*dev_open)(local_info_t *local);
-       int (*dev_close)(local_info_t *local);
        void (*genesis_reset)(local_info_t *local, int hcr);
 
        /* the following functions are from hostap_hw.c, but they may have some
index 2414e6493aa5639ad88aaa829395976c404fa972..ad7f8cd76db9041376b19a024a74dc38ac5854b4 100644 (file)
@@ -800,8 +800,7 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
         * doesn't seem to have as many firmware restart cycles...
         *
         * As a test, we're sticking in a 1/100s delay here */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ / 100);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(10));
 
        return 0;
 
@@ -1256,8 +1255,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
        IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
        i = 5000;
        do {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(40 * HZ / 1000);
+               schedule_timeout_uninterruptible(msecs_to_jiffies(40));
                /* Todo... wait for sync command ... */
 
                read_register(priv->net_dev, IPW_REG_INTA, &inta);
@@ -1411,8 +1409,7 @@ static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
                    (val2 & IPW2100_COMMAND_PHY_OFF))
                        return 0;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
+               schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
        }
 
        return -EIO;
@@ -1466,7 +1463,7 @@ fail_up:
 
 static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
 {
-#define HW_POWER_DOWN_DELAY (HZ / 10)
+#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
 
        struct host_command cmd = {
                .host_command = HOST_PRE_POWER_DOWN,
@@ -1520,10 +1517,8 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
                        printk(KERN_WARNING DRV_NAME ": "
                               "%s: Power down command failed: Error %d\n",
                               priv->net_dev->name, err);
-               else {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(HW_POWER_DOWN_DELAY);
-               }
+               else
+                       schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
        }
 
        priv->status &= ~STATUS_ENABLED;
@@ -2953,7 +2948,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
        int next = txq->next;
         int i = 0;
        struct ipw2100_data_header *ipw_hdr;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_3addr *hdr;
 
        while (!list_empty(&priv->tx_pend_list)) {
                /* if there isn't enough space in TBD queue, then
@@ -2989,7 +2984,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
                packet->index = txq->next;
 
                ipw_hdr = packet->info.d_struct.data;
-               hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
+               hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
                        fragments[0]->data;
 
                if (priv->ieee->iw_mode == IW_MODE_INFRA) {
@@ -3274,7 +3269,8 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data,
        return IRQ_NONE;
 }
 
-static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
+                     int pri)
 {
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        struct list_head *element;
index 2a3cdbd50168aada6c620aac39eb6eb65b4992f0..c9e99ce15d66f45b107845baae368292f3b4f86d 100644 (file)
@@ -808,7 +808,7 @@ struct ipw2100_priv {
 struct ipw2100_rx {
        union {
                unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
-               struct ieee80211_hdr header;
+               struct ieee80211_hdr_4addr header;
                u32 status;
                struct ipw2100_notification notification;
                struct ipw2100_cmd_header command;
index b7f275c00de3cecc592368e90183bb96a3067563..de4e6c23e4b8693a23da434d66d6269b49519974 100644 (file)
@@ -4904,7 +4904,7 @@ static void ipw_rx(struct ipw_priv *priv)
 {
        struct ipw_rx_mem_buffer *rxb;
        struct ipw_rx_packet *pkt;
-       struct ieee80211_hdr *header;
+       struct ieee80211_hdr_4addr *header;
        u32 r, w, i;
        u8 network_packet;
 
@@ -4967,8 +4967,9 @@ static void ipw_rx(struct ipw_priv *priv)
 #endif
 
                                header =
-                                   (struct ieee80211_hdr *)(rxb->skb->data +
-                                                            IPW_RX_FRAME_SIZE);
+                                   (struct ieee80211_hdr_4addr *)(rxb->skb->
+                                                                  data +
+                                                                  IPW_RX_FRAME_SIZE);
                                /* TODO: Check Ad-Hoc dest/source and make sure
                                 * that we are actually parsing these packets
                                 * correctly -- we should probably use the
@@ -5317,8 +5318,6 @@ static int ipw_wx_set_freq(struct net_device *dev,
 
        IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
        return ipw_set_channel(priv, (u8) fwrq->m);
-
-       return 0;
 }
 
 static int ipw_wx_get_freq(struct net_device *dev,
@@ -6010,12 +6009,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
        }
 
        if (priv->adapter == IPW_2915ABG) {
-               priv->ieee->abg_ture = 1;
+               priv->ieee->abg_true = 1;
                if (mode & IEEE_A) {
                        band |= IEEE80211_52GHZ_BAND;
                        modulation |= IEEE80211_OFDM_MODULATION;
                } else
-                       priv->ieee->abg_ture = 0;
+                       priv->ieee->abg_true = 0;
        } else {
                if (mode & IEEE_A) {
                        IPW_WARNING("Attempt to set 2200BG into "
@@ -6023,20 +6022,20 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
                        return -EINVAL;
                }
 
-               priv->ieee->abg_ture = 0;
+               priv->ieee->abg_true = 0;
        }
 
        if (mode & IEEE_B) {
                band |= IEEE80211_24GHZ_BAND;
                modulation |= IEEE80211_CCK_MODULATION;
        } else
-               priv->ieee->abg_ture = 0;
+               priv->ieee->abg_true = 0;
 
        if (mode & IEEE_G) {
                band |= IEEE80211_24GHZ_BAND;
                modulation |= IEEE80211_OFDM_MODULATION;
        } else
-               priv->ieee->abg_ture = 0;
+               priv->ieee->abg_true = 0;
 
        priv->ieee->mode = mode;
        priv->ieee->freq_band = band;
@@ -6325,7 +6324,7 @@ we need to heavily modify the ieee80211_skb_to_txb.
 
 static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
 {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
+       struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
            txb->fragments[0]->data;
        int i = 0;
        struct tfd_frame *tfd;
@@ -6448,7 +6447,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
 }
 
 static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
-                                  struct net_device *dev)
+                                  struct net_device *dev, int pri)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
        unsigned long flags;
@@ -7108,7 +7107,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                printk(KERN_INFO DRV_NAME
                       ": Detected Intel PRO/Wireless 2915ABG Network "
                       "Connection\n");
-               priv->ieee->abg_ture = 1;
+               priv->ieee->abg_true = 1;
                band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
                modulation = IEEE80211_OFDM_MODULATION |
                    IEEE80211_CCK_MODULATION;
@@ -7124,7 +7123,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                               ": Detected Intel PRO/Wireless 2200BG Network "
                               "Connection\n");
 
-               priv->ieee->abg_ture = 0;
+               priv->ieee->abg_true = 0;
                band = IEEE80211_24GHZ_BAND;
                modulation = IEEE80211_OFDM_MODULATION |
                    IEEE80211_CCK_MODULATION;
index 5b00882133f919740cbe7e098a500e270ff8a5ff..e9cf32bf3e31741936882932b24ce289bf28f982 100644 (file)
@@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
 
 #define IPW_MAX_CONFIG_RETRIES 10
 
-static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
+static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
 {
        u32 retval;
        u16 fc;
 
-       retval = sizeof(struct ieee80211_hdr);
+       retval = sizeof(struct ieee80211_hdr_3addr);
        fc = le16_to_cpu(hdr->frame_ctl);
 
        /*
index ca6c03c89926ca89605c5b881a2ccabc0cb81411..92793b958e327d0777ea76291e614460bbe5bb40 100644 (file)
@@ -57,9 +57,7 @@
 #include <linux/bitops.h>
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>
-#if WIRELESS_EXT > 12
 #include <net/iw_handler.h>
-#endif /* WIRELESS_EXT > 12 */
 #endif
 
 #include <pcmcia/cs_types.h>
@@ -225,10 +223,7 @@ static void update_stats(struct net_device *dev);
 static struct net_device_stats *netwave_get_stats(struct net_device *dev);
 
 /* Wireless extensions */
-#ifdef WIRELESS_EXT
 static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
-#endif
-static int netwave_ioctl(struct net_device *, struct ifreq *, int);
 
 static void set_multicast_list(struct net_device *dev);
 
@@ -260,26 +255,7 @@ static dev_link_t *dev_list;
    because they generally can't be allocated dynamically.
 */
 
-#if WIRELESS_EXT <= 12
-/* Wireless extensions backward compatibility */
-
-/* Part of iw_handler prototype we need */
-struct iw_request_info
-{
-       __u16           cmd;            /* Wireless Extension command */
-       __u16           flags;          /* More to come ;-) */
-};
-
-/* Wireless Extension Backward compatibility - Jean II
- * If the new wireless device private ioctl range is not defined,
- * default to standard device private ioctl range */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV        SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
-#else  /* WIRELESS_EXT <= 12 */
 static const struct iw_handler_def     netwave_handler_def;
-#endif /* WIRELESS_EXT <= 12 */
 
 #define SIOCGIPSNAP    SIOCIWFIRSTPRIV + 1     /* Site Survey Snapshot */
 
@@ -319,9 +295,7 @@ typedef struct netwave_private {
     struct timer_list      watchdog;   /* To avoid blocking state */
     struct site_survey     nss;
     struct net_device_stats stats;
-#ifdef WIRELESS_EXT
     struct iw_statistics   iw_stats;    /* Wireless stats */
-#endif
 } netwave_private;
 
 #ifdef NETWAVE_STATS
@@ -353,7 +327,6 @@ static inline void wait_WOC(unsigned int iobase)
     while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ; 
 }
 
-#ifdef WIRELESS_EXT
 static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase, 
                             kio_addr_t iobase) {
     u_short resultBuffer;
@@ -376,9 +349,7 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
                      sizeof(struct site_survey)); 
     } 
 }
-#endif
 
-#ifdef WIRELESS_EXT
 /*
  * Function netwave_get_wireless_stats (dev)
  *
@@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
     
     return &priv->iw_stats;
 }
-#endif
 
 /*
  * Function netwave_attach (void)
@@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
     dev->get_stats  = &netwave_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     /* wireless extensions */
-#if WIRELESS_EXT <= 16
-    dev->get_wireless_stats = &netwave_get_wireless_stats;
-#endif /* WIRELESS_EXT <= 16 */
-#if WIRELESS_EXT > 12
     dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
-#endif /* WIRELESS_EXT > 12 */
-    dev->do_ioctl = &netwave_ioctl;
 
     dev->tx_timeout = &netwave_watchdog;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -576,13 +540,8 @@ static int netwave_set_nwid(struct net_device *dev,
        /* Disable interrupts & save flags */
        spin_lock_irqsave(&priv->spinlock, flags);
 
-#if WIRELESS_EXT > 8
        if(!wrqu->nwid.disabled) {
            domain = wrqu->nwid.value;
-#else  /* WIRELESS_EXT > 8 */
-       if(wrqu->nwid.on) {
-           domain = wrqu->nwid.nwid;
-#endif /* WIRELESS_EXT > 8 */
            printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", 
                    (domain >> 8) & 0x01, domain & 0xff);
            wait_WOC(iobase);
@@ -606,15 +565,9 @@ static int netwave_get_nwid(struct net_device *dev,
                            union iwreq_data *wrqu,
                            char *extra)
 {
-#if WIRELESS_EXT > 8
        wrqu->nwid.value = domain;
        wrqu->nwid.disabled = 0;
        wrqu->nwid.fixed = 1;
-#else  /* WIRELESS_EXT > 8 */
-       wrqu->nwid.nwid = domain;
-       wrqu->nwid.on = 1;
-#endif /* WIRELESS_EXT > 8 */
-
        return 0;
 }
 
@@ -657,17 +610,11 @@ static int netwave_get_scramble(struct net_device *dev,
 {
        key[1] = scramble_key & 0xff;
        key[0] = (scramble_key>>8) & 0xff;
-#if WIRELESS_EXT > 8
        wrqu->encoding.flags = IW_ENCODE_ENABLED;
        wrqu->encoding.length = 2;
-#else /* WIRELESS_EXT > 8 */
-       wrqu->encoding.method = 1;
-#endif /* WIRELESS_EXT > 8 */
-
        return 0;
 }
 
-#if WIRELESS_EXT > 8
 /*
  * Wireless Handler : get mode
  */
@@ -683,7 +630,6 @@ static int netwave_get_mode(struct net_device *dev,
 
        return 0;
 }
-#endif /* WIRELESS_EXT > 8 */
 
 /*
  * Wireless Handler : get range info
@@ -702,11 +648,9 @@ static int netwave_get_range(struct net_device *dev,
        /* Set all the info we don't care or don't know about to zero */
        memset(range, 0, sizeof(struct iw_range));
 
-#if WIRELESS_EXT > 10
        /* Set the Wireless Extension versions */
        range->we_version_compiled = WIRELESS_EXT;
        range->we_version_source = 9;   /* Nothing for us in v10 and v11 */
-#endif /* WIRELESS_EXT > 10 */
                   
        /* Set information in the range struct */
        range->throughput = 450 * 1000; /* don't argue on this ! */
@@ -720,16 +664,12 @@ static int netwave_get_range(struct net_device *dev,
        range->max_qual.level = 255;
        range->max_qual.noise = 0;
                   
-#if WIRELESS_EXT > 7
        range->num_bitrates = 1;
        range->bitrate[0] = 1000000;    /* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
 
-#if WIRELESS_EXT > 8
        range->encoding_size[0] = 2;            /* 16 bits scrambling */
        range->num_encoding_sizes = 1;
        range->max_encoding_tokens = 1; /* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
 
        return ret;
 }
@@ -775,8 +715,6 @@ static const struct iw_priv_args netwave_private_args[] = {
     "getsitesurvey" },
 };
 
-#if WIRELESS_EXT > 12
-
 static const iw_handler                netwave_handler[] =
 {
        NULL,                           /* SIOCSIWNAME */
@@ -839,131 +777,8 @@ static const struct iw_handler_def        netwave_handler_def =
        .standard       = (iw_handler *) netwave_handler,
        .private        = (iw_handler *) netwave_private_handler,
        .private_args   = (struct iw_priv_args *) netwave_private_args,
-#if WIRELESS_EXT > 16
        .get_wireless_stats = netwave_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
 };
-#endif /* WIRELESS_EXT > 12 */
-
-/*
- * Function netwave_ioctl (dev, rq, cmd)
- *
- *     Perform ioctl : config & info stuff
- *     This is the stuff that are treated the wireless extensions (iwconfig)
- *
- */
-static int netwave_ioctl(struct net_device *dev, /* ioctl device */
-                        struct ifreq *rq,       /* Data passed */
-                        int    cmd)         /* Ioctl number */
-{
-    int                        ret = 0;
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
-    struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-#endif
-       
-    DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
-       
-    /* Look what is the request */
-    switch(cmd) {
-       /* --------------- WIRELESS EXTENSIONS --------------- */
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
-    case SIOCGIWNAME:
-       netwave_get_name(dev, NULL, &(wrq->u), NULL);
-       break;
-    case SIOCSIWNWID:
-       ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
-       break;
-    case SIOCGIWNWID:
-       ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
-       break;
-#if WIRELESS_EXT > 8   /* Note : The API did change... */
-    case SIOCGIWENCODE:
-       /* Get scramble key */
-       if(wrq->u.encoding.pointer != (caddr_t) 0)
-         {
-           char        key[2];
-           ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
-           if(copy_to_user(wrq->u.encoding.pointer, key, 2))
-             ret = -EFAULT;
-         }
-       break;
-    case SIOCSIWENCODE:
-       /* Set  scramble key */
-       if(wrq->u.encoding.pointer != (caddr_t) 0)
-         {
-           char        key[2];
-           if(copy_from_user(key, wrq->u.encoding.pointer, 2))
-             {
-               ret = -EFAULT;
-               break;
-             }
-           ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
-         }
-       break;
-    case SIOCGIWMODE:
-       /* Mode of operation */
-       ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
-       break;
-#else /* WIRELESS_EXT > 8 */
-    case SIOCGIWENCODE:
-       /* Get scramble key */
-       ret = netwave_get_scramble(dev, NULL, &(wrq->u),
-                                  (char *) &wrq->u.encoding.code);
-       break;
-    case SIOCSIWENCODE:
-       /* Set  scramble key */
-       ret = netwave_set_scramble(dev, NULL, &(wrq->u),
-                                  (char *) &wrq->u.encoding.code);
-       break;
-#endif /* WIRELESS_EXT > 8 */
-   case SIOCGIWRANGE:
-       /* Basic checking... */
-       if(wrq->u.data.pointer != (caddr_t) 0) {
-           struct iw_range range;
-          ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
-          if (copy_to_user(wrq->u.data.pointer, &range,
-                           sizeof(struct iw_range)))
-              ret = -EFAULT;
-       }
-       break;
-    case SIOCGIWPRIV:
-       /* Basic checking... */
-       if(wrq->u.data.pointer != (caddr_t) 0) {
-           /* Set the number of ioctl available */
-           wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
-                       
-           /* Copy structure to the user buffer */
-           if(copy_to_user(wrq->u.data.pointer,
-                           (u_char *) netwave_private_args,
-                           sizeof(netwave_private_args)))
-             ret = -EFAULT;
-       } 
-       break;
-    case SIOCGIPSNAP:
-       if(wrq->u.data.pointer != (caddr_t) 0) {
-           char buffer[sizeof( struct site_survey)];
-           ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
-           /* Copy structure to the user buffer */
-           if(copy_to_user(wrq->u.data.pointer, 
-                           buffer,
-                           sizeof( struct site_survey)))
-             {
-               printk(KERN_DEBUG "Bad buffer!\n");
-               break;
-             }
-       }
-       break;
-#endif /* WIRELESS_EXT <= 12 */
-#endif /* WIRELESS_EXT */
-    default:
-       ret = -EOPNOTSUPP;
-    }
-       
-    return ret;
-}
 
 /*
  * Function netwave_pcmcia_config (link)
index 15ceaf615756a2ceb397993c384b81ef117354a5..d3d4ec9e242e311a16127e635c37585d8fc1d61e 100644 (file)
 #define DRIVER_NAME "orinoco"
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
 #include <linux/netdevice.h>
-#include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211.h>
 
-#include <net/ieee80211.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
 #include "hermes_rid.h"
 #include "orinoco.h"
 
@@ -137,7 +123,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
 
 /* We do this this way to avoid ifdefs in the actual code */
 #ifdef WIRELESS_SPY
-#define SPY_NUMBER(priv)       (priv->spy_number)
+#define SPY_NUMBER(priv)       (priv->spy_data.spy_number)
 #else
 #define SPY_NUMBER(priv)       0
 #endif /* WIRELESS_SPY */
@@ -216,31 +202,32 @@ static struct {
 /********************************************************************/
 
 /* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
+ * We avoid nested structures as they break on ARM -- Moustafa */
 struct hermes_tx_descriptor_802_11 {
        /* hermes_tx_descriptor */
-       u16 status;
-       u16 reserved1;
-       u16 reserved2;
-       u32 sw_support;
+       __le16 status;
+       __le16 reserved1;
+       __le16 reserved2;
+       __le32 sw_support;
        u8 retry_count;
        u8 tx_rate;
-       u16 tx_control;
+       __le16 tx_control;
 
-       /* ieee802_11_hdr */
-       u16 frame_ctl;
-       u16 duration_id;
+       /* ieee80211_hdr */
+       __le16 frame_ctl;
+       __le16 duration_id;
        u8 addr1[ETH_ALEN];
        u8 addr2[ETH_ALEN];
        u8 addr3[ETH_ALEN];
-       u16 seq_ctl;
+       __le16 seq_ctl;
        u8 addr4[ETH_ALEN];
-       u16 data_len;
+
+       __le16 data_len;
 
        /* ethhdr */
-       unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
-       unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
-       unsigned short  h_proto;                /* packet type ID field */
+       u8 h_dest[ETH_ALEN];    /* destination eth addr */
+       u8 h_source[ETH_ALEN];  /* source ether addr    */
+       __be16 h_proto;         /* packet type ID field */
 
        /* p8022_hdr */
        u8 dsap;
@@ -248,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
        u8 ctrl;
        u8 oui[3];
 
-       u16 ethertype;
+       __be16 ethertype;
 } __attribute__ ((packed));
 
 /* Rx frame header except compatibility 802.3 header */
 struct hermes_rx_descriptor {
        /* Control */
-       u16 status;
-       u32 time;
+       __le16 status;
+       __le32 time;
        u8 silence;
        u8 signal;
        u8 rate;
        u8 rxflow;
-       u32 reserved;
+       __le32 reserved;
 
        /* 802.11 header */
-       u16 frame_ctl;
-       u16 duration_id;
+       __le16 frame_ctl;
+       __le16 duration_id;
        u8 addr1[ETH_ALEN];
        u8 addr2[ETH_ALEN];
        u8 addr3[ETH_ALEN];
-       u16 seq_ctl;
+       __le16 seq_ctl;
        u8 addr4[ETH_ALEN];
 
        /* Data length */
-       u16 data_len;
+       __le16 data_len;
 } __attribute__ ((packed));
 
 /********************************************************************/
@@ -396,14 +383,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
                /* If a spy address is defined, we report stats of the
                 * first spy address - Jean II */
                if (SPY_NUMBER(priv)) {
-                       wstats->qual.qual = priv->spy_stat[0].qual;
-                       wstats->qual.level = priv->spy_stat[0].level;
-                       wstats->qual.noise = priv->spy_stat[0].noise;
-                       wstats->qual.updated = priv->spy_stat[0].updated;
+                       wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
+                       wstats->qual.level = priv->spy_data.spy_stat[0].level;
+                       wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
+                       wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
                }
        } else {
                struct {
-                       u16 qual, signal, noise;
+                       __le16 qual, signal, noise;
                } __attribute__ ((packed)) cq;
 
                err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -505,11 +492,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Check packet length, pad short packets, round up odd length */
        len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
-       if (skb->len < len) {
-               skb = skb_padto(skb, len);
-               if (skb == NULL)
-                       goto fail;
-       }
+       skb = skb_padto(skb, len);
+       if (skb == NULL)
+               goto fail;
        len -= ETH_HLEN;
 
        eh = (struct ethhdr *)skb->data;
@@ -634,16 +619,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
        struct orinoco_private *priv = netdev_priv(dev);
        struct net_device_stats *stats = &priv->stats;
        u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+       u16 status;
        struct hermes_tx_descriptor_802_11 hdr;
        int err = 0;
 
        if (fid == DUMMY_FID)
                return; /* Nothing's really happened */
 
-       /* Read the frame header */
+       /* Read part of the frame header - we need status and addr1 */
        err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-                              sizeof(struct hermes_tx_descriptor) +
-                              sizeof(struct ieee80211_hdr),
+                              offsetof(struct hermes_tx_descriptor_802_11,
+                                       addr2),
                               fid, 0);
 
        hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -663,8 +649,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
         * exceeded, because that's the only status that really mean
         * that this particular node went away.
         * Other errors means that *we* screwed up. - Jean II */
-       hdr.status = le16_to_cpu(hdr.status);
-       if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+       status = le16_to_cpu(hdr.status);
+       if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
                union iwreq_data        wrqu;
 
                /* Copy 802.11 dest address.
@@ -723,18 +709,13 @@ static inline int is_ethersnap(void *_hdr)
 static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
                                      int level, int noise)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
-       int i;
-
-       /* Gather wireless spy statistics: for each packet, compare the
-        * source address with out list, and if match, get the stats... */
-       for (i = 0; i < priv->spy_number; i++)
-               if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-                       priv->spy_stat[i].level = level - 0x95;
-                       priv->spy_stat[i].noise = noise - 0x95;
-                       priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
-                       priv->spy_stat[i].updated = 7;
-               }
+       struct iw_quality wstats;
+       wstats.level = level - 0x95;
+       wstats.noise = noise - 0x95;
+       wstats.qual = (level > noise) ? (level - noise) : 0;
+       wstats.updated = 7;
+       /* Update spy records */
+       wireless_spy_update(dev, mac, &wstats);
 }
 
 static void orinoco_stat_gather(struct net_device *dev,
@@ -1055,7 +1036,7 @@ static void orinoco_join_ap(struct net_device *dev)
        unsigned long flags;
        struct join_req {
                u8 bssid[ETH_ALEN];
-               u16 channel;
+               __le16 channel;
        } __attribute__ ((packed)) req;
        const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
        struct prism2_scan_apinfo *atom = NULL;
@@ -1070,7 +1051,7 @@ static void orinoco_join_ap(struct net_device *dev)
                return;
 
        if (orinoco_lock(priv, &flags) != 0)
-               goto out;
+               goto fail_lock;
 
        /* Sanity checks in case user changed something in the meantime */
        if (! priv->bssid_fixed)
@@ -1115,8 +1096,10 @@ static void orinoco_join_ap(struct net_device *dev)
                printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
 
  out:
-       kfree(buf);
        orinoco_unlock(priv, &flags);
+
+ fail_lock:
+       kfree(buf);
 }
 
 /* Send new BSSID to userspace */
@@ -1134,12 +1117,14 @@ static void orinoco_send_wevents(struct net_device *dev)
        err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
                              ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
        if (err != 0)
-               return;
+               goto out;
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
        /* Send event to user space */
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+
+ out:
        orinoco_unlock(priv, &flags);
 }
 
@@ -1148,8 +1133,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
        struct orinoco_private *priv = netdev_priv(dev);
        u16 infofid;
        struct {
-               u16 len;
-               u16 type;
+               __le16 len;
+               __le16 type;
        } __attribute__ ((packed)) info;
        int len, type;
        int err;
@@ -2464,6 +2449,10 @@ struct net_device *alloc_orinocodev(int sizeof_card,
        dev->get_stats = orinoco_get_stats;
        dev->ethtool_ops = &orinoco_ethtool_ops;
        dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+#ifdef WIRELESS_SPY
+       priv->wireless_data.spy_data = &priv->spy_data;
+       dev->wireless_data = &priv->wireless_data;
+#endif
        dev->change_mtu = orinoco_change_mtu;
        dev->set_multicast_list = orinoco_set_multicast_list;
        /* we use the default eth_mac_addr for setting the MAC addr */
@@ -2835,7 +2824,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
                }
        }
 
-       if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
+       if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
                /* Quality stats meaningless in ad-hoc mode */
        } else {
                range->max_qual.qual = 0x8b - 0x2f;
@@ -2882,6 +2871,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
        range->min_r_time = 0;
        range->max_r_time = 65535 * 1000;       /* ??? */
 
+       /* Event capability (kernel) */
+       IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+       /* Event capability (driver) */
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+       IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+
        TRACE_EXIT(dev->name);
 
        return 0;
@@ -3841,92 +3838,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
        return err;
 }
 
-/* Spy is used for link quality/strength measurements in Ad-Hoc mode
- * Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev,
-                               struct iw_request_info *info,
-                               struct iw_point *srq,
-                               char *extra)
-
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       struct sockaddr *address = (struct sockaddr *) extra;
-       int number = srq->length;
-       int i;
-       unsigned long flags;
-
-       /* Make sure nobody mess with the structure while we do */
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       /* orinoco_lock() doesn't disable interrupts, so make sure the
-        * interrupt rx path don't get confused while we copy */
-       priv->spy_number = 0;
-
-       if (number > 0) {
-               /* Extract the addresses */
-               for (i = 0; i < number; i++)
-                       memcpy(priv->spy_address[i], address[i].sa_data,
-                              ETH_ALEN);
-               /* Reset stats */
-               memset(priv->spy_stat, 0,
-                      sizeof(struct iw_quality) * IW_MAX_SPY);
-               /* Set number of addresses */
-               priv->spy_number = number;
-       }
-
-       /* Now, let the others play */
-       orinoco_unlock(priv, &flags);
-
-       /* Do NOT call commit handler */
-       return 0;
-}
-
-static int orinoco_ioctl_getspy(struct net_device *dev,
-                               struct iw_request_info *info,
-                               struct iw_point *srq,
-                               char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       struct sockaddr *address = (struct sockaddr *) extra;
-       int number;
-       int i;
-       unsigned long flags;
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       number = priv->spy_number;
-       /* Create address struct */
-       for (i = 0; i < number; i++) {
-               memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
-               address[i].sa_family = AF_UNIX;
-       }
-       if (number > 0) {
-               /* Create address struct */
-               for (i = 0; i < number; i++) {
-                       memcpy(address[i].sa_data, priv->spy_address[i],
-                              ETH_ALEN);
-                       address[i].sa_family = AF_UNIX;
-               }
-               /* Copy stats */
-               /* In theory, we should disable irqs while copying the stats
-                * because the rx path might update it in the middle...
-                * Bah, who care ? - Jean II */
-               memcpy(extra  + (sizeof(struct sockaddr) * number),
-                      priv->spy_stat, sizeof(struct iw_quality) * number);
-       }
-       /* Reset updated flags. */
-       for (i = 0; i < number; i++)
-               priv->spy_stat[i].updated = 0;
-
-       orinoco_unlock(priv, &flags);
-
-       srq->length = number;
-
-       return 0;
-}
-
 /* Trigger a scan (look for other cells in the vicinity */
 static int orinoco_ioctl_setscan(struct net_device *dev,
                                 struct iw_request_info *info,
@@ -3999,7 +3910,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
                                                   HERMES_HOSTSCAN_SYMBOL_BCAST);
                        break;
                case FIRMWARE_TYPE_INTERSIL: {
-                       u16 req[3];
+                       __le16 req[3];
 
                        req[0] = cpu_to_le16(0x3fff);   /* All channels */
                        req[1] = cpu_to_le16(0x0001);   /* rate 1 Mbps */
@@ -4073,7 +3984,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
        case FIRMWARE_TYPE_INTERSIL:
                offset = 4;
                if (priv->has_hostscan) {
-                       atom_len = le16_to_cpup((u16 *)scan);
+                       atom_len = le16_to_cpup((__le16 *)scan);
                        /* Sanity check for atom_len */
                        if (atom_len < sizeof(struct prism2_scan_apinfo)) {
                                printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
@@ -4357,8 +4268,10 @@ static const iw_handler  orinoco_handler[] = {
        [SIOCSIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
        [SIOCGIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
        [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
-       [SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
-       [SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
+       [SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
+       [SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
+       [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
+       [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
        [SIOCSIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
        [SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
        [SIOCSIWSCAN  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
index 2f213a7103fe70cee7ca41ca66f0994928471f85..7a17bb31fc896da55e1943c021aaa2ad7c125c51 100644 (file)
@@ -7,12 +7,11 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
-#define DRIVER_VERSION "0.15rc2"
+#define DRIVER_VERSION "0.15rc3"
 
-#include <linux/types.h>
-#include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
+#include <net/iw_handler.h>
 #include <linux/version.h>
 
 #include "hermes.h"
@@ -28,7 +27,7 @@
 #define ORINOCO_MAX_KEYS       4
 
 struct orinoco_key {
-       u16 len;        /* always stored as little-endian */
+       __le16 len;     /* always stored as little-endian */
        char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
@@ -36,14 +35,14 @@ struct header_struct {
        /* 802.3 */
        u8 dest[ETH_ALEN];
        u8 src[ETH_ALEN];
-       u16 len;
+       __be16 len;
        /* 802.2 */
        u8 dsap;
        u8 ssap;
        u8 ctrl;
        /* SNAP */
        u8 oui[3];
-       u16 ethertype;
+       unsigned short ethertype;
 } __attribute__ ((packed));
 
 typedef enum {
@@ -112,9 +111,8 @@ struct orinoco_private {
        u16 pm_on, pm_mcast, pm_period, pm_timeout;
        u16 preamble;
 #ifdef WIRELESS_SPY
-       int                     spy_number;
-       u_char                  spy_address[IW_MAX_SPY][ETH_ALEN];
-       struct iw_quality       spy_stat[IW_MAX_SPY];
+       struct iw_spy_data spy_data; /* iwspy support */
+       struct iw_public_data   wireless_data;
 #endif
 
        /* Configuration dependent variables */
index bedd7f9f23e48cd37201e79f6a3b4c3b35697bc6..dc1128a009719811c39a426ef132a8dd88c94ca7 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-#ifdef  __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
 #include "orinoco.h"
 
 /********************************************************************/
@@ -97,17 +80,8 @@ static dev_link_t *dev_list; /* = NULL */
 /* Function prototypes                                             */
 /********************************************************************/
 
-/* device methods */
-static int orinoco_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void orinoco_cs_config(dev_link_t * link);
-static void orinoco_cs_release(dev_link_t * link);
-static int orinoco_cs_event(event_t event, int priority,
-                           event_callback_args_t * args);
-
-static dev_link_t *orinoco_cs_attach(void);
-static void orinoco_cs_detach(dev_link_t *);
+static void orinoco_cs_release(dev_link_t *link);
+static void orinoco_cs_detach(dev_link_t *link);
 
 /********************************************************************/
 /* Device methods                                                  */
@@ -603,49 +577,85 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
        "Pavel Roskin <proski@gnu.org>, et al)";
 
 static struct pcmcia_device_id orinoco_cs_ids[] = {
-       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
-       PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
-       PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
-       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
-       PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
-       PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
-       PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
-       PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
-       PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
+       PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+       PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
+       PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
+       PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
+       PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
+       PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
+       PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+       PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
+       PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
+       PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
+       PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
+       PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
+       PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
+       PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
        PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
-       PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
        PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
+       PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
+       PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
        PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+       PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
        PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
+       PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
        PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+       PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+       PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
        PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
        PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
        PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
+       PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+       PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
        PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
        PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+       PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+       PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
        PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
+       PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
+       PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+       PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
+       PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
        PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
        PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
        PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
        PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
        PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
+       PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
        PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
+       PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+       PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
+       PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
        PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
+       PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
        PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
        PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
        PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
-       PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
+       PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
+       PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+       PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
+       PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
        PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
@@ -656,8 +666,8 @@ static struct pcmcia_driver orinoco_driver = {
                .name   = DRIVER_NAME,
        },
        .attach         = orinoco_cs_attach,
-       .event          = orinoco_cs_event,
        .detach         = orinoco_cs_detach,
+       .event          = orinoco_cs_event,
        .id_table       = orinoco_cs_ids,
 };
 
index 86fa58e5cfac87279c28f729c8c840c6f446a9d7..d8afd51ff8a59010dd89f26dddcc38ff2e20496c 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_OFFSET    (0xe0)   /* COR attribute offset of Prism2 PC card */
@@ -108,7 +92,7 @@ static int nortel_pci_cor_reset(struct orinoco_private *priv)
        return 0;
 }
 
-int nortel_pci_hw_init(struct nortel_pci_card *card)
+static int nortel_pci_hw_init(struct nortel_pci_card *card)
 {
        int i;
        u32 reg;
index 42e03438291b8e3ad7967ea93198c996211434ed..5362c214fc8e299da8bd0003f5d2bd76ab9fea6f 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 /* All the magic there is from wlan-ng */
index 7ab05b89fb3f6176405cf1244c78061afe633980..210e73776545d6750e0e99289ff7f023acf2b69a 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_OFFSET     (0x3e0) /* COR attribute offset of Prism2 PC card */
index 85893f42445be7e227c7fd3627747d66e984b656..5e68b7026186bc9f497c1abbf9d14259e4a96bca 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_VALUE      (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
index 9a8790e3580c648d33f948717c38bc0d94a29728..5c1a1adf1ff8b2421d93549f765c071c2bc9e0fb 100644 (file)
@@ -462,14 +462,12 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
        /* txpower is supported in dBm's */
        range->txpower_capa = IW_TXPOW_DBM;
 
-#if WIRELESS_EXT > 16
        /* Event capability (kernel + driver) */
        range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
        IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
        IW_EVENT_CAPA_MASK(SIOCGIWAP));
        range->event_capa[1] = IW_EVENT_CAPA_K_1;
        range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
-#endif /* WIRELESS_EXT > 16 */
 
        if (islpci_get_state(priv) < PRV_STATE_INIT)
                return 0;
@@ -693,14 +691,13 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
                                                   extra + dwrq->length,
                                                   &(bsslist->bsslist[i]),
                                                   noise);
-#if WIRELESS_EXT > 16
+
                /* Check if there is space for one more entry */
                if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
                        /* Ask user space to try again with a bigger buffer */
                        rvalue = -E2BIG;
                        break;
                }
-#endif /* WIRELESS_EXT > 16 */
        }
 
        kfree(bsslist);
@@ -2727,12 +2724,7 @@ const struct iw_handler_def prism54_handler_def = {
        .standard = (iw_handler *) prism54_handler,
        .private = (iw_handler *) prism54_private_handler,
        .private_args = (struct iw_priv_args *) prism54_private_args,
-#if WIRELESS_EXT > 16
        .get_wireless_stats = prism54_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
-#if WIRELESS_EXT == 16
-       .spy_offset = offsetof(islpci_private, spy_data),
-#endif /* WIRELESS_EXT == 16 */
 };
 
 /* For wpa_supplicant */
index 6f13d4a8e2d33805b93952d1663459afb7cd8995..6c9584a9f284dc1b357af18804d6856b47260156 100644 (file)
@@ -439,8 +439,7 @@ prism54_bring_down(islpci_private *priv)
        wmb();
 
        /* wait a while for the device to reset */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(50*HZ/1000);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(50));
 
        return 0;
 }
@@ -491,8 +490,7 @@ islpci_reset_if(islpci_private *priv)
                /* The software reset acknowledge needs about 220 msec here.
                 * Be conservative and wait for up to one second. */
        
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               remaining = schedule_timeout(HZ);
+               remaining = schedule_timeout_uninterruptible(HZ);
 
                if(remaining > 0) {
                        result = 0;
@@ -839,13 +837,9 @@ islpci_setup(struct pci_dev *pdev)
        priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
                priv->monitor_type : ARPHRD_ETHER;
 
-#if WIRELESS_EXT > 16
        /* Add pointers to enable iwspy support. */
        priv->wireless_data.spy_data = &priv->spy_data;
        ndev->wireless_data = &priv->wireless_data;
-#else  /* WIRELESS_EXT > 16 */
-       ndev->get_wireless_stats = &prism54_get_wireless_stats;
-#endif /* WIRELESS_EXT > 16 */
 
        /* save the start and end address of the PCI memory area */
        ndev->mem_start = (unsigned long) priv->device_base;
index 32a1019f1b363ef9c8486eba3138c159f5dee784..efbed439795111ac4e9021f56b60c4fc00ac2dad 100644 (file)
@@ -100,9 +100,7 @@ typedef struct {
 
        struct iw_spy_data spy_data; /* iwspy support */
 
-#if WIRELESS_EXT > 16
        struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT > 16 */
 
        int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
 
index b6f2e5a223be623e56f4f5a156cf96a3ea8d5abf..4937a5ad4b2cee319d63eabf5ee423b2e8aa955c 100644 (file)
@@ -455,7 +455,7 @@ islpci_mgt_transaction(struct net_device *ndev,
                       struct islpci_mgmtframe **recvframe)
 {
        islpci_private *priv = netdev_priv(ndev);
-       const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
+       const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10);
        long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
        int err;
        DEFINE_WAIT(wait);
@@ -475,8 +475,7 @@ islpci_mgt_transaction(struct net_device *ndev,
                int timeleft;
                struct islpci_mgmtframe *frame;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               timeleft = schedule_timeout(wait_cycle_jiffies);
+               timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies);
                frame = xchg(&priv->mgmt_received, NULL);
                if (frame) {
                        if (frame->header->oid == oid) {
index e9c5ea0f5535dada4e4416fdad26d81caa6de948..70fd6fd8feb9bd5fb856043e8e195ddfccea84e6 100644 (file)
@@ -1649,28 +1649,28 @@ static iw_stats * ray_get_wireless_stats(struct net_device *    dev)
  */
 
 static const iw_handler        ray_handler[] = {
-       [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
-       [SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) ray_get_name,
-       [SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) ray_set_freq,
-       [SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) ray_get_freq,
-       [SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) ray_set_mode,
-       [SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) ray_get_mode,
-       [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
+       [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
+       [SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) ray_get_name,
+       [SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) ray_set_freq,
+       [SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) ray_get_freq,
+       [SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) ray_set_mode,
+       [SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) ray_get_mode,
+       [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
 #ifdef WIRELESS_SPY
-       [SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
-       [SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
-       [SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
-       [SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
+       [SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
+       [SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
+       [SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
+       [SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
 #endif /* WIRELESS_SPY */
-       [SIOCGIWAP    -SIOCIWFIRST] (iw_handler) ray_get_wap,
-       [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
-       [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
-       [SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) ray_set_rate,
-       [SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) ray_get_rate,
-       [SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) ray_set_rts,
-       [SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) ray_get_rts,
-       [SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) ray_set_frag,
-       [SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) ray_get_frag,
+       [SIOCGIWAP    -SIOCIWFIRST] (iw_handler) ray_get_wap,
+       [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
+       [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
+       [SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) ray_set_rate,
+       [SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) ray_get_rate,
+       [SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) ray_set_rts,
+       [SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) ray_get_rts,
+       [SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) ray_set_frag,
+       [SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) ray_get_frag,
 };
 
 #define SIOCSIPFRAMING SIOCIWFIRSTPRIV         /* Set framing mode */
@@ -1678,9 +1678,9 @@ static const iw_handler   ray_handler[] = {
 #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3     /* Get country code */
 
 static const iw_handler        ray_private_handler[] = {
-       [0] (iw_handler) ray_set_framing,
-       [1] (iw_handler) ray_get_framing,
-       [3] (iw_handler) ray_get_country,
+       [0] (iw_handler) ray_set_framing,
+       [1] (iw_handler) ray_get_framing,
+       [3] (iw_handler) ray_get_country,
 };
 
 static const struct iw_priv_args       ray_private_args[] = {
index 39c6cdf7f3f736707c968008bdd11a0e7952fbed..b1bbc8e8e91f432e9e46cb44b969cbc70e550bc1 100644 (file)
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-#ifdef  __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
+#include <linux/firmware.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
 #include "orinoco.h"
 
-/*
- * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
- * the driver.  Use get_symbol_fw script to generate spectrum_fw.h and
- * copy it to the same directory as spectrum_cs.c.
- *
- * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
- * runtime using hotplug.  Use the same get_symbol_fw script to generate
- * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
- * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
- * make sure that you have hotplug installed and enabled in the kernel.
- */
-/* #define SPECTRUM_FW_INCLUDED 1 */
-
-#ifdef SPECTRUM_FW_INCLUDED
-/* Header with the firmware */
-#include "spectrum_fw.h"
-#else  /* !SPECTRUM_FW_INCLUDED */
-#include <linux/firmware.h>
 static unsigned char *primsym;
 static unsigned char *secsym;
 static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
 static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-#endif /* !SPECTRUM_FW_INCLUDED */
 
 /********************************************************************/
 /* Module stuff                                                            */
@@ -124,17 +89,8 @@ static dev_link_t *dev_list; /* = NULL */
 /* Function prototypes                                             */
 /********************************************************************/
 
-/* device methods */
-static int spectrum_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void spectrum_cs_config(dev_link_t * link);
-static void spectrum_cs_release(dev_link_t * link);
-static int spectrum_cs_event(event_t event, int priority,
-                           event_callback_args_t * args);
-
-static dev_link_t *spectrum_cs_attach(void);
-static void spectrum_cs_detach(dev_link_t *);
+static void spectrum_cs_release(dev_link_t *link);
+static void spectrum_cs_detach(dev_link_t *link);
 
 /********************************************************************/
 /* Firmware downloader                                             */
@@ -182,8 +138,8 @@ static void spectrum_cs_detach(dev_link_t *);
  * Each block has the following structure.
  */
 struct dblock {
-       u32 _addr;              /* adapter address where to write the block */
-       u16 _len;               /* length of the data only, in bytes */
+       __le32 _addr;           /* adapter address where to write the block */
+       __le16 _len;            /* length of the data only, in bytes */
        char data[0];           /* data to be written */
 } __attribute__ ((packed));
 
@@ -193,9 +149,9 @@ struct dblock {
  * items with matching ID should be written.
  */
 struct pdr {
-       u32 _id;                /* record ID */
-       u32 _addr;              /* adapter address where to write the data */
-       u32 _len;               /* expected length of the data, in bytes */
+       __le32 _id;             /* record ID */
+       __le32 _addr;           /* adapter address where to write the data */
+       __le32 _len;            /* expected length of the data, in bytes */
        char next[0];           /* next PDR starts here */
 } __attribute__ ((packed));
 
@@ -206,8 +162,8 @@ struct pdr {
  * be plugged into the secondary firmware.
  */
 struct pdi {
-       u16 _len;               /* length of ID and data, in words */
-       u16 _id;                /* record ID */
+       __le16 _len;            /* length of ID and data, in words */
+       __le16 _id;             /* record ID */
        char data[0];           /* plug data */
 } __attribute__ ((packed));;
 
@@ -414,7 +370,7 @@ spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
 
 /* Read PDA from the adapter */
 static int
-spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
 {
        int ret;
        int pda_size;
@@ -445,7 +401,7 @@ spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
 /* Parse PDA and write the records into the adapter */
 static int
 spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
-                  u16 *pda)
+                  __le16 *pda)
 {
        int ret;
        struct pdi *pdi;
@@ -511,7 +467,7 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
        const struct dblock *first_block;
 
        /* Plug Data Area (PDA) */
-       u16 pda[PDA_WORDS];
+       __le16 pda[PDA_WORDS];
 
        /* Binary block begins after the 0x1A marker */
        ptr = image;
@@ -571,8 +527,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
 {
        int ret;
        client_handle_t handle = link->handle;
-
-#ifndef SPECTRUM_FW_INCLUDED
        const struct firmware *fw_entry;
 
        if (request_firmware(&fw_entry, primary_fw_name,
@@ -592,7 +546,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
                       secondary_fw_name);
                return -ENOENT;
        }
-#endif
 
        /* Load primary firmware */
        ret = spectrum_dl_image(hw, link, primsym);
@@ -1085,7 +1038,7 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
 static struct pcmcia_device_id spectrum_cs_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
        PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
-       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+       PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
        PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
@@ -1096,8 +1049,8 @@ static struct pcmcia_driver orinoco_driver = {
                .name   = DRIVER_NAME,
        },
        .attach         = spectrum_cs_attach,
-       .event          = spectrum_cs_event,
        .detach         = spectrum_cs_detach,
+       .event          = spectrum_cs_event,
        .id_table       = spectrum_cs_ids,
 };
 
index 7a5e20a17890c81316c8bac8dcefd0963c29288e..b0d8b5b03152769974b382809418b47d1bd6fb08 100644 (file)
@@ -430,7 +430,6 @@ static void fee_read(unsigned long ioaddr,  /* I/O port of the card */
        }
 }
 
-#ifdef WIRELESS_EXT            /* if the wireless extension exists in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -514,7 +513,6 @@ static void fee_write(unsigned long ioaddr, /* I/O port of the card */
        fee_wait(ioaddr, 10, 100);
 #endif                         /* EEPROM_IS_PROTECTED */
 }
-#endif                         /* WIRELESS_EXT */
 
 /************************ I82586 SUBROUTINES *************************/
 /*
@@ -973,11 +971,9 @@ static void wv_mmc_show(struct net_device * dev)
        mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
        mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
 
-#ifdef WIRELESS_EXT            /* if wireless extension exists in the kernel */
        /* Don't forget to update statistics */
        lp->wstats.discard.nwid +=
            (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif                         /* WIRELESS_EXT */
 
        printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
 #ifdef DEBUG_SHOW_UNUSED
@@ -1499,7 +1495,6 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
 }
 #endif                         /* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT            /* if wireless extensions exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2473,7 +2468,6 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
 #endif
        return &lp->wstats;
 }
-#endif                         /* WIRELESS_EXT */
 
 /************************* PACKET RECEPTION *************************/
 /*
@@ -4194,11 +4188,9 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr)
        dev->set_mac_address = &wavelan_set_mac_address;
 #endif                         /* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT            /* if wireless extension exists in the kernel */
        dev->wireless_handlers = &wavelan_handler_def;
        lp->wireless_data.spy_data = &lp->spy_data;
        dev->wireless_data = &lp->wireless_data;
-#endif
 
        dev->mtu = WAVELAN_MTU;
 
index 509ff22a6caa674f5bc41fe41780611d45362146..166e28b9a4f7fca1464b5b500cd1759a0b2a6e34 100644 (file)
 #define MULTICAST_AVOID                /* Avoid extra multicast (I'm sceptical). */
 #undef SET_MAC_ADDRESS         /* Experimental */
 
-#ifdef WIRELESS_EXT    /* If wireless extensions exist in the kernel */
 /* Warning:  this stuff will slow down the driver. */
 #define WIRELESS_SPY           /* Enable spying addresses. */
 #undef HISTOGRAM               /* Enable histogram of signal level. */
-#endif
 
 /****************************** DEBUG ******************************/
 
@@ -506,12 +504,10 @@ struct net_local
   u_short      tx_first_free;
   u_short      tx_first_in_use;
 
-#ifdef WIRELESS_EXT
   iw_stats     wstats;         /* Wireless-specific statistics */
 
   struct iw_spy_data   spy_data;
   struct iw_public_data        wireless_data;
-#endif
 
 #ifdef HISTOGRAM
   int          his_number;             /* number of intervals */
index 183c4732ef65ca0eb24e99c79d1b43197a3f8930..4b3c98f5c564fba27800d496cd42695419924c65 100644 (file)
@@ -415,7 +415,6 @@ fee_read(u_long             base,   /* i/o port of the card */
     }
 }
 
-#ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -500,7 +499,6 @@ fee_write(u_long    base,   /* i/o port of the card */
   fee_wait(base, 10, 100);
 #endif /* EEPROM_IS_PROTECTED */
 }
-#endif /* WIRELESS_EXT */
 
 /******************* WaveLAN Roaming routines... ********************/
 
@@ -1161,10 +1159,8 @@ wv_mmc_show(struct net_device *  dev)
   mmc_read(base, 0, (u_char *)&m, sizeof(m));
   mmc_out(base, mmwoff(0, mmw_freeze), 0);
 
-#ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
   /* Don't forget to update statistics */
   lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
 
   spin_unlock_irqrestore(&lp->spinlock, flags);
 
@@ -1550,7 +1546,6 @@ wavelan_set_mac_address(struct net_device *       dev,
 }
 #endif /* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2793,7 +2788,6 @@ wavelan_get_wireless_stats(struct net_device *    dev)
 #endif
   return &lp->wstats;
 }
-#endif /* WIRELESS_EXT */
 
 /************************* PACKET RECEPTION *************************/
 /*
@@ -4679,11 +4673,9 @@ wavelan_attach(void)
   dev->watchdog_timeo  = WATCHDOG_JIFFIES;
   SET_ETHTOOL_OPS(dev, &ops);
 
-#ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
   dev->wireless_handlers = &wavelan_handler_def;
   lp->wireless_data.spy_data = &lp->spy_data;
   dev->wireless_data = &lp->wireless_data;
-#endif
 
   /* Other specific data */
   dev->mtu = WAVELAN_MTU;
index 01d882be8790c1b9c8d2b81d71fcc64248210dad..724a715089c996f79b7e59e04ebf049bd3b0b182 100644 (file)
 #define MULTICAST_AVOID                /* Avoid extra multicast (I'm sceptical) */
 #undef SET_MAC_ADDRESS         /* Experimental */
 
-#ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
 /* Warning : these stuff will slow down the driver... */
 #define WIRELESS_SPY           /* Enable spying addresses */
 #undef HISTOGRAM               /* Enable histogram of sig level... */
-#endif
 
 /****************************** DEBUG ******************************/
 
@@ -624,12 +622,10 @@ struct net_local
   int          rfp;            /* Last DMA machine receive pointer */
   int          overrunning;    /* Receiver overrun flag */
 
-#ifdef WIRELESS_EXT
   iw_stats     wstats;         /* Wireless specific stats */
 
   struct iw_spy_data   spy_data;
   struct iw_public_data        wireless_data;
-#endif
 
 #ifdef HISTOGRAM
   int          his_number;             /* Number of intervals */
index 7fcbe589c3f2bf4808284e1dfc595c8127fb6589..4303c50c2ab619eec386f2ec3f4b4bdc43b768f3 100644 (file)
@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
 
 struct wl3501_80211_tx_hdr {
        struct wl3501_80211_tx_plcp_hdr pclp_hdr;
-       struct ieee80211_hdr            mac_hdr;
+       struct ieee80211_hdr_4addr              mac_hdr;
 } __attribute__ ((packed));
 
 /*
index 9963479ba89f71df304cdb87ab552da5ea834eaf..38a2441564d7d85bc94d2b931f4d641f619a7f0a 100644 (file)
@@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
        QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
        QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
        QETH_MAX_QUEUES,0x103}, \
+       {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+       QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+       QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+       QETH_MAX_QUEUES,0}, \
        {0,0,0,0,0,0,0,0,0}}
 
 #define QETH_REAL_CARD         1
@@ -363,10 +367,22 @@ struct qeth_hdr_layer2 {
        __u8 reserved2[16];
 } __attribute__ ((packed));
 
+struct qeth_hdr_osn {
+       __u8 id;
+       __u8 reserved;
+       __u16 seq_no;
+       __u16 reserved2;
+       __u16 control_flags;
+       __u16 pdu_length;
+       __u8 reserved3[18];
+       __u32 ccid;
+} __attribute__ ((packed));
+                                           
 struct qeth_hdr {
        union {
                struct qeth_hdr_layer2 l2;
                struct qeth_hdr_layer3 l3;
+               struct qeth_hdr_osn    osn;
        } hdr;
 } __attribute__ ((packed));
 
@@ -413,6 +429,7 @@ enum qeth_header_ids {
        QETH_HEADER_TYPE_LAYER3 = 0x01,
        QETH_HEADER_TYPE_LAYER2 = 0x02,
        QETH_HEADER_TYPE_TSO    = 0x03,
+       QETH_HEADER_TYPE_OSN    = 0x04,
 };
 /* flags for qeth_hdr.ext_flags */
 #define QETH_HDR_EXT_VLAN_FRAME       0x01
@@ -582,7 +599,6 @@ enum qeth_card_states {
  * Protocol versions
  */
 enum qeth_prot_versions {
-       QETH_PROT_SNA  = 0x0001,
        QETH_PROT_IPV4 = 0x0004,
        QETH_PROT_IPV6 = 0x0006,
 };
@@ -761,6 +777,11 @@ enum qeth_threads {
        QETH_RECOVER_THREAD = 2,
 };
 
+struct qeth_osn_info {
+       int (*assist_cb)(struct net_device *dev, void *data);
+       int (*data_cb)(struct sk_buff *skb);
+};
+
 struct qeth_card {
        struct list_head list;
        enum qeth_card_states state;
@@ -803,6 +824,7 @@ struct qeth_card {
        int use_hard_stop;
        int (*orig_hard_header)(struct sk_buff *,struct net_device *,
                                unsigned short,void *,void *,unsigned);
+       struct qeth_osn_info osn_info; 
 };
 
 struct qeth_card_list_struct {
@@ -916,10 +938,12 @@ qeth_get_hlen(__u8 link_type)
 static inline unsigned short
 qeth_get_netdev_flags(struct qeth_card *card)
 {
-       if (card->options.layer2)
+       if (card->options.layer2 &&
+          (card->info.type == QETH_CARD_TYPE_OSAE))
                return 0;
        switch (card->info.type) {
        case QETH_CARD_TYPE_IQD:
+       case QETH_CARD_TYPE_OSN:        
                return IFF_NOARP;
 #ifdef CONFIG_QETH_IPV6
        default:
@@ -956,9 +980,10 @@ static inline int
 qeth_get_max_mtu_for_card(int cardtype)
 {
        switch (cardtype) {
+               
        case QETH_CARD_TYPE_UNKNOWN:
-               return 61440;
        case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSN:
                return 61440;
        case QETH_CARD_TYPE_IQD:
                return 57344;
@@ -1004,6 +1029,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu)
        case QETH_CARD_TYPE_IQD:
                return ((mtu >= 576) &&
                        (mtu <= card->info.max_mtu + 4096 - 32));
+       case QETH_CARD_TYPE_OSN:
        case QETH_CARD_TYPE_UNKNOWN:
        default:
                return 1;
@@ -1015,6 +1041,7 @@ qeth_get_arphdr_type(int cardtype, int linktype)
 {
        switch (cardtype) {
        case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSN:
                switch (linktype) {
                case QETH_LINK_TYPE_LANE_TR:
                case QETH_LINK_TYPE_HSTR:
@@ -1182,4 +1209,16 @@ qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
 extern void
 qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
 
+extern int
+qeth_osn_assist(struct net_device *, void *, int);
+
+extern int
+qeth_osn_register(unsigned char *read_dev_no,
+                 struct net_device **,
+                 int (*assist_cb)(struct net_device *, void *),
+                 int (*data_cb)(struct sk_buff *));
+
+extern void
+qeth_osn_deregister(struct net_device *);
+               
 #endif /* __QETH_H__ */
index 5c9a51ce91b6287301364fc7e3179d3024a3bfac..c0b4c8d82c45e3108927eb6c2d27c61147199db0 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef __QETH_FS_H__
 #define __QETH_FS_H__
 
-#define VERSION_QETH_FS_H "$Revision: 1.9 $"
+#define VERSION_QETH_FS_H "$Revision: 1.10 $"
 
 extern const char *VERSION_QETH_PROC_C;
 extern const char *VERSION_QETH_SYS_C;
@@ -42,6 +42,12 @@ qeth_create_device_attributes(struct device *dev);
 extern void
 qeth_remove_device_attributes(struct device *dev);
 
+extern int
+qeth_create_device_attributes_osn(struct device *dev);
+
+extern void
+qeth_remove_device_attributes_osn(struct device *dev);
+                   
 extern int
 qeth_create_driver_attributes(void);
 
@@ -108,6 +114,8 @@ qeth_get_cardname(struct qeth_card *card)
                        return " OSD Express";
                case QETH_CARD_TYPE_IQD:
                        return " HiperSockets";
+               case QETH_CARD_TYPE_OSN:
+                       return " OSN QDIO";
                default:
                        return " unknown";
                }
@@ -153,6 +161,8 @@ qeth_get_cardname_short(struct qeth_card *card)
                        }
                case QETH_CARD_TYPE_IQD:
                        return "HiperSockets";
+               case QETH_CARD_TYPE_OSN:
+                       return "OSN";
                default:
                        return "unknown";
                }
index bd28e2438d7f5168272a1ee94a4e94e46295ac81..692003c9f896fd3dc54ea8265f8c834e00a80533 100644 (file)
@@ -196,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum)
 {
        struct qeth_notify_list_struct *n_entry;
 
-
        /*check first if entry already exists*/
        spin_lock(&qeth_notify_lock);
        list_for_each_entry(n_entry, &qeth_notify_list, list) {
@@ -1024,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card)
        card->options.fake_broadcast = 0;
        card->options.add_hhlen = DEFAULT_ADD_HHLEN;
        card->options.fake_ll = 0;
-       card->options.layer2 = 0;
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               card->options.layer2 = 1;
+       else
+               card->options.layer2 = 0;
 }
 
 /**
@@ -1113,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card)
 
        QETH_DBF_TEXT(setup, 2, "detcdtyp");
 
+       card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+       card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
        while (known_devices[i][4]) {
                if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
                    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
                        card->info.type = known_devices[i][4];
+                       card->qdio.no_out_queues = known_devices[i][8];
+                       card->info.is_multicast_different = known_devices[i][9];
                        if (is_1920_device(card)) {
                                PRINT_INFO("Priority Queueing not able "
                                           "due to hardware limitations!\n");
                                card->qdio.no_out_queues = 1;
                                card->qdio.default_out_queue = 0;
-                       } else {
-                               card->qdio.no_out_queues = known_devices[i][8];
-                       }
-                       card->info.is_multicast_different = known_devices[i][9];
+                       } 
                        return 0;
                }
                i++;
@@ -1149,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev)
        if (!get_device(dev))
                return -ENODEV;
 
+       QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+       
        card = qeth_alloc_card();
        if (!card) {
                put_device(dev);
@@ -1158,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev)
        card->read.ccwdev  = gdev->cdev[0];
        card->write.ccwdev = gdev->cdev[1];
        card->data.ccwdev  = gdev->cdev[2];
-
-       if ((rc = qeth_setup_card(card))){
-               QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-               put_device(dev);
-               qeth_free_card(card);
-               return rc;
-       }
        gdev->dev.driver_data = card;
        card->gdev = gdev;
        gdev->cdev[0]->handler = qeth_irq;
        gdev->cdev[1]->handler = qeth_irq;
        gdev->cdev[2]->handler = qeth_irq;
 
-       rc = qeth_create_device_attributes(dev);
-       if (rc) {
+       if ((rc = qeth_determine_card_type(card))){
+               PRINT_WARN("%s: not a valid card type\n", __func__);
+               QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+               put_device(dev);
+               qeth_free_card(card);
+               return rc;
+       }                           
+       if ((rc = qeth_setup_card(card))){
+               QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
                put_device(dev);
                qeth_free_card(card);
                return rc;
        }
-       if ((rc = qeth_determine_card_type(card))){
-               PRINT_WARN("%s: not a valid card type\n", __func__);
-               QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+       rc = qeth_create_device_attributes(dev);
+       if (rc) {
                put_device(dev);
                qeth_free_card(card);
                return rc;
@@ -1660,6 +1664,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
                                netif_carrier_on(card->dev);
                                qeth_schedule_recovery(card);
                                return NULL;
+                       case IPA_CMD_MODCCID:
+                               return cmd;
                        case IPA_CMD_REGISTER_LOCAL_ADDR:
                                QETH_DBF_TEXT(trace,3, "irla");
                                break;
@@ -1721,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
        cmd = qeth_check_ipa_data(card, iob);
        if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
                goto out;
+       /*in case of OSN : check if cmd is set */
+       if (card->info.type == QETH_CARD_TYPE_OSN &&
+           cmd &&
+           cmd->hdr.command != IPA_CMD_STARTLAN &&
+           card->osn_info.assist_cb != NULL) {
+               card->osn_info.assist_cb(card->dev, cmd);
+               goto out;
+       }
 
        spin_lock_irqsave(&card->lock, flags);
        list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
@@ -1737,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
                                        keep_reply = reply->callback(card,
                                                        reply,
                                                        (unsigned long)cmd);
-                               }
-                               else
+                               } else
                                        keep_reply = reply->callback(card,
                                                        reply,
                                                        (unsigned long)iob);
@@ -1768,6 +1781,24 @@ out:
        qeth_release_buffer(channel,iob);
 }
 
+static inline void
+qeth_prepare_control_data(struct qeth_card *card, int len,
+struct qeth_cmd_buffer *iob)
+{
+       qeth_setup_ccw(&card->write,iob->data,len);
+       iob->callback = qeth_release_buffer;
+
+       memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+              &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+       card->seqno.trans_hdr++;
+       memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+              &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+       card->seqno.pdu_hdr++;
+       memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+              &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+       QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+                                                   
 static int
 qeth_send_control_data(struct qeth_card *card, int len,
                       struct qeth_cmd_buffer *iob,
@@ -1778,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
 {
        int rc;
        unsigned long flags;
-       struct qeth_reply *reply;
+       struct qeth_reply *reply = NULL;
        struct timer_list timer;
 
        QETH_DBF_TEXT(trace, 2, "sendctl");
 
-       qeth_setup_ccw(&card->write,iob->data,len);
-
-       memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
-              &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
-       card->seqno.trans_hdr++;
-
-       memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
-              &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
-       card->seqno.pdu_hdr++;
-       memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
-              &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
-       iob->callback = qeth_release_buffer;
-
        reply = qeth_alloc_reply(card);
        if (!reply) {
                PRINT_WARN("Could no alloc qeth_reply!\n");
@@ -1810,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len,
        init_timer(&timer);
        timer.function = qeth_cmd_timeout;
        timer.data = (unsigned long) reply;
-       if (IS_IPA(iob->data))
-               timer.expires = jiffies + QETH_IPA_TIMEOUT;
-       else
-               timer.expires = jiffies + QETH_TIMEOUT;
        init_waitqueue_head(&reply->wait_q);
        spin_lock_irqsave(&card->lock, flags);
        list_add_tail(&reply->list, &card->cmd_waiter_list);
@@ -1821,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
        QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
        wait_event(card->wait_q,
                   atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+       qeth_prepare_control_data(card, len, iob);
+       if (IS_IPA(iob->data))
+               timer.expires = jiffies + QETH_IPA_TIMEOUT;
+       else
+               timer.expires = jiffies + QETH_TIMEOUT;
        QETH_DBF_TEXT(trace, 6, "noirqpnd");
        spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
        rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1847,6 +1866,62 @@ qeth_send_control_data(struct qeth_card *card, int len,
        return rc;
 }
 
+static int
+qeth_osn_send_control_data(struct qeth_card *card, int len,
+                          struct qeth_cmd_buffer *iob)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+       wait_event(card->wait_q,
+                  atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+       qeth_prepare_control_data(card, len, iob);
+       QETH_DBF_TEXT(trace, 6, "osnoirqp");
+       spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+       rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+                             (addr_t) iob, 0, 0);
+       spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+       if (rc){
+               PRINT_WARN("qeth_osn_send_control_data: "
+                          "ccw_device_start rc = %i\n", rc);
+               QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+               qeth_release_buffer(iob->channel, iob);
+               atomic_set(&card->write.irq_pending, 0);
+               wake_up(&card->wait_q);
+       }
+       return rc;
+}                                      
+
+static inline void
+qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+                    char prot_type)
+{
+       memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+       memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+       memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+              &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+
+static int
+qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+                     int data_len)
+{
+       u16 s1, s2;
+
+QETH_DBF_TEXT(trace,4,"osndipa");
+
+       qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+       s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+       s2 = (u16)data_len;
+       memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+       memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+       memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+       memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+       return qeth_osn_send_control_data(card, s1, iob);
+}
+                                                           
 static int
 qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
                  int (*reply_cb)
@@ -1858,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
 
        QETH_DBF_TEXT(trace,4,"sendipa");
 
-       memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-
        if (card->options.layer2)
-               prot_type = QETH_PROT_LAYER2;
+               if (card->info.type == QETH_CARD_TYPE_OSN)
+                       prot_type = QETH_PROT_OSN2;
+               else
+                       prot_type = QETH_PROT_LAYER2;
        else
                prot_type = QETH_PROT_TCPIP;
-
-       memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
-       memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
-              &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-
+       qeth_prepare_ipa_cmd(card,iob,prot_type);
        rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
                                    reply_cb, reply_param);
        return rc;
@@ -2010,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card)
        *(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
                (__u8) card->info.portno;
        if (card->options.layer2)
-               prot_type = QETH_PROT_LAYER2;
+               if (card->info.type == QETH_CARD_TYPE_OSN)
+                       prot_type = QETH_PROT_OSN2;
+               else
+                       prot_type = QETH_PROT_LAYER2;
        else
                prot_type = QETH_PROT_TCPIP;
 
@@ -2100,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
 }
 
 static inline struct sk_buff *
-qeth_get_skb(unsigned int length)
+qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
 {
        struct sk_buff* skb;
+       int add_len;
+
+       add_len = 0;
+       if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+               add_len = sizeof(struct qeth_hdr);
 #ifdef CONFIG_QETH_VLAN
-       if ((skb = dev_alloc_skb(length + VLAN_HLEN)))
-               skb_reserve(skb, VLAN_HLEN);
-#else
-       skb = dev_alloc_skb(length);
+       else
+               add_len = VLAN_HLEN;
 #endif
+       skb = dev_alloc_skb(length + add_len);
+       if (skb && add_len)
+               skb_reserve(skb, add_len);
        return skb;
 }
 
@@ -2138,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
 
        offset += sizeof(struct qeth_hdr);
        if (card->options.layer2)
-               skb_len = (*hdr)->hdr.l2.pkt_length;
+               if (card->info.type == QETH_CARD_TYPE_OSN)
+                       skb_len = (*hdr)->hdr.osn.pdu_length;
+               else
+                       skb_len = (*hdr)->hdr.l2.pkt_length;
        else
                skb_len = (*hdr)->hdr.l3.length;
 
@@ -2146,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
                return NULL;
        if (card->options.fake_ll){
                if(card->dev->type == ARPHRD_IEEE802_TR){
-                       if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+                       if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
                                goto no_mem;
                        skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
                } else {
-                       if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+                       if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
                                goto no_mem;
                        skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
                }
-       } else if (!(skb = qeth_get_skb(skb_len)))
+       } else if (!(skb = qeth_get_skb(skb_len, *hdr)))
                goto no_mem;
        data_ptr = element->addr + offset;
        while (skb_len) {
@@ -2453,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card,
                skb->dev = card->dev;
                if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
                        vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
-               else
+               else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)     
                        qeth_rebuild_skb(card, skb, hdr);
+               else { /*in case of OSN*/
+                       skb_push(skb, sizeof(struct qeth_hdr));
+                       memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+               }
                /* is device UP ? */
                if (!(card->dev->flags & IFF_UP)){
                        dev_kfree_skb_any(skb);
@@ -2465,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card,
                        vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
                else
 #endif
-               rxrc = netif_rx(skb);
+               if (card->info.type == QETH_CARD_TYPE_OSN)
+                       rxrc = card->osn_info.data_cb(skb);
+               else
+                       rxrc = netif_rx(skb);
                card->dev->last_rx = jiffies;
                card->stats.rx_packets++;
                card->stats.rx_bytes += skb->len;
@@ -3150,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card)
        INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
        INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
        /* outbound */
-       card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
-       card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
 }
 
 static int
@@ -3466,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card)
 
        return 0;
 out_qdio:
-       qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE);
+       qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
        return rc;
 }
 
@@ -3491,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
        case QETH_CARD_TYPE_IQD:
                dev = alloc_netdev(0, "hsi%d", ether_setup);
                break;
+       case QETH_CARD_TYPE_OSN:
+               dev = alloc_netdev(0, "osn%d", ether_setup);
+               break;
        default:
                dev = alloc_etherdev(0);
        }
@@ -3655,7 +3747,8 @@ qeth_open(struct net_device *dev)
        if (card->state != CARD_STATE_SOFTSETUP)
                return -ENODEV;
 
-       if ( (card->options.layer2) &&
+       if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+            (card->options.layer2) &&
             (!card->info.layer2_mac_registered)) {
                QETH_DBF_TEXT(trace,4,"nomacadr");
                return -EPERM;
@@ -3693,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
 {
        int cast_type = RTN_UNSPEC;
 
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return cast_type;
+
        if (skb->dst && skb->dst->neighbour){
                cast_type = skb->dst->neighbour->type;
                if ((cast_type == RTN_BROADCAST) ||
@@ -3782,13 +3878,16 @@ static inline int
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
                 struct qeth_hdr **hdr, int ipv)
 {
-       int rc;
+       int rc = 0;
 #ifdef CONFIG_QETH_VLAN
        u16 *tag;
 #endif
 
        QETH_DBF_TEXT(trace, 6, "prepskb");
-
+       if (card->info.type == QETH_CARD_TYPE_OSN) {
+               *hdr = (struct qeth_hdr *)(*skb)->data;
+               return rc;
+       }
         rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
         if (rc)
                 return rc;
@@ -4291,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                        }
                }
        }
+       if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+               (skb->protocol == htons(ETH_P_IPV6))) {
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
        cast_type = qeth_get_cast_type(card, skb);
-       if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+       if ((cast_type == RTN_BROADCAST) && 
+           (card->info.broadcast_capable == 0)){
                card->stats.tx_dropped++;
                card->stats.tx_errors++;
                dev_kfree_skb_any(skb);
@@ -4320,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                        QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
                        return rc;
                }
-               qeth_fill_header(card, hdr, skb, ipv, cast_type);
+               if (card->info.type != QETH_CARD_TYPE_OSN)
+                       qeth_fill_header(card, hdr, skb, ipv, cast_type);
        }
 
        if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -4381,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
        case MII_BMCR: /* Basic mode control register */
                rc = BMCR_FULLDPLX;
                if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+                   (card->info.link_type != QETH_LINK_TYPE_OSN) &&
                    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
                        rc |= BMCR_SPEED100;
                break;
@@ -5004,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             (card->state != CARD_STATE_SOFTSETUP))
                return -ENODEV;
 
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return -EPERM;
+
        switch (cmd){
        case SIOC_QETH_ARP_SET_NO_ENTRIES:
                if ( !capable(CAP_NET_ADMIN) ||
@@ -5329,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev)
 {
        struct qeth_card *card = (struct qeth_card *) dev->priv;
 
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return ;
+        
        QETH_DBF_TEXT(trace,3,"setmulti");
        qeth_delete_mc_addresses(card);
        qeth_add_multicast_ipv4(card);
@@ -5370,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot)
        return addr;
 }
 
+int
+qeth_osn_assist(struct net_device *dev,
+               void *data,
+               int data_len)
+{
+       struct qeth_cmd_buffer *iob;
+       struct qeth_card *card;
+       int rc;
+       
+       QETH_DBF_TEXT(trace, 2, "osnsdmc");
+       if (!dev)
+               return -ENODEV;
+       card = (struct qeth_card *)dev->priv;
+       if (!card)
+               return -ENODEV;
+       if ((card->state != CARD_STATE_UP) &&
+           (card->state != CARD_STATE_SOFTSETUP))
+               return -ENODEV;
+       iob = qeth_wait_for_buffer(&card->write);
+       memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+       rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+       return rc;
+}
+
+static struct net_device *
+qeth_netdev_by_devno(unsigned char *read_dev_no)
+{
+       struct qeth_card *card;
+       struct net_device *ndev;
+       unsigned char *readno;
+       __u16 temp_dev_no, card_dev_no;
+       char *endp;
+       unsigned long flags;
+
+       ndev = NULL;
+       memcpy(&temp_dev_no, read_dev_no, 2);
+       read_lock_irqsave(&qeth_card_list.rwlock, flags);
+       list_for_each_entry(card, &qeth_card_list.list, list) {
+               readno = CARD_RDEV_ID(card);
+               readno += (strlen(readno) - 4);
+               card_dev_no = simple_strtoul(readno, &endp, 16);
+               if (card_dev_no == temp_dev_no) {
+                       ndev = card->dev;
+                       break;
+               }
+       }
+       read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+       return ndev;
+}
+
+int
+qeth_osn_register(unsigned char *read_dev_no,
+                 struct net_device **dev,
+                 int (*assist_cb)(struct net_device *, void *),
+                 int (*data_cb)(struct sk_buff *))
+{
+       struct qeth_card * card;
+
+       QETH_DBF_TEXT(trace, 2, "osnreg");
+       *dev = qeth_netdev_by_devno(read_dev_no);
+       if (*dev == NULL)
+               return -ENODEV;
+       card = (struct qeth_card *)(*dev)->priv;
+       if (!card)
+               return -ENODEV;
+       if ((assist_cb == NULL) || (data_cb == NULL))
+               return -EINVAL;
+       card->osn_info.assist_cb = assist_cb;
+       card->osn_info.data_cb = data_cb;
+       return 0;
+}
+
+void
+qeth_osn_deregister(struct net_device * dev)
+{
+       struct qeth_card *card;
+
+       QETH_DBF_TEXT(trace, 2, "osndereg");
+       if (!dev)
+               return;
+       card = (struct qeth_card *)dev->priv;
+       if (!card)
+               return;
+       card->osn_info.assist_cb = NULL;
+       card->osn_info.data_cb = NULL;
+       return;
+}
+                                          
 static void
 qeth_delete_mc_addresses(struct qeth_card *card)
 {
@@ -5700,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
                QETH_DBF_TEXT(trace, 3, "setmcLY3");
                return -EOPNOTSUPP;
        }
+       if (card->info.type == QETH_CARD_TYPE_OSN) {
+               PRINT_WARN("Setting MAC address on %s is not supported.\n",
+                          dev->name);
+               QETH_DBF_TEXT(trace, 3, "setmcOSN");
+               return -EOPNOTSUPP;
+       }
        QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
        QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
        rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
@@ -6076,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev)
                        qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
        dev->addr_len = OSA_ADDR_LEN;
        dev->mtu = card->info.initial_mtu;
-
-       SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-
+       if (card->info.type != QETH_CARD_TYPE_OSN)
+               SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
        SET_MODULE_OWNER(dev);
        return 0;
 }
@@ -6095,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card)
                                        QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
        } else {
                if (card->info.type == QETH_CARD_TYPE_IQD)
+               /*FIXME:why do we have same values for  dis and ena for osae??? */
                        card->info.func_level =
                                QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
                else
@@ -6124,7 +6331,7 @@ retry:
                ccw_device_set_online(CARD_WDEV(card));
                ccw_device_set_online(CARD_DDEV(card));
        }
-       rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE);
+       rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
        if (rc == -ERESTARTSYS) {
                QETH_DBF_TEXT(setup, 2, "break1");
                return rc;
@@ -6176,8 +6383,8 @@ retry:
        card->dev = qeth_get_netdevice(card->info.type,
                                       card->info.link_type);
        if (!card->dev){
-               qeth_qdio_clear_card(card, card->info.type ==
-                                    QETH_CARD_TYPE_OSAE);
+               qeth_qdio_clear_card(card, card->info.type !=
+                                    QETH_CARD_TYPE_IQD);
                rc = -ENODEV;
                QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
                goto out;
@@ -7084,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card)
                        return rc;
        } else
                card->lan_online = 1;
+       if (card->info.type==QETH_CARD_TYPE_OSN)
+               goto out;
        if (card->options.layer2) {
                card->dev->features |=
                        NETIF_F_HW_VLAN_FILTER |
@@ -7255,7 +7464,8 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
        if (card->read.state == CH_STATE_UP &&
            card->write.state == CH_STATE_UP &&
            (card->state == CARD_STATE_UP)) {
-               if(recovery_mode) {
+               if (recovery_mode && 
+                   card->info.type != QETH_CARD_TYPE_OSN) {
                        qeth_stop(card->dev);
                } else {
                        rtnl_lock();
@@ -7437,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
 {
        QETH_DBF_TEXT(setup ,2, "startag");
 
-       if(recovery_mode) {
+       if (recovery_mode && 
+           card->info.type != QETH_CARD_TYPE_OSN) {
                qeth_open(card->dev);
        } else {
                rtnl_lock();
@@ -7469,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
 static void qeth_make_parameters_consistent(struct qeth_card *card)
 {
 
-        if (card->options.layer2) {
-                if (card->info.type == QETH_CARD_TYPE_IQD) {
-                        PRINT_ERR("Device %s does not support " \
-                                  "layer 2 functionality. "  \
-                                  "Ignoring layer2 option.\n",CARD_BUS_ID(card));
-                }
-                IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
-                                 "Routing options are");
+       if (card->options.layer2 == 0)
+               return;
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return;
+       if (card->info.type == QETH_CARD_TYPE_IQD) {
+                       PRINT_ERR("Device %s does not support layer 2 functionality." \
+                         " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+                       card->options.layer2 = 0;
+               return;
+       }
+               IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+                                "Routing options are");
 #ifdef CONFIG_QETH_IPV6
-                IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
-                                 "Routing options are");
+               IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+                                "Routing options are");
 #endif
-                IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
-                                QETH_CHECKSUM_DEFAULT,
-                                "Checksumming options are");
-                IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
-                                 QETH_TR_BROADCAST_ALLRINGS,
-                                 "Broadcast mode options are");
-                IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
-                                 QETH_TR_MACADDR_NONCANONICAL,
-                                 "Canonical MAC addr options are");
-                IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
-                                "Broadcast faking options are");
-                IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
-                                 DEFAULT_ADD_HHLEN,"Option add_hhlen is");
-                IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
-        }
+               IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+                               QETH_CHECKSUM_DEFAULT,
+                               "Checksumming options are");
+               IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+                                QETH_TR_BROADCAST_ALLRINGS,
+                                "Broadcast mode options are");
+               IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+                                QETH_TR_MACADDR_NONCANONICAL,
+                                "Canonical MAC addr options are");
+               IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+                        "Broadcast faking options are");
+               IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+                                DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+        IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
 }
 
 
@@ -7525,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
                return -EIO;
        }
 
-       if (card->options.layer2)
-               qeth_make_parameters_consistent(card);
+       qeth_make_parameters_consistent(card);
 
        if ((rc = qeth_hardsetup_card(card))){
                QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
@@ -7585,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev)
 static struct ccw_device_id qeth_ids[] = {
        {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
        {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+       {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
        {},
 };
 MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -8329,6 +8543,9 @@ again:
        printk("qeth: removed\n");
 }
 
+EXPORT_SYMBOL(qeth_osn_register);
+EXPORT_SYMBOL(qeth_osn_deregister);
+EXPORT_SYMBOL(qeth_osn_assist);
 module_init(qeth_init);
 module_exit(qeth_exit);
 MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
index f685ecc7da99dc8dbca4ac61a5ab63cfb6c7683a..30e053d3cac2932ef90c679c5d3db4024c8bd660 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/cio.h>
 #include "qeth_mpc.h"
 
-const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
+const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $";
 
 unsigned char IDX_ACTIVATE_READ[]={
        0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
@@ -138,7 +138,9 @@ unsigned char IPA_PDU_HEADER[]={
                sizeof(struct qeth_ipa_cmd)%256,
        0x00,
                sizeof(struct qeth_ipa_cmd)/256,
-               sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+               sizeof(struct qeth_ipa_cmd)%256,
+       0x05,
+       0x77,0x77,0x77,0x77,
        0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
        0x01,0x00,
                sizeof(struct qeth_ipa_cmd)/256,
index 3d916b5c5d09c4a4f0b2b0d697938481b8cd9dc6..7edc5f1fc0d24da927ac81bc2ebe01fe1b57fc79 100644 (file)
@@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[];
 /* IP Assist related definitions                                             */
 /*****************************************************************************/
 #define IPA_CMD_INITIATOR_HOST  0x00
-#define IPA_CMD_INITIATOR_HYDRA 0x01
+#define IPA_CMD_INITIATOR_OSA   0x01
+#define IPA_CMD_INITIATOR_HOST_REPLY  0x80
+#define IPA_CMD_INITIATOR_OSA_REPLY   0x81
 #define IPA_CMD_PRIM_VERSION_NO 0x01
 
 enum qeth_card_types {
        QETH_CARD_TYPE_UNKNOWN = 0,
        QETH_CARD_TYPE_OSAE    = 10,
        QETH_CARD_TYPE_IQD     = 1234,
+       QETH_CARD_TYPE_OSN     = 11,
 };
 
 #define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -61,6 +64,7 @@ enum qeth_link_types {
        QETH_LINK_TYPE_FAST_ETH     = 0x01,
        QETH_LINK_TYPE_HSTR         = 0x02,
        QETH_LINK_TYPE_GBIT_ETH     = 0x03,
+       QETH_LINK_TYPE_OSN          = 0x04,
        QETH_LINK_TYPE_10GBIT_ETH   = 0x10,
        QETH_LINK_TYPE_LANE_ETH100  = 0x81,
        QETH_LINK_TYPE_LANE_TR      = 0x82,
@@ -111,6 +115,9 @@ enum qeth_ipa_cmds {
        IPA_CMD_DELGMAC               = 0x24,
        IPA_CMD_SETVLAN               = 0x25,
        IPA_CMD_DELVLAN               = 0x26,
+       IPA_CMD_SETCCID               = 0x41,
+       IPA_CMD_DELCCID               = 0x42,
+       IPA_CMD_MODCCID               = 0x43,
        IPA_CMD_SETIP                 = 0xb1,
        IPA_CMD_DELIP                 = 0xb7,
        IPA_CMD_QIPASSIST             = 0xb2,
@@ -437,8 +444,9 @@ enum qeth_ipa_arp_return_codes {
 #define QETH_ARP_DATA_SIZE 3968
 #define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
 /* Helper functions */
-#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
-
+#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+                          (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+       
 /*****************************************************************************/
 /* END OF   IP Assist related definitions                                    */
 /*****************************************************************************/
@@ -483,6 +491,7 @@ extern unsigned char ULP_ENABLE[];
 /* Layer 2 defintions */
 #define QETH_PROT_LAYER2 0x08
 #define QETH_PROT_TCPIP  0x03
+#define QETH_PROT_OSN2   0x0a     
 #define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
 #define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
 
index dda105b73063d09a7091b25c627c1c28e05985ed..f91a02db57437b57f0603294d8da9fc9e07eb222 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -20,7 +20,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
 
 /*****************************************************************************/
 /*                                                                           */
@@ -937,6 +937,19 @@ static struct attribute_group qeth_device_attr_group = {
        .attrs = (struct attribute **)qeth_device_attrs,
 };
 
+static struct device_attribute * qeth_osn_device_attrs[] = {
+       &dev_attr_state,
+       &dev_attr_chpid,
+       &dev_attr_if_name,
+       &dev_attr_card_type,
+       &dev_attr_buffer_count,
+       &dev_attr_recover,
+       NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+       .attrs = (struct attribute **)qeth_osn_device_attrs,
+};
 
 #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)                      \
 struct device_attribute dev_attr_##_id = {                                  \
@@ -1667,7 +1680,12 @@ int
 qeth_create_device_attributes(struct device *dev)
 {
        int ret;
+       struct qeth_card *card = dev->driver_data;
 
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return sysfs_create_group(&dev->kobj,
+                                         &qeth_osn_device_attr_group);
+       
        if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
                return ret;
        if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1693,6 +1711,12 @@ qeth_create_device_attributes(struct device *dev)
 void
 qeth_remove_device_attributes(struct device *dev)
 {
+       struct qeth_card *card = dev->driver_data;
+
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return sysfs_remove_group(&dev->kobj,
+                                         &qeth_osn_device_attr_group);
+                     
        sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
        sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
        sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
index ac3dfc7af5b0e9b78a4d663e8d8855fe2096eb9c..fcec52bafb25ddd01c4c6589a33d5183c3cbe325 100644 (file)
@@ -128,26 +128,26 @@ struct hpc3_ethregs {
        volatile u32 rx_gfptr;  /* current GIO fifo ptr */
        volatile u32 rx_dfptr;  /* current device fifo ptr */
        u32 _unused1;           /* padding */
-       volatile u32 rx_reset;  /* reset register */
-#define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */
-#define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */
-#define HPC3_ERXRST_LBACK  0x4 /* Enable diagnostic loopback mode of Seeq8003 */
-
-       volatile u32 rx_dconfig;        /* DMA configuration register */
-#define HPC3_ERXDCFG_D1    0x0000f /* Cycles to spend in D1 state for PIO */
-#define HPC3_ERXDCFG_D2    0x000f0 /* Cycles to spend in D2 state for PIO */
-#define HPC3_ERXDCFG_D3    0x00f00 /* Cycles to spend in D3 state for PIO */
-#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
-#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
-#define HPC3_ERXDCFG_FEOP  0x04000 /* Bad packet marker timeout enable */
-#define HPC3_ERXDCFG_FIRQ  0x08000 /* Another bad packet timeout enable */
-#define HPC3_ERXDCFG_PTO   0x30000 /* Programmed timeout value for above two */
-
-       volatile u32 rx_pconfig;        /* PIO configuration register */
-#define HPC3_ERXPCFG_P1    0x000f /* Cycles to spend in P1 state for PIO */
-#define HPC3_ERXPCFG_P2    0x00f0 /* Cycles to spend in P2 state for PIO */
-#define HPC3_ERXPCFG_P3    0x0f00 /* Cycles to spend in P3 state for PIO */
-#define HPC3_ERXPCFG_TST   0x1000 /* Diagnistic ram test feature bit */
+       volatile u32 reset;     /* reset register */
+#define HPC3_ERST_CRESET 0x1   /* Reset dma channel and external controller */
+#define HPC3_ERST_CLRIRQ 0x2   /* Clear channel interrupt */
+#define HPC3_ERST_LBACK  0x4   /* Enable diagnostic loopback mode of Seeq8003 */
+
+       volatile u32 dconfig;    /* DMA configuration register */
+#define HPC3_EDCFG_D1    0x0000f /* Cycles to spend in D1 state for PIO */
+#define HPC3_EDCFG_D2    0x000f0 /* Cycles to spend in D2 state for PIO */
+#define HPC3_EDCFG_D3    0x00f00 /* Cycles to spend in D3 state for PIO */
+#define HPC3_EDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
+#define HPC3_EDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
+#define HPC3_EDCFG_FEOP  0x04000 /* Bad packet marker timeout enable */
+#define HPC3_EDCFG_FIRQ  0x08000 /* Another bad packet timeout enable */
+#define HPC3_EDCFG_PTO   0x30000 /* Programmed timeout value for above two */
+
+       volatile u32 pconfig;   /* PIO configuration register */
+#define HPC3_EPCFG_P1    0x000f /* Cycles to spend in P1 state for PIO */
+#define HPC3_EPCFG_P2    0x00f0 /* Cycles to spend in P2 state for PIO */
+#define HPC3_EPCFG_P3    0x0f00 /* Cycles to spend in P3 state for PIO */
+#define HPC3_EPCFG_TST   0x1000 /* Diagnistic ram test feature bit */
 
        u32 _unused2[0x1000/4 - 8];     /* padding */
 
index 04fa7dff079c42225eb4caf97d4f29cfe65963e8..300d704bdb9a5416b781b955f0c7172a6451d269 100644 (file)
@@ -37,8 +37,6 @@
 #include <linux/cycx_x25.h>
 #endif
 
-#define        is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
-
 /* Adapter Data Space.
  * This structure is needed because we handle multiple cards, otherwise
  * static data would do it.
index 6621df86a7487745fca4b447900b59431f5d3b2e..12fe6b0bfcff8e45de8b52b2710543a4a7da7c20 100644 (file)
@@ -60,6 +60,5 @@ extern int cycx_peek(struct cycx_hw *hw, u32 addr, void *buf, u32 len);
 extern int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len);
 extern int cycx_exec(void __iomem *addr);
 
-extern void cycx_inten(struct cycx_hw *hw);
 extern void cycx_intr(struct cycx_hw *hw);
 #endif /* _CYCX_DRV_H */
index 2ef0b21517fbd20f56fe85c43aa5c7c14786c2c8..1c7a0dd5536aca7e8d2a1527ec60e48b0d26736c 100644 (file)
@@ -7,8 +7,8 @@
 /* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */
 
 #define TR_RETRY_INTERVAL      (30*HZ) /* 500 on PC = 5 s */
-#define TR_RST_TIME            (HZ/20) /* 5 on PC = 50 ms */
-#define TR_BUSY_INTERVAL       (HZ/5)  /* 5 on PC = 200 ms */
+#define TR_RST_TIME            (msecs_to_jiffies(50))  /* 5 on PC = 50 ms */
+#define TR_BUSY_INTERVAL       (msecs_to_jiffies(200)) /* 5 on PC = 200 ms */
 #define TR_SPIN_INTERVAL       (3*HZ)  /* 3 seconds before init timeout */
 
 #define TR_ISA 1
index 0856548a2a08b2eadab1b6e9de56dfc667993673..a8b1a2071838f70794fc7605b0b44f5def7f44d4 100644 (file)
@@ -84,6 +84,7 @@
 #define ARPHRD_IEEE802_TR 800          /* Magic type ident for TR      */
 #define ARPHRD_IEEE80211 801           /* IEEE 802.11                  */
 #define ARPHRD_IEEE80211_PRISM 802     /* IEEE 802.11 + Prism2 header  */
+#define ARPHRD_IEEE80211_RADIOTAP 803  /* IEEE 802.11 + radiotap header */
 
 #define ARPHRD_VOID      0xFFFF        /* Void type, nothing is known */
 #define ARPHRD_NONE      0xFFFE        /* zero header length */
index 9b8d0476988ad3bb1aa9bfeeae74b9d8b1a6f57f..68f5a0f392dd969a9e063a2e835ecced5ba1c61f 100644 (file)
@@ -158,6 +158,7 @@ extern int mii_link_ok (struct mii_if_info *mii);
 extern int mii_nway_restart (struct mii_if_info *mii);
 extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
 extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_check_gmii_support(struct mii_if_info *mii);
 extern void mii_check_link (struct mii_if_info *mii);
 extern unsigned int mii_check_media (struct mii_if_info *mii,
                                     unsigned int ok_to_print,
index 368e4c825ff1b5006adfe8a962083500a6776e0c..a9281b24c40b8bfa748899dad4c5e17574e4aaaf 100644 (file)
@@ -873,11 +873,9 @@ static inline void netif_rx_complete(struct net_device *dev)
 
 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 78f634007fc6b88d09ddf1ffde90cea1e7c58f72..c85e103d5e7b664d9f0d3ad005175705f4ee3bce 100644 (file)
@@ -52,12 +52,8 @@ typedef struct sdlahw
 
 extern int sdla_setup  (sdlahw_t* hw, void* sfm, unsigned len);
 extern int sdla_down   (sdlahw_t* hw);
-extern int sdla_inten  (sdlahw_t* hw);
-extern int sdla_intde  (sdlahw_t* hw);
-extern int sdla_intack (sdlahw_t* hw);
 extern void S514_intack  (sdlahw_t* hw, u32 int_status);
 extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
-extern int sdla_intr   (sdlahw_t* hw);
 extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
 extern int sdla_peek   (sdlahw_t* hw, unsigned long addr, void* buf,
                         unsigned len);
index 167d956c492b12d484697dca5376b4855b37de86..dae9860091ddc8c99d472979b54b68577ac321ba 100644 (file)
@@ -265,15 +265,6 @@ typedef struct {
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 
-
-#define        is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
-#define        is_alpha(ch) ((((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'z')||\
-                 ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'Z'))?1:0)
-#define        is_hex_digit(ch) ((((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')||\
-                 ((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'f')||\
-                 ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'F'))?1:0)
-
-
 /****** Data Structures *****************************************************/
 
 /* Adapter Data Space.
index dc36b1be6745ac7c8b2e8e28810b9b99bc49de66..58f62224e7ea1c1ae79c4acab252d040e0db37ae 100644 (file)
  *
  * Adaption to a generic IEEE 802.11 stack by James Ketrenos
  * <jketreno@linux.intel.com>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation. See README and COPYING for
  * more details.
+ *
+ * API Version History
+ * 1.0.x -- Initial version
+ * 1.1.x -- Added radiotap, QoS, TIM, ieee80211_geo APIs,
+ *          various structure changes, and crypto API init method
  */
 #ifndef IEEE80211_H
 #define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h>   /* ARRAY_SIZE */
+#include <linux/if_ether.h>    /* ETH_ALEN */
+#include <linux/kernel.h>      /* ARRAY_SIZE */
 #include <linux/wireless.h>
 
+#define IEEE80211_VERSION "git-1.1.5"
+
 #define IEEE80211_DATA_LEN             2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
    6.2.1.1.2.
    represents the 2304 bytes of real data, plus a possible 8 bytes of
    WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
 
-
-#define IEEE80211_HLEN                 30
-#define IEEE80211_FRAME_LEN            (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct ieee80211_hdr {
-       __le16 frame_ctl;
-       __le16 duration_id;
-       u8 addr1[ETH_ALEN];
-       u8 addr2[ETH_ALEN];
-       u8 addr3[ETH_ALEN];
-       __le16 seq_ctl;
-       u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addr {
-       __le16 frame_ctl;
-       __le16 duration_id;
-       u8 addr1[ETH_ALEN];
-       u8 addr2[ETH_ALEN];
-       u8 addr3[ETH_ALEN];
-       __le16 seq_ctl;
-} __attribute__ ((packed));
-
 #define IEEE80211_1ADDR_LEN 10
 #define IEEE80211_2ADDR_LEN 16
 #define IEEE80211_3ADDR_LEN 24
 #define IEEE80211_4ADDR_LEN 30
 #define IEEE80211_FCS_LEN    4
+#define IEEE80211_HLEN                 (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN            (IEEE80211_DATA_LEN + IEEE80211_HLEN)
 
 #define MIN_FRAG_THRESHOLD     256U
 #define        MAX_FRAG_THRESHOLD     2346U
@@ -113,11 +99,11 @@ struct ieee80211_hdr_3addr {
 #define IEEE80211_STYPE_CFACK          0x0050
 #define IEEE80211_STYPE_CFPOLL         0x0060
 #define IEEE80211_STYPE_CFACKPOLL      0x0070
+#define IEEE80211_STYPE_QOS_DATA        0x0080
 
 #define IEEE80211_SCTL_FRAG            0x000F
 #define IEEE80211_SCTL_SEQ             0xFFF0
 
-
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -128,8 +114,7 @@ do { if (ieee80211_debug_level & (level)) \
          in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 #else
 #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#endif /* CONFIG_IEEE80211_DEBUG */
-
+#endif                         /* CONFIG_IEEE80211_DEBUG */
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
@@ -140,7 +125,6 @@ do { if (ieee80211_debug_level & (level)) \
  * messages. It should never be used for passing essid to user space. */
 const char *escape_essid(const char *essid, u8 essid_len);
 
-
 /*
  * To use the debug system:
  *
@@ -177,6 +161,7 @@ const char *escape_essid(const char *essid, u8 essid_len);
 
 #define IEEE80211_DL_TX            (1<<8)
 #define IEEE80211_DL_RX            (1<<9)
+#define IEEE80211_DL_QOS           (1<<31)
 
 #define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
 #define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
@@ -190,9 +175,10 @@ const char *escape_essid(const char *essid, u8 essid_len);
 #define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
 #define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
 #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+#define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <linux/if_arp.h>      /* ARPHRD_ETHER */
 
 #ifndef WIRELESS_SPY
 #define WIRELESS_SPY           /* enable iwspy support */
@@ -200,10 +186,10 @@ const char *escape_essid(const char *essid, u8 essid_len);
 #include <net/iw_handler.h>    /* new driver API */
 
 #ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
+#define ETH_P_PAE 0x888E       /* Port Access Entity (IEEE 802.1X) */
+#endif                         /* ETH_P_PAE */
 
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+#define ETH_P_PREAUTH 0x88C7   /* IEEE 802.11i pre-authentication */
 
 #ifndef ETH_P_80211_RAW
 #define ETH_P_80211_RAW (ETH_P_ECONET + 1)
@@ -215,10 +201,10 @@ const char *escape_essid(const char *essid, u8 essid_len);
 
 struct ieee80211_snap_hdr {
 
-        u8    dsap;   /* always 0xAA */
-        u8    ssap;   /* always 0xAA */
-        u8    ctrl;   /* always 0x03 */
-        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+       u8 dsap;                /* always 0xAA */
+       u8 ssap;                /* always 0xAA */
+       u8 ctrl;                /* always 0x03 */
+       u8 oui[P80211_OUI_LEN]; /* organizational universal id */
 
 } __attribute__ ((packed));
 
@@ -246,8 +232,9 @@ struct ieee80211_snap_hdr {
 #define WLAN_CAPABILITY_PBCC (1<<6)
 #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
 #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_QOS (1<<9)
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
-#define WLAN_CAPABILITY_OSSS_OFDM (1<<13)
+#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
 
 /* Status codes */
 enum ieee80211_statuscode {
@@ -312,14 +299,12 @@ enum ieee80211_reasoncode {
        WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
 };
 
-
 #define IEEE80211_STATMASK_SIGNAL (1<<0)
 #define IEEE80211_STATMASK_RSSI (1<<1)
 #define IEEE80211_STATMASK_NOISE (1<<2)
 #define IEEE80211_STATMASK_RATE (1<<3)
 #define IEEE80211_STATMASK_WEMASK 0x7
 
-
 #define IEEE80211_CCK_MODULATION    (1<<0)
 #define IEEE80211_OFDM_MODULATION   (1<<1)
 
@@ -377,9 +362,6 @@ enum ieee80211_reasoncode {
 #define IEEE80211_NUM_CCK_RATES                    4
 #define IEEE80211_OFDM_SHIFT_MASK_A         4
 
-
-
-
 /* NOTE: This data is for statistical purposes; not all hardware provides this
  *       information for frames received.  Not setting these will not cause
  *       any adverse affects. */
@@ -388,7 +370,7 @@ struct ieee80211_rx_stats {
        s8 rssi;
        u8 signal;
        u8 noise;
-       u16 rate; /* in 100 kbps */
+       u16 rate;               /* in 100 kbps */
        u8 received_channel;
        u8 control;
        u8 mask;
@@ -439,38 +421,44 @@ struct ieee80211_device;
 
 #include "ieee80211_crypt.h"
 
-#define SEC_KEY_1         (1<<0)
-#define SEC_KEY_2         (1<<1)
-#define SEC_KEY_3         (1<<2)
-#define SEC_KEY_4         (1<<3)
-#define SEC_ACTIVE_KEY    (1<<4)
-#define SEC_AUTH_MODE     (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL         (1<<7)
-#define SEC_ENABLED       (1<<8)
-
-#define SEC_LEVEL_0      0 /* None */
-#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
-
-#define WEP_KEYS 4
-#define WEP_KEY_LEN 13
+#define SEC_KEY_1              (1<<0)
+#define SEC_KEY_2              (1<<1)
+#define SEC_KEY_3              (1<<2)
+#define SEC_KEY_4              (1<<3)
+#define SEC_ACTIVE_KEY         (1<<4)
+#define SEC_AUTH_MODE          (1<<5)
+#define SEC_UNICAST_GROUP      (1<<6)
+#define SEC_LEVEL              (1<<7)
+#define SEC_ENABLED            (1<<8)
+#define SEC_ENCRYPT            (1<<9)
+
+#define SEC_LEVEL_0            0       /* None */
+#define SEC_LEVEL_1            1       /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2            2       /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP       3       /* Level 1 + CKIP */
+#define SEC_LEVEL_3            4       /* Level 2 + CCMP */
+
+#define SEC_ALG_NONE           0
+#define SEC_ALG_WEP            1
+#define SEC_ALG_TKIP           2
+#define SEC_ALG_CCMP           3
+
+#define WEP_KEYS               4
+#define WEP_KEY_LEN            13
+#define SCM_KEY_LEN            32
+#define SCM_TEMPORAL_KEY_LENGTH        16
 
 struct ieee80211_security {
        u16 active_key:2,
-            enabled:1,
-           auth_mode:2,
-            auth_algo:4,
-            unicast_uses_group:1;
+           enabled:1,
+           auth_mode:2, auth_algo:4, unicast_uses_group:1, encrypt:1;
+       u8 encode_alg[WEP_KEYS];
        u8 key_sizes[WEP_KEYS];
-       u8 keys[WEP_KEYS][WEP_KEY_LEN];
+       u8 keys[WEP_KEYS][SCM_KEY_LEN];
        u8 level;
        u16 flags;
 } __attribute__ ((packed));
 
-
 /*
 
  802.11 data frame from AP
@@ -494,7 +482,7 @@ enum ieee80211_mfie {
        MFIE_TYPE_RATES = 1,
        MFIE_TYPE_FH_SET = 2,
        MFIE_TYPE_DS_SET = 3,
-       MFIE_TYPE_CF_SET =  4,
+       MFIE_TYPE_CF_SET = 4,
        MFIE_TYPE_TIM = 5,
        MFIE_TYPE_IBSS_SET = 6,
        MFIE_TYPE_COUNTRY = 7,
@@ -516,11 +504,75 @@ enum ieee80211_mfie {
        MFIE_TYPE_RSN = 48,
        MFIE_TYPE_RATES_EX = 50,
        MFIE_TYPE_GENERIC = 221,
+       MFIE_TYPE_QOS_PARAMETER = 222,
 };
 
-struct ieee80211_info_element_hdr {
-       u8 id;
-       u8 len;
+/* Minimal header; can be used for passing 802.11 frames with sufficient
+ * information to determine what type of underlying data type is actually
+ * stored in the data. */
+struct ieee80211_hdr {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_1addr {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_2addr {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addr {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       __le16 seq_ctl;
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addr {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       __le16 seq_ctl;
+       u8 addr4[ETH_ALEN];
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addrqos {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       __le16 seq_ctl;
+       u8 payload[0];
+       __le16 qos_ctl;
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addrqos {
+       __le16 frame_ctl;
+       __le16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       __le16 seq_ctl;
+       u8 addr4[ETH_ALEN];
+       u8 payload[0];
+       __le16 qos_ctl;
 } __attribute__ ((packed));
 
 struct ieee80211_info_element {
@@ -546,49 +598,77 @@ struct ieee80211_info_element {
        u16 status;
 */
 
-struct ieee80211_authentication {
+struct ieee80211_auth {
        struct ieee80211_hdr_3addr header;
        __le16 algorithm;
        __le16 transaction;
        __le16 status;
-       struct ieee80211_info_element info_element;
+       /* challenge */
+       struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
+struct ieee80211_disassoc {
+       struct ieee80211_hdr_3addr header;
+       __le16 reason;
+} __attribute__ ((packed));
+
+/* Alias deauth for disassoc */
+#define ieee80211_deauth ieee80211_disassoc
+
+struct ieee80211_probe_request {
+       struct ieee80211_hdr_3addr header;
+       /* SSID, supported rates */
+       struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
 
 struct ieee80211_probe_response {
        struct ieee80211_hdr_3addr header;
        u32 time_stamp[2];
        __le16 beacon_interval;
        __le16 capability;
-       struct ieee80211_info_element info_element;
+       /* SSID, supported rates, FH params, DS params,
+        * CF params, IBSS params, TIM (if beacon), RSN */
+       struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_request_frame {
+/* Alias beacon for probe_response */
+#define ieee80211_beacon ieee80211_probe_response
+
+struct ieee80211_assoc_request {
+       struct ieee80211_hdr_3addr header;
+       __le16 capability;
+       __le16 listen_interval;
+       /* SSID, supported rates, RSN */
+       struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct ieee80211_reassoc_request {
+       struct ieee80211_hdr_3addr header;
        __le16 capability;
        __le16 listen_interval;
        u8 current_ap[ETH_ALEN];
-       struct ieee80211_info_element info_element;
+       struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_response_frame {
+struct ieee80211_assoc_response {
        struct ieee80211_hdr_3addr header;
        __le16 capability;
        __le16 status;
        __le16 aid;
-       struct ieee80211_info_element info_element; /* supported rates */
+       /* supported rates */
+       struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-
 struct ieee80211_txb {
        u8 nr_frags;
        u8 encrypted;
-       u16 reserved;
-       u16 frag_size;
-       u16 payload_size;
+       u8 rts_included;
+       u8 reserved;
+       __le16 frag_size;
+       __le16 payload_size;
        struct sk_buff *fragments[0];
 };
 
-
 /* SWEEP TABLE ENTRIES NUMBER */
 #define MAX_SWEEP_TAB_ENTRIES            42
 #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
@@ -604,9 +684,68 @@ struct ieee80211_txb {
 
 #define MAX_WPA_IE_LEN 64
 
-#define NETWORK_EMPTY_ESSID (1<<0)
-#define NETWORK_HAS_OFDM    (1<<1)
-#define NETWORK_HAS_CCK     (1<<2)
+#define NETWORK_EMPTY_ESSID    (1<<0)
+#define NETWORK_HAS_OFDM       (1<<1)
+#define NETWORK_HAS_CCK        (1<<2)
+
+/* QoS structure */
+#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
+#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
+#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
+
+#define QOS_QUEUE_NUM                   4
+#define QOS_OUI_LEN                     3
+#define QOS_OUI_TYPE                    2
+#define QOS_ELEMENT_ID                  221
+#define QOS_OUI_INFO_SUB_TYPE           0
+#define QOS_OUI_PARAM_SUB_TYPE          1
+#define QOS_VERSION_1                   1
+#define QOS_AIFSN_MIN_VALUE             2
+
+struct ieee80211_qos_information_element {
+       u8 elementID;
+       u8 length;
+       u8 qui[QOS_OUI_LEN];
+       u8 qui_type;
+       u8 qui_subtype;
+       u8 version;
+       u8 ac_info;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_ac_parameter {
+       u8 aci_aifsn;
+       u8 ecw_min_max;
+       __le16 tx_op_limit;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameter_info {
+       struct ieee80211_qos_information_element info_element;
+       u8 reserved;
+       struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameters {
+       __le16 cw_min[QOS_QUEUE_NUM];
+       __le16 cw_max[QOS_QUEUE_NUM];
+       u8 aifs[QOS_QUEUE_NUM];
+       u8 flag[QOS_QUEUE_NUM];
+       __le16 tx_op_limit[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_data {
+       struct ieee80211_qos_parameters parameters;
+       int active;
+       int supported;
+       u8 param_count;
+       u8 old_param_count;
+};
+
+struct ieee80211_tim_parameters {
+       u8 tim_count;
+       u8 tim_period;
+} __attribute__ ((packed));
+
+/*******************************************************/
 
 struct ieee80211_network {
        /* These entries are used to identify a unique network */
@@ -616,6 +755,8 @@ struct ieee80211_network {
        u8 ssid[IW_ESSID_MAX_SIZE + 1];
        u8 ssid_len;
 
+       struct ieee80211_qos_data qos_data;
+
        /* These are network statistics */
        struct ieee80211_rx_stats stats;
        u16 capability;
@@ -631,10 +772,12 @@ struct ieee80211_network {
        u16 beacon_interval;
        u16 listen_interval;
        u16 atim_window;
+       u8 erp_value;
        u8 wpa_ie[MAX_WPA_IE_LEN];
        size_t wpa_ie_len;
        u8 rsn_ie[MAX_WPA_IE_LEN];
        size_t rsn_ie_len;
+       struct ieee80211_tim_parameters tim;
        struct list_head list;
 };
 
@@ -651,17 +794,52 @@ enum ieee80211_state {
 #define DEFAULT_MAX_SCAN_AGE (15 * HZ)
 #define DEFAULT_FTS 2346
 
-
 #define CFG_IEEE80211_RESERVE_FCS (1<<0)
 #define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+#define CFG_IEEE80211_RTS (1<<2)
+
+#define IEEE80211_24GHZ_MIN_CHANNEL 1
+#define IEEE80211_24GHZ_MAX_CHANNEL 14
+#define IEEE80211_24GHZ_CHANNELS    14
+
+#define IEEE80211_52GHZ_MIN_CHANNEL 36
+#define IEEE80211_52GHZ_MAX_CHANNEL 165
+#define IEEE80211_52GHZ_CHANNELS    32
+
+enum {
+       IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+       IEEE80211_CH_B_ONLY = (1 << 2),
+       IEEE80211_CH_NO_IBSS = (1 << 3),
+       IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
+       IEEE80211_CH_RADAR_DETECT = (1 << 5),
+       IEEE80211_CH_INVALID = (1 << 6),
+};
+
+struct ieee80211_channel {
+       u32 freq;
+       u8 channel;
+       u8 flags;
+       u8 max_power;
+};
+
+struct ieee80211_geo {
+       u8 name[4];
+       u8 bg_channels;
+       u8 a_channels;
+       struct ieee80211_channel bg[IEEE80211_24GHZ_CHANNELS];
+       struct ieee80211_channel a[IEEE80211_52GHZ_CHANNELS];
+};
 
 struct ieee80211_device {
        struct net_device *dev;
+       struct ieee80211_security sec;
 
        /* Bookkeeping structures */
        struct net_device_stats stats;
        struct ieee80211_stats ieee_stats;
 
+       struct ieee80211_geo geo;
+
        /* Probe / Beacon management */
        struct list_head network_free_list;
        struct list_head network_list;
@@ -669,62 +847,102 @@ struct ieee80211_device {
        int scans;
        int scan_age;
 
-       int iw_mode; /* operating mode (IW_MODE_*) */
+       int iw_mode;            /* operating mode (IW_MODE_*) */
+       struct iw_spy_data spy_data;    /* iwspy support */
 
        spinlock_t lock;
 
-       int tx_headroom; /* Set to size of any additional room needed at front
-                         * of allocated Tx SKBs */
+       int tx_headroom;        /* Set to size of any additional room needed at front
+                                * of allocated Tx SKBs */
        u32 config;
 
        /* WEP and other encryption related settings at the device level */
-       int open_wep; /* Set to 1 to allow unencrypted frames */
+       int open_wep;           /* Set to 1 to allow unencrypted frames */
 
-       int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+       int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
                                 * WEP key changes */
 
        /* If the host performs {en,de}cryption, then set to 1 */
        int host_encrypt;
+       int host_encrypt_msdu;
        int host_decrypt;
-       int ieee802_1x; /* is IEEE 802.1X used */
+       /* host performs multicast decryption */
+       int host_mc_decrypt;
+
+       int host_open_frag;
+       int host_build_iv;
+       int ieee802_1x;         /* is IEEE 802.1X used */
 
        /* WPA data */
        int wpa_enabled;
        int drop_unencrypted;
-       int tkip_countermeasures;
        int privacy_invoked;
        size_t wpa_ie_len;
        u8 *wpa_ie;
 
        struct list_head crypt_deinit_list;
        struct ieee80211_crypt_data *crypt[WEP_KEYS];
-       int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+       int tx_keyidx;          /* default TX key index (crypt[tx_keyidx]) */
        struct timer_list crypt_deinit_timer;
+       int crypt_quiesced;
 
-       int bcrx_sta_key; /* use individual keys to override default keys even
-                          * with RX of broad/multicast frames */
+       int bcrx_sta_key;       /* use individual keys to override default keys even
+                                * with RX of broad/multicast frames */
 
        /* Fragmentation structures */
        struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
        unsigned int frag_next_idx;
-       u16 fts; /* Fragmentation Threshold */
+       u16 fts;                /* Fragmentation Threshold */
+       u16 rts;                /* RTS threshold */
 
        /* Association info */
        u8 bssid[ETH_ALEN];
 
        enum ieee80211_state state;
 
-       int mode;       /* A, B, G */
-       int modulation; /* CCK, OFDM */
-       int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
-       int abg_ture;   /* ABG flag              */
+       int mode;               /* A, B, G */
+       int modulation;         /* CCK, OFDM */
+       int freq_band;          /* 2.4Ghz, 5.2Ghz, Mixed */
+       int abg_true;           /* ABG flag              */
+
+       int perfect_rssi;
+       int worst_rssi;
 
        /* Callback functions */
-       void (*set_security)(struct net_device *dev,
-                            struct ieee80211_security *sec);
-       int (*hard_start_xmit)(struct ieee80211_txb *txb,
-                              struct net_device *dev);
-       int (*reset_port)(struct net_device *dev);
+       void (*set_security) (struct net_device * dev,
+                             struct ieee80211_security * sec);
+       int (*hard_start_xmit) (struct ieee80211_txb * txb,
+                               struct net_device * dev, int pri);
+       int (*reset_port) (struct net_device * dev);
+       int (*is_queue_full) (struct net_device * dev, int pri);
+
+       int (*handle_management) (struct net_device * dev,
+                                 struct ieee80211_network * network, u16 type);
+
+       /* Typical STA methods */
+       int (*handle_auth) (struct net_device * dev,
+                           struct ieee80211_auth * auth);
+       int (*handle_deauth) (struct net_device * dev,
+                             struct ieee80211_auth * auth);
+       int (*handle_disassoc) (struct net_device * dev,
+                               struct ieee80211_disassoc * assoc);
+       int (*handle_beacon) (struct net_device * dev,
+                             struct ieee80211_beacon * beacon,
+                             struct ieee80211_network * network);
+       int (*handle_probe_response) (struct net_device * dev,
+                                     struct ieee80211_probe_response * resp,
+                                     struct ieee80211_network * network);
+       int (*handle_probe_request) (struct net_device * dev,
+                                    struct ieee80211_probe_request * req,
+                                    struct ieee80211_rx_stats * stats);
+       int (*handle_assoc_response) (struct net_device * dev,
+                                     struct ieee80211_assoc_response * resp,
+                                     struct ieee80211_network * network);
+
+       /* Typical AP methods */
+       int (*handle_assoc_request) (struct net_device * dev);
+       int (*handle_reassoc_request) (struct net_device * dev,
+                                      struct ieee80211_reassoc_request * req);
 
        /* This must be the last item so that it points to the data
         * allocated beyond this structure by alloc_ieee80211 */
@@ -736,12 +954,12 @@ struct ieee80211_device {
 #define IEEE_G            (1<<2)
 #define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
 
-extern inline void *ieee80211_priv(struct net_device *dev)
+static inline void *ieee80211_priv(struct net_device *dev)
 {
        return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
        /* Single white space is for Linksys APs */
        if (essid_len == 1 && essid[0] == ' ')
@@ -757,7 +975,8 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
        return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
+                                         int mode)
 {
        /*
         * It is possible for both access points and our device to support
@@ -783,14 +1002,17 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mod
        return 0;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
        int hdrlen = IEEE80211_3ADDR_LEN;
+       u16 stype = WLAN_FC_GET_STYPE(fc);
 
        switch (WLAN_FC_GET_TYPE(fc)) {
        case IEEE80211_FTYPE_DATA:
                if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
                        hdrlen = IEEE80211_4ADDR_LEN;
+               if (stype & IEEE80211_STYPE_QOS_DATA)
+                       hdrlen += 2;
                break;
        case IEEE80211_FTYPE_CTL:
                switch (WLAN_FC_GET_STYPE(fc)) {
@@ -808,7 +1030,48 @@ extern inline int ieee80211_get_hdrlen(u16 fc)
        return hdrlen;
 }
 
+static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
+{
+       switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+       case IEEE80211_1ADDR_LEN:
+               return ((struct ieee80211_hdr_1addr *)hdr)->payload;
+       case IEEE80211_2ADDR_LEN:
+               return ((struct ieee80211_hdr_2addr *)hdr)->payload;
+       case IEEE80211_3ADDR_LEN:
+               return ((struct ieee80211_hdr_3addr *)hdr)->payload;
+       case IEEE80211_4ADDR_LEN:
+               return ((struct ieee80211_hdr_4addr *)hdr)->payload;
+       }
+
+}
+
+static inline int ieee80211_is_ofdm_rate(u8 rate)
+{
+       switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+       case IEEE80211_OFDM_RATE_6MB:
+       case IEEE80211_OFDM_RATE_9MB:
+       case IEEE80211_OFDM_RATE_12MB:
+       case IEEE80211_OFDM_RATE_18MB:
+       case IEEE80211_OFDM_RATE_24MB:
+       case IEEE80211_OFDM_RATE_36MB:
+       case IEEE80211_OFDM_RATE_48MB:
+       case IEEE80211_OFDM_RATE_54MB:
+               return 1;
+       }
+       return 0;
+}
 
+static inline int ieee80211_is_cck_rate(u8 rate)
+{
+       switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+       case IEEE80211_CCK_RATE_1MB:
+       case IEEE80211_CCK_RATE_2MB:
+       case IEEE80211_CCK_RATE_5MB:
+       case IEEE80211_CCK_RATE_11MB:
+               return 1;
+       }
+       return 0;
+}
 
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev);
@@ -817,18 +1080,30 @@ extern struct net_device *alloc_ieee80211(int sizeof_priv);
 extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
 
 /* ieee80211_tx.c */
-extern int ieee80211_xmit(struct sk_buff *skb,
-                         struct net_device *dev);
+extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
-
+extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
+                             struct ieee80211_hdr *frame, int len);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-                            struct ieee80211_hdr *header,
+                            struct ieee80211_hdr_4addr *header,
                             struct ieee80211_rx_stats *stats);
 
+/* ieee80211_geo.c */
+extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
+                                                    *ieee);
+extern int ieee80211_set_geo(struct ieee80211_device *ieee,
+                            const struct ieee80211_geo *geo);
+
+extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
+                                     u8 channel);
+extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
+                                     u8 channel);
+extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
+
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
                                 struct iw_request_info *info,
@@ -839,17 +1114,21 @@ extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
                                   struct iw_request_info *info,
                                   union iwreq_data *wrqu, char *key);
-
-
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+                                     struct iw_request_info *info,
+                                     union iwreq_data *wrqu, char *extra);
+extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+                                     struct iw_request_info *info,
+                                     union iwreq_data *wrqu, char *extra);
+
+static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
        ieee->scans++;
 }
 
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
 {
        return ieee->scans;
 }
 
-
-#endif /* IEEE80211_H */
+#endif                         /* IEEE80211_H */
index b58a3bcc0dc0972c882f5992ad02264510769bf5..0a1c2d82ca4b9091b9f9dce9d575e5e04199c194 100644 (file)
 
 #include <linux/skbuff.h>
 
+enum {
+       IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
+};
+
 struct ieee80211_crypto_ops {
        const char *name;
 
        /* init new crypto context (e.g., allocate private data space,
         * select IV, etc.); returns NULL on failure or pointer to allocated
         * private data on success */
-       void * (*init)(int keyidx);
+       void *(*init) (int keyidx);
 
        /* deinitialize crypto context and free allocated private data */
-       void (*deinit)(void *priv);
+       void (*deinit) (void *priv);
+
+       int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
 
        /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
         * value from decrypt_mpdu is passed as the keyidx value for
@@ -42,34 +48,39 @@ struct ieee80211_crypto_ops {
         * encryption; if not, error will be returned; these functions are
         * called for all MPDUs (i.e., fragments).
         */
-       int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-       int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+       int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+       int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
 
        /* These functions are called for full MSDUs, i.e. full frames.
         * These can be NULL if full MSDU operations are not needed. */
-       int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-       int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-                           void *priv);
+       int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
+       int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
+                            void *priv);
 
-       int (*set_key)(void *key, int len, u8 *seq, void *priv);
-       int (*get_key)(void *key, int len, u8 *seq, void *priv);
+       int (*set_key) (void *key, int len, u8 * seq, void *priv);
+       int (*get_key) (void *key, int len, u8 * seq, void *priv);
 
        /* procfs handler for printing out key information and possible
         * statistics */
-       char * (*print_stats)(char *p, void *priv);
+       char *(*print_stats) (char *p, void *priv);
+
+       /* Crypto specific flag get/set for configuration settings */
+       unsigned long (*get_flags) (void *priv);
+       unsigned long (*set_flags) (unsigned long flags, void *priv);
 
        /* maximum number of bytes added by encryption; encrypt buf is
         * allocated with extra_prefix_len bytes, copy of in_buf, and
         * extra_postfix_len; encrypt need not use all this space, but
         * the result must start at the beginning of the buffer and correct
         * length must be returned */
-       int extra_prefix_len, extra_postfix_len;
+       int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
+       int extra_msdu_prefix_len, extra_msdu_postfix_len;
 
        struct module *owner;
 };
 
 struct ieee80211_crypt_data {
-       struct list_head list; /* delayed deletion list */
+       struct list_head list;  /* delayed deletion list */
        struct ieee80211_crypto_ops *ops;
        void *priv;
        atomic_t refcnt;
@@ -77,10 +88,11 @@ struct ieee80211_crypt_data {
 
 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
 int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
+struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
 void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
 void ieee80211_crypt_deinit_handler(unsigned long);
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
                                    struct ieee80211_crypt_data **crypt);
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee);
 
 #endif
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
new file mode 100644 (file)
index 0000000..429b738
--- /dev/null
@@ -0,0 +1,231 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+
+/* Radiotap header version (from official NetBSD feed) */
+#define IEEE80211RADIOTAP_VERSION      "1.5"
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION                0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/* XXX tcpdump/libpcap do not tolerate variable-length headers,
+ * yet, so we pad every radiotap header to 64 bytes. Ugh.
+ */
+#define IEEE80211_RADIOTAP_HDRLEN      64
+
+/* The radio capture header precedes the 802.11 header. */
+struct ieee80211_radiotap_header {
+       u8 it_version;          /* Version 0. Only increases
+                                * for drastic changes,
+                                * introduction of compatible
+                                * new fields does not count.
+                                */
+       u8 it_pad;
+       u16 it_len;             /* length of the whole
+                                * header in bytes, including
+                                * it_version, it_pad,
+                                * it_len, and data fields.
+                                */
+       u32 it_present;         /* A bitmap telling which
+                                * fields are present. Set bit 31
+                                * (0x80000000) to extend the
+                                * bitmap by another 32 bits.
+                                * Additional extensions are made
+                                * by setting bit 31.
+                                */
+};
+
+/* Name                                 Data type       Units
+ * ----                                 ---------       -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              u64       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x u16   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              u16       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u8        500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8        decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8        decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      u16       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    u16       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u16       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u8        bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u8        antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_FCS              u32       data
+ *
+ *     FCS from frame in network byte order.
+ */
+enum ieee80211_radiotap_type {
+       IEEE80211_RADIOTAP_TSFT = 0,
+       IEEE80211_RADIOTAP_FLAGS = 1,
+       IEEE80211_RADIOTAP_RATE = 2,
+       IEEE80211_RADIOTAP_CHANNEL = 3,
+       IEEE80211_RADIOTAP_FHSS = 4,
+       IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+       IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+       IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+       IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+       IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+       IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+       IEEE80211_RADIOTAP_ANTENNA = 11,
+       IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+       IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+       IEEE80211_RADIOTAP_EXT = 31,
+};
+
+/* Channel flags. */
+#define        IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
+#define        IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
+#define        IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
+#define        IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
+#define        IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
+#define        IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
+#define        IEEE80211_CHAN_DYN      0x0400  /* Dynamic CCK-OFDM channel */
+#define        IEEE80211_CHAN_GFSK     0x0800  /* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define        IEEE80211_RADIOTAP_F_CFP        0x01    /* sent/received
+                                                * during CFP
+                                                */
+#define        IEEE80211_RADIOTAP_F_SHORTPRE   0x02    /* sent/received
+                                                * with short
+                                                * preamble
+                                                */
+#define        IEEE80211_RADIOTAP_F_WEP        0x04    /* sent/received
+                                                * with WEP encryption
+                                                */
+#define        IEEE80211_RADIOTAP_F_FRAG       0x08    /* sent/received
+                                                * with fragmentation
+                                                */
+#define        IEEE80211_RADIOTAP_F_FCS        0x10    /* frame includes FCS */
+#define        IEEE80211_RADIOTAP_F_DATAPAD    0x20    /* frame has padding between
+                                                * 802.11 header and payload
+                                                * (to 32-bit boundary)
+                                                */
+
+/* Ugly macro to convert literal channel numbers into their mhz equivalents
+ * There are certianly some conditions that will break this (like feeding it '30')
+ * but they shouldn't arise since nothing talks on channel 30. */
+#define ieee80211chan2mhz(x) \
+       (((x) <= 14) ? \
+       (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
+       ((x) + 1000) * 5)
+
+#endif                         /* IEEE80211_RADIOTAP_H */
index 614cb6ba564e41c476381c0201c9c0e2a7076f5c..877efa434700bec7d7a997b8492568be0316af5a 100644 (file)
@@ -86,7 +86,6 @@ static inline struct sppp *sppp_of(struct net_device *dev)
 
 void sppp_attach (struct ppp_device *pd);
 void sppp_detach (struct net_device *dev);
-void sppp_input (struct net_device *dev, struct sk_buff *m);
 int sppp_do_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
 struct sk_buff *sppp_dequeue (struct net_device *dev);
 int sppp_isempty (struct net_device *dev);
index a6ccac5baea8863b77b967d2fe61358ea77cb158..f988417121da76646ad995ce3a556c09349b0338 100644 (file)
@@ -7,5 +7,6 @@ ieee80211-objs := \
        ieee80211_module.o \
        ieee80211_tx.o \
        ieee80211_rx.o \
-       ieee80211_wx.o
+       ieee80211_wx.o \
+       ieee80211_geo.o
 
index 61a9d92e455b67e5dc9651470780a32120e57d7a..f3b6aa3be63878a08708cf5542f654117882527e 100644 (file)
@@ -41,6 +41,12 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
 {
        struct list_head *ptr, *n;
        struct ieee80211_crypt_data *entry;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ieee->lock, flags);
+
+       if (list_empty(&ieee->crypt_deinit_list))
+               goto unlock;
 
        for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
             ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
@@ -57,6 +63,18 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
                }
                kfree(entry);
        }
+      unlock:
+       spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+/* After this, crypt_deinit_list won't accept new members */
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ieee->lock, flags);
+       ieee->crypt_quiesced = 1;
+       spin_unlock_irqrestore(&ieee->lock, flags);
 }
 
 void ieee80211_crypt_deinit_handler(unsigned long data)
@@ -64,16 +82,16 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
        struct ieee80211_device *ieee = (struct ieee80211_device *)data;
        unsigned long flags;
 
-       spin_lock_irqsave(&ieee->lock, flags);
        ieee80211_crypt_deinit_entries(ieee, 0);
-       if (!list_empty(&ieee->crypt_deinit_list)) {
+
+       spin_lock_irqsave(&ieee->lock, flags);
+       if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
                printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
                       "deletion list\n", ieee->dev->name);
                ieee->crypt_deinit_timer.expires = jiffies + HZ;
                add_timer(&ieee->crypt_deinit_timer);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
-
 }
 
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
@@ -93,10 +111,12 @@ void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
         * locking. */
 
        spin_lock_irqsave(&ieee->lock, flags);
-       list_add(&tmp->list, &ieee->crypt_deinit_list);
-       if (!timer_pending(&ieee->crypt_deinit_timer)) {
-               ieee->crypt_deinit_timer.expires = jiffies + HZ;
-               add_timer(&ieee->crypt_deinit_timer);
+       if (!ieee->crypt_quiesced) {
+               list_add(&tmp->list, &ieee->crypt_deinit_list);
+               if (!timer_pending(&ieee->crypt_deinit_timer)) {
+                       ieee->crypt_deinit_timer.expires = jiffies + HZ;
+                       add_timer(&ieee->crypt_deinit_timer);
+               }
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -191,18 +211,18 @@ static void ieee80211_crypt_null_deinit(void *priv)
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_null = {
-       .name                   = "NULL",
-       .init                   = ieee80211_crypt_null_init,
-       .deinit                 = ieee80211_crypt_null_deinit,
-       .encrypt_mpdu           = NULL,
-       .decrypt_mpdu           = NULL,
-       .encrypt_msdu           = NULL,
-       .decrypt_msdu           = NULL,
-       .set_key                = NULL,
-       .get_key                = NULL,
-       .extra_prefix_len       = 0,
-       .extra_postfix_len      = 0,
-       .owner                  = THIS_MODULE,
+       .name = "NULL",
+       .init = ieee80211_crypt_null_init,
+       .deinit = ieee80211_crypt_null_deinit,
+       .encrypt_mpdu = NULL,
+       .decrypt_mpdu = NULL,
+       .encrypt_msdu = NULL,
+       .decrypt_msdu = NULL,
+       .set_key = NULL,
+       .get_key = NULL,
+       .extra_mpdu_prefix_len = 0,
+       .extra_mpdu_postfix_len = 0,
+       .owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_init(void)
@@ -249,6 +269,7 @@ static void __exit ieee80211_crypto_deinit(void)
 EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
 EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
 EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
+EXPORT_SYMBOL(ieee80211_crypt_quiescing);
 
 EXPORT_SYMBOL(ieee80211_register_crypto_ops);
 EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
index 8fc13f45971e3b895ffa508f4750319a5a6e641c..05a853c13012836fe518cf965049e84ce1f59b0a 100644 (file)
@@ -119,7 +119,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
 }
 
 static void ccmp_init_blocks(struct crypto_tfm *tfm,
-                            struct ieee80211_hdr *hdr,
+                            struct ieee80211_hdr_4addr *hdr,
                             u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
 {
        u8 *pos, qc = 0;
@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_ccmp_data *key = priv;
-       int data_len, i, blocks, last, len;
-       u8 *pos, *mic;
-       struct ieee80211_hdr *hdr;
-       u8 *b0 = key->tx_b0;
-       u8 *b = key->tx_b;
-       u8 *e = key->tx_e;
-       u8 *s0 = key->tx_s0;
+       int i;
+       u8 *pos;
 
-       if (skb_headroom(skb) < CCMP_HDR_LEN ||
-           skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+       if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
                return -1;
 
-       data_len = skb->len - hdr_len;
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
        pos += hdr_len;
-       mic = skb_put(skb, CCMP_MIC_LEN);
 
        i = CCMP_PN_LEN - 1;
        while (i >= 0) {
@@ -229,7 +221,31 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        *pos++ = key->tx_pn[1];
        *pos++ = key->tx_pn[0];
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       return CCMP_HDR_LEN;
+}
+
+static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+       struct ieee80211_ccmp_data *key = priv;
+       int data_len, i, blocks, last, len;
+       u8 *pos, *mic;
+       struct ieee80211_hdr_4addr *hdr;
+       u8 *b0 = key->tx_b0;
+       u8 *b = key->tx_b;
+       u8 *e = key->tx_e;
+       u8 *s0 = key->tx_s0;
+
+       if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+               return -1;
+
+       data_len = skb->len - hdr_len;
+       len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
+       if (len < 0)
+               return -1;
+
+       pos = skb->data + hdr_len + CCMP_HDR_LEN;
+       mic = skb_put(skb, CCMP_MIC_LEN);
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
 
        blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
@@ -258,7 +274,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_ccmp_data *key = priv;
        u8 keyidx, *pos;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u8 *b0 = key->rx_b0;
        u8 *b = key->rx_b;
        u8 *a = key->rx_a;
@@ -272,7 +288,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
        }
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        pos = skb->data + hdr_len;
        keyidx = pos[3];
        if (!(keyidx & (1 << 5))) {
@@ -426,19 +442,20 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
-       .name                   = "CCMP",
-       .init                   = ieee80211_ccmp_init,
-       .deinit                 = ieee80211_ccmp_deinit,
-       .encrypt_mpdu           = ieee80211_ccmp_encrypt,
-       .decrypt_mpdu           = ieee80211_ccmp_decrypt,
-       .encrypt_msdu           = NULL,
-       .decrypt_msdu           = NULL,
-       .set_key                = ieee80211_ccmp_set_key,
-       .get_key                = ieee80211_ccmp_get_key,
-       .print_stats            = ieee80211_ccmp_print_stats,
-       .extra_prefix_len       = CCMP_HDR_LEN,
-       .extra_postfix_len      = CCMP_MIC_LEN,
-       .owner                  = THIS_MODULE,
+       .name = "CCMP",
+       .init = ieee80211_ccmp_init,
+       .deinit = ieee80211_ccmp_deinit,
+       .build_iv = ieee80211_ccmp_hdr,
+       .encrypt_mpdu = ieee80211_ccmp_encrypt,
+       .decrypt_mpdu = ieee80211_ccmp_decrypt,
+       .encrypt_msdu = NULL,
+       .decrypt_msdu = NULL,
+       .set_key = ieee80211_ccmp_set_key,
+       .get_key = ieee80211_ccmp_get_key,
+       .print_stats = ieee80211_ccmp_print_stats,
+       .extra_mpdu_prefix_len = CCMP_HDR_LEN,
+       .extra_mpdu_postfix_len = CCMP_MIC_LEN,
+       .owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_ccmp_init(void)
index d4f9164be1a1848f75f49fd0ee631ce70aa6fdc6..2e34f29b7956f46c4f81fef31953af4953fd2752 100644 (file)
@@ -59,8 +59,24 @@ struct ieee80211_tkip_data {
 
        /* scratch buffers for virt_to_page() (crypto API) */
        u8 rx_hdr[16], tx_hdr[16];
+
+       unsigned long flags;
 };
 
+static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
+{
+       struct ieee80211_tkip_data *_priv = priv;
+       unsigned long old_flags = _priv->flags;
+       _priv->flags = flags;
+       return old_flags;
+}
+
+static unsigned long ieee80211_tkip_get_flags(void *priv)
+{
+       struct ieee80211_tkip_data *_priv = priv;
+       return _priv->flags;
+}
+
 static void *ieee80211_tkip_init(int key_idx)
 {
        struct ieee80211_tkip_data *priv;
@@ -69,6 +85,7 @@ static void *ieee80211_tkip_init(int key_idx)
        if (priv == NULL)
                goto fail;
        memset(priv, 0, sizeof(*priv));
+
        priv->key_idx = key_idx;
 
        priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -255,25 +272,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
 #endif
 }
 
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       u8 rc4key[16], *pos, *icv;
-       struct ieee80211_hdr *hdr;
+       u8 *rc4key, *pos, *icv;
+       struct ieee80211_hdr_4addr *hdr;
        u32 crc;
-       struct scatterlist sg;
 
-       if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
-           skb->len < hdr_len)
-               return -1;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
+
+       if (skb_headroom(skb) < 8 || skb->len < hdr_len)
+               return NULL;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
        if (!tkey->tx_phase1_done) {
                tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
                                   tkey->tx_iv32);
                tkey->tx_phase1_done = 1;
        }
+       rc4key = kmalloc(16, GFP_ATOMIC);
+       if (!rc4key)
+               return NULL;
        tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
 
        len = skb->len - hdr_len;
@@ -282,9 +301,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        pos += hdr_len;
        icv = skb_put(skb, 4);
 
-       *pos++ = rc4key[0];
-       *pos++ = rc4key[1];
-       *pos++ = rc4key[2];
+       *pos++ = *rc4key;
+       *pos++ = *(rc4key + 1);
+       *pos++ = *(rc4key + 2);
        *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
        *pos++ = tkey->tx_iv32 & 0xff;
        *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
@@ -297,6 +316,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        icv[2] = crc >> 16;
        icv[3] = crc >> 24;
 
+       return rc4key;
+}
+
+static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+       struct ieee80211_tkip_data *tkey = priv;
+       int len;
+       const u8 *rc4key;
+       u8 *pos;
+       struct scatterlist sg;
+
+       if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
+               if (net_ratelimit()) {
+                       struct ieee80211_hdr_4addr *hdr =
+                           (struct ieee80211_hdr_4addr *)skb->data;
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
+                              "TX packet to " MAC_FMT "\n",
+                              MAC_ARG(hdr->addr1));
+               }
+               return -1;
+       }
+
+       if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
+               return -1;
+
+       len = skb->len - hdr_len;
+       pos = skb->data + hdr_len;
+
+       rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
+       if (!rc4key)
+               return -1;
+
        crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
        sg.page = virt_to_page(pos);
        sg.offset = offset_in_page(pos);
@@ -319,16 +370,26 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
        u8 keyidx, *pos;
        u32 iv32;
        u16 iv16;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u8 icv[4];
        u32 crc;
        struct scatterlist sg;
        int plen;
 
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
+
+       if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
+                              "received packet from " MAC_FMT "\n",
+                              MAC_ARG(hdr->addr2));
+               }
+               return -1;
+       }
+
        if (skb->len < hdr_len + 8 + 4)
                return -1;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
        pos = skb->data + hdr_len;
        keyidx = pos[3];
        if (!(keyidx & (1 << 5))) {
@@ -441,9 +502,9 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
 
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
-       struct ieee80211_hdr *hdr11;
+       struct ieee80211_hdr_4addr *hdr11;
 
-       hdr11 = (struct ieee80211_hdr *)skb->data;
+       hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
        switch (le16_to_cpu(hdr11->frame_ctl) &
                (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
        case IEEE80211_FCTL_TODS:
@@ -490,9 +551,9 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
        return 0;
 }
 
-#if WIRELESS_EXT >= 18
 static void ieee80211_michael_mic_failure(struct net_device *dev,
-                                         struct ieee80211_hdr *hdr, int keyidx)
+                                         struct ieee80211_hdr_4addr *hdr,
+                                         int keyidx)
 {
        union iwreq_data wrqu;
        struct iw_michaelmicfailure ev;
@@ -510,28 +571,6 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
        wrqu.data.length = sizeof(ev);
        wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 }
-#elif WIRELESS_EXT >= 15
-static void ieee80211_michael_mic_failure(struct net_device *dev,
-                                         struct ieee80211_hdr *hdr, int keyidx)
-{
-       union iwreq_data wrqu;
-       char buf[128];
-
-       /* TODO: needed parameters: count, keyid, key type, TSC */
-       sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
-               MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-               MAC_ARG(hdr->addr2));
-       memset(&wrqu, 0, sizeof(wrqu));
-       wrqu.data.length = strlen(buf);
-       wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-}
-#else                          /* WIRELESS_EXT >= 15 */
-static inline void ieee80211_michael_mic_failure(struct net_device *dev,
-                                                struct ieee80211_hdr *hdr,
-                                                int keyidx)
-{
-}
-#endif                         /* WIRELESS_EXT >= 15 */
 
 static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
                                        int hdr_len, void *priv)
@@ -547,8 +586,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
                        skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
                return -1;
        if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
-               struct ieee80211_hdr *hdr;
-               hdr = (struct ieee80211_hdr *)skb->data;
+               struct ieee80211_hdr_4addr *hdr;
+               hdr = (struct ieee80211_hdr_4addr *)skb->data;
                printk(KERN_DEBUG "%s: Michael MIC verification failed for "
                       "MSDU from " MAC_FMT " keyidx=%d\n",
                       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
@@ -654,19 +693,22 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv)
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
-       .name                   = "TKIP",
-       .init                   = ieee80211_tkip_init,
-       .deinit                 = ieee80211_tkip_deinit,
-       .encrypt_mpdu           = ieee80211_tkip_encrypt,
-       .decrypt_mpdu           = ieee80211_tkip_decrypt,
-       .encrypt_msdu           = ieee80211_michael_mic_add,
-       .decrypt_msdu           = ieee80211_michael_mic_verify,
-       .set_key                = ieee80211_tkip_set_key,
-       .get_key                = ieee80211_tkip_get_key,
-       .print_stats            = ieee80211_tkip_print_stats,
-       .extra_prefix_len       = 4 + 4,        /* IV + ExtIV */
-       .extra_postfix_len      = 8 + 4,        /* MIC + ICV */
-       .owner                  = THIS_MODULE,
+       .name = "TKIP",
+       .init = ieee80211_tkip_init,
+       .deinit = ieee80211_tkip_deinit,
+       .encrypt_mpdu = ieee80211_tkip_encrypt,
+       .decrypt_mpdu = ieee80211_tkip_decrypt,
+       .encrypt_msdu = ieee80211_michael_mic_add,
+       .decrypt_msdu = ieee80211_michael_mic_verify,
+       .set_key = ieee80211_tkip_set_key,
+       .get_key = ieee80211_tkip_get_key,
+       .print_stats = ieee80211_tkip_print_stats,
+       .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
+       .extra_mpdu_postfix_len = 4,    /* ICV */
+       .extra_msdu_postfix_len = 8,    /* MIC */
+       .get_flags = ieee80211_tkip_get_flags,
+       .set_flags = ieee80211_tkip_set_flags,
+       .owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_tkip_init(void)
index b4d2514a090270be5b5822e671678ded227231df..7c08ed2f2628f4dd439465f0abdd90358a8e39a9 100644 (file)
@@ -229,19 +229,19 @@ static char *prism2_wep_print_stats(char *p, void *priv)
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
-       .name                   = "WEP",
-       .init                   = prism2_wep_init,
-       .deinit                 = prism2_wep_deinit,
-       .encrypt_mpdu           = prism2_wep_encrypt,
-       .decrypt_mpdu           = prism2_wep_decrypt,
-       .encrypt_msdu           = NULL,
-       .decrypt_msdu           = NULL,
-       .set_key                = prism2_wep_set_key,
-       .get_key                = prism2_wep_get_key,
-       .print_stats            = prism2_wep_print_stats,
-       .extra_prefix_len       = 4,    /* IV */
-       .extra_postfix_len      = 4,    /* ICV */
-       .owner                  = THIS_MODULE,
+       .name = "WEP",
+       .init = prism2_wep_init,
+       .deinit = prism2_wep_deinit,
+       .encrypt_mpdu = prism2_wep_encrypt,
+       .decrypt_mpdu = prism2_wep_decrypt,
+       .encrypt_msdu = NULL,
+       .decrypt_msdu = NULL,
+       .set_key = prism2_wep_set_key,
+       .get_key = prism2_wep_get_key,
+       .print_stats = prism2_wep_print_stats,
+       .extra_mpdu_prefix_len = 4,     /* IV */
+       .extra_mpdu_postfix_len = 4,    /* ICV */
+       .owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_wep_init(void)
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
new file mode 100644 (file)
index 0000000..c4b54ef
--- /dev/null
@@ -0,0 +1,141 @@
+/******************************************************************************
+
+  Copyright(c) 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
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
+{
+       int i;
+
+       /* Driver needs to initialize the geography map before using
+        * these helper functions */
+       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+               for (i = 0; i < ieee->geo.bg_channels; i++)
+                       /* NOTE: If G mode is currently supported but
+                        * this is a B only channel, we don't see it
+                        * as valid. */
+                       if ((ieee->geo.bg[i].channel == channel) &&
+                           (!(ieee->mode & IEEE_G) ||
+                            !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
+                               return IEEE80211_24GHZ_BAND;
+
+       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+               for (i = 0; i < ieee->geo.a_channels; i++)
+                       if (ieee->geo.a[i].channel == channel)
+                               return IEEE80211_52GHZ_BAND;
+
+       return 0;
+}
+
+int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
+{
+       int i;
+
+       /* Driver needs to initialize the geography map before using
+        * these helper functions */
+       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+               for (i = 0; i < ieee->geo.bg_channels; i++)
+                       if (ieee->geo.bg[i].channel == channel)
+                               return i;
+
+       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+               for (i = 0; i < ieee->geo.a_channels; i++)
+                       if (ieee->geo.a[i].channel == channel)
+                               return i;
+
+       return -1;
+}
+
+u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
+{
+       int i;
+
+       /* Driver needs to initialize the geography map before using
+        * these helper functions */
+       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+       freq /= 100000;
+
+       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+               for (i = 0; i < ieee->geo.bg_channels; i++)
+                       if (ieee->geo.bg[i].freq == freq)
+                               return ieee->geo.bg[i].channel;
+
+       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+               for (i = 0; i < ieee->geo.a_channels; i++)
+                       if (ieee->geo.a[i].freq == freq)
+                               return ieee->geo.a[i].channel;
+
+       return 0;
+}
+
+int ieee80211_set_geo(struct ieee80211_device *ieee,
+                     const struct ieee80211_geo *geo)
+{
+       memcpy(ieee->geo.name, geo->name, 3);
+       ieee->geo.name[3] = '\0';
+       ieee->geo.bg_channels = geo->bg_channels;
+       ieee->geo.a_channels = geo->a_channels;
+       memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
+              sizeof(struct ieee80211_channel));
+       memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
+              sizeof(struct ieee80211_channel));
+       return 0;
+}
+
+const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
+{
+       return &ieee->geo;
+}
+
+EXPORT_SYMBOL(ieee80211_is_valid_channel);
+EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_index);
+EXPORT_SYMBOL(ieee80211_set_geo);
+EXPORT_SYMBOL(ieee80211_get_geo);
index 6059e9e37123b711554c6e50a18daf8a5872c793..f66d792cd204b068976f7655e625cb4a21d99978 100644 (file)
@@ -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)
 {
@@ -126,26 +129,34 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
 
        /* 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;
 
@@ -161,6 +172,7 @@ void free_ieee80211(struct net_device *dev)
 
        int i;
 
+       ieee80211_crypt_quiescing(ieee);
        del_timer_sync(&ieee->crypt_deinit_timer);
        ieee80211_crypt_deinit_entries(ieee, 1);
 
@@ -195,38 +207,26 @@ static int show_debug_level(char *page, char **start, off_t offset,
 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;
@@ -246,26 +246,33 @@ static int __init ieee80211_init(void)
        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 f7dcd854139e011c960643a76e2a40ae77566341..6b005cb0caa0efb86218a049b49bb7ddccbf1b21 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
  * <jkmaline@cc.hut.fi>
  * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -87,7 +87,7 @@ static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
-                                               struct ieee80211_hdr *hdr)
+                                               struct ieee80211_hdr_4addr *hdr)
 {
        struct sk_buff *skb = NULL;
        u16 sc;
@@ -101,7 +101,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
        if (frag == 0) {
                /* Reserve enough space to fit maximum frame length */
                skb = dev_alloc_skb(ieee->dev->mtu +
-                                   sizeof(struct ieee80211_hdr) +
+                                   sizeof(struct ieee80211_hdr_4addr) +
                                    8 /* LLC */  +
                                    2 /* alignment */  +
                                    8 /* WEP */  + ETH_ALEN /* WDS */ );
@@ -138,7 +138,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
 
 /* Called only as a tasklet (software IRQ) */
 static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
-                                          struct ieee80211_hdr *hdr)
+                                          struct ieee80211_hdr_4addr *hdr)
 {
        u16 sc;
        unsigned int seq;
@@ -176,7 +176,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
                       ieee->dev->name);
                return 0;
 /*
-  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
+  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
   skb->data);*/
        }
 
@@ -232,13 +232,13 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 {
        struct net_device *dev = ieee->dev;
        u16 fc, ethertype;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_3addr *hdr;
        u8 *pos;
 
        if (skb->len < 24)
                return 0;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_3addr *)skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        /* check that the frame is unicast frame to us */
@@ -271,26 +271,15 @@ static inline int
 ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
                           struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_3addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_3addr *)skb->data;
        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-       if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
-               if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-                              "received packet from " MAC_FMT "\n",
-                              ieee->dev->name, MAC_ARG(hdr->addr2));
-               }
-               return -1;
-       }
-#endif
-
        atomic_inc(&crypt->refcnt);
        res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
        atomic_dec(&crypt->refcnt);
@@ -314,13 +303,13 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
                                struct sk_buff *skb, int keyidx,
                                struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_3addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_3addr *)skb->data;
        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
        atomic_inc(&crypt->refcnt);
@@ -343,7 +332,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        size_t hdrlen;
        u16 fc, type, stype, sc;
        struct net_device_stats *stats;
@@ -363,7 +352,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        struct ieee80211_crypt_data *crypt = NULL;
        int keyidx = 0;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        stats = &ieee->stats;
 
        if (skb->len < 10) {
@@ -378,35 +367,50 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        frag = WLAN_GET_SEQ_FRAG(sc);
        hdrlen = ieee80211_get_hdrlen(fc);
 
-#ifdef NOT_YET
-#if WIRELESS_EXT > 15
        /* Put this code here so that we avoid duplicating it in all
         * Rx paths. - Jean II */
 #ifdef IW_WIRELESS_SPY         /* defined in iw_handler.h */
        /* If spy monitoring on */
-       if (iface->spy_data.spy_number > 0) {
+       if (ieee->spy_data.spy_number > 0) {
                struct iw_quality wstats;
-               wstats.level = rx_stats->signal;
-               wstats.noise = rx_stats->noise;
-               wstats.updated = 6;     /* No qual value */
+
+               wstats.updated = 0;
+               if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
+                       wstats.level = rx_stats->rssi;
+                       wstats.updated |= IW_QUAL_LEVEL_UPDATED;
+               } else
+                       wstats.updated |= IW_QUAL_LEVEL_INVALID;
+
+               if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
+                       wstats.noise = rx_stats->noise;
+                       wstats.updated |= IW_QUAL_NOISE_UPDATED;
+               } else
+                       wstats.updated |= IW_QUAL_NOISE_INVALID;
+
+               if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
+                       wstats.qual = rx_stats->signal;
+                       wstats.updated |= IW_QUAL_QUAL_UPDATED;
+               } else
+                       wstats.updated |= IW_QUAL_QUAL_INVALID;
+
                /* Update spy records */
-               wireless_spy_update(dev, hdr->addr2, &wstats);
+               wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
        }
 #endif                         /* IW_WIRELESS_SPY */
-#endif                         /* WIRELESS_EXT > 15 */
+
+#ifdef NOT_YET
        hostap_update_rx_stats(local->ap, hdr, rx_stats);
 #endif
 
-#if WIRELESS_EXT > 15
        if (ieee->iw_mode == IW_MODE_MONITOR) {
                ieee80211_monitor_rx(ieee, skb, rx_stats);
                stats->rx_packets++;
                stats->rx_bytes += skb->len;
                return 1;
        }
-#endif
 
-       if (ieee->host_decrypt) {
+       if (is_multicast_ether_addr(hdr->addr1) ? ieee->host_mc_decrypt :
+           ieee->host_decrypt) {
                int idx = 0;
                if (skb->len >= hdrlen + 3)
                        idx = skb->data[hdrlen + 3] >> 6;
@@ -531,6 +535,9 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        /* Nullfunc frames may have PS-bit set, so they must be passed to
         * hostap_handle_sta_rx() before being dropped here. */
+
+       stype &= ~IEEE80211_STYPE_QOS_DATA;
+
        if (stype != IEEE80211_STYPE_DATA &&
            stype != IEEE80211_STYPE_DATA_CFACK &&
            stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -549,7 +556,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
            (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
                goto rx_dropped;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
        /* skb: hdr + (possibly fragmented) plaintext payload */
        // PR: FIXME: hostap has additional conditions in the "if" below:
@@ -603,7 +610,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                /* this was the last fragment and the frame will be
                 * delivered, so remove skb from fragment cache */
                skb = frag_skb;
-               hdr = (struct ieee80211_hdr *)skb->data;
+               hdr = (struct ieee80211_hdr_4addr *)skb->data;
                ieee80211_frag_cache_invalidate(ieee, hdr);
        }
 
@@ -613,7 +620,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
            ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
                goto rx_dropped;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
                if (            /*ieee->ieee802_1x && */
                           ieee80211_is_eapol_frame(ieee, skb)) {
@@ -755,69 +762,179 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
 #define MGMT_FRAME_FIXED_PART_LENGTH           0x24
 
-static inline int ieee80211_is_ofdm_rate(u8 rate)
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/*
+* Make ther structure we read from the beacon packet has
+* the right values
+*/
+static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
+                                    *info_element, int sub_type)
 {
-       switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-       case IEEE80211_OFDM_RATE_6MB:
-       case IEEE80211_OFDM_RATE_9MB:
-       case IEEE80211_OFDM_RATE_12MB:
-       case IEEE80211_OFDM_RATE_18MB:
-       case IEEE80211_OFDM_RATE_24MB:
-       case IEEE80211_OFDM_RATE_36MB:
-       case IEEE80211_OFDM_RATE_48MB:
-       case IEEE80211_OFDM_RATE_54MB:
-               return 1;
-       }
+
+       if (info_element->qui_subtype != sub_type)
+               return -1;
+       if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+               return -1;
+       if (info_element->qui_type != QOS_OUI_TYPE)
+               return -1;
+       if (info_element->version != QOS_VERSION_1)
+               return -1;
+
        return 0;
 }
 
-static inline int ieee80211_network_init(struct ieee80211_device *ieee,
-                                        struct ieee80211_probe_response
-                                        *beacon,
-                                        struct ieee80211_network *network,
-                                        struct ieee80211_rx_stats *stats)
+/*
+ * Parse a QoS parameter element
+ */
+static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
+                                           *element_param, struct ieee80211_info_element
+                                           *info_element)
 {
-#ifdef CONFIG_IEEE80211_DEBUG
-       char rates_str[64];
-       char *p;
-#endif
-       struct ieee80211_info_element *info_element;
-       u16 left;
-       u8 i;
+       int ret = 0;
+       u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
 
-       /* Pull out fixed field data */
-       memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
-       network->capability = beacon->capability;
-       network->last_scanned = jiffies;
-       network->time_stamp[0] = beacon->time_stamp[0];
-       network->time_stamp[1] = beacon->time_stamp[1];
-       network->beacon_interval = beacon->beacon_interval;
-       /* Where to pull this? beacon->listen_interval; */
-       network->listen_interval = 0x0A;
-       network->rates_len = network->rates_ex_len = 0;
-       network->last_associate = 0;
-       network->ssid_len = 0;
-       network->flags = 0;
-       network->atim_window = 0;
+       if ((info_element == NULL) || (element_param == NULL))
+               return -1;
 
-       if (stats->freq == IEEE80211_52GHZ_BAND) {
-               /* for A band (No DS info) */
-               network->channel = stats->received_channel;
+       if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+               memcpy(element_param->info_element.qui, info_element->data,
+                      info_element->len);
+               element_param->info_element.elementID = info_element->id;
+               element_param->info_element.length = info_element->len;
        } else
-               network->flags |= NETWORK_HAS_CCK;
+               ret = -1;
+       if (ret == 0)
+               ret = ieee80211_verify_qos_info(&element_param->info_element,
+                                               QOS_OUI_PARAM_SUB_TYPE);
+       return ret;
+}
 
-       network->wpa_ie_len = 0;
-       network->rsn_ie_len = 0;
+/*
+ * Parse a QoS information element
+ */
+static int ieee80211_read_qos_info_element(struct
+                                          ieee80211_qos_information_element
+                                          *element_info, struct ieee80211_info_element
+                                          *info_element)
+{
+       int ret = 0;
+       u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+
+       if (element_info == NULL)
+               return -1;
+       if (info_element == NULL)
+               return -1;
+
+       if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+               memcpy(element_info->qui, info_element->data,
+                      info_element->len);
+               element_info->elementID = info_element->id;
+               element_info->length = info_element->len;
+       } else
+               ret = -1;
+
+       if (ret == 0)
+               ret = ieee80211_verify_qos_info(element_info,
+                                               QOS_OUI_INFO_SUB_TYPE);
+       return ret;
+}
+
+/*
+ * Write QoS parameters from the ac parameters.
+ */
+static int ieee80211_qos_convert_ac_to_parameters(struct
+                                                 ieee80211_qos_parameter_info
+                                                 *param_elm, struct
+                                                 ieee80211_qos_parameters
+                                                 *qos_param)
+{
+       int rc = 0;
+       int i;
+       struct ieee80211_qos_ac_parameter *ac_params;
+       u32 txop;
+       u8 cw_min;
+       u8 cw_max;
+
+       for (i = 0; i < QOS_QUEUE_NUM; i++) {
+               ac_params = &(param_elm->ac_params_record[i]);
+
+               qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
+               qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
+
+               cw_min = ac_params->ecw_min_max & 0x0F;
+               qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
+
+               cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
+               qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
+
+               qos_param->flag[i] =
+                   (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+
+               txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
+               qos_param->tx_op_limit[i] = (u16) txop;
+       }
+       return rc;
+}
+
+/*
+ * we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
+                                            *info_element,
+                                            struct ieee80211_network *network)
+{
+       int rc = 0;
+       struct ieee80211_qos_parameters *qos_param = NULL;
+       struct ieee80211_qos_information_element qos_info_element;
+
+       rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
+
+       if (rc == 0) {
+               network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+               network->flags |= NETWORK_HAS_QOS_INFORMATION;
+       } else {
+               struct ieee80211_qos_parameter_info param_element;
+
+               rc = ieee80211_read_qos_param_element(&param_element,
+                                                     info_element);
+               if (rc == 0) {
+                       qos_param = &(network->qos_data.parameters);
+                       ieee80211_qos_convert_ac_to_parameters(&param_element,
+                                                              qos_param);
+                       network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+                       network->qos_data.param_count =
+                           param_element.info_element.ac_info & 0x0F;
+               }
+       }
+
+       if (rc == 0) {
+               IEEE80211_DEBUG_QOS("QoS is supported\n");
+               network->qos_data.supported = 1;
+       }
+       return rc;
+}
+
+static int ieee80211_parse_info_param(struct ieee80211_info_element
+                                     *info_element, u16 length,
+                                     struct ieee80211_network *network)
+{
+       u8 i;
+#ifdef CONFIG_IEEE80211_DEBUG
+       char rates_str[64];
+       char *p;
+#endif
 
-       info_element = &beacon->info_element;
-       left = stats->len - ((void *)info_element - (void *)beacon);
-       while (left >= sizeof(struct ieee80211_info_element_hdr)) {
-               if (sizeof(struct ieee80211_info_element_hdr) +
-                   info_element->len > left) {
-                       IEEE80211_DEBUG_SCAN
-                           ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
-                            info_element->len +
-                            sizeof(struct ieee80211_info_element), left);
+       while (length >= sizeof(*info_element)) {
+               if (sizeof(*info_element) + info_element->len > length) {
+                       IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
+                                            "info_element->len + 2 > left : "
+                                            "info_element->len+2=%zd left=%d, id=%d.\n",
+                                            info_element->len +
+                                            sizeof(*info_element),
+                                            length, info_element->id);
                        return 1;
                }
 
@@ -837,7 +954,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
                                memset(network->ssid + network->ssid_len, 0,
                                       IW_ESSID_MAX_SIZE - network->ssid_len);
 
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
                                             network->ssid, network->ssid_len);
                        break;
 
@@ -845,15 +962,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
 #ifdef CONFIG_IEEE80211_DEBUG
                        p = rates_str;
 #endif
-                       network->rates_len =
-                           min(info_element->len, MAX_RATES_LENGTH);
+                       network->rates_len = min(info_element->len,
+                                                MAX_RATES_LENGTH);
                        for (i = 0; i < network->rates_len; i++) {
                                network->rates[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-                               p += snprintf(p,
-                                             sizeof(rates_str) - (p -
-                                                                  rates_str),
-                                             "%02X ", network->rates[i]);
+                               p += snprintf(p, sizeof(rates_str) -
+                                             (p - rates_str), "%02X ",
+                                             network->rates[i]);
 #endif
                                if (ieee80211_is_ofdm_rate
                                    (info_element->data[i])) {
@@ -865,7 +981,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
                                }
                        }
 
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
                                             rates_str, network->rates_len);
                        break;
 
@@ -873,15 +989,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
 #ifdef CONFIG_IEEE80211_DEBUG
                        p = rates_str;
 #endif
-                       network->rates_ex_len =
-                           min(info_element->len, MAX_RATES_EX_LENGTH);
+                       network->rates_ex_len = min(info_element->len,
+                                                   MAX_RATES_EX_LENGTH);
                        for (i = 0; i < network->rates_ex_len; i++) {
                                network->rates_ex[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-                               p += snprintf(p,
-                                             sizeof(rates_str) - (p -
-                                                                  rates_str),
-                                             "%02X ", network->rates[i]);
+                               p += snprintf(p, sizeof(rates_str) -
+                                             (p - rates_str), "%02X ",
+                                             network->rates[i]);
 #endif
                                if (ieee80211_is_ofdm_rate
                                    (info_element->data[i])) {
@@ -893,40 +1008,51 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
                                }
                        }
 
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
                                             rates_str, network->rates_ex_len);
                        break;
 
                case MFIE_TYPE_DS_SET:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
                                             info_element->data[0]);
-                       if (stats->freq == IEEE80211_24GHZ_BAND)
-                               network->channel = info_element->data[0];
+                       network->channel = info_element->data[0];
                        break;
 
                case MFIE_TYPE_FH_SET:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
                        break;
 
                case MFIE_TYPE_CF_SET:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
                        break;
 
                case MFIE_TYPE_TIM:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
+                       break;
+
+               case MFIE_TYPE_ERP_INFO:
+                       network->erp_value = info_element->data[0];
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
+                                            network->erp_value);
                        break;
 
                case MFIE_TYPE_IBSS_SET:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
+                       network->atim_window = info_element->data[0];
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
+                                            network->atim_window);
                        break;
 
                case MFIE_TYPE_CHALLENGE:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
                        break;
 
                case MFIE_TYPE_GENERIC:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
                                             info_element->len);
+                       if (!ieee80211_parse_qos_info_param_IE(info_element,
+                                                              network))
+                               break;
+
                        if (info_element->len >= 4 &&
                            info_element->data[0] == 0x00 &&
                            info_element->data[1] == 0x50 &&
@@ -940,7 +1066,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
                        break;
 
                case MFIE_TYPE_RSN:
-                       IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
                                             info_element->len);
                        network->rsn_ie_len = min(info_element->len + 2,
                                                  MAX_WPA_IE_LEN);
@@ -948,18 +1074,127 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
                               network->rsn_ie_len);
                        break;
 
+               case MFIE_TYPE_QOS_PARAMETER:
+                       printk(KERN_ERR
+                              "QoS Error need to parse QOS_PARAMETER IE\n");
+                       break;
+
                default:
-                       IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
+                       IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
                                             info_element->id);
                        break;
                }
 
-               left -= sizeof(struct ieee80211_info_element_hdr) +
-                   info_element->len;
-               info_element = (struct ieee80211_info_element *)
-                   &info_element->data[info_element->len];
+               length -= sizeof(*info_element) + info_element->len;
+               info_element =
+                   (struct ieee80211_info_element *)&info_element->
+                   data[info_element->len];
+       }
+
+       return 0;
+}
+
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
+                                      *frame, struct ieee80211_rx_stats *stats)
+{
+       struct ieee80211_network network_resp;
+       struct ieee80211_network *network = &network_resp;
+       struct net_device *dev = ieee->dev;
+
+       network->flags = 0;
+       network->qos_data.active = 0;
+       network->qos_data.supported = 0;
+       network->qos_data.param_count = 0;
+       network->qos_data.old_param_count = 0;
+
+       //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
+       network->atim_window = le16_to_cpu(frame->aid);
+       network->listen_interval = le16_to_cpu(frame->status);
+       memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
+       network->capability = le16_to_cpu(frame->capability);
+       network->last_scanned = jiffies;
+       network->rates_len = network->rates_ex_len = 0;
+       network->last_associate = 0;
+       network->ssid_len = 0;
+       network->erp_value =
+           (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
+
+       if (stats->freq == IEEE80211_52GHZ_BAND) {
+               /* for A band (No DS info) */
+               network->channel = stats->received_channel;
+       } else
+               network->flags |= NETWORK_HAS_CCK;
+
+       network->wpa_ie_len = 0;
+       network->rsn_ie_len = 0;
+
+       if (ieee80211_parse_info_param
+           (frame->info_element, stats->len - sizeof(*frame), network))
+               return 1;
+
+       network->mode = 0;
+       if (stats->freq == IEEE80211_52GHZ_BAND)
+               network->mode = IEEE_A;
+       else {
+               if (network->flags & NETWORK_HAS_OFDM)
+                       network->mode |= IEEE_G;
+               if (network->flags & NETWORK_HAS_CCK)
+                       network->mode |= IEEE_B;
        }
 
+       if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
+               network->flags |= NETWORK_EMPTY_ESSID;
+
+       memcpy(&network->stats, stats, sizeof(network->stats));
+
+       if (ieee->handle_assoc_response != NULL)
+               ieee->handle_assoc_response(dev, frame, network);
+
+       return 0;
+}
+
+/***************************************************/
+
+static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
+                                        *beacon,
+                                        struct ieee80211_network *network,
+                                        struct ieee80211_rx_stats *stats)
+{
+       network->qos_data.active = 0;
+       network->qos_data.supported = 0;
+       network->qos_data.param_count = 0;
+       network->qos_data.old_param_count = 0;
+
+       /* Pull out fixed field data */
+       memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+       network->capability = le16_to_cpu(beacon->capability);
+       network->last_scanned = jiffies;
+       network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+       network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+       network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
+       /* Where to pull this? beacon->listen_interval; */
+       network->listen_interval = 0x0A;
+       network->rates_len = network->rates_ex_len = 0;
+       network->last_associate = 0;
+       network->ssid_len = 0;
+       network->flags = 0;
+       network->atim_window = 0;
+       network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+           0x3 : 0x0;
+
+       if (stats->freq == IEEE80211_52GHZ_BAND) {
+               /* for A band (No DS info) */
+               network->channel = stats->received_channel;
+       } else
+               network->flags |= NETWORK_HAS_CCK;
+
+       network->wpa_ie_len = 0;
+       network->rsn_ie_len = 0;
+
+       if (ieee80211_parse_info_param
+           (beacon->info_element, stats->len - sizeof(*beacon), network))
+               return 1;
+
        network->mode = 0;
        if (stats->freq == IEEE80211_52GHZ_BAND)
                network->mode = IEEE_A;
@@ -1002,6 +1237,9 @@ static inline int is_same_network(struct ieee80211_network *src,
 static inline void update_network(struct ieee80211_network *dst,
                                  struct ieee80211_network *src)
 {
+       int qos_active;
+       u8 old_param;
+
        memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
        dst->capability = src->capability;
        memcpy(dst->rates, src->rates, src->rates_len);
@@ -1017,6 +1255,7 @@ static inline void update_network(struct ieee80211_network *dst,
        dst->beacon_interval = src->beacon_interval;
        dst->listen_interval = src->listen_interval;
        dst->atim_window = src->atim_window;
+       dst->erp_value = src->erp_value;
 
        memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
        dst->wpa_ie_len = src->wpa_ie_len;
@@ -1024,22 +1263,48 @@ static inline void update_network(struct ieee80211_network *dst,
        dst->rsn_ie_len = src->rsn_ie_len;
 
        dst->last_scanned = jiffies;
+       qos_active = src->qos_data.active;
+       old_param = dst->qos_data.old_param_count;
+       if (dst->flags & NETWORK_HAS_QOS_MASK)
+               memcpy(&dst->qos_data, &src->qos_data,
+                      sizeof(struct ieee80211_qos_data));
+       else {
+               dst->qos_data.supported = src->qos_data.supported;
+               dst->qos_data.param_count = src->qos_data.param_count;
+       }
+
+       if (dst->qos_data.supported == 1) {
+               if (dst->ssid_len)
+                       IEEE80211_DEBUG_QOS
+                           ("QoS the network %s is QoS supported\n",
+                            dst->ssid);
+               else
+                       IEEE80211_DEBUG_QOS
+                           ("QoS the network is QoS supported\n");
+       }
+       dst->qos_data.active = qos_active;
+       dst->qos_data.old_param_count = old_param;
+
        /* dst->last_associate is not overwritten */
 }
 
+static inline int is_beacon(int fc)
+{
+       return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
+}
+
 static inline void ieee80211_process_probe_response(struct ieee80211_device
-                                                   *ieee,
-                                                   struct
+                                                   *ieee, struct
                                                    ieee80211_probe_response
-                                                   *beacon,
-                                                   struct ieee80211_rx_stats
+                                                   *beacon, struct ieee80211_rx_stats
                                                    *stats)
 {
+       struct net_device *dev = ieee->dev;
        struct ieee80211_network network;
        struct ieee80211_network *target;
        struct ieee80211_network *oldest = NULL;
 #ifdef CONFIG_IEEE80211_DEBUG
-       struct ieee80211_info_element *info_element = &beacon->info_element;
+       struct ieee80211_info_element *info_element = beacon->info_element;
 #endif
        unsigned long flags;
 
@@ -1070,10 +1335,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
                                     escape_essid(info_element->data,
                                                  info_element->len),
                                     MAC_ARG(beacon->header.addr3),
-                                    WLAN_FC_GET_STYPE(beacon->header.
-                                                      frame_ctl) ==
-                                    IEEE80211_STYPE_PROBE_RESP ?
-                                    "PROBE RESPONSE" : "BEACON");
+                                    is_beacon(le16_to_cpu
+                                              (beacon->header.
+                                               frame_ctl)) ?
+                                    "BEACON" : "PROBE RESPONSE");
                return;
        }
 
@@ -1122,10 +1387,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
                                     escape_essid(network.ssid,
                                                  network.ssid_len),
                                     MAC_ARG(network.bssid),
-                                    WLAN_FC_GET_STYPE(beacon->header.
-                                                      frame_ctl) ==
-                                    IEEE80211_STYPE_PROBE_RESP ?
-                                    "PROBE RESPONSE" : "BEACON");
+                                    is_beacon(le16_to_cpu
+                                              (beacon->header.
+                                               frame_ctl)) ?
+                                    "BEACON" : "PROBE RESPONSE");
 #endif
                memcpy(target, &network, sizeof(*target));
                list_add_tail(&target->list, &ieee->network_list);
@@ -1134,34 +1399,60 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
                                     escape_essid(target->ssid,
                                                  target->ssid_len),
                                     MAC_ARG(target->bssid),
-                                    WLAN_FC_GET_STYPE(beacon->header.
-                                                      frame_ctl) ==
-                                    IEEE80211_STYPE_PROBE_RESP ?
-                                    "PROBE RESPONSE" : "BEACON");
+                                    is_beacon(le16_to_cpu
+                                              (beacon->header.
+                                               frame_ctl)) ?
+                                    "BEACON" : "PROBE RESPONSE");
                update_network(target, &network);
        }
 
        spin_unlock_irqrestore(&ieee->lock, flags);
+
+       if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
+               if (ieee->handle_beacon != NULL)
+                       ieee->handle_beacon(dev, beacon, &network);
+       } else {
+               if (ieee->handle_probe_response != NULL)
+                       ieee->handle_probe_response(dev, beacon, &network);
+       }
 }
 
 void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-                     struct ieee80211_hdr *header,
+                     struct ieee80211_hdr_4addr *header,
                      struct ieee80211_rx_stats *stats)
 {
-       switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+       switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
        case IEEE80211_STYPE_ASSOC_RESP:
                IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
-                                    WLAN_FC_GET_STYPE(header->frame_ctl));
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+               ieee80211_handle_assoc_resp(ieee,
+                                           (struct ieee80211_assoc_response *)
+                                           header, stats);
                break;
 
        case IEEE80211_STYPE_REASSOC_RESP:
                IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
-                                    WLAN_FC_GET_STYPE(header->frame_ctl));
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+               break;
+
+       case IEEE80211_STYPE_PROBE_REQ:
+               IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+
+               if (ieee->handle_probe_request != NULL)
+                       ieee->handle_probe_request(ieee->dev,
+                                                  (struct
+                                                   ieee80211_probe_request *)
+                                                  header, stats);
                break;
 
        case IEEE80211_STYPE_PROBE_RESP:
                IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
-                                    WLAN_FC_GET_STYPE(header->frame_ctl));
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
                IEEE80211_DEBUG_SCAN("Probe response\n");
                ieee80211_process_probe_response(ieee,
                                                 (struct
@@ -1171,20 +1462,46 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
 
        case IEEE80211_STYPE_BEACON:
                IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
-                                    WLAN_FC_GET_STYPE(header->frame_ctl));
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
                IEEE80211_DEBUG_SCAN("Beacon\n");
                ieee80211_process_probe_response(ieee,
                                                 (struct
                                                  ieee80211_probe_response *)
                                                 header, stats);
                break;
+       case IEEE80211_STYPE_AUTH:
 
+               IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+
+               if (ieee->handle_auth != NULL)
+                       ieee->handle_auth(ieee->dev,
+                                         (struct ieee80211_auth *)header);
+               break;
+
+       case IEEE80211_STYPE_DISASSOC:
+               if (ieee->handle_disassoc != NULL)
+                       ieee->handle_disassoc(ieee->dev,
+                                             (struct ieee80211_disassoc *)
+                                             header);
+               break;
+
+       case IEEE80211_STYPE_DEAUTH:
+               printk("DEAUTH from AP\n");
+               if (ieee->handle_deauth != NULL)
+                       ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
+                                           header);
+               break;
        default:
                IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
-                                    WLAN_FC_GET_STYPE(header->frame_ctl));
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
                IEEE80211_WARNING("%s: Unknown management packet: %d\n",
                                  ieee->dev->name,
-                                 WLAN_FC_GET_STYPE(header->frame_ctl));
+                                 WLAN_FC_GET_STYPE(le16_to_cpu
+                                                   (header->frame_ctl)));
                break;
        }
 }
index eed07bbbe6b6282972d47815bf1f43cd7e69e018..42c50619aa8e3a1d0d60c978fa87aa009005b286 100644 (file)
@@ -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 @@ payload of each frame is reduced to 492 bytes.
 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,31 +157,11 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
        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);
@@ -236,25 +216,31 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
        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);
 
@@ -276,7 +262,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        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) {
@@ -285,8 +275,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* 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));
@@ -294,7 +284,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        /* 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
@@ -302,50 +292,90 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 
        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,
@@ -357,15 +387,47 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                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
@@ -379,11 +441,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                        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);
                }
 
@@ -394,8 +455,19 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 
                /* 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);
@@ -407,11 +479,20 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        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);
        }
 
@@ -422,7 +503,72 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        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);
index 94882f39b0728f9ec92c11f7545f9755bdd10c90..1ce7af9bec35a167b8e17512ec7ab716a2013549 100644 (file)
@@ -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
@@ -32,6 +32,7 @@
 
 #include <linux/kmod.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #include <net/ieee80211.h>
 #include <linux/wireless.h>
@@ -140,18 +141,41 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
                start = iwe_stream_add_point(start, stop, &iwe, custom);
 
        /* Add quality statistics */
-       /* TODO: Fix these values... */
        iwe.cmd = IWEVQUAL;
-       iwe.u.qual.qual = network->stats.signal;
-       iwe.u.qual.level = network->stats.rssi;
-       iwe.u.qual.noise = network->stats.noise;
-       iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
-       if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
-               iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
-       if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
+       iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+           IW_QUAL_NOISE_UPDATED;
+
+       if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
+               iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
+                   IW_QUAL_LEVEL_INVALID;
+               iwe.u.qual.qual = 0;
+               iwe.u.qual.level = 0;
+       } else {
+               iwe.u.qual.level = network->stats.rssi;
+               if (ieee->perfect_rssi == ieee->worst_rssi)
+                       iwe.u.qual.qual = 100;
+               else
+                       iwe.u.qual.qual =
+                           (100 *
+                            (ieee->perfect_rssi - ieee->worst_rssi) *
+                            (ieee->perfect_rssi - ieee->worst_rssi) -
+                            (ieee->perfect_rssi - network->stats.rssi) *
+                            (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
+                             62 * (ieee->perfect_rssi - network->stats.rssi))) /
+                           ((ieee->perfect_rssi - ieee->worst_rssi) *
+                            (ieee->perfect_rssi - ieee->worst_rssi));
+               if (iwe.u.qual.qual > 100)
+                       iwe.u.qual.qual = 100;
+               else if (iwe.u.qual.qual < 1)
+                       iwe.u.qual.qual = 0;
+       }
+
+       if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
                iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
-       if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
-               iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+               iwe.u.qual.noise = 0;
+       } else {
+               iwe.u.qual.noise = network->stats.noise;
+       }
 
        start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
 
@@ -162,7 +186,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
        if (iwe.u.data.length)
                start = iwe_stream_add_point(start, stop, &iwe, custom);
 
-       if (ieee->wpa_enabled && network->wpa_ie_len) {
+       if (network->wpa_ie_len) {
                char buf[MAX_WPA_IE_LEN * 2 + 30];
 
                u8 *p = buf;
@@ -177,7 +201,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
                start = iwe_stream_add_point(start, stop, &iwe, buf);
        }
 
-       if (ieee->wpa_enabled && network->rsn_ie_len) {
+       if (network->rsn_ie_len) {
                char buf[MAX_WPA_IE_LEN * 2 + 30];
 
                u8 *p = buf;
@@ -197,8 +221,8 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
        iwe.cmd = IWEVCUSTOM;
        p = custom;
        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-                     " Last beacon: %lums ago",
-                     (jiffies - network->last_scanned) / (HZ / 100));
+                     " Last beacon: %dms ago",
+                     jiffies_to_msecs(jiffies - network->last_scanned));
        iwe.u.data.length = p - custom;
        if (iwe.u.data.length)
                start = iwe_stream_add_point(start, stop, &iwe, custom);
@@ -228,13 +252,13 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
                        ev = ipw2100_translate_scan(ieee, ev, stop, network);
                else
                        IEEE80211_DEBUG_SCAN("Not showing network '%s ("
-                                            MAC_FMT ")' due to age (%lums).\n",
+                                            MAC_FMT ")' due to age (%dms).\n",
                                             escape_essid(network->ssid,
                                                          network->ssid_len),
                                             MAC_ARG(network->bssid),
-                                            (jiffies -
-                                             network->last_scanned) / (HZ /
-                                                                       100));
+                                            jiffies_to_msecs(jiffies -
+                                                             network->
+                                                             last_scanned));
        }
 
        spin_unlock_irqrestore(&ieee->lock, flags);
@@ -258,6 +282,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
        };
        int i, key, key_provided, len;
        struct ieee80211_crypt_data **crypt;
+       int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
 
        IEEE80211_DEBUG_WX("SET_ENCODE\n");
 
@@ -298,15 +323,17 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 
                if (i == WEP_KEYS) {
                        sec.enabled = 0;
+                       sec.encrypt = 0;
                        sec.level = SEC_LEVEL_0;
-                       sec.flags |= SEC_ENABLED | SEC_LEVEL;
+                       sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
                }
 
                goto done;
        }
 
        sec.enabled = 1;
-       sec.flags |= SEC_ENABLED;
+       sec.encrypt = 1;
+       sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
 
        if (*crypt != NULL && (*crypt)->ops != NULL &&
            strcmp((*crypt)->ops->name, "WEP") != 0) {
@@ -315,7 +342,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                ieee80211_crypt_delayed_deinit(ieee, crypt);
        }
 
-       if (*crypt == NULL) {
+       if (*crypt == NULL && host_crypto) {
                struct ieee80211_crypt_data *new_crypt;
 
                /* take WEP into use */
@@ -355,49 +382,56 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                                   key, escape_essid(sec.keys[key], len),
                                   erq->length, len);
                sec.key_sizes[key] = len;
-               (*crypt)->ops->set_key(sec.keys[key], len, NULL,
-                                      (*crypt)->priv);
+               if (*crypt)
+                       (*crypt)->ops->set_key(sec.keys[key], len, NULL,
+                                              (*crypt)->priv);
                sec.flags |= (1 << key);
                /* This ensures a key will be activated if no key is
                 * explicitely set */
                if (key == sec.active_key)
                        sec.flags |= SEC_ACTIVE_KEY;
+
        } else {
-               len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
-                                            NULL, (*crypt)->priv);
-               if (len == 0) {
-                       /* Set a default key of all 0 */
-                       IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
-                                          key);
-                       memset(sec.keys[key], 0, 13);
-                       (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
-                                              (*crypt)->priv);
-                       sec.key_sizes[key] = 13;
-                       sec.flags |= (1 << key);
+               if (host_crypto) {
+                       len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+                                                    NULL, (*crypt)->priv);
+                       if (len == 0) {
+                               /* Set a default key of all 0 */
+                               IEEE80211_DEBUG_WX("Setting key %d to all "
+                                                  "zero.\n", key);
+                               memset(sec.keys[key], 0, 13);
+                               (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+                                                      (*crypt)->priv);
+                               sec.key_sizes[key] = 13;
+                               sec.flags |= (1 << key);
+                       }
                }
-
                /* No key data - just set the default TX key index */
                if (key_provided) {
-                       IEEE80211_DEBUG_WX
-                           ("Setting key %d to default Tx key.\n", key);
+                       IEEE80211_DEBUG_WX("Setting key %d to default Tx "
+                                          "key.\n", key);
                        ieee->tx_keyidx = key;
                        sec.active_key = key;
                        sec.flags |= SEC_ACTIVE_KEY;
                }
        }
-
-      done:
-       ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
-       sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-       sec.flags |= SEC_AUTH_MODE;
-       IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
-                          "OPEN" : "SHARED KEY");
+       if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
+               ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+               sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
+                   WLAN_AUTH_SHARED_KEY;
+               sec.flags |= SEC_AUTH_MODE;
+               IEEE80211_DEBUG_WX("Auth: %s\n",
+                                  sec.auth_mode == WLAN_AUTH_OPEN ?
+                                  "OPEN" : "SHARED KEY");
+       }
 
        /* For now we just support WEP, so only set that security level...
         * TODO: When WPA is added this is one place that needs to change */
        sec.flags |= SEC_LEVEL;
        sec.level = SEC_LEVEL_1;        /* 40 and 104 bit WEP */
+       sec.encode_alg[key] = SEC_ALG_WEP;
 
+      done:
        if (ieee->set_security)
                ieee->set_security(dev, &sec);
 
@@ -422,6 +456,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
        struct iw_point *erq = &(wrqu->encoding);
        int len, key;
        struct ieee80211_crypt_data *crypt;
+       struct ieee80211_security *sec = &ieee->sec;
 
        IEEE80211_DEBUG_WX("GET_ENCODE\n");
 
@@ -436,23 +471,16 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
        crypt = ieee->crypt[key];
        erq->flags = key + 1;
 
-       if (crypt == NULL || crypt->ops == NULL) {
+       if (!sec->enabled) {
                erq->length = 0;
                erq->flags |= IW_ENCODE_DISABLED;
                return 0;
        }
 
-       if (strcmp(crypt->ops->name, "WEP") != 0) {
-               /* only WEP is supported with wireless extensions, so just
-                * report that encryption is used */
-               erq->length = 0;
-               erq->flags |= IW_ENCODE_ENABLED;
-               return 0;
-       }
+       len = sec->key_sizes[key];
+       memcpy(keybuf, sec->keys[key], len);
 
-       len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
        erq->length = (len >= 0 ? len : 0);
-
        erq->flags |= IW_ENCODE_ENABLED;
 
        if (ieee->open_wep)
@@ -463,6 +491,240 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
        return 0;
 }
 
+int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct net_device *dev = ieee->dev;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int i, idx, ret = 0;
+       int group_key = 0;
+       const char *alg, *module;
+       struct ieee80211_crypto_ops *ops;
+       struct ieee80211_crypt_data **crypt;
+
+       struct ieee80211_security sec = {
+               .flags = 0,
+       };
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > WEP_KEYS)
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = ieee->tx_keyidx;
+
+       if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+               crypt = &ieee->crypt[idx];
+               group_key = 1;
+       } else {
+               if (idx != 0)
+                       return -EINVAL;
+               if (ieee->iw_mode == IW_MODE_INFRA)
+                       crypt = &ieee->crypt[idx];
+               else
+                       return -EINVAL;
+       }
+
+       sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
+       if ((encoding->flags & IW_ENCODE_DISABLED) ||
+           ext->alg == IW_ENCODE_ALG_NONE) {
+               if (*crypt)
+                       ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+               for (i = 0; i < WEP_KEYS; i++)
+                       if (ieee->crypt[i] != NULL)
+                               break;
+
+               if (i == WEP_KEYS) {
+                       sec.enabled = 0;
+                       sec.encrypt = 0;
+                       sec.level = SEC_LEVEL_0;
+                       sec.flags |= SEC_LEVEL;
+               }
+               goto done;
+       }
+
+       sec.enabled = 1;
+       sec.encrypt = 1;
+
+       if (group_key ? !ieee->host_mc_decrypt :
+           !(ieee->host_encrypt || ieee->host_decrypt ||
+             ieee->host_encrypt_msdu))
+               goto skip_host_crypt;
+
+       switch (ext->alg) {
+       case IW_ENCODE_ALG_WEP:
+               alg = "WEP";
+               module = "ieee80211_crypt_wep";
+               break;
+       case IW_ENCODE_ALG_TKIP:
+               alg = "TKIP";
+               module = "ieee80211_crypt_tkip";
+               break;
+       case IW_ENCODE_ALG_CCMP:
+               alg = "CCMP";
+               module = "ieee80211_crypt_ccmp";
+               break;
+       default:
+               IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+                                  dev->name, ext->alg);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       ops = ieee80211_get_crypto_ops(alg);
+       if (ops == NULL) {
+               request_module(module);
+               ops = ieee80211_get_crypto_ops(alg);
+       }
+       if (ops == NULL) {
+               IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+                                  dev->name, ext->alg);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (*crypt == NULL || (*crypt)->ops != ops) {
+               struct ieee80211_crypt_data *new_crypt;
+
+               ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+               new_crypt = (struct ieee80211_crypt_data *)
+                   kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+               if (new_crypt == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+               memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+               new_crypt->ops = ops;
+               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+                       new_crypt->priv = new_crypt->ops->init(idx);
+               if (new_crypt->priv == NULL) {
+                       kfree(new_crypt);
+                       ret = -EINVAL;
+                       goto done;
+               }
+               *crypt = new_crypt;
+       }
+
+       if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+           (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+                                  (*crypt)->priv) < 0) {
+               IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
+               ret = -EINVAL;
+               goto done;
+       }
+
+      skip_host_crypt:
+       if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+               ieee->tx_keyidx = idx;
+               sec.active_key = idx;
+               sec.flags |= SEC_ACTIVE_KEY;
+       }
+
+       if (ext->alg != IW_ENCODE_ALG_NONE) {
+               memcpy(sec.keys[idx], ext->key, ext->key_len);
+               sec.key_sizes[idx] = ext->key_len;
+               sec.flags |= (1 << idx);
+               if (ext->alg == IW_ENCODE_ALG_WEP) {
+                       sec.encode_alg[idx] = SEC_ALG_WEP;
+                       sec.flags |= SEC_LEVEL;
+                       sec.level = SEC_LEVEL_1;
+               } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+                       sec.encode_alg[idx] = SEC_ALG_TKIP;
+                       sec.flags |= SEC_LEVEL;
+                       sec.level = SEC_LEVEL_2;
+               } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+                       sec.encode_alg[idx] = SEC_ALG_CCMP;
+                       sec.flags |= SEC_LEVEL;
+                       sec.level = SEC_LEVEL_3;
+               }
+               /* Don't set sec level for group keys. */
+               if (group_key)
+                       sec.flags &= ~SEC_LEVEL;
+       }
+      done:
+       if (ieee->set_security)
+               ieee->set_security(ieee->dev, &sec);
+
+       /*
+        * Do not reset port if card is in Managed mode since resetting will
+        * generate new IEEE 802.11 authentication which may end up in looping
+        * with IEEE 802.1X. If your hardware requires a reset after WEP
+        * configuration (for example... Prism2), implement the reset_port in
+        * the callbacks structures used to initialize the 802.11 stack.
+        */
+       if (ieee->reset_on_keychange &&
+           ieee->iw_mode != IW_MODE_INFRA &&
+           ieee->reset_port && ieee->reset_port(dev)) {
+               IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       struct ieee80211_security *sec = &ieee->sec;
+       int idx, max_key_len;
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > WEP_KEYS)
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = ieee->tx_keyidx;
+
+       if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+               if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
+                       return -EINVAL;
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       if (!sec->enabled) {
+               ext->alg = IW_ENCODE_ALG_NONE;
+               ext->key_len = 0;
+               encoding->flags |= IW_ENCODE_DISABLED;
+       } else {
+               if (sec->encode_alg[idx] == SEC_ALG_WEP)
+                       ext->alg = IW_ENCODE_ALG_WEP;
+               else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
+                       ext->alg = IW_ENCODE_ALG_TKIP;
+               else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
+                       ext->alg = IW_ENCODE_ALG_CCMP;
+               else
+                       return -EINVAL;
+
+               ext->key_len = sec->key_sizes[idx];
+               memcpy(ext->key, sec->keys[idx], ext->key_len);
+               encoding->flags |= IW_ENCODE_ENABLED;
+               if (ext->key_len &&
+                   (ext->alg == IW_ENCODE_ALG_TKIP ||
+                    ext->alg == IW_ENCODE_ALG_CCMP))
+                       ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
+EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
+
 EXPORT_SYMBOL(ieee80211_wx_get_scan);
 EXPORT_SYMBOL(ieee80211_wx_set_encode);
 EXPORT_SYMBOL(ieee80211_wx_get_encode);