Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Nov 2012 03:48:41 +0000 (20:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Nov 2012 03:48:41 +0000 (20:48 -0700)
Pull networking fixes from David Miller:
 "First post-Sandy pull request"

 1) Fix antenna gain handling and initialization of chan->max_reg_power
    in wireless, from Felix Fietkau.

 2) Fix nexthop handling in H.232 conntrack helper, from Julian
    Anastasov.

 3) Only process 80211 mesh config header in certain kinds of frames,
    from Javier Cardona.

 4) 80211 management frame header length needs to be validated, from
    Johannes Berg.

 5) Don't access free'd SKBs in ath9k driver, from Felix Fietkay.

 6) Test for permanent state correctly in VXLAN driver, from Stephen
    Hemminger.

 7) BNX2X bug fixes from Yaniv Rosner and Dmitry Kravkov.

 8) Fix off by one errors in bonding, from Nikolay ALeksandrov.

 9) Fix divide by zero in TCP-Illinois congestion control.  From Jesper
    Dangaard Brouer.

10) TCP metrics code says "Yo dawg, I heard you like sizeof, so I did a
    sizeof of a sizeof, so you can size your size" Fix from Julian
    Anastasov.

11) Several drivers do mdiobus_free without first doing an
    mdiobus_unregister leading to stray pointer references.  Fix from
    Peter Senna Tschudin.

12) Fix OOPS in l2tp_eth_create() error path, it's another danling
    pointer kinda situation.  Fix from Tom Parkin.

13) Hardware driven by the vmxnet driver can't handle larger than 16K
    fragments, so split them up when necessary.  From Eric Dumazet.

14) Handle zero length data length in tcp_send_rcvq() properly.  Fix
    from Pavel Emelyanov.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (38 commits)
  tcp-repair: Handle zero-length data put in rcv queue
  vmxnet3: must split too big fragments
  l2tp: fix oops in l2tp_eth_create() error path
  cxgb4: Fix unable to get UP event from the LLD
  drivers/net/phy/mdio-bitbang.c: Call mdiobus_unregister before mdiobus_free
  drivers/net/ethernet/nxp/lpc_eth.c: Call mdiobus_unregister before mdiobus_free
  bnx2x: fix HW initialization using fw 7.8.x
  tcp: Fix double sizeof in new tcp_metrics code
  net: fix divide by zero in tcp algorithm illinois
  net: sctp: Fix typo in net/sctp
  bonding: fix second off-by-one error
  bonding: fix off-by-one error
  bnx2x: Disable FCoE for 57840 since not yet supported by FW
  bnx2x: Fix no link on 577xx 10G-baseT
  bnx2x: Fix unrecognized SFP+ module after driver is loaded
  bnx2x: Fix potential incorrect link speed provision
  bnx2x: Restore global registers back to default.
  bnx2x: Fix link down in 57712 following LFA
  bnx2x: Fix 57810 1G-KR link against certain switches.
  ixgbe: PTP get_ts_info missing software support
  ...

27 files changed:
drivers/net/bonding/bond_sysfs.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/phy/mdio-bitbang.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/rt2x00/rt2800lib.c
include/net/cfg80211.h
net/ipv4/netfilter/iptable_nat.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_metrics.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/l2tp/l2tp_eth.c
net/mac80211/ibss.c
net/mac80211/rx.c
net/mac80211/util.c
net/netfilter/nf_conntrack_h323_main.c
net/sctp/socket.c
net/wireless/core.c
net/wireless/reg.c
net/wireless/util.c

index dc15d248443fd833ae17199a41f28ab6712b5d5c..ef8d2a080d17f4c61b8f28aa7e07bc54ed5c0abc 100644 (file)
@@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing primary */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing active */
        if (!strlen(ifname) || buf[0] == '\n') {
index e2e45ee5df33fcc75c491c78643dfe406297aabb..6dd0dd076cc527434e64569d64c8cd37d48a33df 100644 (file)
 #define LINK_20GTFD            LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
 #define LINK_20GXFD            LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
 
-
+#define LINK_UPDATE_MASK \
+                       (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+                        LINK_STATUS_LINK_UP | \
+                        LINK_STATUS_PHYSICAL_LINK_FLAG | \
+                        LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
+                        LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
+                        LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+                        LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
@@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
               DEFAULT_PHY_DEV_ADDR);
 }
 
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    u32 action)
+{
+       struct bnx2x *bp = params->bp;
+       switch (action) {
+       case PHY_INIT:
+               /* Set correct devad */
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+                      phy->def_md_devad);
+               break;
+       }
+}
+
 static void bnx2x_xgxs_deassert(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
        udelay(500);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-              params->phy[INT_PHY].def_md_devad);
