Pull networking fixes from David Miller: 1) Fix leak in nl80211 AP start where we leak the ACL memory, from Johannes Berg. 2) Fix double mutex unlock in mac80211, from Andrei Otcheretianski. 3) Fix RCU stall in ipset, from Jozsef Kadlecsik. 4) Fix devlink locking in devlink_dpipe_table_register, from Madhuparna Bhowmik. 5) Fix race causing TX hang in ll_temac, from Esben Haabendal. 6) Stale eth hdr pointer in br_dev_xmit(), from Nikolay Aleksandrov. 7) Fix TX hash calculation bounds checking wrt. tc rules, from Amritha Nambiar. 8) Size netlink responses properly in schedule action code to take into consideration TCA_ACT_FLAGS. From Jiri Pirko. 9) Fix firmware paths for mscc PHY driver, from Antoine Tenart. 10) Don't register stmmac notifier multiple times, from Aaro Koskinen. 11) Various rmnet bug fixes, from Taehee Yoo. 12) Fix vsock deadlock in vsock transport release, from Stefano Garzarella. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (61 commits) net: dsa: mv88e6xxx: Fix masking of egress port mlxsw: pci: Wait longer before accessing the device after reset sfc: fix timestamp reconstruction at 16-bit rollover points vsock: fix potential deadlock in transport->release() unix: It's CONFIG_PROC_FS not CONFIG_PROCFS net: rmnet: fix packet forwarding in rmnet bridge mode net: rmnet: fix bridge mode bugs net: rmnet: use upper/lower device infrastructure net: rmnet: do not allow to change mux id if mux id is duplicated net: rmnet: remove rcu_read_lock in rmnet_force_unassociate_device() net: rmnet: fix suspicious RCU usage net: rmnet: fix NULL pointer dereference in rmnet_changelink() net: rmnet: fix NULL pointer dereference in rmnet_newlink() net: phy: marvell: don't interpret PHY status unless resolved mlx5: register lag notifier for init network namespace only unix: define and set show_fdinfo only if procfs is enabled hinic: fix a bug of rss configuration hinic: fix a bug of setting hw_ioctxt hinic: fix a irq affinity bug net/smc: check for valid ib_client_data ...
Unified · Split
| @@ -487,8 +487,9 @@ phy_register_fixup_for_id():: · 486 unmodified lines | |||
| 487 | The stubs set one of the two matching criteria, and set the other one to | 487 | The stubs set one of the two matching criteria, and set the other one to |
| 488 | match anything. | 488 | match anything. |
| 489 | 489 | ||
| 490 | When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module, | 490 | When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load |
| 491 | unregister fixup and free allocate memory are required. | 491 | time, the module needs to unregister the fixup and free allocated memory when |
| 492 | it's unloaded. | ||
| 492 | 493 | ||
| 493 | Call one of following function before unloading module:: | 494 | Call one of following function before unloading module:: |
| 494 | 495 | ||
| @@ -69,8 +69,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) · 68 unmodified lines | |||
| 69 | /* Force link status for IMP port */ | 69 | /* Force link status for IMP port */ |
| 70 | reg = core_readl(priv, offset); | 70 | reg = core_readl(priv, offset); |
| 71 | reg |= (MII_SW_OR | LINK_STS); | 71 | reg |= (MII_SW_OR | LINK_STS); |
| 72 | if (priv->type == BCM7278_DEVICE_ID) | 72 | reg &= ~GMII_SPEED_UP_2G; |
| 73 | reg |= GMII_SPEED_UP_2G; | ||
| 74 | core_writel(priv, reg, offset); | 73 | core_writel(priv, reg, offset); |
| 75 | 74 | ||
| 76 | /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ | 75 | /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ |
| @@ -278,13 +278,13 @@ int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, · 277 unmodified lines | |||
| 278 | switch (direction) { | 278 | switch (direction) { |
| 279 | case MV88E6XXX_EGRESS_DIR_INGRESS: | 279 | case MV88E6XXX_EGRESS_DIR_INGRESS: |
| 280 | dest_port_chip = &chip->ingress_dest_port; | 280 | dest_port_chip = &chip->ingress_dest_port; |
| 281 | reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; | 281 | reg &= ~MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; |
| 282 | reg |= port << | 282 | reg |= port << |
| 283 | __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); | 283 | __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); |
| 284 | break; | 284 | break; |
| 285 | case MV88E6XXX_EGRESS_DIR_EGRESS: | 285 | case MV88E6XXX_EGRESS_DIR_EGRESS: |
| 286 | dest_port_chip = &chip->egress_dest_port; | 286 | dest_port_chip = &chip->egress_dest_port; |
| 287 | reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; | 287 | reg &= ~MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; |
| 288 | reg |= port << | 288 | reg |= port << |
| 289 | __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); | 289 | __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); |
| 290 | break; | 290 | break; |
| @@ -11252,7 +11252,7 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp) · 11251 unmodified lines | |||
| 11252 | } | 11252 | } |
| 11253 | } | 11253 | } |
| 11254 | if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event)) | 11254 | if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event)) |
| 11255 | netdev_info(bp->dev, "Receive PF driver unload event!"); | 11255 | netdev_info(bp->dev, "Receive PF driver unload event!\n"); |
| 11256 | } | 11256 | } |
| 11257 | 11257 | ||
| 11258 | #else | 11258 | #else |
| @@ -11759,7 +11759,7 @@ static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[]) · 500 unmodified lines | |||
| 11759 | u32 dw; | 11759 | u32 dw; |
| 11760 | 11760 | ||
| 11761 | if (!pos) { | 11761 | if (!pos) { |
| 11762 | netdev_info(bp->dev, "Unable do read adapter's DSN"); | 11762 | netdev_info(bp->dev, "Unable do read adapter's DSN\n"); |
| 11763 | return -EOPNOTSUPP; | 11763 | return -EOPNOTSUPP; |
| 11764 | } | 11764 | } |
| 11765 | 11765 | ||
| @@ -641,14 +641,14 @@ static int bnxt_dl_params_register(struct bnxt *bp) · 640 unmodified lines | |||
| 641 | rc = devlink_params_register(bp->dl, bnxt_dl_params, | 641 | rc = devlink_params_register(bp->dl, bnxt_dl_params, |
| 642 | ARRAY_SIZE(bnxt_dl_params)); | 642 | ARRAY_SIZE(bnxt_dl_params)); |
| 643 | if (rc) { | 643 | if (rc) { |
| 644 | netdev_warn(bp->dev, "devlink_params_register failed. rc=%d", | 644 | netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n", |
| 645 | rc); | 645 | rc); |
| 646 | return rc; | 646 | return rc; |
| 647 | } | 647 | } |
| 648 | rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, | 648 | rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, |
| 649 | ARRAY_SIZE(bnxt_dl_port_params)); | 649 | ARRAY_SIZE(bnxt_dl_port_params)); |
| 650 | if (rc) { | 650 | if (rc) { |
| 651 | netdev_err(bp->dev, "devlink_port_params_register failed"); | 651 | netdev_err(bp->dev, "devlink_port_params_register failed\n"); |
| 652 | devlink_params_unregister(bp->dl, bnxt_dl_params, | 652 | devlink_params_unregister(bp->dl, bnxt_dl_params, |
| 653 | ARRAY_SIZE(bnxt_dl_params)); | 653 | ARRAY_SIZE(bnxt_dl_params)); |
| 654 | return rc; | 654 | return rc; |
| @@ -679,7 +679,7 @@ int bnxt_dl_register(struct bnxt *bp) · 24 unmodified lines | |||
| 679 | else | 679 | else |
| 680 | dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl)); | 680 | dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl)); |
| 681 | if (!dl) { | 681 | if (!dl) { |
| 682 | netdev_warn(bp->dev, "devlink_alloc failed"); | 682 | netdev_warn(bp->dev, "devlink_alloc failed\n"); |
| 683 | return -ENOMEM; | 683 | return -ENOMEM; |
| 684 | } | 684 | } |
| 685 | 685 | ||
| @@ -692,7 +692,7 @@ int bnxt_dl_register(struct bnxt *bp) · 6 unmodified lines | |||
| 692 | 692 | ||
| 693 | rc = devlink_register(dl, &bp->pdev->dev); | 693 | rc = devlink_register(dl, &bp->pdev->dev); |
| 694 | if (rc) { | 694 | if (rc) { |
| 695 | netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc); | 695 | netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc); |
| 696 | goto err_dl_free; | 696 | goto err_dl_free; |
| 697 | } | 697 | } |
| 698 | 698 | ||
| @@ -704,7 +704,7 @@ int bnxt_dl_register(struct bnxt *bp) · 5 unmodified lines | |||
| 704 | sizeof(bp->dsn)); | 704 | sizeof(bp->dsn)); |
| 705 | rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); | 705 | rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); |
| 706 | if (rc) { | 706 | if (rc) { |
| 707 | netdev_err(bp->dev, "devlink_port_register failed"); | 707 | netdev_err(bp->dev, "devlink_port_register failed\n"); |
| 708 | goto err_dl_unreg; | 708 | goto err_dl_unreg; |
| 709 | } | 709 | } |
| 710 | 710 | ||
| @@ -2028,7 +2028,7 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename, · 2027 unmodified lines | |||
| 2028 | } | 2028 | } |
| 2029 | 2029 | ||
| 2030 | if (fw->size > item_len) { | 2030 | if (fw->size > item_len) { |
| 2031 | netdev_err(dev, "PKG insufficient update area in nvram: %lu", | 2031 | netdev_err(dev, "PKG insufficient update area in nvram: %lu\n", |
| 2032 | (unsigned long)fw->size); | 2032 | (unsigned long)fw->size); |
| 2033 | rc = -EFBIG; | 2033 | rc = -EFBIG; |
| 2034 | } else { | 2034 | } else { |
| @@ -3338,7 +3338,7 @@ err: · 1303 unmodified lines | |||
| 3338 | kfree(coredump.data); | 3338 | kfree(coredump.data); |
| 3339 | *dump_len += sizeof(struct bnxt_coredump_record); | 3339 | *dump_len += sizeof(struct bnxt_coredump_record); |
| 3340 | if (rc == -ENOBUFS) | 3340 | if (rc == -ENOBUFS) |
| 3341 | netdev_err(bp->dev, "Firmware returned large coredump buffer"); | 3341 | netdev_err(bp->dev, "Firmware returned large coredump buffer\n"); |
| 3342 | return rc; | 3342 | return rc; |
| 3343 | } | 3343 | } |
| 3344 | 3344 | ||
| @@ -50,7 +50,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev) · 49 unmodified lines | |||
| 50 | 50 | ||
| 51 | /* check if dev belongs to the same switch */ | 51 | /* check if dev belongs to the same switch */ |
| 52 | if (!netdev_port_same_parent_id(pf_bp->dev, dev)) { | 52 | if (!netdev_port_same_parent_id(pf_bp->dev, dev)) { |
| 53 | netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch", | 53 | netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch\n", |
| 54 | dev->ifindex); | 54 | dev->ifindex); |
| 55 | return BNXT_FID_INVALID; | 55 | return BNXT_FID_INVALID; |
| 56 | } | 56 | } |
| @@ -70,7 +70,7 @@ static int bnxt_tc_parse_redir(struct bnxt *bp, · 13 unmodified lines | |||
| 70 | struct net_device *dev = act->dev; | 70 | struct net_device *dev = act->dev; |
| 71 | 71 | ||
| 72 | if (!dev) { | 72 | if (!dev) { |
| 73 | netdev_info(bp->dev, "no dev in mirred action"); | 73 | netdev_info(bp->dev, "no dev in mirred action\n"); |
| 74 | return -EINVAL; | 74 | return -EINVAL; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| @@ -106,7 +106,7 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp, · 29 unmodified lines | |||
| 106 | const struct ip_tunnel_key *tun_key = &tun_info->key; | 106 | const struct ip_tunnel_key *tun_key = &tun_info->key; |
| 107 | 107 | ||
| 108 | if (ip_tunnel_info_af(tun_info) != AF_INET) { | 108 | if (ip_tunnel_info_af(tun_info) != AF_INET) { |
| 109 | netdev_info(bp->dev, "only IPv4 tunnel-encap is supported"); | 109 | netdev_info(bp->dev, "only IPv4 tunnel-encap is supported\n"); |
| 110 | return -EOPNOTSUPP; | 110 | return -EOPNOTSUPP; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| @@ -295,7 +295,7 @@ static int bnxt_tc_parse_actions(struct bnxt *bp, · 182 unmodified lines | |||
| 295 | int i, rc; | 295 | int i, rc; |
| 296 | 296 | ||
| 297 | if (!flow_action_has_entries(flow_action)) { | 297 | if (!flow_action_has_entries(flow_action)) { |
| 298 | netdev_info(bp->dev, "no actions"); | 298 | netdev_info(bp->dev, "no actions\n"); |
| 299 | return -EINVAL; | 299 | return -EINVAL; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| @@ -370,7 +370,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp, · 68 unmodified lines | |||
| 370 | /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ | 370 | /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ |
| 371 | if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || | 371 | if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || |
| 372 | (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) { | 372 | (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) { |
| 373 | netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x", | 373 | netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x\n", |
| 374 | dissector->used_keys); | 374 | dissector->used_keys); |
| 375 | return -EOPNOTSUPP; | 375 | return -EOPNOTSUPP; |
| 376 | } | 376 | } |
| @@ -508,7 +508,7 @@ static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp, · 131 unmodified lines | |||
| 508 | 508 | ||
| 509 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | 509 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 510 | if (rc) | 510 | if (rc) |
| 511 | netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc); | 511 | netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc); |
| 512 | 512 | ||
| 513 | return rc; | 513 | return rc; |
| 514 | } | 514 | } |
| @@ -841,7 +841,7 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp, · 326 unmodified lines | |||
| 841 | resp = bnxt_get_hwrm_resp_addr(bp, &req); | 841 | resp = bnxt_get_hwrm_resp_addr(bp, &req); |
| 842 | *decap_filter_handle = resp->decap_filter_id; | 842 | *decap_filter_handle = resp->decap_filter_id; |
| 843 | } else { | 843 | } else { |
| 844 | netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc); | 844 | netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc); |
| 845 | } | 845 | } |
| 846 | mutex_unlock(&bp->hwrm_cmd_lock); | 846 | mutex_unlock(&bp->hwrm_cmd_lock); |
| 847 | 847 | ||
| @@ -859,7 +859,7 @@ static int hwrm_cfa_decap_filter_free(struct bnxt *bp, · 11 unmodified lines | |||
| 859 | 859 | ||
| 860 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | 860 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 861 | if (rc) | 861 | if (rc) |
| 862 | netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc); | 862 | netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc); |
| 863 | 863 | ||
| 864 | return rc; | 864 | return rc; |
| 865 | } | 865 | } |
| @@ -906,7 +906,7 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp, · 40 unmodified lines | |||
| 906 | resp = bnxt_get_hwrm_resp_addr(bp, &req); | 906 | resp = bnxt_get_hwrm_resp_addr(bp, &req); |
| 907 | *encap_record_handle = resp->encap_record_id; | 907 | *encap_record_handle = resp->encap_record_id; |
| 908 | } else { | 908 | } else { |
| 909 | netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc); | 909 | netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc); |
| 910 | } | 910 | } |
| 911 | mutex_unlock(&bp->hwrm_cmd_lock); | 911 | mutex_unlock(&bp->hwrm_cmd_lock); |
| 912 | 912 | ||
| @@ -924,7 +924,7 @@ static int hwrm_cfa_encap_record_free(struct bnxt *bp, · 11 unmodified lines | |||
| 924 | 924 | ||
| 925 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | 925 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 926 | if (rc) | 926 | if (rc) |
| 927 | netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc); | 927 | netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc); |
| 928 | 928 | ||
| 929 | return rc; | 929 | return rc; |
| 930 | } | 930 | } |
| @@ -943,7 +943,7 @@ static int bnxt_tc_put_l2_node(struct bnxt *bp, · 12 unmodified lines | |||
| 943 | tc_info->l2_ht_params); | 943 | tc_info->l2_ht_params); |
| 944 | if (rc) | 944 | if (rc) |
| 945 | netdev_err(bp->dev, | 945 | netdev_err(bp->dev, |
| 946 | "Error: %s: rhashtable_remove_fast: %d", | 946 | "Error: %s: rhashtable_remove_fast: %d\n", |
| 947 | __func__, rc); | 947 | __func__, rc); |
| 948 | kfree_rcu(l2_node, rcu); | 948 | kfree_rcu(l2_node, rcu); |
| 949 | } | 949 | } |
| @@ -972,7 +972,7 @@ bnxt_tc_get_l2_node(struct bnxt *bp, struct rhashtable *l2_table, · 22 unmodified lines | |||
| 972 | if (rc) { | 972 | if (rc) { |
| 973 | kfree_rcu(l2_node, rcu); | 973 | kfree_rcu(l2_node, rcu); |
| 974 | netdev_err(bp->dev, | 974 | netdev_err(bp->dev, |
| 975 | "Error: %s: rhashtable_insert_fast: %d", | 975 | "Error: %s: rhashtable_insert_fast: %d\n", |
| 976 | __func__, rc); | 976 | __func__, rc); |
| 977 | return NULL; | 977 | return NULL; |
| 978 | } | 978 | } |
| @@ -1031,7 +1031,7 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow) · 52 unmodified lines | |||
| 1031 | if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) && | 1031 | if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) && |
| 1032 | (flow->l4_key.ip_proto != IPPROTO_TCP && | 1032 | (flow->l4_key.ip_proto != IPPROTO_TCP && |
| 1033 | flow->l4_key.ip_proto != IPPROTO_UDP)) { | 1033 | flow->l4_key.ip_proto != IPPROTO_UDP)) { |
| 1034 | netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports", | 1034 | netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports\n", |
| 1035 | flow->l4_key.ip_proto); | 1035 | flow->l4_key.ip_proto); |
| 1036 | return false; | 1036 | return false; |
| 1037 | } | 1037 | } |
| @@ -1088,7 +1088,7 @@ static int bnxt_tc_put_tunnel_node(struct bnxt *bp, · 50 unmodified lines | |||
| 1088 | rc = rhashtable_remove_fast(tunnel_table, &tunnel_node->node, | 1088 | rc = rhashtable_remove_fast(tunnel_table, &tunnel_node->node, |
| 1089 | *ht_params); | 1089 | *ht_params); |
| 1090 | if (rc) { | 1090 | if (rc) { |
| 1091 | netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc); | 1091 | netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc); |
| 1092 | rc = -1; | 1092 | rc = -1; |
| 1093 | } | 1093 | } |
| 1094 | kfree_rcu(tunnel_node, rcu); | 1094 | kfree_rcu(tunnel_node, rcu); |
| @@ -1129,7 +1129,7 @@ bnxt_tc_get_tunnel_node(struct bnxt *bp, struct rhashtable *tunnel_table, · 34 unmodified lines | |||
| 1129 | tunnel_node->refcount++; | 1129 | tunnel_node->refcount++; |
| 1130 | return tunnel_node; | 1130 | return tunnel_node; |
| 1131 | err: | 1131 | err: |
| 1132 | netdev_info(bp->dev, "error rc=%d", rc); | 1132 | netdev_info(bp->dev, "error rc=%d\n", rc); |
| 1133 | return NULL; | 1133 | return NULL; |
| 1134 | } | 1134 | } |
| 1135 | 1135 | ||
| @@ -1187,7 +1187,7 @@ static void bnxt_tc_put_decap_l2_node(struct bnxt *bp, · 51 unmodified lines | |||
| 1187 | &decap_l2_node->node, | 1187 | &decap_l2_node->node, |
| 1188 | tc_info->decap_l2_ht_params); | 1188 | tc_info->decap_l2_ht_params); |
| 1189 | if (rc) | 1189 | if (rc) |
| 1190 | netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc); | 1190 | netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc); |
| 1191 | kfree_rcu(decap_l2_node, rcu); | 1191 | kfree_rcu(decap_l2_node, rcu); |
| 1192 | } | 1192 | } |
| 1193 | } | 1193 | } |
| @@ -1227,7 +1227,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 33 unmodified lines | |||
| 1227 | 1227 | ||
| 1228 | rt = ip_route_output_key(dev_net(real_dst_dev), &flow); | 1228 | rt = ip_route_output_key(dev_net(real_dst_dev), &flow); |
| 1229 | if (IS_ERR(rt)) { | 1229 | if (IS_ERR(rt)) { |
| 1230 | netdev_info(bp->dev, "no route to %pI4b", &flow.daddr); | 1230 | netdev_info(bp->dev, "no route to %pI4b\n", &flow.daddr); |
| 1231 | return -EOPNOTSUPP; | 1231 | return -EOPNOTSUPP; |
| 1232 | } | 1232 | } |
| 1233 | 1233 | ||
| @@ -1241,7 +1241,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 7 unmodified lines | |||
| 1241 | 1241 | ||
| 1242 | if (vlan->real_dev != real_dst_dev) { | 1242 | if (vlan->real_dev != real_dst_dev) { |
| 1243 | netdev_info(bp->dev, | 1243 | netdev_info(bp->dev, |
| 1244 | "dst_dev(%s) doesn't use PF-if(%s)", | 1244 | "dst_dev(%s) doesn't use PF-if(%s)\n", |
| 1245 | netdev_name(dst_dev), | 1245 | netdev_name(dst_dev), |
| 1246 | netdev_name(real_dst_dev)); | 1246 | netdev_name(real_dst_dev)); |
| 1247 | rc = -EOPNOTSUPP; | 1247 | rc = -EOPNOTSUPP; |
| @@ -1253,7 +1253,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 5 unmodified lines | |||
| 1253 | #endif | 1253 | #endif |
| 1254 | } else if (dst_dev != real_dst_dev) { | 1254 | } else if (dst_dev != real_dst_dev) { |
| 1255 | netdev_info(bp->dev, | 1255 | netdev_info(bp->dev, |
| 1256 | "dst_dev(%s) for %pI4b is not PF-if(%s)", | 1256 | "dst_dev(%s) for %pI4b is not PF-if(%s)\n", |
| 1257 | netdev_name(dst_dev), &flow.daddr, | 1257 | netdev_name(dst_dev), &flow.daddr, |
| 1258 | netdev_name(real_dst_dev)); | 1258 | netdev_name(real_dst_dev)); |
| 1259 | rc = -EOPNOTSUPP; | 1259 | rc = -EOPNOTSUPP; |
| @@ -1262,7 +1262,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 2 unmodified lines | |||
| 1262 | 1262 | ||
| 1263 | nbr = dst_neigh_lookup(&rt->dst, &flow.daddr); | 1263 | nbr = dst_neigh_lookup(&rt->dst, &flow.daddr); |
| 1264 | if (!nbr) { | 1264 | if (!nbr) { |
| 1265 | netdev_info(bp->dev, "can't lookup neighbor for %pI4b", | 1265 | netdev_info(bp->dev, "can't lookup neighbor for %pI4b\n", |
| 1266 | &flow.daddr); | 1266 | &flow.daddr); |
| 1267 | rc = -EOPNOTSUPP; | 1267 | rc = -EOPNOTSUPP; |
| 1268 | goto put_rt; | 1268 | goto put_rt; |
| @@ -1472,7 +1472,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp, · 203 unmodified lines | |||
| 1472 | rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node, | 1472 | rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node, |
| 1473 | tc_info->flow_ht_params); | 1473 | tc_info->flow_ht_params); |
| 1474 | if (rc) | 1474 | if (rc) |
| 1475 | netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d", | 1475 | netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d\n", |
| 1476 | __func__, rc); | 1476 | __func__, rc); |
| 1477 | 1477 | ||
| 1478 | kfree_rcu(flow_node, rcu); | 1478 | kfree_rcu(flow_node, rcu); |
| @@ -1587,7 +1587,7 @@ unlock: · 108 unmodified lines | |||
| 1587 | free_node: | 1587 | free_node: |
| 1588 | kfree_rcu(new_node, rcu); | 1588 | kfree_rcu(new_node, rcu); |
| 1589 | done: | 1589 | done: |
| 1590 | netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d", | 1590 | netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d\n", |
| 1591 | __func__, tc_flow_cmd->cookie, rc); | 1591 | __func__, tc_flow_cmd->cookie, rc); |
| 1592 | return rc; | 1592 | return rc; |
| 1593 | } | 1593 | } |
| @@ -1700,7 +1700,7 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows, · 106 unmodified lines | |||
| 1700 | le64_to_cpu(resp_bytes[i]); | 1700 | le64_to_cpu(resp_bytes[i]); |
| 1701 | } | 1701 | } |
| 1702 | } else { | 1702 | } else { |
| 1703 | netdev_info(bp->dev, "error rc=%d", rc); | 1703 | netdev_info(bp->dev, "error rc=%d\n", rc); |
| 1704 | } | 1704 | } |
| 1705 | mutex_unlock(&bp->hwrm_cmd_lock); | 1705 | mutex_unlock(&bp->hwrm_cmd_lock); |
| 1706 | 1706 | ||
| @@ -1970,7 +1970,7 @@ static int bnxt_tc_indr_block_event(struct notifier_block *nb, · 263 unmodified lines | |||
| 1970 | bp); | 1970 | bp); |
| 1971 | if (rc) | 1971 | if (rc) |
| 1972 | netdev_info(bp->dev, | 1972 | netdev_info(bp->dev, |
| 1973 | "Failed to register indirect blk: dev: %s", | 1973 | "Failed to register indirect blk: dev: %s\n", |
| 1974 | netdev->name); | 1974 | netdev->name); |
| 1975 | break; | 1975 | break; |
| 1976 | case NETDEV_UNREGISTER: | 1976 | case NETDEV_UNREGISTER: |
| @@ -43,7 +43,7 @@ static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx, · 42 unmodified lines | |||
| 43 | netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x", | 43 | netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x", |
| 44 | *tx_cfa_action, *rx_cfa_code); | 44 | *tx_cfa_action, *rx_cfa_code); |
| 45 | } else { | 45 | } else { |
| 46 | netdev_info(bp->dev, "%s error rc=%d", __func__, rc); | 46 | netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | mutex_unlock(&bp->hwrm_cmd_lock); | 49 | mutex_unlock(&bp->hwrm_cmd_lock); |
| @@ -60,7 +60,7 @@ static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx) · 10 unmodified lines | |||
| 60 | 60 | ||
| 61 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | 61 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 62 | if (rc) | 62 | if (rc) |
| 63 | netdev_info(bp->dev, "%s error rc=%d", __func__, rc); | 63 | netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc); |
| 64 | return rc; | 64 | return rc; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -465,7 +465,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp) · 398 unmodified lines | |||
| 465 | return 0; | 465 | return 0; |
| 466 | 466 | ||
| 467 | err: | 467 | err: |
| 468 | netdev_info(bp->dev, "%s error=%d", __func__, rc); | 468 | netdev_info(bp->dev, "%s error=%d\n", __func__, rc); |
| 469 | kfree(cfa_code_map); | 469 | kfree(cfa_code_map); |
| 470 | __bnxt_vf_reps_destroy(bp); | 470 | __bnxt_vf_reps_destroy(bp); |
| 471 | return rc; | 471 | return rc; |
| @@ -488,7 +488,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode, · 16 unmodified lines | |||
| 488 | 488 | ||
| 489 | mutex_lock(&bp->sriov_lock); | 489 | mutex_lock(&bp->sriov_lock); |
| 490 | if (bp->eswitch_mode == mode) { | 490 | if (bp->eswitch_mode == mode) { |
| 491 | netdev_info(bp->dev, "already in %s eswitch mode", | 491 | netdev_info(bp->dev, "already in %s eswitch mode\n", |
| 492 | mode == DEVLINK_ESWITCH_MODE_LEGACY ? | 492 | mode == DEVLINK_ESWITCH_MODE_LEGACY ? |
| 493 | "legacy" : "switchdev"); | 493 | "legacy" : "switchdev"); |
| 494 | rc = -EINVAL; | 494 | rc = -EINVAL; |
| @@ -508,7 +508,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode, · 13 unmodified lines | |||
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | if (pci_num_vf(bp->pdev) == 0) { | 510 | if (pci_num_vf(bp->pdev) == 0) { |
| 511 | netdev_info(bp->dev, "Enable VFs before setting switchdev mode"); | 511 | netdev_info(bp->dev, "Enable VFs before setting switchdev mode\n"); |
| 512 | rc = -EPERM; | 512 | rc = -EPERM; |
| 513 | goto done; | 513 | goto done; |
| 514 | } | 514 | } |
| @@ -294,6 +294,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) · 293 unmodified lines | |||
| 294 | */ | 294 | */ |
| 295 | if (priv->ext_phy) { | 295 | if (priv->ext_phy) { |
| 296 | reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); | 296 | reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); |
| 297 | reg &= ~ID_MODE_DIS; | ||
| 297 | reg |= id_mode_dis; | 298 | reg |= id_mode_dis; |
| 298 | if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) | 299 | if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) |
| 299 | reg |= RGMII_MODE_EN_V123; | 300 | reg |= RGMII_MODE_EN_V123; |
| @@ -297,6 +297,7 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth, · 296 unmodified lines | |||
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); | 299 | hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
| 300 | hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif); | ||
| 300 | 301 | ||
| 301 | hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT; | 302 | hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT; |
| 302 | hw_ioctxt.cmdq_depth = 0; | 303 | hw_ioctxt.cmdq_depth = 0; |
| @@ -151,8 +151,8 @@ struct hinic_cmd_hw_ioctxt { · 150 unmodified lines | |||
| 151 | 151 | ||
| 152 | u8 lro_en; | 152 | u8 lro_en; |
| 153 | u8 rsvd3; | 153 | u8 rsvd3; |
| 154 | u8 ppf_idx; | ||
| 154 | u8 rsvd4; | 155 | u8 rsvd4; |
| 155 | u8 rsvd5; | ||
| 156 | 156 | ||
| 157 | u16 rq_depth; | 157 | u16 rq_depth; |
| 158 | u16 rx_buf_sz_idx; | 158 | u16 rx_buf_sz_idx; |
| @@ -137,6 +137,7 @@ · 136 unmodified lines | |||
| 137 | #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) | 137 | #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) |
| 138 | #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) | 138 | #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) |
| 139 | #define HINIC_HWIF_PF_IDX(hwif) ((hwif)->attr.pf_idx) | 139 | #define HINIC_HWIF_PF_IDX(hwif) ((hwif)->attr.pf_idx) |
| 140 | #define HINIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) | ||
| 140 | 141 | ||
| 141 | #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) | 142 | #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) |
| 142 | #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) | 143 | #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) |
| @@ -94,6 +94,7 @@ struct hinic_rq { · 93 unmodified lines | |||
| 94 | 94 | ||
| 95 | struct hinic_wq *wq; | 95 | struct hinic_wq *wq; |
| 96 | 96 | ||
| 97 | struct cpumask affinity_mask; | ||
| 97 | u32 irq; | 98 | u32 irq; |
| 98 | u16 msix_entry; | 99 | u16 msix_entry; |
| 99 | 100 | ||
| @@ -356,7 +356,8 @@ static void hinic_enable_rss(struct hinic_dev *nic_dev) · 355 unmodified lines | |||
| 356 | if (!num_cpus) | 356 | if (!num_cpus) |
| 357 | num_cpus = num_online_cpus(); | 357 | num_cpus = num_online_cpus(); |
| 358 | 358 | ||
| 359 | nic_dev->num_qps = min_t(u16, nic_dev->max_qps, num_cpus); | 359 | nic_dev->num_qps = hinic_hwdev_num_qps(hwdev); |
| 360 | nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus); | ||
| 360 | 361 | ||
| 361 | nic_dev->rss_limit = nic_dev->num_qps; | 362 | nic_dev->rss_limit = nic_dev->num_qps; |
| 362 | nic_dev->num_rss = nic_dev->num_qps; | 363 | nic_dev->num_rss = nic_dev->num_qps; |
| @@ -475,7 +475,6 @@ static int rx_request_irq(struct hinic_rxq *rxq) · 474 unmodified lines | |||
| 475 | struct hinic_hwdev *hwdev = nic_dev->hwdev; | 475 | struct hinic_hwdev *hwdev = nic_dev->hwdev; |
| 476 | struct hinic_rq *rq = rxq->rq; | 476 | struct hinic_rq *rq = rxq->rq; |
| 477 | struct hinic_qp *qp; | 477 | struct hinic_qp *qp; |
| 478 | struct cpumask mask; | ||
| 479 | int err; | 478 | int err; |
| 480 | 479 | ||
| 481 | rx_add_napi(rxq); | 480 | rx_add_napi(rxq); |
| @@ -492,8 +491,8 @@ static int rx_request_irq(struct hinic_rxq *rxq) · 10 unmodified lines | |||
| 492 | } | 491 | } |
| 493 | 492 | ||
| 494 | qp = container_of(rq, struct hinic_qp, rq); | 493 | qp = container_of(rq, struct hinic_qp, rq); |
| 495 | cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask); | 494 | cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask); |
| 496 | return irq_set_affinity_hint(rq->irq, &mask); | 495 | return irq_set_affinity_hint(rq->irq, &rq->affinity_mask); |
| 497 | } | 496 | } |
| 498 | 497 | ||
| 499 | static void rx_free_irq(struct hinic_rxq *rxq) | 498 | static void rx_free_irq(struct hinic_rxq *rxq) |
| @@ -5147,7 +5147,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) · 5146 unmodified lines | |||
| 5147 | 5147 | ||
| 5148 | static void mlx5e_nic_disable(struct mlx5e_priv *priv) | 5148 | static void mlx5e_nic_disable(struct mlx5e_priv *priv) |
| 5149 | { | 5149 | { |
| 5150 | struct net_device *netdev = priv->netdev; | ||
| 5151 | struct mlx5_core_dev *mdev = priv->mdev; | 5150 | struct mlx5_core_dev *mdev = priv->mdev; |
| 5152 | 5151 | ||
| 5153 | #ifdef CONFIG_MLX5_CORE_EN_DCB | 5152 | #ifdef CONFIG_MLX5_CORE_EN_DCB |
| @@ -5168,7 +5167,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) · 14 unmodified lines | |||
| 5168 | mlx5e_monitor_counter_cleanup(priv); | 5167 | mlx5e_monitor_counter_cleanup(priv); |
| 5169 | 5168 | ||
| 5170 | mlx5e_disable_async_events(priv); | 5169 | mlx5e_disable_async_events(priv); |
| 5171 | mlx5_lag_remove(mdev, netdev); | 5170 | mlx5_lag_remove(mdev); |
| 5172 | } | 5171 | } |
| 5173 | 5172 | ||
| 5174 | int mlx5e_update_nic_rx(struct mlx5e_priv *priv) | 5173 | int mlx5e_update_nic_rx(struct mlx5e_priv *priv) |
| @@ -1861,7 +1861,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) · 1860 unmodified lines | |||
| 1861 | 1861 | ||
| 1862 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) | 1862 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) |
| 1863 | { | 1863 | { |
| 1864 | struct net_device *netdev = priv->netdev; | ||
| 1865 | struct mlx5_core_dev *mdev = priv->mdev; | 1864 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1866 | struct mlx5e_rep_priv *rpriv = priv->ppriv; | 1865 | struct mlx5e_rep_priv *rpriv = priv->ppriv; |
| 1867 | 1866 | ||
| @@ -1870,7 +1869,7 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) · 2 unmodified lines | |||
| 1870 | #endif | 1869 | #endif |
| 1871 | mlx5_notifier_unregister(mdev, &priv->events_nb); | 1870 | mlx5_notifier_unregister(mdev, &priv->events_nb); |
| 1872 | cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work); | 1871 | cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work); |
| 1873 | mlx5_lag_remove(mdev, netdev); | 1872 | mlx5_lag_remove(mdev); |
| 1874 | } | 1873 | } |
| 1875 | 1874 | ||
| 1876 | static MLX5E_DEFINE_STATS_GRP(sw_rep, 0); | 1875 | static MLX5E_DEFINE_STATS_GRP(sw_rep, 0); |
| @@ -464,9 +464,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this, · 463 unmodified lines | |||
| 464 | struct mlx5_lag *ldev; | 464 | struct mlx5_lag *ldev; |
| 465 | int changed = 0; | 465 | int changed = 0; |
| 466 | 466 | ||
| 467 | if (!net_eq(dev_net(ndev), &init_net)) | ||
| 468 | return NOTIFY_DONE; | ||
| 469 | |||
| 470 | if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE)) | 467 | if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE)) |
| 471 | return NOTIFY_DONE; | 468 | return NOTIFY_DONE; |
| 472 | 469 | ||
| @@ -586,8 +583,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev) · 113 unmodified lines | |||
| 586 | 583 | ||
| 587 | if (!ldev->nb.notifier_call) { | 584 | if (!ldev->nb.notifier_call) { |
| 588 | ldev->nb.notifier_call = mlx5_lag_netdev_event; | 585 | ldev->nb.notifier_call = mlx5_lag_netdev_event; |
| 589 | if (register_netdevice_notifier_dev_net(netdev, &ldev->nb, | 586 | if (register_netdevice_notifier_net(&init_net, &ldev->nb)) { |
| 590 | &ldev->nn)) { | ||
| 591 | ldev->nb.notifier_call = NULL; | 587 | ldev->nb.notifier_call = NULL; |
| 592 | mlx5_core_err(dev, "Failed to register LAG netdev notifier\n"); | 588 | mlx5_core_err(dev, "Failed to register LAG netdev notifier\n"); |
| 593 | } | 589 | } |
| @@ -600,7 +596,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev) · 6 unmodified lines | |||
| 600 | } | 596 | } |
| 601 | 597 | ||
| 602 | /* Must be called with intf_mutex held */ | 598 | /* Must be called with intf_mutex held */ |
| 603 | void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev) | 599 | void mlx5_lag_remove(struct mlx5_core_dev *dev) |
| 604 | { | 600 | { |
| 605 | struct mlx5_lag *ldev; | 601 | struct mlx5_lag *ldev; |
| 606 | int i; | 602 | int i; |
| @@ -620,8 +616,7 @@ void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev) · 13 unmodified lines | |||
| 620 | 616 | ||
| 621 | if (i == MLX5_MAX_PORTS) { | 617 | if (i == MLX5_MAX_PORTS) { |
| 622 | if (ldev->nb.notifier_call) | 618 | if (ldev->nb.notifier_call) |
| 623 | unregister_netdevice_notifier_dev_net(netdev, &ldev->nb, | 619 | unregister_netdevice_notifier_net(&init_net, &ldev->nb); |
| 624 | &ldev->nn); | ||
| 625 | mlx5_lag_mp_cleanup(ldev); | 620 | mlx5_lag_mp_cleanup(ldev); |
| 626 | cancel_delayed_work_sync(&ldev->bond_work); | 621 | cancel_delayed_work_sync(&ldev->bond_work); |
| 627 | mlx5_lag_dev_free(ldev); | 622 | mlx5_lag_dev_free(ldev); |
| @@ -44,7 +44,6 @@ struct mlx5_lag { · 43 unmodified lines | |||
| 44 | struct workqueue_struct *wq; | 44 | struct workqueue_struct *wq; |
| 45 | struct delayed_work bond_work; | 45 | struct delayed_work bond_work; |
| 46 | struct notifier_block nb; | 46 | struct notifier_block nb; |
| 47 | struct netdev_net_notifier nn; | ||
| 48 | struct lag_mp lag_mp; | 47 | struct lag_mp lag_mp; |
| 49 | }; | 48 | }; |
| 50 | 49 | ||
| @@ -157,7 +157,7 @@ int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam, · 156 unmodified lines | |||
| 157 | u8 feature_group, u8 access_reg_group); | 157 | u8 feature_group, u8 access_reg_group); |
| 158 | 158 | ||
| 159 | void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev); | 159 | void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev); |
| 160 | void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev); | 160 | void mlx5_lag_remove(struct mlx5_core_dev *dev); |
| 161 | 161 | ||
| 162 | int mlx5_irq_table_init(struct mlx5_core_dev *dev); | 162 | int mlx5_irq_table_init(struct mlx5_core_dev *dev); |
| 163 | void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev); | 163 | void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev); |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | |||
| 28 | #define MLXSW_PCI_SW_RESET 0xF0010 | 28 | #define MLXSW_PCI_SW_RESET 0xF0010 |
| 29 | #define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) | 29 | #define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) |
| 30 | #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 900000 | 30 | #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 900000 |
| 31 | #define MLXSW_PCI_SW_RESET_WAIT_MSECS 100 | 31 | #define MLXSW_PCI_SW_RESET_WAIT_MSECS 200 |
| 32 | #define MLXSW_PCI_FW_READY 0xA1844 | 32 | #define MLXSW_PCI_FW_READY 0xA1844 |
| 33 | #define MLXSW_PCI_FW_READY_MASK 0xFFFF | 33 | #define MLXSW_PCI_FW_READY_MASK 0xFFFF |
| 34 | #define MLXSW_PCI_FW_READY_MAGIC 0x5E | 34 | #define MLXSW_PCI_FW_READY_MAGIC 0x5E |
| @@ -513,14 +513,17 @@ static irqreturn_t ks_irq(int irq, void *pw) · 512 unmodified lines | |||
| 513 | { | 513 | { |
| 514 | struct net_device *netdev = pw; | 514 | struct net_device *netdev = pw; |
| 515 | struct ks_net *ks = netdev_priv(netdev); | 515 | struct ks_net *ks = netdev_priv(netdev); |
| 516 | unsigned long flags; | ||
| 516 | u16 status; | 517 | u16 status; |
| 517 | 518 | ||
| 519 | spin_lock_irqsave(&ks->statelock, flags); | ||
| 518 | /*this should be the first in IRQ handler */ | 520 | /*this should be the first in IRQ handler */ |
| 519 | ks_save_cmd_reg(ks); | 521 | ks_save_cmd_reg(ks); |
| 520 | 522 | ||
| 521 | status = ks_rdreg16(ks, KS_ISR); | 523 | status = ks_rdreg16(ks, KS_ISR); |
| 522 | if (unlikely(!status)) { | 524 | if (unlikely(!status)) { |
| 523 | ks_restore_cmd_reg(ks); | 525 | ks_restore_cmd_reg(ks); |
| 526 | spin_unlock_irqrestore(&ks->statelock, flags); | ||
| 524 | return IRQ_NONE; | 527 | return IRQ_NONE; |
| 525 | } | 528 | } |
| 526 | 529 | ||
| @@ -546,6 +549,7 @@ static irqreturn_t ks_irq(int irq, void *pw) · 19 unmodified lines | |||
| 546 | ks->netdev->stats.rx_over_errors++; | 549 | ks->netdev->stats.rx_over_errors++; |
| 547 | /* this should be the last in IRQ handler*/ | 550 | /* this should be the last in IRQ handler*/ |
| 548 | ks_restore_cmd_reg(ks); | 551 | ks_restore_cmd_reg(ks); |
| 552 | spin_unlock_irqrestore(&ks->statelock, flags); | ||
| 549 | return IRQ_HANDLED; | 553 | return IRQ_HANDLED; |
| 550 | } | 554 | } |
| 551 | 555 | ||
| @@ -615,6 +619,7 @@ static int ks_net_stop(struct net_device *netdev) · 63 unmodified lines | |||
| 615 | 619 | ||
| 616 | /* shutdown RX/TX QMU */ | 620 | /* shutdown RX/TX QMU */ |
| 617 | ks_disable_qmu(ks); | 621 | ks_disable_qmu(ks); |
| 622 | ks_disable_int(ks); | ||
| 618 | 623 | ||
| 619 | /* set powermode to soft power down to save power */ | 624 | /* set powermode to soft power down to save power */ |
| 620 | ks_set_powermode(ks, PMECR_PM_SOFTDOWN); | 625 | ks_set_powermode(ks, PMECR_PM_SOFTDOWN); |
| @@ -671,10 +676,9 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) · 50 unmodified lines | |||
| 671 | { | 676 | { |
| 672 | netdev_tx_t retv = NETDEV_TX_OK; | 677 | netdev_tx_t retv = NETDEV_TX_OK; |
| 673 | struct ks_net *ks = netdev_priv(netdev); | 678 | struct ks_net *ks = netdev_priv(netdev); |
| 679 | unsigned long flags; | ||
| 674 | 680 | ||
| 675 | disable_irq(netdev->irq); | 681 | spin_lock_irqsave(&ks->statelock, flags); |
| 676 | ks_disable_int(ks); | ||
| 677 | spin_lock(&ks->statelock); | ||
| 678 | 682 | ||
| 679 | /* Extra space are required: | 683 | /* Extra space are required: |
| 680 | * 4 byte for alignment, 4 for status/length, 4 for CRC | 684 | * 4 byte for alignment, 4 for status/length, 4 for CRC |
| @@ -688,9 +692,7 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) · 7 unmodified lines | |||
| 688 | dev_kfree_skb(skb); | 692 | dev_kfree_skb(skb); |
| 689 | } else | 693 | } else |
| 690 | retv = NETDEV_TX_BUSY; | 694 | retv = NETDEV_TX_BUSY; |
| 691 | spin_unlock(&ks->statelock); | 695 | spin_unlock_irqrestore(&ks->statelock, flags); |
| 692 | ks_enable_int(ks); | ||
| 693 | enable_irq(netdev->irq); | ||
| 694 | return retv; | 696 | return retv; |
| 695 | } | 697 | } |
| 696 | 698 | ||
| @@ -13,25 +13,6 @@ · 12 unmodified lines | |||
| 13 | #include "rmnet_vnd.h" | 13 | #include "rmnet_vnd.h" |
| 14 | #include "rmnet_private.h" | 14 | #include "rmnet_private.h" |
| 15 | 15 | ||
| 16 | /* Locking scheme - | ||
| 17 | * The shared resource which needs to be protected is realdev->rx_handler_data. | ||
| 18 | * For the writer path, this is using rtnl_lock(). The writer paths are | ||
| 19 | * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These | ||
| 20 | * paths are already called with rtnl_lock() acquired in. There is also an | ||
| 21 | * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For | ||
| 22 | * dereference here, we will need to use rtnl_dereference(). Dev list writing | ||
| 23 | * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link(). | ||
| 24 | * For the reader path, the real_dev->rx_handler_data is called in the TX / RX | ||
| 25 | * path. We only need rcu_read_lock() for these scenarios. In these cases, | ||
| 26 | * the rcu_read_lock() is held in __dev_queue_xmit() and | ||
| 27 | * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl() | ||
| 28 | * to get the relevant information. For dev list reading, we again acquire | ||
| 29 | * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu(). | ||
| 30 | * We also use unregister_netdevice_many() to free all rmnet devices in | ||
| 31 | * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in | ||
| 32 | * same context. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /* Local Definitions and Declarations */ | 16 | /* Local Definitions and Declarations */ |
| 36 | 17 | ||
| 37 | static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = { | 18 | static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = { |
| @@ -51,9 +32,10 @@ rmnet_get_port_rtnl(const struct net_device *real_dev) · 13 unmodified lines | |||
| 51 | return rtnl_dereference(real_dev->rx_handler_data); | 32 | return rtnl_dereference(real_dev->rx_handler_data); |
| 52 | } | 33 | } |
| 53 | 34 | ||
| 54 | static int rmnet_unregister_real_device(struct net_device *real_dev, | 35 | static int rmnet_unregister_real_device(struct net_device *real_dev) |
| 55 | struct rmnet_port *port) | ||
| 56 | { | 36 | { |
| 37 | struct rmnet_port *port = rmnet_get_port_rtnl(real_dev); | ||
| 38 | |||
| 57 | if (port->nr_rmnet_devs) | 39 | if (port->nr_rmnet_devs) |
| 58 | return -EINVAL; | 40 | return -EINVAL; |
| 59 | 41 | ||
| @@ -61,9 +43,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev, · 1 unmodified line | |||
| 61 | 43 | ||
| 62 | kfree(port); | 44 | kfree(port); |
| 63 | 45 | ||
| 64 | /* release reference on real_dev */ | ||
| 65 | dev_put(real_dev); | ||
| 66 | |||
| 67 | netdev_dbg(real_dev, "Removed from rmnet\n"); | 46 | netdev_dbg(real_dev, "Removed from rmnet\n"); |
| 68 | return 0; | 47 | return 0; |
| 69 | } | 48 | } |
| @@ -89,9 +68,6 @@ static int rmnet_register_real_device(struct net_device *real_dev) · 19 unmodified lines | |||
| 89 | return -EBUSY; | 68 | return -EBUSY; |
| 90 | } | 69 | } |
| 91 | 70 | ||
| 92 | /* hold on to real dev for MAP data */ | ||
| 93 | dev_hold(real_dev); | ||
| 94 | |||
| 95 | for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++) | 71 | for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++) |
| 96 | INIT_HLIST_HEAD(&port->muxed_ep[entry]); | 72 | INIT_HLIST_HEAD(&port->muxed_ep[entry]); |
| 97 | 73 | ||
| @@ -99,28 +75,33 @@ static int rmnet_register_real_device(struct net_device *real_dev) · 1 unmodified line | |||
| 99 | return 0; | 75 | return 0; |
| 100 | } | 76 | } |
| 101 | 77 | ||
| 102 | static void rmnet_unregister_bridge(struct net_device *dev, | 78 | static void rmnet_unregister_bridge(struct rmnet_port *port) |
| 103 | struct rmnet_port *port) | ||
| 104 | { | 79 | { |
| 105 | struct rmnet_port *bridge_port; | 80 | struct net_device *bridge_dev, *real_dev, *rmnet_dev; |
| 106 | struct net_device *bridge_dev; | 81 | struct rmnet_port *real_port; |
| 107 | 82 | ||
| 108 | if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) | 83 | if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) |
| 109 | return; | 84 | return; |
| 110 | 85 | ||
| 111 | /* bridge slave handling */ | 86 | rmnet_dev = port->rmnet_dev; |
| 112 | if (!port->nr_rmnet_devs) { | 87 | if (!port->nr_rmnet_devs) { |
| 113 | bridge_dev = port->bridge_ep; | 88 | /* bridge device */ |
| 89 | real_dev = port->bridge_ep; | ||
| 90 | bridge_dev = port->dev; | ||
| 114 | 91 | ||
| 115 | bridge_port = rmnet_get_port_rtnl(bridge_dev); | 92 | real_port = rmnet_get_port_rtnl(real_dev); |
| 116 | bridge_port->bridge_ep = NULL; | 93 | real_port->bridge_ep = NULL; |
| 117 | bridge_port->rmnet_mode = RMNET_EPMODE_VND; | 94 | real_port->rmnet_mode = RMNET_EPMODE_VND; |
| 118 | } else { | 95 | } else { |
| 96 | /* real device */ | ||
| 119 | bridge_dev = port->bridge_ep; | 97 | bridge_dev = port->bridge_ep; |
| 120 | 98 | ||
| 121 | bridge_port = rmnet_get_port_rtnl(bridge_dev); | 99 | port->bridge_ep = NULL; |
| 122 | rmnet_unregister_real_device(bridge_dev, bridge_port); | 100 | port->rmnet_mode = RMNET_EPMODE_VND; |
| 123 | } | 101 | } |
| 102 | |||
| 103 | netdev_upper_dev_unlink(bridge_dev, rmnet_dev); | ||
| 104 | rmnet_unregister_real_device(bridge_dev); | ||
| 124 | } | 105 | } |
| 125 | 106 | ||
| 126 | static int rmnet_newlink(struct net *src_net, struct net_device *dev, | 107 | static int rmnet_newlink(struct net *src_net, struct net_device *dev, |
| @@ -135,6 +116,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, · 8 unmodified lines | |||
| 135 | int err = 0; | 116 | int err = 0; |
| 136 | u16 mux_id; | 117 | u16 mux_id; |
| 137 | 118 | ||
| 119 | if (!tb[IFLA_LINK]) { | ||
| 120 | NL_SET_ERR_MSG_MOD(extack, "link not specified"); | ||
| 121 | return -EINVAL; | ||
| 122 | } | ||
| 123 | |||
| 138 | real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); | 124 | real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); |
| 139 | if (!real_dev || !dev) | 125 | if (!real_dev || !dev) |
| 140 | return -ENODEV; | 126 | return -ENODEV; |
| @@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, · 16 unmodified lines | |||
| 157 | if (err) | 143 | if (err) |
| 158 | goto err1; | 144 | goto err1; |
| 159 | 145 | ||
| 146 | err = netdev_upper_dev_link(real_dev, dev, extack); | ||
| 147 | if (err < 0) | ||
| 148 | goto err2; | ||
| 149 | |||
| 160 | port->rmnet_mode = mode; | 150 | port->rmnet_mode = mode; |
| 151 | port->rmnet_dev = dev; | ||
| 161 | 152 | ||
| 162 | hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); | 153 | hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); |
| 163 | 154 | ||
| @@ -173,8 +164,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, · 9 unmodified lines | |||
| 173 | 164 | ||
| 174 | return 0; | 165 | return 0; |
| 175 | 166 | ||
| 167 | err2: | ||
| 168 | unregister_netdevice(dev); | ||
| 169 | rmnet_vnd_dellink(mux_id, port, ep); | ||
| 176 | err1: | 170 | err1: |
| 177 | rmnet_unregister_real_device(real_dev, port); | 171 | rmnet_unregister_real_device(real_dev); |
| 178 | err0: | 172 | err0: |
| 179 | kfree(ep); | 173 | kfree(ep); |
| 180 | return err; | 174 | return err; |
| @@ -183,77 +177,74 @@ err0: · 2 unmodified lines | |||
| 183 | static void rmnet_dellink(struct net_device *dev, struct list_head *head) | 177 | static void rmnet_dellink(struct net_device *dev, struct list_head *head) |
| 184 | { | 178 | { |
| 185 | struct rmnet_priv *priv = netdev_priv(dev); | 179 | struct rmnet_priv *priv = netdev_priv(dev); |
| 186 | struct net_device *real_dev; | 180 | struct net_device *real_dev, *bridge_dev; |
| 181 | struct rmnet_port *real_port, *bridge_port; | ||
| 187 | struct rmnet_endpoint *ep; | 182 | struct rmnet_endpoint *ep; |
| 188 | struct rmnet_port *port; | 183 | u8 mux_id = priv->mux_id; |
| 189 | u8 mux_id; | ||
| 190 | 184 | ||
| 191 | real_dev = priv->real_dev; | 185 | real_dev = priv->real_dev; |
| 192 | 186 | ||
| 193 | if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) | 187 | if (!rmnet_is_real_dev_registered(real_dev)) |
| 194 | return; | 188 | return; |
| 195 | 189 | ||
| 196 | port = rmnet_get_port_rtnl(real_dev); | 190 | real_port = rmnet_get_port_rtnl(real_dev); |
| 197 | 191 | bridge_dev = real_port->bridge_ep; | |
| 198 | mux_id = rmnet_vnd_get_mux(dev); | 192 | if (bridge_dev) { |
| 193 | bridge_port = rmnet_get_port_rtnl(bridge_dev); | ||
| 194 | rmnet_unregister_bridge(bridge_port); | ||
| 195 | } | ||
| 199 | 196 | ||
| 200 | ep = rmnet_get_endpoint(port, mux_id); | 197 | ep = rmnet_get_endpoint(real_port, mux_id); |
| 201 | if (ep) { | 198 | if (ep) { |
| 202 | hlist_del_init_rcu(&ep->hlnode); | 199 | hlist_del_init_rcu(&ep->hlnode); |
| 203 | rmnet_unregister_bridge(dev, port); | 200 | rmnet_vnd_dellink(mux_id, real_port, ep); |
| 204 | rmnet_vnd_dellink(mux_id, port, ep); | ||
| 205 | kfree(ep); | 201 | kfree(ep); |
| 206 | } | 202 | } |
| 207 | rmnet_unregister_real_device(real_dev, port); | ||
| 208 | 203 | ||
| 204 | netdev_upper_dev_unlink(real_dev, dev); | ||
| 205 | rmnet_unregister_real_device(real_dev); | ||
| 209 | unregister_netdevice_queue(dev, head); | 206 | unregister_netdevice_queue(dev, head); |
| 210 | } | 207 | } |
| 211 | 208 | ||
| 212 | static void rmnet_force_unassociate_device(struct net_device *dev) | 209 | static void rmnet_force_unassociate_device(struct net_device *real_dev) |
| 213 | { | 210 | { |
| 214 | struct net_device *real_dev = dev; | ||
| 215 | struct hlist_node *tmp_ep; | 211 | struct hlist_node *tmp_ep; |
| 216 | struct rmnet_endpoint *ep; | 212 | struct rmnet_endpoint *ep; |
| 217 | struct rmnet_port *port; | 213 | struct rmnet_port *port; |
| 218 | unsigned long bkt_ep; | 214 | unsigned long bkt_ep; |
| 219 | LIST_HEAD(list); | 215 | LIST_HEAD(list); |
| 220 | 216 | ||
| 221 | if (!rmnet_is_real_dev_registered(real_dev)) | 217 | port = rmnet_get_port_rtnl(real_dev); |
| 222 | return; | ||
| 223 | |||
| 224 | ASSERT_RTNL(); | ||
| 225 | |||
| 226 | port = rmnet_get_port_rtnl(dev); | ||
| 227 | |||
| 228 | rcu_read_lock(); | ||
| 229 | rmnet_unregister_bridge(dev, port); | ||
| 230 | |||
| 231 | hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) { | ||
| 232 | unregister_netdevice_queue(ep->egress_dev, &list); | ||
| 233 | rmnet_vnd_dellink(ep->mux_id, port, ep); | ||
| 234 | 218 | ||
| 235 | hlist_del_init_rcu(&ep->hlnode); | 219 | if (port->nr_rmnet_devs) { |
| 236 | kfree(ep); | 220 | /* real device */ |
| 221 | rmnet_unregister_bridge(port); | ||
| 222 | hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) { | ||
| 223 | unregister_netdevice_queue(ep->egress_dev, &list); | ||
| 224 | netdev_upper_dev_unlink(real_dev, ep->egress_dev); | ||
| 225 | rmnet_vnd_dellink(ep->mux_id, port, ep); | ||
| 226 | hlist_del_init_rcu(&ep->hlnode); | ||
| 227 | kfree(ep); | ||
| 228 | } | ||
| 229 | rmnet_unregister_real_device(real_dev); | ||
| 230 | unregister_netdevice_many(&list); | ||
| 231 | } else { | ||
| 232 | rmnet_unregister_bridge(port); | ||
| 237 | } | 233 | } |
| 238 | |||
| 239 | rcu_read_unlock(); | ||
| 240 | unregister_netdevice_many(&list); | ||
| 241 | |||
| 242 | rmnet_unregister_real_device(real_dev, port); | ||
| 243 | } | 234 | } |
| 244 | 235 | ||
| 245 | static int rmnet_config_notify_cb(struct notifier_block *nb, | 236 | static int rmnet_config_notify_cb(struct notifier_block *nb, |
| 246 | unsigned long event, void *data) | 237 | unsigned long event, void *data) |
| 247 | { | 238 | { |
| 248 | struct net_device *dev = netdev_notifier_info_to_dev(data); | 239 | struct net_device *real_dev = netdev_notifier_info_to_dev(data); |
| 249 | 240 | ||
| 250 | if (!dev) | 241 | if (!rmnet_is_real_dev_registered(real_dev)) |
| 251 | return NOTIFY_DONE; | 242 | return NOTIFY_DONE; |
| 252 | 243 | ||
| 253 | switch (event) { | 244 | switch (event) { |
| 254 | case NETDEV_UNREGISTER: | 245 | case NETDEV_UNREGISTER: |
| 255 | netdev_dbg(dev, "Kernel unregister\n"); | 246 | netdev_dbg(real_dev, "Kernel unregister\n"); |
| 256 | rmnet_force_unassociate_device(dev); | 247 | rmnet_force_unassociate_device(real_dev); |
| 257 | break; | 248 | break; |
| 258 | 249 | ||
| 259 | default: | 250 | default: |
| @@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[], · 35 unmodified lines | |||
| 295 | if (!dev) | 286 | if (!dev) |
| 296 | return -ENODEV; | 287 | return -ENODEV; |
| 297 | 288 | ||
| 298 | real_dev = __dev_get_by_index(dev_net(dev), | 289 | real_dev = priv->real_dev; |
| 299 | nla_get_u32(tb[IFLA_LINK])); | 290 | if (!rmnet_is_real_dev_registered(real_dev)) |
| 300 | |||
| 301 | if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) | ||
| 302 | return -ENODEV; | 291 | return -ENODEV; |
| 303 | 292 | ||
| 304 | port = rmnet_get_port_rtnl(real_dev); | 293 | port = rmnet_get_port_rtnl(real_dev); |
| 305 | 294 | ||
| 306 | if (data[IFLA_RMNET_MUX_ID]) { | 295 | if (data[IFLA_RMNET_MUX_ID]) { |
| 307 | mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]); | 296 | mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]); |
| 297 | if (rmnet_get_endpoint(port, mux_id)) { | ||
| 298 | NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists"); | ||
| 299 | return -EINVAL; | ||
| 300 | } | ||
| 308 | ep = rmnet_get_endpoint(port, priv->mux_id); | 301 | ep = rmnet_get_endpoint(port, priv->mux_id); |
| 309 | if (!ep) | 302 | if (!ep) |
| 310 | return -ENODEV; | 303 | return -ENODEV; |
| @@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = { · 68 unmodified lines | |||
| 379 | .fill_info = rmnet_fill_info, | 372 | .fill_info = rmnet_fill_info, |
| 380 | }; | 373 | }; |
| 381 | 374 | ||
| 382 | /* Needs either rcu_read_lock() or rtnl lock */ | 375 | struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev) |
| 383 | struct rmnet_port *rmnet_get_port(struct net_device *real_dev) | ||
| 384 | { | 376 | { |
| 385 | if (rmnet_is_real_dev_registered(real_dev)) | 377 | if (rmnet_is_real_dev_registered(real_dev)) |
| 386 | return rcu_dereference_rtnl(real_dev->rx_handler_data); | 378 | return rcu_dereference_bh(real_dev->rx_handler_data); |
| 387 | else | 379 | else |
| 388 | return NULL; | 380 | return NULL; |
| 389 | } | 381 | } |
| @@ -409,7 +401,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 19 unmodified lines | |||
| 409 | struct rmnet_port *port, *slave_port; | 401 | struct rmnet_port *port, *slave_port; |
| 410 | int err; | 402 | int err; |
| 411 | 403 | ||
| 412 | port = rmnet_get_port(real_dev); | 404 | port = rmnet_get_port_rtnl(real_dev); |
| 413 | 405 | ||
| 414 | /* If there is more than one rmnet dev attached, its probably being | 406 | /* If there is more than one rmnet dev attached, its probably being |
| 415 | * used for muxing. Skip the briding in that case | 407 | * used for muxing. Skip the briding in that case |
| @@ -417,6 +409,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 1 unmodified line | |||
| 417 | if (port->nr_rmnet_devs > 1) | 409 | if (port->nr_rmnet_devs > 1) |
| 418 | return -EINVAL; | 410 | return -EINVAL; |
| 419 | 411 | ||
| 412 | if (port->rmnet_mode != RMNET_EPMODE_VND) | ||
| 413 | return -EINVAL; | ||
| 414 | |||
| 420 | if (rmnet_is_real_dev_registered(slave_dev)) | 415 | if (rmnet_is_real_dev_registered(slave_dev)) |
| 421 | return -EBUSY; | 416 | return -EBUSY; |
| 422 | 417 | ||
| @@ -424,9 +419,17 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 1 unmodified line | |||
| 424 | if (err) | 419 | if (err) |
| 425 | return -EBUSY; | 420 | return -EBUSY; |
| 426 | 421 | ||
| 427 | slave_port = rmnet_get_port(slave_dev); | 422 | err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL, |
| 423 | extack); | ||
| 424 | if (err) { | ||
| 425 | rmnet_unregister_real_device(slave_dev); | ||
| 426 | return err; | ||
| 427 | } | ||
| 428 | |||
| 429 | slave_port = rmnet_get_port_rtnl(slave_dev); | ||
| 428 | slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; | 430 | slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; |
| 429 | slave_port->bridge_ep = real_dev; | 431 | slave_port->bridge_ep = real_dev; |
| 432 | slave_port->rmnet_dev = rmnet_dev; | ||
| 430 | 433 | ||
| 431 | port->rmnet_mode = RMNET_EPMODE_BRIDGE; | 434 | port->rmnet_mode = RMNET_EPMODE_BRIDGE; |
| 432 | port->bridge_ep = slave_dev; | 435 | port->bridge_ep = slave_dev; |
| @@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 5 unmodified lines | |||
| 438 | int rmnet_del_bridge(struct net_device *rmnet_dev, | 441 | int rmnet_del_bridge(struct net_device *rmnet_dev, |
| 439 | struct net_device *slave_dev) | 442 | struct net_device *slave_dev) |
| 440 | { | 443 | { |
| 441 | struct rmnet_priv *priv = netdev_priv(rmnet_dev); | 444 | struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev); |
| 442 | struct net_device *real_dev = priv->real_dev; | ||
| 443 | struct rmnet_port *port, *slave_port; | ||
| 444 | 445 | ||
| 445 | port = rmnet_get_port(real_dev); | 446 | rmnet_unregister_bridge(port); |
| 446 | port->rmnet_mode = RMNET_EPMODE_VND; | ||
| 447 | port->bridge_ep = NULL; | ||
| 448 | |||
| 449 | slave_port = rmnet_get_port(slave_dev); | ||
| 450 | rmnet_unregister_real_device(slave_dev, slave_port); | ||
| 451 | 447 | ||
| 452 | netdev_dbg(slave_dev, "removed from rmnet as slave\n"); | 448 | netdev_dbg(slave_dev, "removed from rmnet as slave\n"); |
| 453 | return 0; | 449 | return 0; |
| @@ -473,8 +469,8 @@ static int __init rmnet_init(void) · 19 unmodified lines | |||
| 473 | 469 | ||
| 474 | static void __exit rmnet_exit(void) | 470 | static void __exit rmnet_exit(void) |
| 475 | { | 471 | { |
| 476 | unregister_netdevice_notifier(&rmnet_dev_notifier); | ||
| 477 | rtnl_link_unregister(&rmnet_link_ops); | 472 | rtnl_link_unregister(&rmnet_link_ops); |
| 473 | unregister_netdevice_notifier(&rmnet_dev_notifier); | ||
| 478 | } | 474 | } |
| 479 | 475 | ||
| 480 | module_init(rmnet_init) | 476 | module_init(rmnet_init) |
| @@ -28,6 +28,7 @@ struct rmnet_port { · 27 unmodified lines | |||
| 28 | u8 rmnet_mode; | 28 | u8 rmnet_mode; |
| 29 | struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; | 29 | struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; |
| 30 | struct net_device *bridge_ep; | 30 | struct net_device *bridge_ep; |
| 31 | struct net_device *rmnet_dev; | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | extern struct rtnl_link_ops rmnet_link_ops; | 34 | extern struct rtnl_link_ops rmnet_link_ops; |
| @@ -65,7 +66,7 @@ struct rmnet_priv { · 31 unmodified lines | |||
| 65 | struct rmnet_priv_stats stats; | 66 | struct rmnet_priv_stats stats; |
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | struct rmnet_port *rmnet_get_port(struct net_device *real_dev); | 69 | struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev); |
| 69 | struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); | 70 | struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); |
| 70 | int rmnet_add_bridge(struct net_device *rmnet_dev, | 71 | int rmnet_add_bridge(struct net_device *rmnet_dev, |
| 71 | struct net_device *slave_dev, | 72 | struct net_device *slave_dev, |
| @@ -159,6 +159,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, · 158 unmodified lines | |||
| 159 | static void | 159 | static void |
| 160 | rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) | 160 | rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) |
| 161 | { | 161 | { |
| 162 | if (skb_mac_header_was_set(skb)) | ||
| 163 | skb_push(skb, skb->mac_len); | ||
| 164 | |||
| 162 | if (bridge_dev) { | 165 | if (bridge_dev) { |
| 163 | skb->dev = bridge_dev; | 166 | skb->dev = bridge_dev; |
| 164 | dev_queue_xmit(skb); | 167 | dev_queue_xmit(skb); |
| @@ -184,7 +187,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) · 19 unmodified lines | |||
| 184 | return RX_HANDLER_PASS; | 187 | return RX_HANDLER_PASS; |
| 185 | 188 | ||
| 186 | dev = skb->dev; | 189 | dev = skb->dev; |
| 187 | port = rmnet_get_port(dev); | 190 | port = rmnet_get_port_rcu(dev); |
| 188 | 191 | ||
| 189 | switch (port->rmnet_mode) { | 192 | switch (port->rmnet_mode) { |
| 190 | case RMNET_EPMODE_VND: | 193 | case RMNET_EPMODE_VND: |
| @@ -217,7 +220,7 @@ void rmnet_egress_handler(struct sk_buff *skb) · 26 unmodified lines | |||
| 217 | skb->dev = priv->real_dev; | 220 | skb->dev = priv->real_dev; |
| 218 | mux_id = priv->mux_id; | 221 | mux_id = priv->mux_id; |
| 219 | 222 | ||
| 220 | port = rmnet_get_port(skb->dev); | 223 | port = rmnet_get_port_rcu(skb->dev); |
| 221 | if (!port) | 224 | if (!port) |
| 222 | goto drop; | 225 | goto drop; |
| 223 | 226 | ||
| @@ -266,14 +266,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, · 265 unmodified lines | |||
| 266 | return 0; | 266 | return 0; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev) | ||
| 270 | { | ||
| 271 | struct rmnet_priv *priv; | ||
| 272 | |||
| 273 | priv = netdev_priv(rmnet_dev); | ||
| 274 | return priv->mux_id; | ||
| 275 | } | ||
| 276 | |||
| 277 | int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) | 269 | int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) |
| 278 | { | 270 | { |
| 279 | netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable); | 271 | netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable); |
| @@ -16,6 +16,5 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, · 15 unmodified lines | |||
| 16 | struct rmnet_endpoint *ep); | 16 | struct rmnet_endpoint *ep); |
| 17 | void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); | 17 | void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); |
| 18 | void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); | 18 | void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); |
| 19 | u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev); | ||
| 20 | void rmnet_vnd_setup(struct net_device *dev); | 19 | void rmnet_vnd_setup(struct net_device *dev); |
| 21 | #endif /* _RMNET_VND_H_ */ | 20 | #endif /* _RMNET_VND_H_ */ |
| @@ -560,13 +560,45 @@ efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx, · 559 unmodified lines | |||
| 560 | u32 nic_major, u32 nic_minor, | 560 | u32 nic_major, u32 nic_minor, |
| 561 | s32 correction) | 561 | s32 correction) |
| 562 | { | 562 | { |
| 563 | u32 sync_timestamp; | ||
| 563 | ktime_t kt = { 0 }; | 564 | ktime_t kt = { 0 }; |
| 565 | s16 delta; | ||
| 564 | 566 | ||
| 565 | if (!(nic_major & 0x80000000)) { | 567 | if (!(nic_major & 0x80000000)) { |
| 566 | WARN_ON_ONCE(nic_major >> 16); | 568 | WARN_ON_ONCE(nic_major >> 16); |
| 567 | /* Use the top bits from the latest sync event. */ | 569 | |
| 568 | nic_major &= 0xffff; | 570 | /* Medford provides 48 bits of timestamp, so we must get the top |
| 569 | nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000); | 571 | * 16 bits from the timesync event state. |
| 572 | * | ||
| 573 | * We only have the lower 16 bits of the time now, but we do | ||
| 574 | * have a full resolution timestamp at some point in past. As | ||
| 575 | * long as the difference between the (real) now and the sync | ||
| 576 | * is less than 2^15, then we can reconstruct the difference | ||
| 577 | * between those two numbers using only the lower 16 bits of | ||
| 578 | * each. | ||
| 579 | * | ||
| 580 | * Put another way | ||
| 581 | * | ||
| 582 | * a - b = ((a mod k) - b) mod k | ||
| 583 | * | ||
| 584 | * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know | ||
| 585 | * (a mod k) and b, so can calculate the delta, a - b. | ||
| 586 | * | ||
| 587 | */ | ||
| 588 | sync_timestamp = last_sync_timestamp_major(efx); | ||
| 589 | |||
| 590 | /* Because delta is s16 this does an implicit mask down to | ||
| 591 | * 16 bits which is what we need, assuming | ||
| 592 | * MEDFORD_TX_SECS_EVENT_BITS is 16. delta is signed so that | ||
| 593 | * we can deal with the (unlikely) case of sync timestamps | ||
| 594 | * arriving from the future. | ||
| 595 | */ | ||
| 596 | delta = nic_major - sync_timestamp; | ||
| 597 | |||
| 598 | /* Recover the fully specified time now, by applying the offset | ||
| 599 | * to the (fully specified) sync time. | ||
| 600 | */ | ||
| 601 | nic_major = sync_timestamp + delta; | ||
| 570 | 602 | ||
| 571 | kt = ptp->nic_to_kernel_time(nic_major, nic_minor, | 603 | kt = ptp->nic_to_kernel_time(nic_major, nic_minor, |
| 572 | correction); | 604 | correction); |
| @@ -4405,6 +4405,8 @@ static void stmmac_init_fs(struct net_device *dev) · 4404 unmodified lines | |||
| 4405 | { | 4405 | { |
| 4406 | struct stmmac_priv *priv = netdev_priv(dev); | 4406 | struct stmmac_priv *priv = netdev_priv(dev); |
| 4407 | 4407 | ||
| 4408 | rtnl_lock(); | ||
| 4409 | |||
| 4408 | /* Create per netdev entries */ | 4410 | /* Create per netdev entries */ |
| 4409 | priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); | 4411 | priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); |
| 4410 | 4412 | ||
| @@ -4416,14 +4418,13 @@ static void stmmac_init_fs(struct net_device *dev) · 5 unmodified lines | |||
| 4416 | debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev, | 4418 | debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev, |
| 4417 | &stmmac_dma_cap_fops); | 4419 | &stmmac_dma_cap_fops); |
| 4418 | 4420 | ||
| 4419 | register_netdevice_notifier(&stmmac_notifier); | 4421 | rtnl_unlock(); |
| 4420 | } | 4422 | } |
| 4421 | 4423 | ||
| 4422 | static void stmmac_exit_fs(struct net_device *dev) | 4424 | static void stmmac_exit_fs(struct net_device *dev) |
| 4423 | { | 4425 | { |
| 4424 | struct stmmac_priv *priv = netdev_priv(dev); | 4426 | struct stmmac_priv *priv = netdev_priv(dev); |
| 4425 | 4427 | ||
| 4426 | unregister_netdevice_notifier(&stmmac_notifier); | ||
| 4427 | debugfs_remove_recursive(priv->dbgfs_dir); | 4428 | debugfs_remove_recursive(priv->dbgfs_dir); |
| 4428 | } | 4429 | } |
| 4429 | #endif /* CONFIG_DEBUG_FS */ | 4430 | #endif /* CONFIG_DEBUG_FS */ |
| @@ -4940,14 +4941,14 @@ int stmmac_dvr_remove(struct device *dev) · 510 unmodified lines | |||
| 4940 | 4941 | ||
| 4941 | netdev_info(priv->dev, "%s: removing driver", __func__); | 4942 | netdev_info(priv->dev, "%s: removing driver", __func__); |
| 4942 | 4943 | ||
| 4943 | #ifdef CONFIG_DEBUG_FS | ||
| 4944 | stmmac_exit_fs(ndev); | ||
| 4945 | #endif | ||
| 4946 | stmmac_stop_all_dma(priv); | 4944 | stmmac_stop_all_dma(priv); |
| 4947 | 4945 | ||
| 4948 | stmmac_mac_set(priv, priv->ioaddr, false); | 4946 | stmmac_mac_set(priv, priv->ioaddr, false); |
| 4949 | netif_carrier_off(ndev); | 4947 | netif_carrier_off(ndev); |
| 4950 | unregister_netdev(ndev); | 4948 | unregister_netdev(ndev); |
| 4949 | #ifdef CONFIG_DEBUG_FS | ||
| 4950 | stmmac_exit_fs(ndev); | ||
| 4951 | #endif | ||
| 4951 | phylink_destroy(priv->phylink); | 4952 | phylink_destroy(priv->phylink); |
| 4952 | if (priv->plat->stmmac_rst) | 4953 | if (priv->plat->stmmac_rst) |
| 4953 | reset_control_assert(priv->plat->stmmac_rst); | 4954 | reset_control_assert(priv->plat->stmmac_rst); |
| @@ -5166,6 +5167,7 @@ static int __init stmmac_init(void) · 212 unmodified lines | |||
| 5166 | /* Create debugfs main directory if it doesn't exist yet */ | 5167 | /* Create debugfs main directory if it doesn't exist yet */ |
| 5167 | if (!stmmac_fs_dir) | 5168 | if (!stmmac_fs_dir) |
| 5168 | stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); | 5169 | stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); |
| 5170 | register_netdevice_notifier(&stmmac_notifier); | ||
| 5169 | #endif | 5171 | #endif |
| 5170 | 5172 | ||
| 5171 | return 0; | 5173 | return 0; |
| @@ -5174,6 +5176,7 @@ static int __init stmmac_init(void) · 2 unmodified lines | |||
| 5174 | static void __exit stmmac_exit(void) | 5176 | static void __exit stmmac_exit(void) |
| 5175 | { | 5177 | { |
| 5176 | #ifdef CONFIG_DEBUG_FS | 5178 | #ifdef CONFIG_DEBUG_FS |
| 5179 | unregister_netdevice_notifier(&stmmac_notifier); | ||
| 5177 | debugfs_remove_recursive(stmmac_fs_dir); | 5180 | debugfs_remove_recursive(stmmac_fs_dir); |
| 5178 | #endif | 5181 | #endif |
| 5179 | } | 5182 | } |
| @@ -375,10 +375,14 @@ struct temac_local { · 374 unmodified lines | |||
| 375 | int tx_bd_next; | 375 | int tx_bd_next; |
| 376 | int tx_bd_tail; | 376 | int tx_bd_tail; |
| 377 | int rx_bd_ci; | 377 | int rx_bd_ci; |
| 378 | int rx_bd_tail; | ||
| 378 | 379 | ||
| 379 | /* DMA channel control setup */ | 380 | /* DMA channel control setup */ |
| 380 | u32 tx_chnl_ctrl; | 381 | u32 tx_chnl_ctrl; |
| 381 | u32 rx_chnl_ctrl; | 382 | u32 rx_chnl_ctrl; |
| 383 | u8 coalesce_count_rx; | ||
| 384 | |||
| 385 | struct delayed_work restart_work; | ||
| 382 | }; | 386 | }; |
| 383 | 387 | ||
| 384 | /* Wrappers for temac_ior()/temac_iow() function pointers above */ | 388 | /* Wrappers for temac_ior()/temac_iow() function pointers above */ |
| @@ -51,6 +51,7 @@ · 50 unmodified lines | |||
| 51 | #include <linux/ip.h> | 51 | #include <linux/ip.h> |
| 52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 53 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
| 54 | #include <linux/workqueue.h> | ||
| 54 | #include <linux/dma-mapping.h> | 55 | #include <linux/dma-mapping.h> |
| 55 | #include <linux/processor.h> | 56 | #include <linux/processor.h> |
| 56 | #include <linux/platform_data/xilinx-ll-temac.h> | 57 | #include <linux/platform_data/xilinx-ll-temac.h> |
| @@ -367,6 +368,8 @@ static int temac_dma_bd_init(struct net_device *ndev) · 310 unmodified lines | |||
| 367 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, | 368 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, |
| 368 | XTE_MAX_JUMBO_FRAME_SIZE, | 369 | XTE_MAX_JUMBO_FRAME_SIZE, |
| 369 | DMA_FROM_DEVICE); | 370 | DMA_FROM_DEVICE); |
| 371 | if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) | ||
| 372 | goto out; | ||
| 370 | lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr); | 373 | lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr); |
| 371 | lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); | 374 | lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); |
| 372 | lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); | 375 | lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); |
| @@ -387,12 +390,13 @@ static int temac_dma_bd_init(struct net_device *ndev) · 14 unmodified lines | |||
| 387 | lp->tx_bd_next = 0; | 390 | lp->tx_bd_next = 0; |
| 388 | lp->tx_bd_tail = 0; | 391 | lp->tx_bd_tail = 0; |
| 389 | lp->rx_bd_ci = 0; | 392 | lp->rx_bd_ci = 0; |
| 393 | lp->rx_bd_tail = RX_BD_NUM - 1; | ||
| 390 | 394 | ||
| 391 | /* Enable RX DMA transfers */ | 395 | /* Enable RX DMA transfers */ |
| 392 | wmb(); | 396 | wmb(); |
| 393 | lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p); | 397 | lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p); |
| 394 | lp->dma_out(lp, RX_TAILDESC_PTR, | 398 | lp->dma_out(lp, RX_TAILDESC_PTR, |
| 395 | lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); | 399 | lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail)); |
| 396 | 400 | ||
| 397 | /* Prepare for TX DMA transfer */ | 401 | /* Prepare for TX DMA transfer */ |
| 398 | lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); | 402 | lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); |
| @@ -788,6 +792,9 @@ static void temac_start_xmit_done(struct net_device *ndev) · 389 unmodified lines | |||
| 788 | stat = be32_to_cpu(cur_p->app0); | 792 | stat = be32_to_cpu(cur_p->app0); |
| 789 | } | 793 | } |
| 790 | 794 | ||
| 795 | /* Matches barrier in temac_start_xmit */ | ||
| 796 | smp_mb(); | ||
| 797 | |||
| 791 | netif_wake_queue(ndev); | 798 | netif_wake_queue(ndev); |
| 792 | } | 799 | } |
| 793 | 800 | ||
| @@ -830,9 +837,19 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 36 unmodified lines | |||
| 830 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; | 837 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; |
| 831 | 838 | ||
| 832 | if (temac_check_tx_bd_space(lp, num_frag + 1)) { | 839 | if (temac_check_tx_bd_space(lp, num_frag + 1)) { |
| 833 | if (!netif_queue_stopped(ndev)) | 840 | if (netif_queue_stopped(ndev)) |
| 834 | netif_stop_queue(ndev); | 841 | return NETDEV_TX_BUSY; |
| 835 | return NETDEV_TX_BUSY; | 842 | |
| 843 | netif_stop_queue(ndev); | ||
| 844 | |||
| 845 | /* Matches barrier in temac_start_xmit_done */ | ||
| 846 | smp_mb(); | ||
| 847 | |||
| 848 | /* Space might have just been freed - check again */ | ||
| 849 | if (temac_check_tx_bd_space(lp, num_frag)) | ||
| 850 | return NETDEV_TX_BUSY; | ||
| 851 | |||
| 852 | netif_wake_queue(ndev); | ||
| 836 | } | 853 | } |
| 837 | 854 | ||
| 838 | cur_p->app0 = 0; | 855 | cur_p->app0 = 0; |
| @@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 11 unmodified lines | |||
| 850 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, | 867 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, |
| 851 | skb_headlen(skb), DMA_TO_DEVICE); | 868 | skb_headlen(skb), DMA_TO_DEVICE); |
| 852 | cur_p->len = cpu_to_be32(skb_headlen(skb)); | 869 | cur_p->len = cpu_to_be32(skb_headlen(skb)); |
| 870 | if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) { | ||
| 871 | dev_kfree_skb_any(skb); | ||
| 872 | ndev->stats.tx_dropped++; | ||
| 873 | return NETDEV_TX_OK; | ||
| 874 | } | ||
| 853 | cur_p->phys = cpu_to_be32(skb_dma_addr); | 875 | cur_p->phys = cpu_to_be32(skb_dma_addr); |
| 854 | ptr_to_txbd((void *)skb, cur_p); | 876 | ptr_to_txbd((void *)skb, cur_p); |
| 855 | 877 | ||
| 856 | for (ii = 0; ii < num_frag; ii++) { | 878 | for (ii = 0; ii < num_frag; ii++) { |
| 857 | lp->tx_bd_tail++; | 879 | if (++lp->tx_bd_tail >= TX_BD_NUM) |
| 858 | if (lp->tx_bd_tail >= TX_BD_NUM) | ||
| 859 | lp->tx_bd_tail = 0; | 880 | lp->tx_bd_tail = 0; |
| 860 | 881 | ||
| 861 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; | 882 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; |
| @@ -863,6 +884,27 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 1 unmodified line | |||
| 863 | skb_frag_address(frag), | 884 | skb_frag_address(frag), |
| 864 | skb_frag_size(frag), | 885 | skb_frag_size(frag), |
| 865 | DMA_TO_DEVICE); | 886 | DMA_TO_DEVICE); |
| 887 | if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) { | ||
| 888 | if (--lp->tx_bd_tail < 0) | ||
| 889 | lp->tx_bd_tail = TX_BD_NUM - 1; | ||
| 890 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; | ||
| 891 | while (--ii >= 0) { | ||
| 892 | --frag; | ||
| 893 | dma_unmap_single(ndev->dev.parent, | ||
| 894 | be32_to_cpu(cur_p->phys), | ||
| 895 | skb_frag_size(frag), | ||
| 896 | DMA_TO_DEVICE); | ||
| 897 | if (--lp->tx_bd_tail < 0) | ||
| 898 | lp->tx_bd_tail = TX_BD_NUM - 1; | ||
| 899 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; | ||
| 900 | } | ||
| 901 | dma_unmap_single(ndev->dev.parent, | ||
| 902 | be32_to_cpu(cur_p->phys), | ||
| 903 | skb_headlen(skb), DMA_TO_DEVICE); | ||
| 904 | dev_kfree_skb_any(skb); | ||
| 905 | ndev->stats.tx_dropped++; | ||
| 906 | return NETDEV_TX_OK; | ||
| 907 | } | ||
| 866 | cur_p->phys = cpu_to_be32(skb_dma_addr); | 908 | cur_p->phys = cpu_to_be32(skb_dma_addr); |
| 867 | cur_p->len = cpu_to_be32(skb_frag_size(frag)); | 909 | cur_p->len = cpu_to_be32(skb_frag_size(frag)); |
| 868 | cur_p->app0 = 0; | 910 | cur_p->app0 = 0; |
| @@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 15 unmodified lines | |||
| 884 | return NETDEV_TX_OK; | 926 | return NETDEV_TX_OK; |
| 885 | } | 927 | } |
| 886 | 928 | ||
| 929 | static int ll_temac_recv_buffers_available(struct temac_local *lp) | ||
| 930 | { | ||
| 931 | int available; | ||
| 932 | |||
| 933 | if (!lp->rx_skb[lp->rx_bd_ci]) | ||
| 934 | return 0; | ||
| 935 | available = 1 + lp->rx_bd_tail - lp->rx_bd_ci; | ||
| 936 | if (available <= 0) | ||
| 937 | available += RX_BD_NUM; | ||
| 938 | return available; | ||
| 939 | } | ||
| 887 | 940 | ||
| 888 | static void ll_temac_recv(struct net_device *ndev) | 941 | static void ll_temac_recv(struct net_device *ndev) |
| 889 | { | 942 | { |
| 890 | struct temac_local *lp = netdev_priv(ndev); | 943 | struct temac_local *lp = netdev_priv(ndev); |
| 891 | struct sk_buff *skb, *new_skb; | ||
| 892 | unsigned int bdstat; | ||
| 893 | struct cdmac_bd *cur_p; | ||
| 894 | dma_addr_t tail_p, skb_dma_addr; | ||
| 895 | int length; | ||
| 896 | unsigned long flags; | 944 | unsigned long flags; |
| 945 | int rx_bd; | ||
| 946 | bool update_tail = false; | ||
| 897 | 947 | ||
| 898 | spin_lock_irqsave(&lp->rx_lock, flags); | 948 | spin_lock_irqsave(&lp->rx_lock, flags); |
| 899 | 949 | ||
| 900 | tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; | 950 | /* Process all received buffers, passing them on network |
| 901 | cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; | 951 | * stack. After this, the buffer descriptors will be in an |
| 902 | 952 | * un-allocated stage, where no skb is allocated for it, and | |
| 903 | bdstat = be32_to_cpu(cur_p->app0); | 953 | * they are therefore not available for TEMAC/DMA. |
| 904 | while ((bdstat & STS_CTRL_APP0_CMPLT)) { | 954 | */ |
| 955 | do { | ||
| 956 | struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci]; | ||
| 957 | struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci]; | ||
| 958 | unsigned int bdstat = be32_to_cpu(bd->app0); | ||
| 959 | int length; | ||
| 960 | |||
| 961 | /* While this should not normally happen, we can end | ||
| 962 | * here when GFP_ATOMIC allocations fail, and we | ||
| 963 | * therefore have un-allocated buffers. | ||
| 964 | */ | ||
| 965 | if (!skb) | ||
| 966 | break; | ||
| 905 | 967 | ||
| 906 | skb = lp->rx_skb[lp->rx_bd_ci]; | 968 | /* Loop over all completed buffer descriptors */ |
| 907 | length = be32_to_cpu(cur_p->app4) & 0x3FFF; | 969 | if (!(bdstat & STS_CTRL_APP0_CMPLT)) |
| 970 | break; | ||
| 908 | 971 | ||
| 909 | dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys), | 972 | dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys), |
| 910 | XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); | 973 | XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); |
| 974 | /* The buffer is not valid for DMA anymore */ | ||
| 975 | bd->phys = 0; | ||
| 976 | bd->len = 0; | ||
| 911 | 977 | ||
| 978 | length = be32_to_cpu(bd->app4) & 0x3FFF; | ||
| 912 | skb_put(skb, length); | 979 | skb_put(skb, length); |
| 913 | skb->protocol = eth_type_trans(skb, ndev); | 980 | skb->protocol = eth_type_trans(skb, ndev); |
| 914 | skb_checksum_none_assert(skb); | 981 | skb_checksum_none_assert(skb); |
| @@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev) · 8 unmodified lines | |||
| 923 | * (back) for proper IP checksum byte order | 990 | * (back) for proper IP checksum byte order |
| 924 | * (be16). | 991 | * (be16). |
| 925 | */ | 992 | */ |
| 926 | skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF); | 993 | skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF); |
| 927 | skb->ip_summed = CHECKSUM_COMPLETE; | 994 | skb->ip_summed = CHECKSUM_COMPLETE; |
| 928 | } | 995 | } |
| 929 | 996 | ||
| 930 | if (!skb_defer_rx_timestamp(skb)) | 997 | if (!skb_defer_rx_timestamp(skb)) |
| 931 | netif_rx(skb); | 998 | netif_rx(skb); |
| 999 | /* The skb buffer is now owned by network stack above */ | ||
| 1000 | lp->rx_skb[lp->rx_bd_ci] = NULL; | ||
| 932 | 1001 | ||
| 933 | ndev->stats.rx_packets++; | 1002 | ndev->stats.rx_packets++; |
| 934 | ndev->stats.rx_bytes += length; | 1003 | ndev->stats.rx_bytes += length; |
| 935 | 1004 | ||
| 936 | new_skb = netdev_alloc_skb_ip_align(ndev, | 1005 | rx_bd = lp->rx_bd_ci; |
| 937 | XTE_MAX_JUMBO_FRAME_SIZE); | 1006 | if (++lp->rx_bd_ci >= RX_BD_NUM) |
| 938 | if (!new_skb) { | 1007 | lp->rx_bd_ci = 0; |
| 939 | spin_unlock_irqrestore(&lp->rx_lock, flags); | 1008 | } while (rx_bd != lp->rx_bd_tail); |
| 940 | return; | 1009 | |
| 1010 | /* DMA operations will halt when the last buffer descriptor is | ||
| 1011 | * processed (ie. the one pointed to by RX_TAILDESC_PTR). | ||
| 1012 | * When that happens, no more interrupt events will be | ||
| 1013 | * generated. No IRQ_COAL or IRQ_DLY, and not even an | ||
| 1014 | * IRQ_ERR. To avoid stalling, we schedule a delayed work | ||
| 1015 | * when there is a potential risk of that happening. The work | ||
| 1016 | * will call this function, and thus re-schedule itself until | ||
| 1017 | * enough buffers are available again. | ||
| 1018 | */ | ||
| 1019 | if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx) | ||
| 1020 | schedule_delayed_work(&lp->restart_work, HZ / 1000); | ||
| 1021 | |||
| 1022 | /* Allocate new buffers for those buffer descriptors that were | ||
| 1023 | * passed to network stack. Note that GFP_ATOMIC allocations | ||
| 1024 | * can fail (e.g. when a larger burst of GFP_ATOMIC | ||
| 1025 | * allocations occurs), so while we try to allocate all | ||
| 1026 | * buffers in the same interrupt where they were processed, we | ||
| 1027 | * continue with what we could get in case of allocation | ||
| 1028 | * failure. Allocation of remaining buffers will be retried | ||
| 1029 | * in following calls. | ||
| 1030 | */ | ||
| 1031 | while (1) { | ||
| 1032 | struct sk_buff *skb; | ||
| 1033 | struct cdmac_bd *bd; | ||
| 1034 | dma_addr_t skb_dma_addr; | ||
| 1035 | |||
| 1036 | rx_bd = lp->rx_bd_tail + 1; | ||
| 1037 | if (rx_bd >= RX_BD_NUM) | ||
| 1038 | rx_bd = 0; | ||
| 1039 | bd = &lp->rx_bd_v[rx_bd]; | ||
| 1040 | |||
| 1041 | if (bd->phys) | ||
| 1042 | break; /* All skb's allocated */ | ||
| 1043 | |||
| 1044 | skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE); | ||
| 1045 | if (!skb) { | ||
| 1046 | dev_warn(&ndev->dev, "skb alloc failed\n"); | ||
| 1047 | break; | ||
| 941 | } | 1048 | } |
| 942 | 1049 | ||
| 943 | cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); | 1050 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, |
| 944 | skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data, | ||
| 945 | XTE_MAX_JUMBO_FRAME_SIZE, | 1051 | XTE_MAX_JUMBO_FRAME_SIZE, |
| 946 | DMA_FROM_DEVICE); | 1052 | DMA_FROM_DEVICE); |
| 947 | cur_p->phys = cpu_to_be32(skb_dma_addr); | 1053 | if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, |
| 948 | cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); | 1054 | skb_dma_addr))) { |
| 949 | lp->rx_skb[lp->rx_bd_ci] = new_skb; | 1055 | dev_kfree_skb_any(skb); |
| 1056 | break; | ||
| 1057 | } | ||
| 950 | 1058 | ||
| 951 | lp->rx_bd_ci++; | 1059 | bd->phys = cpu_to_be32(skb_dma_addr); |
| 952 | if (lp->rx_bd_ci >= RX_BD_NUM) | 1060 | bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); |
| 953 | lp->rx_bd_ci = 0; | 1061 | bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); |
| 1062 | lp->rx_skb[rx_bd] = skb; | ||
| 954 | 1063 | ||
| 955 | cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; | 1064 | lp->rx_bd_tail = rx_bd; |
| 956 | bdstat = be32_to_cpu(cur_p->app0); | 1065 | update_tail = true; |
| 1066 | } | ||
| 1067 | |||
| 1068 | /* Move tail pointer when buffers have been allocated */ | ||
| 1069 | if (update_tail) { | ||
| 1070 | lp->dma_out(lp, RX_TAILDESC_PTR, | ||
| 1071 | lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail); | ||
| 957 | } | 1072 | } |
| 958 | lp->dma_out(lp, RX_TAILDESC_PTR, tail_p); | ||
| 959 | 1073 | ||
| 960 | spin_unlock_irqrestore(&lp->rx_lock, flags); | 1074 | spin_unlock_irqrestore(&lp->rx_lock, flags); |
| 961 | } | 1075 | } |
| 962 | 1076 | ||
| 1077 | /* Function scheduled to ensure a restart in case of DMA halt | ||
| 1078 | * condition caused by running out of buffer descriptors. | ||
| 1079 | */ | ||
| 1080 | static void ll_temac_restart_work_func(struct work_struct *work) | ||
| 1081 | { | ||
| 1082 | struct temac_local *lp = container_of(work, struct temac_local, | ||
| 1083 | restart_work.work); | ||
| 1084 | struct net_device *ndev = lp->ndev; | ||
| 1085 | |||
| 1086 | ll_temac_recv(ndev); | ||
| 1087 | } | ||
| 1088 | |||
| 963 | static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) | 1089 | static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) |
| 964 | { | 1090 | { |
| 965 | struct net_device *ndev = _ndev; | 1091 | struct net_device *ndev = _ndev; |
| @@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev) · 86 unmodified lines | |||
| 1052 | 1178 | ||
| 1053 | dev_dbg(&ndev->dev, "temac_close()\n"); | 1179 | dev_dbg(&ndev->dev, "temac_close()\n"); |
| 1054 | 1180 | ||
| 1181 | cancel_delayed_work_sync(&lp->restart_work); | ||
| 1182 | |||
| 1055 | free_irq(lp->tx_irq, ndev); | 1183 | free_irq(lp->tx_irq, ndev); |
| 1056 | free_irq(lp->rx_irq, ndev); | 1184 | free_irq(lp->rx_irq, ndev); |
| 1057 | 1185 | ||
| @@ -1173,6 +1301,7 @@ static int temac_probe(struct platform_device *pdev) · 115 unmodified lines | |||
| 1173 | lp->dev = &pdev->dev; | 1301 | lp->dev = &pdev->dev; |
| 1174 | lp->options = XTE_OPTION_DEFAULTS; | 1302 | lp->options = XTE_OPTION_DEFAULTS; |
| 1175 | spin_lock_init(&lp->rx_lock); | 1303 | spin_lock_init(&lp->rx_lock); |
| 1304 | INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func); | ||
| 1176 | 1305 | ||
| 1177 | /* Setup mutex for synchronization of indirect register access */ | 1306 | /* Setup mutex for synchronization of indirect register access */ |
| 1178 | if (pdata) { | 1307 | if (pdata) { |
| @@ -1279,6 +1408,7 @@ static int temac_probe(struct platform_device *pdev) · 100 unmodified lines | |||
| 1279 | */ | 1408 | */ |
| 1280 | lp->tx_chnl_ctrl = 0x10220000; | 1409 | lp->tx_chnl_ctrl = 0x10220000; |
| 1281 | lp->rx_chnl_ctrl = 0xff070000; | 1410 | lp->rx_chnl_ctrl = 0xff070000; |
| 1411 | lp->coalesce_count_rx = 0x07; | ||
| 1282 | 1412 | ||
| 1283 | /* Finished with the DMA node; drop the reference */ | 1413 | /* Finished with the DMA node; drop the reference */ |
| 1284 | of_node_put(dma_np); | 1414 | of_node_put(dma_np); |
| @@ -1310,11 +1440,14 @@ static int temac_probe(struct platform_device *pdev) · 25 unmodified lines | |||
| 1310 | (pdata->tx_irq_count << 16); | 1440 | (pdata->tx_irq_count << 16); |
| 1311 | else | 1441 | else |
| 1312 | lp->tx_chnl_ctrl = 0x10220000; | 1442 | lp->tx_chnl_ctrl = 0x10220000; |
| 1313 | if (pdata->rx_irq_timeout || pdata->rx_irq_count) | 1443 | if (pdata->rx_irq_timeout || pdata->rx_irq_count) { |
| 1314 | lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) | | 1444 | lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) | |
| 1315 | (pdata->rx_irq_count << 16); | 1445 | (pdata->rx_irq_count << 16); |
| 1316 | else | 1446 | lp->coalesce_count_rx = pdata->rx_irq_count; |
| 1447 | } else { | ||
| 1317 | lp->rx_chnl_ctrl = 0xff070000; | 1448 | lp->rx_chnl_ctrl = 0xff070000; |
| 1449 | lp->coalesce_count_rx = 0x07; | ||
| 1450 | } | ||
| 1318 | } | 1451 | } |
| 1319 | 1452 | ||
| 1320 | /* Error handle returned DMA RX and TX interrupts */ | 1453 | /* Error handle returned DMA RX and TX interrupts */ |
| @@ -99,7 +99,7 @@ static struct netvsc_device *alloc_net_device(void) · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | init_waitqueue_head(&net_device->wait_drain); | 100 | init_waitqueue_head(&net_device->wait_drain); |
| 101 | net_device->destroy = false; | 101 | net_device->destroy = false; |
| 102 | net_device->tx_disable = false; | 102 | net_device->tx_disable = true; |
| 103 | 103 | ||
| 104 | net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; | 104 | net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; |
| 105 | net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; | 105 | net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; |
| @@ -1068,6 +1068,7 @@ static int netvsc_attach(struct net_device *ndev, · 1067 unmodified lines | |||
| 1068 | } | 1068 | } |
| 1069 | 1069 | ||
| 1070 | /* In any case device is now ready */ | 1070 | /* In any case device is now ready */ |
| 1071 | nvdev->tx_disable = false; | ||
| 1071 | netif_device_attach(ndev); | 1072 | netif_device_attach(ndev); |
| 1072 | 1073 | ||
| 1073 | /* Note: enable and attach happen when sub-channels setup */ | 1074 | /* Note: enable and attach happen when sub-channels setup */ |
| @@ -2476,6 +2477,8 @@ static int netvsc_probe(struct hv_device *dev, · 1402 unmodified lines | |||
| 2476 | else | 2477 | else |
| 2477 | net->max_mtu = ETH_DATA_LEN; | 2478 | net->max_mtu = ETH_DATA_LEN; |
| 2478 | 2479 | ||
| 2480 | nvdev->tx_disable = false; | ||
| 2481 | |||
| 2479 | ret = register_netdevice(net); | 2482 | ret = register_netdevice(net); |
| 2480 | if (ret != 0) { | 2483 | if (ret != 0) { |
| 2481 | pr_err("Unable to register netdev.\n"); | 2484 | pr_err("Unable to register netdev.\n"); |
| @@ -1306,6 +1306,9 @@ static int marvell_read_status_page_an(struct phy_device *phydev, · 1305 unmodified lines | |||
| 1306 | } | 1306 | } |
| 1307 | } | 1307 | } |
| 1308 | 1308 | ||
| 1309 | if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) | ||
| 1310 | return 0; | ||
| 1311 | |||
| 1309 | if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) | 1312 | if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) |
| 1310 | phydev->duplex = DUPLEX_FULL; | 1313 | phydev->duplex = DUPLEX_FULL; |
| 1311 | else | 1314 | else |
| @@ -1365,6 +1368,8 @@ static int marvell_read_status_page(struct phy_device *phydev, int page) · 53 unmodified lines | |||
| 1365 | linkmode_zero(phydev->lp_advertising); | 1368 | linkmode_zero(phydev->lp_advertising); |
| 1366 | phydev->pause = 0; | 1369 | phydev->pause = 0; |
| 1367 | phydev->asym_pause = 0; | 1370 | phydev->asym_pause = 0; |
| 1371 | phydev->speed = SPEED_UNKNOWN; | ||
| 1372 | phydev->duplex = DUPLEX_UNKNOWN; | ||
| 1368 | 1373 | ||
| 1369 | if (phydev->autoneg == AUTONEG_ENABLE) | 1374 | if (phydev->autoneg == AUTONEG_ENABLE) |
| 1370 | err = marvell_read_status_page_an(phydev, fiber, status); | 1375 | err = marvell_read_status_page_an(phydev, fiber, status); |
| @@ -345,11 +345,11 @@ enum macsec_bank { · 344 unmodified lines | |||
| 345 | BIT(VSC8531_FORCE_LED_OFF) | \ | 345 | BIT(VSC8531_FORCE_LED_OFF) | \ |
| 346 | BIT(VSC8531_FORCE_LED_ON)) | 346 | BIT(VSC8531_FORCE_LED_ON)) |
| 347 | 347 | ||
| 348 | #define MSCC_VSC8584_REVB_INT8051_FW "mscc_vsc8584_revb_int8051_fb48.bin" | 348 | #define MSCC_VSC8584_REVB_INT8051_FW "microchip/mscc_vsc8584_revb_int8051_fb48.bin" |
| 349 | #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800 | 349 | #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800 |
| 350 | #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48 | 350 | #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48 |
| 351 | 351 | ||
| 352 | #define MSCC_VSC8574_REVB_INT8051_FW "mscc_vsc8574_revb_int8051_29e8.bin" | 352 | #define MSCC_VSC8574_REVB_INT8051_FW "microchip/mscc_vsc8574_revb_int8051_29e8.bin" |
| 353 | #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000 | 353 | #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000 |
| 354 | #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8 | 354 | #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8 |
| 355 | 355 | ||
| @@ -167,7 +167,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg); · 166 unmodified lines | |||
| 167 | */ | 167 | */ |
| 168 | int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart) | 168 | int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart) |
| 169 | { | 169 | { |
| 170 | int ret = 0; | 170 | int ret; |
| 171 | 171 | ||
| 172 | if (!restart) { | 172 | if (!restart) { |
| 173 | /* Configure and restart aneg if it wasn't set before */ | 173 | /* Configure and restart aneg if it wasn't set before */ |
| @@ -180,9 +180,9 @@ int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart) · 6 unmodified lines | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | if (restart) | 182 | if (restart) |
| 183 | ret = genphy_c45_restart_aneg(phydev); | 183 | return genphy_c45_restart_aneg(phydev); |
| 184 | 184 | ||
| 185 | return ret; | 185 | return 0; |
| 186 | } | 186 | } |
| 187 | EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg); | 187 | EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg); |
| 188 | 188 | ||
| @@ -247,7 +247,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) · 246 unmodified lines | |||
| 247 | * MDIO bus driver and clock gated at this point. | 247 | * MDIO bus driver and clock gated at this point. |
| 248 | */ | 248 | */ |
| 249 | if (!netdev) | 249 | if (!netdev) |
| 250 | return !phydev->suspended; | 250 | goto out; |
| 251 | 251 | ||
| 252 | if (netdev->wol_enabled) | 252 | if (netdev->wol_enabled) |
| 253 | return false; | 253 | return false; |
| @@ -267,7 +267,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) · 13 unmodified lines | |||
| 267 | if (device_may_wakeup(&netdev->dev)) | 267 | if (device_may_wakeup(&netdev->dev)) |
| 268 | return false; | 268 | return false; |
| 269 | 269 | ||
| 270 | return true; | 270 | out: |
| 271 | return !phydev->suspended; | ||
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | static int mdio_bus_phy_suspend(struct device *dev) | 274 | static int mdio_bus_phy_suspend(struct device *dev) |
| @@ -1792,7 +1793,7 @@ EXPORT_SYMBOL(genphy_restart_aneg); · 1518 unmodified lines | |||
| 1792 | */ | 1793 | */ |
| 1793 | int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) | 1794 | int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) |
| 1794 | { | 1795 | { |
| 1795 | int ret = 0; | 1796 | int ret; |
| 1796 | 1797 | ||
| 1797 | if (!restart) { | 1798 | if (!restart) { |
| 1798 | /* Advertisement hasn't changed, but maybe aneg was never on to | 1799 | /* Advertisement hasn't changed, but maybe aneg was never on to |
| @@ -1807,9 +1808,9 @@ int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) · 8 unmodified lines | |||
| 1807 | } | 1808 | } |
| 1808 | 1809 | ||
| 1809 | if (restart) | 1810 | if (restart) |
| 1810 | ret = genphy_restart_aneg(phydev); | 1811 | return genphy_restart_aneg(phydev); |
| 1811 | 1812 | ||
| 1812 | return ret; | 1813 | return 0; |
| 1813 | } | 1814 | } |
| 1814 | EXPORT_SYMBOL(genphy_check_and_restart_aneg); | 1815 | EXPORT_SYMBOL(genphy_check_and_restart_aneg); |
| 1815 | 1816 | ||
| @@ -863,7 +863,10 @@ err_free_chan: · 862 unmodified lines | |||
| 863 | tty->disc_data = NULL; | 863 | tty->disc_data = NULL; |
| 864 | clear_bit(SLF_INUSE, &sl->flags); | 864 | clear_bit(SLF_INUSE, &sl->flags); |
| 865 | sl_free_netdev(sl->dev); | 865 | sl_free_netdev(sl->dev); |
| 866 | /* do not call free_netdev before rtnl_unlock */ | ||
| 867 | rtnl_unlock(); | ||
| 866 | free_netdev(sl->dev); | 868 | free_netdev(sl->dev); |
| 869 | return err; | ||
| 867 | 870 | ||
| 868 | err_exit: | 871 | err_exit: |
| 869 | rtnl_unlock(); | 872 | rtnl_unlock(); |
| @@ -337,6 +337,9 @@ static void qmi_wwan_netdev_setup(struct net_device *net) · 336 unmodified lines | |||
| 337 | netdev_dbg(net, "mode: raw IP\n"); | 337 | netdev_dbg(net, "mode: raw IP\n"); |
| 338 | } else if (!net->header_ops) { /* don't bother if already set */ | 338 | } else if (!net->header_ops) { /* don't bother if already set */ |
| 339 | ether_setup(net); | 339 | ether_setup(net); |
| 340 | /* Restoring min/max mtu values set originally by usbnet */ | ||
| 341 | net->min_mtu = 0; | ||
| 342 | net->max_mtu = ETH_MAX_MTU; | ||
| 340 | clear_bit(EVENT_NO_IP_ALIGN, &dev->flags); | 343 | clear_bit(EVENT_NO_IP_ALIGN, &dev->flags); |
| 341 | netdev_dbg(net, "mode: Ethernet\n"); | 344 | netdev_dbg(net, "mode: Ethernet\n"); |
| 342 | } | 345 | } |
| @@ -1414,10 +1414,6 @@ static int vhost_net_release(struct inode *inode, struct file *f) · 1413 unmodified lines | |||
| 1414 | 1414 | ||
| 1415 | static struct socket *get_raw_socket(int fd) | 1415 | static struct socket *get_raw_socket(int fd) |
| 1416 | { | 1416 | { |
| 1417 | struct { | ||
| 1418 | struct sockaddr_ll sa; | ||
| 1419 | char buf[MAX_ADDR_LEN]; | ||
| 1420 | } uaddr; | ||
| 1421 | int r; | 1417 | int r; |
| 1422 | struct socket *sock = sockfd_lookup(fd, &r); | 1418 | struct socket *sock = sockfd_lookup(fd, &r); |
| 1423 | 1419 | ||
| @@ -1430,11 +1426,7 @@ static struct socket *get_raw_socket(int fd) · 6 unmodified lines | |||
| 1430 | goto err; | 1426 | goto err; |
| 1431 | } | 1427 | } |
| 1432 | 1428 | ||
| 1433 | r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, 0); | 1429 | if (sock->sk->sk_family != AF_PACKET) { |
| 1434 | if (r < 0) | ||
| 1435 | goto err; | ||
| 1436 | |||
| 1437 | if (uaddr.sa.sll_family != AF_PACKET) { | ||
| 1438 | r = -EPFNOSUPPORT; | 1430 | r = -EPFNOSUPPORT; |
| 1439 | goto err; | 1431 | goto err; |
| 1440 | } | 1432 | } |
| @@ -22,19 +22,23 @@ extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); · 21 unmodified lines | |||
| 22 | int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, | 22 | int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, |
| 23 | unsigned int data_len); | 23 | unsigned int data_len); |
| 24 | 24 | ||
| 25 | #if IS_ENABLED(CONFIG_NF_NAT) | ||
| 26 | void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); | ||
| 27 | #else | ||
| 28 | #define icmpv6_ndo_send icmpv6_send | ||
| 29 | #endif | ||
| 30 | |||
| 25 | #else | 31 | #else |
| 26 | 32 | ||
| 27 | static inline void icmpv6_send(struct sk_buff *skb, | 33 | static inline void icmpv6_send(struct sk_buff *skb, |
| 28 | u8 type, u8 code, __u32 info) | 34 | u8 type, u8 code, __u32 info) |
| 29 | { | 35 | { |
| 30 | |||
| 31 | } | 36 | } |
| 32 | #endif | ||
| 33 | 37 | ||
| 34 | #if IS_ENABLED(CONFIG_NF_NAT) | 38 | static inline void icmpv6_ndo_send(struct sk_buff *skb, |
| 35 | void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); | 39 | u8 type, u8 code, __u32 info) |
| 36 | #else | 40 | { |
| 37 | #define icmpv6_ndo_send icmpv6_send | 41 | } |
| 38 | #endif | 42 | #endif |
| 39 | 43 | ||
| 40 | extern int icmpv6_init(void); | 44 | extern int icmpv6_init(void); |
| @@ -121,6 +121,7 @@ struct ip_set_ext { · 120 unmodified lines | |||
| 121 | u32 timeout; | 121 | u32 timeout; |
| 122 | u8 packets_op; | 122 | u8 packets_op; |
| 123 | u8 bytes_op; | 123 | u8 bytes_op; |
| 124 | bool target; | ||
| 124 | }; | 125 | }; |
| 125 | 126 | ||
| 126 | struct ip_set; | 127 | struct ip_set; |
| @@ -187,6 +188,14 @@ struct ip_set_type_variant { · 60 unmodified lines | |||
| 187 | /* Return true if "b" set is the same as "a" | 188 | /* Return true if "b" set is the same as "a" |
| 188 | * according to the create set parameters */ | 189 | * according to the create set parameters */ |
| 189 | bool (*same_set)(const struct ip_set *a, const struct ip_set *b); | 190 | bool (*same_set)(const struct ip_set *a, const struct ip_set *b); |
| 191 | /* Region-locking is used */ | ||
| 192 | bool region_lock; | ||
| 193 | }; | ||
| 194 | |||
| 195 | struct ip_set_region { | ||
| 196 | spinlock_t lock; /* Region lock */ | ||
| 197 | size_t ext_size; /* Size of the dynamic extensions */ | ||
| 198 | u32 elements; /* Number of elements vs timeout */ | ||
| 190 | }; | 199 | }; |
| 191 | 200 | ||
| 192 | /* The core set type structure */ | 201 | /* The core set type structure */ |
| @@ -501,7 +510,7 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, · 308 unmodified lines | |||
| 501 | } | 510 | } |
| 502 | 511 | ||
| 503 | #define IP_SET_INIT_KEXT(skb, opt, set) \ | 512 | #define IP_SET_INIT_KEXT(skb, opt, set) \ |
| 504 | { .bytes = (skb)->len, .packets = 1, \ | 513 | { .bytes = (skb)->len, .packets = 1, .target = true,\ |
| 505 | .timeout = ip_set_adt_opt_timeout(opt, set) } | 514 | .timeout = ip_set_adt_opt_timeout(opt, set) } |
| 506 | 515 | ||
| 507 | #define IP_SET_INIT_UEXT(set) \ | 516 | #define IP_SET_INIT_UEXT(set) \ |
| @@ -34,7 +34,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) · 33 unmodified lines | |||
| 34 | const struct nf_br_ops *nf_ops; | 34 | const struct nf_br_ops *nf_ops; |
| 35 | u8 state = BR_STATE_FORWARDING; | 35 | u8 state = BR_STATE_FORWARDING; |
| 36 | const unsigned char *dest; | 36 | const unsigned char *dest; |
| 37 | struct ethhdr *eth; | ||
| 38 | u16 vid = 0; | 37 | u16 vid = 0; |
| 39 | 38 | ||
| 40 | rcu_read_lock(); | 39 | rcu_read_lock(); |
| @@ -54,15 +53,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) · 13 unmodified lines | |||
| 54 | BR_INPUT_SKB_CB(skb)->frag_max_size = 0; | 53 | BR_INPUT_SKB_CB(skb)->frag_max_size = 0; |
| 55 | 54 | ||
| 56 | skb_reset_mac_header(skb); | 55 | skb_reset_mac_header(skb); |
| 57 | eth = eth_hdr(skb); | ||
| 58 | skb_pull(skb, ETH_HLEN); | 56 | skb_pull(skb, ETH_HLEN); |
| 59 | 57 | ||
| 60 | if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid, &state)) | 58 | if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid, &state)) |
| 61 | goto out; | 59 | goto out; |
| 62 | 60 | ||
| 63 | if (IS_ENABLED(CONFIG_INET) && | 61 | if (IS_ENABLED(CONFIG_INET) && |
| 64 | (eth->h_proto == htons(ETH_P_ARP) || | 62 | (eth_hdr(skb)->h_proto == htons(ETH_P_ARP) || |
| 65 | eth->h_proto == htons(ETH_P_RARP)) && | 63 | eth_hdr(skb)->h_proto == htons(ETH_P_RARP)) && |
| 66 | br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { | 64 | br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { |
| 67 | br_do_proxy_suppress_arp(skb, br, vid, NULL); | 65 | br_do_proxy_suppress_arp(skb, br, vid, NULL); |
| 68 | } else if (IS_ENABLED(CONFIG_IPV6) && | 66 | } else if (IS_ENABLED(CONFIG_IPV6) && |
| @@ -3076,6 +3076,8 @@ static u16 skb_tx_hash(const struct net_device *dev, · 3075 unmodified lines | |||
| 3076 | 3076 | ||
| 3077 | if (skb_rx_queue_recorded(skb)) { | 3077 | if (skb_rx_queue_recorded(skb)) { |
| 3078 | hash = skb_get_rx_queue(skb); | 3078 | hash = skb_get_rx_queue(skb); |
| 3079 | if (hash >= qoffset) | ||
| 3080 | hash -= qoffset; | ||
| 3079 | while (unlikely(hash >= qcount)) | 3081 | while (unlikely(hash >= qcount)) |
| 3080 | hash -= qcount; | 3082 | hash -= qcount; |
| 3081 | return hash + qoffset; | 3083 | return hash + qoffset; |
| @@ -2103,11 +2103,11 @@ err_action_values_put: · 2102 unmodified lines | |||
| 2103 | 2103 | ||
| 2104 | static struct devlink_dpipe_table * | 2104 | static struct devlink_dpipe_table * |
| 2105 | devlink_dpipe_table_find(struct list_head *dpipe_tables, | 2105 | devlink_dpipe_table_find(struct list_head *dpipe_tables, |
| 2106 | const char *table_name) | 2106 | const char *table_name, struct devlink *devlink) |
| 2107 | { | 2107 | { |
| 2108 | struct devlink_dpipe_table *table; | 2108 | struct devlink_dpipe_table *table; |
| 2109 | 2109 | list_for_each_entry_rcu(table, dpipe_tables, list, | |
| 2110 | list_for_each_entry_rcu(table, dpipe_tables, list) { | 2110 | lockdep_is_held(&devlink->lock)) { |
| 2111 | if (!strcmp(table->name, table_name)) | 2111 | if (!strcmp(table->name, table_name)) |
| 2112 | return table; | 2112 | return table; |
| 2113 | } | 2113 | } |
| @@ -2226,7 +2226,7 @@ static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, · 112 unmodified lines | |||
| 2226 | 2226 | ||
| 2227 | table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); | 2227 | table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); |
| 2228 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, | 2228 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 2229 | table_name); | 2229 | table_name, devlink); |
| 2230 | if (!table) | 2230 | if (!table) |
| 2231 | return -EINVAL; | 2231 | return -EINVAL; |
| 2232 | 2232 | ||
| @@ -2382,7 +2382,7 @@ static int devlink_dpipe_table_counters_set(struct devlink *devlink, · 149 unmodified lines | |||
| 2382 | struct devlink_dpipe_table *table; | 2382 | struct devlink_dpipe_table *table; |
| 2383 | 2383 | ||
| 2384 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, | 2384 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 2385 | table_name); | 2385 | table_name, devlink); |
| 2386 | if (!table) | 2386 | if (!table) |
| 2387 | return -EINVAL; | 2387 | return -EINVAL; |
| 2388 | 2388 | ||
| @@ -6854,7 +6854,7 @@ bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, · 4465 unmodified lines | |||
| 6854 | 6854 | ||
| 6855 | rcu_read_lock(); | 6855 | rcu_read_lock(); |
| 6856 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, | 6856 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 6857 | table_name); | 6857 | table_name, devlink); |
| 6858 | enabled = false; | 6858 | enabled = false; |
| 6859 | if (table) | 6859 | if (table) |
| 6860 | enabled = table->counters_enabled; | 6860 | enabled = table->counters_enabled; |
| @@ -6878,26 +6878,34 @@ int devlink_dpipe_table_register(struct devlink *devlink, · 17 unmodified lines | |||
| 6878 | void *priv, bool counter_control_extern) | 6878 | void *priv, bool counter_control_extern) |
| 6879 | { | 6879 | { |
| 6880 | struct devlink_dpipe_table *table; | 6880 | struct devlink_dpipe_table *table; |
| 6881 | 6881 | int err = 0; | |
| 6882 | if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) | ||
| 6883 | return -EEXIST; | ||
| 6884 | 6882 | ||
| 6885 | if (WARN_ON(!table_ops->size_get)) | 6883 | if (WARN_ON(!table_ops->size_get)) |
| 6886 | return -EINVAL; | 6884 | return -EINVAL; |
| 6887 | 6885 | ||
| 6886 | mutex_lock(&devlink->lock); | ||
| 6887 | |||
| 6888 | if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name, | ||
| 6889 | devlink)) { | ||
| 6890 | err = -EEXIST; | ||
| 6891 | goto unlock; | ||
| 6892 | } | ||
| 6893 | |||
| 6888 | table = kzalloc(sizeof(*table), GFP_KERNEL); | 6894 | table = kzalloc(sizeof(*table), GFP_KERNEL); |
| 6889 | if (!table) | 6895 | if (!table) { |
| 6890 | return -ENOMEM; | 6896 | err = -ENOMEM; |
| 6897 | goto unlock; | ||
| 6898 | } | ||
| 6891 | 6899 | ||
| 6892 | table->name = table_name; | 6900 | table->name = table_name; |
| 6893 | table->table_ops = table_ops; | 6901 | table->table_ops = table_ops; |
| 6894 | table->priv = priv; | 6902 | table->priv = priv; |
| 6895 | table->counter_control_extern = counter_control_extern; | 6903 | table->counter_control_extern = counter_control_extern; |
| 6896 | 6904 | ||
| 6897 | mutex_lock(&devlink->lock); | ||
| 6898 | list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); | 6905 | list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); |
| 6906 | unlock: | ||
| 6899 | mutex_unlock(&devlink->lock); | 6907 | mutex_unlock(&devlink->lock); |
| 6900 | return 0; | 6908 | return err; |
| 6901 | } | 6909 | } |
| 6902 | EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); | 6910 | EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); |
| 6903 | 6911 | ||
| @@ -6914,7 +6922,7 @@ void devlink_dpipe_table_unregister(struct devlink *devlink, · 10 unmodified lines | |||
| 6914 | 6922 | ||
| 6915 | mutex_lock(&devlink->lock); | 6923 | mutex_lock(&devlink->lock); |
| 6916 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, | 6924 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 6917 | table_name); | 6925 | table_name, devlink); |
| 6918 | if (!table) | 6926 | if (!table) |
| 6919 | goto unlock; | 6927 | goto unlock; |
| 6920 | list_del_rcu(&table->list); | 6928 | list_del_rcu(&table->list); |
| @@ -7071,7 +7079,7 @@ int devlink_dpipe_table_resource_set(struct devlink *devlink, · 150 unmodified lines | |||
| 7071 | 7079 | ||
| 7072 | mutex_lock(&devlink->lock); | 7080 | mutex_lock(&devlink->lock); |
| 7073 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, | 7081 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 7074 | table_name); | 7082 | table_name, devlink); |
| 7075 | if (!table) { | 7083 | if (!table) { |
| 7076 | err = -EINVAL; | 7084 | err = -EINVAL; |
| 7077 | goto out; | 7085 | goto out; |
| @@ -305,7 +305,8 @@ nla_put_failure: · 304 unmodified lines | |||
| 305 | static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { | 305 | static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { |
| 306 | [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT }, | 306 | [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT }, |
| 307 | [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG }, | 307 | [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG }, |
| 308 | [ETHTOOL_A_BITSET_SIZE] = { .type = NLA_U32 }, | 308 | [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32, |
| 309 | ETHNL_MAX_BITSET_SIZE), | ||
| 309 | [ETHTOOL_A_BITSET_BITS] = { .type = NLA_NESTED }, | 310 | [ETHTOOL_A_BITSET_BITS] = { .type = NLA_NESTED }, |
| 310 | [ETHTOOL_A_BITSET_VALUE] = { .type = NLA_BINARY }, | 311 | [ETHTOOL_A_BITSET_VALUE] = { .type = NLA_BINARY }, |
| 311 | [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY }, | 312 | [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY }, |
| @@ -3,6 +3,8 @@ · 2 unmodified lines | |||
| 3 | #ifndef _NET_ETHTOOL_BITSET_H | 3 | #ifndef _NET_ETHTOOL_BITSET_H |
| 4 | #define _NET_ETHTOOL_BITSET_H | 4 | #define _NET_ETHTOOL_BITSET_H |
| 5 | 5 | ||
| 6 | #define ETHNL_MAX_BITSET_SIZE S16_MAX | ||
| 7 | |||
| 6 | typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN]; | 8 | typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN]; |
| 7 | 9 | ||
| 8 | int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact); | 10 | int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact); |
| @@ -1724,6 +1724,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) · 1723 unmodified lines | |||
| 1724 | { | 1724 | { |
| 1725 | unsigned char optbuf[sizeof(struct ip_options) + 40]; | 1725 | unsigned char optbuf[sizeof(struct ip_options) + 40]; |
| 1726 | struct ip_options *opt = (struct ip_options *)optbuf; | 1726 | struct ip_options *opt = (struct ip_options *)optbuf; |
| 1727 | int res; | ||
| 1727 | 1728 | ||
| 1728 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) | 1729 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) |
| 1729 | return; | 1730 | return; |
| @@ -1735,7 +1736,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) · 5 unmodified lines | |||
| 1735 | 1736 | ||
| 1736 | memset(opt, 0, sizeof(struct ip_options)); | 1737 | memset(opt, 0, sizeof(struct ip_options)); |
| 1737 | opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); | 1738 | opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); |
| 1738 | if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL)) | 1739 | rcu_read_lock(); |
| 1740 | res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL); | ||
| 1741 | rcu_read_unlock(); | ||
| 1742 | |||
| 1743 | if (res) | ||
| 1739 | return; | 1744 | return; |
| 1740 | 1745 | ||
| 1741 | if (gateway) | 1746 | if (gateway) |
| @@ -6124,7 +6124,11 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) · 6123 unmodified lines | |||
| 6124 | { | 6124 | { |
| 6125 | struct request_sock *req; | 6125 | struct request_sock *req; |
| 6126 | 6126 | ||
| 6127 | tcp_try_undo_loss(sk, false); | 6127 | /* If we are still handling the SYNACK RTO, see if timestamp ECR allows |
| 6128 | * undo. If peer SACKs triggered fast recovery, we can't undo here. | ||
| 6129 | */ | ||
| 6130 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) | ||
| 6131 | tcp_try_undo_loss(sk, false); | ||
| 6128 | 6132 | ||
| 6129 | /* Reset rtx states to prevent spurious retransmits_timed_out() */ | 6133 | /* Reset rtx states to prevent spurious retransmits_timed_out() */ |
| 6130 | tcp_sk(sk)->retrans_stamp = 0; | 6134 | tcp_sk(sk)->retrans_stamp = 0; |
| @@ -183,9 +183,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, · 182 unmodified lines | |||
| 183 | retv = -EBUSY; | 183 | retv = -EBUSY; |
| 184 | break; | 184 | break; |
| 185 | } | 185 | } |
| 186 | } else if (sk->sk_protocol != IPPROTO_TCP) | 186 | } else if (sk->sk_protocol == IPPROTO_TCP) { |
| 187 | if (sk->sk_prot != &tcpv6_prot) { | ||
| 188 | retv = -EBUSY; | ||
| 189 | break; | ||
| 190 | } | ||
| 187 | break; | 191 | break; |
| 188 | 192 | } else { | |
| 193 | break; | ||
| 194 | } | ||
| 189 | if (sk->sk_state != TCP_ESTABLISHED) { | 195 | if (sk->sk_state != TCP_ESTABLISHED) { |
| 190 | retv = -ENOTCONN; | 196 | retv = -ENOTCONN; |
| 191 | break; | 197 | break; |
| @@ -2959,7 +2959,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 2958 unmodified lines | |||
| 2959 | (auth_transaction == 2 && | 2959 | (auth_transaction == 2 && |
| 2960 | ifmgd->auth_data->expected_transaction == 2)) { | 2960 | ifmgd->auth_data->expected_transaction == 2)) { |
| 2961 | if (!ieee80211_mark_sta_auth(sdata, bssid)) | 2961 | if (!ieee80211_mark_sta_auth(sdata, bssid)) |
| 2962 | goto out_err; | 2962 | return; /* ignore frame -- wait for timeout */ |
| 2963 | } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && | 2963 | } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && |
| 2964 | auth_transaction == 2) { | 2964 | auth_transaction == 2) { |
| 2965 | sdata_info(sdata, "SAE peer confirmed\n"); | 2965 | sdata_info(sdata, "SAE peer confirmed\n"); |
| @@ -2967,10 +2967,6 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 1 unmodified line | |||
| 2967 | } | 2967 | } |
| 2968 | 2968 | ||
| 2969 | cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); | 2969 | cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); |
| 2970 | return; | ||
| 2971 | out_err: | ||
| 2972 | mutex_unlock(&sdata->local->sta_mtx); | ||
| 2973 | /* ignore frame -- wait for timeout */ | ||
| 2974 | } | 2970 | } |
| 2975 | 2971 | ||
| 2976 | #define case_WLAN(type) \ | 2972 | #define case_WLAN(type) \ |
| @@ -4114,7 +4114,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) · 4113 unmodified lines | |||
| 4114 | 4114 | ||
| 4115 | lockdep_assert_held(&local->sta_mtx); | 4115 | lockdep_assert_held(&local->sta_mtx); |
| 4116 | 4116 | ||
| 4117 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 4117 | list_for_each_entry(sta, &local->sta_list, list) { |
| 4118 | if (sdata != sta->sdata && | 4118 | if (sdata != sta->sdata && |
| 4119 | (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) | 4119 | (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) |
| 4120 | continue; | 4120 | continue; |
| @@ -543,6 +543,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, · 542 unmodified lines | |||
| 543 | } | 543 | } |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu) | ||
| 547 | { | ||
| 548 | return 0; | ||
| 549 | } | ||
| 550 | |||
| 546 | static int __mptcp_init_sock(struct sock *sk) | 551 | static int __mptcp_init_sock(struct sock *sk) |
| 547 | { | 552 | { |
| 548 | struct mptcp_sock *msk = mptcp_sk(sk); | 553 | struct mptcp_sock *msk = mptcp_sk(sk); |
| @@ -551,6 +556,7 @@ static int __mptcp_init_sock(struct sock *sk) · 2 unmodified lines | |||
| 551 | __set_bit(MPTCP_SEND_SPACE, &msk->flags); | 556 | __set_bit(MPTCP_SEND_SPACE, &msk->flags); |
| 552 | 557 | ||
| 553 | msk->first = NULL; | 558 | msk->first = NULL; |
| 559 | inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss; | ||
| 554 | 560 | ||
| 555 | return 0; | 561 | return 0; |
| 556 | } | 562 | } |
| @@ -723,6 +723,20 @@ ip_set_rcu_get(struct net *net, ip_set_id_t index) · 722 unmodified lines | |||
| 723 | return set; | 723 | return set; |
| 724 | } | 724 | } |
| 725 | 725 | ||
| 726 | static inline void | ||
| 727 | ip_set_lock(struct ip_set *set) | ||
| 728 | { | ||
| 729 | if (!set->variant->region_lock) | ||
| 730 | spin_lock_bh(&set->lock); | ||
| 731 | } | ||
| 732 | |||
| 733 | static inline void | ||
| 734 | ip_set_unlock(struct ip_set *set) | ||
| 735 | { | ||
| 736 | if (!set->variant->region_lock) | ||
| 737 | spin_unlock_bh(&set->lock); | ||
| 738 | } | ||
| 739 | |||
| 726 | int | 740 | int |
| 727 | ip_set_test(ip_set_id_t index, const struct sk_buff *skb, | 741 | ip_set_test(ip_set_id_t index, const struct sk_buff *skb, |
| 728 | const struct xt_action_param *par, struct ip_set_adt_opt *opt) | 742 | const struct xt_action_param *par, struct ip_set_adt_opt *opt) |
| @@ -744,9 +758,9 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, · 15 unmodified lines | |||
| 744 | if (ret == -EAGAIN) { | 758 | if (ret == -EAGAIN) { |
| 745 | /* Type requests element to be completed */ | 759 | /* Type requests element to be completed */ |
| 746 | pr_debug("element must be completed, ADD is triggered\n"); | 760 | pr_debug("element must be completed, ADD is triggered\n"); |
| 747 | spin_lock_bh(&set->lock); | 761 | ip_set_lock(set); |
| 748 | set->variant->kadt(set, skb, par, IPSET_ADD, opt); | 762 | set->variant->kadt(set, skb, par, IPSET_ADD, opt); |
| 749 | spin_unlock_bh(&set->lock); | 763 | ip_set_unlock(set); |
| 750 | ret = 1; | 764 | ret = 1; |
| 751 | } else { | 765 | } else { |
| 752 | /* --return-nomatch: invert matched element */ | 766 | /* --return-nomatch: invert matched element */ |
| @@ -775,9 +789,9 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, · 22 unmodified lines | |||
| 775 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) | 789 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 776 | return -IPSET_ERR_TYPE_MISMATCH; | 790 | return -IPSET_ERR_TYPE_MISMATCH; |
| 777 | 791 | ||
| 778 | spin_lock_bh(&set->lock); | 792 | ip_set_lock(set); |
| 779 | ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt); | 793 | ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt); |
| 780 | spin_unlock_bh(&set->lock); | 794 | ip_set_unlock(set); |
| 781 | 795 | ||
| 782 | return ret; | 796 | return ret; |
| 783 | } | 797 | } |
| @@ -797,9 +811,9 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, · 13 unmodified lines | |||
| 797 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) | 811 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 798 | return -IPSET_ERR_TYPE_MISMATCH; | 812 | return -IPSET_ERR_TYPE_MISMATCH; |
| 799 | 813 | ||
| 800 | spin_lock_bh(&set->lock); | 814 | ip_set_lock(set); |
| 801 | ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt); | 815 | ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt); |
| 802 | spin_unlock_bh(&set->lock); | 816 | ip_set_unlock(set); |
| 803 | 817 | ||
| 804 | return ret; | 818 | return ret; |
| 805 | } | 819 | } |
| @@ -1264,9 +1278,9 @@ ip_set_flush_set(struct ip_set *set) · 458 unmodified lines | |||
| 1264 | { | 1278 | { |
| 1265 | pr_debug("set: %s\n", set->name); | 1279 | pr_debug("set: %s\n", set->name); |
| 1266 | 1280 | ||
| 1267 | spin_lock_bh(&set->lock); | 1281 | ip_set_lock(set); |
| 1268 | set->variant->flush(set); | 1282 | set->variant->flush(set); |
| 1269 | spin_unlock_bh(&set->lock); | 1283 | ip_set_unlock(set); |
| 1270 | } | 1284 | } |
| 1271 | 1285 | ||
| 1272 | static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb, | 1286 | static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
| @@ -1713,9 +1727,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, · 440 unmodified lines | |||
| 1713 | bool eexist = flags & IPSET_FLAG_EXIST, retried = false; | 1727 | bool eexist = flags & IPSET_FLAG_EXIST, retried = false; |
| 1714 | 1728 | ||
| 1715 | do { | 1729 | do { |
| 1716 | spin_lock_bh(&set->lock); | 1730 | ip_set_lock(set); |
| 1717 | ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried); | 1731 | ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried); |
| 1718 | spin_unlock_bh(&set->lock); | 1732 | ip_set_unlock(set); |
| 1719 | retried = true; | 1733 | retried = true; |
| 1720 | } while (ret == -EAGAIN && | 1734 | } while (ret == -EAGAIN && |
| 1721 | set->variant->resize && | 1735 | set->variant->resize && |
| @@ -7,13 +7,21 @@ · 6 unmodified lines | |||
| 7 | #include <linux/rcupdate.h> | 7 | #include <linux/rcupdate.h> |
| 8 | #include <linux/jhash.h> | 8 | #include <linux/jhash.h> |
| 9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
| 10 | #include <linux/netfilter/nfnetlink.h> | ||
| 10 | #include <linux/netfilter/ipset/ip_set.h> | 11 | #include <linux/netfilter/ipset/ip_set.h> |
| 11 | 12 | ||
| 12 | #define __ipset_dereference_protected(p, c) rcu_dereference_protected(p, c) | 13 | #define __ipset_dereference(p) \ |
| 13 | #define ipset_dereference_protected(p, set) \ | 14 | rcu_dereference_protected(p, 1) |
| 14 | __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock)) | 15 | #define ipset_dereference_nfnl(p) \ |
| 15 | 16 | rcu_dereference_protected(p, \ | |
| 16 | #define rcu_dereference_bh_nfnl(p) rcu_dereference_bh_check(p, 1) | 17 | lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) |
| 18 | #define ipset_dereference_set(p, set) \ | ||
| 19 | rcu_dereference_protected(p, \ | ||
| 20 | lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \ | ||
| 21 | lockdep_is_held(&(set)->lock)) | ||
| 22 | #define ipset_dereference_bh_nfnl(p) \ | ||
| 23 | rcu_dereference_bh_check(p, \ | ||
| 24 | lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) | ||
| 17 | 25 | ||
| 18 | /* Hashing which uses arrays to resolve clashing. The hash table is resized | 26 | /* Hashing which uses arrays to resolve clashing. The hash table is resized |
| 19 | * (doubled) when searching becomes too long. | 27 | * (doubled) when searching becomes too long. |
| @@ -72,11 +80,35 @@ struct hbucket { · 52 unmodified lines | |||
| 72 | __aligned(__alignof__(u64)); | 80 | __aligned(__alignof__(u64)); |
| 73 | }; | 81 | }; |
| 74 | 82 | ||
| 83 | /* Region size for locking == 2^HTABLE_REGION_BITS */ | ||
| 84 | #define HTABLE_REGION_BITS 10 | ||
| 85 | #define ahash_numof_locks(htable_bits) \ | ||
| 86 | ((htable_bits) < HTABLE_REGION_BITS ? 1 \ | ||
| 87 | : jhash_size((htable_bits) - HTABLE_REGION_BITS)) | ||
| 88 | #define ahash_sizeof_regions(htable_bits) \ | ||
| 89 | (ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region)) | ||
| 90 | #define ahash_region(n, htable_bits) \ | ||
| 91 | ((n) % ahash_numof_locks(htable_bits)) | ||
| 92 | #define ahash_bucket_start(h, htable_bits) \ | ||
| 93 | ((htable_bits) < HTABLE_REGION_BITS ? 0 \ | ||
| 94 | : (h) * jhash_size(HTABLE_REGION_BITS)) | ||
| 95 | #define ahash_bucket_end(h, htable_bits) \ | ||
| 96 | ((htable_bits) < HTABLE_REGION_BITS ? jhash_size(htable_bits) \ | ||
| 97 | : ((h) + 1) * jhash_size(HTABLE_REGION_BITS)) | ||
| 98 | |||
| 99 | struct htable_gc { | ||
| 100 | struct delayed_work dwork; | ||
| 101 | struct ip_set *set; /* Set the gc belongs to */ | ||
| 102 | u32 region; /* Last gc run position */ | ||
| 103 | }; | ||
| 104 | |||
| 75 | /* The hash table: the table size stored here in order to make resizing easy */ | 105 | /* The hash table: the table size stored here in order to make resizing easy */ |
| 76 | struct htable { | 106 | struct htable { |
| 77 | atomic_t ref; /* References for resizing */ | 107 | atomic_t ref; /* References for resizing */ |
| 78 | atomic_t uref; /* References for dumping */ | 108 | atomic_t uref; /* References for dumping and gc */ |
| 79 | u8 htable_bits; /* size of hash table == 2^htable_bits */ | 109 | u8 htable_bits; /* size of hash table == 2^htable_bits */ |
| 110 | u32 maxelem; /* Maxelem per region */ | ||
| 111 | struct ip_set_region *hregion; /* Region locks and ext sizes */ | ||
| 80 | struct hbucket __rcu *bucket[0]; /* hashtable buckets */ | 112 | struct hbucket __rcu *bucket[0]; /* hashtable buckets */ |
| 81 | }; | 113 | }; |
| 82 | 114 | ||
| @@ -162,6 +194,10 @@ htable_bits(u32 hashsize) · 79 unmodified lines | |||
| 162 | #define NLEN 0 | 194 | #define NLEN 0 |
| 163 | #endif /* IP_SET_HASH_WITH_NETS */ | 195 | #endif /* IP_SET_HASH_WITH_NETS */ |
| 164 | 196 | ||
| 197 | #define SET_ELEM_EXPIRED(set, d) \ | ||
| 198 | (SET_WITH_TIMEOUT(set) && \ | ||
| 199 | ip_set_timeout_expired(ext_timeout(d, set))) | ||
| 200 | |||
| 165 | #endif /* _IP_SET_HASH_GEN_H */ | 201 | #endif /* _IP_SET_HASH_GEN_H */ |
| 166 | 202 | ||
| 167 | #ifndef MTYPE | 203 | #ifndef MTYPE |
| @@ -205,10 +241,12 @@ htable_bits(u32 hashsize) · 37 unmodified lines | |||
| 205 | #undef mtype_test_cidrs | 241 | #undef mtype_test_cidrs |
| 206 | #undef mtype_test | 242 | #undef mtype_test |
| 207 | #undef mtype_uref | 243 | #undef mtype_uref |
| 208 | #undef mtype_expire | ||
| 209 | #undef mtype_resize | 244 | #undef mtype_resize |
| 245 | #undef mtype_ext_size | ||
| 246 | #undef mtype_resize_ad | ||
| 210 | #undef mtype_head | 247 | #undef mtype_head |
| 211 | #undef mtype_list | 248 | #undef mtype_list |
| 249 | #undef mtype_gc_do | ||
| 212 | #undef mtype_gc | 250 | #undef mtype_gc |
| 213 | #undef mtype_gc_init | 251 | #undef mtype_gc_init |
| 214 | #undef mtype_variant | 252 | #undef mtype_variant |
| @@ -247,10 +285,12 @@ htable_bits(u32 hashsize) · 32 unmodified lines | |||
| 247 | #define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs) | 285 | #define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs) |
| 248 | #define mtype_test IPSET_TOKEN(MTYPE, _test) | 286 | #define mtype_test IPSET_TOKEN(MTYPE, _test) |
| 249 | #define mtype_uref IPSET_TOKEN(MTYPE, _uref) | 287 | #define mtype_uref IPSET_TOKEN(MTYPE, _uref) |
| 250 | #define mtype_expire IPSET_TOKEN(MTYPE, _expire) | ||
| 251 | #define mtype_resize IPSET_TOKEN(MTYPE, _resize) | 288 | #define mtype_resize IPSET_TOKEN(MTYPE, _resize) |
| 289 | #define mtype_ext_size IPSET_TOKEN(MTYPE, _ext_size) | ||
| 290 | #define mtype_resize_ad IPSET_TOKEN(MTYPE, _resize_ad) | ||
| 252 | #define mtype_head IPSET_TOKEN(MTYPE, _head) | 291 | #define mtype_head IPSET_TOKEN(MTYPE, _head) |
| 253 | #define mtype_list IPSET_TOKEN(MTYPE, _list) | 292 | #define mtype_list IPSET_TOKEN(MTYPE, _list) |
| 293 | #define mtype_gc_do IPSET_TOKEN(MTYPE, _gc_do) | ||
| 254 | #define mtype_gc IPSET_TOKEN(MTYPE, _gc) | 294 | #define mtype_gc IPSET_TOKEN(MTYPE, _gc) |
| 255 | #define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) | 295 | #define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) |
| 256 | #define mtype_variant IPSET_TOKEN(MTYPE, _variant) | 296 | #define mtype_variant IPSET_TOKEN(MTYPE, _variant) |
| @@ -275,8 +315,7 @@ htable_bits(u32 hashsize) · 18 unmodified lines | |||
| 275 | /* The generic hash structure */ | 315 | /* The generic hash structure */ |
| 276 | struct htype { | 316 | struct htype { |
| 277 | struct htable __rcu *table; /* the hash table */ | 317 | struct htable __rcu *table; /* the hash table */ |
| 278 | struct timer_list gc; /* garbage collection when timeout enabled */ | 318 | struct htable_gc gc; /* gc workqueue */ |
| 279 | struct ip_set *set; /* attached to this ip_set */ | ||
| 280 | u32 maxelem; /* max elements in the hash */ | 319 | u32 maxelem; /* max elements in the hash */ |
| 281 | u32 initval; /* random jhash init value */ | 320 | u32 initval; /* random jhash init value */ |
| 282 | #ifdef IP_SET_HASH_WITH_MARKMASK | 321 | #ifdef IP_SET_HASH_WITH_MARKMASK |
| @@ -288,21 +327,33 @@ struct htype { · 5 unmodified lines | |||
| 288 | #ifdef IP_SET_HASH_WITH_NETMASK | 327 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 289 | u8 netmask; /* netmask value for subnets to store */ | 328 | u8 netmask; /* netmask value for subnets to store */ |
| 290 | #endif | 329 | #endif |
| 330 | struct list_head ad; /* Resize add|del backlist */ | ||
| 291 | struct mtype_elem next; /* temporary storage for uadd */ | 331 | struct mtype_elem next; /* temporary storage for uadd */ |
| 292 | #ifdef IP_SET_HASH_WITH_NETS | 332 | #ifdef IP_SET_HASH_WITH_NETS |
| 293 | struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */ | 333 | struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */ |
| 294 | #endif | 334 | #endif |
| 295 | }; | 335 | }; |
| 296 | 336 | ||
| 337 | /* ADD|DEL entries saved during resize */ | ||
| 338 | struct mtype_resize_ad { | ||
| 339 | struct list_head list; | ||
| 340 | enum ipset_adt ad; /* ADD|DEL element */ | ||
| 341 | struct mtype_elem d; /* Element value */ | ||
| 342 | struct ip_set_ext ext; /* Extensions for ADD */ | ||
| 343 | struct ip_set_ext mext; /* Target extensions for ADD */ | ||
| 344 | u32 flags; /* Flags for ADD */ | ||
| 345 | }; | ||
| 346 | |||
| 297 | #ifdef IP_SET_HASH_WITH_NETS | 347 | #ifdef IP_SET_HASH_WITH_NETS |
| 298 | /* Network cidr size book keeping when the hash stores different | 348 | /* Network cidr size book keeping when the hash stores different |
| 299 | * sized networks. cidr == real cidr + 1 to support /0. | 349 | * sized networks. cidr == real cidr + 1 to support /0. |
| 300 | */ | 350 | */ |
| 301 | static void | 351 | static void |
| 302 | mtype_add_cidr(struct htype *h, u8 cidr, u8 n) | 352 | mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) |
| 303 | { | 353 | { |
| 304 | int i, j; | 354 | int i, j; |
| 305 | 355 | ||
| 356 | spin_lock_bh(&set->lock); | ||
| 306 | /* Add in increasing prefix order, so larger cidr first */ | 357 | /* Add in increasing prefix order, so larger cidr first */ |
| 307 | for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) { | 358 | for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) { |
| 308 | if (j != -1) { | 359 | if (j != -1) { |
| @@ -311,7 +362,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) · 2 unmodified lines | |||
| 311 | j = i; | 362 | j = i; |
| 312 | } else if (h->nets[i].cidr[n] == cidr) { | 363 | } else if (h->nets[i].cidr[n] == cidr) { |
| 313 | h->nets[CIDR_POS(cidr)].nets[n]++; | 364 | h->nets[CIDR_POS(cidr)].nets[n]++; |
| 314 | return; | 365 | goto unlock; |
| 315 | } | 366 | } |
| 316 | } | 367 | } |
| 317 | if (j != -1) { | 368 | if (j != -1) { |
| @@ -320,24 +371,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) · 2 unmodified lines | |||
| 320 | } | 371 | } |
| 321 | h->nets[i].cidr[n] = cidr; | 372 | h->nets[i].cidr[n] = cidr; |
| 322 | h->nets[CIDR_POS(cidr)].nets[n] = 1; | 373 | h->nets[CIDR_POS(cidr)].nets[n] = 1; |
| 374 | unlock: | ||
| 375 | spin_unlock_bh(&set->lock); | ||
| 323 | } | 376 | } |
| 324 | 377 | ||
| 325 | static void | 378 | static void |
| 326 | mtype_del_cidr(struct htype *h, u8 cidr, u8 n) | 379 | mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) |
| 327 | { | 380 | { |
| 328 | u8 i, j, net_end = NLEN - 1; | 381 | u8 i, j, net_end = NLEN - 1; |
| 329 | 382 | ||
| 383 | spin_lock_bh(&set->lock); | ||
| 330 | for (i = 0; i < NLEN; i++) { | 384 | for (i = 0; i < NLEN; i++) { |
| 331 | if (h->nets[i].cidr[n] != cidr) | 385 | if (h->nets[i].cidr[n] != cidr) |
| 332 | continue; | 386 | continue; |
| 333 | h->nets[CIDR_POS(cidr)].nets[n]--; | 387 | h->nets[CIDR_POS(cidr)].nets[n]--; |
| 334 | if (h->nets[CIDR_POS(cidr)].nets[n] > 0) | 388 | if (h->nets[CIDR_POS(cidr)].nets[n] > 0) |
| 335 | return; | 389 | goto unlock; |
| 336 | for (j = i; j < net_end && h->nets[j].cidr[n]; j++) | 390 | for (j = i; j < net_end && h->nets[j].cidr[n]; j++) |
| 337 | h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; | 391 | h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; |
| 338 | h->nets[j].cidr[n] = 0; | 392 | h->nets[j].cidr[n] = 0; |
| 339 | return; | 393 | goto unlock; |
| 340 | } | 394 | } |
| 395 | unlock: | ||
| 396 | spin_unlock_bh(&set->lock); | ||
| 341 | } | 397 | } |
| 342 | #endif | 398 | #endif |
| 343 | 399 | ||
| @@ -345,7 +401,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n) · 1 unmodified line | |||
| 345 | static size_t | 401 | static size_t |
| 346 | mtype_ahash_memsize(const struct htype *h, const struct htable *t) | 402 | mtype_ahash_memsize(const struct htype *h, const struct htable *t) |
| 347 | { | 403 | { |
| 348 | return sizeof(*h) + sizeof(*t); | 404 | return sizeof(*h) + sizeof(*t) + ahash_sizeof_regions(t->htable_bits); |
| 349 | } | 405 | } |
| 350 | 406 | ||
| 351 | /* Get the ith element from the array block n */ | 407 | /* Get the ith element from the array block n */ |
| @@ -369,24 +425,29 @@ mtype_flush(struct ip_set *set) · 17 unmodified lines | |||
| 369 | struct htype *h = set->data; | 425 | struct htype *h = set->data; |
| 370 | struct htable *t; | 426 | struct htable *t; |
| 371 | struct hbucket *n; | 427 | struct hbucket *n; |
| 372 | u32 i; | 428 | u32 r, i; |
| 373 | 429 | ||
| 374 | t = ipset_dereference_protected(h->table, set); | 430 | t = ipset_dereference_nfnl(h->table); |
| 375 | for (i = 0; i < jhash_size(t->htable_bits); i++) { | 431 | for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) { |
| 376 | n = __ipset_dereference_protected(hbucket(t, i), 1); | 432 | spin_lock_bh(&t->hregion[r].lock); |
| 377 | if (!n) | 433 | for (i = ahash_bucket_start(r, t->htable_bits); |
| 378 | continue; | 434 | i < ahash_bucket_end(r, t->htable_bits); i++) { |
| 379 | if (set->extensions & IPSET_EXT_DESTROY) | 435 | n = __ipset_dereference(hbucket(t, i)); |
| 380 | mtype_ext_cleanup(set, n); | 436 | if (!n) |
| 381 | /* FIXME: use slab cache */ | 437 | continue; |
| 382 | rcu_assign_pointer(hbucket(t, i), NULL); | 438 | if (set->extensions & IPSET_EXT_DESTROY) |
| 383 | kfree_rcu(n, rcu); | 439 | mtype_ext_cleanup(set, n); |
| 440 | /* FIXME: use slab cache */ | ||
| 441 | rcu_assign_pointer(hbucket(t, i), NULL); | ||
| 442 | kfree_rcu(n, rcu); | ||
| 443 | } | ||
| 444 | t->hregion[r].ext_size = 0; | ||
| 445 | t->hregion[r].elements = 0; | ||
| 446 | spin_unlock_bh(&t->hregion[r].lock); | ||
| 384 | } | 447 | } |
| 385 | #ifdef IP_SET_HASH_WITH_NETS | 448 | #ifdef IP_SET_HASH_WITH_NETS |
| 386 | memset(h->nets, 0, sizeof(h->nets)); | 449 | memset(h->nets, 0, sizeof(h->nets)); |
| 387 | #endif | 450 | #endif |
| 388 | set->elements = 0; | ||
| 389 | set->ext_size = 0; | ||
| 390 | } | 451 | } |
| 391 | 452 | ||
| 392 | /* Destroy the hashtable part of the set */ | 453 | /* Destroy the hashtable part of the set */ |
| @@ -397,7 +458,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy) · 4 unmodified lines | |||
| 397 | u32 i; | 458 | u32 i; |
| 398 | 459 | ||
| 399 | for (i = 0; i < jhash_size(t->htable_bits); i++) { | 460 | for (i = 0; i < jhash_size(t->htable_bits); i++) { |
| 400 | n = __ipset_dereference_protected(hbucket(t, i), 1); | 461 | n = __ipset_dereference(hbucket(t, i)); |
| 401 | if (!n) | 462 | if (!n) |
| 402 | continue; | 463 | continue; |
| 403 | if (set->extensions & IPSET_EXT_DESTROY && ext_destroy) | 464 | if (set->extensions & IPSET_EXT_DESTROY && ext_destroy) |
| @@ -406,6 +467,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy) · 2 unmodified lines | |||
| 406 | kfree(n); | 467 | kfree(n); |
| 407 | } | 468 | } |
| 408 | 469 | ||
| 470 | ip_set_free(t->hregion); | ||
| 409 | ip_set_free(t); | 471 | ip_set_free(t); |
| 410 | } | 472 | } |
| 411 | 473 | ||
| @@ -414,28 +476,21 @@ static void · 2 unmodified lines | |||
| 414 | mtype_destroy(struct ip_set *set) | 476 | mtype_destroy(struct ip_set *set) |
| 415 | { | 477 | { |
| 416 | struct htype *h = set->data; | 478 | struct htype *h = set->data; |
| 479 | struct list_head *l, *lt; | ||
| 417 | 480 | ||
| 418 | if (SET_WITH_TIMEOUT(set)) | 481 | if (SET_WITH_TIMEOUT(set)) |
| 419 | del_timer_sync(&h->gc); | 482 | cancel_delayed_work_sync(&h->gc.dwork); |
| 420 | 483 | ||
| 421 | mtype_ahash_destroy(set, | 484 | mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true); |
| 422 | __ipset_dereference_protected(h->table, 1), true); | 485 | list_for_each_safe(l, lt, &h->ad) { |
| 486 | list_del(l); | ||
| 487 | kfree(l); | ||
| 488 | } | ||
| 423 | kfree(h); | 489 | kfree(h); |
| 424 | 490 | ||
| 425 | set->data = NULL; | 491 | set->data = NULL; |
| 426 | } | 492 | } |
| 427 | 493 | ||
| 428 | static void | ||
| 429 | mtype_gc_init(struct ip_set *set, void (*gc)(struct timer_list *t)) | ||
| 430 | { | ||
| 431 | struct htype *h = set->data; | ||
| 432 | |||
| 433 | timer_setup(&h->gc, gc, 0); | ||
| 434 | mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ); | ||
| 435 | pr_debug("gc initialized, run in every %u\n", | ||
| 436 | IPSET_GC_PERIOD(set->timeout)); | ||
| 437 | } | ||
| 438 | |||
| 439 | static bool | 494 | static bool |
| 440 | mtype_same_set(const struct ip_set *a, const struct ip_set *b) | 495 | mtype_same_set(const struct ip_set *a, const struct ip_set *b) |
| 441 | { | 496 | { |
| @@ -454,11 +509,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b) · 12 unmodified lines | |||
| 454 | a->extensions == b->extensions; | 509 | a->extensions == b->extensions; |
| 455 | } | 510 | } |
| 456 | 511 | ||
| 457 | /* Delete expired elements from the hashtable */ | ||
| 458 | static void | 512 | static void |
| 459 | mtype_expire(struct ip_set *set, struct htype *h) | 513 | mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r) |
| 460 | { | 514 | { |
| 461 | struct htable *t; | ||
| 462 | struct hbucket *n, *tmp; | 515 | struct hbucket *n, *tmp; |
| 463 | struct mtype_elem *data; | 516 | struct mtype_elem *data; |
| 464 | u32 i, j, d; | 517 | u32 i, j, d; |
| @@ -466,10 +519,12 @@ mtype_expire(struct ip_set *set, struct htype *h) · 1 unmodified line | |||
| 466 | #ifdef IP_SET_HASH_WITH_NETS | 519 | #ifdef IP_SET_HASH_WITH_NETS |
| 467 | u8 k; | 520 | u8 k; |
| 468 | #endif | 521 | #endif |
| 522 | u8 htable_bits = t->htable_bits; | ||
| 469 | 523 | ||
| 470 | t = ipset_dereference_protected(h->table, set); | 524 | spin_lock_bh(&t->hregion[r].lock); |
| 471 | for (i = 0; i < jhash_size(t->htable_bits); i++) { | 525 | for (i = ahash_bucket_start(r, htable_bits); |
| 472 | n = __ipset_dereference_protected(hbucket(t, i), 1); | 526 | i < ahash_bucket_end(r, htable_bits); i++) { |
| 527 | n = __ipset_dereference(hbucket(t, i)); | ||
| 473 | if (!n) | 528 | if (!n) |
| 474 | continue; | 529 | continue; |
| 475 | for (j = 0, d = 0; j < n->pos; j++) { | 530 | for (j = 0, d = 0; j < n->pos; j++) { |
| @@ -485,58 +540,100 @@ mtype_expire(struct ip_set *set, struct htype *h) · 9 unmodified lines | |||
| 485 | smp_mb__after_atomic(); | 540 | smp_mb__after_atomic(); |
| 486 | #ifdef IP_SET_HASH_WITH_NETS | 541 | #ifdef IP_SET_HASH_WITH_NETS |
| 487 | for (k = 0; k < IPSET_NET_COUNT; k++) | 542 | for (k = 0; k < IPSET_NET_COUNT; k++) |
| 488 | mtype_del_cidr(h, | 543 | mtype_del_cidr(set, h, |
| 489 | NCIDR_PUT(DCIDR_GET(data->cidr, k)), | 544 | NCIDR_PUT(DCIDR_GET(data->cidr, k)), |
| 490 | k); | 545 | k); |
| 491 | #endif | 546 | #endif |
| 547 | t->hregion[r].elements--; | ||
| 492 | ip_set_ext_destroy(set, data); | 548 | ip_set_ext_destroy(set, data); |
| 493 | set->elements--; | ||
| 494 | d++; | 549 | d++; |
| 495 | } | 550 | } |
| 496 | if (d >= AHASH_INIT_SIZE) { | 551 | if (d >= AHASH_INIT_SIZE) { |
| 497 | if (d >= n->size) { | 552 | if (d >= n->size) { |
| 553 | t->hregion[r].ext_size -= | ||
| 554 | ext_size(n->size, dsize); | ||
| 498 | rcu_assign_pointer(hbucket(t, i), NULL); | 555 | rcu_assign_pointer(hbucket(t, i), NULL); |
| 499 | kfree_rcu(n, rcu); | 556 | kfree_rcu(n, rcu); |
| 500 | continue; | 557 | continue; |
| 501 | } | 558 | } |
| 502 | tmp = kzalloc(sizeof(*tmp) + | 559 | tmp = kzalloc(sizeof(*tmp) + |
| 503 | (n->size - AHASH_INIT_SIZE) * dsize, | 560 | (n->size - AHASH_INIT_SIZE) * dsize, |
| 504 | GFP_ATOMIC); | 561 | GFP_ATOMIC); |
| 505 | if (!tmp) | 562 | if (!tmp) |
| 506 | /* Still try to delete expired elements */ | 563 | /* Still try to delete expired elements. */ |
| 507 | continue; | 564 | continue; |
| 508 | tmp->size = n->size - AHASH_INIT_SIZE; | 565 | tmp->size = n->size - AHASH_INIT_SIZE; |
| 509 | for (j = 0, d = 0; j < n->pos; j++) { | 566 | for (j = 0, d = 0; j < n->pos; j++) { |
| 510 | if (!test_bit(j, n->used)) | 567 | if (!test_bit(j, n->used)) |
| 511 | continue; | 568 | continue; |
| 512 | data = ahash_data(n, j, dsize); | 569 | data = ahash_data(n, j, dsize); |
| 513 | memcpy(tmp->value + d * dsize, data, dsize); | 570 | memcpy(tmp->value + d * dsize, |
| 571 | data, dsize); | ||
| 514 | set_bit(d, tmp->used); | 572 | set_bit(d, tmp->used); |
| 515 | d++; | 573 | d++; |
| 516 | } | 574 | } |
| 517 | tmp->pos = d; | 575 | tmp->pos = d; |
| 518 | set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize); | 576 | t->hregion[r].ext_size -= |
| 577 | ext_size(AHASH_INIT_SIZE, dsize); | ||
| 519 | rcu_assign_pointer(hbucket(t, i), tmp); | 578 | rcu_assign_pointer(hbucket(t, i), tmp); |
| 520 | kfree_rcu(n, rcu); | 579 | kfree_rcu(n, rcu); |
| 521 | } | 580 | } |
| 522 | } | 581 | } |
| 582 | spin_unlock_bh(&t->hregion[r].lock); | ||
| 523 | } | 583 | } |
| 524 | 584 | ||
| 525 | static void | 585 | static void |
| 526 | mtype_gc(struct timer_list *t) | 586 | mtype_gc(struct work_struct *work) |
| 527 | { | 587 | { |
| 528 | struct htype *h = from_timer(h, t, gc); | 588 | struct htable_gc *gc; |
| 529 | struct ip_set *set = h->set; | 589 | struct ip_set *set; |
| 590 | struct htype *h; | ||
| 591 | struct htable *t; | ||
| 592 | u32 r, numof_locks; | ||
| 593 | unsigned int next_run; | ||
| 594 | |||
| 595 | gc = container_of(work, struct htable_gc, dwork.work); | ||
| 596 | set = gc->set; | ||
| 597 | h = set->data; | ||
| 530 | 598 | ||
| 531 | pr_debug("called\n"); | ||
| 532 | spin_lock_bh(&set->lock); | 599 | spin_lock_bh(&set->lock); |
| 533 | mtype_expire(set, h); | 600 | t = ipset_dereference_set(h->table, set); |
| 601 | atomic_inc(&t->uref); | ||
| 602 | numof_locks = ahash_numof_locks(t->htable_bits); | ||
| 603 | r = gc->region++; | ||
| 604 | if (r >= numof_locks) { | ||
| 605 | r = gc->region = 0; | ||
| 606 | } | ||
| 607 | next_run = (IPSET_GC_PERIOD(set->timeout) * HZ) / numof_locks; | ||
| 608 | if (next_run < HZ/10) | ||
| 609 | next_run = HZ/10; | ||
| 534 | spin_unlock_bh(&set->lock); | 610 | spin_unlock_bh(&set->lock); |
| 535 | 611 | ||
| 536 | h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; | 612 | mtype_gc_do(set, h, t, r); |
| 537 | add_timer(&h->gc); | 613 | |
| 614 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { | ||
| 615 | pr_debug("Table destroy after resize by expire: %p\n", t); | ||
| 616 | mtype_ahash_destroy(set, t, false); | ||
| 617 | } | ||
| 618 | |||
| 619 | queue_delayed_work(system_power_efficient_wq, &gc->dwork, next_run); | ||
| 620 | |||
| 621 | } | ||
| 622 | |||
| 623 | static void | ||
| 624 | mtype_gc_init(struct htable_gc *gc) | ||
| 625 | { | ||
| 626 | INIT_DEFERRABLE_WORK(&gc->dwork, mtype_gc); | ||
| 627 | queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ); | ||
| 538 | } | 628 | } |
| 539 | 629 | ||
| 630 | static int | ||
| 631 | mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, | ||
| 632 | struct ip_set_ext *mext, u32 flags); | ||
| 633 | static int | ||
| 634 | mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, | ||
| 635 | struct ip_set_ext *mext, u32 flags); | ||
| 636 | |||
| 540 | /* Resize a hash: create a new hash table with doubling the hashsize | 637 | /* Resize a hash: create a new hash table with doubling the hashsize |
| 541 | * and inserting the elements to it. Repeat until we succeed or | 638 | * and inserting the elements to it. Repeat until we succeed or |
| 542 | * fail due to memory pressures. | 639 | * fail due to memory pressures. |
| @@ -547,7 +644,7 @@ mtype_resize(struct ip_set *set, bool retried) · 4 unmodified lines | |||
| 547 | struct htype *h = set->data; | 644 | struct htype *h = set->data; |
| 548 | struct htable *t, *orig; | 645 | struct htable *t, *orig; |
| 549 | u8 htable_bits; | 646 | u8 htable_bits; |
| 550 | size_t extsize, dsize = set->dsize; | 647 | size_t dsize = set->dsize; |
| 551 | #ifdef IP_SET_HASH_WITH_NETS | 648 | #ifdef IP_SET_HASH_WITH_NETS |
| 552 | u8 flags; | 649 | u8 flags; |
| 553 | struct mtype_elem *tmp; | 650 | struct mtype_elem *tmp; |
| @@ -555,7 +652,9 @@ mtype_resize(struct ip_set *set, bool retried) · 1 unmodified line | |||
| 555 | struct mtype_elem *data; | 652 | struct mtype_elem *data; |
| 556 | struct mtype_elem *d; | 653 | struct mtype_elem *d; |
| 557 | struct hbucket *n, *m; | 654 | struct hbucket *n, *m; |
| 558 | u32 i, j, key; | 655 | struct list_head *l, *lt; |
| 656 | struct mtype_resize_ad *x; | ||
| 657 | u32 i, j, r, nr, key; | ||
| 559 | int ret; | 658 | int ret; |
| 560 | 659 | ||
| 561 | #ifdef IP_SET_HASH_WITH_NETS | 660 | #ifdef IP_SET_HASH_WITH_NETS |
| @@ -563,10 +662,8 @@ mtype_resize(struct ip_set *set, bool retried) · 1 unmodified line | |||
| 563 | if (!tmp) | 662 | if (!tmp) |
| 564 | return -ENOMEM; | 663 | return -ENOMEM; |
| 565 | #endif | 664 | #endif |
| 566 | rcu_read_lock_bh(); | 665 | orig = ipset_dereference_bh_nfnl(h->table); |
| 567 | orig = rcu_dereference_bh_nfnl(h->table); | ||
| 568 | htable_bits = orig->htable_bits; | 666 | htable_bits = orig->htable_bits; |
| 569 | rcu_read_unlock_bh(); | ||
| 570 | 667 | ||
| 571 | retry: | 668 | retry: |
| 572 | ret = 0; | 669 | ret = 0; |
| @@ -583,88 +680,124 @@ retry: · 10 unmodified lines | |||
| 583 | ret = -ENOMEM; | 680 | ret = -ENOMEM; |
| 584 | goto out; | 681 | goto out; |
| 585 | } | 682 | } |
| 683 | t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits)); | ||
| 684 | if (!t->hregion) { | ||
| 685 | kfree(t); | ||
| 686 | ret = -ENOMEM; | ||
| 687 | goto out; | ||
| 688 | } | ||
| 586 | t->htable_bits = htable_bits; | 689 | t->htable_bits = htable_bits; |
| 690 | t->maxelem = h->maxelem / ahash_numof_locks(htable_bits); | ||
| 691 | for (i = 0; i < ahash_numof_locks(htable_bits); i++) | ||
| 692 | spin_lock_init(&t->hregion[i].lock); | ||
| 587 | 693 | ||
| 588 | spin_lock_bh(&set->lock); | 694 | /* There can't be another parallel resizing, |
| 589 | orig = __ipset_dereference_protected(h->table, 1); | 695 | * but dumping, gc, kernel side add/del are possible |
| 590 | /* There can't be another parallel resizing, but dumping is possible */ | 696 | */ |
| 697 | orig = ipset_dereference_bh_nfnl(h->table); | ||
| 591 | atomic_set(&orig->ref, 1); | 698 | atomic_set(&orig->ref, 1); |
| 592 | atomic_inc(&orig->uref); | 699 | atomic_inc(&orig->uref); |
| 593 | extsize = 0; | ||
| 594 | pr_debug("attempt to resize set %s from %u to %u, t %p\n", | 700 | pr_debug("attempt to resize set %s from %u to %u, t %p\n", |
| 595 | set->name, orig->htable_bits, htable_bits, orig); | 701 | set->name, orig->htable_bits, htable_bits, orig); |
| 596 | for (i = 0; i < jhash_size(orig->htable_bits); i++) { | 702 | for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) { |
| 597 | n = __ipset_dereference_protected(hbucket(orig, i), 1); | 703 | /* Expire may replace a hbucket with another one */ |
| 598 | if (!n) | 704 | rcu_read_lock_bh(); |
| 599 | continue; | 705 | for (i = ahash_bucket_start(r, orig->htable_bits); |
| 600 | for (j = 0; j < n->pos; j++) { | 706 | i < ahash_bucket_end(r, orig->htable_bits); i++) { |
| 601 | if (!test_bit(j, n->used)) | 707 | n = __ipset_dereference(hbucket(orig, i)); |
| 708 | if (!n) | ||
| 602 | continue; | 709 | continue; |
| 603 | data = ahash_data(n, j, dsize); | 710 | for (j = 0; j < n->pos; j++) { |
| 711 | if (!test_bit(j, n->used)) | ||
| 712 | continue; | ||
| 713 | data = ahash_data(n, j, dsize); | ||
| 714 | if (SET_ELEM_EXPIRED(set, data)) | ||
| 715 | continue; | ||
| 604 | #ifdef IP_SET_HASH_WITH_NETS | 716 | #ifdef IP_SET_HASH_WITH_NETS |
| 605 | /* We have readers running parallel with us, | 717 | /* We have readers running parallel with us, |
| 606 | * so the live data cannot be modified. | 718 | * so the live data cannot be modified. |
| 607 | */ | 719 | */ |
| 608 | flags = 0; | 720 | flags = 0; |
| 609 | memcpy(tmp, data, dsize); | 721 | memcpy(tmp, data, dsize); |
| 610 | data = tmp; | 722 | data = tmp; |
| 611 | mtype_data_reset_flags(data, &flags); | 723 | mtype_data_reset_flags(data, &flags); |
| 612 | #endif | 724 | #endif |
| 613 | key = HKEY(data, h->initval, htable_bits); | 725 | key = HKEY(data, h->initval, htable_bits); |
| 614 | m = __ipset_dereference_protected(hbucket(t, key), 1); | 726 | m = __ipset_dereference(hbucket(t, key)); |
| 615 | if (!m) { | 727 | nr = ahash_region(key, htable_bits); |
| 616 | m = kzalloc(sizeof(*m) + | 728 | if (!m) { |
| 729 | m = kzalloc(sizeof(*m) + | ||
| 617 | AHASH_INIT_SIZE * dsize, | 730 | AHASH_INIT_SIZE * dsize, |
| 618 | GFP_ATOMIC); | 731 | GFP_ATOMIC); |
| 619 | if (!m) { | 732 | if (!m) { |
| 620 | ret = -ENOMEM; | 733 | ret = -ENOMEM; |
| 621 | goto cleanup; | 734 | goto cleanup; |
| 622 | } | 735 | } |
| 623 | m->size = AHASH_INIT_SIZE; | 736 | m->size = AHASH_INIT_SIZE; |
| 624 | extsize += ext_size(AHASH_INIT_SIZE, dsize); | 737 | t->hregion[nr].ext_size += |
| 625 | RCU_INIT_POINTER(hbucket(t, key), m); | 738 | ext_size(AHASH_INIT_SIZE, |
| 626 | } else if (m->pos >= m->size) { | 739 | dsize); |
| 627 | struct hbucket *ht; | 740 | RCU_INIT_POINTER(hbucket(t, key), m); |
| 628 | 741 | } else if (m->pos >= m->size) { | |
| 629 | if (m->size >= AHASH_MAX(h)) { | 742 | struct hbucket *ht; |
| 630 | ret = -EAGAIN; | 743 | |
| 631 | } else { | 744 | if (m->size >= AHASH_MAX(h)) { |
| 632 | ht = kzalloc(sizeof(*ht) + | 745 | ret = -EAGAIN; |
| 746 | } else { | ||
| 747 | ht = kzalloc(sizeof(*ht) + | ||
| 633 | (m->size + AHASH_INIT_SIZE) | 748 | (m->size + AHASH_INIT_SIZE) |
| 634 | * dsize, | 749 | * dsize, |
| 635 | GFP_ATOMIC); | 750 | GFP_ATOMIC); |
| 636 | if (!ht) | 751 | if (!ht) |
| 637 | ret = -ENOMEM; | 752 | ret = -ENOMEM; |
| 753 | } | ||
| 754 | if (ret < 0) | ||
| 755 | goto cleanup; | ||
| 756 | memcpy(ht, m, sizeof(struct hbucket) + | ||
| 757 | m->size * dsize); | ||
| 758 | ht->size = m->size + AHASH_INIT_SIZE; | ||
| 759 | t->hregion[nr].ext_size += | ||
| 760 | ext_size(AHASH_INIT_SIZE, | ||
| 761 | dsize); | ||
| 762 | kfree(m); | ||
| 763 | m = ht; | ||
| 764 | RCU_INIT_POINTER(hbucket(t, key), ht); | ||
| 638 | } | 765 | } |
| 639 | if (ret < 0) | 766 | d = ahash_data(m, m->pos, dsize); |
| 640 | goto cleanup; | 767 | memcpy(d, data, dsize); |
| 641 | memcpy(ht, m, sizeof(struct hbucket) + | 768 | set_bit(m->pos++, m->used); |
| 642 | m->size * dsize); | 769 | t->hregion[nr].elements++; |
| 643 | ht->size = m->size + AHASH_INIT_SIZE; | ||
| 644 | extsize += ext_size(AHASH_INIT_SIZE, dsize); | ||
| 645 | kfree(m); | ||
| 646 | m = ht; | ||
| 647 | RCU_INIT_POINTER(hbucket(t, key), ht); | ||
| 648 | } | ||
| 649 | d = ahash_data(m, m->pos, dsize); | ||
| 650 | memcpy(d, data, dsize); | ||
| 651 | set_bit(m->pos++, m->used); | ||
| 652 | #ifdef IP_SET_HASH_WITH_NETS | 770 | #ifdef IP_SET_HASH_WITH_NETS |
| 653 | mtype_data_reset_flags(d, &flags); | 771 | mtype_data_reset_flags(d, &flags); |
| 654 | #endif | 772 | #endif |
| 773 | } | ||
| 655 | } | 774 | } |
| 775 | rcu_read_unlock_bh(); | ||
| 656 | } | 776 | } |
| 657 | rcu_assign_pointer(h->table, t); | ||
| 658 | set->ext_size = extsize; | ||
| 659 | 777 | ||
| 660 | spin_unlock_bh(&set->lock); | 778 | /* There can't be any other writer. */ |
| 779 | rcu_assign_pointer(h->table, t); | ||
| 661 | 780 | ||
| 662 | /* Give time to other readers of the set */ | 781 | /* Give time to other readers of the set */ |
| 663 | synchronize_rcu(); | 782 | synchronize_rcu(); |
| 664 | 783 | ||
| 665 | pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, | 784 | pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, |
| 666 | orig->htable_bits, orig, t->htable_bits, t); | 785 | orig->htable_bits, orig, t->htable_bits, t); |
| 667 | /* If there's nobody else dumping the table, destroy it */ | 786 | /* Add/delete elements processed by the SET target during resize. |
| 787 | * Kernel-side add cannot trigger a resize and userspace actions | ||
| 788 | * are serialized by the mutex. | ||
| 789 | */ | ||
| 790 | list_for_each_safe(l, lt, &h->ad) { | ||
| 791 | x = list_entry(l, struct mtype_resize_ad, list); | ||
| 792 | if (x->ad == IPSET_ADD) { | ||
| 793 | mtype_add(set, &x->d, &x->ext, &x->mext, x->flags); | ||
| 794 | } else { | ||
| 795 | mtype_del(set, &x->d, NULL, NULL, 0); | ||
| 796 | } | ||
| 797 | list_del(l); | ||
| 798 | kfree(l); | ||
| 799 | } | ||
| 800 | /* If there's nobody else using the table, destroy it */ | ||
| 668 | if (atomic_dec_and_test(&orig->uref)) { | 801 | if (atomic_dec_and_test(&orig->uref)) { |
| 669 | pr_debug("Table destroy by resize %p\n", orig); | 802 | pr_debug("Table destroy by resize %p\n", orig); |
| 670 | mtype_ahash_destroy(set, orig, false); | 803 | mtype_ahash_destroy(set, orig, false); |
| @@ -677,15 +810,44 @@ out: · 6 unmodified lines | |||
| 677 | return ret; | 810 | return ret; |
| 678 | 811 | ||
| 679 | cleanup: | 812 | cleanup: |
| 813 | rcu_read_unlock_bh(); | ||
| 680 | atomic_set(&orig->ref, 0); | 814 | atomic_set(&orig->ref, 0); |
| 681 | atomic_dec(&orig->uref); | 815 | atomic_dec(&orig->uref); |
| 682 | spin_unlock_bh(&set->lock); | ||
| 683 | mtype_ahash_destroy(set, t, false); | 816 | mtype_ahash_destroy(set, t, false); |
| 684 | if (ret == -EAGAIN) | 817 | if (ret == -EAGAIN) |
| 685 | goto retry; | 818 | goto retry; |
| 686 | goto out; | 819 | goto out; |
| 687 | } | 820 | } |
| 688 | 821 | ||
| 822 | /* Get the current number of elements and ext_size in the set */ | ||
| 823 | static void | ||
| 824 | mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size) | ||
| 825 | { | ||
| 826 | struct htype *h = set->data; | ||
| 827 | const struct htable *t; | ||
| 828 | u32 i, j, r; | ||
| 829 | struct hbucket *n; | ||
| 830 | struct mtype_elem *data; | ||
| 831 | |||
| 832 | t = rcu_dereference_bh(h->table); | ||
| 833 | for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) { | ||
| 834 | for (i = ahash_bucket_start(r, t->htable_bits); | ||
| 835 | i < ahash_bucket_end(r, t->htable_bits); i++) { | ||
| 836 | n = rcu_dereference_bh(hbucket(t, i)); | ||
| 837 | if (!n) | ||
| 838 | continue; | ||
| 839 | for (j = 0; j < n->pos; j++) { | ||
| 840 | if (!test_bit(j, n->used)) | ||
| 841 | continue; | ||
| 842 | data = ahash_data(n, j, set->dsize); | ||
| 843 | if (!SET_ELEM_EXPIRED(set, data)) | ||
| 844 | (*elements)++; | ||
| 845 | } | ||
| 846 | } | ||
| 847 | *ext_size += t->hregion[r].ext_size; | ||
| 848 | } | ||
| 849 | } | ||
| 850 | |||
| 689 | /* Add an element to a hash and update the internal counters when succeeded, | 851 | /* Add an element to a hash and update the internal counters when succeeded, |
| 690 | * otherwise report the proper error code. | 852 | * otherwise report the proper error code. |
| 691 | */ | 853 | */ |
| @@ -698,32 +860,49 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 6 unmodified lines | |||
| 698 | const struct mtype_elem *d = value; | 860 | const struct mtype_elem *d = value; |
| 699 | struct mtype_elem *data; | 861 | struct mtype_elem *data; |
| 700 | struct hbucket *n, *old = ERR_PTR(-ENOENT); | 862 | struct hbucket *n, *old = ERR_PTR(-ENOENT); |
| 701 | int i, j = -1; | 863 | int i, j = -1, ret; |
| 702 | bool flag_exist = flags & IPSET_FLAG_EXIST; | 864 | bool flag_exist = flags & IPSET_FLAG_EXIST; |
| 703 | bool deleted = false, forceadd = false, reuse = false; | 865 | bool deleted = false, forceadd = false, reuse = false; |
| 704 | u32 key, multi = 0; | 866 | u32 r, key, multi = 0, elements, maxelem; |
| 705 | 867 | ||
| 706 | if (set->elements >= h->maxelem) { | 868 | rcu_read_lock_bh(); |
| 707 | if (SET_WITH_TIMEOUT(set)) | 869 | t = rcu_dereference_bh(h->table); |
| 708 | /* FIXME: when set is full, we slow down here */ | 870 | key = HKEY(value, h->initval, t->htable_bits); |
| 709 | mtype_expire(set, h); | 871 | r = ahash_region(key, t->htable_bits); |
| 710 | if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set)) | 872 | atomic_inc(&t->uref); |
| 873 | elements = t->hregion[r].elements; | ||
| 874 | maxelem = t->maxelem; | ||
| 875 | if (elements >= maxelem) { | ||
| 876 | u32 e; | ||
| 877 | if (SET_WITH_TIMEOUT(set)) { | ||
| 878 | rcu_read_unlock_bh(); | ||
| 879 | mtype_gc_do(set, h, t, r); | ||
| 880 | rcu_read_lock_bh(); | ||
| 881 | } | ||
| 882 | maxelem = h->maxelem; | ||
| 883 | elements = 0; | ||
| 884 | for (e = 0; e < ahash_numof_locks(t->htable_bits); e++) | ||
| 885 | elements += t->hregion[e].elements; | ||
| 886 | if (elements >= maxelem && SET_WITH_FORCEADD(set)) | ||
| 711 | forceadd = true; | 887 | forceadd = true; |
| 712 | } | 888 | } |
| 889 | rcu_read_unlock_bh(); | ||
| 713 | 890 | ||
| 714 | t = ipset_dereference_protected(h->table, set); | 891 | spin_lock_bh(&t->hregion[r].lock); |
| 715 | key = HKEY(value, h->initval, t->htable_bits); | 892 | n = rcu_dereference_bh(hbucket(t, key)); |
| 716 | n = __ipset_dereference_protected(hbucket(t, key), 1); | ||
| 717 | if (!n) { | 893 | if (!n) { |
| 718 | if (forceadd || set->elements >= h->maxelem) | 894 | if (forceadd || elements >= maxelem) |
| 719 | goto set_full; | 895 | goto set_full; |
| 720 | old = NULL; | 896 | old = NULL; |
| 721 | n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize, | 897 | n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize, |
| 722 | GFP_ATOMIC); | 898 | GFP_ATOMIC); |
| 723 | if (!n) | 899 | if (!n) { |
| 724 | return -ENOMEM; | 900 | ret = -ENOMEM; |
| 901 | goto unlock; | ||
| 902 | } | ||
| 725 | n->size = AHASH_INIT_SIZE; | 903 | n->size = AHASH_INIT_SIZE; |
| 726 | set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize); | 904 | t->hregion[r].ext_size += |
| 905 | ext_size(AHASH_INIT_SIZE, set->dsize); | ||
| 727 | goto copy_elem; | 906 | goto copy_elem; |
| 728 | } | 907 | } |
| 729 | for (i = 0; i < n->pos; i++) { | 908 | for (i = 0; i < n->pos; i++) { |
| @@ -737,38 +916,37 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 7 unmodified lines | |||
| 737 | } | 916 | } |
| 738 | data = ahash_data(n, i, set->dsize); | 917 | data = ahash_data(n, i, set->dsize); |
| 739 | if (mtype_data_equal(data, d, &multi)) { | 918 | if (mtype_data_equal(data, d, &multi)) { |
| 740 | if (flag_exist || | 919 | if (flag_exist || SET_ELEM_EXPIRED(set, data)) { |
| 741 | (SET_WITH_TIMEOUT(set) && | ||
| 742 | ip_set_timeout_expired(ext_timeout(data, set)))) { | ||
| 743 | /* Just the extensions could be overwritten */ | 920 | /* Just the extensions could be overwritten */ |
| 744 | j = i; | 921 | j = i; |
| 745 | goto overwrite_extensions; | 922 | goto overwrite_extensions; |
| 746 | } | 923 | } |
| 747 | return -IPSET_ERR_EXIST; | 924 | ret = -IPSET_ERR_EXIST; |
| 925 | goto unlock; | ||
| 748 | } | 926 | } |
| 749 | /* Reuse first timed out entry */ | 927 | /* Reuse first timed out entry */ |
| 750 | if (SET_WITH_TIMEOUT(set) && | 928 | if (SET_ELEM_EXPIRED(set, data) && j == -1) { |
| 751 | ip_set_timeout_expired(ext_timeout(data, set)) && | ||
| 752 | j == -1) { | ||
| 753 | j = i; | 929 | j = i; |
| 754 | reuse = true; | 930 | reuse = true; |
| 755 | } | 931 | } |
| 756 | } | 932 | } |
| 757 | if (reuse || forceadd) { | 933 | if (reuse || forceadd) { |
| 934 | if (j == -1) | ||
| 935 | j = 0; | ||
| 758 | data = ahash_data(n, j, set->dsize); | 936 | data = ahash_data(n, j, set->dsize); |
| 759 | if (!deleted) { | 937 | if (!deleted) { |
| 760 | #ifdef IP_SET_HASH_WITH_NETS | 938 | #ifdef IP_SET_HASH_WITH_NETS |
| 761 | for (i = 0; i < IPSET_NET_COUNT; i++) | 939 | for (i = 0; i < IPSET_NET_COUNT; i++) |
| 762 | mtype_del_cidr(h, | 940 | mtype_del_cidr(set, h, |
| 763 | NCIDR_PUT(DCIDR_GET(data->cidr, i)), | 941 | NCIDR_PUT(DCIDR_GET(data->cidr, i)), |
| 764 | i); | 942 | i); |
| 765 | #endif | 943 | #endif |
| 766 | ip_set_ext_destroy(set, data); | 944 | ip_set_ext_destroy(set, data); |
| 767 | set->elements--; | 945 | t->hregion[r].elements--; |
| 768 | } | 946 | } |
| 769 | goto copy_data; | 947 | goto copy_data; |
| 770 | } | 948 | } |
| 771 | if (set->elements >= h->maxelem) | 949 | if (elements >= maxelem) |
| 772 | goto set_full; | 950 | goto set_full; |
| 773 | /* Create a new slot */ | 951 | /* Create a new slot */ |
| 774 | if (n->pos >= n->size) { | 952 | if (n->pos >= n->size) { |
| @@ -776,28 +954,32 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 1 unmodified line | |||
| 776 | if (n->size >= AHASH_MAX(h)) { | 954 | if (n->size >= AHASH_MAX(h)) { |
| 777 | /* Trigger rehashing */ | 955 | /* Trigger rehashing */ |
| 778 | mtype_data_next(&h->next, d); | 956 | mtype_data_next(&h->next, d); |
| 779 | return -EAGAIN; | 957 | ret = -EAGAIN; |
| 958 | goto resize; | ||
| 780 | } | 959 | } |
| 781 | old = n; | 960 | old = n; |
| 782 | n = kzalloc(sizeof(*n) + | 961 | n = kzalloc(sizeof(*n) + |
| 783 | (old->size + AHASH_INIT_SIZE) * set->dsize, | 962 | (old->size + AHASH_INIT_SIZE) * set->dsize, |
| 784 | GFP_ATOMIC); | 963 | GFP_ATOMIC); |
| 785 | if (!n) | 964 | if (!n) { |
| 786 | return -ENOMEM; | 965 | ret = -ENOMEM; |
| 966 | goto unlock; | ||
| 967 | } | ||
| 787 | memcpy(n, old, sizeof(struct hbucket) + | 968 | memcpy(n, old, sizeof(struct hbucket) + |
| 788 | old->size * set->dsize); | 969 | old->size * set->dsize); |
| 789 | n->size = old->size + AHASH_INIT_SIZE; | 970 | n->size = old->size + AHASH_INIT_SIZE; |
| 790 | set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize); | 971 | t->hregion[r].ext_size += |
| 972 | ext_size(AHASH_INIT_SIZE, set->dsize); | ||
| 791 | } | 973 | } |
| 792 | 974 | ||
| 793 | copy_elem: | 975 | copy_elem: |
| 794 | j = n->pos++; | 976 | j = n->pos++; |
| 795 | data = ahash_data(n, j, set->dsize); | 977 | data = ahash_data(n, j, set->dsize); |
| 796 | copy_data: | 978 | copy_data: |
| 797 | set->elements++; | 979 | t->hregion[r].elements++; |
| 798 | #ifdef IP_SET_HASH_WITH_NETS | 980 | #ifdef IP_SET_HASH_WITH_NETS |
| 799 | for (i = 0; i < IPSET_NET_COUNT; i++) | 981 | for (i = 0; i < IPSET_NET_COUNT; i++) |
| 800 | mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i); | 982 | mtype_add_cidr(set, h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i); |
| 801 | #endif | 983 | #endif |
| 802 | memcpy(data, d, sizeof(struct mtype_elem)); | 984 | memcpy(data, d, sizeof(struct mtype_elem)); |
| 803 | overwrite_extensions: | 985 | overwrite_extensions: |
| @@ -820,13 +1002,41 @@ overwrite_extensions: · 16 unmodified lines | |||
| 820 | if (old) | 1002 | if (old) |
| 821 | kfree_rcu(old, rcu); | 1003 | kfree_rcu(old, rcu); |
| 822 | } | 1004 | } |
| 1005 | ret = 0; | ||
| 1006 | resize: | ||
| 1007 | spin_unlock_bh(&t->hregion[r].lock); | ||
| 1008 | if (atomic_read(&t->ref) && ext->target) { | ||
| 1009 | /* Resize is in process and kernel side add, save values */ | ||
| 1010 | struct mtype_resize_ad *x; | ||
| 1011 | |||
| 1012 | x = kzalloc(sizeof(struct mtype_resize_ad), GFP_ATOMIC); | ||
| 1013 | if (!x) | ||
| 1014 | /* Don't bother */ | ||
| 1015 | goto out; | ||
| 1016 | x->ad = IPSET_ADD; | ||
| 1017 | memcpy(&x->d, value, sizeof(struct mtype_elem)); | ||
| 1018 | memcpy(&x->ext, ext, sizeof(struct ip_set_ext)); | ||
| 1019 | memcpy(&x->mext, mext, sizeof(struct ip_set_ext)); | ||
| 1020 | x->flags = flags; | ||
| 1021 | spin_lock_bh(&set->lock); | ||
| 1022 | list_add_tail(&x->list, &h->ad); | ||
| 1023 | spin_unlock_bh(&set->lock); | ||
| 1024 | } | ||
| 1025 | goto out; | ||
| 823 | 1026 | ||
| 824 | return 0; | ||
| 825 | set_full: | 1027 | set_full: |
| 826 | if (net_ratelimit()) | 1028 | if (net_ratelimit()) |
| 827 | pr_warn("Set %s is full, maxelem %u reached\n", | 1029 | pr_warn("Set %s is full, maxelem %u reached\n", |
| 828 | set->name, h->maxelem); | 1030 | set->name, maxelem); |
| 829 | return -IPSET_ERR_HASH_FULL; | 1031 | ret = -IPSET_ERR_HASH_FULL; |
| 1032 | unlock: | ||
| 1033 | spin_unlock_bh(&t->hregion[r].lock); | ||
| 1034 | out: | ||
| 1035 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { | ||
| 1036 | pr_debug("Table destroy after resize by add: %p\n", t); | ||
| 1037 | mtype_ahash_destroy(set, t, false); | ||
| 1038 | } | ||
| 1039 | return ret; | ||
| 830 | } | 1040 | } |
| 831 | 1041 | ||
| 832 | /* Delete an element from the hash and free up space if possible. | 1042 | /* Delete an element from the hash and free up space if possible. |
| @@ -840,13 +1050,23 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 7 unmodified lines | |||
| 840 | const struct mtype_elem *d = value; | 1050 | const struct mtype_elem *d = value; |
| 841 | struct mtype_elem *data; | 1051 | struct mtype_elem *data; |
| 842 | struct hbucket *n; | 1052 | struct hbucket *n; |
| 843 | int i, j, k, ret = -IPSET_ERR_EXIST; | 1053 | struct mtype_resize_ad *x = NULL; |
| 1054 | int i, j, k, r, ret = -IPSET_ERR_EXIST; | ||
| 844 | u32 key, multi = 0; | 1055 | u32 key, multi = 0; |
| 845 | size_t dsize = set->dsize; | 1056 | size_t dsize = set->dsize; |
| 846 | 1057 | ||
| 847 | t = ipset_dereference_protected(h->table, set); | 1058 | /* Userspace add and resize is excluded by the mutex. |
| 1059 | * Kernespace add does not trigger resize. | ||
| 1060 | */ | ||
| 1061 | rcu_read_lock_bh(); | ||
| 1062 | t = rcu_dereference_bh(h->table); | ||
| 848 | key = HKEY(value, h->initval, t->htable_bits); | 1063 | key = HKEY(value, h->initval, t->htable_bits); |
| 849 | n = __ipset_dereference_protected(hbucket(t, key), 1); | 1064 | r = ahash_region(key, t->htable_bits); |
| 1065 | atomic_inc(&t->uref); | ||
| 1066 | rcu_read_unlock_bh(); | ||
| 1067 | |||
| 1068 | spin_lock_bh(&t->hregion[r].lock); | ||
| 1069 | n = rcu_dereference_bh(hbucket(t, key)); | ||
| 850 | if (!n) | 1070 | if (!n) |
| 851 | goto out; | 1071 | goto out; |
| 852 | for (i = 0, k = 0; i < n->pos; i++) { | 1072 | for (i = 0, k = 0; i < n->pos; i++) { |
| @@ -857,8 +1077,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 4 unmodified lines | |||
| 857 | data = ahash_data(n, i, dsize); | 1077 | data = ahash_data(n, i, dsize); |
| 858 | if (!mtype_data_equal(data, d, &multi)) | 1078 | if (!mtype_data_equal(data, d, &multi)) |
| 859 | continue; | 1079 | continue; |
| 860 | if (SET_WITH_TIMEOUT(set) && | 1080 | if (SET_ELEM_EXPIRED(set, data)) |
| 861 | ip_set_timeout_expired(ext_timeout(data, set))) | ||
| 862 | goto out; | 1081 | goto out; |
| 863 | 1082 | ||
| 864 | ret = 0; | 1083 | ret = 0; |
| @@ -866,20 +1085,33 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 1 unmodified line | |||
| 866 | smp_mb__after_atomic(); | 1085 | smp_mb__after_atomic(); |
| 867 | if (i + 1 == n->pos) | 1086 | if (i + 1 == n->pos) |
| 868 | n->pos--; | 1087 | n->pos--; |
| 869 | set->elements--; | 1088 | t->hregion[r].elements--; |
| 870 | #ifdef IP_SET_HASH_WITH_NETS | 1089 | #ifdef IP_SET_HASH_WITH_NETS |
| 871 | for (j = 0; j < IPSET_NET_COUNT; j++) | 1090 | for (j = 0; j < IPSET_NET_COUNT; j++) |
| 872 | mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)), | 1091 | mtype_del_cidr(set, h, |
| 873 | j); | 1092 | NCIDR_PUT(DCIDR_GET(d->cidr, j)), j); |
| 874 | #endif | 1093 | #endif |
| 875 | ip_set_ext_destroy(set, data); | 1094 | ip_set_ext_destroy(set, data); |
| 876 | 1095 | ||
| 1096 | if (atomic_read(&t->ref) && ext->target) { | ||
| 1097 | /* Resize is in process and kernel side del, | ||
| 1098 | * save values | ||
| 1099 | */ | ||
| 1100 | x = kzalloc(sizeof(struct mtype_resize_ad), | ||
| 1101 | GFP_ATOMIC); | ||
| 1102 | if (x) { | ||
| 1103 | x->ad = IPSET_DEL; | ||
| 1104 | memcpy(&x->d, value, | ||
| 1105 | sizeof(struct mtype_elem)); | ||
| 1106 | x->flags = flags; | ||
| 1107 | } | ||
| 1108 | } | ||
| 877 | for (; i < n->pos; i++) { | 1109 | for (; i < n->pos; i++) { |
| 878 | if (!test_bit(i, n->used)) | 1110 | if (!test_bit(i, n->used)) |
| 879 | k++; | 1111 | k++; |
| 880 | } | 1112 | } |
| 881 | if (n->pos == 0 && k == 0) { | 1113 | if (n->pos == 0 && k == 0) { |
| 882 | set->ext_size -= ext_size(n->size, dsize); | 1114 | t->hregion[r].ext_size -= ext_size(n->size, dsize); |
| 883 | rcu_assign_pointer(hbucket(t, key), NULL); | 1115 | rcu_assign_pointer(hbucket(t, key), NULL); |
| 884 | kfree_rcu(n, rcu); | 1116 | kfree_rcu(n, rcu); |
| 885 | } else if (k >= AHASH_INIT_SIZE) { | 1117 | } else if (k >= AHASH_INIT_SIZE) { |
| @@ -898,7 +1130,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 12 unmodified lines | |||
| 898 | k++; | 1130 | k++; |
| 899 | } | 1131 | } |
| 900 | tmp->pos = k; | 1132 | tmp->pos = k; |
| 901 | set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize); | 1133 | t->hregion[r].ext_size -= |
| 1134 | ext_size(AHASH_INIT_SIZE, dsize); | ||
| 902 | rcu_assign_pointer(hbucket(t, key), tmp); | 1135 | rcu_assign_pointer(hbucket(t, key), tmp); |
| 903 | kfree_rcu(n, rcu); | 1136 | kfree_rcu(n, rcu); |
| 904 | } | 1137 | } |
| @@ -906,6 +1139,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 1 unmodified line | |||
| 906 | } | 1139 | } |
| 907 | 1140 | ||
| 908 | out: | 1141 | out: |
| 1142 | spin_unlock_bh(&t->hregion[r].lock); | ||
| 1143 | if (x) { | ||
| 1144 | spin_lock_bh(&set->lock); | ||
| 1145 | list_add(&x->list, &h->ad); | ||
| 1146 | spin_unlock_bh(&set->lock); | ||
| 1147 | } | ||
| 1148 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { | ||
| 1149 | pr_debug("Table destroy after resize by del: %p\n", t); | ||
| 1150 | mtype_ahash_destroy(set, t, false); | ||
| 1151 | } | ||
| 909 | return ret; | 1152 | return ret; |
| 910 | } | 1153 | } |
| 911 | 1154 | ||
| @@ -991,6 +1234,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 79 unmodified lines | |||
| 991 | int i, ret = 0; | 1234 | int i, ret = 0; |
| 992 | u32 key, multi = 0; | 1235 | u32 key, multi = 0; |
| 993 | 1236 | ||
| 1237 | rcu_read_lock_bh(); | ||
| 994 | t = rcu_dereference_bh(h->table); | 1238 | t = rcu_dereference_bh(h->table); |
| 995 | #ifdef IP_SET_HASH_WITH_NETS | 1239 | #ifdef IP_SET_HASH_WITH_NETS |
| 996 | /* If we test an IP address and not a network address, | 1240 | /* If we test an IP address and not a network address, |
| @@ -1022,6 +1266,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, · 25 unmodified lines | |||
| 1022 | goto out; | 1266 | goto out; |
| 1023 | } | 1267 | } |
| 1024 | out: | 1268 | out: |
| 1269 | rcu_read_unlock_bh(); | ||
| 1025 | return ret; | 1270 | return ret; |
| 1026 | } | 1271 | } |
| 1027 | 1272 | ||
| @@ -1033,23 +1278,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) · 5 unmodified lines | |||
| 1033 | const struct htable *t; | 1278 | const struct htable *t; |
| 1034 | struct nlattr *nested; | 1279 | struct nlattr *nested; |
| 1035 | size_t memsize; | 1280 | size_t memsize; |
| 1281 | u32 elements = 0; | ||
| 1282 | size_t ext_size = 0; | ||
| 1036 | u8 htable_bits; | 1283 | u8 htable_bits; |
| 1037 | 1284 | ||
| 1038 | /* If any members have expired, set->elements will be wrong | ||
| 1039 | * mytype_expire function will update it with the right count. | ||
| 1040 | * we do not hold set->lock here, so grab it first. | ||
| 1041 | * set->elements can still be incorrect in the case of a huge set, | ||
| 1042 | * because elements might time out during the listing. | ||
| 1043 | */ | ||
| 1044 | if (SET_WITH_TIMEOUT(set)) { | ||
| 1045 | spin_lock_bh(&set->lock); | ||
| 1046 | mtype_expire(set, h); | ||
| 1047 | spin_unlock_bh(&set->lock); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | rcu_read_lock_bh(); | 1285 | rcu_read_lock_bh(); |
| 1051 | t = rcu_dereference_bh_nfnl(h->table); | 1286 | t = rcu_dereference_bh(h->table); |
| 1052 | memsize = mtype_ahash_memsize(h, t) + set->ext_size; | 1287 | mtype_ext_size(set, &elements, &ext_size); |
| 1288 | memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size; | ||
| 1053 | htable_bits = t->htable_bits; | 1289 | htable_bits = t->htable_bits; |
| 1054 | rcu_read_unlock_bh(); | 1290 | rcu_read_unlock_bh(); |
| 1055 | 1291 | ||
| @@ -1071,7 +1307,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) · 15 unmodified lines | |||
| 1071 | #endif | 1307 | #endif |
| 1072 | if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) || | 1308 | if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) || |
| 1073 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) || | 1309 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) || |
| 1074 | nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements))) | 1310 | nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements))) |
| 1075 | goto nla_put_failure; | 1311 | goto nla_put_failure; |
| 1076 | if (unlikely(ip_set_put_flags(skb, set))) | 1312 | if (unlikely(ip_set_put_flags(skb, set))) |
| 1077 | goto nla_put_failure; | 1313 | goto nla_put_failure; |
| @@ -1091,15 +1327,15 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start) · 13 unmodified lines | |||
| 1091 | 1327 | ||
| 1092 | if (start) { | 1328 | if (start) { |
| 1093 | rcu_read_lock_bh(); | 1329 | rcu_read_lock_bh(); |
| 1094 | t = rcu_dereference_bh_nfnl(h->table); | 1330 | t = ipset_dereference_bh_nfnl(h->table); |
| 1095 | atomic_inc(&t->uref); | 1331 | atomic_inc(&t->uref); |
| 1096 | cb->args[IPSET_CB_PRIVATE] = (unsigned long)t; | 1332 | cb->args[IPSET_CB_PRIVATE] = (unsigned long)t; |
| 1097 | rcu_read_unlock_bh(); | 1333 | rcu_read_unlock_bh(); |
| 1098 | } else if (cb->args[IPSET_CB_PRIVATE]) { | 1334 | } else if (cb->args[IPSET_CB_PRIVATE]) { |
| 1099 | t = (struct htable *)cb->args[IPSET_CB_PRIVATE]; | 1335 | t = (struct htable *)cb->args[IPSET_CB_PRIVATE]; |
| 1100 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { | 1336 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { |
| 1101 | /* Resizing didn't destroy the hash table */ | 1337 | pr_debug("Table destroy after resize " |
| 1102 | pr_debug("Table destroy by dump: %p\n", t); | 1338 | " by dump: %p\n", t); |
| 1103 | mtype_ahash_destroy(set, t, false); | 1339 | mtype_ahash_destroy(set, t, false); |
| 1104 | } | 1340 | } |
| 1105 | cb->args[IPSET_CB_PRIVATE] = 0; | 1341 | cb->args[IPSET_CB_PRIVATE] = 0; |
| @@ -1141,8 +1377,7 @@ mtype_list(const struct ip_set *set, · 35 unmodified lines | |||
| 1141 | if (!test_bit(i, n->used)) | 1377 | if (!test_bit(i, n->used)) |
| 1142 | continue; | 1378 | continue; |
| 1143 | e = ahash_data(n, i, set->dsize); | 1379 | e = ahash_data(n, i, set->dsize); |
| 1144 | if (SET_WITH_TIMEOUT(set) && | 1380 | if (SET_ELEM_EXPIRED(set, e)) |
| 1145 | ip_set_timeout_expired(ext_timeout(e, set))) | ||
| 1146 | continue; | 1381 | continue; |
| 1147 | pr_debug("list hash %lu hbucket %p i %u, data %p\n", | 1382 | pr_debug("list hash %lu hbucket %p i %u, data %p\n", |
| 1148 | cb->args[IPSET_CB_ARG0], n, i, e); | 1383 | cb->args[IPSET_CB_ARG0], n, i, e); |
| @@ -1208,6 +1443,7 @@ static const struct ip_set_type_variant mtype_variant = { · 59 unmodified lines | |||
| 1208 | .uref = mtype_uref, | 1443 | .uref = mtype_uref, |
| 1209 | .resize = mtype_resize, | 1444 | .resize = mtype_resize, |
| 1210 | .same_set = mtype_same_set, | 1445 | .same_set = mtype_same_set, |
| 1446 | .region_lock = true, | ||
| 1211 | }; | 1447 | }; |
| 1212 | 1448 | ||
| 1213 | #ifdef IP_SET_EMIT_CREATE | 1449 | #ifdef IP_SET_EMIT_CREATE |
| @@ -1226,6 +1462,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, · 12 unmodified lines | |||
| 1226 | size_t hsize; | 1462 | size_t hsize; |
| 1227 | struct htype *h; | 1463 | struct htype *h; |
| 1228 | struct htable *t; | 1464 | struct htable *t; |
| 1465 | u32 i; | ||
| 1229 | 1466 | ||
| 1230 | pr_debug("Create set %s with family %s\n", | 1467 | pr_debug("Create set %s with family %s\n", |
| 1231 | set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6"); | 1468 | set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6"); |
| @@ -1294,6 +1531,15 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, · 62 unmodified lines | |||
| 1294 | kfree(h); | 1531 | kfree(h); |
| 1295 | return -ENOMEM; | 1532 | return -ENOMEM; |
| 1296 | } | 1533 | } |
| 1534 | t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits)); | ||
| 1535 | if (!t->hregion) { | ||
| 1536 | kfree(t); | ||
| 1537 | kfree(h); | ||
| 1538 | return -ENOMEM; | ||
| 1539 | } | ||
| 1540 | h->gc.set = set; | ||
| 1541 | for (i = 0; i < ahash_numof_locks(hbits); i++) | ||
| 1542 | spin_lock_init(&t->hregion[i].lock); | ||
| 1297 | h->maxelem = maxelem; | 1543 | h->maxelem = maxelem; |
| 1298 | #ifdef IP_SET_HASH_WITH_NETMASK | 1544 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 1299 | h->netmask = netmask; | 1545 | h->netmask = netmask; |
| @@ -1304,9 +1550,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, · 4 unmodified lines | |||
| 1304 | get_random_bytes(&h->initval, sizeof(h->initval)); | 1550 | get_random_bytes(&h->initval, sizeof(h->initval)); |
| 1305 | 1551 | ||
| 1306 | t->htable_bits = hbits; | 1552 | t->htable_bits = hbits; |
| 1553 | t->maxelem = h->maxelem / ahash_numof_locks(hbits); | ||
| 1307 | RCU_INIT_POINTER(h->table, t); | 1554 | RCU_INIT_POINTER(h->table, t); |
| 1308 | 1555 | ||
| 1309 | h->set = set; | 1556 | INIT_LIST_HEAD(&h->ad); |
| 1310 | set->data = h; | 1557 | set->data = h; |
| 1311 | #ifndef IP_SET_PROTO_UNDEF | 1558 | #ifndef IP_SET_PROTO_UNDEF |
| 1312 | if (set->family == NFPROTO_IPV4) { | 1559 | if (set->family == NFPROTO_IPV4) { |
| @@ -1329,12 +1576,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, · 16 unmodified lines | |||
| 1329 | #ifndef IP_SET_PROTO_UNDEF | 1576 | #ifndef IP_SET_PROTO_UNDEF |
| 1330 | if (set->family == NFPROTO_IPV4) | 1577 | if (set->family == NFPROTO_IPV4) |
| 1331 | #endif | 1578 | #endif |
| 1332 | IPSET_TOKEN(HTYPE, 4_gc_init)(set, | 1579 | IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc); |
| 1333 | IPSET_TOKEN(HTYPE, 4_gc)); | ||
| 1334 | #ifndef IP_SET_PROTO_UNDEF | 1580 | #ifndef IP_SET_PROTO_UNDEF |
| 1335 | else | 1581 | else |
| 1336 | IPSET_TOKEN(HTYPE, 6_gc_init)(set, | 1582 | IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc); |
| 1337 | IPSET_TOKEN(HTYPE, 6_gc)); | ||
| 1338 | #endif | 1583 | #endif |
| 1339 | } | 1584 | } |
| 1340 | pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", | 1585 | pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", |
| @@ -1766,11 +1766,13 @@ static bool pipapo_match_field(struct nft_pipapo_field *f, · 1765 unmodified lines | |||
| 1766 | static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, | 1766 | static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, |
| 1767 | const struct nft_set_elem *elem) | 1767 | const struct nft_set_elem *elem) |
| 1768 | { | 1768 | { |
| 1769 | const u8 *data = (const u8 *)elem->key.val.data; | ||
| 1770 | struct nft_pipapo *priv = nft_set_priv(set); | 1769 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1771 | struct nft_pipapo_match *m = priv->clone; | 1770 | struct nft_pipapo_match *m = priv->clone; |
| 1771 | struct nft_pipapo_elem *e = elem->priv; | ||
| 1772 | int rules_f0, first_rule = 0; | 1772 | int rules_f0, first_rule = 0; |
| 1773 | struct nft_pipapo_elem *e; | 1773 | const u8 *data; |
| 1774 | |||
| 1775 | data = (const u8 *)nft_set_ext_key(&e->ext); | ||
| 1774 | 1776 | ||
| 1775 | e = pipapo_get(net, set, data, 0); | 1777 | e = pipapo_get(net, set, data, 0); |
| 1776 | if (IS_ERR(e)) | 1778 | if (IS_ERR(e)) |
| @@ -402,15 +402,6 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) · 401 unmodified lines | |||
| 402 | remove_proc_entry(hinfo->name, parent); | 402 | remove_proc_entry(hinfo->name, parent); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | static void htable_destroy(struct xt_hashlimit_htable *hinfo) | ||
| 406 | { | ||
| 407 | cancel_delayed_work_sync(&hinfo->gc_work); | ||
| 408 | htable_remove_proc_entry(hinfo); | ||
| 409 | htable_selective_cleanup(hinfo, true); | ||
| 410 | kfree(hinfo->name); | ||
| 411 | vfree(hinfo); | ||
| 412 | } | ||
| 413 | |||
| 414 | static struct xt_hashlimit_htable *htable_find_get(struct net *net, | 405 | static struct xt_hashlimit_htable *htable_find_get(struct net *net, |
| 415 | const char *name, | 406 | const char *name, |
| 416 | u_int8_t family) | 407 | u_int8_t family) |
| @@ -432,8 +423,13 @@ static void htable_put(struct xt_hashlimit_htable *hinfo) · 15 unmodified lines | |||
| 432 | { | 423 | { |
| 433 | if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) { | 424 | if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) { |
| 434 | hlist_del(&hinfo->node); | 425 | hlist_del(&hinfo->node); |
| 426 | htable_remove_proc_entry(hinfo); | ||
| 435 | mutex_unlock(&hashlimit_mutex); | 427 | mutex_unlock(&hashlimit_mutex); |
| 436 | htable_destroy(hinfo); | 428 | |
| 429 | cancel_delayed_work_sync(&hinfo->gc_work); | ||
| 430 | htable_selective_cleanup(hinfo, true); | ||
| 431 | kfree(hinfo->name); | ||
| 432 | vfree(hinfo); | ||
| 437 | } | 433 | } |
| 438 | } | 434 | } |
| 439 | 435 | ||
| @@ -497,8 +497,9 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family, · 496 unmodified lines | |||
| 497 | 497 | ||
| 498 | err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr, | 498 | err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr, |
| 499 | family->policy, validate, extack); | 499 | family->policy, validate, extack); |
| 500 | if (err && parallel) { | 500 | if (err) { |
| 501 | kfree(attrbuf); | 501 | if (parallel) |
| 502 | kfree(attrbuf); | ||
| 502 | return ERR_PTR(err); | 503 | return ERR_PTR(err); |
| 503 | } | 504 | } |
| 504 | return attrbuf; | 505 | return attrbuf; |
| @@ -186,6 +186,7 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act) · 185 unmodified lines | |||
| 186 | + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */ | 186 | + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */ |
| 187 | + cookie_len /* TCA_ACT_COOKIE */ | 187 | + cookie_len /* TCA_ACT_COOKIE */ |
| 188 | + nla_total_size(0) /* TCA_ACT_STATS nested */ | 188 | + nla_total_size(0) /* TCA_ACT_STATS nested */ |
| 189 | + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */ | ||
| 189 | /* TCA_STATS_BASIC */ | 190 | /* TCA_STATS_BASIC */ |
| 190 | + nla_total_size_64bit(sizeof(struct gnet_stats_basic)) | 191 | + nla_total_size_64bit(sizeof(struct gnet_stats_basic)) |
| 191 | /* TCA_STATS_PKT64 */ | 192 | /* TCA_STATS_PKT64 */ |
| @@ -512,15 +512,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code) · 511 unmodified lines | |||
| 512 | static int smc_connect_abort(struct smc_sock *smc, int reason_code, | 512 | static int smc_connect_abort(struct smc_sock *smc, int reason_code, |
| 513 | int local_contact) | 513 | int local_contact) |
| 514 | { | 514 | { |
| 515 | bool is_smcd = smc->conn.lgr->is_smcd; | ||
| 516 | |||
| 515 | if (local_contact == SMC_FIRST_CONTACT) | 517 | if (local_contact == SMC_FIRST_CONTACT) |
| 516 | smc_lgr_forget(smc->conn.lgr); | 518 | smc_lgr_cleanup_early(&smc->conn); |
| 517 | if (smc->conn.lgr->is_smcd) | 519 | else |
| 520 | smc_conn_free(&smc->conn); | ||
| 521 | if (is_smcd) | ||
| 518 | /* there is only one lgr role for SMC-D; use server lock */ | 522 | /* there is only one lgr role for SMC-D; use server lock */ |
| 519 | mutex_unlock(&smc_server_lgr_pending); | 523 | mutex_unlock(&smc_server_lgr_pending); |
| 520 | else | 524 | else |
| 521 | mutex_unlock(&smc_client_lgr_pending); | 525 | mutex_unlock(&smc_client_lgr_pending); |
| 522 | 526 | ||
| 523 | smc_conn_free(&smc->conn); | ||
| 524 | smc->connect_nonblock = 0; | 527 | smc->connect_nonblock = 0; |
| 525 | return reason_code; | 528 | return reason_code; |
| 526 | } | 529 | } |
| @@ -1091,7 +1094,6 @@ static void smc_listen_out_err(struct smc_sock *new_smc) · 564 unmodified lines | |||
| 1091 | if (newsmcsk->sk_state == SMC_INIT) | 1094 | if (newsmcsk->sk_state == SMC_INIT) |
| 1092 | sock_put(&new_smc->sk); /* passive closing */ | 1095 | sock_put(&new_smc->sk); /* passive closing */ |
| 1093 | newsmcsk->sk_state = SMC_CLOSED; | 1096 | newsmcsk->sk_state = SMC_CLOSED; |
| 1094 | smc_conn_free(&new_smc->conn); | ||
| 1095 | 1097 | ||
| 1096 | smc_listen_out(new_smc); | 1098 | smc_listen_out(new_smc); |
| 1097 | } | 1099 | } |
| @@ -1102,12 +1104,13 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code, · 4 unmodified lines | |||
| 1102 | { | 1104 | { |
| 1103 | /* RDMA setup failed, switch back to TCP */ | 1105 | /* RDMA setup failed, switch back to TCP */ |
| 1104 | if (local_contact == SMC_FIRST_CONTACT) | 1106 | if (local_contact == SMC_FIRST_CONTACT) |
| 1105 | smc_lgr_forget(new_smc->conn.lgr); | 1107 | smc_lgr_cleanup_early(&new_smc->conn); |
| 1108 | else | ||
| 1109 | smc_conn_free(&new_smc->conn); | ||
| 1106 | if (reason_code < 0) { /* error, no fallback possible */ | 1110 | if (reason_code < 0) { /* error, no fallback possible */ |
| 1107 | smc_listen_out_err(new_smc); | 1111 | smc_listen_out_err(new_smc); |
| 1108 | return; | 1112 | return; |
| 1109 | } | 1113 | } |
| 1110 | smc_conn_free(&new_smc->conn); | ||
| 1111 | smc_switch_to_fallback(new_smc); | 1114 | smc_switch_to_fallback(new_smc); |
| 1112 | new_smc->fallback_rsn = reason_code; | 1115 | new_smc->fallback_rsn = reason_code; |
| 1113 | if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { | 1116 | if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { |
| @@ -1170,16 +1173,18 @@ static int smc_listen_ism_init(struct smc_sock *new_smc, · 56 unmodified lines | |||
| 1170 | new_smc->conn.lgr->vlan_id, | 1173 | new_smc->conn.lgr->vlan_id, |
| 1171 | new_smc->conn.lgr->smcd)) { | 1174 | new_smc->conn.lgr->smcd)) { |
| 1172 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) | 1175 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
| 1173 | smc_lgr_forget(new_smc->conn.lgr); | 1176 | smc_lgr_cleanup_early(&new_smc->conn); |
| 1174 | smc_conn_free(&new_smc->conn); | 1177 | else |
| 1178 | smc_conn_free(&new_smc->conn); | ||
| 1175 | return SMC_CLC_DECL_SMCDNOTALK; | 1179 | return SMC_CLC_DECL_SMCDNOTALK; |
| 1176 | } | 1180 | } |
| 1177 | 1181 | ||
| 1178 | /* Create send and receive buffers */ | 1182 | /* Create send and receive buffers */ |
| 1179 | if (smc_buf_create(new_smc, true)) { | 1183 | if (smc_buf_create(new_smc, true)) { |
| 1180 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) | 1184 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
| 1181 | smc_lgr_forget(new_smc->conn.lgr); | 1185 | smc_lgr_cleanup_early(&new_smc->conn); |
| 1182 | smc_conn_free(&new_smc->conn); | 1186 | else |
| 1187 | smc_conn_free(&new_smc->conn); | ||
| 1183 | return SMC_CLC_DECL_MEM; | 1188 | return SMC_CLC_DECL_MEM; |
| 1184 | } | 1189 | } |
| 1185 | 1190 | ||
| @@ -162,6 +162,18 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn) · 161 unmodified lines | |||
| 162 | conn->lgr = NULL; | 162 | conn->lgr = NULL; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | void smc_lgr_cleanup_early(struct smc_connection *conn) | ||
| 166 | { | ||
| 167 | struct smc_link_group *lgr = conn->lgr; | ||
| 168 | |||
| 169 | if (!lgr) | ||
| 170 | return; | ||
| 171 | |||
| 172 | smc_conn_free(conn); | ||
| 173 | smc_lgr_forget(lgr); | ||
| 174 | smc_lgr_schedule_free_work_fast(lgr); | ||
| 175 | } | ||
| 176 | |||
| 165 | /* Send delete link, either as client to request the initiation | 177 | /* Send delete link, either as client to request the initiation |
| 166 | * of the DELETE LINK sequence from server; or as server to | 178 | * of the DELETE LINK sequence from server; or as server to |
| 167 | * initiate the delete processing. See smc_llc_rx_delete_link(). | 179 | * initiate the delete processing. See smc_llc_rx_delete_link(). |
| @@ -296,6 +296,7 @@ struct smc_clc_msg_accept_confirm; · 295 unmodified lines | |||
| 296 | struct smc_clc_msg_local; | 296 | struct smc_clc_msg_local; |
| 297 | 297 | ||
| 298 | void smc_lgr_forget(struct smc_link_group *lgr); | 298 | void smc_lgr_forget(struct smc_link_group *lgr); |
| 299 | void smc_lgr_cleanup_early(struct smc_connection *conn); | ||
| 299 | void smc_lgr_terminate(struct smc_link_group *lgr, bool soft); | 300 | void smc_lgr_terminate(struct smc_link_group *lgr, bool soft); |
| 300 | void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); | 301 | void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); |
| 301 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, | 302 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, |
| @@ -316,7 +317,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini); · 14 unmodified lines | |||
| 316 | 317 | ||
| 317 | void smc_conn_free(struct smc_connection *conn); | 318 | void smc_conn_free(struct smc_connection *conn); |
| 318 | int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini); | 319 | int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini); |
| 319 | void smcd_conn_free(struct smc_connection *conn); | ||
| 320 | void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr); | 320 | void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr); |
| 321 | int smc_core_init(void); | 321 | int smc_core_init(void); |
| 322 | void smc_core_exit(void); | 322 | void smc_core_exit(void); |
| @@ -573,6 +573,8 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data) · 572 unmodified lines | |||
| 573 | struct smc_ib_device *smcibdev; | 573 | struct smc_ib_device *smcibdev; |
| 574 | 574 | ||
| 575 | smcibdev = ib_get_client_data(ibdev, &smc_ib_client); | 575 | smcibdev = ib_get_client_data(ibdev, &smc_ib_client); |
| 576 | if (!smcibdev || smcibdev->ibdev != ibdev) | ||
| 577 | return; | ||
| 576 | ib_set_client_data(ibdev, &smc_ib_client, NULL); | 578 | ib_set_client_data(ibdev, &smc_ib_client, NULL); |
| 577 | spin_lock(&smc_ib_devices.lock); | 579 | spin_lock(&smc_ib_devices.lock); |
| 578 | list_del_init(&smcibdev->list); /* remove from smc_ib_devices */ | 580 | list_del_init(&smcibdev->list); /* remove from smc_ib_devices */ |
| @@ -682,6 +682,7 @@ static int unix_set_peek_off(struct sock *sk, int val) · 681 unmodified lines | |||
| 682 | return 0; | 682 | return 0; |
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | #ifdef CONFIG_PROC_FS | ||
| 685 | static void unix_show_fdinfo(struct seq_file *m, struct socket *sock) | 686 | static void unix_show_fdinfo(struct seq_file *m, struct socket *sock) |
| 686 | { | 687 | { |
| 687 | struct sock *sk = sock->sk; | 688 | struct sock *sk = sock->sk; |
| @@ -692,6 +693,9 @@ static void unix_show_fdinfo(struct seq_file *m, struct socket *sock) · 4 unmodified lines | |||
| 692 | seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds)); | 693 | seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds)); |
| 693 | } | 694 | } |
| 694 | } | 695 | } |
| 696 | #else | ||
| 697 | #define unix_show_fdinfo NULL | ||
| 698 | #endif | ||
| 695 | 699 | ||
| 696 | static const struct proto_ops unix_stream_ops = { | 700 | static const struct proto_ops unix_stream_ops = { |
| 697 | .family = PF_UNIX, | 701 | .family = PF_UNIX, |
| @@ -451,6 +451,12 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk) · 450 unmodified lines | |||
| 451 | if (vsk->transport == new_transport) | 451 | if (vsk->transport == new_transport) |
| 452 | return 0; | 452 | return 0; |
| 453 | 453 | ||
| 454 | /* transport->release() must be called with sock lock acquired. | ||
| 455 | * This path can only be taken during vsock_stream_connect(), | ||
| 456 | * where we have already held the sock lock. | ||
| 457 | * In the other cases, this function is called on a new socket | ||
| 458 | * which is not assigned to any transport. | ||
| 459 | */ | ||
| 454 | vsk->transport->release(vsk); | 460 | vsk->transport->release(vsk); |
| 455 | vsock_deassign_transport(vsk); | 461 | vsock_deassign_transport(vsk); |
| 456 | } | 462 | } |
| @@ -753,20 +759,18 @@ static void __vsock_release(struct sock *sk, int level) · 296 unmodified lines | |||
| 753 | vsk = vsock_sk(sk); | 759 | vsk = vsock_sk(sk); |
| 754 | pending = NULL; /* Compiler warning. */ | 760 | pending = NULL; /* Compiler warning. */ |
| 755 | 761 | ||
| 756 | /* The release call is supposed to use lock_sock_nested() | ||
| 757 | * rather than lock_sock(), if a sock lock should be acquired. | ||
| 758 | */ | ||
| 759 | if (vsk->transport) | ||
| 760 | vsk->transport->release(vsk); | ||
| 761 | else if (sk->sk_type == SOCK_STREAM) | ||
| 762 | vsock_remove_sock(vsk); | ||
| 763 | |||
| 764 | /* When "level" is SINGLE_DEPTH_NESTING, use the nested | 762 | /* When "level" is SINGLE_DEPTH_NESTING, use the nested |
| 765 | * version to avoid the warning "possible recursive locking | 763 | * version to avoid the warning "possible recursive locking |
| 766 | * detected". When "level" is 0, lock_sock_nested(sk, level) | 764 | * detected". When "level" is 0, lock_sock_nested(sk, level) |
| 767 | * is the same as lock_sock(sk). | 765 | * is the same as lock_sock(sk). |
| 768 | */ | 766 | */ |
| 769 | lock_sock_nested(sk, level); | 767 | lock_sock_nested(sk, level); |
| 768 | |||
| 769 | if (vsk->transport) | ||
| 770 | vsk->transport->release(vsk); | ||
| 771 | else if (sk->sk_type == SOCK_STREAM) | ||
| 772 | vsock_remove_sock(vsk); | ||
| 773 | |||
| 770 | sock_orphan(sk); | 774 | sock_orphan(sk); |
| 771 | sk->sk_shutdown = SHUTDOWN_MASK; | 775 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 772 | 776 | ||
| @@ -526,12 +526,9 @@ static bool hvs_close_lock_held(struct vsock_sock *vsk) · 525 unmodified lines | |||
| 526 | 526 | ||
| 527 | static void hvs_release(struct vsock_sock *vsk) | 527 | static void hvs_release(struct vsock_sock *vsk) |
| 528 | { | 528 | { |
| 529 | struct sock *sk = sk_vsock(vsk); | ||
| 530 | bool remove_sock; | 529 | bool remove_sock; |
| 531 | 530 | ||
| 532 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | ||
| 533 | remove_sock = hvs_close_lock_held(vsk); | 531 | remove_sock = hvs_close_lock_held(vsk); |
| 534 | release_sock(sk); | ||
| 535 | if (remove_sock) | 532 | if (remove_sock) |
| 536 | vsock_remove_sock(vsk); | 533 | vsock_remove_sock(vsk); |
| 537 | } | 534 | } |
| @@ -829,7 +829,6 @@ void virtio_transport_release(struct vsock_sock *vsk) · 828 unmodified lines | |||
| 829 | struct sock *sk = &vsk->sk; | 829 | struct sock *sk = &vsk->sk; |
| 830 | bool remove_sock = true; | 830 | bool remove_sock = true; |
| 831 | 831 | ||
| 832 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | ||
| 833 | if (sk->sk_type == SOCK_STREAM) | 832 | if (sk->sk_type == SOCK_STREAM) |
| 834 | remove_sock = virtio_transport_close(vsk); | 833 | remove_sock = virtio_transport_close(vsk); |
| 835 | 834 | ||
| @@ -837,7 +836,6 @@ void virtio_transport_release(struct vsock_sock *vsk) · 1 unmodified line | |||
| 837 | list_del(&pkt->list); | 836 | list_del(&pkt->list); |
| 838 | virtio_transport_free_pkt(pkt); | 837 | virtio_transport_free_pkt(pkt); |
| 839 | } | 838 | } |
| 840 | release_sock(sk); | ||
| 841 | 839 | ||
| 842 | if (remove_sock) | 840 | if (remove_sock) |
| 843 | vsock_remove_sock(vsk); | 841 | vsock_remove_sock(vsk); |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | #include <linux/netlink.h> | 20 | #include <linux/netlink.h> |
| 21 | #include <linux/nospec.h> | 21 | #include <linux/nospec.h> |
| 22 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
| 23 | #include <linux/if_vlan.h> | ||
| 23 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
| 24 | #include <net/genetlink.h> | 25 | #include <net/genetlink.h> |
| 25 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
| @@ -4800,8 +4801,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 4774 unmodified lines | |||
| 4800 | err = nl80211_parse_he_obss_pd( | 4801 | err = nl80211_parse_he_obss_pd( |
| 4801 | info->attrs[NL80211_ATTR_HE_OBSS_PD], | 4802 | info->attrs[NL80211_ATTR_HE_OBSS_PD], |
| 4802 | ¶ms.he_obss_pd); | 4803 | ¶ms.he_obss_pd); |
| 4803 | if (err) | 4804 | goto out; |
| 4804 | return err; | ||
| 4805 | } | 4805 | } |
| 4806 | 4806 | ||
| 4807 | nl80211_calculate_ap_params(¶ms); | 4807 | nl80211_calculate_ap_params(¶ms); |
| @@ -4823,6 +4823,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 15 unmodified lines | |||
| 4823 | } | 4823 | } |
| 4824 | wdev_unlock(wdev); | 4824 | wdev_unlock(wdev); |
| 4825 | 4825 | ||
| 4826 | out: | ||
| 4826 | kfree(params.acl); | 4827 | kfree(params.acl); |
| 4827 | 4828 | ||
| 4828 | return err; | 4829 | return err; |
| @@ -2276,7 +2276,7 @@ static void handle_channel_custom(struct wiphy *wiphy, · 2275 unmodified lines | |||
| 2276 | break; | 2276 | break; |
| 2277 | } | 2277 | } |
| 2278 | 2278 | ||
| 2279 | if (IS_ERR(reg_rule)) { | 2279 | if (IS_ERR_OR_NULL(reg_rule)) { |
| 2280 | pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", | 2280 | pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", |
| 2281 | chan->center_freq); | 2281 | chan->center_freq); |
| 2282 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { | 2282 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { |
| @@ -13,11 +13,12 @@ · 12 unmodified lines | |||
| 13 | KSELFTEST_SKIP=4 | 13 | KSELFTEST_SKIP=4 |
| 14 | 14 | ||
| 15 | # Available test groups: | 15 | # Available test groups: |
| 16 | # - reported_issues: check for issues that were reported in the past | ||
| 16 | # - correctness: check that packets match given entries, and only those | 17 | # - correctness: check that packets match given entries, and only those |
| 17 | # - concurrency: attempt races between insertion, deletion and lookup | 18 | # - concurrency: attempt races between insertion, deletion and lookup |
| 18 | # - timeout: check that packets match entries until they expire | 19 | # - timeout: check that packets match entries until they expire |
| 19 | # - performance: estimate matching rate, compare with rbtree and hash baselines | 20 | # - performance: estimate matching rate, compare with rbtree and hash baselines |
| 20 | TESTS="correctness concurrency timeout" | 21 | TESTS="reported_issues correctness concurrency timeout" |
| 21 | [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance" | 22 | [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance" |
| 22 | 23 | ||
| 23 | # Set types, defined by TYPE_ variables below | 24 | # Set types, defined by TYPE_ variables below |
| @@ -25,6 +26,9 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto · 1 unmodified line | |||
| 25 | net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port | 26 | net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port |
| 26 | net_port_mac_proto_net" | 27 | net_port_mac_proto_net" |
| 27 | 28 | ||
| 29 | # Reported bugs, also described by TYPE_ variables below | ||
| 30 | BUGS="flush_remove_add" | ||
| 31 | |||
| 28 | # List of possible paths to pktgen script from kernel tree for performance tests | 32 | # List of possible paths to pktgen script from kernel tree for performance tests |
| 29 | PKTGEN_SCRIPT_PATHS=" | 33 | PKTGEN_SCRIPT_PATHS=" |
| 30 | ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh | 34 | ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh |
| @@ -327,6 +331,12 @@ flood_spec ip daddr . tcp dport . meta l4proto . ip saddr · 296 unmodified lines | |||
| 327 | perf_duration 0 | 331 | perf_duration 0 |
| 328 | " | 332 | " |
| 329 | 333 | ||
| 334 | # Definition of tests for bugs reported in the past: | ||
| 335 | # display display text for test report | ||
| 336 | TYPE_flush_remove_add=" | ||
| 337 | display Add two elements, flush, re-add | ||
| 338 | " | ||
| 339 | |||
| 330 | # Set template for all tests, types and rules are filled in depending on test | 340 | # Set template for all tests, types and rules are filled in depending on test |
| 331 | set_template=' | 341 | set_template=' |
| 332 | flush ruleset | 342 | flush ruleset |
| @@ -440,6 +450,8 @@ setup_set() { · 107 unmodified lines | |||
| 440 | 450 | ||
| 441 | # Check that at least one of the needed tools is available | 451 | # Check that at least one of the needed tools is available |
| 442 | check_tools() { | 452 | check_tools() { |
| 453 | [ -z "${tools}" ] && return 0 | ||
| 454 | |||
| 443 | __tools= | 455 | __tools= |
| 444 | for tool in ${tools}; do | 456 | for tool in ${tools}; do |
| 445 | if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \ | 457 | if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \ |
| @@ -1025,7 +1037,7 @@ format_noconcat() { · 579 unmodified lines | |||
| 1025 | add() { | 1037 | add() { |
| 1026 | if ! nft add element inet filter test "${1}"; then | 1038 | if ! nft add element inet filter test "${1}"; then |
| 1027 | err "Failed to add ${1} given ruleset:" | 1039 | err "Failed to add ${1} given ruleset:" |
| 1028 | err "$(nft list ruleset -a)" | 1040 | err "$(nft -a list ruleset)" |
| 1029 | return 1 | 1041 | return 1 |
| 1030 | fi | 1042 | fi |
| 1031 | } | 1043 | } |
| @@ -1045,7 +1057,7 @@ add_perf() { · 13 unmodified lines | |||
| 1045 | add_perf_norange() { | 1057 | add_perf_norange() { |
| 1046 | if ! nft add element netdev perf norange "${1}"; then | 1058 | if ! nft add element netdev perf norange "${1}"; then |
| 1047 | err "Failed to add ${1} given ruleset:" | 1059 | err "Failed to add ${1} given ruleset:" |
| 1048 | err "$(nft list ruleset -a)" | 1060 | err "$(nft -a list ruleset)" |
| 1049 | return 1 | 1061 | return 1 |
| 1050 | fi | 1062 | fi |
| 1051 | } | 1063 | } |
| @@ -1054,7 +1066,7 @@ add_perf_norange() { · 2 unmodified lines | |||
| 1054 | add_perf_noconcat() { | 1066 | add_perf_noconcat() { |
| 1055 | if ! nft add element netdev perf noconcat "${1}"; then | 1067 | if ! nft add element netdev perf noconcat "${1}"; then |
| 1056 | err "Failed to add ${1} given ruleset:" | 1068 | err "Failed to add ${1} given ruleset:" |
| 1057 | err "$(nft list ruleset -a)" | 1069 | err "$(nft -a list ruleset)" |
| 1058 | return 1 | 1070 | return 1 |
| 1059 | fi | 1071 | fi |
| 1060 | } | 1072 | } |
| @@ -1063,7 +1075,7 @@ add_perf_noconcat() { · 2 unmodified lines | |||
| 1063 | del() { | 1075 | del() { |
| 1064 | if ! nft delete element inet filter test "${1}"; then | 1076 | if ! nft delete element inet filter test "${1}"; then |
| 1065 | err "Failed to delete ${1} given ruleset:" | 1077 | err "Failed to delete ${1} given ruleset:" |
| 1066 | err "$(nft list ruleset -a)" | 1078 | err "$(nft -a list ruleset)" |
| 1067 | return 1 | 1079 | return 1 |
| 1068 | fi | 1080 | fi |
| 1069 | } | 1081 | } |
| @@ -1134,7 +1146,7 @@ send_match() { · 64 unmodified lines | |||
| 1134 | err " $(for f in ${src}; do | 1146 | err " $(for f in ${src}; do |
| 1135 | eval format_\$f "${2}"; printf ' '; done)" | 1147 | eval format_\$f "${2}"; printf ' '; done)" |
| 1136 | err "should have matched ruleset:" | 1148 | err "should have matched ruleset:" |
| 1137 | err "$(nft list ruleset -a)" | 1149 | err "$(nft -a list ruleset)" |
| 1138 | return 1 | 1150 | return 1 |
| 1139 | fi | 1151 | fi |
| 1140 | nft reset counter inet filter test >/dev/null | 1152 | nft reset counter inet filter test >/dev/null |
| @@ -1160,7 +1172,7 @@ send_nomatch() { · 19 unmodified lines | |||
| 1160 | err " $(for f in ${src}; do | 1172 | err " $(for f in ${src}; do |
| 1161 | eval format_\$f "${2}"; printf ' '; done)" | 1173 | eval format_\$f "${2}"; printf ' '; done)" |
| 1162 | err "should not have matched ruleset:" | 1174 | err "should not have matched ruleset:" |
| 1163 | err "$(nft list ruleset -a)" | 1175 | err "$(nft -a list ruleset)" |
| 1164 | return 1 | 1176 | return 1 |
| 1165 | fi | 1177 | fi |
| 1166 | } | 1178 | } |
| @@ -1430,6 +1442,23 @@ test_performance() { · 263 unmodified lines | |||
| 1430 | kill "${perf_pid}" | 1442 | kill "${perf_pid}" |
| 1431 | } | 1443 | } |
| 1432 | 1444 | ||
| 1445 | test_bug_flush_remove_add() { | ||
| 1446 | set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }' | ||
| 1447 | elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }' | ||
| 1448 | elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }' | ||
| 1449 | for i in `seq 1 100`; do | ||
| 1450 | nft add table t ${set_cmd} || return ${KSELFTEST_SKIP} | ||
| 1451 | nft add element t s ${elem1} 2>/dev/null || return 1 | ||
| 1452 | nft flush set t s 2>/dev/null || return 1 | ||
| 1453 | nft add element t s ${elem2} 2>/dev/null || return 1 | ||
| 1454 | done | ||
| 1455 | nft flush ruleset | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | test_reported_issues() { | ||
| 1459 | eval test_bug_"${subtest}" | ||
| 1460 | } | ||
| 1461 | |||
| 1433 | # Run everything in a separate network namespace | 1462 | # Run everything in a separate network namespace |
| 1434 | [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } | 1463 | [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } |
| 1435 | tmp="$(mktemp)" | 1464 | tmp="$(mktemp)" |
| @@ -1438,9 +1467,15 @@ trap cleanup EXIT · 2 unmodified lines | |||
| 1438 | # Entry point for test runs | 1467 | # Entry point for test runs |
| 1439 | passed=0 | 1468 | passed=0 |
| 1440 | for name in ${TESTS}; do | 1469 | for name in ${TESTS}; do |
| 1441 | printf "TEST: %s\n" "${name}" | 1470 | printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')" |
| 1442 | for type in ${TYPES}; do | 1471 | if [ "${name}" = "reported_issues" ]; then |
| 1443 | eval desc=\$TYPE_"${type}" | 1472 | SUBTESTS="${BUGS}" |
| 1473 | else | ||
| 1474 | SUBTESTS="${TYPES}" | ||
| 1475 | fi | ||
| 1476 | |||
| 1477 | for subtest in ${SUBTESTS}; do | ||
| 1478 | eval desc=\$TYPE_"${subtest}" | ||
| 1444 | IFS=' | 1479 | IFS=' |
| 1445 | ' | 1480 | ' |
| 1446 | for __line in ${desc}; do | 1481 | for __line in ${desc}; do |