diff options
60 files changed, 659 insertions, 339 deletions
diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt index 9ecd43d8792c..3fc360523bc9 100644 --- a/Documentation/devicetree/bindings/net/ethernet.txt +++ b/Documentation/devicetree/bindings/net/ethernet.txt | |||
| @@ -10,7 +10,7 @@ The following properties are common to the Ethernet controllers: | |||
| 10 | - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than | 10 | - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than |
| 11 | the maximum frame size (there's contradiction in ePAPR). | 11 | the maximum frame size (there's contradiction in ePAPR). |
| 12 | - phy-mode: string, operation mode of the PHY interface; supported values are | 12 | - phy-mode: string, operation mode of the PHY interface; supported values are |
| 13 | "mii", "gmii", "sgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id", | 13 | "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id", |
| 14 | "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto | 14 | "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto |
| 15 | standard property; | 15 | standard property; |
| 16 | - phy-connection-type: the same as "phy-mode" property but described in ePAPR; | 16 | - phy-connection-type: the same as "phy-mode" property but described in ePAPR; |
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 53d487f0c79d..6a7447c304ac 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c | |||
| @@ -1155,7 +1155,7 @@ icn_command(isdn_ctrl *c, icn_card *card) | |||
| 1155 | ulong a; | 1155 | ulong a; |
| 1156 | ulong flags; | 1156 | ulong flags; |
| 1157 | int i; | 1157 | int i; |
| 1158 | char cbuf[60]; | 1158 | char cbuf[80]; |
| 1159 | isdn_ctrl cmd; | 1159 | isdn_ctrl cmd; |
| 1160 | icn_cdef cdef; | 1160 | icn_cdef cdef; |
| 1161 | char __user *arg; | 1161 | char __user *arg; |
| @@ -1309,7 +1309,6 @@ icn_command(isdn_ctrl *c, icn_card *card) | |||
| 1309 | break; | 1309 | break; |
| 1310 | if ((c->arg & 255) < ICN_BCH) { | 1310 | if ((c->arg & 255) < ICN_BCH) { |
| 1311 | char *p; | 1311 | char *p; |
| 1312 | char dial[50]; | ||
| 1313 | char dcode[4]; | 1312 | char dcode[4]; |
| 1314 | 1313 | ||
| 1315 | a = c->arg; | 1314 | a = c->arg; |
| @@ -1321,10 +1320,10 @@ icn_command(isdn_ctrl *c, icn_card *card) | |||
| 1321 | } else | 1320 | } else |
| 1322 | /* Normal Dial */ | 1321 | /* Normal Dial */ |
| 1323 | strcpy(dcode, "CAL"); | 1322 | strcpy(dcode, "CAL"); |
| 1324 | strcpy(dial, p); | 1323 | snprintf(cbuf, sizeof(cbuf), |
| 1325 | sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), | 1324 | "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), |
| 1326 | dcode, dial, c->parm.setup.si1, | 1325 | dcode, p, c->parm.setup.si1, |
| 1327 | c->parm.setup.si2, c->parm.setup.eazmsn); | 1326 | c->parm.setup.si2, c->parm.setup.eazmsn); |
| 1328 | i = icn_writecmd(cbuf, strlen(cbuf), 0, card); | 1327 | i = icn_writecmd(cbuf, strlen(cbuf), 0, card); |
| 1329 | } | 1328 | } |
| 1330 | break; | 1329 | break; |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b9f7022f4e81..e5d95c5ce1ad 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
| @@ -12286,7 +12286,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e | |||
| 12286 | if (tg3_flag(tp, MAX_RXPEND_64) && | 12286 | if (tg3_flag(tp, MAX_RXPEND_64) && |
| 12287 | tp->rx_pending > 63) | 12287 | tp->rx_pending > 63) |
| 12288 | tp->rx_pending = 63; | 12288 | tp->rx_pending = 63; |
| 12289 | tp->rx_jumbo_pending = ering->rx_jumbo_pending; | 12289 | |
| 12290 | if (tg3_flag(tp, JUMBO_RING_ENABLE)) | ||
| 12291 | tp->rx_jumbo_pending = ering->rx_jumbo_pending; | ||
| 12290 | 12292 | ||
| 12291 | for (i = 0; i < tp->irq_max; i++) | 12293 | for (i = 0; i < tp->irq_max; i++) |
| 12292 | tp->napi[i].tx_pending = ering->tx_pending; | 12294 | tp->napi[i].tx_pending = ering->tx_pending; |
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b248bcbdae63..14786c8bf99e 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c | |||
| @@ -89,8 +89,9 @@ | |||
| 89 | #define MVNETA_TX_IN_PRGRS BIT(1) | 89 | #define MVNETA_TX_IN_PRGRS BIT(1) |
| 90 | #define MVNETA_TX_FIFO_EMPTY BIT(8) | 90 | #define MVNETA_TX_FIFO_EMPTY BIT(8) |
| 91 | #define MVNETA_RX_MIN_FRAME_SIZE 0x247c | 91 | #define MVNETA_RX_MIN_FRAME_SIZE 0x247c |
| 92 | #define MVNETA_SGMII_SERDES_CFG 0x24A0 | 92 | #define MVNETA_SERDES_CFG 0x24A0 |
| 93 | #define MVNETA_SGMII_SERDES_PROTO 0x0cc7 | 93 | #define MVNETA_SGMII_SERDES_PROTO 0x0cc7 |
| 94 | #define MVNETA_QSGMII_SERDES_PROTO 0x0667 | ||
| 94 | #define MVNETA_TYPE_PRIO 0x24bc | 95 | #define MVNETA_TYPE_PRIO 0x24bc |
| 95 | #define MVNETA_FORCE_UNI BIT(21) | 96 | #define MVNETA_FORCE_UNI BIT(21) |
| 96 | #define MVNETA_TXQ_CMD_1 0x24e4 | 97 | #define MVNETA_TXQ_CMD_1 0x24e4 |
| @@ -711,35 +712,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp, | |||
| 711 | mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); | 712 | mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); |
| 712 | } | 713 | } |
| 713 | 714 | ||
| 714 | |||
| 715 | |||
| 716 | /* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ | ||
| 717 | static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) | ||
| 718 | { | ||
| 719 | u32 val; | ||
| 720 | |||
| 721 | val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||
| 722 | |||
| 723 | if (enable) | ||
| 724 | val |= MVNETA_GMAC2_PORT_RGMII; | ||
| 725 | else | ||
| 726 | val &= ~MVNETA_GMAC2_PORT_RGMII; | ||
| 727 | |||
| 728 | mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||
| 729 | } | ||
| 730 | |||
| 731 | /* Config SGMII port */ | ||
| 732 | static void mvneta_port_sgmii_config(struct mvneta_port *pp) | ||
| 733 | { | ||
| 734 | u32 val; | ||
| 735 | |||
| 736 | val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||
| 737 | val |= MVNETA_GMAC2_PCS_ENABLE; | ||
| 738 | mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||
| 739 | |||
| 740 | mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); | ||
| 741 | } | ||
| 742 | |||
| 743 | /* Start the Ethernet port RX and TX activity */ | 715 | /* Start the Ethernet port RX and TX activity */ |
| 744 | static void mvneta_port_up(struct mvneta_port *pp) | 716 | static void mvneta_port_up(struct mvneta_port *pp) |
| 745 | { | 717 | { |
| @@ -2749,26 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp, | |||
| 2749 | } | 2721 | } |
| 2750 | 2722 | ||
| 2751 | /* Power up the port */ | 2723 | /* Power up the port */ |
| 2752 | static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) | 2724 | static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) |
| 2753 | { | 2725 | { |
| 2754 | u32 val; | 2726 | u32 ctrl; |
| 2755 | 2727 | ||
| 2756 | /* MAC Cause register should be cleared */ | 2728 | /* MAC Cause register should be cleared */ |
| 2757 | mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); | 2729 | mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); |
| 2758 | 2730 | ||
| 2759 | if (phy_mode == PHY_INTERFACE_MODE_SGMII) | 2731 | ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
| 2760 | mvneta_port_sgmii_config(pp); | ||
| 2761 | 2732 | ||
| 2762 | mvneta_gmac_rgmii_set(pp, 1); | 2733 | /* Even though it might look weird, when we're configured in |
| 2734 | * SGMII or QSGMII mode, the RGMII bit needs to be set. | ||
| 2735 | */ | ||
| 2736 | switch(phy_mode) { | ||
| 2737 | case PHY_INTERFACE_MODE_QSGMII: | ||
| 2738 | mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); | ||
| 2739 | ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; | ||
| 2740 | break; | ||
| 2741 | case PHY_INTERFACE_MODE_SGMII: | ||
| 2742 | mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); | ||
| 2743 | ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; | ||
| 2744 | break; | ||
| 2745 | case PHY_INTERFACE_MODE_RGMII: | ||
| 2746 | case PHY_INTERFACE_MODE_RGMII_ID: | ||
| 2747 | ctrl |= MVNETA_GMAC2_PORT_RGMII; | ||
| 2748 | break; | ||
| 2749 | default: | ||
| 2750 | return -EINVAL; | ||
| 2751 | } | ||
| 2763 | 2752 | ||
| 2764 | /* Cancel Port Reset */ | 2753 | /* Cancel Port Reset */ |
| 2765 | val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | 2754 | ctrl &= ~MVNETA_GMAC2_PORT_RESET; |
| 2766 | val &= ~MVNETA_GMAC2_PORT_RESET; | 2755 | mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl); |
| 2767 | mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||
| 2768 | 2756 | ||
| 2769 | while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & | 2757 | while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & |
| 2770 | MVNETA_GMAC2_PORT_RESET) != 0) | 2758 | MVNETA_GMAC2_PORT_RESET) != 0) |
| 2771 | continue; | 2759 | continue; |
| 2760 | |||
| 2761 | return 0; | ||
| 2772 | } | 2762 | } |
| 2773 | 2763 | ||
| 2774 | /* Device initialization routine */ | 2764 | /* Device initialization routine */ |
| @@ -2879,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev) | |||
| 2879 | dev_err(&pdev->dev, "can't init eth hal\n"); | 2869 | dev_err(&pdev->dev, "can't init eth hal\n"); |
| 2880 | goto err_free_stats; | 2870 | goto err_free_stats; |
| 2881 | } | 2871 | } |
| 2882 | mvneta_port_power_up(pp, phy_mode); | 2872 | |
| 2873 | err = mvneta_port_power_up(pp, phy_mode); | ||
| 2874 | if (err < 0) { | ||
| 2875 | dev_err(&pdev->dev, "can't power up port\n"); | ||
| 2876 | goto err_deinit; | ||
| 2877 | } | ||
| 2883 | 2878 | ||
| 2884 | dram_target_info = mv_mbus_dram_info(); | 2879 | dram_target_info = mv_mbus_dram_info(); |
| 2885 | if (dram_target_info) | 2880 | if (dram_target_info) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 70e95324a97d..c2cd8d31bcad 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c | |||
| @@ -66,7 +66,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, | |||
| 66 | 66 | ||
| 67 | cq->ring = ring; | 67 | cq->ring = ring; |
| 68 | cq->is_tx = mode; | 68 | cq->is_tx = mode; |
| 69 | spin_lock_init(&cq->lock); | ||
| 70 | 69 | ||
| 71 | /* Allocate HW buffers on provided NUMA node. | 70 | /* Allocate HW buffers on provided NUMA node. |
| 72 | * dev->numa_node is used in mtt range allocation flow. | 71 | * dev->numa_node is used in mtt range allocation flow. |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f085c2df5e69..7e4b1720c3d1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
| @@ -1304,15 +1304,11 @@ static void mlx4_en_netpoll(struct net_device *dev) | |||
| 1304 | { | 1304 | { |
| 1305 | struct mlx4_en_priv *priv = netdev_priv(dev); | 1305 | struct mlx4_en_priv *priv = netdev_priv(dev); |
| 1306 | struct mlx4_en_cq *cq; | 1306 | struct mlx4_en_cq *cq; |
| 1307 | unsigned long flags; | ||
| 1308 | int i; | 1307 | int i; |
| 1309 | 1308 | ||
| 1310 | for (i = 0; i < priv->rx_ring_num; i++) { | 1309 | for (i = 0; i < priv->rx_ring_num; i++) { |
| 1311 | cq = priv->rx_cq[i]; | 1310 | cq = priv->rx_cq[i]; |
| 1312 | spin_lock_irqsave(&cq->lock, flags); | 1311 | napi_schedule(&cq->napi); |
| 1313 | napi_synchronize(&cq->napi); | ||
| 1314 | mlx4_en_process_rx_cq(dev, cq, 0); | ||
| 1315 | spin_unlock_irqrestore(&cq->lock, flags); | ||
| 1316 | } | 1312 | } |
| 1317 | } | 1313 | } |
| 1318 | #endif | 1314 | #endif |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 7a733c287744..04d9b6fe3e80 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
| @@ -319,7 +319,6 @@ struct mlx4_en_cq { | |||
| 319 | struct mlx4_cq mcq; | 319 | struct mlx4_cq mcq; |
| 320 | struct mlx4_hwq_resources wqres; | 320 | struct mlx4_hwq_resources wqres; |
| 321 | int ring; | 321 | int ring; |
| 322 | spinlock_t lock; | ||
| 323 | struct net_device *dev; | 322 | struct net_device *dev; |
| 324 | struct napi_struct napi; | 323 | struct napi_struct napi; |
| 325 | int size; | 324 | int size; |
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 21c20ea0dad0..b5ed30a39144 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c | |||
| @@ -738,8 +738,11 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type) | |||
| 738 | /* If it was a port reset, trigger reallocation of MC resources. | 738 | /* If it was a port reset, trigger reallocation of MC resources. |
| 739 | * Note that on an MC reset nothing needs to be done now because we'll | 739 | * Note that on an MC reset nothing needs to be done now because we'll |
| 740 | * detect the MC reset later and handle it then. | 740 | * detect the MC reset later and handle it then. |
| 741 | * For an FLR, we never get an MC reset event, but the MC has reset all | ||
| 742 | * resources assigned to us, so we have to trigger reallocation now. | ||
| 741 | */ | 743 | */ |
| 742 | if (reset_type == RESET_TYPE_ALL && !rc) | 744 | if ((reset_type == RESET_TYPE_ALL || |
| 745 | reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc) | ||
| 743 | efx_ef10_reset_mc_allocations(efx); | 746 | efx_ef10_reset_mc_allocations(efx); |
| 744 | return rc; | 747 | return rc; |
| 745 | } | 748 | } |
| @@ -2141,6 +2144,11 @@ static int efx_ef10_fini_dmaq(struct efx_nic *efx) | |||
| 2141 | return 0; | 2144 | return 0; |
| 2142 | } | 2145 | } |
| 2143 | 2146 | ||
| 2147 | static void efx_ef10_prepare_flr(struct efx_nic *efx) | ||
| 2148 | { | ||
| 2149 | atomic_set(&efx->active_queues, 0); | ||
| 2150 | } | ||
| 2151 | |||
| 2144 | static bool efx_ef10_filter_equal(const struct efx_filter_spec *left, | 2152 | static bool efx_ef10_filter_equal(const struct efx_filter_spec *left, |
| 2145 | const struct efx_filter_spec *right) | 2153 | const struct efx_filter_spec *right) |
| 2146 | { | 2154 | { |
| @@ -3603,6 +3611,8 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { | |||
| 3603 | .probe_port = efx_mcdi_port_probe, | 3611 | .probe_port = efx_mcdi_port_probe, |
| 3604 | .remove_port = efx_mcdi_port_remove, | 3612 | .remove_port = efx_mcdi_port_remove, |
| 3605 | .fini_dmaq = efx_ef10_fini_dmaq, | 3613 | .fini_dmaq = efx_ef10_fini_dmaq, |
| 3614 | .prepare_flr = efx_ef10_prepare_flr, | ||
| 3615 | .finish_flr = efx_port_dummy_op_void, | ||
| 3606 | .describe_stats = efx_ef10_describe_stats, | 3616 | .describe_stats = efx_ef10_describe_stats, |
| 3607 | .update_stats = efx_ef10_update_stats, | 3617 | .update_stats = efx_ef10_update_stats, |
| 3608 | .start_stats = efx_mcdi_mac_start_stats, | 3618 | .start_stats = efx_mcdi_mac_start_stats, |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 57b971e5e6b2..63d595fd3cc5 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
| @@ -76,6 +76,7 @@ const char *const efx_reset_type_names[] = { | |||
| 76 | [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", | 76 | [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", |
| 77 | [RESET_TYPE_WORLD] = "WORLD", | 77 | [RESET_TYPE_WORLD] = "WORLD", |
| 78 | [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", | 78 | [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", |
| 79 | [RESET_TYPE_MC_BIST] = "MC_BIST", | ||
| 79 | [RESET_TYPE_DISABLE] = "DISABLE", | 80 | [RESET_TYPE_DISABLE] = "DISABLE", |
| 80 | [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", | 81 | [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", |
| 81 | [RESET_TYPE_INT_ERROR] = "INT_ERROR", | 82 | [RESET_TYPE_INT_ERROR] = "INT_ERROR", |
| @@ -83,7 +84,7 @@ const char *const efx_reset_type_names[] = { | |||
| 83 | [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", | 84 | [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", |
| 84 | [RESET_TYPE_TX_SKIP] = "TX_SKIP", | 85 | [RESET_TYPE_TX_SKIP] = "TX_SKIP", |
| 85 | [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", | 86 | [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", |
| 86 | [RESET_TYPE_MC_BIST] = "MC_BIST", | 87 | [RESET_TYPE_MCDI_TIMEOUT] = "MCDI_TIMEOUT (FLR)", |
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | /* Reset workqueue. If any NIC has a hardware failure then a reset will be | 90 | /* Reset workqueue. If any NIC has a hardware failure then a reset will be |
| @@ -1739,7 +1740,8 @@ static void efx_start_all(struct efx_nic *efx) | |||
| 1739 | 1740 | ||
| 1740 | /* Check that it is appropriate to restart the interface. All | 1741 | /* Check that it is appropriate to restart the interface. All |
| 1741 | * of these flags are safe to read under just the rtnl lock */ | 1742 | * of these flags are safe to read under just the rtnl lock */ |
| 1742 | if (efx->port_enabled || !netif_running(efx->net_dev)) | 1743 | if (efx->port_enabled || !netif_running(efx->net_dev) || |
| 1744 | efx->reset_pending) | ||
| 1743 | return; | 1745 | return; |
| 1744 | 1746 | ||
| 1745 | efx_start_port(efx); | 1747 | efx_start_port(efx); |
| @@ -2334,6 +2336,9 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method) | |||
| 2334 | { | 2336 | { |
| 2335 | EFX_ASSERT_RESET_SERIALISED(efx); | 2337 | EFX_ASSERT_RESET_SERIALISED(efx); |
| 2336 | 2338 | ||
| 2339 | if (method == RESET_TYPE_MCDI_TIMEOUT) | ||
| 2340 | efx->type->prepare_flr(efx); | ||
| 2341 | |||
| 2337 | efx_stop_all(efx); | 2342 | efx_stop_all(efx); |
| 2338 | efx_disable_interrupts(efx); | 2343 | efx_disable_interrupts(efx); |
| 2339 | 2344 | ||
| @@ -2354,6 +2359,10 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) | |||
| 2354 | 2359 | ||
| 2355 | EFX_ASSERT_RESET_SERIALISED(efx); | 2360 | EFX_ASSERT_RESET_SERIALISED(efx); |
| 2356 | 2361 | ||
| 2362 | if (method == RESET_TYPE_MCDI_TIMEOUT) | ||
| 2363 | efx->type->finish_flr(efx); | ||
| 2364 | |||
| 2365 | /* Ensure that SRAM is initialised even if we're disabling the device */ | ||
| 2357 | rc = efx->type->init(efx); | 2366 | rc = efx->type->init(efx); |
| 2358 | if (rc) { | 2367 | if (rc) { |
| 2359 | netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); | 2368 | netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); |
| @@ -2417,7 +2426,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) | |||
| 2417 | /* Clear flags for the scopes we covered. We assume the NIC and | 2426 | /* Clear flags for the scopes we covered. We assume the NIC and |
| 2418 | * driver are now quiescent so that there is no race here. | 2427 | * driver are now quiescent so that there is no race here. |
| 2419 | */ | 2428 | */ |
| 2420 | efx->reset_pending &= -(1 << (method + 1)); | 2429 | if (method < RESET_TYPE_MAX_METHOD) |
| 2430 | efx->reset_pending &= -(1 << (method + 1)); | ||
| 2431 | else /* it doesn't fit into the well-ordered scope hierarchy */ | ||
| 2432 | __clear_bit(method, &efx->reset_pending); | ||
| 2421 | 2433 | ||
| 2422 | /* Reinitialise bus-mastering, which may have been turned off before | 2434 | /* Reinitialise bus-mastering, which may have been turned off before |
| 2423 | * the reset was scheduled. This is still appropriate, even in the | 2435 | * the reset was scheduled. This is still appropriate, even in the |
| @@ -2546,6 +2558,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) | |||
| 2546 | case RESET_TYPE_DISABLE: | 2558 | case RESET_TYPE_DISABLE: |
| 2547 | case RESET_TYPE_RECOVER_OR_DISABLE: | 2559 | case RESET_TYPE_RECOVER_OR_DISABLE: |
| 2548 | case RESET_TYPE_MC_BIST: | 2560 | case RESET_TYPE_MC_BIST: |
| 2561 | case RESET_TYPE_MCDI_TIMEOUT: | ||
| 2549 | method = type; | 2562 | method = type; |
| 2550 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", | 2563 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", |
| 2551 | RESET_TYPE(method)); | 2564 | RESET_TYPE(method)); |
diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h index 75ef7ef6450b..d1dbb5fb31bb 100644 --- a/drivers/net/ethernet/sfc/enum.h +++ b/drivers/net/ethernet/sfc/enum.h | |||
| @@ -143,6 +143,7 @@ enum efx_loopback_mode { | |||
| 143 | * @RESET_TYPE_WORLD: Reset as much as possible | 143 | * @RESET_TYPE_WORLD: Reset as much as possible |
| 144 | * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if | 144 | * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if |
| 145 | * unsuccessful. | 145 | * unsuccessful. |
| 146 | * @RESET_TYPE_MC_BIST: MC entering BIST mode. | ||
| 146 | * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled | 147 | * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled |
| 147 | * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog | 148 | * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog |
| 148 | * @RESET_TYPE_INT_ERROR: reset due to internal error | 149 | * @RESET_TYPE_INT_ERROR: reset due to internal error |
| @@ -150,14 +151,16 @@ enum efx_loopback_mode { | |||
| 150 | * @RESET_TYPE_DMA_ERROR: DMA error | 151 | * @RESET_TYPE_DMA_ERROR: DMA error |
| 151 | * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors | 152 | * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors |
| 152 | * @RESET_TYPE_MC_FAILURE: MC reboot/assertion | 153 | * @RESET_TYPE_MC_FAILURE: MC reboot/assertion |
| 154 | * @RESET_TYPE_MCDI_TIMEOUT: MCDI timeout. | ||
| 153 | */ | 155 | */ |
| 154 | enum reset_type { | 156 | enum reset_type { |
| 155 | RESET_TYPE_INVISIBLE = 0, | 157 | RESET_TYPE_INVISIBLE, |
| 156 | RESET_TYPE_RECOVER_OR_ALL = 1, | 158 | RESET_TYPE_RECOVER_OR_ALL, |
| 157 | RESET_TYPE_ALL = 2, | 159 | RESET_TYPE_ALL, |
| 158 | RESET_TYPE_WORLD = 3, | 160 | RESET_TYPE_WORLD, |
| 159 | RESET_TYPE_RECOVER_OR_DISABLE = 4, | 161 | RESET_TYPE_RECOVER_OR_DISABLE, |
| 160 | RESET_TYPE_DISABLE = 5, | 162 | RESET_TYPE_MC_BIST, |
| 163 | RESET_TYPE_DISABLE, | ||
| 161 | RESET_TYPE_MAX_METHOD, | 164 | RESET_TYPE_MAX_METHOD, |
| 162 | RESET_TYPE_TX_WATCHDOG, | 165 | RESET_TYPE_TX_WATCHDOG, |
| 163 | RESET_TYPE_INT_ERROR, | 166 | RESET_TYPE_INT_ERROR, |
| @@ -165,7 +168,13 @@ enum reset_type { | |||
| 165 | RESET_TYPE_DMA_ERROR, | 168 | RESET_TYPE_DMA_ERROR, |
| 166 | RESET_TYPE_TX_SKIP, | 169 | RESET_TYPE_TX_SKIP, |
| 167 | RESET_TYPE_MC_FAILURE, | 170 | RESET_TYPE_MC_FAILURE, |
| 168 | RESET_TYPE_MC_BIST, | 171 | /* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but |
| 172 | * it doesn't fit the scope hierarchy (not well-ordered by inclusion). | ||
| 173 | * We encode this by having its enum value be greater than | ||
| 174 | * RESET_TYPE_MAX_METHOD. This also prevents issuing it with | ||
| 175 | * efx_ioctl_reset. | ||
| 176 | */ | ||
| 177 | RESET_TYPE_MCDI_TIMEOUT, | ||
| 169 | RESET_TYPE_MAX, | 178 | RESET_TYPE_MAX, |
| 170 | }; | 179 | }; |
| 171 | 180 | ||
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ec20b713cc6..fae25a418647 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c | |||
| @@ -2696,6 +2696,8 @@ const struct efx_nic_type falcon_a1_nic_type = { | |||
| 2696 | .fini_dmaq = efx_farch_fini_dmaq, | 2696 | .fini_dmaq = efx_farch_fini_dmaq, |
| 2697 | .prepare_flush = falcon_prepare_flush, | 2697 | .prepare_flush = falcon_prepare_flush, |
| 2698 | .finish_flush = efx_port_dummy_op_void, | 2698 | .finish_flush = efx_port_dummy_op_void, |
| 2699 | .prepare_flr = efx_port_dummy_op_void, | ||
| 2700 | .finish_flr = efx_farch_finish_flr, | ||
| 2699 | .describe_stats = falcon_describe_nic_stats, | 2701 | .describe_stats = falcon_describe_nic_stats, |
| 2700 | .update_stats = falcon_update_nic_stats, | 2702 | .update_stats = falcon_update_nic_stats, |
| 2701 | .start_stats = falcon_start_nic_stats, | 2703 | .start_stats = falcon_start_nic_stats, |
| @@ -2790,6 +2792,8 @@ const struct efx_nic_type falcon_b0_nic_type = { | |||
| 2790 | .fini_dmaq = efx_farch_fini_dmaq, | 2792 | .fini_dmaq = efx_farch_fini_dmaq, |
| 2791 | .prepare_flush = falcon_prepare_flush, | 2793 | .prepare_flush = falcon_prepare_flush, |
| 2792 | .finish_flush = efx_port_dummy_op_void, | 2794 | .finish_flush = efx_port_dummy_op_void, |
| 2795 | .prepare_flr = efx_port_dummy_op_void, | ||
| 2796 | .finish_flr = efx_farch_finish_flr, | ||
| 2793 | .describe_stats = falcon_describe_nic_stats, | 2797 | .describe_stats = falcon_describe_nic_stats, |
| 2794 | .update_stats = falcon_update_nic_stats, | 2798 | .update_stats = falcon_update_nic_stats, |
| 2795 | .start_stats = falcon_start_nic_stats, | 2799 | .start_stats = falcon_start_nic_stats, |
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index a08761360cdf..0537381cd2f6 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c | |||
| @@ -741,6 +741,28 @@ int efx_farch_fini_dmaq(struct efx_nic *efx) | |||
| 741 | return rc; | 741 | return rc; |
| 742 | } | 742 | } |
| 743 | 743 | ||
| 744 | /* Reset queue and flush accounting after FLR | ||
| 745 | * | ||
| 746 | * One possible cause of FLR recovery is that DMA may be failing (eg. if bus | ||
| 747 | * mastering was disabled), in which case we don't receive (RXQ) flush | ||
| 748 | * completion events. This means that efx->rxq_flush_outstanding remained at 4 | ||
| 749 | * after the FLR; also, efx->active_queues was non-zero (as no flush completion | ||
| 750 | * events were received, and we didn't go through efx_check_tx_flush_complete()) | ||
| 751 | * If we don't fix this up, on the next call to efx_realloc_channels() we won't | ||
| 752 | * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4 | ||
| 753 | * for batched flush requests; and the efx->active_queues gets messed up because | ||
| 754 | * we keep incrementing for the newly initialised queues, but it never went to | ||
| 755 | * zero previously. Then we get a timeout every time we try to restart the | ||
| 756 | * queues, as it doesn't go back to zero when we should be flushing the queues. | ||
| 757 | */ | ||
| 758 | void efx_farch_finish_flr(struct efx_nic *efx) | ||
| 759 | { | ||
| 760 | atomic_set(&efx->rxq_flush_pending, 0); | ||
| 761 | atomic_set(&efx->rxq_flush_outstanding, 0); | ||
| 762 | atomic_set(&efx->active_queues, 0); | ||
| 763 | } | ||
| 764 | |||
| 765 | |||
| 744 | /************************************************************************** | 766 | /************************************************************************** |
| 745 | * | 767 | * |
| 746 | * Event queue processing | 768 | * Event queue processing |
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 7bd4b14bf3b3..5239cf9bdc56 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c | |||
| @@ -52,12 +52,7 @@ static void efx_mcdi_timeout_async(unsigned long context); | |||
| 52 | static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, | 52 | static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, |
| 53 | bool *was_attached_out); | 53 | bool *was_attached_out); |
| 54 | static bool efx_mcdi_poll_once(struct efx_nic *efx); | 54 | static bool efx_mcdi_poll_once(struct efx_nic *efx); |
| 55 | 55 | static void efx_mcdi_abandon(struct efx_nic *efx); | |
| 56 | static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) | ||
| 57 | { | ||
| 58 | EFX_BUG_ON_PARANOID(!efx->mcdi); | ||
| 59 | return &efx->mcdi->iface; | ||
| 60 | } | ||
| 61 | 56 | ||
| 62 | int efx_mcdi_init(struct efx_nic *efx) | 57 | int efx_mcdi_init(struct efx_nic *efx) |
| 63 | { | 58 | { |
| @@ -558,6 +553,8 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, | |||
| 558 | rc = 0; | 553 | rc = 0; |
| 559 | } | 554 | } |
| 560 | 555 | ||
| 556 | efx_mcdi_abandon(efx); | ||
| 557 | |||
| 561 | /* Close the race with efx_mcdi_ev_cpl() executing just too late | 558 | /* Close the race with efx_mcdi_ev_cpl() executing just too late |
| 562 | * and completing a request we've just cancelled, by ensuring | 559 | * and completing a request we've just cancelled, by ensuring |
| 563 | * that the seqno check therein fails. | 560 | * that the seqno check therein fails. |
| @@ -672,6 +669,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, | |||
| 672 | if (efx->mc_bist_for_other_fn) | 669 | if (efx->mc_bist_for_other_fn) |
| 673 | return -ENETDOWN; | 670 | return -ENETDOWN; |
| 674 | 671 | ||
| 672 | if (mcdi->mode == MCDI_MODE_FAIL) | ||
| 673 | return -ENETDOWN; | ||
| 674 | |||
| 675 | efx_mcdi_acquire_sync(mcdi); | 675 | efx_mcdi_acquire_sync(mcdi); |
| 676 | efx_mcdi_send_request(efx, cmd, inbuf, inlen); | 676 | efx_mcdi_send_request(efx, cmd, inbuf, inlen); |
| 677 | return 0; | 677 | return 0; |
| @@ -812,7 +812,11 @@ void efx_mcdi_mode_poll(struct efx_nic *efx) | |||
| 812 | return; | 812 | return; |
| 813 | 813 | ||
| 814 | mcdi = efx_mcdi(efx); | 814 | mcdi = efx_mcdi(efx); |
| 815 | if (mcdi->mode == MCDI_MODE_POLL) | 815 | /* If already in polling mode, nothing to do. |
| 816 | * If in fail-fast state, don't switch to polled completion. | ||
| 817 | * FLR recovery will do that later. | ||
| 818 | */ | ||
| 819 | if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL) | ||
| 816 | return; | 820 | return; |
| 817 | 821 | ||
| 818 | /* We can switch from event completion to polled completion, because | 822 | /* We can switch from event completion to polled completion, because |
| @@ -841,8 +845,8 @@ void efx_mcdi_flush_async(struct efx_nic *efx) | |||
| 841 | 845 | ||
| 842 | mcdi = efx_mcdi(efx); | 846 | mcdi = efx_mcdi(efx); |
| 843 | 847 | ||
| 844 | /* We must be in polling mode so no more requests can be queued */ | 848 | /* We must be in poll or fail mode so no more requests can be queued */ |
| 845 | BUG_ON(mcdi->mode != MCDI_MODE_POLL); | 849 | BUG_ON(mcdi->mode == MCDI_MODE_EVENTS); |
| 846 | 850 | ||
| 847 | del_timer_sync(&mcdi->async_timer); | 851 | del_timer_sync(&mcdi->async_timer); |
| 848 | 852 | ||
| @@ -875,8 +879,11 @@ void efx_mcdi_mode_event(struct efx_nic *efx) | |||
| 875 | return; | 879 | return; |
| 876 | 880 | ||
| 877 | mcdi = efx_mcdi(efx); | 881 | mcdi = efx_mcdi(efx); |
| 878 | 882 | /* If already in event completion mode, nothing to do. | |
| 879 | if (mcdi->mode == MCDI_MODE_EVENTS) | 883 | * If in fail-fast state, don't switch to event completion. FLR |
| 884 | * recovery will do that later. | ||
| 885 | */ | ||
| 886 | if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL) | ||
| 880 | return; | 887 | return; |
| 881 | 888 | ||
| 882 | /* We can't switch from polled to event completion in the middle of a | 889 | /* We can't switch from polled to event completion in the middle of a |
| @@ -966,6 +973,19 @@ static void efx_mcdi_ev_bist(struct efx_nic *efx) | |||
| 966 | spin_unlock(&mcdi->iface_lock); | 973 | spin_unlock(&mcdi->iface_lock); |
| 967 | } | 974 | } |
| 968 | 975 | ||
| 976 | /* MCDI timeouts seen, so make all MCDI calls fail-fast and issue an FLR to try | ||
| 977 | * to recover. | ||
| 978 | */ | ||
| 979 | static void efx_mcdi_abandon(struct efx_nic *efx) | ||
| 980 | { | ||
| 981 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); | ||
| 982 | |||
| 983 | if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL) | ||
| 984 | return; /* it had already been done */ | ||
| 985 | netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n"); | ||
| 986 | efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT); | ||
| 987 | } | ||
| 988 | |||
| 969 | /* Called from falcon_process_eventq for MCDI events */ | 989 | /* Called from falcon_process_eventq for MCDI events */ |
| 970 | void efx_mcdi_process_event(struct efx_channel *channel, | 990 | void efx_mcdi_process_event(struct efx_channel *channel, |
| 971 | efx_qword_t *event) | 991 | efx_qword_t *event) |
| @@ -1512,6 +1532,19 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method) | |||
| 1512 | { | 1532 | { |
| 1513 | int rc; | 1533 | int rc; |
| 1514 | 1534 | ||
| 1535 | /* If MCDI is down, we can't handle_assertion */ | ||
| 1536 | if (method == RESET_TYPE_MCDI_TIMEOUT) { | ||
| 1537 | rc = pci_reset_function(efx->pci_dev); | ||
| 1538 | if (rc) | ||
| 1539 | return rc; | ||
| 1540 | /* Re-enable polled MCDI completion */ | ||
| 1541 | if (efx->mcdi) { | ||
| 1542 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); | ||
| 1543 | mcdi->mode = MCDI_MODE_POLL; | ||
| 1544 | } | ||
| 1545 | return 0; | ||
| 1546 | } | ||
| 1547 | |||
| 1515 | /* Recover from a failed assertion pre-reset */ | 1548 | /* Recover from a failed assertion pre-reset */ |
| 1516 | rc = efx_mcdi_handle_assertion(efx); | 1549 | rc = efx_mcdi_handle_assertion(efx); |
| 1517 | if (rc) | 1550 | if (rc) |
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 52931aebf3c3..56465f7465a2 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h | |||
| @@ -28,9 +28,16 @@ enum efx_mcdi_state { | |||
| 28 | MCDI_STATE_COMPLETED, | 28 | MCDI_STATE_COMPLETED, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | /** | ||
| 32 | * enum efx_mcdi_mode - MCDI transaction mode | ||
| 33 | * @MCDI_MODE_POLL: poll for MCDI completion, until timeout | ||
| 34 | * @MCDI_MODE_EVENTS: wait for an mcdi_event. On timeout, poll once | ||
| 35 | * @MCDI_MODE_FAIL: we think MCDI is dead, so fail-fast all calls | ||
| 36 | */ | ||
| 31 | enum efx_mcdi_mode { | 37 | enum efx_mcdi_mode { |
| 32 | MCDI_MODE_POLL, | 38 | MCDI_MODE_POLL, |
| 33 | MCDI_MODE_EVENTS, | 39 | MCDI_MODE_EVENTS, |
| 40 | MCDI_MODE_FAIL, | ||
| 34 | }; | 41 | }; |
| 35 | 42 | ||
| 36 | /** | 43 | /** |
| @@ -104,6 +111,12 @@ struct efx_mcdi_data { | |||
| 104 | u32 fn_flags; | 111 | u32 fn_flags; |
| 105 | }; | 112 | }; |
| 106 | 113 | ||
| 114 | static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) | ||
| 115 | { | ||
| 116 | EFX_BUG_ON_PARANOID(!efx->mcdi); | ||
| 117 | return &efx->mcdi->iface; | ||
| 118 | } | ||
| 119 | |||
| 107 | #ifdef CONFIG_SFC_MCDI_MON | 120 | #ifdef CONFIG_SFC_MCDI_MON |
| 108 | static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) | 121 | static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) |
| 109 | { | 122 | { |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 8a400a0595eb..5bdae8ed7c57 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
| @@ -972,6 +972,8 @@ struct efx_mtd_partition { | |||
| 972 | * (for Falcon architecture) | 972 | * (for Falcon architecture) |
| 973 | * @finish_flush: Clean up after flushing the DMA queues (for Falcon | 973 | * @finish_flush: Clean up after flushing the DMA queues (for Falcon |
| 974 | * architecture) | 974 | * architecture) |
| 975 | * @prepare_flr: Prepare for an FLR | ||
| 976 | * @finish_flr: Clean up after an FLR | ||
| 975 | * @describe_stats: Describe statistics for ethtool | 977 | * @describe_stats: Describe statistics for ethtool |
| 976 | * @update_stats: Update statistics not provided by event handling. | 978 | * @update_stats: Update statistics not provided by event handling. |
| 977 | * Either argument may be %NULL. | 979 | * Either argument may be %NULL. |
| @@ -1100,6 +1102,8 @@ struct efx_nic_type { | |||
| 1100 | int (*fini_dmaq)(struct efx_nic *efx); | 1102 | int (*fini_dmaq)(struct efx_nic *efx); |
| 1101 | void (*prepare_flush)(struct efx_nic *efx); | 1103 | void (*prepare_flush)(struct efx_nic *efx); |
| 1102 | void (*finish_flush)(struct efx_nic *efx); | 1104 | void (*finish_flush)(struct efx_nic *efx); |
| 1105 | void (*prepare_flr)(struct efx_nic *efx); | ||
| 1106 | void (*finish_flr)(struct efx_nic *efx); | ||
| 1103 | size_t (*describe_stats)(struct efx_nic *efx, u8 *names); | 1107 | size_t (*describe_stats)(struct efx_nic *efx, u8 *names); |
| 1104 | size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, | 1108 | size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, |
| 1105 | struct rtnl_link_stats64 *core_stats); | 1109 | struct rtnl_link_stats64 *core_stats); |
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index a001fae1a8d7..d3ad8ed8d901 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h | |||
| @@ -757,6 +757,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx) | |||
| 757 | int efx_nic_flush_queues(struct efx_nic *efx); | 757 | int efx_nic_flush_queues(struct efx_nic *efx); |
| 758 | void siena_prepare_flush(struct efx_nic *efx); | 758 | void siena_prepare_flush(struct efx_nic *efx); |
| 759 | int efx_farch_fini_dmaq(struct efx_nic *efx); | 759 | int efx_farch_fini_dmaq(struct efx_nic *efx); |
| 760 | void efx_farch_finish_flr(struct efx_nic *efx); | ||
| 760 | void siena_finish_flush(struct efx_nic *efx); | 761 | void siena_finish_flush(struct efx_nic *efx); |
| 761 | void falcon_start_nic_stats(struct efx_nic *efx); | 762 | void falcon_start_nic_stats(struct efx_nic *efx); |
| 762 | void falcon_stop_nic_stats(struct efx_nic *efx); | 763 | void falcon_stop_nic_stats(struct efx_nic *efx); |
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 23f3a6f7737a..50ffefed492c 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c | |||
| @@ -921,6 +921,8 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
| 921 | .fini_dmaq = efx_farch_fini_dmaq, | 921 | .fini_dmaq = efx_farch_fini_dmaq, |
| 922 | .prepare_flush = siena_prepare_flush, | 922 | .prepare_flush = siena_prepare_flush, |
| 923 | .finish_flush = siena_finish_flush, | 923 | .finish_flush = siena_finish_flush, |
| 924 | .prepare_flr = efx_port_dummy_op_void, | ||
| 925 | .finish_flr = efx_farch_finish_flr, | ||
| 924 | .describe_stats = siena_describe_nic_stats, | 926 | .describe_stats = siena_describe_nic_stats, |
| 925 | .update_stats = siena_update_nic_stats, | 927 | .update_stats = siena_update_nic_stats, |
| 926 | .start_stats = efx_mcdi_mac_start_stats, | 928 | .start_stats = efx_mcdi_mac_start_stats, |
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index e701433bf52f..9c4defdec67b 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c | |||
| @@ -32,29 +32,39 @@ | |||
| 32 | 32 | ||
| 33 | struct mdio_gpio_info { | 33 | struct mdio_gpio_info { |
| 34 | struct mdiobb_ctrl ctrl; | 34 | struct mdiobb_ctrl ctrl; |
| 35 | int mdc, mdio; | 35 | int mdc, mdio, mdo; |
| 36 | int mdc_active_low, mdio_active_low, mdo_active_low; | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | static void *mdio_gpio_of_get_data(struct platform_device *pdev) | 39 | static void *mdio_gpio_of_get_data(struct platform_device *pdev) |
| 39 | { | 40 | { |
| 40 | struct device_node *np = pdev->dev.of_node; | 41 | struct device_node *np = pdev->dev.of_node; |
| 41 | struct mdio_gpio_platform_data *pdata; | 42 | struct mdio_gpio_platform_data *pdata; |
| 43 | enum of_gpio_flags flags; | ||
| 42 | int ret; | 44 | int ret; |
| 43 | 45 | ||
| 44 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 46 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 45 | if (!pdata) | 47 | if (!pdata) |
| 46 | return NULL; | 48 | return NULL; |
| 47 | 49 | ||
| 48 | ret = of_get_gpio(np, 0); | 50 | ret = of_get_gpio_flags(np, 0, &flags); |
| 49 | if (ret < 0) | 51 | if (ret < 0) |
| 50 | return NULL; | 52 | return NULL; |
| 51 | 53 | ||
| 52 | pdata->mdc = ret; | 54 | pdata->mdc = ret; |
| 55 | pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
| 53 | 56 | ||
| 54 | ret = of_get_gpio(np, 1); | 57 | ret = of_get_gpio_flags(np, 1, &flags); |
| 55 | if (ret < 0) | 58 | if (ret < 0) |
| 56 | return NULL; | 59 | return NULL; |
| 57 | pdata->mdio = ret; | 60 | pdata->mdio = ret; |
| 61 | pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
| 62 | |||
| 63 | ret = of_get_gpio_flags(np, 2, &flags); | ||
| 64 | if (ret > 0) { | ||
| 65 | pdata->mdo = ret; | ||
| 66 | pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
| 67 | } | ||
| 58 | 68 | ||
| 59 | return pdata; | 69 | return pdata; |
| 60 | } | 70 | } |
| @@ -64,8 +74,19 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) | |||
| 64 | struct mdio_gpio_info *bitbang = | 74 | struct mdio_gpio_info *bitbang = |
| 65 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 75 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
| 66 | 76 | ||
| 77 | if (bitbang->mdo) { | ||
| 78 | /* Separate output pin. Always set its value to high | ||
| 79 | * when changing direction. If direction is input, | ||
| 80 | * assume the pin serves as pull-up. If direction is | ||
| 81 | * output, the default value is high. | ||
| 82 | */ | ||
| 83 | gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 67 | if (dir) | 87 | if (dir) |
| 68 | gpio_direction_output(bitbang->mdio, 1); | 88 | gpio_direction_output(bitbang->mdio, |
| 89 | 1 ^ bitbang->mdio_active_low); | ||
| 69 | else | 90 | else |
| 70 | gpio_direction_input(bitbang->mdio); | 91 | gpio_direction_input(bitbang->mdio); |
| 71 | } | 92 | } |
| @@ -75,7 +96,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl) | |||
| 75 | struct mdio_gpio_info *bitbang = | 96 | struct mdio_gpio_info *bitbang = |
| 76 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 97 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
| 77 | 98 | ||
| 78 | return gpio_get_value(bitbang->mdio); | 99 | return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low; |
| 79 | } | 100 | } |
| 80 | 101 | ||
| 81 | static void mdio_set(struct mdiobb_ctrl *ctrl, int what) | 102 | static void mdio_set(struct mdiobb_ctrl *ctrl, int what) |
| @@ -83,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what) | |||
| 83 | struct mdio_gpio_info *bitbang = | 104 | struct mdio_gpio_info *bitbang = |
| 84 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 105 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
| 85 | 106 | ||
| 86 | gpio_set_value(bitbang->mdio, what); | 107 | if (bitbang->mdo) |
| 108 | gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low); | ||
| 109 | else | ||
| 110 | gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); | ||
| 87 | } | 111 | } |
| 88 | 112 | ||
| 89 | static void mdc_set(struct mdiobb_ctrl *ctrl, int what) | 113 | static void mdc_set(struct mdiobb_ctrl *ctrl, int what) |
| @@ -91,7 +115,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what) | |||
| 91 | struct mdio_gpio_info *bitbang = | 115 | struct mdio_gpio_info *bitbang = |
| 92 | container_of(ctrl, struct mdio_gpio_info, ctrl); | 116 | container_of(ctrl, struct mdio_gpio_info, ctrl); |
| 93 | 117 | ||
| 94 | gpio_set_value(bitbang->mdc, what); | 118 | gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low); |
| 95 | } | 119 | } |
| 96 | 120 | ||
| 97 | static struct mdiobb_ops mdio_gpio_ops = { | 121 | static struct mdiobb_ops mdio_gpio_ops = { |
| @@ -110,18 +134,22 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, | |||
| 110 | struct mdio_gpio_info *bitbang; | 134 | struct mdio_gpio_info *bitbang; |
| 111 | int i; | 135 | int i; |
| 112 | 136 | ||
| 113 | bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL); | 137 | bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL); |
| 114 | if (!bitbang) | 138 | if (!bitbang) |
| 115 | goto out; | 139 | goto out; |
| 116 | 140 | ||
| 117 | bitbang->ctrl.ops = &mdio_gpio_ops; | 141 | bitbang->ctrl.ops = &mdio_gpio_ops; |
| 118 | bitbang->ctrl.reset = pdata->reset; | 142 | bitbang->ctrl.reset = pdata->reset; |
| 119 | bitbang->mdc = pdata->mdc; | 143 | bitbang->mdc = pdata->mdc; |
| 144 | bitbang->mdc_active_low = pdata->mdc_active_low; | ||
| 120 | bitbang->mdio = pdata->mdio; | 145 | bitbang->mdio = pdata->mdio; |
| 146 | bitbang->mdio_active_low = pdata->mdio_active_low; | ||
| 147 | bitbang->mdo = pdata->mdo; | ||
| 148 | bitbang->mdo_active_low = pdata->mdo_active_low; | ||
| 121 | 149 | ||
| 122 | new_bus = alloc_mdio_bitbang(&bitbang->ctrl); | 150 | new_bus = alloc_mdio_bitbang(&bitbang->ctrl); |
| 123 | if (!new_bus) | 151 | if (!new_bus) |
| 124 | goto out_free_bitbang; | 152 | goto out; |
| 125 | 153 | ||
| 126 | new_bus->name = "GPIO Bitbanged MDIO", | 154 | new_bus->name = "GPIO Bitbanged MDIO", |
| 127 | 155 | ||
| @@ -138,11 +166,18 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, | |||
| 138 | 166 | ||
| 139 | snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); | 167 | snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); |
| 140 | 168 | ||
| 141 | if (gpio_request(bitbang->mdc, "mdc")) | 169 | if (devm_gpio_request(dev, bitbang->mdc, "mdc")) |
| 170 | goto out_free_bus; | ||
| 171 | |||
| 172 | if (devm_gpio_request(dev, bitbang->mdio, "mdio")) | ||
| 142 | goto out_free_bus; | 173 | goto out_free_bus; |
| 143 | 174 | ||
| 144 | if (gpio_request(bitbang->mdio, "mdio")) | 175 | if (bitbang->mdo) { |
| 145 | goto out_free_mdc; | 176 | if (devm_gpio_request(dev, bitbang->mdo, "mdo")) |
| 177 | goto out_free_bus; | ||
| 178 | gpio_direction_output(bitbang->mdo, 1); | ||
| 179 | gpio_direction_input(bitbang->mdio); | ||
| 180 | } | ||
| 146 | 181 | ||
| 147 | gpio_direction_output(bitbang->mdc, 0); | 182 | gpio_direction_output(bitbang->mdc, 0); |
| 148 | 183 | ||
| @@ -150,12 +185,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, | |||
| 150 | 185 | ||
| 151 | return new_bus; | 186 | return new_bus; |
| 152 | 187 | ||
| 153 | out_free_mdc: | ||
| 154 | gpio_free(bitbang->mdc); | ||
| 155 | out_free_bus: | 188 | out_free_bus: |
| 156 | free_mdio_bitbang(new_bus); | 189 | free_mdio_bitbang(new_bus); |
| 157 | out_free_bitbang: | ||
| 158 | kfree(bitbang); | ||
| 159 | out: | 190 | out: |
| 160 | return NULL; | 191 | return NULL; |
| 161 | } | 192 | } |
| @@ -163,13 +194,8 @@ out: | |||
| 163 | static void mdio_gpio_bus_deinit(struct device *dev) | 194 | static void mdio_gpio_bus_deinit(struct device *dev) |
| 164 | { | 195 | { |
| 165 | struct mii_bus *bus = dev_get_drvdata(dev); | 196 | struct mii_bus *bus = dev_get_drvdata(dev); |
| 166 | struct mdio_gpio_info *bitbang = bus->priv; | ||
| 167 | 197 | ||
| 168 | dev_set_drvdata(dev, NULL); | ||
| 169 | gpio_free(bitbang->mdio); | ||
| 170 | gpio_free(bitbang->mdc); | ||
| 171 | free_mdio_bitbang(bus); | 198 | free_mdio_bitbang(bus); |
| 172 | kfree(bitbang); | ||
| 173 | } | 199 | } |
| 174 | 200 | ||
| 175 | static void mdio_gpio_bus_destroy(struct device *dev) | 201 | static void mdio_gpio_bus_destroy(struct device *dev) |
diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index e323b4d54338..34f97c31eecf 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c | |||
| @@ -41,6 +41,8 @@ static const char * const cw1200_debug_link_id[] = { | |||
| 41 | "REQ", | 41 | "REQ", |
| 42 | "SOFT", | 42 | "SOFT", |
| 43 | "HARD", | 43 | "HARD", |
| 44 | "RESET", | ||
| 45 | "RESET_REMAP", | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | static const char *cw1200_debug_mode(int mode) | 48 | static const char *cw1200_debug_mode(int mode) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 003a546571d4..4c2d4ef28b22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -67,8 +67,8 @@ | |||
| 67 | #include "iwl-agn-hw.h" | 67 | #include "iwl-agn-hw.h" |
| 68 | 68 | ||
| 69 | /* Highest firmware API version supported */ | 69 | /* Highest firmware API version supported */ |
| 70 | #define IWL7260_UCODE_API_MAX 8 | 70 | #define IWL7260_UCODE_API_MAX 9 |
| 71 | #define IWL3160_UCODE_API_MAX 8 | 71 | #define IWL3160_UCODE_API_MAX 9 |
| 72 | 72 | ||
| 73 | /* Oldest version we won't warn about */ | 73 | /* Oldest version we won't warn about */ |
| 74 | #define IWL7260_UCODE_API_OK 8 | 74 | #define IWL7260_UCODE_API_OK 8 |
| @@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { | |||
| 244 | 244 | ||
| 245 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | 245 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
| 246 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); | 246 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); |
| 247 | MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 685f7e8e6943..fa858d548d13 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
| @@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | |||
| 190 | cpu_to_le32(0xcc00aaaa), | 190 | cpu_to_le32(0xcc00aaaa), |
| 191 | cpu_to_le32(0x0000aaaa), | 191 | cpu_to_le32(0x0000aaaa), |
| 192 | cpu_to_le32(0xc0004000), | 192 | cpu_to_le32(0xc0004000), |
| 193 | cpu_to_le32(0x00000000), | 193 | cpu_to_le32(0x00004000), |
| 194 | cpu_to_le32(0xf0005000), | 194 | cpu_to_le32(0xf0005000), |
| 195 | cpu_to_le32(0xf0005000), | 195 | cpu_to_le32(0xf0005000), |
| 196 | }, | 196 | }, |
| @@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | |||
| 213 | /* Tx Tx disabled */ | 213 | /* Tx Tx disabled */ |
| 214 | cpu_to_le32(0xaaaaaaaa), | 214 | cpu_to_le32(0xaaaaaaaa), |
| 215 | cpu_to_le32(0xaaaaaaaa), | 215 | cpu_to_le32(0xaaaaaaaa), |
| 216 | cpu_to_le32(0xaaaaaaaa), | 216 | cpu_to_le32(0xeeaaaaaa), |
| 217 | cpu_to_le32(0xaaaaaaaa), | 217 | cpu_to_le32(0xaaaaaaaa), |
| 218 | cpu_to_le32(0xcc00ff28), | 218 | cpu_to_le32(0xcc00ff28), |
| 219 | cpu_to_le32(0x0000aaaa), | 219 | cpu_to_le32(0x0000aaaa), |
| 220 | cpu_to_le32(0xcc00aaaa), | 220 | cpu_to_le32(0xcc00aaaa), |
| 221 | cpu_to_le32(0x0000aaaa), | 221 | cpu_to_le32(0x0000aaaa), |
| 222 | cpu_to_le32(0xC0004000), | 222 | cpu_to_le32(0xc0004000), |
| 223 | cpu_to_le32(0xC0004000), | 223 | cpu_to_le32(0xc0004000), |
| 224 | cpu_to_le32(0xF0005000), | 224 | cpu_to_le32(0xf0005000), |
| 225 | cpu_to_le32(0xF0005000), | 225 | cpu_to_le32(0xf0005000), |
| 226 | }, | 226 | }, |
| 227 | }; | 227 | }; |
| 228 | 228 | ||
| @@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | |||
| 1262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 1263 | u32 ant_isolation = le32_to_cpup((void *)pkt->data); | 1263 | u32 ant_isolation = le32_to_cpup((void *)pkt->data); |
| 1264 | u8 __maybe_unused lower_bound, upper_bound; | 1264 | u8 __maybe_unused lower_bound, upper_bound; |
| 1265 | int ret; | ||
| 1265 | u8 lut; | 1266 | u8 lut; |
| 1266 | 1267 | ||
| 1267 | struct iwl_bt_coex_cmd *bt_cmd; | 1268 | struct iwl_bt_coex_cmd *bt_cmd; |
| @@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | |||
| 1318 | memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, | 1319 | memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, |
| 1319 | sizeof(bt_cmd->bt4_corun_lut40)); | 1320 | sizeof(bt_cmd->bt4_corun_lut40)); |
| 1320 | 1321 | ||
| 1321 | return 0; | 1322 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
| 1323 | |||
| 1324 | kfree(bt_cmd); | ||
| 1325 | return ret; | ||
| 1322 | } | 1326 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 4dd9ff43b8b6..f0cebf12c7b8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 1332 | */ | 1332 | */ |
| 1333 | iwl_mvm_remove_time_event(mvm, mvmvif, | 1333 | iwl_mvm_remove_time_event(mvm, mvmvif, |
| 1334 | &mvmvif->time_event_data); | 1334 | &mvmvif->time_event_data); |
| 1335 | iwl_mvm_sf_update(mvm, vif, false); | ||
| 1335 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); | 1336 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); |
| 1336 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | | 1337 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
| 1337 | BSS_CHANGED_QOS)) { | 1338 | BSS_CHANGED_QOS)) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 568abd61b14f..9f52c5b3f0ec 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -59,7 +59,7 @@ | |||
| 59 | /* max allowed rate miss before sync LQ cmd */ | 59 | /* max allowed rate miss before sync LQ cmd */ |
| 60 | #define IWL_MISSED_RATE_MAX 15 | 60 | #define IWL_MISSED_RATE_MAX 15 |
| 61 | #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) | 61 | #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) |
| 62 | 62 | #define RS_IDLE_TIMEOUT (5*HZ) | |
| 63 | 63 | ||
| 64 | static u8 rs_ht_to_legacy[] = { | 64 | static u8 rs_ht_to_legacy[] = { |
| 65 | [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, | 65 | [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, |
| @@ -142,7 +142,7 @@ enum rs_column_mode { | |||
| 142 | RS_MIMO2, | 142 | RS_MIMO2, |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | #define MAX_NEXT_COLUMNS 5 | 145 | #define MAX_NEXT_COLUMNS 7 |
| 146 | #define MAX_COLUMN_CHECKS 3 | 146 | #define MAX_COLUMN_CHECKS 3 |
| 147 | 147 | ||
| 148 | typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, | 148 | typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, |
| @@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 212 | RS_COLUMN_LEGACY_ANT_B, | 212 | RS_COLUMN_LEGACY_ANT_B, |
| 213 | RS_COLUMN_SISO_ANT_A, | 213 | RS_COLUMN_SISO_ANT_A, |
| 214 | RS_COLUMN_SISO_ANT_B, | 214 | RS_COLUMN_SISO_ANT_B, |
| 215 | RS_COLUMN_MIMO2, | 215 | RS_COLUMN_INVALID, |
| 216 | RS_COLUMN_MIMO2_SGI, | 216 | RS_COLUMN_INVALID, |
| 217 | RS_COLUMN_INVALID, | ||
| 218 | RS_COLUMN_INVALID, | ||
| 217 | }, | 219 | }, |
| 218 | }, | 220 | }, |
| 219 | [RS_COLUMN_LEGACY_ANT_B] = { | 221 | [RS_COLUMN_LEGACY_ANT_B] = { |
| @@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 223 | RS_COLUMN_LEGACY_ANT_A, | 225 | RS_COLUMN_LEGACY_ANT_A, |
| 224 | RS_COLUMN_SISO_ANT_A, | 226 | RS_COLUMN_SISO_ANT_A, |
| 225 | RS_COLUMN_SISO_ANT_B, | 227 | RS_COLUMN_SISO_ANT_B, |
| 226 | RS_COLUMN_MIMO2, | 228 | RS_COLUMN_INVALID, |
| 227 | RS_COLUMN_MIMO2_SGI, | 229 | RS_COLUMN_INVALID, |
| 230 | RS_COLUMN_INVALID, | ||
| 231 | RS_COLUMN_INVALID, | ||
| 228 | }, | 232 | }, |
| 229 | }, | 233 | }, |
| 230 | [RS_COLUMN_SISO_ANT_A] = { | 234 | [RS_COLUMN_SISO_ANT_A] = { |
| @@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 235 | RS_COLUMN_MIMO2, | 239 | RS_COLUMN_MIMO2, |
| 236 | RS_COLUMN_SISO_ANT_A_SGI, | 240 | RS_COLUMN_SISO_ANT_A_SGI, |
| 237 | RS_COLUMN_SISO_ANT_B_SGI, | 241 | RS_COLUMN_SISO_ANT_B_SGI, |
| 238 | RS_COLUMN_MIMO2_SGI, | 242 | RS_COLUMN_LEGACY_ANT_A, |
| 243 | RS_COLUMN_LEGACY_ANT_B, | ||
| 244 | RS_COLUMN_INVALID, | ||
| 239 | }, | 245 | }, |
| 240 | .checks = { | 246 | .checks = { |
| 241 | rs_siso_allow, | 247 | rs_siso_allow, |
| @@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 249 | RS_COLUMN_MIMO2, | 255 | RS_COLUMN_MIMO2, |
| 250 | RS_COLUMN_SISO_ANT_B_SGI, | 256 | RS_COLUMN_SISO_ANT_B_SGI, |
| 251 | RS_COLUMN_SISO_ANT_A_SGI, | 257 | RS_COLUMN_SISO_ANT_A_SGI, |
| 252 | RS_COLUMN_MIMO2_SGI, | 258 | RS_COLUMN_LEGACY_ANT_A, |
| 259 | RS_COLUMN_LEGACY_ANT_B, | ||
| 260 | RS_COLUMN_INVALID, | ||
| 253 | }, | 261 | }, |
| 254 | .checks = { | 262 | .checks = { |
| 255 | rs_siso_allow, | 263 | rs_siso_allow, |
| @@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 265 | RS_COLUMN_SISO_ANT_A, | 273 | RS_COLUMN_SISO_ANT_A, |
| 266 | RS_COLUMN_SISO_ANT_B, | 274 | RS_COLUMN_SISO_ANT_B, |
| 267 | RS_COLUMN_MIMO2, | 275 | RS_COLUMN_MIMO2, |
| 276 | RS_COLUMN_LEGACY_ANT_A, | ||
| 277 | RS_COLUMN_LEGACY_ANT_B, | ||
| 268 | }, | 278 | }, |
| 269 | .checks = { | 279 | .checks = { |
| 270 | rs_siso_allow, | 280 | rs_siso_allow, |
| @@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 281 | RS_COLUMN_SISO_ANT_B, | 291 | RS_COLUMN_SISO_ANT_B, |
| 282 | RS_COLUMN_SISO_ANT_A, | 292 | RS_COLUMN_SISO_ANT_A, |
| 283 | RS_COLUMN_MIMO2, | 293 | RS_COLUMN_MIMO2, |
| 294 | RS_COLUMN_LEGACY_ANT_A, | ||
| 295 | RS_COLUMN_LEGACY_ANT_B, | ||
| 284 | }, | 296 | }, |
| 285 | .checks = { | 297 | .checks = { |
| 286 | rs_siso_allow, | 298 | rs_siso_allow, |
| @@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 296 | RS_COLUMN_SISO_ANT_A_SGI, | 308 | RS_COLUMN_SISO_ANT_A_SGI, |
| 297 | RS_COLUMN_SISO_ANT_B_SGI, | 309 | RS_COLUMN_SISO_ANT_B_SGI, |
| 298 | RS_COLUMN_MIMO2_SGI, | 310 | RS_COLUMN_MIMO2_SGI, |
| 311 | RS_COLUMN_LEGACY_ANT_A, | ||
| 312 | RS_COLUMN_LEGACY_ANT_B, | ||
| 299 | }, | 313 | }, |
| 300 | .checks = { | 314 | .checks = { |
| 301 | rs_mimo_allow, | 315 | rs_mimo_allow, |
| @@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 311 | RS_COLUMN_SISO_ANT_A, | 325 | RS_COLUMN_SISO_ANT_A, |
| 312 | RS_COLUMN_SISO_ANT_B, | 326 | RS_COLUMN_SISO_ANT_B, |
| 313 | RS_COLUMN_MIMO2, | 327 | RS_COLUMN_MIMO2, |
| 328 | RS_COLUMN_LEGACY_ANT_A, | ||
| 329 | RS_COLUMN_LEGACY_ANT_B, | ||
| 314 | }, | 330 | }, |
| 315 | .checks = { | 331 | .checks = { |
| 316 | rs_mimo_allow, | 332 | rs_mimo_allow, |
| @@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | |||
| 503 | window->average_tpt = IWL_INVALID_VALUE; | 519 | window->average_tpt = IWL_INVALID_VALUE; |
| 504 | } | 520 | } |
| 505 | 521 | ||
| 506 | static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) | 522 | static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm, |
| 523 | struct iwl_scale_tbl_info *tbl) | ||
| 507 | { | 524 | { |
| 508 | int i; | 525 | int i; |
| 509 | 526 | ||
| 527 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | ||
| 510 | for (i = 0; i < IWL_RATE_COUNT; i++) | 528 | for (i = 0; i < IWL_RATE_COUNT; i++) |
| 511 | rs_rate_scale_clear_window(&tbl->win[i]); | 529 | rs_rate_scale_clear_window(&tbl->win[i]); |
| 512 | } | 530 | } |
| @@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
| 992 | return; | 1010 | return; |
| 993 | } | 1011 | } |
| 994 | 1012 | ||
| 1013 | #ifdef CPTCFG_MAC80211_DEBUGFS | ||
| 1014 | /* Disable last tx check if we are debugging with fixed rate */ | ||
| 1015 | if (lq_sta->dbg_fixed_rate) { | ||
| 1016 | IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); | ||
| 1017 | return; | ||
| 1018 | } | ||
| 1019 | #endif | ||
| 995 | if (!ieee80211_is_data(hdr->frame_control) || | 1020 | if (!ieee80211_is_data(hdr->frame_control) || |
| 996 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 1021 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
| 997 | return; | 1022 | return; |
| @@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
| 1034 | mac_index++; | 1059 | mac_index++; |
| 1035 | } | 1060 | } |
| 1036 | 1061 | ||
| 1062 | if (time_after(jiffies, | ||
| 1063 | (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) { | ||
| 1064 | int tid; | ||
| 1065 | IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); | ||
| 1066 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) | ||
| 1067 | ieee80211_stop_tx_ba_session(sta, tid); | ||
| 1068 | |||
| 1069 | iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); | ||
| 1070 | return; | ||
| 1071 | } | ||
| 1072 | lq_sta->last_tx = jiffies; | ||
| 1073 | |||
| 1037 | /* Here we actually compare this rate to the latest LQ command */ | 1074 | /* Here we actually compare this rate to the latest LQ command */ |
| 1038 | if ((mac_index < 0) || | 1075 | if ((mac_index < 0) || |
| 1039 | (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 1076 | (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
| @@ -1186,9 +1223,26 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, | |||
| 1186 | lq_sta->visited_columns = 0; | 1223 | lq_sta->visited_columns = 0; |
| 1187 | } | 1224 | } |
| 1188 | 1225 | ||
| 1226 | static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta, | ||
| 1227 | const struct rs_tx_column *column) | ||
| 1228 | { | ||
| 1229 | switch (column->mode) { | ||
| 1230 | case RS_LEGACY: | ||
| 1231 | return lq_sta->max_legacy_rate_idx; | ||
| 1232 | case RS_SISO: | ||
| 1233 | return lq_sta->max_siso_rate_idx; | ||
| 1234 | case RS_MIMO2: | ||
| 1235 | return lq_sta->max_mimo2_rate_idx; | ||
| 1236 | default: | ||
| 1237 | WARN_ON_ONCE(1); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | return lq_sta->max_legacy_rate_idx; | ||
| 1241 | } | ||
| 1242 | |||
| 1189 | static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, | 1243 | static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
| 1190 | const struct rs_tx_column *column, | 1244 | const struct rs_tx_column *column, |
| 1191 | u32 bw) | 1245 | u32 bw) |
| 1192 | { | 1246 | { |
| 1193 | /* Used to choose among HT tables */ | 1247 | /* Used to choose among HT tables */ |
| 1194 | const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | 1248 | const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; |
| @@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
| 1438 | 1492 | ||
| 1439 | IWL_DEBUG_RATE(mvm, | 1493 | IWL_DEBUG_RATE(mvm, |
| 1440 | "LQ: stay in table clear win\n"); | 1494 | "LQ: stay in table clear win\n"); |
| 1441 | rs_rate_scale_clear_tbl_windows(tbl); | 1495 | rs_rate_scale_clear_tbl_windows(mvm, tbl); |
| 1442 | } | 1496 | } |
| 1443 | } | 1497 | } |
| 1444 | 1498 | ||
| @@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
| 1446 | * bitmaps and stats in active table (this will become the new | 1500 | * bitmaps and stats in active table (this will become the new |
| 1447 | * "search" table). */ | 1501 | * "search" table). */ |
| 1448 | if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { | 1502 | if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { |
| 1449 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | 1503 | rs_rate_scale_clear_tbl_windows(mvm, tbl); |
| 1450 | rs_rate_scale_clear_tbl_windows(tbl); | ||
| 1451 | } | 1504 | } |
| 1452 | } | 1505 | } |
| 1453 | } | 1506 | } |
| @@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | |||
| 1485 | struct ieee80211_sta *sta, | 1538 | struct ieee80211_sta *sta, |
| 1486 | struct iwl_scale_tbl_info *tbl) | 1539 | struct iwl_scale_tbl_info *tbl) |
| 1487 | { | 1540 | { |
| 1488 | int i, j, n; | 1541 | int i, j, max_rate; |
| 1489 | enum rs_column next_col_id; | 1542 | enum rs_column next_col_id; |
| 1490 | const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; | 1543 | const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; |
| 1491 | const struct rs_tx_column *next_col; | 1544 | const struct rs_tx_column *next_col; |
| 1492 | allow_column_func_t allow_func; | 1545 | allow_column_func_t allow_func; |
| 1493 | u8 valid_ants = mvm->fw->valid_tx_ant; | 1546 | u8 valid_ants = mvm->fw->valid_tx_ant; |
| 1494 | const u16 *expected_tpt_tbl; | 1547 | const u16 *expected_tpt_tbl; |
| 1495 | s32 tpt, max_expected_tpt; | 1548 | u16 tpt, max_expected_tpt; |
| 1496 | 1549 | ||
| 1497 | for (i = 0; i < MAX_NEXT_COLUMNS; i++) { | 1550 | for (i = 0; i < MAX_NEXT_COLUMNS; i++) { |
| 1498 | next_col_id = curr_col->next_columns[i]; | 1551 | next_col_id = curr_col->next_columns[i]; |
| @@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | |||
| 1535 | if (WARN_ON_ONCE(!expected_tpt_tbl)) | 1588 | if (WARN_ON_ONCE(!expected_tpt_tbl)) |
| 1536 | continue; | 1589 | continue; |
| 1537 | 1590 | ||
| 1538 | max_expected_tpt = 0; | 1591 | max_rate = rs_get_max_allowed_rate(lq_sta, next_col); |
| 1539 | for (n = 0; n < IWL_RATE_COUNT; n++) | 1592 | if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) |
| 1540 | if (expected_tpt_tbl[n] > max_expected_tpt) | 1593 | continue; |
| 1541 | max_expected_tpt = expected_tpt_tbl[n]; | ||
| 1542 | 1594 | ||
| 1595 | max_expected_tpt = expected_tpt_tbl[max_rate]; | ||
| 1543 | if (tpt >= max_expected_tpt) { | 1596 | if (tpt >= max_expected_tpt) { |
| 1544 | IWL_DEBUG_RATE(mvm, | 1597 | IWL_DEBUG_RATE(mvm, |
| 1545 | "Skip column %d: can't beat current TPT. Max expected %d current %d\n", | 1598 | "Skip column %d: can't beat current TPT. Max expected %d current %d\n", |
| @@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | |||
| 1547 | continue; | 1600 | continue; |
| 1548 | } | 1601 | } |
| 1549 | 1602 | ||
| 1603 | IWL_DEBUG_RATE(mvm, | ||
| 1604 | "Found potential column %d. Max expected %d current %d\n", | ||
| 1605 | next_col_id, max_expected_tpt, tpt); | ||
| 1550 | break; | 1606 | break; |
| 1551 | } | 1607 | } |
| 1552 | 1608 | ||
| 1553 | if (i == MAX_NEXT_COLUMNS) | 1609 | if (i == MAX_NEXT_COLUMNS) |
| 1554 | return RS_COLUMN_INVALID; | 1610 | return RS_COLUMN_INVALID; |
| 1555 | 1611 | ||
| 1556 | IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); | ||
| 1557 | |||
| 1558 | return next_col_id; | 1612 | return next_col_id; |
| 1559 | } | 1613 | } |
| 1560 | 1614 | ||
| @@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, | |||
| 1640 | { | 1694 | { |
| 1641 | enum rs_action action = RS_ACTION_STAY; | 1695 | enum rs_action action = RS_ACTION_STAY; |
| 1642 | 1696 | ||
| 1643 | /* Too many failures, decrease rate */ | ||
| 1644 | if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { | 1697 | if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { |
| 1645 | IWL_DEBUG_RATE(mvm, | 1698 | IWL_DEBUG_RATE(mvm, |
| 1646 | "decrease rate because of low SR\n"); | 1699 | "Decrease rate because of low SR\n"); |
| 1647 | action = RS_ACTION_DOWNSCALE; | 1700 | return RS_ACTION_DOWNSCALE; |
| 1648 | /* No throughput measured yet for adjacent rates; try increase. */ | ||
| 1649 | } else if ((low_tpt == IWL_INVALID_VALUE) && | ||
| 1650 | (high_tpt == IWL_INVALID_VALUE)) { | ||
| 1651 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { | ||
| 1652 | IWL_DEBUG_RATE(mvm, | ||
| 1653 | "Good SR and no high rate measurement. " | ||
| 1654 | "Increase rate\n"); | ||
| 1655 | action = RS_ACTION_UPSCALE; | ||
| 1656 | } else if (low != IWL_RATE_INVALID) { | ||
| 1657 | IWL_DEBUG_RATE(mvm, | ||
| 1658 | "Remain in current rate\n"); | ||
| 1659 | action = RS_ACTION_STAY; | ||
| 1660 | } | ||
| 1661 | } | 1701 | } |
| 1662 | 1702 | ||
| 1663 | /* Both adjacent throughputs are measured, but neither one has better | 1703 | if ((low_tpt == IWL_INVALID_VALUE) && |
| 1664 | * throughput; we're using the best rate, don't change it! | 1704 | (high_tpt == IWL_INVALID_VALUE) && |
| 1665 | */ | 1705 | (high != IWL_RATE_INVALID)) { |
| 1666 | else if ((low_tpt != IWL_INVALID_VALUE) && | ||
| 1667 | (high_tpt != IWL_INVALID_VALUE) && | ||
| 1668 | (low_tpt < current_tpt) && | ||
| 1669 | (high_tpt < current_tpt)) { | ||
| 1670 | IWL_DEBUG_RATE(mvm, | 1706 | IWL_DEBUG_RATE(mvm, |
| 1671 | "Both high and low are worse. " | 1707 | "No data about high/low rates. Increase rate\n"); |
| 1672 | "Maintain rate\n"); | 1708 | return RS_ACTION_UPSCALE; |
| 1673 | action = RS_ACTION_STAY; | ||
| 1674 | } | 1709 | } |
| 1675 | 1710 | ||
| 1676 | /* At least one adjacent rate's throughput is measured, | 1711 | if ((high_tpt == IWL_INVALID_VALUE) && |
| 1677 | * and may have better performance. | 1712 | (high != IWL_RATE_INVALID) && |
| 1678 | */ | 1713 | (low_tpt != IWL_INVALID_VALUE) && |
| 1679 | else { | 1714 | (low_tpt < current_tpt)) { |
| 1680 | /* Higher adjacent rate's throughput is measured */ | 1715 | IWL_DEBUG_RATE(mvm, |
| 1681 | if (high_tpt != IWL_INVALID_VALUE) { | 1716 | "No data about high rate and low rate is worse. Increase rate\n"); |
| 1682 | /* Higher rate has better throughput */ | 1717 | return RS_ACTION_UPSCALE; |
| 1683 | if (high_tpt > current_tpt && | 1718 | } |
| 1684 | sr >= IWL_RATE_INCREASE_TH) { | ||
| 1685 | IWL_DEBUG_RATE(mvm, | ||
| 1686 | "Higher rate is better and good " | ||
| 1687 | "SR. Increate rate\n"); | ||
| 1688 | action = RS_ACTION_UPSCALE; | ||
| 1689 | } else { | ||
| 1690 | IWL_DEBUG_RATE(mvm, | ||
| 1691 | "Higher rate isn't better OR " | ||
| 1692 | "no good SR. Maintain rate\n"); | ||
| 1693 | action = RS_ACTION_STAY; | ||
| 1694 | } | ||
| 1695 | 1719 | ||
| 1696 | /* Lower adjacent rate's throughput is measured */ | 1720 | if ((high_tpt != IWL_INVALID_VALUE) && |
| 1697 | } else if (low_tpt != IWL_INVALID_VALUE) { | 1721 | (high_tpt > current_tpt)) { |
| 1698 | /* Lower rate has better throughput */ | 1722 | IWL_DEBUG_RATE(mvm, |
| 1699 | if (low_tpt > current_tpt) { | 1723 | "Higher rate is better. Increate rate\n"); |
| 1700 | IWL_DEBUG_RATE(mvm, | 1724 | return RS_ACTION_UPSCALE; |
| 1701 | "Lower rate is better. " | ||
| 1702 | "Decrease rate\n"); | ||
| 1703 | action = RS_ACTION_DOWNSCALE; | ||
| 1704 | } else if (sr >= IWL_RATE_INCREASE_TH) { | ||
| 1705 | IWL_DEBUG_RATE(mvm, | ||
| 1706 | "Lower rate isn't better and " | ||
| 1707 | "good SR. Increase rate\n"); | ||
| 1708 | action = RS_ACTION_UPSCALE; | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | } | 1725 | } |
| 1712 | 1726 | ||
| 1713 | /* Sanity check; asked for decrease, but success rate or throughput | 1727 | if ((low_tpt != IWL_INVALID_VALUE) && |
| 1714 | * has been good at old rate. Don't change it. | 1728 | (high_tpt != IWL_INVALID_VALUE) && |
| 1715 | */ | 1729 | (low_tpt < current_tpt) && |
| 1716 | if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && | 1730 | (high_tpt < current_tpt)) { |
| 1717 | ((sr > IWL_RATE_HIGH_TH) || | 1731 | IWL_DEBUG_RATE(mvm, |
| 1718 | (current_tpt > (100 * tbl->expected_tpt[low])))) { | 1732 | "Both high and low are worse. Maintain rate\n"); |
| 1733 | return RS_ACTION_STAY; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | if ((low_tpt != IWL_INVALID_VALUE) && | ||
| 1737 | (low_tpt > current_tpt)) { | ||
| 1738 | IWL_DEBUG_RATE(mvm, | ||
| 1739 | "Lower rate is better\n"); | ||
| 1740 | action = RS_ACTION_DOWNSCALE; | ||
| 1741 | goto out; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | if ((low_tpt == IWL_INVALID_VALUE) && | ||
| 1745 | (low != IWL_RATE_INVALID)) { | ||
| 1719 | IWL_DEBUG_RATE(mvm, | 1746 | IWL_DEBUG_RATE(mvm, |
| 1720 | "Sanity check failed. Maintain rate\n"); | 1747 | "No data about lower rate\n"); |
| 1721 | action = RS_ACTION_STAY; | 1748 | action = RS_ACTION_DOWNSCALE; |
| 1749 | goto out; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | IWL_DEBUG_RATE(mvm, "Maintain rate\n"); | ||
| 1753 | |||
| 1754 | out: | ||
| 1755 | if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { | ||
| 1756 | if (sr >= RS_SR_NO_DECREASE) { | ||
| 1757 | IWL_DEBUG_RATE(mvm, | ||
| 1758 | "SR is above NO DECREASE. Avoid downscale\n"); | ||
| 1759 | action = RS_ACTION_STAY; | ||
| 1760 | } else if (current_tpt > (100 * tbl->expected_tpt[low])) { | ||
| 1761 | IWL_DEBUG_RATE(mvm, | ||
| 1762 | "Current TPT is higher than max expected in low rate. Avoid downscale\n"); | ||
| 1763 | action = RS_ACTION_STAY; | ||
| 1764 | } else { | ||
| 1765 | IWL_DEBUG_RATE(mvm, "Decrease rate\n"); | ||
| 1766 | } | ||
| 1722 | } | 1767 | } |
| 1723 | 1768 | ||
| 1724 | return action; | 1769 | return action; |
| @@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1792 | "Aggregation changed: prev %d current %d. Update expected TPT table\n", | 1837 | "Aggregation changed: prev %d current %d. Update expected TPT table\n", |
| 1793 | prev_agg, lq_sta->is_agg); | 1838 | prev_agg, lq_sta->is_agg); |
| 1794 | rs_set_expected_tpt_table(lq_sta, tbl); | 1839 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 1840 | rs_rate_scale_clear_tbl_windows(mvm, tbl); | ||
| 1795 | } | 1841 | } |
| 1796 | 1842 | ||
| 1797 | /* current tx rate */ | 1843 | /* current tx rate */ |
| @@ -2021,7 +2067,7 @@ lq_update: | |||
| 2021 | if (lq_sta->search_better_tbl) { | 2067 | if (lq_sta->search_better_tbl) { |
| 2022 | /* Access the "search" table, clear its history. */ | 2068 | /* Access the "search" table, clear its history. */ |
| 2023 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 2069 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
| 2024 | rs_rate_scale_clear_tbl_windows(tbl); | 2070 | rs_rate_scale_clear_tbl_windows(mvm, tbl); |
| 2025 | 2071 | ||
| 2026 | /* Use new "search" start rate */ | 2072 | /* Use new "search" start rate */ |
| 2027 | index = tbl->rate.index; | 2073 | index = tbl->rate.index; |
| @@ -2042,8 +2088,18 @@ lq_update: | |||
| 2042 | * stay with best antenna legacy modulation for a while | 2088 | * stay with best antenna legacy modulation for a while |
| 2043 | * before next round of mode comparisons. */ | 2089 | * before next round of mode comparisons. */ |
| 2044 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); | 2090 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 2045 | if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { | 2091 | if (is_legacy(&tbl1->rate)) { |
| 2046 | IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); | 2092 | IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); |
| 2093 | |||
| 2094 | if (tid != IWL_MAX_TID_COUNT) { | ||
| 2095 | tid_data = &sta_priv->tid_data[tid]; | ||
| 2096 | if (tid_data->state != IWL_AGG_OFF) { | ||
| 2097 | IWL_DEBUG_RATE(mvm, | ||
| 2098 | "Stop aggregation on tid %d\n", | ||
| 2099 | tid); | ||
| 2100 | ieee80211_stop_tx_ba_session(sta, tid); | ||
| 2101 | } | ||
| 2102 | } | ||
| 2047 | rs_set_stay_in_table(mvm, 1, lq_sta); | 2103 | rs_set_stay_in_table(mvm, 1, lq_sta); |
| 2048 | } else { | 2104 | } else { |
| 2049 | /* If we're in an HT mode, and all 3 mode switch actions | 2105 | /* If we're in an HT mode, and all 3 mode switch actions |
| @@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2342 | lq_sta->lq.sta_id = sta_priv->sta_id; | 2398 | lq_sta->lq.sta_id = sta_priv->sta_id; |
| 2343 | 2399 | ||
| 2344 | for (j = 0; j < LQ_SIZE; j++) | 2400 | for (j = 0; j < LQ_SIZE; j++) |
| 2345 | rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); | 2401 | rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); |
| 2346 | 2402 | ||
| 2347 | lq_sta->flush_timer = 0; | 2403 | lq_sta->flush_timer = 0; |
| 2404 | lq_sta->last_tx = jiffies; | ||
| 2348 | 2405 | ||
| 2349 | IWL_DEBUG_RATE(mvm, | 2406 | IWL_DEBUG_RATE(mvm, |
| 2350 | "LQ: *** rate scale station global init for station %d ***\n", | 2407 | "LQ: *** rate scale station global init for station %d ***\n", |
| @@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2388 | lq_sta->is_vht = true; | 2445 | lq_sta->is_vht = true; |
| 2389 | } | 2446 | } |
| 2390 | 2447 | ||
| 2391 | IWL_DEBUG_RATE(mvm, | 2448 | lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, |
| 2392 | "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", | 2449 | BITS_PER_LONG); |
| 2450 | lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, | ||
| 2451 | BITS_PER_LONG); | ||
| 2452 | lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate, | ||
| 2453 | BITS_PER_LONG); | ||
| 2454 | |||
| 2455 | IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n", | ||
| 2456 | lq_sta->active_legacy_rate, | ||
| 2393 | lq_sta->active_siso_rate, | 2457 | lq_sta->active_siso_rate, |
| 2394 | lq_sta->active_mimo2_rate, | 2458 | lq_sta->active_mimo2_rate, |
| 2395 | lq_sta->is_vht); | 2459 | lq_sta->is_vht); |
| 2460 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", | ||
| 2461 | lq_sta->max_legacy_rate_idx, | ||
| 2462 | lq_sta->max_siso_rate_idx, | ||
| 2463 | lq_sta->max_mimo2_rate_idx); | ||
| 2396 | 2464 | ||
| 2397 | /* These values will be overridden later */ | 2465 | /* These values will be overridden later */ |
| 2398 | lq_sta->lq.single_stream_ant_msk = | 2466 | lq_sta->lq.single_stream_ant_msk = |
| @@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2547 | if (is_siso(&rate)) { | 2615 | if (is_siso(&rate)) { |
| 2548 | num_rates = RS_SECONDARY_SISO_NUM_RATES; | 2616 | num_rates = RS_SECONDARY_SISO_NUM_RATES; |
| 2549 | num_retries = RS_SECONDARY_SISO_RETRIES; | 2617 | num_retries = RS_SECONDARY_SISO_RETRIES; |
| 2618 | lq_cmd->mimo_delim = index; | ||
| 2550 | } else if (is_legacy(&rate)) { | 2619 | } else if (is_legacy(&rate)) { |
| 2551 | num_rates = RS_SECONDARY_LEGACY_NUM_RATES; | 2620 | num_rates = RS_SECONDARY_LEGACY_NUM_RATES; |
| 2552 | num_retries = RS_LEGACY_RETRIES_PER_RATE; | 2621 | num_retries = RS_LEGACY_RETRIES_PER_RATE; |
| @@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
| 2749 | return -ENOMEM; | 2818 | return -ENOMEM; |
| 2750 | 2819 | ||
| 2751 | desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); | 2820 | desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); |
| 2752 | desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", | 2821 | desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n", |
| 2753 | lq_sta->total_failed, lq_sta->total_success, | 2822 | lq_sta->total_failed, lq_sta->total_success, |
| 2754 | lq_sta->active_legacy_rate); | 2823 | lq_sta->active_legacy_rate); |
| 2755 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 2824 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 3332b396011e..0acfac96a56c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
| @@ -156,6 +156,7 @@ enum { | |||
| 156 | #define IWL_RATE_HIGH_TH 10880 /* 85% */ | 156 | #define IWL_RATE_HIGH_TH 10880 /* 85% */ |
| 157 | #define IWL_RATE_INCREASE_TH 6400 /* 50% */ | 157 | #define IWL_RATE_INCREASE_TH 6400 /* 50% */ |
| 158 | #define RS_SR_FORCE_DECREASE 1920 /* 15% */ | 158 | #define RS_SR_FORCE_DECREASE 1920 /* 15% */ |
| 159 | #define RS_SR_NO_DECREASE 10880 /* 85% */ | ||
| 159 | 160 | ||
| 160 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ | 161 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ |
| 161 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) | 162 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) |
| @@ -310,13 +311,20 @@ struct iwl_lq_sta { | |||
| 310 | u32 visited_columns; /* Bitmask marking which Tx columns were | 311 | u32 visited_columns; /* Bitmask marking which Tx columns were |
| 311 | * explored during a search cycle | 312 | * explored during a search cycle |
| 312 | */ | 313 | */ |
| 314 | u64 last_tx; | ||
| 313 | bool is_vht; | 315 | bool is_vht; |
| 314 | enum ieee80211_band band; | 316 | enum ieee80211_band band; |
| 315 | 317 | ||
| 316 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 318 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
| 317 | u16 active_legacy_rate; | 319 | unsigned long active_legacy_rate; |
| 318 | u16 active_siso_rate; | 320 | unsigned long active_siso_rate; |
| 319 | u16 active_mimo2_rate; | 321 | unsigned long active_mimo2_rate; |
| 322 | |||
| 323 | /* Highest rate per Tx mode */ | ||
| 324 | u8 max_legacy_rate_idx; | ||
| 325 | u8 max_siso_rate_idx; | ||
| 326 | u8 max_mimo2_rate_idx; | ||
| 327 | |||
| 320 | s8 max_rate_idx; /* Max rate set by user */ | 328 | s8 max_rate_idx; /* Max rate set by user */ |
| 321 | u8 missed_rate_counter; | 329 | u8 missed_rate_counter; |
| 322 | 330 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 8401627c0030..88809b2d1654 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
| @@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, | |||
| 274 | return -EINVAL; | 274 | return -EINVAL; |
| 275 | if (changed_vif->type != NL80211_IFTYPE_STATION) { | 275 | if (changed_vif->type != NL80211_IFTYPE_STATION) { |
| 276 | new_state = SF_UNINIT; | 276 | new_state = SF_UNINIT; |
| 277 | } else if (changed_vif->bss_conf.assoc) { | 277 | } else if (changed_vif->bss_conf.assoc && |
| 278 | changed_vif->bss_conf.dtim_period) { | ||
| 278 | mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); | 279 | mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); |
| 279 | sta_id = mvmvif->ap_sta_id; | 280 | sta_id = mvmvif->ap_sta_id; |
| 280 | new_state = SF_FULL_ON; | 281 | new_state = SF_FULL_ON; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index edb015c99049..3d1d57f9f5bc 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
| 373 | {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, | 373 | {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, |
| 374 | {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, | 374 | {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, |
| 375 | {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, | 375 | {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, |
| 376 | {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)}, | ||
| 376 | {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, | 377 | {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, |
| 377 | {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, | 378 | {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, |
| 378 | {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, | 379 | {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, |
| 379 | {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, | 380 | {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, |
| 380 | {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, | 381 | {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, |
| 381 | {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, | 382 | {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, |
| 383 | {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)}, | ||
| 382 | {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, | 384 | {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, |
| 383 | {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, | 385 | {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, |
| 384 | {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, | 386 | {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 77db0886c6e2..9c771b3e9918 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -292,6 +292,12 @@ process_start: | |||
| 292 | while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) | 292 | while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) |
| 293 | mwifiex_handle_rx_packet(adapter, skb); | 293 | mwifiex_handle_rx_packet(adapter, skb); |
| 294 | 294 | ||
| 295 | /* Check for event */ | ||
| 296 | if (adapter->event_received) { | ||
| 297 | adapter->event_received = false; | ||
| 298 | mwifiex_process_event(adapter); | ||
| 299 | } | ||
| 300 | |||
| 295 | /* Check for Cmd Resp */ | 301 | /* Check for Cmd Resp */ |
| 296 | if (adapter->cmd_resp_received) { | 302 | if (adapter->cmd_resp_received) { |
| 297 | adapter->cmd_resp_received = false; | 303 | adapter->cmd_resp_received = false; |
| @@ -304,12 +310,6 @@ process_start: | |||
| 304 | } | 310 | } |
| 305 | } | 311 | } |
| 306 | 312 | ||
| 307 | /* Check for event */ | ||
| 308 | if (adapter->event_received) { | ||
| 309 | adapter->event_received = false; | ||
| 310 | mwifiex_process_event(adapter); | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Check if we need to confirm Sleep Request | 313 | /* Check if we need to confirm Sleep Request |
| 314 | received previously */ | 314 | received previously */ |
| 315 | if (adapter->ps_state == PS_STATE_PRE_SLEEP) { | 315 | if (adapter->ps_state == PS_STATE_PRE_SLEEP) { |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 894270611f2c..536c14aa71f3 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
| @@ -60,9 +60,10 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, | |||
| 60 | int status; | 60 | int status; |
| 61 | 61 | ||
| 62 | /* Wait for completion */ | 62 | /* Wait for completion */ |
| 63 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, | 63 | status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, |
| 64 | *(cmd_queued->condition)); | 64 | *(cmd_queued->condition), |
| 65 | if (status) { | 65 | (12 * HZ)); |
| 66 | if (status <= 0) { | ||
| 66 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); | 67 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
| 67 | mwifiex_cancel_all_pending_cmd(adapter); | 68 | mwifiex_cancel_all_pending_cmd(adapter); |
| 68 | return status; | 69 | return status; |
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index 1a8d32138593..cf61d6e3eaa7 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c | |||
| @@ -88,7 +88,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common) | |||
| 88 | bool recontend_queue = false; | 88 | bool recontend_queue = false; |
| 89 | u32 q_len = 0; | 89 | u32 q_len = 0; |
| 90 | u8 q_num = INVALID_QUEUE; | 90 | u8 q_num = INVALID_QUEUE; |
| 91 | u8 ii, min = 0; | 91 | u8 ii = 0, min = 0; |
| 92 | 92 | ||
| 93 | if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { | 93 | if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { |
| 94 | if (!common->mgmt_q_block) | 94 | if (!common->mgmt_q_block) |
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 73694295648f..1b28cda6ca88 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c | |||
| @@ -841,16 +841,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) | |||
| 841 | rsi_dbg(MGMT_TX_ZONE, | 841 | rsi_dbg(MGMT_TX_ZONE, |
| 842 | "%s: Sending scan req frame\n", __func__); | 842 | "%s: Sending scan req frame\n", __func__); |
| 843 | 843 | ||
| 844 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
| 845 | if (!skb) { | ||
| 846 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
| 847 | __func__); | ||
| 848 | return -ENOMEM; | ||
| 849 | } | ||
| 850 | |||
| 851 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
| 852 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
| 853 | |||
| 854 | if (common->band == IEEE80211_BAND_5GHZ) { | 844 | if (common->band == IEEE80211_BAND_5GHZ) { |
| 855 | if ((channel >= 36) && (channel <= 64)) | 845 | if ((channel >= 36) && (channel <= 64)) |
| 856 | channel = ((channel - 32) / 4); | 846 | channel = ((channel - 32) / 4); |
| @@ -868,6 +858,16 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) | |||
| 868 | } | 858 | } |
| 869 | } | 859 | } |
| 870 | 860 | ||
| 861 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
| 862 | if (!skb) { | ||
| 863 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
| 864 | __func__); | ||
| 865 | return -ENOMEM; | ||
| 866 | } | ||
| 867 | |||
| 868 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
| 869 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
| 870 | |||
| 871 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | 871 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); |
| 872 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); | 872 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); |
| 873 | mgmt_frame->desc_word[4] = cpu_to_le16(channel); | 873 | mgmt_frame->desc_word[4] = cpu_to_le16(channel); |
| @@ -966,6 +966,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common) | |||
| 966 | if (!selected_rates) { | 966 | if (!selected_rates) { |
| 967 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", | 967 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", |
| 968 | __func__); | 968 | __func__); |
| 969 | dev_kfree_skb(skb); | ||
| 969 | return -ENOMEM; | 970 | return -ENOMEM; |
| 970 | } | 971 | } |
| 971 | 972 | ||
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index 398f3d2c0a6c..a76e98eb8372 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h | |||
| @@ -68,6 +68,26 @@ struct wl18xx_event_mailbox { | |||
| 68 | 68 | ||
| 69 | /* bitmap of inactive stations (by HLID) */ | 69 | /* bitmap of inactive stations (by HLID) */ |
| 70 | __le32 inactive_sta_bitmap; | 70 | __le32 inactive_sta_bitmap; |
| 71 | |||
| 72 | /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */ | ||
| 73 | u8 rx_ba_role_id; | ||
| 74 | u8 rx_ba_link_id; | ||
| 75 | u8 rx_ba_win_size; | ||
| 76 | u8 padding; | ||
| 77 | |||
| 78 | /* smart config */ | ||
| 79 | u8 sc_ssid_len; | ||
| 80 | u8 sc_pwd_len; | ||
| 81 | u8 sc_token_len; | ||
| 82 | u8 padding1; | ||
| 83 | u8 sc_ssid[32]; | ||
| 84 | u8 sc_pwd[32]; | ||
| 85 | u8 sc_token[32]; | ||
| 86 | |||
| 87 | /* smart config sync channel */ | ||
| 88 | u8 sc_sync_channel; | ||
| 89 | u8 sc_sync_band; | ||
| 90 | u8 padding2[2]; | ||
| 71 | } __packed; | 91 | } __packed; |
| 72 | 92 | ||
| 73 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | 93 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 1f9a36031b06..16d10281798d 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
| @@ -158,6 +158,11 @@ EXPORT_SYMBOL_GPL(wlcore_event_channel_switch); | |||
| 158 | 158 | ||
| 159 | void wlcore_event_dummy_packet(struct wl1271 *wl) | 159 | void wlcore_event_dummy_packet(struct wl1271 *wl) |
| 160 | { | 160 | { |
| 161 | if (wl->plt) { | ||
| 162 | wl1271_info("Got DUMMY_PACKET event in PLT mode. FW bug, ignoring."); | ||
| 163 | return; | ||
| 164 | } | ||
| 165 | |||
| 161 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); | 166 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
| 162 | wl1271_tx_dummy_packet(wl); | 167 | wl1271_tx_dummy_packet(wl); |
| 163 | } | 168 | } |
diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h index 7c9fe3c2be73..66c30a763b10 100644 --- a/include/linux/mdio-gpio.h +++ b/include/linux/mdio-gpio.h | |||
| @@ -17,6 +17,11 @@ struct mdio_gpio_platform_data { | |||
| 17 | /* GPIO numbers for bus pins */ | 17 | /* GPIO numbers for bus pins */ |
| 18 | unsigned int mdc; | 18 | unsigned int mdc; |
| 19 | unsigned int mdio; | 19 | unsigned int mdio; |
| 20 | unsigned int mdo; | ||
| 21 | |||
| 22 | bool mdc_active_low; | ||
| 23 | bool mdio_active_low; | ||
| 24 | bool mdo_active_low; | ||
| 20 | 25 | ||
| 21 | unsigned int phy_mask; | 26 | unsigned int phy_mask; |
| 22 | int irqs[PHY_MAX_ADDR]; | 27 | int irqs[PHY_MAX_ADDR]; |
diff --git a/include/linux/phy.h b/include/linux/phy.h index 24126c4b27b5..4d0221fd0688 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
| @@ -75,6 +75,7 @@ typedef enum { | |||
| 75 | PHY_INTERFACE_MODE_SMII, | 75 | PHY_INTERFACE_MODE_SMII, |
| 76 | PHY_INTERFACE_MODE_XGMII, | 76 | PHY_INTERFACE_MODE_XGMII, |
| 77 | PHY_INTERFACE_MODE_MOCA, | 77 | PHY_INTERFACE_MODE_MOCA, |
| 78 | PHY_INTERFACE_MODE_QSGMII, | ||
| 78 | PHY_INTERFACE_MODE_MAX, | 79 | PHY_INTERFACE_MODE_MAX, |
| 79 | } phy_interface_t; | 80 | } phy_interface_t; |
| 80 | 81 | ||
| @@ -116,6 +117,8 @@ static inline const char *phy_modes(phy_interface_t interface) | |||
| 116 | return "xgmii"; | 117 | return "xgmii"; |
| 117 | case PHY_INTERFACE_MODE_MOCA: | 118 | case PHY_INTERFACE_MODE_MOCA: |
| 118 | return "moca"; | 119 | return "moca"; |
| 120 | case PHY_INTERFACE_MODE_QSGMII: | ||
| 121 | return "qsgmii"; | ||
| 119 | default: | 122 | default: |
| 120 | return "unknown"; | 123 | return "unknown"; |
| 121 | } | 124 | } |
diff --git a/include/net/flow.h b/include/net/flow.h index 64fd24836650..8109a159d1b3 100644 --- a/include/net/flow.h +++ b/include/net/flow.h | |||
| @@ -11,6 +11,14 @@ | |||
| 11 | #include <linux/in6.h> | 11 | #include <linux/in6.h> |
| 12 | #include <linux/atomic.h> | 12 | #include <linux/atomic.h> |
| 13 | 13 | ||
| 14 | /* | ||
| 15 | * ifindex generation is per-net namespace, and loopback is | ||
| 16 | * always the 1st device in ns (see net_dev_init), thus any | ||
| 17 | * loopback device should get ifindex 1 | ||
| 18 | */ | ||
| 19 | |||
| 20 | #define LOOPBACK_IFINDEX 1 | ||
| 21 | |||
| 14 | struct flowi_common { | 22 | struct flowi_common { |
| 15 | int flowic_oif; | 23 | int flowic_oif; |
| 16 | int flowic_iif; | 24 | int flowic_iif; |
| @@ -80,7 +88,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif, | |||
| 80 | __be16 dport, __be16 sport) | 88 | __be16 dport, __be16 sport) |
| 81 | { | 89 | { |
| 82 | fl4->flowi4_oif = oif; | 90 | fl4->flowi4_oif = oif; |
| 83 | fl4->flowi4_iif = 0; | 91 | fl4->flowi4_iif = LOOPBACK_IFINDEX; |
| 84 | fl4->flowi4_mark = mark; | 92 | fl4->flowi4_mark = mark; |
| 85 | fl4->flowi4_tos = tos; | 93 | fl4->flowi4_tos = tos; |
| 86 | fl4->flowi4_scope = scope; | 94 | fl4->flowi4_scope = scope; |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 79387f73f875..5f9eb260990f 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
| 10 | #include <linux/sysctl.h> | 10 | #include <linux/sysctl.h> |
| 11 | 11 | ||
| 12 | #include <net/flow.h> | ||
| 12 | #include <net/netns/core.h> | 13 | #include <net/netns/core.h> |
| 13 | #include <net/netns/mib.h> | 14 | #include <net/netns/mib.h> |
| 14 | #include <net/netns/unix.h> | 15 | #include <net/netns/unix.h> |
| @@ -131,14 +132,6 @@ struct net { | |||
| 131 | atomic_t fnhe_genid; | 132 | atomic_t fnhe_genid; |
| 132 | }; | 133 | }; |
| 133 | 134 | ||
| 134 | /* | ||
| 135 | * ifindex generation is per-net namespace, and loopback is | ||
| 136 | * always the 1st device in ns (see net_dev_init), thus any | ||
| 137 | * loopback device should get ifindex 1 | ||
| 138 | */ | ||
| 139 | |||
| 140 | #define LOOPBACK_IFINDEX 1 | ||
| 141 | |||
| 142 | #include <linux/seq_file_net.h> | 135 | #include <linux/seq_file_net.h> |
| 143 | 136 | ||
| 144 | /* Init's network namespace */ | 137 | /* Init's network namespace */ |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d992ca3145fe..0dfcc92600e8 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -1241,6 +1241,7 @@ struct sctp_endpoint { | |||
| 1241 | /* SCTP-AUTH: endpoint shared keys */ | 1241 | /* SCTP-AUTH: endpoint shared keys */ |
| 1242 | struct list_head endpoint_shared_keys; | 1242 | struct list_head endpoint_shared_keys; |
| 1243 | __u16 active_key_id; | 1243 | __u16 active_key_id; |
| 1244 | __u8 auth_enable; | ||
| 1244 | }; | 1245 | }; |
| 1245 | 1246 | ||
| 1246 | /* Recover the outter endpoint structure. */ | 1247 | /* Recover the outter endpoint structure. */ |
| @@ -1269,7 +1270,8 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *, | |||
| 1269 | int sctp_has_association(struct net *net, const union sctp_addr *laddr, | 1270 | int sctp_has_association(struct net *net, const union sctp_addr *laddr, |
| 1270 | const union sctp_addr *paddr); | 1271 | const union sctp_addr *paddr); |
| 1271 | 1272 | ||
| 1272 | int sctp_verify_init(struct net *net, const struct sctp_association *asoc, | 1273 | int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, |
| 1274 | const struct sctp_association *asoc, | ||
| 1273 | sctp_cid_t, sctp_init_chunk_t *peer_init, | 1275 | sctp_cid_t, sctp_init_chunk_t *peer_init, |
| 1274 | struct sctp_chunk *chunk, struct sctp_chunk **err_chunk); | 1276 | struct sctp_chunk *chunk, struct sctp_chunk **err_chunk); |
| 1275 | int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk, | 1277 | int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk, |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 590c37925084..b35c21503a36 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
| @@ -255,6 +255,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) | |||
| 255 | goto free_prog; | 255 | goto free_prog; |
| 256 | 256 | ||
| 257 | /* Allocate a new seccomp_filter */ | 257 | /* Allocate a new seccomp_filter */ |
| 258 | ret = -ENOMEM; | ||
| 258 | filter = kzalloc(sizeof(struct seccomp_filter) + | 259 | filter = kzalloc(sizeof(struct seccomp_filter) + |
| 259 | sizeof(struct sock_filter_int) * new_len, | 260 | sizeof(struct sock_filter_int) * new_len, |
| 260 | GFP_KERNEL|__GFP_NOWARN); | 261 | GFP_KERNEL|__GFP_NOWARN); |
| @@ -264,6 +265,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) | |||
| 264 | ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len); | 265 | ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len); |
| 265 | if (ret) | 266 | if (ret) |
| 266 | goto free_filter; | 267 | goto free_filter; |
| 268 | kfree(fp); | ||
| 267 | 269 | ||
| 268 | atomic_set(&filter->usage, 1); | 270 | atomic_set(&filter->usage, 1); |
| 269 | filter->len = new_len; | 271 | filter->len = new_len; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6f142f03716d..733ec283ed1b 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -493,10 +493,48 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) | |||
| 493 | } | 493 | } |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | static int vlan_calculate_locking_subclass(struct net_device *real_dev) | ||
| 497 | { | ||
| 498 | int subclass = 0; | ||
| 499 | |||
| 500 | while (is_vlan_dev(real_dev)) { | ||
| 501 | subclass++; | ||
| 502 | real_dev = vlan_dev_priv(real_dev)->real_dev; | ||
| 503 | } | ||
| 504 | |||
| 505 | return subclass; | ||
| 506 | } | ||
| 507 | |||
| 508 | static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from) | ||
| 509 | { | ||
| 510 | int err = 0, subclass; | ||
| 511 | |||
| 512 | subclass = vlan_calculate_locking_subclass(to); | ||
| 513 | |||
| 514 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
| 515 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | ||
| 516 | if (!err) | ||
| 517 | __dev_set_rx_mode(to); | ||
| 518 | spin_unlock(&to->addr_list_lock); | ||
| 519 | } | ||
| 520 | |||
| 521 | static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from) | ||
| 522 | { | ||
| 523 | int err = 0, subclass; | ||
| 524 | |||
| 525 | subclass = vlan_calculate_locking_subclass(to); | ||
| 526 | |||
| 527 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
| 528 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); | ||
| 529 | if (!err) | ||
| 530 | __dev_set_rx_mode(to); | ||
| 531 | spin_unlock(&to->addr_list_lock); | ||
| 532 | } | ||
| 533 | |||
| 496 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) | 534 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) |
| 497 | { | 535 | { |
| 498 | dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 536 | vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
| 499 | dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 537 | vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
| 500 | } | 538 | } |
| 501 | 539 | ||
| 502 | /* | 540 | /* |
| @@ -608,9 +646,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
| 608 | 646 | ||
| 609 | SET_NETDEV_DEVTYPE(dev, &vlan_type); | 647 | SET_NETDEV_DEVTYPE(dev, &vlan_type); |
| 610 | 648 | ||
| 611 | if (is_vlan_dev(real_dev)) | 649 | subclass = vlan_calculate_locking_subclass(dev); |
| 612 | subclass = 1; | ||
| 613 | |||
| 614 | vlan_dev_set_lockdep_class(dev, subclass); | 650 | vlan_dev_set_lockdep_class(dev, subclass); |
| 615 | 651 | ||
| 616 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); | 652 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
diff --git a/net/core/dev.c b/net/core/dev.c index 5b3042e69f85..d2c8a06b3a98 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -5238,6 +5238,7 @@ void __dev_set_rx_mode(struct net_device *dev) | |||
| 5238 | if (ops->ndo_set_rx_mode) | 5238 | if (ops->ndo_set_rx_mode) |
| 5239 | ops->ndo_set_rx_mode(dev); | 5239 | ops->ndo_set_rx_mode(dev); |
| 5240 | } | 5240 | } |
| 5241 | EXPORT_SYMBOL(__dev_set_rx_mode); | ||
| 5241 | 5242 | ||
| 5242 | void dev_set_rx_mode(struct net_device *dev) | 5243 | void dev_set_rx_mode(struct net_device *dev) |
| 5243 | { | 5244 | { |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 1a629f870274..255aa9946fe7 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -250,7 +250,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, | |||
| 250 | bool dev_match; | 250 | bool dev_match; |
| 251 | 251 | ||
| 252 | fl4.flowi4_oif = 0; | 252 | fl4.flowi4_oif = 0; |
| 253 | fl4.flowi4_iif = oif; | 253 | fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX; |
| 254 | fl4.daddr = src; | 254 | fl4.daddr = src; |
| 255 | fl4.saddr = dst; | 255 | fl4.saddr = dst; |
| 256 | fl4.flowi4_tos = tos; | 256 | fl4.flowi4_tos = tos; |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index b53f0bf84dca..8a043f03c88e 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
| @@ -631,6 +631,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, | |||
| 631 | .daddr = nh->nh_gw, | 631 | .daddr = nh->nh_gw, |
| 632 | .flowi4_scope = cfg->fc_scope + 1, | 632 | .flowi4_scope = cfg->fc_scope + 1, |
| 633 | .flowi4_oif = nh->nh_oif, | 633 | .flowi4_oif = nh->nh_oif, |
| 634 | .flowi4_iif = LOOPBACK_IFINDEX, | ||
| 634 | }; | 635 | }; |
| 635 | 636 | ||
| 636 | /* It is not necessary, but requires a bit of thinking */ | 637 | /* It is not necessary, but requires a bit of thinking */ |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 484d0ce27ef7..fa5b7519765f 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -722,19 +722,18 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, | |||
| 722 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | 722 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) |
| 723 | { | 723 | { |
| 724 | int err = 0; | 724 | int err = 0; |
| 725 | struct ip_tunnel *t; | 725 | struct ip_tunnel *t = netdev_priv(dev); |
| 726 | struct net *net = dev_net(dev); | 726 | struct net *net = t->net; |
| 727 | struct ip_tunnel *tunnel = netdev_priv(dev); | 727 | struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); |
| 728 | struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); | ||
| 729 | 728 | ||
| 730 | BUG_ON(!itn->fb_tunnel_dev); | 729 | BUG_ON(!itn->fb_tunnel_dev); |
| 731 | switch (cmd) { | 730 | switch (cmd) { |
| 732 | case SIOCGETTUNNEL: | 731 | case SIOCGETTUNNEL: |
| 733 | t = NULL; | 732 | if (dev == itn->fb_tunnel_dev) { |
| 734 | if (dev == itn->fb_tunnel_dev) | ||
| 735 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); | 733 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); |
| 736 | if (t == NULL) | 734 | if (t == NULL) |
| 737 | t = netdev_priv(dev); | 735 | t = netdev_priv(dev); |
| 736 | } | ||
| 738 | memcpy(p, &t->parms, sizeof(*p)); | 737 | memcpy(p, &t->parms, sizeof(*p)); |
| 739 | break; | 738 | break; |
| 740 | 739 | ||
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 28863570dd60..d84dc8d4c916 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
| @@ -455,7 +455,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 455 | struct mr_table *mrt; | 455 | struct mr_table *mrt; |
| 456 | struct flowi4 fl4 = { | 456 | struct flowi4 fl4 = { |
| 457 | .flowi4_oif = dev->ifindex, | 457 | .flowi4_oif = dev->ifindex, |
| 458 | .flowi4_iif = skb->skb_iif, | 458 | .flowi4_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, |
| 459 | .flowi4_mark = skb->mark, | 459 | .flowi4_mark = skb->mark, |
| 460 | }; | 460 | }; |
| 461 | int err; | 461 | int err; |
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index c49dcd0284a0..4bfaedf9b34e 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c | |||
| @@ -89,11 +89,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 89 | if (ipv4_is_multicast(iph->daddr)) { | 89 | if (ipv4_is_multicast(iph->daddr)) { |
| 90 | if (ipv4_is_zeronet(iph->saddr)) | 90 | if (ipv4_is_zeronet(iph->saddr)) |
| 91 | return ipv4_is_local_multicast(iph->daddr) ^ invert; | 91 | return ipv4_is_local_multicast(iph->daddr) ^ invert; |
| 92 | flow.flowi4_iif = 0; | ||
| 93 | } else { | ||
| 94 | flow.flowi4_iif = LOOPBACK_IFINDEX; | ||
| 95 | } | 92 | } |
| 96 | 93 | flow.flowi4_iif = LOOPBACK_IFINDEX; | |
| 97 | flow.daddr = iph->saddr; | 94 | flow.daddr = iph->saddr; |
| 98 | flow.saddr = rpfilter_get_saddr(iph->daddr); | 95 | flow.saddr = rpfilter_get_saddr(iph->daddr); |
| 99 | flow.flowi4_oif = 0; | 96 | flow.flowi4_oif = 0; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 1485aafcad59..db1e0da871f4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -1700,8 +1700,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
| 1700 | 1700 | ||
| 1701 | if (res.type == RTN_LOCAL) { | 1701 | if (res.type == RTN_LOCAL) { |
| 1702 | err = fib_validate_source(skb, saddr, daddr, tos, | 1702 | err = fib_validate_source(skb, saddr, daddr, tos, |
| 1703 | LOOPBACK_IFINDEX, | 1703 | 0, dev, in_dev, &itag); |
| 1704 | dev, in_dev, &itag); | ||
| 1705 | if (err < 0) | 1704 | if (err < 0) |
| 1706 | goto martian_source_keep_err; | 1705 | goto martian_source_keep_err; |
| 1707 | goto local_input; | 1706 | goto local_input; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e1df691d78be..b05b609f69d1 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -1340,8 +1340,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1340 | int err = 0; | 1340 | int err = 0; |
| 1341 | struct ip6_tnl_parm p; | 1341 | struct ip6_tnl_parm p; |
| 1342 | struct __ip6_tnl_parm p1; | 1342 | struct __ip6_tnl_parm p1; |
| 1343 | struct ip6_tnl *t = NULL; | 1343 | struct ip6_tnl *t = netdev_priv(dev); |
| 1344 | struct net *net = dev_net(dev); | 1344 | struct net *net = t->net; |
| 1345 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1345 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
| 1346 | 1346 | ||
| 1347 | switch (cmd) { | 1347 | switch (cmd) { |
| @@ -1353,11 +1353,11 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1353 | } | 1353 | } |
| 1354 | ip6_tnl_parm_from_user(&p1, &p); | 1354 | ip6_tnl_parm_from_user(&p1, &p); |
| 1355 | t = ip6_tnl_locate(net, &p1, 0); | 1355 | t = ip6_tnl_locate(net, &p1, 0); |
| 1356 | if (t == NULL) | ||
| 1357 | t = netdev_priv(dev); | ||
| 1356 | } else { | 1358 | } else { |
| 1357 | memset(&p, 0, sizeof(p)); | 1359 | memset(&p, 0, sizeof(p)); |
| 1358 | } | 1360 | } |
| 1359 | if (t == NULL) | ||
| 1360 | t = netdev_priv(dev); | ||
| 1361 | ip6_tnl_parm_to_user(&p, &t->parms); | 1361 | ip6_tnl_parm_to_user(&p, &t->parms); |
| 1362 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { | 1362 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { |
| 1363 | err = -EFAULT; | 1363 | err = -EFAULT; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8737400af0a0..8659067da28e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -700,7 +700,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
| 700 | struct mr6_table *mrt; | 700 | struct mr6_table *mrt; |
| 701 | struct flowi6 fl6 = { | 701 | struct flowi6 fl6 = { |
| 702 | .flowi6_oif = dev->ifindex, | 702 | .flowi6_oif = dev->ifindex, |
| 703 | .flowi6_iif = skb->skb_iif, | 703 | .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, |
| 704 | .flowi6_mark = skb->mark, | 704 | .flowi6_mark = skb->mark, |
| 705 | }; | 705 | }; |
| 706 | int err; | 706 | int err; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8da8268d65f8..e5a453ca302e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -1127,8 +1127,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1127 | int err = 0; | 1127 | int err = 0; |
| 1128 | struct ip_tunnel_parm p; | 1128 | struct ip_tunnel_parm p; |
| 1129 | struct ip_tunnel_prl prl; | 1129 | struct ip_tunnel_prl prl; |
| 1130 | struct ip_tunnel *t; | 1130 | struct ip_tunnel *t = netdev_priv(dev); |
| 1131 | struct net *net = dev_net(dev); | 1131 | struct net *net = t->net; |
| 1132 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1132 | struct sit_net *sitn = net_generic(net, sit_net_id); |
| 1133 | #ifdef CONFIG_IPV6_SIT_6RD | 1133 | #ifdef CONFIG_IPV6_SIT_6RD |
| 1134 | struct ip_tunnel_6rd ip6rd; | 1134 | struct ip_tunnel_6rd ip6rd; |
| @@ -1139,16 +1139,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1139 | #ifdef CONFIG_IPV6_SIT_6RD | 1139 | #ifdef CONFIG_IPV6_SIT_6RD |
| 1140 | case SIOCGET6RD: | 1140 | case SIOCGET6RD: |
| 1141 | #endif | 1141 | #endif |
| 1142 | t = NULL; | ||
| 1143 | if (dev == sitn->fb_tunnel_dev) { | 1142 | if (dev == sitn->fb_tunnel_dev) { |
| 1144 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 1143 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
| 1145 | err = -EFAULT; | 1144 | err = -EFAULT; |
| 1146 | break; | 1145 | break; |
| 1147 | } | 1146 | } |
| 1148 | t = ipip6_tunnel_locate(net, &p, 0); | 1147 | t = ipip6_tunnel_locate(net, &p, 0); |
| 1148 | if (t == NULL) | ||
| 1149 | t = netdev_priv(dev); | ||
| 1149 | } | 1150 | } |
| 1150 | if (t == NULL) | ||
| 1151 | t = netdev_priv(dev); | ||
| 1152 | 1151 | ||
| 1153 | err = -EFAULT; | 1152 | err = -EFAULT; |
| 1154 | if (cmd == SIOCGETTUNNEL) { | 1153 | if (cmd == SIOCGETTUNNEL) { |
| @@ -1244,9 +1243,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1244 | err = -EINVAL; | 1243 | err = -EINVAL; |
| 1245 | if (dev == sitn->fb_tunnel_dev) | 1244 | if (dev == sitn->fb_tunnel_dev) |
| 1246 | goto done; | 1245 | goto done; |
| 1247 | err = -ENOENT; | ||
| 1248 | if (!(t = netdev_priv(dev))) | ||
| 1249 | goto done; | ||
| 1250 | err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); | 1246 | err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); |
| 1251 | break; | 1247 | break; |
| 1252 | 1248 | ||
| @@ -1262,9 +1258,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1262 | err = -EFAULT; | 1258 | err = -EFAULT; |
| 1263 | if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) | 1259 | if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) |
| 1264 | goto done; | 1260 | goto done; |
| 1265 | err = -ENOENT; | ||
| 1266 | if (!(t = netdev_priv(dev))) | ||
| 1267 | goto done; | ||
| 1268 | 1261 | ||
| 1269 | switch (cmd) { | 1262 | switch (cmd) { |
| 1270 | case SIOCDELPRL: | 1263 | case SIOCDELPRL: |
| @@ -1292,8 +1285,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1292 | sizeof(ip6rd))) | 1285 | sizeof(ip6rd))) |
| 1293 | goto done; | 1286 | goto done; |
| 1294 | 1287 | ||
| 1295 | t = netdev_priv(dev); | ||
| 1296 | |||
| 1297 | if (cmd != SIOCDEL6RD) { | 1288 | if (cmd != SIOCDEL6RD) { |
| 1298 | err = ipip6_tunnel_update_6rd(t, &ip6rd); | 1289 | err = ipip6_tunnel_update_6rd(t, &ip6rd); |
| 1299 | if (err < 0) | 1290 | if (err < 0) |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index bd1fd8ea5105..75b5dd2c9267 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -249,7 +249,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
| 249 | 249 | ||
| 250 | if (!local->use_chanctx) { | 250 | if (!local->use_chanctx) { |
| 251 | local->_oper_chandef = *chandef; | 251 | local->_oper_chandef = *chandef; |
| 252 | ieee80211_hw_config(local, 0); | 252 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
| 253 | } else { | 253 | } else { |
| 254 | err = drv_add_chanctx(local, ctx); | 254 | err = drv_add_chanctx(local, ctx); |
| 255 | if (err) { | 255 | if (err) { |
| @@ -286,7 +286,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
| 286 | check_single_channel = true; | 286 | check_single_channel = true; |
| 287 | local->hw.conf.radar_enabled = false; | 287 | local->hw.conf.radar_enabled = false; |
| 288 | 288 | ||
| 289 | ieee80211_hw_config(local, 0); | 289 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
| 290 | } else { | 290 | } else { |
| 291 | drv_remove_chanctx(local, ctx); | 291 | drv_remove_chanctx(local, ctx); |
| 292 | } | 292 | } |
| @@ -492,6 +492,13 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | |||
| 492 | rx_chains_static = max(rx_chains_static, needed_static); | 492 | rx_chains_static = max(rx_chains_static, needed_static); |
| 493 | rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic); | 493 | rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic); |
| 494 | } | 494 | } |
| 495 | |||
| 496 | /* Disable SMPS for the monitor interface */ | ||
| 497 | sdata = rcu_dereference(local->monitor_sdata); | ||
| 498 | if (sdata && | ||
| 499 | rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf) | ||
| 500 | rx_chains_dynamic = rx_chains_static = local->rx_chains; | ||
| 501 | |||
| 495 | rcu_read_unlock(); | 502 | rcu_read_unlock(); |
| 496 | 503 | ||
| 497 | if (!local->use_chanctx) { | 504 | if (!local->use_chanctx) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b055f6a55c68..4c1bf61bc778 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -148,6 +148,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
| 148 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 148 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
| 149 | if (!rcu_access_pointer(sdata->vif.chanctx_conf)) | 149 | if (!rcu_access_pointer(sdata->vif.chanctx_conf)) |
| 150 | continue; | 150 | continue; |
| 151 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
| 152 | continue; | ||
| 151 | power = min(power, sdata->vif.bss_conf.txpower); | 153 | power = min(power, sdata->vif.bss_conf.txpower); |
| 152 | } | 154 | } |
| 153 | rcu_read_unlock(); | 155 | rcu_read_unlock(); |
| @@ -199,7 +201,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
| 199 | { | 201 | { |
| 200 | struct ieee80211_local *local = sdata->local; | 202 | struct ieee80211_local *local = sdata->local; |
| 201 | 203 | ||
| 202 | if (!changed) | 204 | if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 203 | return; | 205 | return; |
| 204 | 206 | ||
| 205 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); | 207 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 0c2a29484c07..6fb38558a5e6 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
| @@ -355,6 +355,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
| 355 | struct ieee80211_roc_work *dep; | 355 | struct ieee80211_roc_work *dep; |
| 356 | 356 | ||
| 357 | /* start this ROC */ | 357 | /* start this ROC */ |
| 358 | ieee80211_offchannel_stop_vifs(local); | ||
| 358 | 359 | ||
| 359 | /* switch channel etc */ | 360 | /* switch channel etc */ |
| 360 | ieee80211_recalc_idle(local); | 361 | ieee80211_recalc_idle(local); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index e6e574a307c8..00ba90b02ab2 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
| @@ -618,6 +618,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 618 | sta, true, acked); | 618 | sta, true, acked); |
| 619 | 619 | ||
| 620 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | 620 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && |
| 621 | (ieee80211_is_data(hdr->frame_control)) && | ||
| 621 | (rates_idx != -1)) | 622 | (rates_idx != -1)) |
| 622 | sta->last_tx_rate = info->status.rates[rates_idx]; | 623 | sta->last_tx_rate = info->status.rates[rates_idx]; |
| 623 | 624 | ||
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 683c7d1b1306..0e8529113dc5 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
| @@ -386,14 +386,13 @@ nomem: | |||
| 386 | */ | 386 | */ |
| 387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) | 387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) |
| 388 | { | 388 | { |
| 389 | struct net *net = sock_net(asoc->base.sk); | ||
| 390 | struct sctp_auth_bytes *secret; | 389 | struct sctp_auth_bytes *secret; |
| 391 | struct sctp_shared_key *ep_key; | 390 | struct sctp_shared_key *ep_key; |
| 392 | 391 | ||
| 393 | /* If we don't support AUTH, or peer is not capable | 392 | /* If we don't support AUTH, or peer is not capable |
| 394 | * we don't need to do anything. | 393 | * we don't need to do anything. |
| 395 | */ | 394 | */ |
| 396 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) | 395 | if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
| 397 | return 0; | 396 | return 0; |
| 398 | 397 | ||
| 399 | /* If the key_id is non-zero and we couldn't find an | 398 | /* If the key_id is non-zero and we couldn't find an |
| @@ -440,16 +439,16 @@ struct sctp_shared_key *sctp_auth_get_shkey( | |||
| 440 | */ | 439 | */ |
| 441 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) | 440 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) |
| 442 | { | 441 | { |
| 443 | struct net *net = sock_net(ep->base.sk); | ||
| 444 | struct crypto_hash *tfm = NULL; | 442 | struct crypto_hash *tfm = NULL; |
| 445 | __u16 id; | 443 | __u16 id; |
| 446 | 444 | ||
| 447 | /* if the transforms are already allocted, we are done */ | 445 | /* If AUTH extension is disabled, we are done */ |
| 448 | if (!net->sctp.auth_enable) { | 446 | if (!ep->auth_enable) { |
| 449 | ep->auth_hmacs = NULL; | 447 | ep->auth_hmacs = NULL; |
| 450 | return 0; | 448 | return 0; |
| 451 | } | 449 | } |
| 452 | 450 | ||
| 451 | /* If the transforms are already allocated, we are done */ | ||
| 453 | if (ep->auth_hmacs) | 452 | if (ep->auth_hmacs) |
| 454 | return 0; | 453 | return 0; |
| 455 | 454 | ||
| @@ -665,12 +664,10 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) | |||
| 665 | /* Check if peer requested that this chunk is authenticated */ | 664 | /* Check if peer requested that this chunk is authenticated */ |
| 666 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 665 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
| 667 | { | 666 | { |
| 668 | struct net *net; | ||
| 669 | if (!asoc) | 667 | if (!asoc) |
| 670 | return 0; | 668 | return 0; |
| 671 | 669 | ||
| 672 | net = sock_net(asoc->base.sk); | 670 | if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
| 673 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) | ||
| 674 | return 0; | 671 | return 0; |
| 675 | 672 | ||
| 676 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); | 673 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); |
| @@ -679,12 +676,10 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | |||
| 679 | /* Check if we requested that peer authenticate this chunk. */ | 676 | /* Check if we requested that peer authenticate this chunk. */ |
| 680 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 677 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
| 681 | { | 678 | { |
| 682 | struct net *net; | ||
| 683 | if (!asoc) | 679 | if (!asoc) |
| 684 | return 0; | 680 | return 0; |
| 685 | 681 | ||
| 686 | net = sock_net(asoc->base.sk); | 682 | if (!asoc->ep->auth_enable) |
| 687 | if (!net->sctp.auth_enable) | ||
| 688 | return 0; | 683 | return 0; |
| 689 | 684 | ||
| 690 | return __sctp_auth_cid(chunk, | 685 | return __sctp_auth_cid(chunk, |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 8e5fdea05216..3d9f429858dc 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -68,7 +68,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 68 | if (!ep->digest) | 68 | if (!ep->digest) |
| 69 | return NULL; | 69 | return NULL; |
| 70 | 70 | ||
| 71 | if (net->sctp.auth_enable) { | 71 | ep->auth_enable = net->sctp.auth_enable; |
| 72 | if (ep->auth_enable) { | ||
| 72 | /* Allocate space for HMACS and CHUNKS authentication | 73 | /* Allocate space for HMACS and CHUNKS authentication |
| 73 | * variables. There are arrays that we encode directly | 74 | * variables. There are arrays that we encode directly |
| 74 | * into parameters to make the rest of the operations easier. | 75 | * into parameters to make the rest of the operations easier. |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 3a1767ef3201..fee5552ddf92 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -219,6 +219,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 219 | gfp_t gfp, int vparam_len) | 219 | gfp_t gfp, int vparam_len) |
| 220 | { | 220 | { |
| 221 | struct net *net = sock_net(asoc->base.sk); | 221 | struct net *net = sock_net(asoc->base.sk); |
| 222 | struct sctp_endpoint *ep = asoc->ep; | ||
| 222 | sctp_inithdr_t init; | 223 | sctp_inithdr_t init; |
| 223 | union sctp_params addrs; | 224 | union sctp_params addrs; |
| 224 | size_t chunksize; | 225 | size_t chunksize; |
| @@ -278,7 +279,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 278 | chunksize += vparam_len; | 279 | chunksize += vparam_len; |
| 279 | 280 | ||
| 280 | /* Account for AUTH related parameters */ | 281 | /* Account for AUTH related parameters */ |
| 281 | if (net->sctp.auth_enable) { | 282 | if (ep->auth_enable) { |
| 282 | /* Add random parameter length*/ | 283 | /* Add random parameter length*/ |
| 283 | chunksize += sizeof(asoc->c.auth_random); | 284 | chunksize += sizeof(asoc->c.auth_random); |
| 284 | 285 | ||
| @@ -363,7 +364,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 363 | } | 364 | } |
| 364 | 365 | ||
| 365 | /* Add SCTP-AUTH chunks to the parameter list */ | 366 | /* Add SCTP-AUTH chunks to the parameter list */ |
| 366 | if (net->sctp.auth_enable) { | 367 | if (ep->auth_enable) { |
| 367 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), | 368 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), |
| 368 | asoc->c.auth_random); | 369 | asoc->c.auth_random); |
| 369 | if (auth_hmacs) | 370 | if (auth_hmacs) |
| @@ -2010,7 +2011,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
| 2010 | /* if the peer reports AUTH, assume that he | 2011 | /* if the peer reports AUTH, assume that he |
| 2011 | * supports AUTH. | 2012 | * supports AUTH. |
| 2012 | */ | 2013 | */ |
| 2013 | if (net->sctp.auth_enable) | 2014 | if (asoc->ep->auth_enable) |
| 2014 | asoc->peer.auth_capable = 1; | 2015 | asoc->peer.auth_capable = 1; |
| 2015 | break; | 2016 | break; |
| 2016 | case SCTP_CID_ASCONF: | 2017 | case SCTP_CID_ASCONF: |
| @@ -2102,6 +2103,7 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, | |||
| 2102 | * SCTP_IERROR_NO_ERROR - continue with the chunk | 2103 | * SCTP_IERROR_NO_ERROR - continue with the chunk |
| 2103 | */ | 2104 | */ |
| 2104 | static sctp_ierror_t sctp_verify_param(struct net *net, | 2105 | static sctp_ierror_t sctp_verify_param(struct net *net, |
| 2106 | const struct sctp_endpoint *ep, | ||
| 2105 | const struct sctp_association *asoc, | 2107 | const struct sctp_association *asoc, |
| 2106 | union sctp_params param, | 2108 | union sctp_params param, |
| 2107 | sctp_cid_t cid, | 2109 | sctp_cid_t cid, |
| @@ -2152,7 +2154,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
| 2152 | goto fallthrough; | 2154 | goto fallthrough; |
| 2153 | 2155 | ||
| 2154 | case SCTP_PARAM_RANDOM: | 2156 | case SCTP_PARAM_RANDOM: |
| 2155 | if (!net->sctp.auth_enable) | 2157 | if (!ep->auth_enable) |
| 2156 | goto fallthrough; | 2158 | goto fallthrough; |
| 2157 | 2159 | ||
| 2158 | /* SCTP-AUTH: Secion 6.1 | 2160 | /* SCTP-AUTH: Secion 6.1 |
| @@ -2169,7 +2171,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
| 2169 | break; | 2171 | break; |
| 2170 | 2172 | ||
| 2171 | case SCTP_PARAM_CHUNKS: | 2173 | case SCTP_PARAM_CHUNKS: |
| 2172 | if (!net->sctp.auth_enable) | 2174 | if (!ep->auth_enable) |
| 2173 | goto fallthrough; | 2175 | goto fallthrough; |
| 2174 | 2176 | ||
| 2175 | /* SCTP-AUTH: Section 3.2 | 2177 | /* SCTP-AUTH: Section 3.2 |
| @@ -2185,7 +2187,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
| 2185 | break; | 2187 | break; |
| 2186 | 2188 | ||
| 2187 | case SCTP_PARAM_HMAC_ALGO: | 2189 | case SCTP_PARAM_HMAC_ALGO: |
| 2188 | if (!net->sctp.auth_enable) | 2190 | if (!ep->auth_enable) |
| 2189 | goto fallthrough; | 2191 | goto fallthrough; |
| 2190 | 2192 | ||
| 2191 | hmacs = (struct sctp_hmac_algo_param *)param.p; | 2193 | hmacs = (struct sctp_hmac_algo_param *)param.p; |
| @@ -2220,10 +2222,9 @@ fallthrough: | |||
| 2220 | } | 2222 | } |
| 2221 | 2223 | ||
| 2222 | /* Verify the INIT packet before we process it. */ | 2224 | /* Verify the INIT packet before we process it. */ |
| 2223 | int sctp_verify_init(struct net *net, const struct sctp_association *asoc, | 2225 | int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, |
| 2224 | sctp_cid_t cid, | 2226 | const struct sctp_association *asoc, sctp_cid_t cid, |
| 2225 | sctp_init_chunk_t *peer_init, | 2227 | sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, |
| 2226 | struct sctp_chunk *chunk, | ||
| 2227 | struct sctp_chunk **errp) | 2228 | struct sctp_chunk **errp) |
| 2228 | { | 2229 | { |
| 2229 | union sctp_params param; | 2230 | union sctp_params param; |
| @@ -2264,8 +2265,8 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc, | |||
| 2264 | 2265 | ||
| 2265 | /* Verify all the variable length parameters */ | 2266 | /* Verify all the variable length parameters */ |
| 2266 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2267 | sctp_walk_params(param, peer_init, init_hdr.params) { |
| 2267 | 2268 | result = sctp_verify_param(net, ep, asoc, param, cid, | |
| 2268 | result = sctp_verify_param(net, asoc, param, cid, chunk, errp); | 2269 | chunk, errp); |
| 2269 | switch (result) { | 2270 | switch (result) { |
| 2270 | case SCTP_IERROR_ABORT: | 2271 | case SCTP_IERROR_ABORT: |
| 2271 | case SCTP_IERROR_NOMEM: | 2272 | case SCTP_IERROR_NOMEM: |
| @@ -2497,6 +2498,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 2497 | struct sctp_af *af; | 2498 | struct sctp_af *af; |
| 2498 | union sctp_addr_param *addr_param; | 2499 | union sctp_addr_param *addr_param; |
| 2499 | struct sctp_transport *t; | 2500 | struct sctp_transport *t; |
| 2501 | struct sctp_endpoint *ep = asoc->ep; | ||
| 2500 | 2502 | ||
| 2501 | /* We maintain all INIT parameters in network byte order all the | 2503 | /* We maintain all INIT parameters in network byte order all the |
| 2502 | * time. This allows us to not worry about whether the parameters | 2504 | * time. This allows us to not worry about whether the parameters |
| @@ -2636,7 +2638,7 @@ do_addr_param: | |||
| 2636 | goto fall_through; | 2638 | goto fall_through; |
| 2637 | 2639 | ||
| 2638 | case SCTP_PARAM_RANDOM: | 2640 | case SCTP_PARAM_RANDOM: |
| 2639 | if (!net->sctp.auth_enable) | 2641 | if (!ep->auth_enable) |
| 2640 | goto fall_through; | 2642 | goto fall_through; |
| 2641 | 2643 | ||
| 2642 | /* Save peer's random parameter */ | 2644 | /* Save peer's random parameter */ |
| @@ -2649,7 +2651,7 @@ do_addr_param: | |||
| 2649 | break; | 2651 | break; |
| 2650 | 2652 | ||
| 2651 | case SCTP_PARAM_HMAC_ALGO: | 2653 | case SCTP_PARAM_HMAC_ALGO: |
| 2652 | if (!net->sctp.auth_enable) | 2654 | if (!ep->auth_enable) |
| 2653 | goto fall_through; | 2655 | goto fall_through; |
| 2654 | 2656 | ||
| 2655 | /* Save peer's HMAC list */ | 2657 | /* Save peer's HMAC list */ |
| @@ -2665,7 +2667,7 @@ do_addr_param: | |||
| 2665 | break; | 2667 | break; |
| 2666 | 2668 | ||
| 2667 | case SCTP_PARAM_CHUNKS: | 2669 | case SCTP_PARAM_CHUNKS: |
| 2668 | if (!net->sctp.auth_enable) | 2670 | if (!ep->auth_enable) |
| 2669 | goto fall_through; | 2671 | goto fall_through; |
| 2670 | 2672 | ||
| 2671 | asoc->peer.peer_chunks = kmemdup(param.p, | 2673 | asoc->peer.peer_chunks = kmemdup(param.p, |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ae9fbeba40b0..5170a1ff95a1 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -357,7 +357,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net, | |||
| 357 | 357 | ||
| 358 | /* Verify the INIT chunk before processing it. */ | 358 | /* Verify the INIT chunk before processing it. */ |
| 359 | err_chunk = NULL; | 359 | err_chunk = NULL; |
| 360 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 360 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
| 361 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 361 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
| 362 | &err_chunk)) { | 362 | &err_chunk)) { |
| 363 | /* This chunk contains fatal error. It is to be discarded. | 363 | /* This chunk contains fatal error. It is to be discarded. |
| @@ -524,7 +524,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, | |||
| 524 | 524 | ||
| 525 | /* Verify the INIT chunk before processing it. */ | 525 | /* Verify the INIT chunk before processing it. */ |
| 526 | err_chunk = NULL; | 526 | err_chunk = NULL; |
| 527 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 527 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
| 528 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 528 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
| 529 | &err_chunk)) { | 529 | &err_chunk)) { |
| 530 | 530 | ||
| @@ -1430,7 +1430,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
| 1430 | 1430 | ||
| 1431 | /* Verify the INIT chunk before processing it. */ | 1431 | /* Verify the INIT chunk before processing it. */ |
| 1432 | err_chunk = NULL; | 1432 | err_chunk = NULL; |
| 1433 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 1433 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
| 1434 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 1434 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
| 1435 | &err_chunk)) { | 1435 | &err_chunk)) { |
| 1436 | /* This chunk contains fatal error. It is to be discarded. | 1436 | /* This chunk contains fatal error. It is to be discarded. |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ff20e2dbbbc7..fee06b99a4da 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -3321,10 +3321,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, | |||
| 3321 | char __user *optval, | 3321 | char __user *optval, |
| 3322 | unsigned int optlen) | 3322 | unsigned int optlen) |
| 3323 | { | 3323 | { |
| 3324 | struct net *net = sock_net(sk); | 3324 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 3325 | struct sctp_authchunk val; | 3325 | struct sctp_authchunk val; |
| 3326 | 3326 | ||
| 3327 | if (!net->sctp.auth_enable) | 3327 | if (!ep->auth_enable) |
| 3328 | return -EACCES; | 3328 | return -EACCES; |
| 3329 | 3329 | ||
| 3330 | if (optlen != sizeof(struct sctp_authchunk)) | 3330 | if (optlen != sizeof(struct sctp_authchunk)) |
| @@ -3341,7 +3341,7 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, | |||
| 3341 | } | 3341 | } |
| 3342 | 3342 | ||
| 3343 | /* add this chunk id to the endpoint */ | 3343 | /* add this chunk id to the endpoint */ |
| 3344 | return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk); | 3344 | return sctp_auth_ep_add_chunkid(ep, val.sauth_chunk); |
| 3345 | } | 3345 | } |
| 3346 | 3346 | ||
| 3347 | /* | 3347 | /* |
| @@ -3354,12 +3354,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
| 3354 | char __user *optval, | 3354 | char __user *optval, |
| 3355 | unsigned int optlen) | 3355 | unsigned int optlen) |
| 3356 | { | 3356 | { |
| 3357 | struct net *net = sock_net(sk); | 3357 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 3358 | struct sctp_hmacalgo *hmacs; | 3358 | struct sctp_hmacalgo *hmacs; |
| 3359 | u32 idents; | 3359 | u32 idents; |
| 3360 | int err; | 3360 | int err; |
| 3361 | 3361 | ||
| 3362 | if (!net->sctp.auth_enable) | 3362 | if (!ep->auth_enable) |
| 3363 | return -EACCES; | 3363 | return -EACCES; |
| 3364 | 3364 | ||
| 3365 | if (optlen < sizeof(struct sctp_hmacalgo)) | 3365 | if (optlen < sizeof(struct sctp_hmacalgo)) |
| @@ -3376,7 +3376,7 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
| 3376 | goto out; | 3376 | goto out; |
| 3377 | } | 3377 | } |
| 3378 | 3378 | ||
| 3379 | err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs); | 3379 | err = sctp_auth_ep_set_hmacs(ep, hmacs); |
| 3380 | out: | 3380 | out: |
| 3381 | kfree(hmacs); | 3381 | kfree(hmacs); |
| 3382 | return err; | 3382 | return err; |
| @@ -3392,12 +3392,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
| 3392 | char __user *optval, | 3392 | char __user *optval, |
| 3393 | unsigned int optlen) | 3393 | unsigned int optlen) |
| 3394 | { | 3394 | { |
| 3395 | struct net *net = sock_net(sk); | 3395 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 3396 | struct sctp_authkey *authkey; | 3396 | struct sctp_authkey *authkey; |
| 3397 | struct sctp_association *asoc; | 3397 | struct sctp_association *asoc; |
| 3398 | int ret; | 3398 | int ret; |
| 3399 | 3399 | ||
| 3400 | if (!net->sctp.auth_enable) | 3400 | if (!ep->auth_enable) |
| 3401 | return -EACCES; | 3401 | return -EACCES; |
| 3402 | 3402 | ||
| 3403 | if (optlen <= sizeof(struct sctp_authkey)) | 3403 | if (optlen <= sizeof(struct sctp_authkey)) |
| @@ -3418,7 +3418,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
| 3418 | goto out; | 3418 | goto out; |
| 3419 | } | 3419 | } |
| 3420 | 3420 | ||
| 3421 | ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); | 3421 | ret = sctp_auth_set_key(ep, asoc, authkey); |
| 3422 | out: | 3422 | out: |
| 3423 | kzfree(authkey); | 3423 | kzfree(authkey); |
| 3424 | return ret; | 3424 | return ret; |
| @@ -3434,11 +3434,11 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
| 3434 | char __user *optval, | 3434 | char __user *optval, |
| 3435 | unsigned int optlen) | 3435 | unsigned int optlen) |
| 3436 | { | 3436 | { |
| 3437 | struct net *net = sock_net(sk); | 3437 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 3438 | struct sctp_authkeyid val; | 3438 | struct sctp_authkeyid val; |
| 3439 | struct sctp_association *asoc; | 3439 | struct sctp_association *asoc; |
| 3440 | 3440 | ||
| 3441 | if (!net->sctp.auth_enable) | 3441 | if (!ep->auth_enable) |
| 3442 | return -EACCES; | 3442 | return -EACCES; |
| 3443 | 3443 | ||
| 3444 | if (optlen != sizeof(struct sctp_authkeyid)) | 3444 | if (optlen != sizeof(struct sctp_authkeyid)) |
| @@ -3450,8 +3450,7 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
| 3450 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | 3450 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
| 3451 | return -EINVAL; | 3451 | return -EINVAL; |
| 3452 | 3452 | ||
| 3453 | return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc, | 3453 | return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); |
| 3454 | val.scact_keynumber); | ||
| 3455 | } | 3454 | } |
| 3456 | 3455 | ||
| 3457 | /* | 3456 | /* |
| @@ -3463,11 +3462,11 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
| 3463 | char __user *optval, | 3462 | char __user *optval, |
| 3464 | unsigned int optlen) | 3463 | unsigned int optlen) |
| 3465 | { | 3464 | { |
| 3466 | struct net *net = sock_net(sk); | 3465 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 3467 | struct sctp_authkeyid val; | 3466 | struct sctp_authkeyid val; |
| 3468 | struct sctp_association *asoc; | 3467 | struct sctp_association *asoc; |
| 3469 | 3468 | ||
| 3470 | if (!net->sctp.auth_enable) | 3469 | if (!ep->auth_enable) |
| 3471 | return -EACCES; | 3470 | return -EACCES; |
| 3472 | 3471 | ||
| 3473 | if (optlen != sizeof(struct sctp_authkeyid)) | 3472 | if (optlen != sizeof(struct sctp_authkeyid)) |
| @@ -3479,8 +3478,7 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
| 3479 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | 3478 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
| 3480 | return -EINVAL; | 3479 | return -EINVAL; |
| 3481 | 3480 | ||
| 3482 | return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc, | 3481 | return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); |
| 3483 | val.scact_keynumber); | ||
| 3484 | 3482 | ||
| 3485 | } | 3483 | } |
| 3486 | 3484 | ||
| @@ -5387,16 +5385,16 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
| 5387 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | 5385 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, |
| 5388 | char __user *optval, int __user *optlen) | 5386 | char __user *optval, int __user *optlen) |
| 5389 | { | 5387 | { |
| 5390 | struct net *net = sock_net(sk); | 5388 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 5391 | struct sctp_hmacalgo __user *p = (void __user *)optval; | 5389 | struct sctp_hmacalgo __user *p = (void __user *)optval; |
| 5392 | struct sctp_hmac_algo_param *hmacs; | 5390 | struct sctp_hmac_algo_param *hmacs; |
| 5393 | __u16 data_len = 0; | 5391 | __u16 data_len = 0; |
| 5394 | u32 num_idents; | 5392 | u32 num_idents; |
| 5395 | 5393 | ||
| 5396 | if (!net->sctp.auth_enable) | 5394 | if (!ep->auth_enable) |
| 5397 | return -EACCES; | 5395 | return -EACCES; |
| 5398 | 5396 | ||
| 5399 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; | 5397 | hmacs = ep->auth_hmacs_list; |
| 5400 | data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); | 5398 | data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); |
| 5401 | 5399 | ||
| 5402 | if (len < sizeof(struct sctp_hmacalgo) + data_len) | 5400 | if (len < sizeof(struct sctp_hmacalgo) + data_len) |
| @@ -5417,11 +5415,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | |||
| 5417 | static int sctp_getsockopt_active_key(struct sock *sk, int len, | 5415 | static int sctp_getsockopt_active_key(struct sock *sk, int len, |
| 5418 | char __user *optval, int __user *optlen) | 5416 | char __user *optval, int __user *optlen) |
| 5419 | { | 5417 | { |
| 5420 | struct net *net = sock_net(sk); | 5418 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 5421 | struct sctp_authkeyid val; | 5419 | struct sctp_authkeyid val; |
| 5422 | struct sctp_association *asoc; | 5420 | struct sctp_association *asoc; |
| 5423 | 5421 | ||
| 5424 | if (!net->sctp.auth_enable) | 5422 | if (!ep->auth_enable) |
| 5425 | return -EACCES; | 5423 | return -EACCES; |
| 5426 | 5424 | ||
| 5427 | if (len < sizeof(struct sctp_authkeyid)) | 5425 | if (len < sizeof(struct sctp_authkeyid)) |
| @@ -5436,7 +5434,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
| 5436 | if (asoc) | 5434 | if (asoc) |
| 5437 | val.scact_keynumber = asoc->active_key_id; | 5435 | val.scact_keynumber = asoc->active_key_id; |
| 5438 | else | 5436 | else |
| 5439 | val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; | 5437 | val.scact_keynumber = ep->active_key_id; |
| 5440 | 5438 | ||
| 5441 | len = sizeof(struct sctp_authkeyid); | 5439 | len = sizeof(struct sctp_authkeyid); |
| 5442 | if (put_user(len, optlen)) | 5440 | if (put_user(len, optlen)) |
| @@ -5450,7 +5448,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
| 5450 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | 5448 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
| 5451 | char __user *optval, int __user *optlen) | 5449 | char __user *optval, int __user *optlen) |
| 5452 | { | 5450 | { |
| 5453 | struct net *net = sock_net(sk); | 5451 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 5454 | struct sctp_authchunks __user *p = (void __user *)optval; | 5452 | struct sctp_authchunks __user *p = (void __user *)optval; |
| 5455 | struct sctp_authchunks val; | 5453 | struct sctp_authchunks val; |
| 5456 | struct sctp_association *asoc; | 5454 | struct sctp_association *asoc; |
| @@ -5458,7 +5456,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | |||
| 5458 | u32 num_chunks = 0; | 5456 | u32 num_chunks = 0; |
| 5459 | char __user *to; | 5457 | char __user *to; |
| 5460 | 5458 | ||
| 5461 | if (!net->sctp.auth_enable) | 5459 | if (!ep->auth_enable) |
| 5462 | return -EACCES; | 5460 | return -EACCES; |
| 5463 | 5461 | ||
| 5464 | if (len < sizeof(struct sctp_authchunks)) | 5462 | if (len < sizeof(struct sctp_authchunks)) |
| @@ -5495,7 +5493,7 @@ num: | |||
| 5495 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | 5493 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, |
| 5496 | char __user *optval, int __user *optlen) | 5494 | char __user *optval, int __user *optlen) |
| 5497 | { | 5495 | { |
| 5498 | struct net *net = sock_net(sk); | 5496 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 5499 | struct sctp_authchunks __user *p = (void __user *)optval; | 5497 | struct sctp_authchunks __user *p = (void __user *)optval; |
| 5500 | struct sctp_authchunks val; | 5498 | struct sctp_authchunks val; |
| 5501 | struct sctp_association *asoc; | 5499 | struct sctp_association *asoc; |
| @@ -5503,7 +5501,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
| 5503 | u32 num_chunks = 0; | 5501 | u32 num_chunks = 0; |
| 5504 | char __user *to; | 5502 | char __user *to; |
| 5505 | 5503 | ||
| 5506 | if (!net->sctp.auth_enable) | 5504 | if (!ep->auth_enable) |
| 5507 | return -EACCES; | 5505 | return -EACCES; |
| 5508 | 5506 | ||
| 5509 | if (len < sizeof(struct sctp_authchunks)) | 5507 | if (len < sizeof(struct sctp_authchunks)) |
| @@ -5520,7 +5518,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
| 5520 | if (asoc) | 5518 | if (asoc) |
| 5521 | ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; | 5519 | ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; |
| 5522 | else | 5520 | else |
| 5523 | ch = sctp_sk(sk)->ep->auth_chunk_list; | 5521 | ch = ep->auth_chunk_list; |
| 5524 | 5522 | ||
| 5525 | if (!ch) | 5523 | if (!ch) |
| 5526 | goto num; | 5524 | goto num; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 35c8923b5554..c82fdc1eab7c 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
| @@ -64,6 +64,9 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | |||
| 64 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | 64 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, |
| 65 | void __user *buffer, size_t *lenp, | 65 | void __user *buffer, size_t *lenp, |
| 66 | loff_t *ppos); | 66 | loff_t *ppos); |
| 67 | static int proc_sctp_do_auth(struct ctl_table *ctl, int write, | ||
| 68 | void __user *buffer, size_t *lenp, | ||
| 69 | loff_t *ppos); | ||
| 67 | 70 | ||
| 68 | static struct ctl_table sctp_table[] = { | 71 | static struct ctl_table sctp_table[] = { |
| 69 | { | 72 | { |
| @@ -266,7 +269,7 @@ static struct ctl_table sctp_net_table[] = { | |||
| 266 | .data = &init_net.sctp.auth_enable, | 269 | .data = &init_net.sctp.auth_enable, |
| 267 | .maxlen = sizeof(int), | 270 | .maxlen = sizeof(int), |
| 268 | .mode = 0644, | 271 | .mode = 0644, |
| 269 | .proc_handler = proc_dointvec, | 272 | .proc_handler = proc_sctp_do_auth, |
| 270 | }, | 273 | }, |
| 271 | { | 274 | { |
| 272 | .procname = "addr_scope_policy", | 275 | .procname = "addr_scope_policy", |
| @@ -400,6 +403,37 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | |||
| 400 | return ret; | 403 | return ret; |
| 401 | } | 404 | } |
| 402 | 405 | ||
| 406 | static int proc_sctp_do_auth(struct ctl_table *ctl, int write, | ||
| 407 | void __user *buffer, size_t *lenp, | ||
| 408 | loff_t *ppos) | ||
| 409 | { | ||
| 410 | struct net *net = current->nsproxy->net_ns; | ||
| 411 | struct ctl_table tbl; | ||
| 412 | int new_value, ret; | ||
| 413 | |||
| 414 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
| 415 | tbl.maxlen = sizeof(unsigned int); | ||
| 416 | |||
| 417 | if (write) | ||
| 418 | tbl.data = &new_value; | ||
| 419 | else | ||
| 420 | tbl.data = &net->sctp.auth_enable; | ||
| 421 | |||
| 422 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
| 423 | |||
| 424 | if (write) { | ||
| 425 | struct sock *sk = net->sctp.ctl_sock; | ||
| 426 | |||
| 427 | net->sctp.auth_enable = new_value; | ||
| 428 | /* Update the value in the control socket */ | ||
| 429 | lock_sock(sk); | ||
| 430 | sctp_sk(sk)->ep->auth_enable = new_value; | ||
| 431 | release_sock(sk); | ||
| 432 | } | ||
| 433 | |||
| 434 | return ret; | ||
| 435 | } | ||
| 436 | |||
| 403 | int sctp_sysctl_net_register(struct net *net) | 437 | int sctp_sysctl_net_register(struct net *net) |
| 404 | { | 438 | { |
| 405 | struct ctl_table *table = sctp_net_table; | 439 | struct ctl_table *table = sctp_net_table; |
diff --git a/net/socket.c b/net/socket.c index 1b1e7e6a960f..abf56b2a14f9 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -1880,8 +1880,8 @@ out: | |||
| 1880 | * Receive a datagram from a socket. | 1880 | * Receive a datagram from a socket. |
| 1881 | */ | 1881 | */ |
| 1882 | 1882 | ||
| 1883 | asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, | 1883 | SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, |
| 1884 | unsigned int flags) | 1884 | unsigned int, flags) |
| 1885 | { | 1885 | { |
| 1886 | return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); | 1886 | return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); |
| 1887 | } | 1887 | } |