+       bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+                                PHY_INIT);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
-       u16 val16 = 0, lane, i;
+       u16 lane, i, cl72_ctrl, an_adv = 0;
+       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
                {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
@@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+       cl72_ctrl &= 0xf8ff;
+       cl72_ctrl |= 0x3800;
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
        /* Check adding advertisement for 1G KX */
        if (((vars->line_speed == SPEED_AUTO_NEG) &&
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
            (vars->line_speed == SPEED_1000)) {
                u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
-               val16 |= (1<<5);
+               an_adv |= (1<<5);
 
                /* Enable CL37 1G Parallel Detect */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
            (vars->line_speed ==  SPEED_10000)) {
                /* Check adding advertisement for 10G KR */
-               val16 |= (1<<7);
+               an_adv |= (1<<7);
                /* Enable 10G Parallel Detect */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+
                bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                                 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+               bnx2x_set_aer_mmd(params, phy);
                DP(NETIF_MSG_LINK, "Advertize 10G\n");
        }
 
@@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertised speeds */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
 
        /* Advertised and set FEC (Forward Error Correction) */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
         */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
-       if (val16 < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+       if (ucode_ver < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+                              ucode_ver);
                vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        }
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                                      struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 i;
+       u16 val16, i, lane;
        static struct bnx2x_reg_set reg_set[] = {
                /* Disable Autoneg */
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
                        0x3f00},
                {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
                {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
-               /* Disable CL36 PCS Tx */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
-               /* Double Wide Single Data Rate @ pll rate */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
                /* Leave cl72 training enable, needed for KR */
                {MDIO_PMA_DEVAD,
                MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
@@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
-       /* Leave CL72 enabled */
-       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-                                0x3800);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Global registers */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 &= ~(0x0011 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 |= (0x0303 << (lane << 1));
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
        /* Set speed via PMA/PMD register */
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       u16 val16;
+       u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
        bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
        bnx2x_set_aer_mmd(params, phy);
@@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                         MDIO_WC_REG_XGXSBLK1_LANECTRL2,
                         val16 & 0xff00);
 
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 |= (0x11 << lane);
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               val16 |= (0x22 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 &= ~(0x0303 << (lane << 1));
+       val16 |= (0x0101 << (lane << 1));
+       if (phy->flags & FLAGS_WC_DUAL_MODE) {
+               val16 &= ~(0x0c0c << (lane << 1));
+               val16 |= (0x0404 << (lane << 1));
+       }
+
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
+
 }
 
 static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
@@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        vars->mac_type = MAC_TYPE_NONE;
 
        /* Update shared memory */
-       vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-                              LINK_STATUS_LINK_UP |
-                              LINK_STATUS_PHYSICAL_LINK_FLAG |
-                              LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
-                              LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
-                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
-                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+       vars->link_status &= ~LINK_UPDATE_MASK;
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
        u8 active_external_phy = INT_PHY;
        vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+       vars->link_status &= ~LINK_UPDATE_MASK;
        for (phy_index = INT_PHY; phy_index < params->num_phys;
              phy_index++) {
                phy_vars[phy_index].flow_ctrl = 0;
@@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                                 struct link_params *params,
                                                 u16 addr, u8 byte_cnt,
-                                                u8 *o_buf)
+                                                u8 *o_buf, u8 is_init)
 {
        int rc = 0;
        u8 i, j = 0, cnt = 0;
@@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* 4 byte aligned address */
        addr32 = addr & (~0x3);
        do {
-               if (cnt == I2C_WA_PWR_ITER) {
+               if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
                        bnx2x_warpcore_power_module(params, phy, 0);
                        /* Note that 100us are not enough here */
-                       usleep_range(1000,1000);
+                       usleep_range(1000, 2000);
                        bnx2x_warpcore_power_module(params, phy, 1);
                }
                rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
@@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
                rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-                                                          byte_cnt, o_buf);
+                                                          byte_cnt, o_buf, 0);
        break;
        }
        return rc;
@@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 {
        u8 val;
+       int rc;
        struct bnx2x *bp = params->bp;
        u16 timeout;
        /* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
         */
 
        for (timeout = 0; timeout < 60; timeout++) {
-               if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-                   == 0) {
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                       rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+                                                                  params, 1,
+                                                                  1, &val, 1);
+               else
+                       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+                                                         &val);
+               if (rc == 0) {
                        DP(NETIF_MSG_LINK,
                           "SFP+ module initialization took %d ms\n",
                           timeout * 5);
@@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
                }
                usleep_range(5000, 10000);
        }
-       return -EINVAL;
+       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+       return rc;
 }
 
 static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
        .set_link_led   = (set_link_led_t)NULL,
