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 | } |