From f03aa2d89ad600a1ed21a223f196776f217cfe00 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 14 Jan 2006 03:10:22 +0100 Subject: [PATCH] drivers/net/arcnet/: possible cleanups This patch contains the following possible cleanups: - make needlessly global code static - arcnet.c: remove the unneeded EXPORT_SYMBOL(arc_proto_null) - arcnet.c: remove the unneeded EXPORT_SYMBOL(arcnet_dump_packet) To make Jeff happy, arcnet.c still prints arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- include/linux/arcdevice.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 7198f129e135..231ba090ae34 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -206,7 +206,6 @@ struct ArcProto { extern struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto, *arc_raw_proto; -extern struct ArcProto arc_proto_null; /* @@ -334,17 +333,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #define arcnet_dump_skb(dev,skb,desc) ; #endif -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, - int take_arcnet_lock); -#else -#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) ; -#endif - void arcnet_unregister_proto(struct ArcProto *proto); irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs); struct net_device *alloc_arcdev(char *name); -void arcnet_rx(struct net_device *dev, int bufnum); #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ -- cgit v1.2.3 From d0412d967032b9e147bcbacc9ff0c0342636cf2d Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 27 Jan 2006 01:15:30 -0700 Subject: [PATCH] mv643xx_eth: use MII library for ethtool functions Use the common ethtool support functions of the MII library. Add generic MII ioctl handler. Add PHY parameter speed/duplex/negotiation initialization and modification. Signed-off-by: James Chapman Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 351 +++++++++++++++++++++++++++------------------- include/linux/mv643xx.h | 3 + 2 files changed, 213 insertions(+), 141 deletions(-) (limited to 'include') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index bca7257c707a..ff2b613a7436 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -101,6 +101,7 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); static int ethernet_phy_detect(unsigned int eth_port_num); static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location); static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val); +static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static struct ethtool_ops mv643xx_ethtool_ops; static char mv643xx_driver_name[] = "mv643xx_eth"; @@ -457,6 +458,56 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) return received_packets; } +/* Set the mv643xx port configuration register for the speed/duplex mode. */ +static void mv643xx_eth_update_pscr(struct net_device *dev, + struct ethtool_cmd *ecmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int port_num = mp->port_num; + u32 o_pscr, n_pscr; + unsigned int channels; + + o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + n_pscr = o_pscr; + + /* clear speed, duplex and rx buffer size fields */ + n_pscr &= ~(MV643XX_ETH_SET_MII_SPEED_TO_100 | + MV643XX_ETH_SET_GMII_SPEED_TO_1000 | + MV643XX_ETH_SET_FULL_DUPLEX_MODE | + MV643XX_ETH_MAX_RX_PACKET_MASK); + + if (ecmd->duplex == DUPLEX_FULL) + n_pscr |= MV643XX_ETH_SET_FULL_DUPLEX_MODE; + + if (ecmd->speed == SPEED_1000) + n_pscr |= MV643XX_ETH_SET_GMII_SPEED_TO_1000 | + MV643XX_ETH_MAX_RX_PACKET_9700BYTE; + else { + if (ecmd->speed == SPEED_100) + n_pscr |= MV643XX_ETH_SET_MII_SPEED_TO_100; + n_pscr |= MV643XX_ETH_MAX_RX_PACKET_1522BYTE; + } + + if (n_pscr != o_pscr) { + if ((o_pscr & MV643XX_ETH_SERIAL_PORT_ENABLE) == 0) + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + else { + channels = mv643xx_eth_port_disable_tx(port_num); + + o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + o_pscr); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + if (channels) + mv643xx_eth_port_enable_tx(port_num, channels); + } + } +} + /* * mv643xx_eth_int_handler * @@ -539,13 +590,19 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, } /* PHY status changed */ if (eth_int_cause_ext & (BIT16 | BIT20)) { + struct ethtool_cmd cmd; + if (mii_link_ok(&mp->mii)) { + mii_ethtool_gset(&mp->mii, &cmd); + mv643xx_eth_update_pscr(dev, &cmd); if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - netif_wake_queue(dev); - /* Start TX queue */ - mv643xx_eth_port_enable_tx(port_num, - mp->port_tx_queue_command); + if (mp->tx_ring_size > mp->tx_desc_count + + MAX_DESCS_PER_SKB) { + netif_wake_queue(dev); + /* Start TX queue */ + mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); + } } } else if (netif_carrier_ok(dev)) { netif_stop_queue(dev); @@ -729,6 +786,34 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) mp->port_tx_queue_command = 1; } +static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int err; + + spin_lock_irq(&mp->lock); + err = mii_ethtool_sset(&mp->mii, cmd); + spin_unlock_irq(&mp->lock); + + return err; +} + +static int mv643xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int err; + + spin_lock_irq(&mp->lock); + err = mii_ethtool_gset(&mp->mii, cmd); + spin_unlock_irq(&mp->lock); + + /* The PHY may support 1000baseT_Half, but the mv643xx does not */ + cmd->supported &= ~SUPPORTED_1000baseT_Half; + cmd->advertising &= ~ADVERTISED_1000baseT_Half; + + return err; +} + /* * mv643xx_eth_open * @@ -842,6 +927,10 @@ static int mv643xx_eth_open(struct net_device *dev) mv643xx_eth_rx_task(dev); /* Fill RX ring with skb's */ + /* Clear any pending ethernet port interrupts */ + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + eth_port_start(dev); /* Interrupt Coalescing */ @@ -854,16 +943,13 @@ static int mv643xx_eth_open(struct net_device *dev) mp->tx_int_coal = eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL); - /* Clear any pending ethernet port interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); - /* Unmask phy and link status changes interrupts */ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), INT_UNMASK_ALL_EXT); /* Unmask RX buffer and TX end interrupt */ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL); + return 0; out_free_tx_skb: @@ -1318,6 +1404,35 @@ static void mv643xx_netpoll(struct net_device *netdev) } #endif +static void mv643xx_init_ethtool_cmd(struct net_device *dev, int phy_address, + int speed, int duplex, + struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->port = PORT_MII; + cmd->transceiver = XCVR_INTERNAL; + cmd->phy_address = phy_address; + + if (speed == 0) { + cmd->autoneg = AUTONEG_ENABLE; + /* mii lib checks, but doesn't use speed on AUTONEG_ENABLE */ + cmd->speed = SPEED_100; + cmd->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + if (mp->mii.supports_gmii) + cmd->advertising |= ADVERTISED_1000baseT_Full; + } else { + cmd->autoneg = AUTONEG_DISABLE; + cmd->speed = speed; + cmd->duplex = duplex; + } +} + /*/ * mv643xx_eth_probe * @@ -1338,6 +1453,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev) u8 *p; struct resource *res; int err; + struct ethtool_cmd cmd; + u32 pscr; + int duplex; + int speed; dev = alloc_etherdev(sizeof(struct mv643xx_private)); if (!dev) @@ -1375,6 +1494,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->tx_queue_len = mp->tx_ring_size; dev->base_addr = 0; dev->change_mtu = mv643xx_eth_change_mtu; + dev->do_ioctl = mv643xx_eth_do_ioctl; SET_ETHTOOL_OPS(dev, &mv643xx_ethtool_ops); #ifdef MV643XX_CHECKSUM_OFFLOAD_TX @@ -1452,10 +1572,35 @@ static int mv643xx_eth_probe(struct platform_device *pdev) pr_debug("MV643xx ethernet port %d: " "No PHY detected at addr %d\n", port_num, ethernet_phy_get(port_num)); - return err; + goto out; } + pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + pscr = mp->port_serial_control; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + + if (!(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX) && + !(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII)) + speed = 0; + else if (pscr & MV643XX_ETH_PORT_STATUS_GMII_1000) + speed = SPEED_1000; + else if (pscr & MV643XX_ETH_PORT_STATUS_MII_100) + speed = SPEED_100; + else + speed = SPEED_10; + + if (pscr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) + duplex = DUPLEX_FULL; + else + duplex = DUPLEX_HALF; + + ethernet_phy_reset(mp->port_num); mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); + mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd); + mv643xx_eth_update_pscr(dev, &cmd); + mv643xx_set_settings(dev, &cmd); err = register_netdev(dev); if (err) @@ -1775,8 +1920,6 @@ static void eth_port_init(struct mv643xx_private *mp) eth_port_reset(mp->port_num); eth_port_init_mac_tables(mp->port_num); - - ethernet_phy_reset(mp->port_num); } /* @@ -1811,6 +1954,8 @@ static void eth_port_start(struct net_device *dev) struct mv643xx_private *mp = netdev_priv(dev); unsigned int port_num = mp->port_num; int tx_curr_desc, rx_curr_desc; + u32 pscr; + struct ethtool_cmd ethtool_cmd; /* Assignment of Tx CTRP of given queue */ tx_curr_desc = mp->tx_curr_desc_q; @@ -1828,31 +1973,35 @@ static void eth_port_start(struct net_device *dev) /* Assign port configuration and command. */ mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config); - mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num), - mp->port_config_extend); + pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + pscr &= ~MV643XX_ETH_FORCE_LINK_PASS; + pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | + MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII | + MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX | + MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | + MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED; - /* Increase the Rx side buffer size if supporting GigE */ - if (mp->port_serial_control & MV643XX_ETH_SET_GMII_SPEED_TO_1000) - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - (mp->port_serial_control & 0xfff1ffff) | (0x5 << 17)); - else - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - mp->port_serial_control); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)) | - MV643XX_ETH_SERIAL_PORT_ENABLE); + pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); /* Assign port SDMA configuration */ - mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), - mp->port_sdma_config); + mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), mp->port_sdma_config); /* Enable port Rx. */ mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); /* Disable port bandwidth limits by clearing MTU register */ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); + + /* save phy settings across reset */ + mv643xx_get_settings(dev, ðtool_cmd); + ethernet_phy_reset(mp->port_num); + mv643xx_set_settings(dev, ðtool_cmd); } /* @@ -2324,6 +2473,12 @@ static void ethernet_phy_reset(unsigned int eth_port_num) eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data); phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data); + + /* wait for PHY to come out of reset */ + do { + udelay(1); + eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data); + } while (phy_reg_data & 0x8000); } static void mv643xx_eth_port_enable_tx(unsigned int port_num, @@ -2417,20 +2572,13 @@ static void eth_port_reset(unsigned int port_num) /* Reset the Enable bit in the Configuration Register */ reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - reg_data &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | + MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | + MV643XX_ETH_FORCE_LINK_PASS); mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); } -static int eth_port_autoneg_supported(unsigned int eth_port_num) -{ - unsigned int phy_reg_data0; - - eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data0); - - return phy_reg_data0 & 0x1000; -} - /* * eth_port_read_smi_reg - Read PHY registers * @@ -2989,111 +3137,6 @@ static const struct mv643xx_stats mv643xx_gstrings_stats[] = { #define MV643XX_STATS_LEN \ sizeof(mv643xx_gstrings_stats) / sizeof(struct mv643xx_stats) -static int -mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - struct mv643xx_private *mp = netdev->priv; - int port_num = mp->port_num; - int autoneg = eth_port_autoneg_supported(port_num); - int mode_10_bit; - int auto_duplex; - int half_duplex = 0; - int full_duplex = 0; - int auto_speed; - int speed_10 = 0; - int speed_100 = 0; - int speed_1000 = 0; - - u32 pcs = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - u32 psr = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)); - - mode_10_bit = psr & MV643XX_ETH_PORT_STATUS_MODE_10_BIT; - - if (mode_10_bit) { - ecmd->supported = SUPPORTED_10baseT_Half; - } else { - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - (autoneg ? SUPPORTED_Autoneg : 0) | - SUPPORTED_TP); - - auto_duplex = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX); - auto_speed = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII); - - ecmd->advertising = ADVERTISED_TP; - - if (autoneg) { - ecmd->advertising |= ADVERTISED_Autoneg; - - if (auto_duplex) { - half_duplex = 1; - full_duplex = 1; - } else { - if (pcs & MV643XX_ETH_SET_FULL_DUPLEX_MODE) - full_duplex = 1; - else - half_duplex = 1; - } - - if (auto_speed) { - speed_10 = 1; - speed_100 = 1; - speed_1000 = 1; - } else { - if (pcs & MV643XX_ETH_SET_GMII_SPEED_TO_1000) - speed_1000 = 1; - else if (pcs & MV643XX_ETH_SET_MII_SPEED_TO_100) - speed_100 = 1; - else - speed_10 = 1; - } - - if (speed_10 & half_duplex) - ecmd->advertising |= ADVERTISED_10baseT_Half; - if (speed_10 & full_duplex) - ecmd->advertising |= ADVERTISED_10baseT_Full; - if (speed_100 & half_duplex) - ecmd->advertising |= ADVERTISED_100baseT_Half; - if (speed_100 & full_duplex) - ecmd->advertising |= ADVERTISED_100baseT_Full; - if (speed_1000) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - } - } - - ecmd->port = PORT_TP; - ecmd->phy_address = ethernet_phy_get(port_num); - - ecmd->transceiver = XCVR_EXTERNAL; - - if (netif_carrier_ok(netdev)) { - if (mode_10_bit) - ecmd->speed = SPEED_10; - else { - if (psr & MV643XX_ETH_PORT_STATUS_GMII_1000) - ecmd->speed = SPEED_1000; - else if (psr & MV643XX_ETH_PORT_STATUS_MII_100) - ecmd->speed = SPEED_100; - else - ecmd->speed = SPEED_10; - } - - if (psr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ecmd->speed = -1; - ecmd->duplex = -1; - } - - ecmd->autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; - return 0; -} - static void mv643xx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { @@ -3140,15 +3183,41 @@ static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, } } +static u32 mv643xx_eth_get_link(struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return mii_link_ok(&mp->mii); +} + +static int mv643xx_eth_nway_restart(struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return mii_nway_restart(&mp->mii); +} + +static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); +} + static struct ethtool_ops mv643xx_ethtool_ops = { .get_settings = mv643xx_get_settings, + .set_settings = mv643xx_set_settings, .get_drvinfo = mv643xx_get_drvinfo, - .get_link = ethtool_op_get_link, + .get_link = mv643xx_eth_get_link, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_strings = mv643xx_get_strings, .get_stats_count = mv643xx_get_stats_count, .get_ethtool_stats = mv643xx_get_ethtool_stats, + .get_strings = mv643xx_get_strings, + .get_stats_count = mv643xx_get_stats_count, + .get_ethtool_stats = mv643xx_get_ethtool_stats, + .nway_reset = mv643xx_eth_nway_restart, }; /************* End ethtool support *************************/ diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 0b08cd692201..7ffbeac7d2bb 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -1214,6 +1214,7 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_FORCE_BP_MODE_NO_JAM 0 #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX (1<<7) #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1<<8) +#define MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED (1<<9) #define MV643XX_ETH_FORCE_LINK_FAIL 0 #define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL (1<<10) #define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS 0 @@ -1243,6 +1244,8 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_SET_MII_SPEED_TO_10 0 #define MV643XX_ETH_SET_MII_SPEED_TO_100 (1<<24) +#define MV643XX_ETH_MAX_RX_PACKET_MASK (0x7<<17) + #define MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE \ MV643XX_ETH_DO_NOT_FORCE_LINK_PASS | \ MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ -- cgit v1.2.3 From 01999873a455fe9104e91820c72849e608239928 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:18:01 -0700 Subject: [PATCH] mv643xx_eth: Clean up platform_data configuration We shouldn't expose the hardware register contents in platform_data. The only things we allow the user to configure are autoneg, speed, and duplex. Add specific platform_data fields for these values and remove the registers configs. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- arch/ppc/platforms/hdpu.c | 5 ++-- drivers/net/mv643xx_eth.c | 71 ++++++++++++++--------------------------------- drivers/net/mv643xx_eth.h | 4 --- include/linux/mv643xx.h | 24 ++++++---------- 4 files changed, 31 insertions(+), 73 deletions(-) (limited to 'include') diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index 50039a204c24..f945416960e9 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -319,11 +319,10 @@ static void __init hdpu_fixup_eth_pdata(struct platform_device *pd) struct mv643xx_eth_platform_data *eth_pd; eth_pd = pd->dev.platform_data; - eth_pd->port_serial_control = - mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1); - eth_pd->force_phy_addr = 1; eth_pd->phy_addr = pd->id; + eth_pd->speed = SPEED_100; + eth_pd->duplex = DUPLEX_FULL; eth_pd->tx_queue_size = 400; eth_pd->rx_queue_size = 800; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index ff2b613a7436..df572018595e 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -266,13 +266,14 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev) static void mv643xx_eth_set_rx_mode(struct net_device *dev) { struct mv643xx_private *mp = netdev_priv(dev); + u32 config_reg; + config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num)); if (dev->flags & IFF_PROMISC) - mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; + config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; else - mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; - - mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config); + config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; + mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), config_reg); eth_port_set_multicast_list(dev); } @@ -1454,9 +1455,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) struct resource *res; int err; struct ethtool_cmd cmd; - u32 pscr; - int duplex; - int speed; + int duplex = DUPLEX_HALF; + int speed = 0; /* default to auto-negotiation */ dev = alloc_etherdev(sizeof(struct mv643xx_private)); if (!dev) @@ -1515,33 +1515,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev) /* set default config values */ eth_port_uc_addr_get(dev, dev->dev_addr); - mp->port_config = MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE; - mp->port_config_extend = MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE; - mp->port_sdma_config = MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE; - mp->port_serial_control = MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE; mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE; mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE; pd = pdev->dev.platform_data; if (pd) { - if (pd->mac_addr != NULL) + if (pd->mac_addr) memcpy(dev->dev_addr, pd->mac_addr, 6); if (pd->phy_addr || pd->force_phy_addr) ethernet_phy_set(port_num, pd->phy_addr); - if (pd->port_config || pd->force_port_config) - mp->port_config = pd->port_config; - - if (pd->port_config_extend || pd->force_port_config_extend) - mp->port_config_extend = pd->port_config_extend; - - if (pd->port_sdma_config || pd->force_port_sdma_config) - mp->port_sdma_config = pd->port_sdma_config; - - if (pd->port_serial_control || pd->force_port_serial_control) - mp->port_serial_control = pd->port_serial_control; - if (pd->rx_queue_size) mp->rx_ring_size = pd->rx_queue_size; @@ -1557,6 +1541,9 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->rx_sram_size = pd->rx_sram_size; mp->rx_sram_addr = pd->rx_sram_addr; } + + duplex = pd->duplex; + speed = pd->speed; } /* Hook up MII support for ethtool */ @@ -1575,28 +1562,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) goto out; } - pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - pscr = mp->port_serial_control; - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - - if (!(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX) && - !(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII)) - speed = 0; - else if (pscr & MV643XX_ETH_PORT_STATUS_GMII_1000) - speed = SPEED_1000; - else if (pscr & MV643XX_ETH_PORT_STATUS_MII_100) - speed = SPEED_100; - else - speed = SPEED_10; - - if (pscr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) - duplex = DUPLEX_FULL; - else - duplex = DUPLEX_HALF; - - ethernet_phy_reset(mp->port_num); + ethernet_phy_reset(port_num); mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd); mv643xx_eth_update_pscr(dev, &cmd); @@ -1971,13 +1937,17 @@ static void eth_port_start(struct net_device *dev) eth_port_uc_addr_set(port_num, dev->dev_addr); /* Assign port configuration and command. */ - mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config); + mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), + MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE); + + mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num), + MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE); pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + + pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS); mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - pscr &= ~MV643XX_ETH_FORCE_LINK_PASS; pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII | MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX | @@ -1990,7 +1960,8 @@ static void eth_port_start(struct net_device *dev) mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); /* Assign port SDMA configuration */ - mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), mp->port_sdma_config); + mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), + MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE); /* Enable port Rx. */ mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index f2e5da79dde8..a553054e8da7 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -321,10 +321,6 @@ struct mv643xx_mib_counters { struct mv643xx_private { int port_num; /* User Ethernet port number */ - u32 port_config; /* User port configuration value*/ - u32 port_config_extend; /* User port config extend value*/ - u32 port_sdma_config; /* User port SDMA config value */ - u32 port_serial_control; /* User port serial control value */ u32 port_tx_queue_command; /* Port active Tx queues summary*/ u32 port_rx_queue_command; /* Port active Rx queues summary*/ diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 7ffbeac7d2bb..955d3069d727 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -1288,23 +1288,15 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_NAME "mv643xx_eth" struct mv643xx_eth_platform_data { - /* - * Non-values for mac_addr, phy_addr, port_config, etc. - * override the default value. Setting the corresponding - * force_* field, causes the default value to be overridden - * even when zero. - */ - unsigned int force_phy_addr:1; - unsigned int force_port_config:1; - unsigned int force_port_config_extend:1; - unsigned int force_port_sdma_config:1; - unsigned int force_port_serial_control:1; - int phy_addr; char *mac_addr; /* pointer to mac address */ - u32 port_config; - u32 port_config_extend; - u32 port_sdma_config; - u32 port_serial_control; + u16 force_phy_addr; /* force override if phy_addr == 0 */ + u16 phy_addr; + + /* If speed is 0, then speed and duplex are autonegotiated. */ + int speed; /* 0, SPEED_10, SPEED_100, SPEED_1000 */ + int duplex; /* DUPLEX_HALF or DUPLEX_FULL */ + + /* non-zero values of the following fields override defaults */ u32 tx_queue_size; u32 rx_queue_size; u32 tx_sram_addr; -- cgit v1.2.3 From 24056bec086aaa99923b21c0e1a0e993bb1c7e2a Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 19 Jan 2006 16:21:09 +0800 Subject: [PATCH] ieee80211: Add LEAP authentication type Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- include/net/ieee80211.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 9a92aef8b0b2..3424a3ed66c4 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -220,6 +220,7 @@ struct ieee80211_snap_hdr { /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_LEAP 2 #define WLAN_AUTH_CHALLENGE_LEN 128 -- cgit v1.2.3 From 9184d9348a7a0e60d70d5f4c23de79fdbc72b9a3 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 19 Jan 2006 16:22:32 +0800 Subject: [PATCH] ieee80211: Add TKIP crypt->build_iv This patch adds ieee80211 TKIP build_iv() method to support hardwares that can do TKIP encryption but relies on ieee80211 layer to build the IV. It also changes the build_iv() interface to return the key if possible after the IV is built (this is required by TKIP). Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- include/net/ieee80211_crypt.h | 3 +- net/ieee80211/ieee80211_crypt_ccmp.c | 8 ++++-- net/ieee80211/ieee80211_crypt_tkip.c | 53 ++++++++++++++++++------------------ net/ieee80211/ieee80211_crypt_wep.c | 5 ++-- net/ieee80211/ieee80211_tx.c | 4 ++- 5 files changed, 41 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h index cd82c3e998e4..eb476414fd72 100644 --- a/include/net/ieee80211_crypt.h +++ b/include/net/ieee80211_crypt.h @@ -47,7 +47,8 @@ struct ieee80211_crypto_ops { /* deinitialize crypto context and free allocated private data */ void (*deinit) (void *priv); - int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv); + int (*build_iv) (struct sk_buff * skb, int hdr_len, + u8 *key, int keylen, 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 diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 470221728503..097bcea2129f 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c @@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, ieee80211_ccmp_aes_encrypt(tfm, b0, s0); } -static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv) +static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, + u8 *aeskey, int keylen, void *priv) { struct ieee80211_ccmp_data *key = priv; int i; @@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv) if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len) return -1; + if (aeskey != NULL && keylen >= CCMP_TK_LEN) + memcpy(aeskey, key->key, CCMP_TK_LEN); + pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; @@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) return -1; data_len = skb->len - hdr_len; - len = ieee80211_ccmp_hdr(skb, hdr_len, priv); + len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv); if (len < 0) return -1; diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index de56a47edb00..93def94c1b32 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -270,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, #endif } -static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv) +static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, + u8 * rc4key, int keylen, void *priv) { struct ieee80211_tkip_data *tkey = priv; int len; - u8 *rc4key, *pos, *icv; + u8 *pos; struct ieee80211_hdr_4addr *hdr; - u32 crc; hdr = (struct ieee80211_hdr_4addr *)skb->data; if (skb_headroom(skb) < 8 || skb->len < hdr_len) - return NULL; + return -1; + + if (rc4key == NULL || keylen < 16) + return -1; 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; pos = skb_push(skb, 8); memmove(pos, pos + 8, hdr_len); pos += hdr_len; - icv = skb_put(skb, 4); *pos++ = *rc4key; *pos++ = *(rc4key + 1); @@ -308,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 16) & 0xff; *pos++ = (tkey->tx_iv32 >> 24) & 0xff; - crc = ~crc32_le(~0, pos, len); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; + tkey->tx_iv16++; + if (tkey->tx_iv16 == 0) { + tkey->tx_phase1_done = 0; + tkey->tx_iv32++; + } - return rc4key; + return 8; } 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; + u8 rc4key[16], *pos, *icv; + u32 crc; 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 " + printk(KERN_DEBUG ": TKIP countermeasures: dropped " "TX packet to " MAC_FMT "\n", MAC_ARG(hdr->addr1)); } @@ -342,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) len = skb->len - hdr_len; pos = skb->data + hdr_len; - rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv); - if (!rc4key) + if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) return -1; + icv = skb_put(skb, 4); + + crc = ~crc32_le(~0, pos, len); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); sg.page = virt_to_page(pos); sg.offset = offset_in_page(pos); sg.length = len + 4; crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); - tkey->tx_iv16++; - if (tkey->tx_iv16 == 0) { - tkey->tx_phase1_done = 0; - tkey->tx_iv32++; - } - return 0; } @@ -378,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP countermeasures: dropped " + printk(KERN_DEBUG ": TKIP countermeasures: dropped " "received packet from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); } @@ -694,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { .name = "TKIP", .init = ieee80211_tkip_init, .deinit = ieee80211_tkip_deinit, + .build_iv = ieee80211_tkip_hdr, .encrypt_mpdu = ieee80211_tkip_encrypt, .decrypt_mpdu = ieee80211_tkip_decrypt, .encrypt_msdu = ieee80211_michael_mic_add, diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index f8dca31be5dd..649e581fa565 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv) } /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ -static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv) +static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, + u8 *key, int keylen, void *priv) { struct prism2_wep_data *wep = priv; u32 klen, len; @@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) return -1; /* add the IV to the frame */ - if (prism2_wep_build_iv(skb, hdr_len, priv)) + if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv)) return -1; /* Copy the IV into the first 3 bytes of the key */ diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 0949803b9c7d..8b4332f53394 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) atomic_inc(&crypt->refcnt); if (crypt->ops->build_iv) crypt->ops->build_iv(skb_frag, hdr_len, - crypt->priv); + ieee->sec.keys[ieee->sec.active_key], + ieee->sec.key_sizes[ieee->sec.active_key], + crypt->priv); atomic_dec(&crypt->refcnt); } -- cgit v1.2.3 From b79e20b60997e427b701055a2c69fb0c1d507aa9 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 19 Jan 2006 16:21:27 +0800 Subject: [PATCH] ieee80211: Add 802.11h data type and structures Add 802.11h data types and structure definitions to ieee80211.h. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- include/net/ieee80211.h | 168 ++++++++++++++++++++++++++++++++++++++++++- net/ieee80211/ieee80211_rx.c | 2 +- 2 files changed, 166 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 3424a3ed66c4..ff6ef9e1a691 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -300,6 +300,23 @@ enum ieee80211_reasoncode { WLAN_REASON_CIPHER_SUITE_REJECTED = 24, }; +/* Action categories - 802.11h */ +enum ieee80211_actioncategories { + WLAN_ACTION_SPECTRUM_MGMT = 0, + /* Reserved 1-127 */ + /* Error 128-255 */ +}; + +/* Action details - 802.11h */ +enum ieee80211_actiondetails { + WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0, + WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1, + WLAN_ACTION_CATEGORY_TPC_REQUEST = 2, + WLAN_ACTION_CATEGORY_TPC_REPORT = 3, + WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4, + /* 5 - 255 Reserved */ +}; + #define IEEE80211_STATMASK_SIGNAL (1<<0) #define IEEE80211_STATMASK_RSSI (1<<1) #define IEEE80211_STATMASK_NOISE (1<<2) @@ -378,6 +395,8 @@ struct ieee80211_rx_stats { u8 mask; u8 freq; u16 len; + u64 tsf; + u32 beacon_time; }; /* IEEE 802.11 requires that STA supports concurrent reception of at least @@ -609,6 +628,28 @@ struct ieee80211_auth { struct ieee80211_info_element info_element[0]; } __attribute__ ((packed)); +struct ieee80211_channel_switch { + u8 id; + u8 len; + u8 mode; + u8 channel; + u8 count; +} __attribute__ ((packed)); + +struct ieee80211_action { + struct ieee80211_hdr_3addr header; + u8 category; + u8 action; + union { + struct ieee80211_action_exchange { + u8 token; + struct ieee80211_info_element info_element[0]; + } exchange; + struct ieee80211_channel_switch channel_switch; + + } format; +} __attribute__ ((packed)); + struct ieee80211_disassoc { struct ieee80211_hdr_3addr header; __le16 reason; @@ -693,7 +734,15 @@ struct ieee80211_txb { /* 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 NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ + NETWORK_HAS_QOS_INFORMATION) + +/* 802.11h */ +#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) +#define NETWORK_HAS_CSA (1<<6) +#define NETWORK_HAS_QUIET (1<<7) +#define NETWORK_HAS_IBSS_DFS (1<<8) +#define NETWORK_HAS_TPC_REPORT (1<<9) #define QOS_QUEUE_NUM 4 #define QOS_OUI_LEN 3 @@ -749,6 +798,91 @@ struct ieee80211_tim_parameters { /*******************************************************/ +enum { /* ieee80211_basic_report.map */ + IEEE80211_BASIC_MAP_BSS = (1 << 0), + IEEE80211_BASIC_MAP_OFDM = (1 << 1), + IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2), + IEEE80211_BASIC_MAP_RADAR = (1 << 3), + IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4), + /* Bits 5-7 are reserved */ + +}; +struct ieee80211_basic_report { + u8 channel; + __le64 start_time; + __le16 duration; + u8 map; +} __attribute__ ((packed)); + +enum { /* ieee80211_measurement_request.mode */ + /* Bit 0 is reserved */ + IEEE80211_MEASUREMENT_ENABLE = (1 << 1), + IEEE80211_MEASUREMENT_REQUEST = (1 << 2), + IEEE80211_MEASUREMENT_REPORT = (1 << 3), + /* Bits 4-7 are reserved */ +}; + +enum { + IEEE80211_REPORT_BASIC = 0, /* required */ + IEEE80211_REPORT_CCA = 1, /* optional */ + IEEE80211_REPORT_RPI = 2, /* optional */ + /* 3-255 reserved */ +}; + +struct ieee80211_measurement_params { + u8 channel; + __le64 start_time; + __le16 duration; +} __attribute__ ((packed)); + +struct ieee80211_measurement_request { + struct ieee80211_info_element ie; + u8 token; + u8 mode; + u8 type; + struct ieee80211_measurement_params params[0]; +} __attribute__ ((packed)); + +struct ieee80211_measurement_report { + struct ieee80211_info_element ie; + u8 token; + u8 mode; + u8 type; + union { + struct ieee80211_basic_report basic[0]; + } u; +} __attribute__ ((packed)); + +struct ieee80211_tpc_report { + u8 transmit_power; + u8 link_margin; +} __attribute__ ((packed)); + +struct ieee80211_channel_map { + u8 channel; + u8 map; +} __attribute__ ((packed)); + +struct ieee80211_ibss_dfs { + struct ieee80211_info_element ie; + u8 owner[ETH_ALEN]; + u8 recovery_interval; + struct ieee80211_channel_map channel_map[0]; +}; + +struct ieee80211_csa { + u8 mode; + u8 channel; + u8 count; +} __attribute__ ((packed)); + +struct ieee80211_quiet { + u8 count; + u8 period; + u8 duration; + u8 offset; +} __attribute__ ((packed)); + struct ieee80211_network { /* These entries are used to identify a unique network */ u8 bssid[ETH_ALEN]; @@ -768,7 +902,7 @@ struct ieee80211_network { u8 rates_ex_len; unsigned long last_scanned; u8 mode; - u8 flags; + u32 flags; u32 last_associate; u32 time_stamp[2]; u16 beacon_interval; @@ -780,6 +914,25 @@ struct ieee80211_network { u8 rsn_ie[MAX_WPA_IE_LEN]; size_t rsn_ie_len; struct ieee80211_tim_parameters tim; + + /* 802.11h info */ + + /* Power Constraint - mandatory if spctrm mgmt required */ + u8 power_constraint; + + /* TPC Report - mandatory if spctrm mgmt required */ + struct ieee80211_tpc_report tpc_report; + + /* IBSS DFS - mandatory if spctrm mgmt required and IBSS + * NOTE: This is variable length and so must be allocated dynamically */ + struct ieee80211_ibss_dfs *ibss_dfs; + + /* Channel Switch Announcement - optional if spctrm mgmt required */ + struct ieee80211_csa csa; + + /* Quiet - optional if spctrm mgmt required */ + struct ieee80211_quiet quiet; + struct list_head list; }; @@ -925,7 +1078,10 @@ struct ieee80211_device { int (*handle_auth) (struct net_device * dev, struct ieee80211_auth * auth); int (*handle_deauth) (struct net_device * dev, - struct ieee80211_auth * auth); + struct ieee80211_deauth * auth); + int (*handle_action) (struct net_device * dev, + struct ieee80211_action * action, + struct ieee80211_rx_stats * stats); int (*handle_disassoc) (struct net_device * dev, struct ieee80211_disassoc * assoc); int (*handle_beacon) (struct net_device * dev, @@ -1094,6 +1250,7 @@ extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *header, struct ieee80211_rx_stats *stats); +extern void ieee80211_network_reset(struct ieee80211_network *network); /* ieee80211_geo.c */ extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device @@ -1106,6 +1263,11 @@ extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee, extern int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel); extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq); +extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee, + u8 channel); +extern const struct ieee80211_channel *ieee80211_get_channel(struct + ieee80211_device + *ieee, u8 channel); /* ieee80211_wx.c */ extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index de402b75c428..4165da7ecff2 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -1514,7 +1514,7 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, case IEEE80211_STYPE_DEAUTH: printk("DEAUTH from AP\n"); if (ieee->handle_deauth != NULL) - ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *) + ieee->handle_deauth(ieee->dev, (struct ieee80211_deauth *) header); break; default: -- cgit v1.2.3 From dd5eeb461ea572f82d34e1f2c4b88037df5afedb Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 30 Jan 2006 13:12:50 +0100 Subject: [PATCH] ieee80211: common wx auth code This patch creates two functions ieee80211_wx_set_auth and ieee80211_wx_get_auth that can be used by drivers for the wireless extension handlers instead of writing their own, if the implementation should be software only. These patches enable using bcm43xx devices with WPA and this seems (as far as I can tell) to be the only difference between the stock ieee80211 and softmac's ieee80211 left. Signed-Off-By: Johannes Berg Signed-off-by: John W. Linville --- include/net/ieee80211.h | 8 ++++ net/ieee80211/ieee80211_wx.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) (limited to 'include') diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index ff6ef9e1a691..4725ff861c57 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1285,6 +1285,14 @@ extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +extern int ieee80211_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); +extern int ieee80211_wx_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) { diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 9496918e6106..e8c55a4d5834 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -761,9 +761,98 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, return 0; } +int ieee80211_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&ieee->lock, flags); + + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * Host AP driver does not use these parameters and allows + * wpa_supplicant to control them internally. + */ + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + break; /* FIXME */ + case IW_AUTH_DROP_UNENCRYPTED: + ieee->drop_unencrypted = !!wrqu->param.value; + break; + case IW_AUTH_80211_AUTH_ALG: + break; /* FIXME */ + case IW_AUTH_WPA_ENABLED: + ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value; + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + ieee->ieee802_1x = !!wrqu->param.value; + break; + case IW_AUTH_PRIVACY_INVOKED: + ieee->privacy_invoked = !!wrqu->param.value; + break; + default: + err = -EOPNOTSUPP; + break; + } + spin_unlock_irqrestore(&ieee->lock, flags); + return err; +} + +int ieee80211_wx_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&ieee->lock, flags); + + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: /* FIXME */ + case IW_AUTH_80211_AUTH_ALG: /* FIXME */ + /* + * Host AP driver does not use these parameters and allows + * wpa_supplicant to control them internally. + */ + err = -EOPNOTSUPP; + break; + case IW_AUTH_DROP_UNENCRYPTED: + wrqu->param.value = ieee->drop_unencrypted; + break; + case IW_AUTH_WPA_ENABLED: + wrqu->param.value = ieee->wpa_enabled; + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + wrqu->param.value = ieee->ieee802_1x; + break; + default: + err = -EOPNOTSUPP; + break; + } + spin_unlock_irqrestore(&ieee->lock, flags); + return err; +} + 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); + +EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth); +EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth); -- cgit v1.2.3 From 8f903c708fcc2b579ebf16542bf6109bad593a1d Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Tue, 21 Feb 2006 16:36:44 -0800 Subject: [PATCH] bonding: suppress duplicate packets Originally submitted by Kenzo Iwami; his original description is: The current bonding driver receives duplicate packets when broadcast/ multicast packets are sent by other devices or packets are flooded by the switch. In this patch, new flags are added in priv_flags of net_device structure to let the bonding driver discard duplicate packets in dev.c:skb_bond(). Modified by Jay Vosburgh to change a define name, update some comments, rearrange the new skb_bond() for clarity, clear all bonding priv_flags on slave release, and update the driver version. Signed-off-by: Kenzo Iwami Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 43 ++++++++++++++++++++-------------------- drivers/net/bonding/bond_sysfs.c | 6 ++++++ drivers/net/bonding/bonding.h | 33 +++++++++++++++++++++++++----- include/linux/if.h | 3 +++ include/linux/if_ether.h | 1 + net/core/dev.c | 26 +++++++++++++++++++++++- 6 files changed, 85 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bcf9f17daf0d..623c87a83615 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1040,6 +1040,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); + if (old_active) + bond_set_slave_inactive_flags(old_active); + if (new_active) + bond_set_slave_active_flags(new_active); } else { bond->curr_active_slave = new_active; } @@ -1443,15 +1447,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: - /* if we're in active-backup mode, we need one and only one active - * interface. The backup interfaces will have their NOARP flag set - * because we need them to be completely deaf and not to respond to - * any ARP request on the network to avoid fooling a switch. Thus, - * since we guarantee that curr_active_slave always point to the last - * usable interface, we just have to verify this interface's flag. + /* if we're in active-backup mode, we need one and + * only one active interface. The backup interfaces + * will have their SLAVE_INACTIVE flag set because we + * need them to be drop all packets. Thus, since we + * guarantee that curr_active_slave always point to + * the last usable interface, we just have to verify + * this interface's flag. */ if (((!bond->curr_active_slave) || - (bond->curr_active_slave->dev->flags & IFF_NOARP)) && + (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (new_slave->link != BOND_LINK_DOWN)) { dprintk("This is the first active slave\n"); /* first slave or no active slave yet, and this link @@ -1492,6 +1497,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + } else { + bond_set_slave_inactive_flags(new_slave); } break; default: @@ -1724,13 +1731,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the - * IFF_NOARP flag that might have been - * set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE); kfree(slave); @@ -1816,12 +1818,8 @@ static int bond_release_all(struct net_device *bond_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the IFF_NOARP flag that might have - * been set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE); kfree(slave); @@ -4061,14 +4059,17 @@ void bond_set_mode_ops(struct bonding *bond, int mode) bond_dev->hard_start_xmit = bond_xmit_broadcast; break; case BOND_MODE_8023AD: + bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) bond->xmit_hash_policy = bond_xmit_hash_policy_l34; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; - case BOND_MODE_TLB: case BOND_MODE_ALB: + bond_set_master_alb_flags(bond); + /* FALLTHRU */ + case BOND_MODE_TLB: bond_dev->hard_start_xmit = bond_alb_xmit; bond_dev->set_mac_address = bond_alb_set_mac_address; break; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 041bcc583557..5a9bd95884be 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -424,6 +424,12 @@ static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size ret = -EINVAL; goto out; } else { + if (bond->params.mode == BOND_MODE_8023AD) + bond_unset_master_3ad_flags(bond); + + if (bond->params.mode == BOND_MODE_ALB) + bond_unset_master_alb_flags(bond); + bond->params.mode = new_value; bond_set_mode_ops(bond, bond->params.mode); printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3dd78d048c3e..ce9dc9b4e2dc 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.0.1" -#define DRV_RELDATE "January 9, 2006" +#define DRV_VERSION "3.0.2" +#define DRV_RELDATE "February 21, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -230,14 +230,37 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) static inline void bond_set_slave_inactive_flags(struct slave *slave) { - slave->state = BOND_STATE_BACKUP; - slave->dev->flags |= IFF_NOARP; + struct bonding *bond = slave->dev->master->priv; + if (bond->params.mode != BOND_MODE_TLB && + bond->params.mode != BOND_MODE_ALB) + slave->state = BOND_STATE_BACKUP; + slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; } static inline void bond_set_slave_active_flags(struct slave *slave) { slave->state = BOND_STATE_ACTIVE; - slave->dev->flags &= ~IFF_NOARP; + slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; +} + +static inline void bond_set_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_8023AD; +} + +static inline void bond_unset_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_8023AD; +} + +static inline void bond_set_master_alb_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_ALB; +} + +static inline void bond_unset_master_alb_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_ALB; } struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); diff --git a/include/linux/if.h b/include/linux/if.h index ce627d9092ef..12c6f6d157c3 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -52,6 +52,9 @@ /* Private (from user) interface flags (netdevice->priv_flags). */ #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ +#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ +#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ +#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 7a92c1ce1457..ab08f35cbc35 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -61,6 +61,7 @@ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol * defined in draft-wilson-wrec-wccp-v2-00.txt */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ diff --git a/net/core/dev.c b/net/core/dev.c index 225e38ff57c4..ef56c035d44e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1446,8 +1446,29 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) { struct net_device *dev = skb->dev; - if (dev->master) + if (dev->master) { + /* + * On bonding slaves other than the currently active + * slave, suppress duplicates except for 802.3ad + * ETH_P_SLOW and alb non-mcast/bcast. + */ + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { + if (dev->master->priv_flags & IFF_MASTER_ALB) { + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + goto keep; + } + + if (dev->master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __constant_htons(ETH_P_SLOW)) + goto keep; + + kfree_skb(skb); + return NULL; + } +keep: skb->dev = dev->master; + } return dev; } @@ -1591,6 +1612,9 @@ int netif_receive_skb(struct sk_buff *skb) orig_dev = skb_bond(skb); + if (!orig_dev) + return NET_RX_DROP; + __get_cpu_var(netdev_rx_stat).total++; skb->h.raw = skb->nh.raw = skb->data; -- cgit v1.2.3