-       .phy_specific_func = (phy_specific_func_t)NULL
+       .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
 static struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
@@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_BASE_T;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_XFI:
+                       phy->supported &= (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_FIBRE |
+                                          SUPPORTED_Pause |
+                                          SUPPORTED_Asym_Pause);
                        phy->media_type = ETH_PHY_XFP_FIBER;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
index d5648fc666bdf6f663505bbb433abebac08dbd48..bd1fd3d87c24d3979f01a0e9864af9866c62b9aa 100644 (file)
@@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
+       bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
        if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-               bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
 
                if (IS_MF(bp))
                        low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        /* disable FCOE L2 queue for E1x */
        if (CHIP_IS_E1x(bp))
                bp->flags |= NO_FCOE_FLAG;
-
+       /* disable FCOE for 57840 device, until FW supports it */
+       switch (ent->driver_data) {
+       case BCM57840_O:
+       case BCM57840_4_10:
+       case BCM57840_2_20:
+       case BCM57840_MFO:
+       case BCM57840_MF:
+               bp->flags |= NO_FCOE_FLAG;
+       }
 #endif
 
 
index c1cde11b0c6d5114e62ba400caab0195905ada3d..0df1284df497d8247fbf602d6578381099619d06 100644 (file)
@@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                         "mismatch: [fini] csum=%#x, computed csum=%#x\n",
                         finicsum, cfcsum);
 
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-
        /*
         * And now tell the firmware to use the configuration we just loaded.
         */
index 56b20d17d0e4c5577828040fddf8bd294868c84d..116f0e901bee2305324c4fa9035d19e6c5676b37 100644 (file)
@@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
        case ixgbe_mac_X540:
        case ixgbe_mac_82599EB:
                info->so_timestamping =
+                       SOF_TIMESTAMPING_TX_SOFTWARE |
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE |
                        SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
                        SOF_TIMESTAMPING_RAW_HARDWARE;
index 53743f7a2ca9604d6f264de3a2e3c727556a0619..af8b4142088c3d6a9114fd8c218336f54fcbcc19 100644 (file)
@@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
                                  pldat->dma_buff_base_p);
        free_irq(ndev->irq, ndev);
        iounmap(pldat->net_base);
+       mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
        clk_disable(pldat->clk);
        clk_put(pldat->clk);
index daec9b05d168ca4f0f103f3638fcc3259e9ea304..6428fcbbdd4bf4f6967e7eb3fee32e97fceba566 100644 (file)
@@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus)
        struct mdiobb_ctrl *ctrl = bus->priv;
 
        module_put(ctrl->ops->owner);
+       mdiobus_unregister(bus);
        mdiobus_free(bus);
 }
 EXPORT_SYMBOL(free_mdio_bitbang);
index ce9d4f2c9776e08d1b543f18de8cb7100fe43a86..0ae1bcc6da730fecd4267f0076b3f3ef422ea7ce 100644 (file)
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               u32 buf_size;
 
-               tbi = tq->buf_info + tq->tx_ring.next2fill;
-               tbi->map_type = VMXNET3_MAP_PAGE;
-               tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
-                                                0, skb_frag_size(frag),
-                                                DMA_TO_DEVICE);
+               buf_offset = 0;
+               len = skb_frag_size(frag);
+               while (len) {
+                       tbi = tq->buf_info + tq->tx_ring.next2fill;
+                       if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+                               buf_size = len;
+                               dw2 |= len;
+                       } else {
+                               buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+                               /* spec says that for TxDesc.len, 0 == 2^14 */
+                       }
+                       tbi->map_type = VMXNET3_MAP_PAGE;
+                       tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+                                                        buf_offset, buf_size,
+                                                        DMA_TO_DEVICE);
 
-               tbi->len = skb_frag_size(frag);
+                       tbi->len = buf_size;
 
-               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
-               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+                       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+                       BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
 
-               gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
-               gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
-               gdesc->dword[3] = 0;
+                       gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+                       gdesc->dword[2] = cpu_to_le32(dw2);
+                       gdesc->dword[3] = 0;
 
