Unified · Split
| @@ -651,16 +651,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max · 650 unmodified lines | ||
| 651 | 651 | |
| 652 | 652 | default: initial size of receive buffer used by TCP sockets. |
| 653 | 653 | This value overrides net.core.rmem_default used by other protocols. |
| 654 | − Default: 87380 bytes. This value results in window of 65535 with | |
| 655 | − default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit | |
| 656 | − less for default tcp_app_win. See below about these variables. | |
| 654 | + Default: 131072 bytes. | |
| 655 | + This value results in initial window of 65535. | |
| 657 | 656 | |
| 658 | 657 | max: maximal size of receive buffer allowed for automatically |
| 659 | 658 | selected receiver buffers for TCP socket. This value does not override |
| 660 | 659 | net.core.rmem_max. Calling setsockopt() with SO_RCVBUF disables |
| 661 | 660 | automatic tuning of that socket's receive buffer size, in which |
| 662 | 661 | case this value is ignored. |
| 663 | − Default: between 87380B and 6MB, depending on RAM size. | |
| 662 | + Default: between 131072 and 6MB, depending on RAM size. | |
| 664 | 663 | |
| 665 | 664 | tcp_sack - BOOLEAN |
| 666 | 665 | Enable select acknowledgments (SACKS). |
| @@ -272,6 +272,22 @@ to the mailing list, e.g.:: · 271 unmodified lines | ||
| 272 | 272 | Posting as one thread is discouraged because it confuses patchwork |
| 273 | 273 | (as of patchwork 2.2.2). |
| 274 | 274 | |
| 275 | +Can I reproduce the checks from patchwork on my local machine? | |
| 276 | +-------------------------------------------------------------- | |
| 277 | + | |
| 278 | +Checks in patchwork are mostly simple wrappers around existing kernel | |
| 279 | +scripts, the sources are available at: | |
| 280 | + | |
| 281 | +https://github.com/kuba-moo/nipa/tree/master/tests | |
| 282 | + | |
| 283 | +Running all the builds and checks locally is a pain, can I post my patches and have the patchwork bot validate them? | |
| 284 | +-------------------------------------------------------------------------------------------------------------------- | |
| 285 | + | |
| 286 | +No, you must ensure that your patches are ready by testing them locally | |
| 287 | +before posting to the mailing list. The patchwork build bot instance | |
| 288 | +gets overloaded very easily and netdev@vger really doesn't need more | |
| 289 | +traffic if we can help it. | |
| 290 | + | |
| 275 | 291 | Any other tips to help ensure my net/net-next patch gets OK'd? |
| 276 | 292 | -------------------------------------------------------------- |
| 277 | 293 | Attention to detail. Re-read your own work as if you were the |
| @@ -3743,16 +3743,7 @@ static int __init idt77252_init(void) · 3742 unmodified lines | ||
| 3743 | 3743 | struct sk_buff *skb; |
| 3744 | 3744 | |
| 3745 | 3745 | printk("%s: at %p\n", __func__, idt77252_init); |
| 3746 | − | |
| 3747 | − if (sizeof(skb->cb) < sizeof(struct atm_skb_data) + | |
| 3748 | − sizeof(struct idt77252_skb_prv)) { | |
| 3749 | − printk(KERN_ERR "%s: skb->cb is too small (%lu < %lu)\n", | |
| 3750 | − __func__, (unsigned long) sizeof(skb->cb), | |
| 3751 | − (unsigned long) sizeof(struct atm_skb_data) + | |
| 3752 | − sizeof(struct idt77252_skb_prv)); | |
| 3753 | − return -EIO; | |
| 3754 | − } | |
| 3755 | − | |
| 3746 | + BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct idt77252_skb_prv) + sizeof(struct atm_skb_data)); | |
| 3756 | 3747 | return pci_register_driver(&idt77252_driver); |
| 3757 | 3748 | } |
| 3758 | 3749 | |
| @@ -789,7 +789,7 @@ struct idt77252_skb_prv { · 788 unmodified lines | ||
| 789 | 789 | struct scqe tbd; /* Transmit Buffer Descriptor */ |
| 790 | 790 | dma_addr_t paddr; /* DMA handle */ |
| 791 | 791 | u32 pool; /* sb_pool handle */ |
| 792 | −}; | |
| 792 | +} __packed; | |
| 793 | 793 | |
| 794 | 794 | #define IDT77252_PRV_TBD(skb) \ |
| 795 | 795 | (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->tbd) |
| @@ -1279,10 +1279,18 @@ · 1278 unmodified lines | ||
| 1279 | 1279 | #define MDIO_PMA_10GBR_FECCTRL 0x00ab |
| 1280 | 1280 | #endif |
| 1281 | 1281 | |
| 1282 | +#ifndef MDIO_PMA_RX_CTRL1 | |
| 1283 | +#define MDIO_PMA_RX_CTRL1 0x8051 | |
| 1284 | +#endif | |
| 1285 | + | |
| 1282 | 1286 | #ifndef MDIO_PCS_DIG_CTRL |
| 1283 | 1287 | #define MDIO_PCS_DIG_CTRL 0x8000 |
| 1284 | 1288 | #endif |
| 1285 | 1289 | |
| 1290 | +#ifndef MDIO_PCS_DIGITAL_STAT | |
| 1291 | +#define MDIO_PCS_DIGITAL_STAT 0x8010 | |
| 1292 | +#endif | |
| 1293 | + | |
| 1286 | 1294 | #ifndef MDIO_AN_XNP |
| 1287 | 1295 | #define MDIO_AN_XNP 0x0016 |
| 1288 | 1296 | #endif |
| @@ -1358,6 +1366,8 @@ · 69 unmodified lines | ||
| 1358 | 1366 | #define XGBE_KR_TRAINING_ENABLE BIT(1) |
| 1359 | 1367 | |
| 1360 | 1368 | #define XGBE_PCS_CL37_BP BIT(12) |
| 1369 | +#define XGBE_PCS_PSEQ_STATE_MASK 0x1c | |
| 1370 | +#define XGBE_PCS_PSEQ_STATE_POWER_GOOD 0x10 | |
| 1361 | 1371 | |
| 1362 | 1372 | #define XGBE_AN_CL37_INT_CMPLT BIT(0) |
| 1363 | 1373 | #define XGBE_AN_CL37_INT_MASK 0x01 |
| @@ -1375,6 +1385,10 @@ · 11 unmodified lines | ||
| 1375 | 1385 | #define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 |
| 1376 | 1386 | #define XGBE_PMA_CDR_TRACK_EN_ON 0x01 |
| 1377 | 1387 | |
| 1388 | +#define XGBE_PMA_RX_RST_0_MASK BIT(4) | |
| 1389 | +#define XGBE_PMA_RX_RST_0_RESET_ON 0x10 | |
| 1390 | +#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 | |
| 1391 | + | |
| 1378 | 1392 | /* Bit setting and getting macros |
| 1379 | 1393 | * The get macro will extract the current bit field value from within |
| 1380 | 1394 | * the variable |
| @@ -1368,6 +1368,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) · 1367 unmodified lines | ||
| 1368 | 1368 | return; |
| 1369 | 1369 | |
| 1370 | 1370 | netif_tx_stop_all_queues(netdev); |
| 1371 | + netif_carrier_off(pdata->netdev); | |
| 1371 | 1372 | |
| 1372 | 1373 | xgbe_stop_timers(pdata); |
| 1373 | 1374 | flush_workqueue(pdata->dev_workqueue); |
| @@ -1345,7 +1345,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) · 1344 unmodified lines | ||
| 1345 | 1345 | &an_restart); |
| 1346 | 1346 | if (an_restart) { |
| 1347 | 1347 | xgbe_phy_config_aneg(pdata); |
| 1348 | − return; | |
| 1348 | + goto adjust_link; | |
| 1349 | 1349 | } |
| 1350 | 1350 | |
| 1351 | 1351 | if (pdata->phy.link) { |
| @@ -1396,7 +1396,6 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) · 44 unmodified lines | ||
| 1396 | 1396 | pdata->phy_if.phy_impl.stop(pdata); |
| 1397 | 1397 | |
| 1398 | 1398 | pdata->phy.link = 0; |
| 1399 | − netif_carrier_off(pdata->netdev); | |
| 1400 | 1399 | |
| 1401 | 1400 | xgbe_phy_adjust_link(pdata); |
| 1402 | 1401 | } |
| @@ -922,6 +922,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) · 921 unmodified lines | ||
| 922 | 922 | if ((phy_id & 0xfffffff0) != 0x03625d10) |
| 923 | 923 | return false; |
| 924 | 924 | |
| 925 | + /* Reset PHY - wait for self-clearing reset bit to clear */ | |
| 926 | + genphy_soft_reset(phy_data->phydev); | |
| 927 | + | |
| 925 | 928 | /* Disable RGMII mode */ |
| 926 | 929 | phy_write(phy_data->phydev, 0x18, 0x7007); |
| 927 | 930 | reg = phy_read(phy_data->phydev, 0x18); |
| @@ -1953,6 +1956,27 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata) · 1025 unmodified lines | ||
| 1953 | 1956 | xgbe_phy_put_comm_ownership(pdata); |
| 1954 | 1957 | } |
| 1955 | 1958 | |
| 1959 | +static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) | |
| 1960 | +{ | |
| 1961 | + int reg; | |
| 1962 | + | |
| 1963 | + reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, | |
| 1964 | + XGBE_PCS_PSEQ_STATE_MASK); | |
| 1965 | + if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { | |
| 1966 | + /* Mailbox command timed out, reset of RX block is required. | |
| 1967 | + * This can be done by asseting the reset bit and wait for | |
| 1968 | + * its compeletion. | |
| 1969 | + */ | |
| 1970 | + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, | |
| 1971 | + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); | |
| 1972 | + ndelay(20); | |
| 1973 | + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, | |
| 1974 | + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF); | |
| 1975 | + usleep_range(40, 50); | |
| 1976 | + netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n"); | |
| 1977 | + } | |
| 1978 | +} | |
| 1979 | + | |
| 1956 | 1980 | static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, |
| 1957 | 1981 | unsigned int cmd, unsigned int sub_cmd) |
| 1958 | 1982 | { |
| @@ -1960,9 +1984,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, · 1 unmodified line | ||
| 1960 | 1984 | unsigned int wait; |
| 1961 | 1985 | |
| 1962 | 1986 | /* Log if a previous command did not complete */ |
| 1963 | − if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) | |
| 1987 | + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { | |
| 1964 | 1988 | netif_dbg(pdata, link, pdata->netdev, |
| 1965 | 1989 | "firmware mailbox not ready for command\n"); |
| 1990 | + xgbe_phy_rx_reset(pdata); | |
| 1991 | + } | |
| 1966 | 1992 | |
| 1967 | 1993 | /* Construct the command */ |
| 1968 | 1994 | XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); |
| @@ -1984,6 +2010,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, · 15 unmodified lines | ||
| 1984 | 2010 | |
| 1985 | 2011 | netif_dbg(pdata, link, pdata->netdev, |
| 1986 | 2012 | "firmware mailbox command did not complete\n"); |
| 2013 | + | |
| 2014 | + /* Reset on error */ | |
| 2015 | + xgbe_phy_rx_reset(pdata); | |
| 1987 | 2016 | } |
| 1988 | 2017 | |
| 1989 | 2018 | static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) |
| @@ -2584,6 +2613,14 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) · 594 unmodified lines | ||
| 2584 | 2613 | if (reg & MDIO_STAT1_LSTATUS) |
| 2585 | 2614 | return 1; |
| 2586 | 2615 | |
| 2616 | + if (pdata->phy.autoneg == AUTONEG_ENABLE && | |
| 2617 | + phy_data->port_mode == XGBE_PORT_MODE_BACKPLANE) { | |
| 2618 | + if (!test_bit(XGBE_LINK_INIT, &pdata->dev_state)) { | |
| 2619 | + netif_carrier_off(pdata->netdev); | |
| 2620 | + *an_restart = 1; | |
| 2621 | + } | |
| 2622 | + } | |
| 2623 | + | |
| 2587 | 2624 | /* No link, attempt a receiver reset cycle */ |
| 2588 | 2625 | if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { |
| 2589 | 2626 | phy_data->rrc_count = 0; |
| @@ -71,8 +71,10 @@ static int aq_ndev_open(struct net_device *ndev) · 70 unmodified lines | ||
| 71 | 71 | goto err_exit; |
| 72 | 72 | |
| 73 | 73 | err = aq_nic_start(aq_nic); |
| 74 | − if (err < 0) | |
| 74 | + if (err < 0) { | |
| 75 | + aq_nic_stop(aq_nic); | |
| 75 | 76 | goto err_exit; |
| 77 | + } | |
| 76 | 78 | |
| 77 | 79 | err_exit: |
| 78 | 80 | if (err < 0) |
| @@ -8984,9 +8984,10 @@ void bnxt_tx_disable(struct bnxt *bp) · 8983 unmodified lines | ||
| 8984 | 8984 | txr->dev_state = BNXT_DEV_STATE_CLOSING; |
| 8985 | 8985 | } |
| 8986 | 8986 | } |
| 8987 | + /* Drop carrier first to prevent TX timeout */ | |
| 8988 | + netif_carrier_off(bp->dev); | |
| 8987 | 8989 | /* Stop all TX queues */ |
| 8988 | 8990 | netif_tx_disable(bp->dev); |
| 8989 | − netif_carrier_off(bp->dev); | |
| 8990 | 8991 | } |
| 8991 | 8992 | |
| 8992 | 8993 | void bnxt_tx_enable(struct bnxt *bp) |
| @@ -471,8 +471,8 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, · 470 unmodified lines | ||
| 471 | 471 | if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) { |
| 472 | 472 | u32 ver = nvm_cfg_ver.vu32; |
| 473 | 473 | |
| 474 | − sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF, | |
| 475 | − ver & 0xF); | |
| 474 | + sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf, | |
| 475 | + ver & 0xf); | |
| 476 | 476 | rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, |
| 477 | 477 | DEVLINK_INFO_VERSION_GENERIC_FW_PSID, |
| 478 | 478 | buf); |
| @@ -46,6 +46,9 @@ · 45 unmodified lines | ||
| 46 | 46 | #define MAX_ULD_QSETS 16 |
| 47 | 47 | #define MAX_ULD_NPORTS 4 |
| 48 | 48 | |
| 49 | +/* ulp_mem_io + ulptx_idata + payload + padding */ | |
| 50 | +#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) | |
| 51 | + | |
| 49 | 52 | /* CPL message priority levels */ |
| 50 | 53 | enum { |
| 51 | 54 | CPL_PRIORITY_DATA = 0, /* data messages */ |
| @@ -2846,17 +2846,22 @@ int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb) · 2845 unmodified lines | ||
| 2846 | 2846 | * @skb: the packet |
| 2847 | 2847 | * |
| 2848 | 2848 | * Returns true if a packet can be sent as an offload WR with immediate |
| 2849 | − * data. We currently use the same limit as for Ethernet packets. | |
| 2849 | + * data. | |
| 2850 | + * FW_OFLD_TX_DATA_WR limits the payload to 255 bytes due to 8-bit field. | |
| 2851 | + * However, FW_ULPTX_WR commands have a 256 byte immediate only | |
| 2852 | + * payload limit. | |
| 2850 | 2853 | */ |
| 2851 | 2854 | static inline int is_ofld_imm(const struct sk_buff *skb) |
| 2852 | 2855 | { |
| 2853 | 2856 | struct work_request_hdr *req = (struct work_request_hdr *)skb->data; |
| 2854 | 2857 | unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi)); |
| 2855 | 2858 | |
| 2856 | − if (opcode == FW_CRYPTO_LOOKASIDE_WR) | |
| 2859 | + if (unlikely(opcode == FW_ULPTX_WR)) | |
| 2860 | + return skb->len <= MAX_IMM_ULPTX_WR_LEN; | |
| 2861 | + else if (opcode == FW_CRYPTO_LOOKASIDE_WR) | |
| 2857 | 2862 | return skb->len <= SGE_MAX_WR_LEN; |
| 2858 | 2863 | else |
| 2859 | − return skb->len <= MAX_IMM_TX_PKT_LEN; | |
| 2864 | + return skb->len <= MAX_IMM_OFLD_TX_DATA_WR_LEN; | |
| 2860 | 2865 | } |
| 2861 | 2866 | |
| 2862 | 2867 | /** |
| @@ -50,9 +50,6 @@ · 49 unmodified lines | ||
| 50 | 50 | #define MIN_RCV_WND (24 * 1024U) |
| 51 | 51 | #define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000)) |
| 52 | 52 | |
| 53 | −/* ulp_mem_io + ulptx_idata + payload + padding */ | |
| 54 | −#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) | |
| 55 | − | |
| 56 | 53 | /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ |
| 57 | 54 | #define TX_HEADER_LEN \ |
| 58 | 55 | (sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr)) |
| @@ -395,10 +395,20 @@ static u32 dpaa2_eth_run_xdp(struct dpaa2_eth_priv *priv, · 394 unmodified lines | ||
| 395 | 395 | xdp.frame_sz = DPAA2_ETH_RX_BUF_RAW_SIZE; |
| 396 | 396 | |
| 397 | 397 | err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog); |
| 398 | − if (unlikely(err)) | |
| 398 | + if (unlikely(err)) { | |
| 399 | + addr = dma_map_page(priv->net_dev->dev.parent, | |
| 400 | + virt_to_page(vaddr), 0, | |
| 401 | + priv->rx_buf_size, DMA_BIDIRECTIONAL); | |
| 402 | + if (unlikely(dma_mapping_error(priv->net_dev->dev.parent, addr))) { | |
| 403 | + free_pages((unsigned long)vaddr, 0); | |
| 404 | + } else { | |
| 405 | + ch->buf_count++; | |
| 406 | + dpaa2_eth_xdp_release_buf(priv, ch, addr); | |
| 407 | + } | |
| 399 | 408 | ch->stats.xdp_drop++; |
| 400 | − else | |
| 409 | + } else { | |
| 401 | 410 | ch->stats.xdp_redirect++; |
| 411 | + } | |
| 402 | 412 | break; |
| 403 | 413 | } |
| 404 | 414 | |
| @@ -27,7 +27,7 @@ config FSL_ENETC_VF · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | config FSL_ENETC_MDIO |
| 29 | 29 | tristate "ENETC MDIO driver" |
| 30 | − depends on PCI | |
| 30 | + depends on PCI && MDIO_DEVRES && MDIO_BUS | |
| 31 | 31 | help |
| 32 | 32 | This driver supports NXP ENETC Central MDIO controller as a PCIe |
| 33 | 33 | physical function (PF) device. |
| @@ -1157,14 +1157,15 @@ static void enetc_pf_remove(struct pci_dev *pdev) · 1156 unmodified lines | ||
| 1157 | 1157 | struct enetc_ndev_priv *priv; |
| 1158 | 1158 | |
| 1159 | 1159 | priv = netdev_priv(si->ndev); |
| 1160 | − enetc_phylink_destroy(priv); | |
| 1161 | − enetc_mdiobus_destroy(pf); | |
| 1162 | 1160 | |
| 1163 | 1161 | if (pf->num_vfs) |
| 1164 | 1162 | enetc_sriov_configure(pdev, 0); |
| 1165 | 1163 | |
| 1166 | 1164 | unregister_netdev(si->ndev); |
| 1167 | 1165 | |
| 1166 | + enetc_phylink_destroy(priv); | |
| 1167 | + enetc_mdiobus_destroy(pf); | |
| 1168 | + | |
| 1168 | 1169 | enetc_free_msix(priv); |
| 1169 | 1170 | |
| 1170 | 1171 | enetc_free_si_resources(priv); |
| @@ -247,8 +247,13 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter, · 246 unmodified lines | ||
| 247 | 247 | if (!ltb->buff) |
| 248 | 248 | return; |
| 249 | 249 | |
| 250 | + /* VIOS automatically unmaps the long term buffer at remote | |
| 251 | + * end for the following resets: | |
| 252 | + * FAILOVER, MOBILITY, TIMEOUT. | |
| 253 | + */ | |
| 250 | 254 | if (adapter->reset_reason != VNIC_RESET_FAILOVER && |
| 251 | − adapter->reset_reason != VNIC_RESET_MOBILITY) | |
| 255 | + adapter->reset_reason != VNIC_RESET_MOBILITY && | |
| 256 | + adapter->reset_reason != VNIC_RESET_TIMEOUT) | |
| 252 | 257 | send_request_unmap(adapter, ltb->map_id); |
| 253 | 258 | dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); |
| 254 | 259 | } |
| @@ -1322,10 +1327,8 @@ static int __ibmvnic_close(struct net_device *netdev) · 1067 unmodified lines | ||
| 1322 | 1327 | |
| 1323 | 1328 | adapter->state = VNIC_CLOSING; |
| 1324 | 1329 | rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN); |
| 1325 | − if (rc) | |
| 1326 | − return rc; | |
| 1327 | 1330 | adapter->state = VNIC_CLOSED; |
| 1328 | − return 0; | |
| 1331 | + return rc; | |
| 1329 | 1332 | } |
| 1330 | 1333 | |
| 1331 | 1334 | static int ibmvnic_close(struct net_device *netdev) |
| @@ -1670,6 +1673,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) · 338 unmodified lines | ||
| 1670 | 1673 | skb_copy_from_linear_data(skb, dst, skb->len); |
| 1671 | 1674 | } |
| 1672 | 1675 | |
| 1676 | + /* post changes to long_term_buff *dst before VIOS accessing it */ | |
| 1677 | + dma_wmb(); | |
| 1678 | + | |
| 1673 | 1679 | tx_pool->consumer_index = |
| 1674 | 1680 | (tx_pool->consumer_index + 1) % tx_pool->num_buffers; |
| 1675 | 1681 | |
| @@ -2288,7 +2294,8 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, · 612 unmodified lines | ||
| 2288 | 2294 | unsigned long flags; |
| 2289 | 2295 | int ret; |
| 2290 | 2296 | |
| 2291 | − /* If failover is pending don't schedule any other reset. | |
| 2297 | + /* | |
| 2298 | + * If failover is pending don't schedule any other reset. | |
| 2292 | 2299 | * Instead let the failover complete. If there is already a |
| 2293 | 2300 | * a failover reset scheduled, we will detect and drop the |
| 2294 | 2301 | * duplicate reset when walking the ->rwi_list below. |
| @@ -2308,14 +2315,11 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, · 13 unmodified lines | ||
| 2308 | 2315 | goto err; |
| 2309 | 2316 | } |
| 2310 | 2317 | |
| 2311 | − spin_lock_irqsave(&adapter->rwi_lock, flags); | |
| 2312 | − | |
| 2313 | 2318 | list_for_each(entry, &adapter->rwi_list) { |
| 2314 | 2319 | tmp = list_entry(entry, struct ibmvnic_rwi, list); |
| 2315 | 2320 | if (tmp->reset_reason == reason) { |
| 2316 | 2321 | netdev_dbg(netdev, "Skipping matching reset, reason=%d\n", |
| 2317 | 2322 | reason); |
| 2318 | − spin_unlock_irqrestore(&adapter->rwi_lock, flags); | |
| 2319 | 2323 | ret = EBUSY; |
| 2320 | 2324 | goto err; |
| 2321 | 2325 | } |
| @@ -2323,8 +2327,6 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, · 1 unmodified line | ||
| 2323 | 2327 | |
| 2324 | 2328 | rwi = kzalloc(sizeof(*rwi), GFP_ATOMIC); |
| 2325 | 2329 | if (!rwi) { |
| 2326 | − spin_unlock_irqrestore(&adapter->rwi_lock, flags); | |
| 2327 | − ibmvnic_close(netdev); | |
| 2328 | 2330 | ret = ENOMEM; |
| 2329 | 2331 | goto err; |
| 2330 | 2332 | } |
| @@ -2337,12 +2339,17 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, · 6 unmodified lines | ||
| 2337 | 2339 | } |
| 2338 | 2340 | rwi->reset_reason = reason; |
| 2339 | 2341 | list_add_tail(&rwi->list, &adapter->rwi_list); |
| 2340 | − spin_unlock_irqrestore(&adapter->rwi_lock, flags); | |
| 2341 | 2342 | netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason); |
| 2342 | 2343 | schedule_work(&adapter->ibmvnic_reset); |
| 2343 | 2344 | |
| 2344 | − return 0; | |
| 2345 | + ret = 0; | |
| 2345 | 2346 | err: |
| 2347 | + /* ibmvnic_close() below can block, so drop the lock first */ | |
| 2348 | + spin_unlock_irqrestore(&adapter->rwi_lock, flags); | |
| 2349 | + | |
| 2350 | + if (ret == ENOMEM) | |
| 2351 | + ibmvnic_close(netdev); | |
| 2352 | + | |
| 2346 | 2353 | return -ret; |
| 2347 | 2354 | } |
| 2348 | 2355 | |
| @@ -2433,6 +2440,8 @@ restart_poll: · 84 unmodified lines | ||
| 2433 | 2440 | offset = be16_to_cpu(next->rx_comp.off_frame_data); |
| 2434 | 2441 | flags = next->rx_comp.flags; |
| 2435 | 2442 | skb = rx_buff->skb; |
| 2443 | + /* load long_term_buff before copying to skb */ | |
| 2444 | + dma_rmb(); | |
| 2436 | 2445 | skb_copy_to_linear_data(skb, rx_buff->data + offset, |
| 2437 | 2446 | length); |
| 2438 | 2447 | |
| @@ -5346,7 +5355,18 @@ static int ibmvnic_remove(struct vio_dev *dev) · 2907 unmodified lines | ||
| 5346 | 5355 | unsigned long flags; |
| 5347 | 5356 | |
| 5348 | 5357 | spin_lock_irqsave(&adapter->state_lock, flags); |
| 5358 | + | |
| 5359 | + /* If ibmvnic_reset() is scheduling a reset, wait for it to | |
| 5360 | + * finish. Then, set the state to REMOVING to prevent it from | |
| 5361 | + * scheduling any more work and to have reset functions ignore | |
| 5362 | + * any resets that have already been scheduled. Drop the lock | |
| 5363 | + * after setting state, so __ibmvnic_reset() which is called | |
| 5364 | + * from the flush_work() below, can make progress. | |
| 5365 | + */ | |
| 5366 | + spin_lock_irqsave(&adapter->rwi_lock, flags); | |
| 5349 | 5367 | adapter->state = VNIC_REMOVING; |
| 5368 | + spin_unlock_irqrestore(&adapter->rwi_lock, flags); | |
| 5369 | + | |
| 5350 | 5370 | spin_unlock_irqrestore(&adapter->state_lock, flags); |
| 5351 | 5371 | |
| 5352 | 5372 | flush_work(&adapter->ibmvnic_reset); |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #define IBMVNIC_BUFFS_PER_POOL 100 |
| 32 | 32 | #define IBMVNIC_MAX_QUEUES 16 |
| 33 | 33 | #define IBMVNIC_MAX_QUEUE_SZ 4096 |
| 34 | −#define IBMVNIC_MAX_IND_DESCS 128 | |
| 34 | +#define IBMVNIC_MAX_IND_DESCS 16 | |
| 35 | 35 | #define IBMVNIC_IND_ARR_SZ (IBMVNIC_MAX_IND_DESCS * 32) |
| 36 | 36 | |
| 37 | 37 | #define IBMVNIC_TSO_BUF_SZ 65536 |
| @@ -1084,6 +1084,8 @@ struct ibmvnic_adapter { · 1046 unmodified lines | ||
| 1084 | 1084 | /* Used for serializatin of state field */ |
| 1085 | 1085 | spinlock_t state_lock; |
| 1086 | 1086 | enum ibmvnic_reset_reason reset_reason; |
| 1087 | + /* when taking both state and rwi locks, take state lock first */ | |
| 1088 | + spinlock_t rwi_lock; | |
| 1087 | 1089 | struct list_head rwi_list; |
| 1088 | 1090 | /* Used for serialization of rwi_list */ |
| 1089 | 1091 | spinlock_t rwi_lock; |
| @@ -141,6 +141,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, · 140 unmodified lines | ||
| 141 | 141 | return -EOPNOTSUPP; |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | + if (mlx5_lag_is_active(dev)) { | |
| 145 | + NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode\n"); | |
| 146 | + return -EOPNOTSUPP; | |
| 147 | + } | |
| 148 | + | |
| 144 | 149 | switch (action) { |
| 145 | 150 | case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: |
| 146 | 151 | mlx5_unload_one(dev, false); |
| @@ -428,6 +433,10 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, · 281 unmodified lines | ||
| 428 | 433 | NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); |
| 429 | 434 | return -EOPNOTSUPP; |
| 430 | 435 | } |
| 436 | + if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) { | |
| 437 | + NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE"); | |
| 438 | + return -EOPNOTSUPP; | |
| 439 | + } | |
| 431 | 440 | |
| 432 | 441 | return 0; |
| 433 | 442 | } |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <net/flow_offload.h> |
| 13 | 13 | #include <net/netfilter/nf_flow_table.h> |
| 14 | 14 | #include <linux/workqueue.h> |
| 15 | +#include <linux/refcount.h> | |
| 15 | 16 | #include <linux/xarray.h> |
| 16 | 17 | |
| 17 | 18 | #include "lib/fs_chains.h" |
| @@ -52,11 +53,11 @@ struct mlx5_tc_ct_priv { · 34 unmodified lines | ||
| 52 | 53 | struct mlx5_flow_table *ct_nat; |
| 53 | 54 | struct mlx5_flow_table *post_ct; |
| 54 | 55 | struct mutex control_lock; /* guards parallel adds/dels */ |
| 55 | − struct mutex shared_counter_lock; | |
| 56 | 56 | struct mapping_ctx *zone_mapping; |
| 57 | 57 | struct mapping_ctx *labels_mapping; |
| 58 | 58 | enum mlx5_flow_namespace_type ns_type; |
| 59 | 59 | struct mlx5_fs_chains *chains; |
| 60 | + spinlock_t ht_lock; /* protects ft entries */ | |
| 60 | 61 | }; |
| 61 | 62 | |
| 62 | 63 | struct mlx5_ct_flow { |
| @@ -125,6 +126,10 @@ struct mlx5_ct_counter { · 62 unmodified lines | ||
| 125 | 126 | bool is_shared; |
| 126 | 127 | }; |
| 127 | 128 | |
| 129 | +enum { | |
| 130 | + MLX5_CT_ENTRY_FLAG_VALID, | |
| 131 | +}; | |
| 132 | + | |
| 128 | 133 | struct mlx5_ct_entry { |
| 129 | 134 | struct rhash_head node; |
| 130 | 135 | struct rhash_head tuple_node; |
| @@ -135,6 +140,12 @@ struct mlx5_ct_entry { · 4 unmodified lines | ||
| 135 | 140 | struct mlx5_ct_tuple tuple; |
| 136 | 141 | struct mlx5_ct_tuple tuple_nat; |
| 137 | 142 | struct mlx5_ct_zone_rule zone_rules[2]; |
| 143 | + | |
| 144 | + struct mlx5_tc_ct_priv *ct_priv; | |
| 145 | + struct work_struct work; | |
| 146 | + | |
| 147 | + refcount_t refcnt; | |
| 148 | + unsigned long flags; | |
| 138 | 149 | }; |
| 139 | 150 | |
| 140 | 151 | static const struct rhashtable_params cts_ht_params = { |
| @@ -742,6 +753,87 @@ err_attr: · 601 unmodified lines | ||
| 742 | 753 | return err; |
| 743 | 754 | } |
| 744 | 755 | |
| 756 | +static bool | |
| 757 | +mlx5_tc_ct_entry_valid(struct mlx5_ct_entry *entry) | |
| 758 | +{ | |
| 759 | + return test_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags); | |
| 760 | +} | |
| 761 | + | |
| 762 | +static struct mlx5_ct_entry * | |
| 763 | +mlx5_tc_ct_entry_get(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_tuple *tuple) | |
| 764 | +{ | |
| 765 | + struct mlx5_ct_entry *entry; | |
| 766 | + | |
| 767 | + entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, tuple, | |
| 768 | + tuples_ht_params); | |
| 769 | + if (entry && mlx5_tc_ct_entry_valid(entry) && | |
| 770 | + refcount_inc_not_zero(&entry->refcnt)) { | |
| 771 | + return entry; | |
| 772 | + } else if (!entry) { | |
| 773 | + entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht, | |
| 774 | + tuple, tuples_nat_ht_params); | |
| 775 | + if (entry && mlx5_tc_ct_entry_valid(entry) && | |
| 776 | + refcount_inc_not_zero(&entry->refcnt)) | |
| 777 | + return entry; | |
| 778 | + } | |
| 779 | + | |
| 780 | + return entry ? ERR_PTR(-EINVAL) : NULL; | |
| 781 | +} | |
| 782 | + | |
| 783 | +static void mlx5_tc_ct_entry_remove_from_tuples(struct mlx5_ct_entry *entry) | |
| 784 | +{ | |
| 785 | + struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv; | |
| 786 | + | |
| 787 | + rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, | |
| 788 | + &entry->tuple_nat_node, | |
| 789 | + tuples_nat_ht_params); | |
| 790 | + rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node, | |
| 791 | + tuples_ht_params); | |
| 792 | +} | |
| 793 | + | |
| 794 | +static void mlx5_tc_ct_entry_del(struct mlx5_ct_entry *entry) | |
| 795 | +{ | |
| 796 | + struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv; | |
| 797 | + | |
| 798 | + mlx5_tc_ct_entry_del_rules(ct_priv, entry); | |
| 799 | + | |
| 800 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 801 | + mlx5_tc_ct_entry_remove_from_tuples(entry); | |
| 802 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 803 | + | |
| 804 | + mlx5_tc_ct_counter_put(ct_priv, entry); | |
| 805 | + kfree(entry); | |
| 806 | +} | |
| 807 | + | |
| 808 | +static void | |
| 809 | +mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry) | |
| 810 | +{ | |
| 811 | + if (!refcount_dec_and_test(&entry->refcnt)) | |
| 812 | + return; | |
| 813 | + | |
| 814 | + mlx5_tc_ct_entry_del(entry); | |
| 815 | +} | |
| 816 | + | |
| 817 | +static void mlx5_tc_ct_entry_del_work(struct work_struct *work) | |
| 818 | +{ | |
| 819 | + struct mlx5_ct_entry *entry = container_of(work, struct mlx5_ct_entry, work); | |
| 820 | + | |
| 821 | + mlx5_tc_ct_entry_del(entry); | |
| 822 | +} | |
| 823 | + | |
| 824 | +static void | |
| 825 | +__mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry) | |
| 826 | +{ | |
| 827 | + struct mlx5e_priv *priv; | |
| 828 | + | |
| 829 | + if (!refcount_dec_and_test(&entry->refcnt)) | |
| 830 | + return; | |
| 831 | + | |
| 832 | + priv = netdev_priv(entry->ct_priv->netdev); | |
| 833 | + INIT_WORK(&entry->work, mlx5_tc_ct_entry_del_work); | |
| 834 | + queue_work(priv->wq, &entry->work); | |
| 835 | +} | |
| 836 | + | |
| 745 | 837 | static struct mlx5_ct_counter * |
| 746 | 838 | mlx5_tc_ct_counter_create(struct mlx5_tc_ct_priv *ct_priv) |
| 747 | 839 | { |
| @@ -793,16 +885,26 @@ mlx5_tc_ct_shared_counter_get(struct mlx5_tc_ct_priv *ct_priv, · 45 unmodified lines | ||
| 793 | 885 | } |
| 794 | 886 | |
| 795 | 887 | /* Use the same counter as the reverse direction */ |
| 796 | − mutex_lock(&ct_priv->shared_counter_lock); | |
| 797 | − rev_entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &rev_tuple, | |
| 798 | − tuples_ht_params); | |
| 799 | − if (rev_entry) { | |
| 800 | − if (refcount_inc_not_zero(&rev_entry->counter->refcount)) { | |
| 801 | − mutex_unlock(&ct_priv->shared_counter_lock); | |
| 802 | − return rev_entry->counter; | |
| 803 | − } | |
| 888 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 889 | + rev_entry = mlx5_tc_ct_entry_get(ct_priv, &rev_tuple); | |
| 890 | + | |
| 891 | + if (IS_ERR(rev_entry)) { | |
| 892 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 893 | + goto create_counter; | |
| 804 | 894 | } |
| 805 | − mutex_unlock(&ct_priv->shared_counter_lock); | |
| 895 | + | |
| 896 | + if (rev_entry && refcount_inc_not_zero(&rev_entry->counter->refcount)) { | |
| 897 | + ct_dbg("Using shared counter entry=0x%p rev=0x%p\n", entry, rev_entry); | |
| 898 | + shared_counter = rev_entry->counter; | |
| 899 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 900 | + | |
| 901 | + mlx5_tc_ct_entry_put(rev_entry); | |
| 902 | + return shared_counter; | |
| 903 | + } | |
| 904 | + | |
| 905 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 906 | + | |
| 907 | +create_counter: | |
| 806 | 908 | |
| 807 | 909 | shared_counter = mlx5_tc_ct_counter_create(ct_priv); |
| 808 | 910 | if (IS_ERR(shared_counter)) |
| @@ -865,10 +967,14 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, · 56 unmodified lines | ||
| 865 | 967 | if (!meta_action) |
| 866 | 968 | return -EOPNOTSUPP; |
| 867 | 969 | |
| 868 | − entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, | |
| 869 | − cts_ht_params); | |
| 870 | − if (entry) | |
| 871 | − return 0; | |
| 970 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 971 | + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); | |
| 972 | + if (entry && refcount_inc_not_zero(&entry->refcnt)) { | |
| 973 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 974 | + mlx5_tc_ct_entry_put(entry); | |
| 975 | + return -EEXIST; | |
| 976 | + } | |
| 977 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 872 | 978 | |
| 873 | 979 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
| 874 | 980 | if (!entry) |
| @@ -877,6 +983,8 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, · 2 unmodified lines | ||
| 877 | 983 | entry->tuple.zone = ft->zone; |
| 878 | 984 | entry->cookie = flow->cookie; |
| 879 | 985 | entry->restore_cookie = meta_action->ct_metadata.cookie; |
| 986 | + refcount_set(&entry->refcnt, 2); | |
| 987 | + entry->ct_priv = ct_priv; | |
| 880 | 988 | |
| 881 | 989 | err = mlx5_tc_ct_rule_to_tuple(&entry->tuple, flow_rule); |
| 882 | 990 | if (err) |
| @@ -887,35 +995,40 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, · 4 unmodified lines | ||
| 887 | 995 | if (err) |
| 888 | 996 | goto err_set; |
| 889 | 997 | |
| 890 | − err = rhashtable_insert_fast(&ct_priv->ct_tuples_ht, | |
| 891 | − &entry->tuple_node, | |
| 892 | − tuples_ht_params); | |
| 998 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 999 | + | |
| 1000 | + err = rhashtable_lookup_insert_fast(&ft->ct_entries_ht, &entry->node, | |
| 1001 | + cts_ht_params); | |
| 1002 | + if (err) | |
| 1003 | + goto err_entries; | |
| 1004 | + | |
| 1005 | + err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_ht, | |
| 1006 | + &entry->tuple_node, | |
| 1007 | + tuples_ht_params); | |
| 893 | 1008 | if (err) |
| 894 | 1009 | goto err_tuple; |
| 895 | 1010 | |
| 896 | 1011 | if (memcmp(&entry->tuple, &entry->tuple_nat, sizeof(entry->tuple))) { |
| 897 | − err = rhashtable_insert_fast(&ct_priv->ct_tuples_nat_ht, | |
| 898 | − &entry->tuple_nat_node, | |
| 899 | − tuples_nat_ht_params); | |
| 1012 | + err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_nat_ht, | |
| 1013 | + &entry->tuple_nat_node, | |
| 1014 | + tuples_nat_ht_params); | |
| 900 | 1015 | if (err) |
| 901 | 1016 | goto err_tuple_nat; |
| 902 | 1017 | } |
| 1018 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 903 | 1019 | |
| 904 | 1020 | err = mlx5_tc_ct_entry_add_rules(ct_priv, flow_rule, entry, |
| 905 | 1021 | ft->zone_restore_id); |
| 906 | 1022 | if (err) |
| 907 | 1023 | goto err_rules; |
| 908 | 1024 | |
| 909 | − err = rhashtable_insert_fast(&ft->ct_entries_ht, &entry->node, | |
| 910 | − cts_ht_params); | |
| 911 | − if (err) | |
| 912 | − goto err_insert; | |
| 1025 | + set_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags); | |
| 1026 | + mlx5_tc_ct_entry_put(entry); /* this function reference */ | |
| 913 | 1027 | |
| 914 | 1028 | return 0; |
| 915 | 1029 | |
| 916 | −err_insert: | |
| 917 | − mlx5_tc_ct_entry_del_rules(ct_priv, entry); | |
| 918 | 1030 | err_rules: |
| 1031 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 919 | 1032 | if (mlx5_tc_ct_entry_has_nat(entry)) |
| 920 | 1033 | rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, |
| 921 | 1034 | &entry->tuple_nat_node, tuples_nat_ht_params); |
| @@ -924,47 +1037,43 @@ err_tuple_nat: · 2 unmodified lines | ||
| 924 | 1037 | &entry->tuple_node, |
| 925 | 1038 | tuples_ht_params); |
| 926 | 1039 | err_tuple: |
| 1040 | + rhashtable_remove_fast(&ft->ct_entries_ht, | |
| 1041 | + &entry->node, | |
| 1042 | + cts_ht_params); | |
| 1043 | +err_entries: | |
| 1044 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 927 | 1045 | err_set: |
| 928 | 1046 | kfree(entry); |
| 929 | − netdev_warn(ct_priv->netdev, | |
| 930 | − "Failed to offload ct entry, err: %d\n", err); | |
| 1047 | + if (err != -EEXIST) | |
| 1048 | + netdev_warn(ct_priv->netdev, "Failed to offload ct entry, err: %d\n", err); | |
| 931 | 1049 | return err; |
| 932 | 1050 | } |
| 933 | 1051 | |
| 934 | −static void | |
| 935 | −mlx5_tc_ct_del_ft_entry(struct mlx5_tc_ct_priv *ct_priv, | |
| 936 | − struct mlx5_ct_entry *entry) | |
| 937 | −{ | |
| 938 | − mlx5_tc_ct_entry_del_rules(ct_priv, entry); | |
| 939 | − mutex_lock(&ct_priv->shared_counter_lock); | |
| 940 | − if (mlx5_tc_ct_entry_has_nat(entry)) | |
| 941 | − rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, | |
| 942 | − &entry->tuple_nat_node, | |
| 943 | − tuples_nat_ht_params); | |
| 944 | − rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node, | |
| 945 | − tuples_ht_params); | |
| 946 | − mutex_unlock(&ct_priv->shared_counter_lock); | |
| 947 | − mlx5_tc_ct_counter_put(ct_priv, entry); | |
| 948 | − | |
| 949 | −} | |
| 950 | − | |
| 951 | 1052 | static int |
| 952 | 1053 | mlx5_tc_ct_block_flow_offload_del(struct mlx5_ct_ft *ft, |
| 953 | 1054 | struct flow_cls_offload *flow) |
| 954 | 1055 | { |
| 1056 | + struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv; | |
| 955 | 1057 | unsigned long cookie = flow->cookie; |
| 956 | 1058 | struct mlx5_ct_entry *entry; |
| 957 | 1059 | |
| 958 | − entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, | |
| 959 | − cts_ht_params); | |
| 960 | − if (!entry) | |
| 1060 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 1061 | + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); | |
| 1062 | + if (!entry) { | |
| 1063 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 961 | 1064 | return -ENOENT; |
| 1065 | + } | |
| 962 | 1066 | |
| 963 | − mlx5_tc_ct_del_ft_entry(ft->ct_priv, entry); | |
| 964 | − WARN_ON(rhashtable_remove_fast(&ft->ct_entries_ht, | |
| 965 | − &entry->node, | |
| 966 | − cts_ht_params)); | |
| 967 | − kfree(entry); | |
| 1067 | + if (!mlx5_tc_ct_entry_valid(entry)) { | |
| 1068 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 1069 | + return -EINVAL; | |
| 1070 | + } | |
| 1071 | + | |
| 1072 | + rhashtable_remove_fast(&ft->ct_entries_ht, &entry->node, cts_ht_params); | |
| 1073 | + mlx5_tc_ct_entry_remove_from_tuples(entry); | |
| 1074 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 1075 | + | |
| 1076 | + mlx5_tc_ct_entry_put(entry); | |
| 968 | 1077 | |
| 969 | 1078 | return 0; |
| 970 | 1079 | } |
| @@ -973,19 +1082,30 @@ static int · 2 unmodified lines | ||
| 973 | 1082 | mlx5_tc_ct_block_flow_offload_stats(struct mlx5_ct_ft *ft, |
| 974 | 1083 | struct flow_cls_offload *f) |
| 975 | 1084 | { |
| 1085 | + struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv; | |
| 976 | 1086 | unsigned long cookie = f->cookie; |
| 977 | 1087 | struct mlx5_ct_entry *entry; |
| 978 | 1088 | u64 lastuse, packets, bytes; |
| 979 | 1089 | |
| 980 | − entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, | |
| 981 | − cts_ht_params); | |
| 982 | − if (!entry) | |
| 1090 | + spin_lock_bh(&ct_priv->ht_lock); | |
| 1091 | + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); | |
| 1092 | + if (!entry) { | |
| 1093 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 983 | 1094 | return -ENOENT; |
| 1095 | + } | |
| 1096 | + | |
| 1097 | + if (!mlx5_tc_ct_entry_valid(entry) || !refcount_inc_not_zero(&entry->refcnt)) { | |
| 1098 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 1099 | + return -EINVAL; | |
| 1100 | + } | |
| 1101 | + | |
| 1102 | + spin_unlock_bh(&ct_priv->ht_lock); | |
| 984 | 1103 | |
| 985 | 1104 | mlx5_fc_query_cached(entry->counter->counter, &bytes, &packets, &lastuse); |
| 986 | 1105 | flow_stats_update(&f->stats, bytes, packets, 0, lastuse, |
| 987 | 1106 | FLOW_ACTION_HW_STATS_DELAYED); |
| 988 | 1107 | |
| 1108 | + mlx5_tc_ct_entry_put(entry); | |
| 989 | 1109 | return 0; |
| 990 | 1110 | } |
| 991 | 1111 | |
| @@ -1481,11 +1601,9 @@ err_mapping: · 489 unmodified lines | ||
| 1481 | 1601 | static void |
| 1482 | 1602 | mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg) |
| 1483 | 1603 | { |
| 1484 | − struct mlx5_tc_ct_priv *ct_priv = arg; | |
| 1485 | 1604 | struct mlx5_ct_entry *entry = ptr; |
| 1486 | 1605 | |
| 1487 | − mlx5_tc_ct_del_ft_entry(ct_priv, entry); | |
| 1488 | − kfree(entry); | |
| 1606 | + mlx5_tc_ct_entry_put(entry); | |
| 1489 | 1607 | } |
| 1490 | 1608 | |
| 1491 | 1609 | static void |
| @@ -1962,6 +2080,7 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains, · 470 unmodified lines | ||
| 1962 | 2080 | goto err_mapping_labels; |
| 1963 | 2081 | } |
| 1964 | 2082 | |
| 2083 | + spin_lock_init(&ct_priv->ht_lock); | |
| 1965 | 2084 | ct_priv->ns_type = ns_type; |
| 1966 | 2085 | ct_priv->chains = chains; |
| 1967 | 2086 | ct_priv->netdev = priv->netdev; |
| @@ -1996,7 +2115,6 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains, · 28 unmodified lines | ||
| 1996 | 2115 | |
| 1997 | 2116 | idr_init(&ct_priv->fte_ids); |
| 1998 | 2117 | mutex_init(&ct_priv->control_lock); |
| 1999 | − mutex_init(&ct_priv->shared_counter_lock); | |
| 2000 | 2118 | rhashtable_init(&ct_priv->zone_ht, &zone_params); |
| 2001 | 2119 | rhashtable_init(&ct_priv->ct_tuples_ht, &tuples_ht_params); |
| 2002 | 2120 | rhashtable_init(&ct_priv->ct_tuples_nat_ht, &tuples_nat_ht_params); |
| @@ -2039,7 +2157,6 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv) · 36 unmodified lines | ||
| 2039 | 2157 | rhashtable_destroy(&ct_priv->ct_tuples_nat_ht); |
| 2040 | 2158 | rhashtable_destroy(&ct_priv->zone_ht); |
| 2041 | 2159 | mutex_destroy(&ct_priv->control_lock); |
| 2042 | − mutex_destroy(&ct_priv->shared_counter_lock); | |
| 2043 | 2160 | idr_destroy(&ct_priv->fte_ids); |
| 2044 | 2161 | kfree(ct_priv); |
| 2045 | 2162 | } |
| @@ -2061,14 +2178,22 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv, · 15 unmodified lines | ||
| 2061 | 2178 | if (!mlx5_tc_ct_skb_to_tuple(skb, &tuple, zone)) |
| 2062 | 2179 | return false; |
| 2063 | 2180 | |
| 2064 | − entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &tuple, | |
| 2065 | − tuples_ht_params); | |
| 2066 | − if (!entry) | |
| 2067 | − entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht, | |
| 2068 | − &tuple, tuples_nat_ht_params); | |
| 2069 | − if (!entry) | |
| 2181 | + spin_lock(&ct_priv->ht_lock); | |
| 2182 | + | |
| 2183 | + entry = mlx5_tc_ct_entry_get(ct_priv, &tuple); | |
| 2184 | + if (!entry) { | |
| 2185 | + spin_unlock(&ct_priv->ht_lock); | |
| 2186 | + return false; | |
| 2187 | + } | |
| 2188 | + | |
| 2189 | + if (IS_ERR(entry)) { | |
| 2190 | + spin_unlock(&ct_priv->ht_lock); | |
| 2070 | 2191 | return false; |
| 2192 | + } | |
| 2193 | + spin_unlock(&ct_priv->ht_lock); | |
| 2071 | 2194 | |
| 2072 | 2195 | tcf_ct_flow_table_restore_skb(skb, entry->restore_cookie); |
| 2196 | + __mlx5_tc_ct_entry_put(entry); | |
| 2197 | + | |
| 2073 | 2198 | return true; |
| 2074 | 2199 | } |
| @@ -83,7 +83,7 @@ static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv) · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); |
| 85 | 85 | /* Let other device's napi(s) and XSK wakeups see our new state. */ |
| 86 | − synchronize_rcu(); | |
| 86 | + synchronize_net(); | |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv) |
| @@ -111,7 +111,7 @@ err_free_cparam: · 110 unmodified lines | ||
| 111 | 111 | void mlx5e_close_xsk(struct mlx5e_channel *c) |
| 112 | 112 | { |
| 113 | 113 | clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state); |
| 114 | − synchronize_rcu(); /* Sync with the XSK wakeup and with NAPI. */ | |
| 114 | + synchronize_net(); /* Sync with the XSK wakeup and with NAPI. */ | |
| 115 | 115 | |
| 116 | 116 | mlx5e_close_rq(&c->xskrq); |
| 117 | 117 | mlx5e_close_cq(&c->xskrq.cq); |
| @@ -173,7 +173,7 @@ static inline bool mlx5e_accel_tx_eseg(struct mlx5e_priv *priv, · 172 unmodified lines | ||
| 173 | 173 | #endif |
| 174 | 174 | |
| 175 | 175 | #if IS_ENABLED(CONFIG_GENEVE) |
| 176 | − if (skb->encapsulation) | |
| 176 | + if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) | |
| 177 | 177 | mlx5e_tx_tunnel_accel(skb, eseg, ihs); |
| 178 | 178 | #endif |
| 179 | 179 | |
| @@ -57,6 +57,20 @@ struct mlx5e_ktls_offload_context_rx { · 56 unmodified lines | ||
| 57 | 57 | struct mlx5e_ktls_rx_resync_ctx resync; |
| 58 | 58 | }; |
| 59 | 59 | |
| 60 | +static bool mlx5e_ktls_priv_rx_put(struct mlx5e_ktls_offload_context_rx *priv_rx) | |
| 61 | +{ | |
| 62 | + if (!refcount_dec_and_test(&priv_rx->resync.refcnt)) | |
| 63 | + return false; | |
| 64 | + | |
| 65 | + kfree(priv_rx); | |
| 66 | + return true; | |
| 67 | +} | |
| 68 | + | |
| 69 | +static void mlx5e_ktls_priv_rx_get(struct mlx5e_ktls_offload_context_rx *priv_rx) | |
| 70 | +{ | |
| 71 | + refcount_inc(&priv_rx->resync.refcnt); | |
| 72 | +} | |
| 73 | + | |
| 60 | 74 | static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn) |
| 61 | 75 | { |
| 62 | 76 | int err, inlen; |
| @@ -326,7 +340,7 @@ static void resync_handle_work(struct work_struct *work) · 263 unmodified lines | ||
| 326 | 340 | priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync); |
| 327 | 341 | |
| 328 | 342 | if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) { |
| 329 | − refcount_dec(&resync->refcnt); | |
| 343 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 330 | 344 | return; |
| 331 | 345 | } |
| 332 | 346 | |
| @@ -334,7 +348,7 @@ static void resync_handle_work(struct work_struct *work) · 1 unmodified line | ||
| 334 | 348 | sq = &c->async_icosq; |
| 335 | 349 | |
| 336 | 350 | if (resync_post_get_progress_params(sq, priv_rx)) |
| 337 | − refcount_dec(&resync->refcnt); | |
| 351 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 338 | 352 | } |
| 339 | 353 | |
| 340 | 354 | static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync, |
| @@ -377,7 +391,11 @@ unlock: · 36 unmodified lines | ||
| 377 | 391 | return err; |
| 378 | 392 | } |
| 379 | 393 | |
| 380 | −/* Function is called with elevated refcount, it decreases it. */ | |
| 394 | +/* Function can be called with the refcount being either elevated or not. | |
| 395 | + * It decreases the refcount and may free the kTLS priv context. | |
| 396 | + * Refcount is not elevated only if tls_dev_del has been called, but GET_PSV was | |
| 397 | + * already in flight. | |
| 398 | + */ | |
| 381 | 399 | void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, |
| 382 | 400 | struct mlx5e_icosq *sq) |
| 383 | 401 | { |
| @@ -410,7 +428,7 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, · 26 unmodified lines | ||
| 410 | 428 | tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq)); |
| 411 | 429 | priv_rx->stats->tls_resync_req_end++; |
| 412 | 430 | out: |
| 413 | − refcount_dec(&resync->refcnt); | |
| 431 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 414 | 432 | dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE); |
| 415 | 433 | kfree(buf); |
| 416 | 434 | } |
| @@ -431,9 +449,9 @@ static bool resync_queue_get_psv(struct sock *sk) · 14 unmodified lines | ||
| 431 | 449 | return false; |
| 432 | 450 | |
| 433 | 451 | resync = &priv_rx->resync; |
| 434 | − refcount_inc(&resync->refcnt); | |
| 452 | + mlx5e_ktls_priv_rx_get(priv_rx); | |
| 435 | 453 | if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work))) |
| 436 | − refcount_dec(&resync->refcnt); | |
| 454 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 437 | 455 | |
| 438 | 456 | return true; |
| 439 | 457 | } |
| @@ -625,31 +643,6 @@ err_create_key: · 185 unmodified lines | ||
| 625 | 643 | return err; |
| 626 | 644 | } |
| 627 | 645 | |
| 628 | −/* Elevated refcount on the resync object means there are | |
| 629 | − * outstanding operations (uncompleted GET_PSV WQEs) that | |
| 630 | − * will read the resync / priv_rx objects once completed. | |
| 631 | − * Wait for them to avoid use-after-free. | |
| 632 | − */ | |
| 633 | −static void wait_for_resync(struct net_device *netdev, | |
| 634 | − struct mlx5e_ktls_rx_resync_ctx *resync) | |
| 635 | −{ | |
| 636 | −#define MLX5E_KTLS_RX_RESYNC_TIMEOUT 20000 /* msecs */ | |
| 637 | − unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5E_KTLS_RX_RESYNC_TIMEOUT); | |
| 638 | − unsigned int refcnt; | |
| 639 | − | |
| 640 | − do { | |
| 641 | − refcnt = refcount_read(&resync->refcnt); | |
| 642 | − if (refcnt == 1) | |
| 643 | − return; | |
| 644 | − | |
| 645 | − msleep(20); | |
| 646 | − } while (time_before(jiffies, exp_time)); | |
| 647 | − | |
| 648 | − netdev_warn(netdev, | |
| 649 | − "Failed waiting for kTLS RX resync refcnt to be released (%u).\n", | |
| 650 | − refcnt); | |
| 651 | −} | |
| 652 | − | |
| 653 | 646 | void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) |
| 654 | 647 | { |
| 655 | 648 | struct mlx5e_ktls_offload_context_rx *priv_rx; |
| @@ -663,7 +656,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) · 7 unmodified lines | ||
| 663 | 656 | priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx); |
| 664 | 657 | set_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags); |
| 665 | 658 | mlx5e_set_ktls_rx_priv_ctx(tls_ctx, NULL); |
| 666 | − synchronize_rcu(); /* Sync with NAPI */ | |
| 659 | + synchronize_net(); /* Sync with NAPI */ | |
| 667 | 660 | if (!cancel_work_sync(&priv_rx->rule.work)) |
| 668 | 661 | /* completion is needed, as the priv_rx in the add flow |
| 669 | 662 | * is maintained on the wqe info (wi), not on the socket. |
| @@ -671,8 +664,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) · 1 unmodified line | ||
| 671 | 664 | wait_for_completion(&priv_rx->add_ctx); |
| 672 | 665 | resync = &priv_rx->resync; |
| 673 | 666 | if (cancel_work_sync(&resync->work)) |
| 674 | − refcount_dec(&resync->refcnt); | |
| 675 | − wait_for_resync(netdev, resync); | |
| 667 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 676 | 668 | |
| 677 | 669 | priv_rx->stats->tls_del++; |
| 678 | 670 | if (priv_rx->rule.rule) |
| @@ -680,5 +672,9 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) · 1 unmodified line | ||
| 680 | 672 | |
| 681 | 673 | mlx5_core_destroy_tir(mdev, priv_rx->tirn); |
| 682 | 674 | mlx5_ktls_destroy_key(mdev, priv_rx->key_id); |
| 683 | − kfree(priv_rx); | |
| 675 | + /* priv_rx should normally be freed here, but if there is an outstanding | |
| 676 | + * GET_PSV, deallocation will be delayed until the CQE for GET_PSV is | |
| 677 | + * processed. | |
| 678 | + */ | |
| 679 | + mlx5e_ktls_priv_rx_put(priv_rx); | |
| 684 | 680 | } |
| @@ -536,7 +536,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev, · 535 unmodified lines | ||
| 536 | 536 | #define MLX5E_MAX_COAL_FRAMES MLX5_MAX_CQ_COUNT |
| 537 | 537 | |
| 538 | 538 | static void |
| 539 | −mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) | |
| 539 | +mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) | |
| 540 | 540 | { |
| 541 | 541 | struct mlx5_core_dev *mdev = priv->mdev; |
| 542 | 542 | int tc; |
| @@ -551,6 +551,17 @@ mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesc · 8 unmodified lines | ||
| 551 | 551 | coal->tx_coalesce_usecs, |
| 552 | 552 | coal->tx_max_coalesced_frames); |
| 553 | 553 | } |
| 554 | + } | |
| 555 | +} | |
| 556 | + | |
| 557 | +static void | |
| 558 | +mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) | |
| 559 | +{ | |
| 560 | + struct mlx5_core_dev *mdev = priv->mdev; | |
| 561 | + int i; | |
| 562 | + | |
| 563 | + for (i = 0; i < priv->channels.num; ++i) { | |
| 564 | + struct mlx5e_channel *c = priv->channels.c[i]; | |
| 554 | 565 | |
| 555 | 566 | mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq, |
| 556 | 567 | coal->rx_coalesce_usecs, |
| @@ -597,21 +608,9 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, · 40 unmodified lines | ||
| 597 | 608 | tx_moder->pkts = coal->tx_max_coalesced_frames; |
| 598 | 609 | new_channels.params.tx_dim_enabled = !!coal->use_adaptive_tx_coalesce; |
| 599 | 610 | |
| 600 | − if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { | |
| 601 | − priv->channels.params = new_channels.params; | |
| 602 | − goto out; | |
| 603 | − } | |
| 604 | − /* we are opened */ | |
| 605 | − | |
| 606 | 611 | reset_rx = !!coal->use_adaptive_rx_coalesce != priv->channels.params.rx_dim_enabled; |
| 607 | 612 | reset_tx = !!coal->use_adaptive_tx_coalesce != priv->channels.params.tx_dim_enabled; |
| 608 | 613 | |
| 609 | − if (!reset_rx && !reset_tx) { | |
| 610 | − mlx5e_set_priv_channels_coalesce(priv, coal); | |
| 611 | − priv->channels.params = new_channels.params; | |
| 612 | − goto out; | |
| 613 | − } | |
| 614 | − | |
| 615 | 614 | if (reset_rx) { |
| 616 | 615 | u8 mode = MLX5E_GET_PFLAG(&new_channels.params, |
| 617 | 616 | MLX5E_PFLAG_RX_CQE_BASED_MODER); |
| @@ -625,6 +624,20 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, · 7 unmodified lines | ||
| 625 | 624 | mlx5e_reset_tx_moderation(&new_channels.params, mode); |
| 626 | 625 | } |
| 627 | 626 | |
| 627 | + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { | |
| 628 | + priv->channels.params = new_channels.params; | |
| 629 | + goto out; | |
| 630 | + } | |
| 631 | + | |
| 632 | + if (!reset_rx && !reset_tx) { | |
| 633 | + if (!coal->use_adaptive_rx_coalesce) | |
| 634 | + mlx5e_set_priv_channels_rx_coalesce(priv, coal); | |
| 635 | + if (!coal->use_adaptive_tx_coalesce) | |
| 636 | + mlx5e_set_priv_channels_tx_coalesce(priv, coal); | |
| 637 | + priv->channels.params = new_channels.params; | |
| 638 | + goto out; | |
| 639 | + } | |
| 640 | + | |
| 628 | 641 | err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL); |
| 629 | 642 | |
| 630 | 643 | out: |
| @@ -67,6 +67,7 @@ · 66 unmodified lines | ||
| 67 | 67 | #include "en/ptp.h" |
| 68 | 68 | #include "qos.h" |
| 69 | 69 | #include "en/trap.h" |
| 70 | +#include "fpga/ipsec.h" | |
| 70 | 71 | |
| 71 | 72 | bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) |
| 72 | 73 | { |
| @@ -108,7 +109,7 @@ bool mlx5e_striding_rq_possible(struct mlx5_core_dev *mdev, · 35 unmodified lines | ||
| 108 | 109 | if (!mlx5e_check_fragmented_striding_rq_cap(mdev)) |
| 109 | 110 | return false; |
| 110 | 111 | |
| 111 | − if (MLX5_IPSEC_DEV(mdev)) | |
| 112 | + if (mlx5_fpga_is_ipsec_device(mdev)) | |
| 112 | 113 | return false; |
| 113 | 114 | |
| 114 | 115 | if (params->xdp_prog) { |
| @@ -947,7 +948,7 @@ void mlx5e_activate_rq(struct mlx5e_rq *rq) · 832 unmodified lines | ||
| 947 | 948 | void mlx5e_deactivate_rq(struct mlx5e_rq *rq) |
| 948 | 949 | { |
| 949 | 950 | clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state); |
| 950 | − synchronize_rcu(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ | |
| 951 | + synchronize_net(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ | |
| 951 | 952 | } |
| 952 | 953 | |
| 953 | 954 | void mlx5e_close_rq(struct mlx5e_rq *rq) |
| @@ -1401,7 +1402,7 @@ void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) · 447 unmodified lines | ||
| 1401 | 1402 | struct mlx5_wq_cyc *wq = &sq->wq; |
| 1402 | 1403 | |
| 1403 | 1404 | clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); |
| 1404 | − synchronize_rcu(); /* Sync with NAPI to prevent netif_tx_wake_queue. */ | |
| 1405 | + synchronize_net(); /* Sync with NAPI to prevent netif_tx_wake_queue. */ | |
| 1405 | 1406 | |
| 1406 | 1407 | mlx5e_tx_disable_queue(sq->txq); |
| 1407 | 1408 | |
| @@ -1476,7 +1477,7 @@ void mlx5e_activate_icosq(struct mlx5e_icosq *icosq) · 68 unmodified lines | ||
| 1476 | 1477 | void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq) |
| 1477 | 1478 | { |
| 1478 | 1479 | clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state); |
| 1479 | − synchronize_rcu(); /* Sync with NAPI. */ | |
| 1480 | + synchronize_net(); /* Sync with NAPI. */ | |
| 1480 | 1481 | } |
| 1481 | 1482 | |
| 1482 | 1483 | void mlx5e_close_icosq(struct mlx5e_icosq *sq) |
| @@ -1555,7 +1556,7 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq) · 72 unmodified lines | ||
| 1555 | 1556 | struct mlx5e_channel *c = sq->channel; |
| 1556 | 1557 | |
| 1557 | 1558 | clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); |
| 1558 | − synchronize_rcu(); /* Sync with NAPI. */ | |
| 1559 | + synchronize_net(); /* Sync with NAPI. */ | |
| 1559 | 1560 | |
| 1560 | 1561 | mlx5e_destroy_sq(c->mdev, sq->sqn); |
| 1561 | 1562 | mlx5e_free_xdpsq_descs(sq); |
| @@ -1879,12 +1880,12 @@ static int mlx5e_open_queues(struct mlx5e_channel *c, · 317 unmodified lines | ||
| 1879 | 1880 | |
| 1880 | 1881 | mlx5e_build_create_cq_param(&ccp, c); |
| 1881 | 1882 | |
| 1882 | − err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp, | |
| 1883 | + err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp, | |
| 1883 | 1884 | &c->async_icosq.cq); |
| 1884 | 1885 | if (err) |
| 1885 | 1886 | return err; |
| 1886 | 1887 | |
| 1887 | − err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp, | |
| 1888 | + err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp, | |
| 1888 | 1889 | &c->icosq.cq); |
| 1889 | 1890 | if (err) |
| 1890 | 1891 | goto err_close_async_icosq_cq; |
| @@ -2122,7 +2123,12 @@ static void mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev, · 231 unmodified lines | ||
| 2122 | 2123 | u32 buf_size = 0; |
| 2123 | 2124 | int i; |
| 2124 | 2125 | |
| 2126 | +<<<<<<< HEAD | |
| 2125 | 2127 | if (MLX5_IPSEC_DEV(mdev)) |
| 2128 | +======= | |
| 2129 | +#ifdef CONFIG_MLX5_EN_IPSEC | |
| 2130 | + if (mlx5_fpga_is_ipsec_device(mdev)) | |
| 2131 | +>>>>>>> 3af409ca278d4a8d50e91f9f7c4c33b175645cf3 | |
| 2126 | 2132 | byte_count += MLX5E_METADATA_ETHER_LEN; |
| 2127 | 2133 | |
| 2128 | 2134 | if (mlx5e_rx_is_linear_skb(params, xsk)) { |
| @@ -4590,8 +4596,9 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog) · 2461 unmodified lines | ||
| 4590 | 4596 | return -EINVAL; |
| 4591 | 4597 | } |
| 4592 | 4598 | |
| 4593 | − if (MLX5_IPSEC_DEV(priv->mdev)) { | |
| 4594 | − netdev_warn(netdev, "can't set XDP with IPSec offload\n"); | |
| 4599 | + if (mlx5_fpga_is_ipsec_device(priv->mdev)) { | |
| 4600 | + netdev_warn(netdev, | |
| 4601 | + "XDP is not available on Innova cards with IPsec support\n"); | |
| 4595 | 4602 | return -EINVAL; |
| 4596 | 4603 | } |
| 4597 | 4604 | |
| @@ -1783,8 +1783,8 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool · 1782 unmodified lines | ||
| 1783 | 1783 | rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe; |
| 1784 | 1784 | |
| 1785 | 1785 | rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe; |
| 1786 | − if (MLX5_IPSEC_DEV(mdev)) { | |
| 1787 | − netdev_err(netdev, "MPWQE RQ with IPSec offload not supported\n"); | |
| 1786 | + if (mlx5_fpga_is_ipsec_device(mdev)) { | |
| 1787 | + netdev_err(netdev, "MPWQE RQ with Innova IPSec offload not supported\n"); | |
| 1788 | 1788 | return -EINVAL; |
| 1789 | 1789 | } |
| 1790 | 1790 | if (!rq->handle_rx_cqe) { |
| @@ -4445,7 +4445,7 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate, · 4444 unmodified lines | ||
| 4445 | 4445 | */ |
| 4446 | 4446 | if (rate) { |
| 4447 | 4447 | rate = (rate * BITS_PER_BYTE) + 500000; |
| 4448 | − rate_mbps = max_t(u32, do_div(rate, 1000000), 1); | |
| 4448 | + rate_mbps = max_t(u64, do_div(rate, 1000000), 1); | |
| 4449 | 4449 | } |
| 4450 | 4450 | |
| 4451 | 4451 | err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps); |
| @@ -124,7 +124,7 @@ struct mlx5_fpga_ipsec { · 123 unmodified lines | ||
| 124 | 124 | struct ida halloc; |
| 125 | 125 | }; |
| 126 | 126 | |
| 127 | −static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) | |
| 127 | +bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) | |
| 128 | 128 | { |
| 129 | 129 | if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga)) |
| 130 | 130 | return false; |
| @@ -43,6 +43,7 @@ u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev); · 42 unmodified lines | ||
| 43 | 43 | const struct mlx5_flow_cmds * |
| 44 | 44 | mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type); |
| 45 | 45 | void mlx5_fpga_ipsec_build_fs_cmds(void); |
| 46 | +bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev); | |
| 46 | 47 | #else |
| 47 | 48 | static inline |
| 48 | 49 | const struct mlx5_accel_ipsec_ops *mlx5_fpga_ipsec_ops(struct mlx5_core_dev *mdev) |
| @@ -55,6 +56,7 @@ mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type) · 6 unmodified lines | ||
| 55 | 56 | } |
| 56 | 57 | |
| 57 | 58 | static inline void mlx5_fpga_ipsec_build_fs_cmds(void) {}; |
| 59 | +static inline bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) { return false; } | |
| 58 | 60 | |
| 59 | 61 | #endif /* CONFIG_MLX5_FPGA_IPSEC */ |
| 60 | 62 | #endif /* __MLX5_FPGA_IPSEC_H__ */ |
| @@ -190,6 +190,16 @@ static bool reset_fw_if_needed(struct mlx5_core_dev *dev) · 189 unmodified lines | ||
| 190 | 190 | return true; |
| 191 | 191 | } |
| 192 | 192 | |
| 193 | +static void enter_error_state(struct mlx5_core_dev *dev, bool force) | |
| 194 | +{ | |
| 195 | + if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */ | |
| 196 | + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; | |
| 197 | + mlx5_cmd_flush(dev); | |
| 198 | + } | |
| 199 | + | |
| 200 | + mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); | |
| 201 | +} | |
| 202 | + | |
| 193 | 203 | void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) |
| 194 | 204 | { |
| 195 | 205 | bool err_detected = false; |
| @@ -208,12 +218,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) · 12 unmodified lines | ||
| 208 | 218 | goto unlock; |
| 209 | 219 | } |
| 210 | 220 | |
| 211 | − if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */ | |
| 212 | − dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; | |
| 213 | − mlx5_cmd_flush(dev); | |
| 214 | − } | |
| 215 | − | |
| 216 | − mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); | |
| 221 | + enter_error_state(dev, force); | |
| 217 | 222 | unlock: |
| 218 | 223 | mutex_unlock(&dev->intf_state_mutex); |
| 219 | 224 | } |
| @@ -613,7 +618,7 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work) · 393 unmodified lines | ||
| 613 | 618 | priv = container_of(health, struct mlx5_priv, health); |
| 614 | 619 | dev = container_of(priv, struct mlx5_core_dev, priv); |
| 615 | 620 | |
| 616 | − mlx5_enter_error_state(dev, false); | |
| 621 | + enter_error_state(dev, false); | |
| 617 | 622 | if (IS_ERR_OR_NULL(health->fw_fatal_reporter)) { |
| 618 | 623 | if (mlx5_health_try_recover(dev)) |
| 619 | 624 | mlx5_core_err(dev, "health recovery failed\n"); |
| @@ -707,8 +712,9 @@ static void poll_health(struct timer_list *t) · 87 unmodified lines | ||
| 707 | 712 | mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error); |
| 708 | 713 | dev->priv.health.fatal_error = fatal_error; |
| 709 | 714 | print_health_info(dev); |
| 715 | + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; | |
| 710 | 716 | mlx5_trigger_health_work(dev); |
| 711 | − goto out; | |
| 717 | + return; | |
| 712 | 718 | } |
| 713 | 719 | |
| 714 | 720 | count = ioread32be(health->health_counter); |
| @@ -1445,7 +1445,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id) · 1444 unmodified lines | ||
| 1445 | 1445 | dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); |
| 1446 | 1446 | |
| 1447 | 1447 | pci_save_state(pdev); |
| 1448 | − devlink_reload_enable(devlink); | |
| 1448 | + if (!mlx5_core_is_mp_slave(dev)) | |
| 1449 | + devlink_reload_enable(devlink); | |
| 1449 | 1450 | return 0; |
| 1450 | 1451 | |
| 1451 | 1452 | err_load_one: |
| @@ -2230,6 +2230,31 @@ static void rtl_prepare_power_down(struct rtl8169_private *tp) · 2229 unmodified lines | ||
| 2230 | 2230 | phy_speed_down(tp->phydev, false); |
| 2231 | 2231 | rtl_wol_enable_rx(tp); |
| 2232 | 2232 | } |
| 2233 | + | |
| 2234 | + switch (tp->mac_version) { | |
| 2235 | + case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26: | |
| 2236 | + case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30: | |
| 2237 | + case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33: | |
| 2238 | + case RTL_GIGA_MAC_VER_37: | |
| 2239 | + case RTL_GIGA_MAC_VER_39: | |
| 2240 | + case RTL_GIGA_MAC_VER_43: | |
| 2241 | + case RTL_GIGA_MAC_VER_44: | |
| 2242 | + case RTL_GIGA_MAC_VER_45: | |
| 2243 | + case RTL_GIGA_MAC_VER_46: | |
| 2244 | + case RTL_GIGA_MAC_VER_47: | |
| 2245 | + case RTL_GIGA_MAC_VER_48: | |
| 2246 | + case RTL_GIGA_MAC_VER_50 ... RTL_GIGA_MAC_VER_63: | |
| 2247 | + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80); | |
| 2248 | + break; | |
| 2249 | + case RTL_GIGA_MAC_VER_40: | |
| 2250 | + case RTL_GIGA_MAC_VER_41: | |
| 2251 | + case RTL_GIGA_MAC_VER_49: | |
| 2252 | + rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000); | |
| 2253 | + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80); | |
| 2254 | + break; | |
| 2255 | + default: | |
| 2256 | + break; | |
| 2257 | + } | |
| 2233 | 2258 | } |
| 2234 | 2259 | |
| 2235 | 2260 | static void rtl_init_rxcfg(struct rtl8169_private *tp) |
| @@ -1862,6 +1862,18 @@ static int axienet_probe(struct platform_device *pdev) · 1861 unmodified lines | ||
| 1862 | 1862 | lp->options = XAE_OPTION_DEFAULTS; |
| 1863 | 1863 | lp->rx_bd_num = RX_BD_NUM_DEFAULT; |
| 1864 | 1864 | lp->tx_bd_num = TX_BD_NUM_DEFAULT; |
| 1865 | + | |
| 1866 | + lp->clk = devm_clk_get_optional(&pdev->dev, NULL); | |
| 1867 | + if (IS_ERR(lp->clk)) { | |
| 1868 | + ret = PTR_ERR(lp->clk); | |
| 1869 | + goto free_netdev; | |
| 1870 | + } | |
| 1871 | + ret = clk_prepare_enable(lp->clk); | |
| 1872 | + if (ret) { | |
| 1873 | + dev_err(&pdev->dev, "Unable to enable clock: %d\n", ret); | |
| 1874 | + goto free_netdev; | |
| 1875 | + } | |
| 1876 | + | |
| 1865 | 1877 | /* Map device registers */ |
| 1866 | 1878 | ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1867 | 1879 | lp->regs = devm_ioremap_resource(&pdev->dev, ethres); |
| @@ -2046,20 +2058,6 @@ static int axienet_probe(struct platform_device *pdev) · 178 unmodified lines | ||
| 2046 | 2058 | |
| 2047 | 2059 | lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); |
| 2048 | 2060 | if (lp->phy_node) { |
| 2049 | − lp->clk = devm_clk_get(&pdev->dev, NULL); | |
| 2050 | − if (IS_ERR(lp->clk)) { | |
| 2051 | − dev_warn(&pdev->dev, "Failed to get clock: %ld\n", | |
| 2052 | − PTR_ERR(lp->clk)); | |
| 2053 | − lp->clk = NULL; | |
| 2054 | − } else { | |
| 2055 | − ret = clk_prepare_enable(lp->clk); | |
| 2056 | − if (ret) { | |
| 2057 | − dev_err(&pdev->dev, "Unable to enable clock: %d\n", | |
| 2058 | − ret); | |
| 2059 | − goto free_netdev; | |
| 2060 | − } | |
| 2061 | − } | |
| 2062 | − | |
| 2063 | 2061 | ret = axienet_mdio_setup(lp); |
| 2064 | 2062 | if (ret) |
| 2065 | 2063 | dev_warn(&pdev->dev, |
| @@ -580,10 +580,10 @@ ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data) · 579 unmodified lines | ||
| 580 | 580 | return -EINVAL; |
| 581 | 581 | |
| 582 | 582 | for (i = 0; i < data->resource_src_count; i++) |
| 583 | − ipa_resource_config_src(ipa, data->resource_src); | |
| 583 | + ipa_resource_config_src(ipa, &data->resource_src[i]); | |
| 584 | 584 | |
| 585 | 585 | for (i = 0; i < data->resource_dst_count; i++) |
| 586 | − ipa_resource_config_dst(ipa, data->resource_dst); | |
| 586 | + ipa_resource_config_dst(ipa, &data->resource_dst[i]); | |
| 587 | 587 | |
| 588 | 588 | return 0; |
| 589 | 589 | } |
| @@ -300,50 +300,22 @@ static int mdio_bus_phy_resume(struct device *dev) · 299 unmodified lines | ||
| 300 | 300 | |
| 301 | 301 | phydev->suspended_by_mdio_bus = 0; |
| 302 | 302 | |
| 303 | − ret = phy_resume(phydev); | |
| 303 | + ret = phy_init_hw(phydev); | |
| 304 | 304 | if (ret < 0) |
| 305 | 305 | return ret; |
| 306 | 306 | |
| 307 | −no_resume: | |
| 308 | − if (phydev->attached_dev && phydev->adjust_link) | |
| 309 | − phy_start_machine(phydev); | |
| 310 | − | |
| 311 | − return 0; | |
| 312 | −} | |
| 313 | − | |
| 314 | −static int mdio_bus_phy_restore(struct device *dev) | |
| 315 | −{ | |
| 316 | − struct phy_device *phydev = to_phy_device(dev); | |
| 317 | − struct net_device *netdev = phydev->attached_dev; | |
| 318 | − int ret; | |
| 319 | − | |
| 320 | − if (!netdev) | |
| 321 | − return 0; | |
| 322 | − | |
| 323 | − ret = phy_init_hw(phydev); | |
| 307 | + ret = phy_resume(phydev); | |
| 324 | 308 | if (ret < 0) |
| 325 | 309 | return ret; |
| 326 | − | |
| 310 | +no_resume: | |
| 327 | 311 | if (phydev->attached_dev && phydev->adjust_link) |
| 328 | 312 | phy_start_machine(phydev); |
| 329 | 313 | |
| 330 | 314 | return 0; |
| 331 | 315 | } |
| 332 | 316 | |
| 333 | −static const struct dev_pm_ops mdio_bus_phy_pm_ops = { | |
| 334 | − .suspend = mdio_bus_phy_suspend, | |
| 335 | − .resume = mdio_bus_phy_resume, | |
| 336 | − .freeze = mdio_bus_phy_suspend, | |
| 337 | − .thaw = mdio_bus_phy_resume, | |
| 338 | − .restore = mdio_bus_phy_restore, | |
| 339 | −}; | |
| 340 | − | |
| 341 | −#define MDIO_BUS_PHY_PM_OPS (&mdio_bus_phy_pm_ops) | |
| 342 | − | |
| 343 | −#else | |
| 344 | − | |
| 345 | −#define MDIO_BUS_PHY_PM_OPS NULL | |
| 346 | − | |
| 317 | +static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend, | |
| 318 | + mdio_bus_phy_resume); | |
| 347 | 319 | #endif /* CONFIG_PM */ |
| 348 | 320 | |
| 349 | 321 | /** |
| @@ -554,7 +526,7 @@ static const struct device_type mdio_bus_phy_type = { · 204 unmodified lines | ||
| 554 | 526 | .name = "PHY", |
| 555 | 527 | .groups = phy_dev_groups, |
| 556 | 528 | .release = phy_device_release, |
| 557 | − .pm = MDIO_BUS_PHY_PM_OPS, | |
| 529 | + .pm = pm_ptr(&mdio_bus_phy_pm_ops), | |
| 558 | 530 | }; |
| 559 | 531 | |
| 560 | 532 | static int phy_request_driver_module(struct phy_device *dev, u32 phy_id) |
| @@ -1144,10 +1116,19 @@ int phy_init_hw(struct phy_device *phydev) · 583 unmodified lines | ||
| 1144 | 1116 | if (ret < 0) |
| 1145 | 1117 | return ret; |
| 1146 | 1118 | |
| 1147 | − if (phydev->drv->config_init) | |
| 1119 | + if (phydev->drv->config_init) { | |
| 1148 | 1120 | ret = phydev->drv->config_init(phydev); |
| 1121 | + if (ret < 0) | |
| 1122 | + return ret; | |
| 1123 | + } | |
| 1149 | 1124 | |
| 1150 | − return ret; | |
| 1125 | + if (phydev->drv->config_intr) { | |
| 1126 | + ret = phydev->drv->config_intr(phydev); | |
| 1127 | + if (ret < 0) | |
| 1128 | + return ret; | |
| 1129 | + } | |
| 1130 | + | |
| 1131 | + return 0; | |
| 1151 | 1132 | } |
| 1152 | 1133 | EXPORT_SYMBOL(phy_init_hw); |
| 1153 | 1134 | |
| @@ -854,7 +854,7 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 853 unmodified lines | ||
| 854 | 854 | spin_lock_init(&sc->lmc_lock); |
| 855 | 855 | pci_set_master(pdev); |
| 856 | 856 | |
| 857 | − printk(KERN_INFO "%s: detected at %lx, irq %d\n", dev->name, | |
| 857 | + printk(KERN_INFO "hdlc: detected at %lx, irq %d\n", | |
| 858 | 858 | dev->base_addr, dev->irq); |
| 859 | 859 | |
| 860 | 860 | err = register_hdlc_device(dev); |
| @@ -899,6 +899,8 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 38 unmodified lines | ||
| 899 | 899 | break; |
| 900 | 900 | default: |
| 901 | 901 | printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name); |
| 902 | + unregister_hdlc_device(dev); | |
| 903 | + return -EIO; | |
| 902 | 904 | break; |
| 903 | 905 | } |
| 904 | 906 | |
| @@ -5311,7 +5311,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) · 5310 unmodified lines | ||
| 5311 | 5311 | |
| 5312 | 5312 | for (i = 0; i < 4; i++) { |
| 5313 | 5313 | if (dev->phy.rev >= 3) |
| 5314 | − table[i] = coef[i]; | |
| 5314 | + coef[i] = table[i]; | |
| 5315 | 5315 | else |
| 5316 | 5316 | coef[i] = 0; |
| 5317 | 5317 | } |
| @@ -86,8 +86,7 @@ static int cxgbit_is_ofld_imm(const struct sk_buff *skb) · 85 unmodified lines | ||
| 86 | 86 | if (likely(cxgbit_skcb_flags(skb) & SKCBF_TX_ISO)) |
| 87 | 87 | length += sizeof(struct cpl_tx_data_iso); |
| 88 | 88 | |
| 89 | −#define MAX_IMM_TX_PKT_LEN 256 | |
| 90 | − return length <= MAX_IMM_TX_PKT_LEN; | |
| 89 | + return length <= MAX_IMM_OFLD_TX_DATA_WR_LEN; | |
| 91 | 90 | } |
| 92 | 91 | |
| 93 | 92 | /* |
| @@ -207,7 +207,7 @@ struct atm_skb_data { · 206 unmodified lines | ||
| 207 | 207 | struct atm_vcc *vcc; /* ATM VCC */ |
| 208 | 208 | unsigned long atm_options; /* ATM layer options */ |
| 209 | 209 | unsigned int acct_truesize; /* truesize accounted to vcc */ |
| 210 | −}; | |
| 210 | +} __packed; | |
| 211 | 211 | |
| 212 | 212 | #define VCC_HTABLE_SIZE 32 |
| 213 | 213 | |
| @@ -166,6 +166,7 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index, · 165 unmodified lines | ||
| 166 | 166 | struct nlattr *est, struct tc_action **a, |
| 167 | 167 | const struct tc_action_ops *ops, int bind, |
| 168 | 168 | u32 flags); |
| 169 | +void tcf_idr_insert_many(struct tc_action *actions[]); | |
| 169 | 170 | void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); |
| 170 | 171 | int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, |
| 171 | 172 | struct tc_action **a, int bind); |
| @@ -593,6 +593,7 @@ enum { · 592 unmodified lines | ||
| 593 | 593 | TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */ |
| 594 | 594 | TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */ |
| 595 | 595 | TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */ |
| 596 | + __TCA_FLOWER_KEY_CT_FLAGS_MAX, | |
| 596 | 597 | }; |
| 597 | 598 | |
| 598 | 599 | enum { |
| @@ -11563,7 +11563,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) · 11562 unmodified lines | ||
| 11563 | 11563 | bool isdiv = BPF_OP(insn->code) == BPF_DIV; |
| 11564 | 11564 | struct bpf_insn *patchlet; |
| 11565 | 11565 | struct bpf_insn chk_and_div[] = { |
| 11566 | − /* Rx div 0 -> 0 */ | |
| 11566 | + /* [R,W]x div 0 -> 0 */ | |
| 11567 | 11567 | BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) | |
| 11568 | 11568 | BPF_JNE | BPF_K, insn->src_reg, |
| 11569 | 11569 | 0, 2, 0), |
| @@ -11572,16 +11572,18 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) · 2 unmodified lines | ||
| 11572 | 11572 | *insn, |
| 11573 | 11573 | }; |
| 11574 | 11574 | struct bpf_insn chk_and_mod[] = { |
| 11575 | − /* Rx mod 0 -> Rx */ | |
| 11575 | + /* [R,W]x mod 0 -> [R,W]x */ | |
| 11576 | 11576 | BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) | |
| 11577 | 11577 | BPF_JEQ | BPF_K, insn->src_reg, |
| 11578 | − 0, 1, 0), | |
| 11578 | + 0, 1 + (is64 ? 0 : 1), 0), | |
| 11579 | 11579 | *insn, |
| 11580 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 11581 | + BPF_MOV32_REG(insn->dst_reg, insn->dst_reg), | |
| 11580 | 11582 | }; |
| 11581 | 11583 | |
| 11582 | 11584 | patchlet = isdiv ? chk_and_div : chk_and_mod; |
| 11583 | 11585 | cnt = isdiv ? ARRAY_SIZE(chk_and_div) : |
| 11584 | − ARRAY_SIZE(chk_and_mod); | |
| 11586 | + ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0); | |
| 11585 | 11587 | |
| 11586 | 11588 | new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt); |
| 11587 | 11589 | if (!new_prog) |
| @@ -1577,8 +1577,8 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) · 1576 unmodified lines | ||
| 1577 | 1577 | struct sk_buff *skb; |
| 1578 | 1578 | struct net_device *dev; |
| 1579 | 1579 | struct ddpehdr *ddp; |
| 1580 | − int size; | |
| 1581 | − struct atalk_route *rt; | |
| 1580 | + int size, hard_header_len; | |
| 1581 | + struct atalk_route *rt, *rt_lo = NULL; | |
| 1582 | 1582 | int err; |
| 1583 | 1583 | |
| 1584 | 1584 | if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
| @@ -1641,7 +1641,22 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) · 56 unmodified lines | ||
| 1641 | 1641 | SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", |
| 1642 | 1642 | sk, size, dev->name); |
| 1643 | 1643 | |
| 1644 | − size += dev->hard_header_len; | |
| 1644 | + hard_header_len = dev->hard_header_len; | |
| 1645 | + /* Leave room for loopback hardware header if necessary */ | |
| 1646 | + if (usat->sat_addr.s_node == ATADDR_BCAST && | |
| 1647 | + (dev->flags & IFF_LOOPBACK || !(rt->flags & RTF_GATEWAY))) { | |
| 1648 | + struct atalk_addr at_lo; | |
| 1649 | + | |
| 1650 | + at_lo.s_node = 0; | |
| 1651 | + at_lo.s_net = 0; | |
| 1652 | + | |
| 1653 | + rt_lo = atrtr_find(&at_lo); | |
| 1654 | + | |
| 1655 | + if (rt_lo && rt_lo->dev->hard_header_len > hard_header_len) | |
| 1656 | + hard_header_len = rt_lo->dev->hard_header_len; | |
| 1657 | + } | |
| 1658 | + | |
| 1659 | + size += hard_header_len; | |
| 1645 | 1660 | release_sock(sk); |
| 1646 | 1661 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); |
| 1647 | 1662 | lock_sock(sk); |
| @@ -1649,7 +1664,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) · 1 unmodified line | ||
| 1649 | 1664 | goto out; |
| 1650 | 1665 | |
| 1651 | 1666 | skb_reserve(skb, ddp_dl->header_length); |
| 1652 | − skb_reserve(skb, dev->hard_header_len); | |
| 1667 | + skb_reserve(skb, hard_header_len); | |
| 1653 | 1668 | skb->dev = dev; |
| 1654 | 1669 | |
| 1655 | 1670 | SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); |
| @@ -1700,18 +1715,12 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) · 44 unmodified lines | ||
| 1700 | 1715 | /* loop back */ |
| 1701 | 1716 | skb_orphan(skb); |
| 1702 | 1717 | if (ddp->deh_dnode == ATADDR_BCAST) { |
| 1703 | − struct atalk_addr at_lo; | |
| 1704 | − | |
| 1705 | − at_lo.s_node = 0; | |
| 1706 | − at_lo.s_net = 0; | |
| 1707 | − | |
| 1708 | − rt = atrtr_find(&at_lo); | |
| 1709 | − if (!rt) { | |
| 1718 | + if (!rt_lo) { | |
| 1710 | 1719 | kfree_skb(skb); |
| 1711 | 1720 | err = -ENETUNREACH; |
| 1712 | 1721 | goto out; |
| 1713 | 1722 | } |
| 1714 | − dev = rt->dev; | |
| 1723 | + dev = rt_lo->dev; | |
| 1715 | 1724 | skb->dev = dev; |
| 1716 | 1725 | } |
| 1717 | 1726 | ddp_dl->request(ddp_dl, skb, dev->dev_addr); |
| @@ -115,10 +115,7 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) · 114 unmodified lines | ||
| 115 | 115 | else |
| 116 | 116 | skb->ip_summed = CHECKSUM_NONE; |
| 117 | 117 | |
| 118 | − if (in_interrupt()) | |
| 119 | − netif_rx(skb); | |
| 120 | − else | |
| 121 | − netif_rx_ni(skb); | |
| 118 | + netif_rx_any_context(skb); | |
| 122 | 119 | |
| 123 | 120 | /* Update statistics. */ |
| 124 | 121 | priv->netdev->stats.rx_packets++; |
| @@ -1056,6 +1056,9 @@ proto_again: · 1055 unmodified lines | ||
| 1056 | 1056 | key_control->addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; |
| 1057 | 1057 | } |
| 1058 | 1058 | |
| 1059 | + __skb_flow_dissect_ipv4(skb, flow_dissector, | |
| 1060 | + target_container, data, iph); | |
| 1061 | + | |
| 1059 | 1062 | if (ip_is_fragment(iph)) { |
| 1060 | 1063 | key_control->flags |= FLOW_DIS_IS_FRAGMENT; |
| 1061 | 1064 | |
| @@ -1072,9 +1075,6 @@ proto_again: · 10 unmodified lines | ||
| 1072 | 1075 | } |
| 1073 | 1076 | } |
| 1074 | 1077 | |
| 1075 | − __skb_flow_dissect_ipv4(skb, flow_dissector, | |
| 1076 | − target_container, data, iph); | |
| 1077 | − | |
| 1078 | 1078 | break; |
| 1079 | 1079 | } |
| 1080 | 1080 | case htons(ETH_P_IPV6): { |
| @@ -508,8 +508,8 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, · 507 unmodified lines | ||
| 508 | 508 | { |
| 509 | 509 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); |
| 510 | 510 | struct mptcp_sock *msk = mptcp_sk(subflow->conn); |
| 511 | + u64 snd_data_fin_enable, ack_seq; | |
| 511 | 512 | unsigned int dss_size = 0; |
| 512 | − u64 snd_data_fin_enable; | |
| 513 | 513 | struct mptcp_ext *mpext; |
| 514 | 514 | unsigned int ack_size; |
| 515 | 515 | bool ret = false; |
| @@ -541,13 +541,14 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, · 25 unmodified lines | ||
| 541 | 541 | return ret; |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | + ack_seq = READ_ONCE(msk->ack_seq); | |
| 544 | 545 | if (READ_ONCE(msk->use_64bit_ack)) { |
| 545 | 546 | ack_size = TCPOLEN_MPTCP_DSS_ACK64; |
| 546 | − opts->ext_copy.data_ack = READ_ONCE(msk->ack_seq); | |
| 547 | + opts->ext_copy.data_ack = ack_seq; | |
| 547 | 548 | opts->ext_copy.ack64 = 1; |
| 548 | 549 | } else { |
| 549 | 550 | ack_size = TCPOLEN_MPTCP_DSS_ACK32; |
| 550 | − opts->ext_copy.data_ack32 = (uint32_t)READ_ONCE(msk->ack_seq); | |
| 551 | + opts->ext_copy.data_ack32 = (uint32_t)ack_seq; | |
| 551 | 552 | opts->ext_copy.ack64 = 0; |
| 552 | 553 | } |
| 553 | 554 | opts->ext_copy.use_ack = 1; |
| @@ -918,8 +919,7 @@ static void ack_update_msk(struct mptcp_sock *msk, · 364 unmodified lines | ||
| 918 | 919 | msk->wnd_end = new_wnd_end; |
| 919 | 920 | |
| 920 | 921 | /* this assumes mptcp_incoming_options() is invoked after tcp_ack() */ |
| 921 | − if (after64(msk->wnd_end, READ_ONCE(msk->snd_nxt)) && | |
| 922 | − sk_stream_memory_free(ssk)) | |
| 922 | + if (after64(msk->wnd_end, READ_ONCE(msk->snd_nxt))) | |
| 923 | 923 | __mptcp_check_push(sk, ssk); |
| 924 | 924 | |
| 925 | 925 | if (after64(new_snd_una, old_snd_una)) { |
| @@ -363,8 +363,6 @@ static void mptcp_check_data_fin_ack(struct sock *sk) · 362 unmodified lines | ||
| 363 | 363 | |
| 364 | 364 | /* Look for an acknowledged DATA_FIN */ |
| 365 | 365 | if (mptcp_pending_data_fin_ack(sk)) { |
| 366 | − mptcp_stop_timer(sk); | |
| 367 | − | |
| 368 | 366 | WRITE_ONCE(msk->snd_data_fin_enable, 0); |
| 369 | 367 | |
| 370 | 368 | switch (sk->sk_state) { |
| @@ -458,7 +456,18 @@ static bool mptcp_subflow_cleanup_rbuf(struct sock *ssk) · 87 unmodified lines | ||
| 458 | 456 | static void mptcp_cleanup_rbuf(struct mptcp_sock *msk) |
| 459 | 457 | { |
| 460 | 458 | struct sock *ack_hint = READ_ONCE(msk->ack_hint); |
| 459 | + int old_space = READ_ONCE(msk->old_wspace); | |
| 461 | 460 | struct mptcp_subflow_context *subflow; |
| 461 | + struct sock *sk = (struct sock *)msk; | |
| 462 | + bool cleanup; | |
| 463 | + | |
| 464 | + /* this is a simple superset of what tcp_cleanup_rbuf() implements | |
| 465 | + * so that we don't have to acquire the ssk socket lock most of the time | |
| 466 | + * to do actually nothing | |
| 467 | + */ | |
| 468 | + cleanup = __mptcp_space(sk) - old_space >= max(0, old_space); | |
| 469 | + if (!cleanup) | |
| 470 | + return; | |
| 462 | 471 | |
| 463 | 472 | /* if the hinted ssk is still active, try to use it */ |
| 464 | 473 | if (likely(ack_hint)) { |
| @@ -1565,6 +1574,9 @@ out: · 1100 unmodified lines | ||
| 1565 | 1574 | mptcp_set_timeout(sk, ssk); |
| 1566 | 1575 | tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle, |
| 1567 | 1576 | info.size_goal); |
| 1577 | + if (!mptcp_timer_pending(sk)) | |
| 1578 | + mptcp_reset_timer(sk); | |
| 1579 | + | |
| 1568 | 1580 | if (msk->snd_data_fin_enable && |
| 1569 | 1581 | msk->snd_nxt + 1 == msk->write_seq) |
| 1570 | 1582 | mptcp_schedule_work(sk); |
| @@ -1868,7 +1880,7 @@ static void __mptcp_splice_receive_queue(struct sock *sk) · 297 unmodified lines | ||
| 1868 | 1880 | skb_queue_splice_tail_init(&sk->sk_receive_queue, &msk->receive_queue); |
| 1869 | 1881 | } |
| 1870 | 1882 | |
| 1871 | −static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv) | |
| 1883 | +static bool __mptcp_move_skbs(struct mptcp_sock *msk) | |
| 1872 | 1884 | { |
| 1873 | 1885 | struct sock *sk = (struct sock *)msk; |
| 1874 | 1886 | unsigned int moved = 0; |
| @@ -1888,13 +1900,10 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv) · 13 unmodified lines | ||
| 1888 | 1900 | |
| 1889 | 1901 | slowpath = lock_sock_fast(ssk); |
| 1890 | 1902 | mptcp_data_lock(sk); |
| 1903 | + __mptcp_update_rmem(sk); | |
| 1891 | 1904 | done = __mptcp_move_skbs_from_subflow(msk, ssk, &moved); |
| 1892 | 1905 | mptcp_data_unlock(sk); |
| 1893 | − if (moved && rcv) { | |
| 1894 | − WRITE_ONCE(msk->rmem_pending, min(rcv, moved)); | |
| 1895 | − tcp_cleanup_rbuf(ssk, 1); | |
| 1896 | − WRITE_ONCE(msk->rmem_pending, 0); | |
| 1897 | − } | |
| 1906 | + tcp_cleanup_rbuf(ssk, moved); | |
| 1898 | 1907 | unlock_sock_fast(ssk, slowpath); |
| 1899 | 1908 | } while (!done); |
| 1900 | 1909 | |
| @@ -1907,6 +1916,7 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv) · 6 unmodified lines | ||
| 1907 | 1916 | ret |= __mptcp_ofo_queue(msk); |
| 1908 | 1917 | __mptcp_splice_receive_queue(sk); |
| 1909 | 1918 | mptcp_data_unlock(sk); |
| 1919 | + mptcp_cleanup_rbuf(msk); | |
| 1910 | 1920 | } |
| 1911 | 1921 | if (ret) |
| 1912 | 1922 | mptcp_check_data_fin((struct sock *)msk); |
| @@ -1936,7 +1946,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, · 23 unmodified lines | ||
| 1936 | 1946 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); |
| 1937 | 1947 | |
| 1938 | 1948 | while (copied < len) { |
| 1939 | − int bytes_read, old_space; | |
| 1949 | + int bytes_read; | |
| 1940 | 1950 | |
| 1941 | 1951 | bytes_read = __mptcp_recvmsg_mskq(msk, msg, len - copied); |
| 1942 | 1952 | if (unlikely(bytes_read < 0)) { |
| @@ -1947,14 +1957,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, · 4 unmodified lines | ||
| 1947 | 1957 | |
| 1948 | 1958 | copied += bytes_read; |
| 1949 | 1959 | |
| 1950 | − if (skb_queue_empty(&msk->receive_queue) && | |
| 1951 | − __mptcp_move_skbs(msk, len - copied)) | |
| 1952 | − continue; | |
| 1953 | − | |
| 1954 | 1960 | /* be sure to advertise window change */ |
| 1955 | − old_space = READ_ONCE(msk->old_wspace); | |
| 1956 | − if ((tcp_space(sk) - old_space) >= old_space) | |
| 1957 | − mptcp_cleanup_rbuf(msk); | |
| 1961 | + mptcp_cleanup_rbuf(msk); | |
| 1962 | + | |
| 1963 | + if (skb_queue_empty(&msk->receive_queue) && __mptcp_move_skbs(msk)) | |
| 1964 | + continue; | |
| 1958 | 1965 | |
| 1959 | 1966 | /* only the master socket status is relevant here. The exit |
| 1960 | 1967 | * conditions mirror closely tcp_recvmsg() |
| @@ -1982,7 +1989,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, · 21 unmodified lines | ||
| 1982 | 1989 | /* race breaker: the shutdown could be after the |
| 1983 | 1990 | * previous receive queue check |
| 1984 | 1991 | */ |
| 1985 | − if (__mptcp_move_skbs(msk, len - copied)) | |
| 1992 | + if (__mptcp_move_skbs(msk)) | |
| 1986 | 1993 | continue; |
| 1987 | 1994 | break; |
| 1988 | 1995 | } |
| @@ -2015,7 +2022,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, · 26 unmodified lines | ||
| 2015 | 2022 | /* .. race-breaker: ssk might have gotten new data |
| 2016 | 2023 | * after last __mptcp_move_skbs() returned false. |
| 2017 | 2024 | */ |
| 2018 | − if (unlikely(__mptcp_move_skbs(msk, 0))) | |
| 2025 | + if (unlikely(__mptcp_move_skbs(msk))) | |
| 2019 | 2026 | set_bit(MPTCP_DATA_READY, &msk->flags); |
| 2020 | 2027 | } else if (unlikely(!test_bit(MPTCP_DATA_READY, &msk->flags))) { |
| 2021 | 2028 | /* data to read but mptcp_wait_data() cleared DATA_READY */ |
| @@ -2275,6 +2282,7 @@ static void mptcp_worker(struct work_struct *work) · 253 unmodified lines | ||
| 2275 | 2282 | if (!test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) |
| 2276 | 2283 | goto unlock; |
| 2277 | 2284 | |
| 2285 | + __mptcp_clean_una(sk); | |
| 2278 | 2286 | dfrag = mptcp_rtx_head(sk); |
| 2279 | 2287 | if (!dfrag) |
| 2280 | 2288 | goto unlock; |
| @@ -2943,6 +2951,8 @@ static void mptcp_release_cb(struct sock *sk) · 662 unmodified lines | ||
| 2943 | 2951 | mptcp_push_pending(sk, 0); |
| 2944 | 2952 | spin_lock_bh(&sk->sk_lock.slock); |
| 2945 | 2953 | } |
| 2954 | + if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags)) | |
| 2955 | + __mptcp_error_report(sk); | |
| 2946 | 2956 | |
| 2947 | 2957 | /* clear any wmem reservation and errors */ |
| 2948 | 2958 | __mptcp_update_wmem(sk); |
| @@ -3319,7 +3329,7 @@ static __poll_t mptcp_check_writeable(struct mptcp_sock *msk) · 370 unmodified lines | ||
| 3319 | 3329 | struct sock *sk = (struct sock *)msk; |
| 3320 | 3330 | |
| 3321 | 3331 | if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) |
| 3322 | − return 0; | |
| 3332 | + return EPOLLOUT | EPOLLWRNORM; | |
| 3323 | 3333 | |
| 3324 | 3334 | if (sk_stream_is_writeable(sk)) |
| 3325 | 3335 | return EPOLLOUT | EPOLLWRNORM; |
| @@ -3352,9 +3362,16 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, · 26 unmodified lines | ||
| 3352 | 3362 | mask |= mptcp_check_readable(msk); |
| 3353 | 3363 | mask |= mptcp_check_writeable(msk); |
| 3354 | 3364 | } |
| 3365 | + if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE) | |
| 3366 | + mask |= EPOLLHUP; | |
| 3355 | 3367 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
| 3356 | 3368 | mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; |
| 3357 | 3369 | |
| 3370 | + /* This barrier is coupled with smp_wmb() in tcp_reset() */ | |
| 3371 | + smp_rmb(); | |
| 3372 | + if (sk->sk_err) | |
| 3373 | + mask |= EPOLLERR; | |
| 3374 | + | |
| 3358 | 3375 | return mask; |
| 3359 | 3376 | } |
| 3360 | 3377 | |
| @@ -102,6 +102,7 @@ · 101 unmodified lines | ||
| 102 | 102 | #define MPTCP_WORK_CLOSE_SUBFLOW 5 |
| 103 | 103 | #define MPTCP_PUSH_PENDING 6 |
| 104 | 104 | #define MPTCP_CLEAN_UNA 7 |
| 105 | +#define MPTCP_ERROR_REPORT 8 | |
| 105 | 106 | |
| 106 | 107 | static inline bool before64(__u64 seq1, __u64 seq2) |
| 107 | 108 | { |
| @@ -237,7 +238,6 @@ struct mptcp_sock { · 129 unmodified lines | ||
| 237 | 238 | u64 wnd_end; |
| 238 | 239 | unsigned long timer_ival; |
| 239 | 240 | u32 token; |
| 240 | − int rmem_pending; | |
| 241 | 241 | int rmem_released; |
| 242 | 242 | unsigned long flags; |
| 243 | 243 | bool can_ack; |
| @@ -301,7 +301,7 @@ static inline struct mptcp_sock *mptcp_sk(const struct sock *sk) · 57 unmodified lines | ||
| 301 | 301 | |
| 302 | 302 | static inline int __mptcp_space(const struct sock *sk) |
| 303 | 303 | { |
| 304 | − return tcp_space(sk) + READ_ONCE(mptcp_sk(sk)->rmem_pending); | |
| 304 | + return tcp_space(sk) + READ_ONCE(mptcp_sk(sk)->rmem_released); | |
| 305 | 305 | } |
| 306 | 306 | |
| 307 | 307 | static inline struct mptcp_data_frag *mptcp_send_head(const struct sock *sk) |
| @@ -334,20 +334,13 @@ static inline struct mptcp_data_frag *mptcp_pending_tail(const struct sock *sk) · 26 unmodified lines | ||
| 334 | 334 | return list_last_entry(&msk->rtx_queue, struct mptcp_data_frag, list); |
| 335 | 335 | } |
| 336 | 336 | |
| 337 | −static inline struct mptcp_data_frag *mptcp_rtx_tail(const struct sock *sk) | |
| 337 | +static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk) | |
| 338 | 338 | { |
| 339 | 339 | struct mptcp_sock *msk = mptcp_sk(sk); |
| 340 | 340 | |
| 341 | − if (!before64(msk->snd_nxt, READ_ONCE(msk->snd_una))) | |
| 341 | + if (msk->snd_una == READ_ONCE(msk->snd_nxt)) | |
| 342 | 342 | return NULL; |
| 343 | 343 | |
| 344 | − return list_last_entry(&msk->rtx_queue, struct mptcp_data_frag, list); | |
| 345 | −} | |
| 346 | − | |
| 347 | −static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk) | |
| 348 | −{ | |
| 349 | − struct mptcp_sock *msk = mptcp_sk(sk); | |
| 350 | − | |
| 351 | 344 | return list_first_entry_or_null(&msk->rtx_queue, struct mptcp_data_frag, list); |
| 352 | 345 | } |
| 353 | 346 | |
| @@ -436,6 +429,7 @@ struct mptcp_subflow_context { · 82 unmodified lines | ||
| 436 | 429 | void (*tcp_data_ready)(struct sock *sk); |
| 437 | 430 | void (*tcp_state_change)(struct sock *sk); |
| 438 | 431 | void (*tcp_write_space)(struct sock *sk); |
| 432 | + void (*tcp_error_report)(struct sock *sk); | |
| 439 | 433 | |
| 440 | 434 | struct rcu_head rcu; |
| 441 | 435 | }; |
| @@ -560,6 +554,7 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk, · 118 unmodified lines | ||
| 560 | 554 | sk->sk_data_ready = ctx->tcp_data_ready; |
| 561 | 555 | sk->sk_state_change = ctx->tcp_state_change; |
| 562 | 556 | sk->sk_write_space = ctx->tcp_write_space; |
| 557 | + sk->sk_error_report = ctx->tcp_error_report; | |
| 563 | 558 | |
| 564 | 559 | inet_csk(sk)->icsk_af_ops = ctx->icsk_af_ops; |
| 565 | 560 | } |
| @@ -587,6 +582,7 @@ bool mptcp_finish_join(struct sock *sk); · 21 unmodified lines | ||
| 587 | 582 | bool mptcp_schedule_work(struct sock *sk); |
| 588 | 583 | void __mptcp_check_push(struct sock *sk, struct sock *ssk); |
| 589 | 584 | void __mptcp_data_acked(struct sock *sk); |
| 585 | +void __mptcp_error_report(struct sock *sk); | |
| 590 | 586 | void mptcp_subflow_eof(struct sock *sk); |
| 591 | 587 | bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit); |
| 592 | 588 | void __mptcp_flush_join_list(struct mptcp_sock *msk); |
| @@ -100,7 +100,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) · 99 unmodified lines | ||
| 100 | 100 | return msk; |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −static int __subflow_init_req(struct request_sock *req, const struct sock *sk_listener) | |
| 103 | +static void subflow_init_req(struct request_sock *req, const struct sock *sk_listener) | |
| 104 | 104 | { |
| 105 | 105 | struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); |
| 106 | 106 | |
| @@ -108,16 +108,6 @@ static int __subflow_init_req(struct request_sock *req, const struct sock *sk_li · 1 unmodified line | ||
| 108 | 108 | subflow_req->mp_join = 0; |
| 109 | 109 | subflow_req->msk = NULL; |
| 110 | 110 | mptcp_token_init_request(req); |
| 111 | − | |
| 112 | −#ifdef CONFIG_TCP_MD5SIG | |
| 113 | − /* no MPTCP if MD5SIG is enabled on this socket or we may run out of | |
| 114 | − * TCP option space. | |
| 115 | − */ | |
| 116 | − if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) | |
| 117 | − return -EINVAL; | |
| 118 | −#endif | |
| 119 | − | |
| 120 | − return 0; | |
| 121 | 111 | } |
| 122 | 112 | |
| 123 | 113 | static bool subflow_use_different_sport(struct mptcp_sock *msk, const struct sock *sk) |
| @@ -130,20 +120,23 @@ static bool subflow_use_different_sport(struct mptcp_sock *msk, const struct soc · 6 unmodified lines | ||
| 130 | 120 | * Returns an error code if a JOIN has failed and a TCP reset |
| 131 | 121 | * should be sent. |
| 132 | 122 | */ |
| 133 | −static int subflow_init_req(struct request_sock *req, | |
| 134 | − const struct sock *sk_listener, | |
| 135 | − struct sk_buff *skb) | |
| 123 | +static int subflow_check_req(struct request_sock *req, | |
| 124 | + const struct sock *sk_listener, | |
| 125 | + struct sk_buff *skb) | |
| 136 | 126 | { |
| 137 | 127 | struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); |
| 138 | 128 | struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); |
| 139 | 129 | struct mptcp_options_received mp_opt; |
| 140 | − int ret; | |
| 141 | 130 | |
| 142 | 131 | pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); |
| 143 | 132 | |
| 144 | − ret = __subflow_init_req(req, sk_listener); | |
| 145 | − if (ret) | |
| 146 | − return 0; | |
| 133 | +#ifdef CONFIG_TCP_MD5SIG | |
| 134 | + /* no MPTCP if MD5SIG is enabled on this socket or we may run out of | |
| 135 | + * TCP option space. | |
| 136 | + */ | |
| 137 | + if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) | |
| 138 | + return -EINVAL; | |
| 139 | +#endif | |
| 147 | 140 | |
| 148 | 141 | mptcp_get_options(skb, &mp_opt); |
| 149 | 142 | |
| @@ -236,10 +229,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req, · 86 unmodified lines | ||
| 236 | 229 | struct mptcp_options_received mp_opt; |
| 237 | 230 | int err; |
| 238 | 231 | |
| 239 | − err = __subflow_init_req(req, sk_listener); | |
| 240 | − if (err) | |
| 241 | − return err; | |
| 242 | − | |
| 232 | + subflow_init_req(req, sk_listener); | |
| 243 | 233 | mptcp_get_options(skb, &mp_opt); |
| 244 | 234 | |
| 245 | 235 | if (mp_opt.mp_capable && mp_opt.mp_join) |
| @@ -279,12 +269,13 @@ static struct dst_entry *subflow_v4_route_req(const struct sock *sk, · 33 unmodified lines | ||
| 279 | 269 | int err; |
| 280 | 270 | |
| 281 | 271 | tcp_rsk(req)->is_mptcp = 1; |
| 272 | + subflow_init_req(req, sk); | |
| 282 | 273 | |
| 283 | 274 | dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req); |
| 284 | 275 | if (!dst) |
| 285 | 276 | return NULL; |
| 286 | 277 | |
| 287 | − err = subflow_init_req(req, sk, skb); | |
| 278 | + err = subflow_check_req(req, sk, skb); | |
| 288 | 279 | if (err == 0) |
| 289 | 280 | return dst; |
| 290 | 281 | |
| @@ -304,12 +295,13 @@ static struct dst_entry *subflow_v6_route_req(const struct sock *sk, · 13 unmodified lines | ||
| 304 | 295 | int err; |
| 305 | 296 | |
| 306 | 297 | tcp_rsk(req)->is_mptcp = 1; |
| 298 | + subflow_init_req(req, sk); | |
| 307 | 299 | |
| 308 | 300 | dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req); |
| 309 | 301 | if (!dst) |
| 310 | 302 | return NULL; |
| 311 | 303 | |
| 312 | − err = subflow_init_req(req, sk, skb); | |
| 304 | + err = subflow_check_req(req, sk, skb); | |
| 313 | 305 | if (err == 0) |
| 314 | 306 | return dst; |
| 315 | 307 | |
| @@ -1124,6 +1116,46 @@ static void subflow_write_space(struct sock *ssk) · 808 unmodified lines | ||
| 1124 | 1116 | mptcp_write_space(sk); |
| 1125 | 1117 | } |
| 1126 | 1118 | |
| 1119 | +void __mptcp_error_report(struct sock *sk) | |
| 1120 | +{ | |
| 1121 | + struct mptcp_subflow_context *subflow; | |
| 1122 | + struct mptcp_sock *msk = mptcp_sk(sk); | |
| 1123 | + | |
| 1124 | + mptcp_for_each_subflow(msk, subflow) { | |
| 1125 | + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | |
| 1126 | + int err = sock_error(ssk); | |
| 1127 | + | |
| 1128 | + if (!err) | |
| 1129 | + continue; | |
| 1130 | + | |
| 1131 | + /* only propagate errors on fallen-back sockets or | |
| 1132 | + * on MPC connect | |
| 1133 | + */ | |
| 1134 | + if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk)) | |
| 1135 | + continue; | |
| 1136 | + | |
| 1137 | + inet_sk_state_store(sk, inet_sk_state_load(ssk)); | |
| 1138 | + sk->sk_err = -err; | |
| 1139 | + | |
| 1140 | + /* This barrier is coupled with smp_rmb() in mptcp_poll() */ | |
| 1141 | + smp_wmb(); | |
| 1142 | + sk->sk_error_report(sk); | |
| 1143 | + break; | |
| 1144 | + } | |
| 1145 | +} | |
| 1146 | + | |
| 1147 | +static void subflow_error_report(struct sock *ssk) | |
| 1148 | +{ | |
| 1149 | + struct sock *sk = mptcp_subflow_ctx(ssk)->conn; | |
| 1150 | + | |
| 1151 | + mptcp_data_lock(sk); | |
| 1152 | + if (!sock_owned_by_user(sk)) | |
| 1153 | + __mptcp_error_report(sk); | |
| 1154 | + else | |
| 1155 | + set_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags); | |
| 1156 | + mptcp_data_unlock(sk); | |
| 1157 | +} | |
| 1158 | + | |
| 1127 | 1159 | static struct inet_connection_sock_af_ops * |
| 1128 | 1160 | subflow_default_af_ops(struct sock *sk) |
| 1129 | 1161 | { |
| @@ -1470,9 +1502,11 @@ static int subflow_ulp_init(struct sock *sk) · 340 unmodified lines | ||
| 1470 | 1502 | ctx->tcp_data_ready = sk->sk_data_ready; |
| 1471 | 1503 | ctx->tcp_state_change = sk->sk_state_change; |
| 1472 | 1504 | ctx->tcp_write_space = sk->sk_write_space; |
| 1505 | + ctx->tcp_error_report = sk->sk_error_report; | |
| 1473 | 1506 | sk->sk_data_ready = subflow_data_ready; |
| 1474 | 1507 | sk->sk_write_space = subflow_write_space; |
| 1475 | 1508 | sk->sk_state_change = subflow_state_change; |
| 1509 | + sk->sk_error_report = subflow_error_report; | |
| 1476 | 1510 | out: |
| 1477 | 1511 | return err; |
| 1478 | 1512 | } |
| @@ -1526,6 +1560,7 @@ static void subflow_ulp_clone(const struct request_sock *req, · 47 unmodified lines | ||
| 1526 | 1560 | new_ctx->tcp_data_ready = old_ctx->tcp_data_ready; |
| 1527 | 1561 | new_ctx->tcp_state_change = old_ctx->tcp_state_change; |
| 1528 | 1562 | new_ctx->tcp_write_space = old_ctx->tcp_write_space; |
| 1563 | + new_ctx->tcp_error_report = old_ctx->tcp_error_report; | |
| 1529 | 1564 | new_ctx->rel_write_seq = 1; |
| 1530 | 1565 | new_ctx->tcp_sock = newsk; |
| 1531 | 1566 | |
| @@ -908,7 +908,7 @@ static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = { · 907 unmodified lines | ||
| 908 | 908 | [TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY), |
| 909 | 909 | }; |
| 910 | 910 | |
| 911 | −static void tcf_idr_insert_many(struct tc_action *actions[]) | |
| 911 | +void tcf_idr_insert_many(struct tc_action *actions[]) | |
| 912 | 912 | { |
| 913 | 913 | int i; |
| 914 | 914 | |
| @@ -3060,6 +3060,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, · 3059 unmodified lines | ||
| 3060 | 3060 | act->type = exts->type = TCA_OLD_COMPAT; |
| 3061 | 3061 | exts->actions[0] = act; |
| 3062 | 3062 | exts->nr_actions = 1; |
| 3063 | + tcf_idr_insert_many(exts->actions); | |
| 3063 | 3064 | } else if (exts->action && tb[exts->action]) { |
| 3064 | 3065 | int err; |
| 3065 | 3066 | |
| @@ -30,6 +30,11 @@ · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | #include <uapi/linux/netfilter/nf_conntrack_common.h> |
| 32 | 32 | |
| 33 | +#define TCA_FLOWER_KEY_CT_FLAGS_MAX \ | |
| 34 | + ((__TCA_FLOWER_KEY_CT_FLAGS_MAX - 1) << 1) | |
| 35 | +#define TCA_FLOWER_KEY_CT_FLAGS_MASK \ | |
| 36 | + (TCA_FLOWER_KEY_CT_FLAGS_MAX - 1) | |
| 37 | + | |
| 33 | 38 | struct fl_flow_key { |
| 34 | 39 | struct flow_dissector_key_meta meta; |
| 35 | 40 | struct flow_dissector_key_control control; |
| @@ -690,8 +695,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { · 654 unmodified lines | ||
| 690 | 695 | [TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 }, |
| 691 | 696 | [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED }, |
| 692 | 697 | [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED }, |
| 693 | − [TCA_FLOWER_KEY_CT_STATE] = { .type = NLA_U16 }, | |
| 694 | − [TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NLA_U16 }, | |
| 698 | + [TCA_FLOWER_KEY_CT_STATE] = | |
| 699 | + NLA_POLICY_MASK(NLA_U16, TCA_FLOWER_KEY_CT_FLAGS_MASK), | |
| 700 | + [TCA_FLOWER_KEY_CT_STATE_MASK] = | |
| 701 | + NLA_POLICY_MASK(NLA_U16, TCA_FLOWER_KEY_CT_FLAGS_MASK), | |
| 695 | 702 | [TCA_FLOWER_KEY_CT_ZONE] = { .type = NLA_U16 }, |
| 696 | 703 | [TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NLA_U16 }, |
| 697 | 704 | [TCA_FLOWER_KEY_CT_MARK] = { .type = NLA_U32 }, |
| @@ -1394,12 +1401,33 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key, · 696 unmodified lines | ||
| 1394 | 1401 | return 0; |
| 1395 | 1402 | } |
| 1396 | 1403 | |
| 1404 | +static int fl_validate_ct_state(u16 state, struct nlattr *tb, | |
| 1405 | + struct netlink_ext_ack *extack) | |
| 1406 | +{ | |
| 1407 | + if (state && !(state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED)) { | |
| 1408 | + NL_SET_ERR_MSG_ATTR(extack, tb, | |
| 1409 | + "no trk, so no other flag can be set"); | |
| 1410 | + return -EINVAL; | |
| 1411 | + } | |
| 1412 | + | |
| 1413 | + if (state & TCA_FLOWER_KEY_CT_FLAGS_NEW && | |
| 1414 | + state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) { | |
| 1415 | + NL_SET_ERR_MSG_ATTR(extack, tb, | |
| 1416 | + "new and est are mutually exclusive"); | |
| 1417 | + return -EINVAL; | |
| 1418 | + } | |
| 1419 | + | |
| 1420 | + return 0; | |
| 1421 | +} | |
| 1422 | + | |
| 1397 | 1423 | static int fl_set_key_ct(struct nlattr **tb, |
| 1398 | 1424 | struct flow_dissector_key_ct *key, |
| 1399 | 1425 | struct flow_dissector_key_ct *mask, |
| 1400 | 1426 | struct netlink_ext_ack *extack) |
| 1401 | 1427 | { |
| 1402 | 1428 | if (tb[TCA_FLOWER_KEY_CT_STATE]) { |
| 1429 | + int err; | |
| 1430 | + | |
| 1403 | 1431 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK)) { |
| 1404 | 1432 | NL_SET_ERR_MSG(extack, "Conntrack isn't enabled"); |
| 1405 | 1433 | return -EOPNOTSUPP; |
| @@ -1407,6 +1435,13 @@ static int fl_set_key_ct(struct nlattr **tb, · 1 unmodified line | ||
| 1407 | 1435 | fl_set_key_val(tb, &key->ct_state, TCA_FLOWER_KEY_CT_STATE, |
| 1408 | 1436 | &mask->ct_state, TCA_FLOWER_KEY_CT_STATE_MASK, |
| 1409 | 1437 | sizeof(key->ct_state)); |
| 1438 | + | |
| 1439 | + err = fl_validate_ct_state(mask->ct_state, | |
| 1440 | + tb[TCA_FLOWER_KEY_CT_STATE_MASK], | |
| 1441 | + extack); | |
| 1442 | + if (err) | |
| 1443 | + return err; | |
| 1444 | + | |
| 1410 | 1445 | } |
| 1411 | 1446 | if (tb[TCA_FLOWER_KEY_CT_ZONE]) { |
| 1412 | 1447 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES)) { |
| @@ -1,4 +1,4 @@ | ||
| 1 | −#!/bin/sh | |
| 1 | +#!/bin/bash | |
| 2 | 2 | # Create 2 namespaces with two veth peers, and |
| 3 | 3 | # forward packets in-between using generic XDP |
| 4 | 4 | # |
| @@ -57,12 +57,8 @@ test_xdp_redirect() · 52 unmodified lines | ||
| 57 | 57 | ip link set dev veth1 $xdpmode obj test_xdp_redirect.o sec redirect_to_222 &> /dev/null |
| 58 | 58 | ip link set dev veth2 $xdpmode obj test_xdp_redirect.o sec redirect_to_111 &> /dev/null |
| 59 | 59 | |
| 60 | − ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null | |
| 61 | − local ret1=$? | |
| 62 | − ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null | |
| 63 | − local ret2=$? | |
| 64 | − | |
| 65 | − if [ $ret1 -eq 0 -a $ret2 -eq 0 ]; then | |
| 60 | + if ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null && | |
| 61 | + ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null; then | |
| 66 | 62 | echo "selftests: test_xdp_redirect $xdpmode [PASS]"; |
| 67 | 63 | else |
| 68 | 64 | ret=1 |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | ALL_TESTS="match_dst_mac_test match_src_mac_test match_dst_ip_test \ |
| 5 | 5 | match_src_ip_test match_ip_flags_test match_pcp_test match_vlan_test \ |
| 6 | − match_ip_tos_test match_indev_test match_mpls_label_test \ | |
| 6 | + match_ip_tos_test match_indev_testmatch_ip_ttl_test match_mpls_label_test \ | |
| 7 | 7 | match_mpls_tc_test match_mpls_bos_test match_mpls_ttl_test \ |
| 8 | 8 | match_mpls_lse_test" |
| 9 | 9 | NUM_NETIFS=2 |
| @@ -312,6 +312,42 @@ match_ip_tos_test() · 302 unmodified lines | ||
| 312 | 312 | log_test "ip_tos match ($tcflags)" |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | +match_ip_ttl_test() | |
| 316 | +{ | |
| 317 | + RET=0 | |
| 318 | + | |
| 319 | + tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ | |
| 320 | + $tcflags dst_ip 192.0.2.2 ip_ttl 63 action drop | |
| 321 | + tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ | |
| 322 | + $tcflags dst_ip 192.0.2.2 action drop | |
| 323 | + | |
| 324 | + $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ | |
| 325 | + -t ip "ttl=63" -q | |
| 326 | + | |
| 327 | + $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ | |
| 328 | + -t ip "ttl=63,mf,frag=256" -q | |
| 329 | + | |
| 330 | + tc_check_packets "dev $h2 ingress" 102 1 | |
| 331 | + check_fail $? "Matched on the wrong filter (no check on ttl)" | |
| 332 | + | |
| 333 | + tc_check_packets "dev $h2 ingress" 101 2 | |
| 334 | + check_err $? "Did not match on correct filter (ttl=63)" | |
| 335 | + | |
| 336 | + $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ | |
| 337 | + -t ip "ttl=255" -q | |
| 338 | + | |
| 339 | + tc_check_packets "dev $h2 ingress" 101 3 | |
| 340 | + check_fail $? "Matched on a wrong filter (ttl=63)" | |
| 341 | + | |
| 342 | + tc_check_packets "dev $h2 ingress" 102 1 | |
| 343 | + check_err $? "Did not match on correct filter (no check on ttl)" | |
| 344 | + | |
| 345 | + tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower | |
| 346 | + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower | |
| 347 | + | |
| 348 | + log_test "ip_ttl match ($tcflags)" | |
| 349 | +} | |
| 350 | + | |
| 315 | 351 | match_indev_test() |
| 316 | 352 | { |
| 317 | 353 | RET=0 |