-               dev_dbg(&adapter->netdev->dev,
-                       "txd[%u]: 0x%llu %u %u\n",
-                       tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
-                       le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
-               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
-               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+                       dev_dbg(&adapter->netdev->dev,
+                               "txd[%u]: 0x%llu %u %u\n",
+                               tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+                               le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+                       vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+                       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+                       len -= buf_size;
+                       buf_offset += buf_size;
+               }
        }
 
        ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
        }
 }
 
+static int txd_estimate(const struct sk_buff *skb)
+{
+       int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+       }
+       return count;
+}
 
 /*
  * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
 
-       /* conservatively estimate # of descriptors to use */
-       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
-               skb_shinfo(skb)->nr_frags + 1;
+       count = txd_estimate(skb);
 
        ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
index 607976c001626a75afbf590411bf6ec1bbff26c0..7b4adde93c016b7e020306220e372524da9f5deb 100644 (file)
@@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state == NUD_PERMANENT)
+                       if (f->state & NUD_PERMANENT)
                                continue;
 
                        timeout = f->used + vxlan->age_interval * HZ;
index 378bd70256b2c7b8ad6358b2488919198dc42950..741918a2027b56ebe0f561d5175e8a129b8a3059 100644 (file)
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
        }
 
        bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       bf->bf_next = NULL;
        list_del(&bf->list);
 
        spin_unlock_bh(&sc->tx.txbuflock);
@@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-       bool rc_update = true;
+       bool rc_update = true, isba;
        struct ieee80211_tx_rate rates[4];
        struct ath_frame_info *fi;
        int nframes;
@@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
        tid = ATH_AN_2_TID(an, tidno);
        seq_first = tid->seq_start;
+       isba = ts->ts_flags & ATH9K_TX_BA;
 
        /*
         * The hardware occasionally sends a tx status for the wrong TID.
         * In this case, the BA status cannot be considered valid and all
         * subframes need to be retransmitted
+        *
+        * Only BlockAcks have a TID and therefore normal Acks cannot be
+        * checked
         */
-       if (tidno != ts->tid)
+       if (isba && tidno != ts->tid)
                txok = false;
 
        isaggr = bf_isaggr(bf);
@@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
 
+       bf->bf_next = NULL;
        bf->bf_lastbf = bf;
        ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
index 01dc8891070c3729c37b08cce18506ab583c4761..59474ae0aec0d14e7dfc2639c19cf65b82b3b7ea 100644 (file)
@@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if temperature compensation is supported.
         */
-       if (tssi_bounds[4] == 0xff)
+       if (tssi_bounds[4] == 0xff || step == 0xff)
                return 0;
 
        /*
index f8cd4cf3fad870d97204e3cf281d72e137db146c..7d5b6000378bbbdaf8a4fe7316ab93786429cf3a 100644 (file)
@@ -2651,6 +2651,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
  */
 unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
 
+/**
+ * ieee80211_get_mesh_hdrlen - get mesh extension header length
+ * @meshhdr: the mesh extension header, only the flags field
+ *     (first byte) will be accessed
+ * Returns the length of the extension header, which is always at
+ * least 6 bytes and at most 18 if address 5 and 6 are present.
+ */
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
+
 /**
  * DOC: Data path helpers
  *
index 9e0ffaf1d942624cf44d9693922e13312fc77ff2..a82047282dbbe2513615ae0c0e60dc1c54b2aa92 100644 (file)
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
 
                if ((ct->tuplehash[dir].tuple.src.u3.ip !=
                     ct->tuplehash[!dir].tuple.dst.u3.ip) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
                                ret = NF_DROP;
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
index 813b43a76fece71e2614878a5830962d55f35a22..834857f3c8713e8d8b80ab7b4f413725ec0ca9b4 100644 (file)
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
                        .tcpv_rttcnt = ca->cnt_rtt,
                        .tcpv_minrtt = ca->base_rtt,
                };
-               u64 t = ca->sum_rtt;
 
-               do_div(t, ca->cnt_rtt);
-               info.tcpv_rtt = t;
+               if (info.tcpv_rttcnt > 0) {
+                       u64 t = ca->sum_rtt;
 
+                       do_div(t, info.tcpv_rttcnt);
+                       info.tcpv_rtt = t;
+               }
                nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
        }
 }
index 1db6639835877bfef79df2d88034bb0e1fdfa082..2c2b13a999eae522c264a97a3d43baaa45c53c7b 100644 (file)
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
        struct tcphdr *th;
        bool fragstolen;
 
+       if (size == 0)
+               return 0;
+
        skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
        if (!skb)
                goto err;
index 4c752a6e0bcd91b0b932b483a2b9f988908c04a2..53bc5847bfa882a34c3d5a34257ec82a3fe92873 100644 (file)
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
        }
        a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
        if (a) {
-               if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
+               if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
index e418bd6350a405c9912f09207b876d1151961551..d57dab17a18251fcb8c63fc27c2dddfe8bc2a89e 100644 (file)
@@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                                      &ct->tuplehash[!dir].tuple.dst.u3) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
                                ret = NF_DROP;
@@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET6))
index 18bd9bbbd1c6c0f50d8bf74c947c05f91a4f20cd..22c8ea9511852e963b982ad68ed7066bda262ad2 100644 (file)
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        { }
 };
 
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
 }
 
 #else
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        return 0;
 }
index 37b8b8ba31f7395001cd2f36e234d82878bc22c7..76125c57ee6dddd2396a8a0bef4f19e7720e43ed 100644 (file)
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
        free_netdev(dev);
+       spriv->dev = NULL;
 out_del_session:
        l2tp_session_delete(session);
 out:
index 5f3620f0bc0a651257aa53e28b91c4b2114be637..bf87c70ac6c5fe1e2b920c6db827e1e9da6abe36 100644 (file)
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
        sdata->u.ibss.ibss_join_req = jiffies;
 
-       memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
+       memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
        sdata->u.ibss.ssid_len = params->ssid_len;
 
        mutex_unlock(&sdata->u.ibss.mtx);
index 61c621e9273fe70c26978d42433d58fca60a80b8..00ade7feb2e3a3b84af12be5bfad378bd8907182 100644 (file)
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
                if (ieee80211_is_action(hdr->frame_control)) {
                        u8 category;
+
+                       /* make sure category field is present */
+                       if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+                               return RX_DROP_MONITOR;
+
                        mgmt = (struct ieee80211_mgmt *)hdr;
                        category = mgmt->u.action.category;
                        if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
                 */
                if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
                    ieee80211_is_data_present(hdr->frame_control)) {
-                       u16 ethertype;
-                       u8 *payload;
-
-                       payload = rx->skb->data +
-                               ieee80211_hdrlen(hdr->frame_control);
-                       ethertype = (payload[6] << 8) | payload[7];
-                       if (cpu_to_be16(ethertype) ==
-                           rx->sdata->control_port_protocol)
+                       unsigned int hdrlen;
+                       __be16 ethertype;
+
+                       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+                       if (rx->skb->len < hdrlen + 8)
+                               return RX_DROP_MONITOR;
+
+                       skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
+                       if (ethertype == rx->sdata->control_port_protocol)
                                return RX_CONTINUE;
                }
 
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *)rx->skb->data;
        fc = hdr->frame_control;
+
+       if (ieee80211_is_ctl(fc))
+               return RX_CONTINUE;
+
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
        if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
-                  (rx->skb)->len < 24 ||
                   is_multicast_ether_addr(hdr->addr1))) {
                /* not fragmented */
                goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+       /* make sure fixed part of mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb, hdrlen + 6))
+               return RX_DROP_MONITOR;
+
+       mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+
+       /* make sure full mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb,
+                          hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
+               return RX_DROP_MONITOR;
+
+       /* reload pointers */
+       hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
        /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
                return RX_DROP_MONITOR;
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           !(status->rx_flags & IEEE80211_RX_RA_MATCH))
                return RX_CONTINUE;
 
        if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                if (is_multicast_ether_addr(hdr->addr1)) {
                        mpp_addr = hdr->addr3;
                        proxied_addr = mesh_hdr->eaddr1;
-               } else {
+               } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
+                       /* has_a4 already checked in ieee80211_rx_mesh_check */
                        mpp_addr = hdr->addr4;
                        proxied_addr = mesh_hdr->eaddr2;
+               } else {
+                       return RX_DROP_MONITOR;
                }
 
                rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        }
        skb_set_queue_mapping(skb, q);
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               goto out;
-
        if (!--mesh_hdr->ttl) {
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-               return RX_DROP_MONITOR;
+               goto out;
        }
 
        if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_SELF_PROTECTED:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.self_prot.action_code)))
+                       break;
+
                switch (mgmt->u.action.u.self_prot.action_code) {
                case WLAN_SP_MESH_PEERING_OPEN:
                case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_MESH_ACTION:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.mesh_action.action_code)))
+                       break;
+
                if (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
                if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
 
-       if (ieee80211_is_mgmt(fc))
-               err = skb_linearize(skb);
-       else
+       if (ieee80211_is_mgmt(fc)) {
+               /* drop frame if too short for header */
+               if (skb->len < ieee80211_hdrlen(fc))
+                       err = -ENOBUFS;
+               else
+                       err = skb_linearize(skb);
+       } else {
                err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
+       }
 
        if (err) {
                dev_kfree_skb(skb);
index 94e58687397908ae2ef2f71f5d6b68d78c80aea3..239391807ca9cff116576d07975c2ce31db393d3 100644 (file)
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        break;
                }
 
-               if (id != WLAN_EID_VENDOR_SPECIFIC &&
-                   id != WLAN_EID_QUIET &&
-                   test_bit(id, seen_elems)) {
-                       elems->parse_error = true;
-                       left -= elen;
-                       pos += elen;
-                       continue;
+               switch (id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_FH_PARAMS:
+               case WLAN_EID_DS_PARAMS:
+               case WLAN_EID_CF_PARAMS:
+               case WLAN_EID_TIM:
+               case WLAN_EID_IBSS_PARAMS:
+               case WLAN_EID_CHALLENGE:
+               case WLAN_EID_RSN:
+               case WLAN_EID_ERP_INFO:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_MESH_ID:
+               case WLAN_EID_MESH_CONFIG:
+               case WLAN_EID_PEER_MGMT:
+               case WLAN_EID_PREQ:
+               case WLAN_EID_PREP:
+               case WLAN_EID_PERR:
+               case WLAN_EID_RANN:
+               case WLAN_EID_CHANNEL_SWITCH:
+               case WLAN_EID_EXT_CHANSWITCH_ANN:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       if (test_bit(id, seen_elems)) {
+                               elems->parse_error = true;
+                               left -= elen;
+                               pos += elen;
+                               continue;
+                       }
+                       break;
                }
 
                if (calc_crc && id < 64 && (filter & (1ULL << id)))
index 1b30b0dee70818c4842b1835964ffc5f59e6b6e3..962795e839ab099ce426a27a1dcd4d887bc56eef 100644 (file)
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi4_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi4_to_flowi(&fl2), false)) {
-                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                               if (rt_nexthop(rt1, fl1.daddr) ==
+                                   rt_nexthop(rt2, fl2.daddr) &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index 59d16ea927f0f83d706d3a59c79d13be0a95c1e8..a60d1f8b41c5e2330e837265e175202aba322fcb 100644 (file)
@@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        void *addr_buf;
        struct sctp_af *af;
 
-       SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+       SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"
                          " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
        if (unlikely(addrs_size <= 0))
index 443d4d7deea299c7e997045d22d8b2b146d2c877..3f72530520883ae4aa510516bf7a4ce641c646d8 100644 (file)
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)
                for (i = 0; i < sband->n_channels; i++) {
                        sband->channels[i].orig_flags =
                                sband->channels[i].flags;
-                       sband->channels[i].orig_mag =
-                               sband->channels[i].max_antenna_gain;
+                       sband->channels[i].orig_mag = INT_MAX;
                        sband->channels[i].orig_mpwr =
                                sband->channels[i].max_power;
                        sband->channels[i].band = band;
index 3b8cbbc214db563ba962ecda1e49fe6929c263cc..bcc7d7ee5a516b8263c93a2556ab079d6d369280 100644 (file)
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,
                        map_regdom_flags(reg_rule->flags) | bw_flags;
                chan->max_antenna_gain = chan->orig_mag =
                        (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-               chan->max_power = chan->orig_mpwr =
+               chan->max_reg_power = chan->max_power = chan->orig_mpwr =
                        (int) MBM_TO_DBM(power_rule->max_eirp);
                return;
        }
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
 
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-       chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+       chan->max_reg_power = chan->max_power =
+               (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
 static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
index ef35f4ef2aa623d16f3556a5e3f4709fba363db4..2762e8329986afd57efd3f7735d1904e221ab05e 100644 (file)
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
 {
        int ae = meshhdr->flags & MESH_FLAGS_AE;
-       /* 7.1.3.5a.2 */
+       /* 802.11-2012, 8.2.4.7.3 */
        switch (ae) {
+       default:
        case 0:
                return 6;
        case MESH_FLAGS_AE_A4:
                return 12;
        case MESH_FLAGS_AE_A5_A6:
                return 18;
-       case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
-               return 24;
-       default:
-               return 6;
        }
 }
+EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
 int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                           enum nl80211_iftype iftype)
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),