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 | 487 | The stubs set one of the two matching criteria, and set the other one to |
| 488 | 488 | match anything. |
| 489 | 489 | |
| 490 | −When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module, | |
| 491 | −unregister fixup and free allocate memory are required. | |
| 490 | +When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load | |
| 491 | +time, the module needs to unregister the fixup and free allocated memory when | |
| 492 | +it's unloaded. | |
| 492 | 493 | |
| 493 | 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 | 69 | /* Force link status for IMP port */ |
| 70 | 70 | reg = core_readl(priv, offset); |
| 71 | 71 | reg |= (MII_SW_OR | LINK_STS); |
| 72 | − if (priv->type == BCM7278_DEVICE_ID) | |
| 73 | − reg |= GMII_SPEED_UP_2G; | |
| 72 | + reg &= ~GMII_SPEED_UP_2G; | |
| 74 | 73 | core_writel(priv, reg, offset); |
| 75 | 74 | |
| 76 | 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 | 278 | switch (direction) { |
| 279 | 279 | case MV88E6XXX_EGRESS_DIR_INGRESS: |
| 280 | 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 | 282 | reg |= port << |
| 283 | 283 | __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); |
| 284 | 284 | break; |
| 285 | 285 | case MV88E6XXX_EGRESS_DIR_EGRESS: |
| 286 | 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 | 288 | reg |= port << |
| 289 | 289 | __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); |
| 290 | 290 | break; |
| @@ -11252,7 +11252,7 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp) · 11251 unmodified lines | ||
| 11252 | 11252 | } |
| 11253 | 11253 | } |
| 11254 | 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 | 11258 | #else |
| @@ -11759,7 +11759,7 @@ static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[]) · 500 unmodified lines | ||
| 11759 | 11759 | u32 dw; |
| 11760 | 11760 | |
| 11761 | 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 | 11763 | return -EOPNOTSUPP; |
| 11764 | 11764 | } |
| 11765 | 11765 | |
| @@ -641,14 +641,14 @@ static int bnxt_dl_params_register(struct bnxt *bp) · 640 unmodified lines | ||
| 641 | 641 | rc = devlink_params_register(bp->dl, bnxt_dl_params, |
| 642 | 642 | ARRAY_SIZE(bnxt_dl_params)); |
| 643 | 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 | 645 | rc); |
| 646 | 646 | return rc; |
| 647 | 647 | } |
| 648 | 648 | rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, |
| 649 | 649 | ARRAY_SIZE(bnxt_dl_port_params)); |
| 650 | 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 | 652 | devlink_params_unregister(bp->dl, bnxt_dl_params, |
| 653 | 653 | ARRAY_SIZE(bnxt_dl_params)); |
| 654 | 654 | return rc; |
| @@ -679,7 +679,7 @@ int bnxt_dl_register(struct bnxt *bp) · 24 unmodified lines | ||
| 679 | 679 | else |
| 680 | 680 | dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl)); |
| 681 | 681 | if (!dl) { |
| 682 | − netdev_warn(bp->dev, "devlink_alloc failed"); | |
| 682 | + netdev_warn(bp->dev, "devlink_alloc failed\n"); | |
| 683 | 683 | return -ENOMEM; |
| 684 | 684 | } |
| 685 | 685 | |
| @@ -692,7 +692,7 @@ int bnxt_dl_register(struct bnxt *bp) · 6 unmodified lines | ||
| 692 | 692 | |
| 693 | 693 | rc = devlink_register(dl, &bp->pdev->dev); |
| 694 | 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 | 696 | goto err_dl_free; |
| 697 | 697 | } |
| 698 | 698 | |
| @@ -704,7 +704,7 @@ int bnxt_dl_register(struct bnxt *bp) · 5 unmodified lines | ||
| 704 | 704 | sizeof(bp->dsn)); |
| 705 | 705 | rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); |
| 706 | 706 | if (rc) { |
| 707 | − netdev_err(bp->dev, "devlink_port_register failed"); | |
| 707 | + netdev_err(bp->dev, "devlink_port_register failed\n"); | |
| 708 | 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 | 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 | 2032 | (unsigned long)fw->size); |
| 2033 | 2033 | rc = -EFBIG; |
| 2034 | 2034 | } else { |
| @@ -3338,7 +3338,7 @@ err: · 1303 unmodified lines | ||
| 3338 | 3338 | kfree(coredump.data); |
| 3339 | 3339 | *dump_len += sizeof(struct bnxt_coredump_record); |
| 3340 | 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 | 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 | 51 | /* check if dev belongs to the same switch */ |
| 52 | 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 | 54 | dev->ifindex); |
| 55 | 55 | return BNXT_FID_INVALID; |
| 56 | 56 | } |
| @@ -70,7 +70,7 @@ static int bnxt_tc_parse_redir(struct bnxt *bp, · 13 unmodified lines | ||
| 70 | 70 | struct net_device *dev = act->dev; |
| 71 | 71 | |
| 72 | 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 | 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 | 106 | const struct ip_tunnel_key *tun_key = &tun_info->key; |
| 107 | 107 | |
| 108 | 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 | 110 | return -EOPNOTSUPP; |
| 111 | 111 | } |
| 112 | 112 | |
| @@ -295,7 +295,7 @@ static int bnxt_tc_parse_actions(struct bnxt *bp, · 182 unmodified lines | ||
| 295 | 295 | int i, rc; |
| 296 | 296 | |
| 297 | 297 | if (!flow_action_has_entries(flow_action)) { |
| 298 | − netdev_info(bp->dev, "no actions"); | |
| 298 | + netdev_info(bp->dev, "no actions\n"); | |
| 299 | 299 | return -EINVAL; |
| 300 | 300 | } |
| 301 | 301 | |
| @@ -370,7 +370,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp, · 68 unmodified lines | ||
| 370 | 370 | /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ |
| 371 | 371 | if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || |
| 372 | 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 | 374 | dissector->used_keys); |
| 375 | 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 | 509 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 510 | 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 | 513 | return rc; |
| 514 | 514 | } |
| @@ -841,7 +841,7 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp, · 326 unmodified lines | ||
| 841 | 841 | resp = bnxt_get_hwrm_resp_addr(bp, &req); |
| 842 | 842 | *decap_filter_handle = resp->decap_filter_id; |
| 843 | 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 | 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 | 860 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 861 | 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 | 864 | return rc; |
| 865 | 865 | } |
| @@ -906,7 +906,7 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp, · 40 unmodified lines | ||
| 906 | 906 | resp = bnxt_get_hwrm_resp_addr(bp, &req); |
| 907 | 907 | *encap_record_handle = resp->encap_record_id; |
| 908 | 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 | 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 | 925 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 926 | 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 | 929 | return rc; |
| 930 | 930 | } |
| @@ -943,7 +943,7 @@ static int bnxt_tc_put_l2_node(struct bnxt *bp, · 12 unmodified lines | ||
| 943 | 943 | tc_info->l2_ht_params); |
| 944 | 944 | if (rc) |
| 945 | 945 | netdev_err(bp->dev, |
| 946 | − "Error: %s: rhashtable_remove_fast: %d", | |
| 946 | + "Error: %s: rhashtable_remove_fast: %d\n", | |
| 947 | 947 | __func__, rc); |
| 948 | 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 | 972 | if (rc) { |
| 973 | 973 | kfree_rcu(l2_node, rcu); |
| 974 | 974 | netdev_err(bp->dev, |
| 975 | − "Error: %s: rhashtable_insert_fast: %d", | |
| 975 | + "Error: %s: rhashtable_insert_fast: %d\n", | |
| 976 | 976 | __func__, rc); |
| 977 | 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 | 1031 | if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) && |
| 1032 | 1032 | (flow->l4_key.ip_proto != IPPROTO_TCP && |
| 1033 | 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 | 1035 | flow->l4_key.ip_proto); |
| 1036 | 1036 | return false; |
| 1037 | 1037 | } |
| @@ -1088,7 +1088,7 @@ static int bnxt_tc_put_tunnel_node(struct bnxt *bp, · 50 unmodified lines | ||
| 1088 | 1088 | rc = rhashtable_remove_fast(tunnel_table, &tunnel_node->node, |
| 1089 | 1089 | *ht_params); |
| 1090 | 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 | 1092 | rc = -1; |
| 1093 | 1093 | } |
| 1094 | 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 | 1129 | tunnel_node->refcount++; |
| 1130 | 1130 | return tunnel_node; |
| 1131 | 1131 | err: |
| 1132 | − netdev_info(bp->dev, "error rc=%d", rc); | |
| 1132 | + netdev_info(bp->dev, "error rc=%d\n", rc); | |
| 1133 | 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 | 1187 | &decap_l2_node->node, |
| 1188 | 1188 | tc_info->decap_l2_ht_params); |
| 1189 | 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 | 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 | 1228 | rt = ip_route_output_key(dev_net(real_dst_dev), &flow); |
| 1229 | 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 | 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 | 1242 | if (vlan->real_dev != real_dst_dev) { |
| 1243 | 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 | 1245 | netdev_name(dst_dev), |
| 1246 | 1246 | netdev_name(real_dst_dev)); |
| 1247 | 1247 | rc = -EOPNOTSUPP; |
| @@ -1253,7 +1253,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 5 unmodified lines | ||
| 1253 | 1253 | #endif |
| 1254 | 1254 | } else if (dst_dev != real_dst_dev) { |
| 1255 | 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 | 1257 | netdev_name(dst_dev), &flow.daddr, |
| 1258 | 1258 | netdev_name(real_dst_dev)); |
| 1259 | 1259 | rc = -EOPNOTSUPP; |
| @@ -1262,7 +1262,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp, · 2 unmodified lines | ||
| 1262 | 1262 | |
| 1263 | 1263 | nbr = dst_neigh_lookup(&rt->dst, &flow.daddr); |
| 1264 | 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 | 1266 | &flow.daddr); |
| 1267 | 1267 | rc = -EOPNOTSUPP; |
| 1268 | 1268 | goto put_rt; |
| @@ -1472,7 +1472,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp, · 203 unmodified lines | ||
| 1472 | 1472 | rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node, |
| 1473 | 1473 | tc_info->flow_ht_params); |
| 1474 | 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 | 1476 | __func__, rc); |
| 1477 | 1477 | |
| 1478 | 1478 | kfree_rcu(flow_node, rcu); |
| @@ -1587,7 +1587,7 @@ unlock: · 108 unmodified lines | ||
| 1587 | 1587 | free_node: |
| 1588 | 1588 | kfree_rcu(new_node, rcu); |
| 1589 | 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 | 1591 | __func__, tc_flow_cmd->cookie, rc); |
| 1592 | 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 | 1700 | le64_to_cpu(resp_bytes[i]); |
| 1701 | 1701 | } |
| 1702 | 1702 | } else { |
| 1703 | − netdev_info(bp->dev, "error rc=%d", rc); | |
| 1703 | + netdev_info(bp->dev, "error rc=%d\n", rc); | |
| 1704 | 1704 | } |
| 1705 | 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 | 1970 | bp); |
| 1971 | 1971 | if (rc) |
| 1972 | 1972 | netdev_info(bp->dev, |
| 1973 | − "Failed to register indirect blk: dev: %s", | |
| 1973 | + "Failed to register indirect blk: dev: %s\n", | |
| 1974 | 1974 | netdev->name); |
| 1975 | 1975 | break; |
| 1976 | 1976 | case NETDEV_UNREGISTER: |
| @@ -43,7 +43,7 @@ static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx, · 42 unmodified lines | ||
| 43 | 43 | netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x", |
| 44 | 44 | *tx_cfa_action, *rx_cfa_code); |
| 45 | 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 | 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 | 61 | rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); |
| 62 | 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 | 64 | return rc; |
| 65 | 65 | } |
| 66 | 66 | |
| @@ -465,7 +465,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp) · 398 unmodified lines | ||
| 465 | 465 | return 0; |
| 466 | 466 | |
| 467 | 467 | err: |
| 468 | − netdev_info(bp->dev, "%s error=%d", __func__, rc); | |
| 468 | + netdev_info(bp->dev, "%s error=%d\n", __func__, rc); | |
| 469 | 469 | kfree(cfa_code_map); |
| 470 | 470 | __bnxt_vf_reps_destroy(bp); |
| 471 | 471 | return rc; |
| @@ -488,7 +488,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode, · 16 unmodified lines | ||
| 488 | 488 | |
| 489 | 489 | mutex_lock(&bp->sriov_lock); |
| 490 | 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 | 492 | mode == DEVLINK_ESWITCH_MODE_LEGACY ? |
| 493 | 493 | "legacy" : "switchdev"); |
| 494 | 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 | 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 | 512 | rc = -EPERM; |
| 513 | 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 | 295 | if (priv->ext_phy) { |
| 296 | 296 | reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); |
| 297 | + reg &= ~ID_MODE_DIS; | |
| 297 | 298 | reg |= id_mode_dis; |
| 298 | 299 | if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) |
| 299 | 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 | 299 | hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
| 300 | + hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif); | |
| 300 | 301 | |
| 301 | 302 | hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT; |
| 302 | 303 | hw_ioctxt.cmdq_depth = 0; |
| @@ -151,8 +151,8 @@ struct hinic_cmd_hw_ioctxt { · 150 unmodified lines | ||
| 151 | 151 | |
| 152 | 152 | u8 lro_en; |
| 153 | 153 | u8 rsvd3; |
| 154 | + u8 ppf_idx; | |
| 154 | 155 | u8 rsvd4; |
| 155 | − u8 rsvd5; | |
| 156 | 156 | |
| 157 | 157 | u16 rq_depth; |
| 158 | 158 | u16 rx_buf_sz_idx; |
| @@ -137,6 +137,7 @@ · 136 unmodified lines | ||
| 137 | 137 | #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) |
| 138 | 138 | #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) |
| 139 | 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 | 142 | #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) |
| 142 | 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 | 95 | struct hinic_wq *wq; |
| 96 | 96 | |
| 97 | + struct cpumask affinity_mask; | |
| 97 | 98 | u32 irq; |
| 98 | 99 | u16 msix_entry; |
| 99 | 100 | |
| @@ -356,7 +356,8 @@ static void hinic_enable_rss(struct hinic_dev *nic_dev) · 355 unmodified lines | ||
| 356 | 356 | if (!num_cpus) |
| 357 | 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 | 362 | nic_dev->rss_limit = nic_dev->num_qps; |
| 362 | 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 | 475 | struct hinic_hwdev *hwdev = nic_dev->hwdev; |
| 476 | 476 | struct hinic_rq *rq = rxq->rq; |
| 477 | 477 | struct hinic_qp *qp; |
| 478 | − struct cpumask mask; | |
| 479 | 478 | int err; |
| 480 | 479 | |
| 481 | 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 | 493 | qp = container_of(rq, struct hinic_qp, rq); |
| 495 | − cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask); | |
| 496 | − return irq_set_affinity_hint(rq->irq, &mask); | |
| 494 | + cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask); | |
| 495 | + return irq_set_affinity_hint(rq->irq, &rq->affinity_mask); | |
| 497 | 496 | } |
| 498 | 497 | |
| 499 | 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 | 5148 | static void mlx5e_nic_disable(struct mlx5e_priv *priv) |
| 5149 | 5149 | { |
| 5150 | − struct net_device *netdev = priv->netdev; | |
| 5151 | 5150 | struct mlx5_core_dev *mdev = priv->mdev; |
| 5152 | 5151 | |
| 5153 | 5152 | #ifdef CONFIG_MLX5_CORE_EN_DCB |
| @@ -5168,7 +5167,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) · 14 unmodified lines | ||
| 5168 | 5167 | mlx5e_monitor_counter_cleanup(priv); |
| 5169 | 5168 | |
| 5170 | 5169 | mlx5e_disable_async_events(priv); |
| 5171 | − mlx5_lag_remove(mdev, netdev); | |
| 5170 | + mlx5_lag_remove(mdev); | |
| 5172 | 5171 | } |
| 5173 | 5172 | |
| 5174 | 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 | 1862 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) |
| 1863 | 1863 | { |
| 1864 | − struct net_device *netdev = priv->netdev; | |
| 1865 | 1864 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1866 | 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 | 1869 | #endif |
| 1871 | 1870 | mlx5_notifier_unregister(mdev, &priv->events_nb); |
| 1872 | 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 | 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 | 464 | struct mlx5_lag *ldev; |
| 465 | 465 | int changed = 0; |
| 466 | 466 | |
| 467 | − if (!net_eq(dev_net(ndev), &init_net)) | |
| 468 | − return NOTIFY_DONE; | |
| 469 | − | |
| 470 | 467 | if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE)) |
| 471 | 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 | 584 | if (!ldev->nb.notifier_call) { |
| 588 | 585 | ldev->nb.notifier_call = mlx5_lag_netdev_event; |
| 589 | − if (register_netdevice_notifier_dev_net(netdev, &ldev->nb, | |
| 590 | − &ldev->nn)) { | |
| 586 | + if (register_netdevice_notifier_net(&init_net, &ldev->nb)) { | |
| 591 | 587 | ldev->nb.notifier_call = NULL; |
| 592 | 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 | 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 | 601 | struct mlx5_lag *ldev; |
| 606 | 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 | 617 | if (i == MLX5_MAX_PORTS) { |
| 622 | 618 | if (ldev->nb.notifier_call) |
| 623 | − unregister_netdevice_notifier_dev_net(netdev, &ldev->nb, | |
| 624 | − &ldev->nn); | |
| 619 | + unregister_netdevice_notifier_net(&init_net, &ldev->nb); | |
| 625 | 620 | mlx5_lag_mp_cleanup(ldev); |
| 626 | 621 | cancel_delayed_work_sync(&ldev->bond_work); |
| 627 | 622 | mlx5_lag_dev_free(ldev); |
| @@ -44,7 +44,6 @@ struct mlx5_lag { · 43 unmodified lines | ||
| 44 | 44 | struct workqueue_struct *wq; |
| 45 | 45 | struct delayed_work bond_work; |
| 46 | 46 | struct notifier_block nb; |
| 47 | − struct netdev_net_notifier nn; | |
| 48 | 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 | 157 | u8 feature_group, u8 access_reg_group); |
| 158 | 158 | |
| 159 | 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 | 162 | int mlx5_irq_table_init(struct mlx5_core_dev *dev); |
| 163 | 163 | void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev); |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #define MLXSW_PCI_SW_RESET 0xF0010 |
| 29 | 29 | #define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) |
| 30 | 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 | 32 | #define MLXSW_PCI_FW_READY 0xA1844 |
| 33 | 33 | #define MLXSW_PCI_FW_READY_MASK 0xFFFF |
| 34 | 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 | 514 | struct net_device *netdev = pw; |
| 515 | 515 | struct ks_net *ks = netdev_priv(netdev); |
| 516 | + unsigned long flags; | |
| 516 | 517 | u16 status; |
| 517 | 518 | |
| 519 | + spin_lock_irqsave(&ks->statelock, flags); | |
| 518 | 520 | /*this should be the first in IRQ handler */ |
| 519 | 521 | ks_save_cmd_reg(ks); |
| 520 | 522 | |
| 521 | 523 | status = ks_rdreg16(ks, KS_ISR); |
| 522 | 524 | if (unlikely(!status)) { |
| 523 | 525 | ks_restore_cmd_reg(ks); |
| 526 | + spin_unlock_irqrestore(&ks->statelock, flags); | |
| 524 | 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 | 549 | ks->netdev->stats.rx_over_errors++; |
| 547 | 550 | /* this should be the last in IRQ handler*/ |
| 548 | 551 | ks_restore_cmd_reg(ks); |
| 552 | + spin_unlock_irqrestore(&ks->statelock, flags); | |
| 549 | 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 | 620 | /* shutdown RX/TX QMU */ |
| 617 | 621 | ks_disable_qmu(ks); |
| 622 | + ks_disable_int(ks); | |
| 618 | 623 | |
| 619 | 624 | /* set powermode to soft power down to save power */ |
| 620 | 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 | 677 | netdev_tx_t retv = NETDEV_TX_OK; |
| 673 | 678 | struct ks_net *ks = netdev_priv(netdev); |
| 679 | + unsigned long flags; | |
| 674 | 680 | |
| 675 | − disable_irq(netdev->irq); | |
| 676 | − ks_disable_int(ks); | |
| 677 | − spin_lock(&ks->statelock); | |
| 681 | + spin_lock_irqsave(&ks->statelock, flags); | |
| 678 | 682 | |
| 679 | 683 | /* Extra space are required: |
| 680 | 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 | 692 | dev_kfree_skb(skb); |
| 689 | 693 | } else |
| 690 | 694 | retv = NETDEV_TX_BUSY; |
| 691 | − spin_unlock(&ks->statelock); | |
| 692 | − ks_enable_int(ks); | |
| 693 | − enable_irq(netdev->irq); | |
| 695 | + spin_unlock_irqrestore(&ks->statelock, flags); | |
| 694 | 696 | return retv; |
| 695 | 697 | } |
| 696 | 698 | |
| @@ -13,25 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "rmnet_vnd.h" |
| 14 | 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 | 16 | /* Local Definitions and Declarations */ |
| 36 | 17 | |
| 37 | 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 | 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, | |
| 55 | − struct rmnet_port *port) | |
| 35 | +static int rmnet_unregister_real_device(struct net_device *real_dev) | |
| 56 | 36 | { |
| 37 | + struct rmnet_port *port = rmnet_get_port_rtnl(real_dev); | |
| 38 | + | |
| 57 | 39 | if (port->nr_rmnet_devs) |
| 58 | 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 | 44 | kfree(port); |
| 63 | 45 | |
| 64 | − /* release reference on real_dev */ | |
| 65 | − dev_put(real_dev); | |
| 66 | − | |
| 67 | 46 | netdev_dbg(real_dev, "Removed from rmnet\n"); |
| 68 | 47 | return 0; |
| 69 | 48 | } |
| @@ -89,9 +68,6 @@ static int rmnet_register_real_device(struct net_device *real_dev) · 19 unmodified lines | ||
| 89 | 68 | return -EBUSY; |
| 90 | 69 | } |
| 91 | 70 | |
| 92 | − /* hold on to real dev for MAP data */ | |
| 93 | − dev_hold(real_dev); | |
| 94 | − | |
| 95 | 71 | for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++) |
| 96 | 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 | 75 | return 0; |
| 100 | 76 | } |
| 101 | 77 | |
| 102 | −static void rmnet_unregister_bridge(struct net_device *dev, | |
| 103 | − struct rmnet_port *port) | |
| 78 | +static void rmnet_unregister_bridge(struct rmnet_port *port) | |
| 104 | 79 | { |
| 105 | − struct rmnet_port *bridge_port; | |
| 106 | − struct net_device *bridge_dev; | |
| 80 | + struct net_device *bridge_dev, *real_dev, *rmnet_dev; | |
| 81 | + struct rmnet_port *real_port; | |
| 107 | 82 | |
| 108 | 83 | if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) |
| 109 | 84 | return; |
| 110 | 85 | |
| 111 | − /* bridge slave handling */ | |
| 86 | + rmnet_dev = port->rmnet_dev; | |
| 112 | 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); | |
| 116 | − bridge_port->bridge_ep = NULL; | |
| 117 | − bridge_port->rmnet_mode = RMNET_EPMODE_VND; | |
| 92 | + real_port = rmnet_get_port_rtnl(real_dev); | |
| 93 | + real_port->bridge_ep = NULL; | |
| 94 | + real_port->rmnet_mode = RMNET_EPMODE_VND; | |
| 118 | 95 | } else { |
| 96 | + /* real device */ | |
| 119 | 97 | bridge_dev = port->bridge_ep; |
| 120 | 98 | |
| 121 | − bridge_port = rmnet_get_port_rtnl(bridge_dev); | |
| 122 | − rmnet_unregister_real_device(bridge_dev, bridge_port); | |
| 99 | + port->bridge_ep = NULL; | |
| 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 | 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 | 116 | int err = 0; |
| 136 | 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 | 124 | real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); |
| 139 | 125 | if (!real_dev || !dev) |
| 140 | 126 | return -ENODEV; |
| @@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, · 16 unmodified lines | ||
| 157 | 143 | if (err) |
| 158 | 144 | goto err1; |
| 159 | 145 | |
| 146 | + err = netdev_upper_dev_link(real_dev, dev, extack); | |
| 147 | + if (err < 0) | |
| 148 | + goto err2; | |
| 149 | + | |
| 160 | 150 | port->rmnet_mode = mode; |
| 151 | + port->rmnet_dev = dev; | |
| 161 | 152 | |
| 162 | 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 | 165 | return 0; |
| 175 | 166 | |
| 167 | +err2: | |
| 168 | + unregister_netdevice(dev); | |
| 169 | + rmnet_vnd_dellink(mux_id, port, ep); | |
| 176 | 170 | err1: |
| 177 | − rmnet_unregister_real_device(real_dev, port); | |
| 171 | + rmnet_unregister_real_device(real_dev); | |
| 178 | 172 | err0: |
| 179 | 173 | kfree(ep); |
| 180 | 174 | return err; |
| @@ -183,77 +177,74 @@ err0: · 2 unmodified lines | ||
| 183 | 177 | static void rmnet_dellink(struct net_device *dev, struct list_head *head) |
| 184 | 178 | { |
| 185 | 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 | 182 | struct rmnet_endpoint *ep; |
| 188 | − struct rmnet_port *port; | |
| 189 | − u8 mux_id; | |
| 183 | + u8 mux_id = priv->mux_id; | |
| 190 | 184 | |
| 191 | 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 | 188 | return; |
| 195 | 189 | |
| 196 | − port = rmnet_get_port_rtnl(real_dev); | |
| 197 | − | |
| 198 | − mux_id = rmnet_vnd_get_mux(dev); | |
| 190 | + real_port = rmnet_get_port_rtnl(real_dev); | |
| 191 | + bridge_dev = real_port->bridge_ep; | |
| 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 | 198 | if (ep) { |
| 202 | 199 | hlist_del_init_rcu(&ep->hlnode); |
| 203 | − rmnet_unregister_bridge(dev, port); | |
| 204 | − rmnet_vnd_dellink(mux_id, port, ep); | |
| 200 | + rmnet_vnd_dellink(mux_id, real_port, ep); | |
| 205 | 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 | 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 | 211 | struct hlist_node *tmp_ep; |
| 216 | 212 | struct rmnet_endpoint *ep; |
| 217 | 213 | struct rmnet_port *port; |
| 218 | 214 | unsigned long bkt_ep; |
| 219 | 215 | LIST_HEAD(list); |
| 220 | 216 | |
| 221 | − if (!rmnet_is_real_dev_registered(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); | |
| 217 | + port = rmnet_get_port_rtnl(real_dev); | |
| 234 | 218 | |
| 235 | − hlist_del_init_rcu(&ep->hlnode); | |
| 236 | − kfree(ep); | |
| 219 | + if (port->nr_rmnet_devs) { | |
| 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 | 236 | static int rmnet_config_notify_cb(struct notifier_block *nb, |
| 246 | 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 | 242 | return NOTIFY_DONE; |
| 252 | 243 | |
| 253 | 244 | switch (event) { |
| 254 | 245 | case NETDEV_UNREGISTER: |
| 255 | − netdev_dbg(dev, "Kernel unregister\n"); | |
| 256 | − rmnet_force_unassociate_device(dev); | |
| 246 | + netdev_dbg(real_dev, "Kernel unregister\n"); | |
| 247 | + rmnet_force_unassociate_device(real_dev); | |
| 257 | 248 | break; |
| 258 | 249 | |
| 259 | 250 | default: |
| @@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[], · 35 unmodified lines | ||
| 295 | 286 | if (!dev) |
| 296 | 287 | return -ENODEV; |
| 297 | 288 | |
| 298 | − real_dev = __dev_get_by_index(dev_net(dev), | |
| 299 | − nla_get_u32(tb[IFLA_LINK])); | |
| 300 | − | |
| 301 | − if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) | |
| 289 | + real_dev = priv->real_dev; | |
| 290 | + if (!rmnet_is_real_dev_registered(real_dev)) | |
| 302 | 291 | return -ENODEV; |
| 303 | 292 | |
| 304 | 293 | port = rmnet_get_port_rtnl(real_dev); |
| 305 | 294 | |
| 306 | 295 | if (data[IFLA_RMNET_MUX_ID]) { |
| 307 | 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 | 301 | ep = rmnet_get_endpoint(port, priv->mux_id); |
| 309 | 302 | if (!ep) |
| 310 | 303 | return -ENODEV; |
| @@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = { · 68 unmodified lines | ||
| 379 | 372 | .fill_info = rmnet_fill_info, |
| 380 | 373 | }; |
| 381 | 374 | |
| 382 | −/* Needs either rcu_read_lock() or rtnl lock */ | |
| 383 | −struct rmnet_port *rmnet_get_port(struct net_device *real_dev) | |
| 375 | +struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev) | |
| 384 | 376 | { |
| 385 | 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 | 379 | else |
| 388 | 380 | return NULL; |
| 389 | 381 | } |
| @@ -409,7 +401,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 19 unmodified lines | ||
| 409 | 401 | struct rmnet_port *port, *slave_port; |
| 410 | 402 | int err; |
| 411 | 403 | |
| 412 | − port = rmnet_get_port(real_dev); | |
| 404 | + port = rmnet_get_port_rtnl(real_dev); | |
| 413 | 405 | |
| 414 | 406 | /* If there is more than one rmnet dev attached, its probably being |
| 415 | 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 | 409 | if (port->nr_rmnet_devs > 1) |
| 418 | 410 | return -EINVAL; |
| 419 | 411 | |
| 412 | + if (port->rmnet_mode != RMNET_EPMODE_VND) | |
| 413 | + return -EINVAL; | |
| 414 | + | |
| 420 | 415 | if (rmnet_is_real_dev_registered(slave_dev)) |
| 421 | 416 | return -EBUSY; |
| 422 | 417 | |
| @@ -424,9 +419,17 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 1 unmodified line | ||
| 424 | 419 | if (err) |
| 425 | 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 | 430 | slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; |
| 429 | 431 | slave_port->bridge_ep = real_dev; |
| 432 | + slave_port->rmnet_dev = rmnet_dev; | |
| 430 | 433 | |
| 431 | 434 | port->rmnet_mode = RMNET_EPMODE_BRIDGE; |
| 432 | 435 | port->bridge_ep = slave_dev; |
| @@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, · 5 unmodified lines | ||
| 438 | 441 | int rmnet_del_bridge(struct net_device *rmnet_dev, |
| 439 | 442 | struct net_device *slave_dev) |
| 440 | 443 | { |
| 441 | − struct rmnet_priv *priv = netdev_priv(rmnet_dev); | |
| 442 | − struct net_device *real_dev = priv->real_dev; | |
| 443 | − struct rmnet_port *port, *slave_port; | |
| 444 | + struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev); | |
| 444 | 445 | |
| 445 | − port = rmnet_get_port(real_dev); | |
| 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); | |
| 446 | + rmnet_unregister_bridge(port); | |
| 451 | 447 | |
| 452 | 448 | netdev_dbg(slave_dev, "removed from rmnet as slave\n"); |
| 453 | 449 | return 0; |
| @@ -473,8 +469,8 @@ static int __init rmnet_init(void) · 19 unmodified lines | ||
| 473 | 469 | |
| 474 | 470 | static void __exit rmnet_exit(void) |
| 475 | 471 | { |
| 476 | − unregister_netdevice_notifier(&rmnet_dev_notifier); | |
| 477 | 472 | rtnl_link_unregister(&rmnet_link_ops); |
| 473 | + unregister_netdevice_notifier(&rmnet_dev_notifier); | |
| 478 | 474 | } |
| 479 | 475 | |
| 480 | 476 | module_init(rmnet_init) |
| @@ -28,6 +28,7 @@ struct rmnet_port { · 27 unmodified lines | ||
| 28 | 28 | u8 rmnet_mode; |
| 29 | 29 | struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; |
| 30 | 30 | struct net_device *bridge_ep; |
| 31 | + struct net_device *rmnet_dev; | |
| 31 | 32 | }; |
| 32 | 33 | |
| 33 | 34 | extern struct rtnl_link_ops rmnet_link_ops; |
| @@ -65,7 +66,7 @@ struct rmnet_priv { · 31 unmodified lines | ||
| 65 | 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 | 70 | struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); |
| 70 | 71 | int rmnet_add_bridge(struct net_device *rmnet_dev, |
| 71 | 72 | struct net_device *slave_dev, |
| @@ -159,6 +159,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, · 158 unmodified lines | ||
| 159 | 159 | static void |
| 160 | 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 | 165 | if (bridge_dev) { |
| 163 | 166 | skb->dev = bridge_dev; |
| 164 | 167 | dev_queue_xmit(skb); |
| @@ -184,7 +187,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) · 19 unmodified lines | ||
| 184 | 187 | return RX_HANDLER_PASS; |
| 185 | 188 | |
| 186 | 189 | dev = skb->dev; |
| 187 | − port = rmnet_get_port(dev); | |
| 190 | + port = rmnet_get_port_rcu(dev); | |
| 188 | 191 | |
| 189 | 192 | switch (port->rmnet_mode) { |
| 190 | 193 | case RMNET_EPMODE_VND: |
| @@ -217,7 +220,7 @@ void rmnet_egress_handler(struct sk_buff *skb) · 26 unmodified lines | ||
| 217 | 220 | skb->dev = priv->real_dev; |
| 218 | 221 | mux_id = priv->mux_id; |
| 219 | 222 | |
| 220 | − port = rmnet_get_port(skb->dev); | |
| 223 | + port = rmnet_get_port_rcu(skb->dev); | |
| 221 | 224 | if (!port) |
| 222 | 225 | goto drop; |
| 223 | 226 | |
| @@ -266,14 +266,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, · 265 unmodified lines | ||
| 266 | 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 | 269 | int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) |
| 278 | 270 | { |
| 279 | 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 | 16 | struct rmnet_endpoint *ep); |
| 17 | 17 | void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); |
| 18 | 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 | 19 | void rmnet_vnd_setup(struct net_device *dev); |
| 21 | 20 | #endif /* _RMNET_VND_H_ */ |
| @@ -560,13 +560,45 @@ efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx, · 559 unmodified lines | ||
| 560 | 560 | u32 nic_major, u32 nic_minor, |
| 561 | 561 | s32 correction) |
| 562 | 562 | { |
| 563 | + u32 sync_timestamp; | |
| 563 | 564 | ktime_t kt = { 0 }; |
| 565 | + s16 delta; | |
| 564 | 566 | |
| 565 | 567 | if (!(nic_major & 0x80000000)) { |
| 566 | 568 | WARN_ON_ONCE(nic_major >> 16); |
| 567 | − /* Use the top bits from the latest sync event. */ | |
| 568 | − nic_major &= 0xffff; | |
| 569 | − nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000); | |
| 569 | + | |
| 570 | + /* Medford provides 48 bits of timestamp, so we must get the top | |
| 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 | 603 | kt = ptp->nic_to_kernel_time(nic_major, nic_minor, |
| 572 | 604 | correction); |
| @@ -4405,6 +4405,8 @@ static void stmmac_init_fs(struct net_device *dev) · 4404 unmodified lines | ||
| 4405 | 4405 | { |
| 4406 | 4406 | struct stmmac_priv *priv = netdev_priv(dev); |
| 4407 | 4407 | |
| 4408 | + rtnl_lock(); | |
| 4409 | + | |
| 4408 | 4410 | /* Create per netdev entries */ |
| 4409 | 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 | 4418 | debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev, |
| 4417 | 4419 | &stmmac_dma_cap_fops); |
| 4418 | 4420 | |
| 4419 | − register_netdevice_notifier(&stmmac_notifier); | |
| 4421 | + rtnl_unlock(); | |
| 4420 | 4422 | } |
| 4421 | 4423 | |
| 4422 | 4424 | static void stmmac_exit_fs(struct net_device *dev) |
| 4423 | 4425 | { |
| 4424 | 4426 | struct stmmac_priv *priv = netdev_priv(dev); |
| 4425 | 4427 | |
| 4426 | − unregister_netdevice_notifier(&stmmac_notifier); | |
| 4427 | 4428 | debugfs_remove_recursive(priv->dbgfs_dir); |
| 4428 | 4429 | } |
| 4429 | 4430 | #endif /* CONFIG_DEBUG_FS */ |
| @@ -4940,14 +4941,14 @@ int stmmac_dvr_remove(struct device *dev) · 510 unmodified lines | ||
| 4940 | 4941 | |
| 4941 | 4942 | netdev_info(priv->dev, "%s: removing driver", __func__); |
| 4942 | 4943 | |
| 4943 | −#ifdef CONFIG_DEBUG_FS | |
| 4944 | − stmmac_exit_fs(ndev); | |
| 4945 | −#endif | |
| 4946 | 4944 | stmmac_stop_all_dma(priv); |
| 4947 | 4945 | |
| 4948 | 4946 | stmmac_mac_set(priv, priv->ioaddr, false); |
| 4949 | 4947 | netif_carrier_off(ndev); |
| 4950 | 4948 | unregister_netdev(ndev); |
| 4949 | +#ifdef CONFIG_DEBUG_FS | |
| 4950 | + stmmac_exit_fs(ndev); | |
| 4951 | +#endif | |
| 4951 | 4952 | phylink_destroy(priv->phylink); |
| 4952 | 4953 | if (priv->plat->stmmac_rst) |
| 4953 | 4954 | reset_control_assert(priv->plat->stmmac_rst); |
| @@ -5166,6 +5167,7 @@ static int __init stmmac_init(void) · 212 unmodified lines | ||
| 5166 | 5167 | /* Create debugfs main directory if it doesn't exist yet */ |
| 5167 | 5168 | if (!stmmac_fs_dir) |
| 5168 | 5169 | stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); |
| 5170 | + register_netdevice_notifier(&stmmac_notifier); | |
| 5169 | 5171 | #endif |
| 5170 | 5172 | |
| 5171 | 5173 | return 0; |
| @@ -5174,6 +5176,7 @@ static int __init stmmac_init(void) · 2 unmodified lines | ||
| 5174 | 5176 | static void __exit stmmac_exit(void) |
| 5175 | 5177 | { |
| 5176 | 5178 | #ifdef CONFIG_DEBUG_FS |
| 5179 | + unregister_netdevice_notifier(&stmmac_notifier); | |
| 5177 | 5180 | debugfs_remove_recursive(stmmac_fs_dir); |
| 5178 | 5181 | #endif |
| 5179 | 5182 | } |
| @@ -375,10 +375,14 @@ struct temac_local { · 374 unmodified lines | ||
| 375 | 375 | int tx_bd_next; |
| 376 | 376 | int tx_bd_tail; |
| 377 | 377 | int rx_bd_ci; |
| 378 | + int rx_bd_tail; | |
| 378 | 379 | |
| 379 | 380 | /* DMA channel control setup */ |
| 380 | 381 | u32 tx_chnl_ctrl; |
| 381 | 382 | u32 rx_chnl_ctrl; |
| 383 | + u8 coalesce_count_rx; | |
| 384 | + | |
| 385 | + struct delayed_work restart_work; | |
| 382 | 386 | }; |
| 383 | 387 | |
| 384 | 388 | /* Wrappers for temac_ior()/temac_iow() function pointers above */ |
| @@ -51,6 +51,7 @@ · 50 unmodified lines | ||
| 51 | 51 | #include <linux/ip.h> |
| 52 | 52 | #include <linux/slab.h> |
| 53 | 53 | #include <linux/interrupt.h> |
| 54 | +#include <linux/workqueue.h> | |
| 54 | 55 | #include <linux/dma-mapping.h> |
| 55 | 56 | #include <linux/processor.h> |
| 56 | 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 | 368 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, |
| 368 | 369 | XTE_MAX_JUMBO_FRAME_SIZE, |
| 369 | 370 | DMA_FROM_DEVICE); |
| 371 | + if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) | |
| 372 | + goto out; | |
| 370 | 373 | lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr); |
| 371 | 374 | lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); |
| 372 | 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 | 390 | lp->tx_bd_next = 0; |
| 388 | 391 | lp->tx_bd_tail = 0; |
| 389 | 392 | lp->rx_bd_ci = 0; |
| 393 | + lp->rx_bd_tail = RX_BD_NUM - 1; | |
| 390 | 394 | |
| 391 | 395 | /* Enable RX DMA transfers */ |
| 392 | 396 | wmb(); |
| 393 | 397 | lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p); |
| 394 | 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 | 401 | /* Prepare for TX DMA transfer */ |
| 398 | 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 | 792 | stat = be32_to_cpu(cur_p->app0); |
| 789 | 793 | } |
| 790 | 794 | |
| 795 | + /* Matches barrier in temac_start_xmit */ | |
| 796 | + smp_mb(); | |
| 797 | + | |
| 791 | 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 | 837 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; |
| 831 | 838 | |
| 832 | 839 | if (temac_check_tx_bd_space(lp, num_frag + 1)) { |
| 833 | − if (!netif_queue_stopped(ndev)) | |
| 834 | − netif_stop_queue(ndev); | |
| 835 | − return NETDEV_TX_BUSY; | |
| 840 | + if (netif_queue_stopped(ndev)) | |
| 841 | + 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 | 855 | cur_p->app0 = 0; |
| @@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 11 unmodified lines | ||
| 850 | 867 | skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, |
| 851 | 868 | skb_headlen(skb), DMA_TO_DEVICE); |
| 852 | 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 | 875 | cur_p->phys = cpu_to_be32(skb_dma_addr); |
| 854 | 876 | ptr_to_txbd((void *)skb, cur_p); |
| 855 | 877 | |
| 856 | 878 | for (ii = 0; ii < num_frag; ii++) { |
| 857 | − lp->tx_bd_tail++; | |
| 858 | − if (lp->tx_bd_tail >= TX_BD_NUM) | |
| 879 | + if (++lp->tx_bd_tail >= TX_BD_NUM) | |
| 859 | 880 | lp->tx_bd_tail = 0; |
| 860 | 881 | |
| 861 | 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 | 884 | skb_frag_address(frag), |
| 864 | 885 | skb_frag_size(frag), |
| 865 | 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 | 908 | cur_p->phys = cpu_to_be32(skb_dma_addr); |
| 867 | 909 | cur_p->len = cpu_to_be32(skb_frag_size(frag)); |
| 868 | 910 | cur_p->app0 = 0; |
| @@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 15 unmodified lines | ||
| 884 | 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 | 941 | static void ll_temac_recv(struct net_device *ndev) |
| 889 | 942 | { |
| 890 | 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 | 944 | unsigned long flags; |
| 945 | + int rx_bd; | |
| 946 | + bool update_tail = false; | |
| 897 | 947 | |
| 898 | 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; | |
| 901 | − cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; | |
| 902 | − | |
| 903 | − bdstat = be32_to_cpu(cur_p->app0); | |
| 904 | − while ((bdstat & STS_CTRL_APP0_CMPLT)) { | |
| 950 | + /* Process all received buffers, passing them on network | |
| 951 | + * stack. After this, the buffer descriptors will be in an | |
| 952 | + * un-allocated stage, where no skb is allocated for it, and | |
| 953 | + * they are therefore not available for TEMAC/DMA. | |
| 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]; | |
| 907 | − length = be32_to_cpu(cur_p->app4) & 0x3FFF; | |
| 968 | + /* Loop over all completed buffer descriptors */ | |
| 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 | 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 | 979 | skb_put(skb, length); |
| 913 | 980 | skb->protocol = eth_type_trans(skb, ndev); |
| 914 | 981 | skb_checksum_none_assert(skb); |
| @@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev) · 8 unmodified lines | ||
| 923 | 990 | * (back) for proper IP checksum byte order |
| 924 | 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 | 994 | skb->ip_summed = CHECKSUM_COMPLETE; |
| 928 | 995 | } |
| 929 | 996 | |
| 930 | 997 | if (!skb_defer_rx_timestamp(skb)) |
| 931 | 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 | 1002 | ndev->stats.rx_packets++; |
| 934 | 1003 | ndev->stats.rx_bytes += length; |
| 935 | 1004 | |
| 936 | − new_skb = netdev_alloc_skb_ip_align(ndev, | |
| 937 | − XTE_MAX_JUMBO_FRAME_SIZE); | |
| 938 | − if (!new_skb) { | |
| 939 | − spin_unlock_irqrestore(&lp->rx_lock, flags); | |
| 940 | − return; | |
| 1005 | + rx_bd = lp->rx_bd_ci; | |
| 1006 | + if (++lp->rx_bd_ci >= RX_BD_NUM) | |
| 1007 | + lp->rx_bd_ci = 0; | |
| 1008 | + } while (rx_bd != lp->rx_bd_tail); | |
| 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); | |
| 944 | − skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data, | |
| 1050 | + skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, | |
| 945 | 1051 | XTE_MAX_JUMBO_FRAME_SIZE, |
| 946 | 1052 | DMA_FROM_DEVICE); |
| 947 | − cur_p->phys = cpu_to_be32(skb_dma_addr); | |
| 948 | − cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); | |
| 949 | − lp->rx_skb[lp->rx_bd_ci] = new_skb; | |
| 1053 | + if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, | |
| 1054 | + skb_dma_addr))) { | |
| 1055 | + dev_kfree_skb_any(skb); | |
| 1056 | + break; | |
| 1057 | + } | |
| 950 | 1058 | |
| 951 | − lp->rx_bd_ci++; | |
| 952 | − if (lp->rx_bd_ci >= RX_BD_NUM) | |
| 953 | − lp->rx_bd_ci = 0; | |
| 1059 | + bd->phys = cpu_to_be32(skb_dma_addr); | |
| 1060 | + bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); | |
| 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]; | |
| 956 | − bdstat = be32_to_cpu(cur_p->app0); | |
| 1064 | + lp->rx_bd_tail = rx_bd; | |
| 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 | 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 | 1089 | static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) |
| 964 | 1090 | { |
| 965 | 1091 | struct net_device *ndev = _ndev; |
| @@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev) · 86 unmodified lines | ||
| 1052 | 1178 | |
| 1053 | 1179 | dev_dbg(&ndev->dev, "temac_close()\n"); |
| 1054 | 1180 | |
| 1181 | + cancel_delayed_work_sync(&lp->restart_work); | |
| 1182 | + | |
| 1055 | 1183 | free_irq(lp->tx_irq, ndev); |
| 1056 | 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 | 1301 | lp->dev = &pdev->dev; |
| 1174 | 1302 | lp->options = XTE_OPTION_DEFAULTS; |
| 1175 | 1303 | spin_lock_init(&lp->rx_lock); |
| 1304 | + INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func); | |
| 1176 | 1305 | |
| 1177 | 1306 | /* Setup mutex for synchronization of indirect register access */ |
| 1178 | 1307 | if (pdata) { |
| @@ -1279,6 +1408,7 @@ static int temac_probe(struct platform_device *pdev) · 100 unmodified lines | ||
| 1279 | 1408 | */ |
| 1280 | 1409 | lp->tx_chnl_ctrl = 0x10220000; |
| 1281 | 1410 | lp->rx_chnl_ctrl = 0xff070000; |
| 1411 | + lp->coalesce_count_rx = 0x07; | |
| 1282 | 1412 | |
| 1283 | 1413 | /* Finished with the DMA node; drop the reference */ |
| 1284 | 1414 | of_node_put(dma_np); |
| @@ -1310,11 +1440,14 @@ static int temac_probe(struct platform_device *pdev) · 25 unmodified lines | ||
| 1310 | 1440 | (pdata->tx_irq_count << 16); |
| 1311 | 1441 | else |
| 1312 | 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 | 1444 | lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) | |
| 1315 | 1445 | (pdata->rx_irq_count << 16); |
| 1316 | − else | |
| 1446 | + lp->coalesce_count_rx = pdata->rx_irq_count; | |
| 1447 | + } else { | |
| 1317 | 1448 | lp->rx_chnl_ctrl = 0xff070000; |
| 1449 | + lp->coalesce_count_rx = 0x07; | |
| 1450 | + } | |
| 1318 | 1451 | } |
| 1319 | 1452 | |
| 1320 | 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 | 100 | init_waitqueue_head(&net_device->wait_drain); |
| 101 | 101 | net_device->destroy = false; |
| 102 | − net_device->tx_disable = false; | |
| 102 | + net_device->tx_disable = true; | |
| 103 | 103 | |
| 104 | 104 | net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; |
| 105 | 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 | 1070 | /* In any case device is now ready */ |
| 1071 | + nvdev->tx_disable = false; | |
| 1071 | 1072 | netif_device_attach(ndev); |
| 1072 | 1073 | |
| 1073 | 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 | 2477 | else |
| 2477 | 2478 | net->max_mtu = ETH_DATA_LEN; |
| 2478 | 2479 | |
| 2480 | + nvdev->tx_disable = false; | |
| 2481 | + | |
| 2479 | 2482 | ret = register_netdevice(net); |
| 2480 | 2483 | if (ret != 0) { |
| 2481 | 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 | 1312 | if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) |
| 1310 | 1313 | phydev->duplex = DUPLEX_FULL; |
| 1311 | 1314 | else |
| @@ -1365,6 +1368,8 @@ static int marvell_read_status_page(struct phy_device *phydev, int page) · 53 unmodified lines | ||
| 1365 | 1368 | linkmode_zero(phydev->lp_advertising); |
| 1366 | 1369 | phydev->pause = 0; |
| 1367 | 1370 | phydev->asym_pause = 0; |
| 1371 | + phydev->speed = SPEED_UNKNOWN; | |
| 1372 | + phydev->duplex = DUPLEX_UNKNOWN; | |
| 1368 | 1373 | |
| 1369 | 1374 | if (phydev->autoneg == AUTONEG_ENABLE) |
| 1370 | 1375 | err = marvell_read_status_page_an(phydev, fiber, status); |
| @@ -345,11 +345,11 @@ enum macsec_bank { · 344 unmodified lines | ||
| 345 | 345 | BIT(VSC8531_FORCE_LED_OFF) | \ |
| 346 | 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 | 349 | #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800 |
| 350 | 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 | 353 | #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000 |
| 354 | 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 | 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 | 172 | if (!restart) { |
| 173 | 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 | 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 | 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 | 247 | * MDIO bus driver and clock gated at this point. |
| 248 | 248 | */ |
| 249 | 249 | if (!netdev) |
| 250 | − return !phydev->suspended; | |
| 250 | + goto out; | |
| 251 | 251 | |
| 252 | 252 | if (netdev->wol_enabled) |
| 253 | 253 | return false; |
| @@ -267,7 +267,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) · 13 unmodified lines | ||
| 267 | 267 | if (device_may_wakeup(&netdev->dev)) |
| 268 | 268 | return false; |
| 269 | 269 | |
| 270 | − return true; | |
| 270 | +out: | |
| 271 | + return !phydev->suspended; | |
| 271 | 272 | } |
| 272 | 273 | |
| 273 | 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 | 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 | 1798 | if (!restart) { |
| 1798 | 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 | 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 | 1815 | EXPORT_SYMBOL(genphy_check_and_restart_aneg); |
| 1815 | 1816 | |
| @@ -863,7 +863,10 @@ err_free_chan: · 862 unmodified lines | ||
| 863 | 863 | tty->disc_data = NULL; |
| 864 | 864 | clear_bit(SLF_INUSE, &sl->flags); |
| 865 | 865 | sl_free_netdev(sl->dev); |
| 866 | + /* do not call free_netdev before rtnl_unlock */ | |
| 867 | + rtnl_unlock(); | |
| 866 | 868 | free_netdev(sl->dev); |
| 869 | + return err; | |
| 867 | 870 | |
| 868 | 871 | err_exit: |
| 869 | 872 | rtnl_unlock(); |
| @@ -337,6 +337,9 @@ static void qmi_wwan_netdev_setup(struct net_device *net) · 336 unmodified lines | ||
| 337 | 337 | netdev_dbg(net, "mode: raw IP\n"); |
| 338 | 338 | } else if (!net->header_ops) { /* don't bother if already set */ |
| 339 | 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 | 343 | clear_bit(EVENT_NO_IP_ALIGN, &dev->flags); |
| 341 | 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 | 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 | 1417 | int r; |
| 1422 | 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 | 1426 | goto err; |
| 1431 | 1427 | } |
| 1432 | 1428 | |
| 1433 | − r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, 0); | |
| 1434 | − if (r < 0) | |
| 1435 | − goto err; | |
| 1436 | − | |
| 1437 | − if (uaddr.sa.sll_family != AF_PACKET) { | |
| 1429 | + if (sock->sk->sk_family != AF_PACKET) { | |
| 1438 | 1430 | r = -EPFNOSUPPORT; |
| 1439 | 1431 | goto err; |
| 1440 | 1432 | } |
| @@ -22,19 +22,23 @@ extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); · 21 unmodified lines | ||
| 22 | 22 | int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, |
| 23 | 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 | 31 | #else |
| 26 | 32 | |
| 27 | 33 | static inline void icmpv6_send(struct sk_buff *skb, |
| 28 | 34 | u8 type, u8 code, __u32 info) |
| 29 | 35 | { |
| 30 | − | |
| 31 | 36 | } |
| 32 | −#endif | |
| 33 | 37 | |
| 34 | −#if IS_ENABLED(CONFIG_NF_NAT) | |
| 35 | −void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); | |
| 36 | −#else | |
| 37 | −#define icmpv6_ndo_send icmpv6_send | |
| 38 | +static inline void icmpv6_ndo_send(struct sk_buff *skb, | |
| 39 | + u8 type, u8 code, __u32 info) | |
| 40 | +{ | |
| 41 | +} | |
| 38 | 42 | #endif |
| 39 | 43 | |
| 40 | 44 | extern int icmpv6_init(void); |
| @@ -121,6 +121,7 @@ struct ip_set_ext { · 120 unmodified lines | ||
| 121 | 121 | u32 timeout; |
| 122 | 122 | u8 packets_op; |
| 123 | 123 | u8 bytes_op; |
| 124 | + bool target; | |
| 124 | 125 | }; |
| 125 | 126 | |
| 126 | 127 | struct ip_set; |
| @@ -187,6 +188,14 @@ struct ip_set_type_variant { · 60 unmodified lines | ||
| 187 | 188 | /* Return true if "b" set is the same as "a" |
| 188 | 189 | * according to the create set parameters */ |
| 189 | 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 | 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 | 512 | #define IP_SET_INIT_KEXT(skb, opt, set) \ |
| 504 | − { .bytes = (skb)->len, .packets = 1, \ | |
| 513 | + { .bytes = (skb)->len, .packets = 1, .target = true,\ | |
| 505 | 514 | .timeout = ip_set_adt_opt_timeout(opt, set) } |
| 506 | 515 | |
| 507 | 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 | 34 | const struct nf_br_ops *nf_ops; |
| 35 | 35 | u8 state = BR_STATE_FORWARDING; |
| 36 | 36 | const unsigned char *dest; |
| 37 | − struct ethhdr *eth; | |
| 38 | 37 | u16 vid = 0; |
| 39 | 38 | |
| 40 | 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 | 53 | BR_INPUT_SKB_CB(skb)->frag_max_size = 0; |
| 55 | 54 | |
| 56 | 55 | skb_reset_mac_header(skb); |
| 57 | − eth = eth_hdr(skb); | |
| 58 | 56 | skb_pull(skb, ETH_HLEN); |
| 59 | 57 | |
| 60 | 58 | if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid, &state)) |
| 61 | 59 | goto out; |
| 62 | 60 | |
| 63 | 61 | if (IS_ENABLED(CONFIG_INET) && |
| 64 | − (eth->h_proto == htons(ETH_P_ARP) || | |
| 65 | − eth->h_proto == htons(ETH_P_RARP)) && | |
| 62 | + (eth_hdr(skb)->h_proto == htons(ETH_P_ARP) || | |
| 63 | + eth_hdr(skb)->h_proto == htons(ETH_P_RARP)) && | |
| 66 | 64 | br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { |
| 67 | 65 | br_do_proxy_suppress_arp(skb, br, vid, NULL); |
| 68 | 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 | 3077 | if (skb_rx_queue_recorded(skb)) { |
| 3078 | 3078 | hash = skb_get_rx_queue(skb); |
| 3079 | + if (hash >= qoffset) | |
| 3080 | + hash -= qoffset; | |
| 3079 | 3081 | while (unlikely(hash >= qcount)) |
| 3080 | 3082 | hash -= qcount; |
| 3081 | 3083 | return hash + qoffset; |
| @@ -2103,11 +2103,11 @@ err_action_values_put: · 2102 unmodified lines | ||
| 2103 | 2103 | |
| 2104 | 2104 | static struct devlink_dpipe_table * |
| 2105 | 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 | 2108 | struct devlink_dpipe_table *table; |
| 2109 | − | |
| 2110 | − list_for_each_entry_rcu(table, dpipe_tables, list) { | |
| 2109 | + list_for_each_entry_rcu(table, dpipe_tables, list, | |
| 2110 | + lockdep_is_held(&devlink->lock)) { | |
| 2111 | 2111 | if (!strcmp(table->name, table_name)) |
| 2112 | 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 | 2227 | table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); |
| 2228 | 2228 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 2229 | − table_name); | |
| 2229 | + table_name, devlink); | |
| 2230 | 2230 | if (!table) |
| 2231 | 2231 | return -EINVAL; |
| 2232 | 2232 | |
| @@ -2382,7 +2382,7 @@ static int devlink_dpipe_table_counters_set(struct devlink *devlink, · 149 unmodified lines | ||
| 2382 | 2382 | struct devlink_dpipe_table *table; |
| 2383 | 2383 | |
| 2384 | 2384 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 2385 | − table_name); | |
| 2385 | + table_name, devlink); | |
| 2386 | 2386 | if (!table) |
| 2387 | 2387 | return -EINVAL; |
| 2388 | 2388 | |
| @@ -6854,7 +6854,7 @@ bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, · 4465 unmodified lines | ||
| 6854 | 6854 | |
| 6855 | 6855 | rcu_read_lock(); |
| 6856 | 6856 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 6857 | − table_name); | |
| 6857 | + table_name, devlink); | |
| 6858 | 6858 | enabled = false; |
| 6859 | 6859 | if (table) |
| 6860 | 6860 | enabled = table->counters_enabled; |
| @@ -6878,26 +6878,34 @@ int devlink_dpipe_table_register(struct devlink *devlink, · 17 unmodified lines | ||
| 6878 | 6878 | void *priv, bool counter_control_extern) |
| 6879 | 6879 | { |
| 6880 | 6880 | struct devlink_dpipe_table *table; |
| 6881 | − | |
| 6882 | − if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) | |
| 6883 | − return -EEXIST; | |
| 6881 | + int err = 0; | |
| 6884 | 6882 | |
| 6885 | 6883 | if (WARN_ON(!table_ops->size_get)) |
| 6886 | 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 | 6894 | table = kzalloc(sizeof(*table), GFP_KERNEL); |
| 6889 | − if (!table) | |
| 6890 | − return -ENOMEM; | |
| 6895 | + if (!table) { | |
| 6896 | + err = -ENOMEM; | |
| 6897 | + goto unlock; | |
| 6898 | + } | |
| 6891 | 6899 | |
| 6892 | 6900 | table->name = table_name; |
| 6893 | 6901 | table->table_ops = table_ops; |
| 6894 | 6902 | table->priv = priv; |
| 6895 | 6903 | table->counter_control_extern = counter_control_extern; |
| 6896 | 6904 | |
| 6897 | − mutex_lock(&devlink->lock); | |
| 6898 | 6905 | list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); |
| 6906 | +unlock: | |
| 6899 | 6907 | mutex_unlock(&devlink->lock); |
| 6900 | − return 0; | |
| 6908 | + return err; | |
| 6901 | 6909 | } |
| 6902 | 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 | 6923 | mutex_lock(&devlink->lock); |
| 6916 | 6924 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 6917 | − table_name); | |
| 6925 | + table_name, devlink); | |
| 6918 | 6926 | if (!table) |
| 6919 | 6927 | goto unlock; |
| 6920 | 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 | 7080 | mutex_lock(&devlink->lock); |
| 7073 | 7081 | table = devlink_dpipe_table_find(&devlink->dpipe_table_list, |
| 7074 | − table_name); | |
| 7082 | + table_name, devlink); | |
| 7075 | 7083 | if (!table) { |
| 7076 | 7084 | err = -EINVAL; |
| 7077 | 7085 | goto out; |
| @@ -305,7 +305,8 @@ nla_put_failure: · 304 unmodified lines | ||
| 305 | 305 | static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { |
| 306 | 306 | [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT }, |
| 307 | 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 | 310 | [ETHTOOL_A_BITSET_BITS] = { .type = NLA_NESTED }, |
| 310 | 311 | [ETHTOOL_A_BITSET_VALUE] = { .type = NLA_BINARY }, |
| 311 | 312 | [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY }, |
| @@ -3,6 +3,8 @@ · 2 unmodified lines | ||
| 3 | 3 | #ifndef _NET_ETHTOOL_BITSET_H |
| 4 | 4 | #define _NET_ETHTOOL_BITSET_H |
| 5 | 5 | |
| 6 | +#define ETHNL_MAX_BITSET_SIZE S16_MAX | |
| 7 | + | |
| 6 | 8 | typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN]; |
| 7 | 9 | |
| 8 | 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 | 1725 | unsigned char optbuf[sizeof(struct ip_options) + 40]; |
| 1726 | 1726 | struct ip_options *opt = (struct ip_options *)optbuf; |
| 1727 | + int res; | |
| 1727 | 1728 | |
| 1728 | 1729 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) |
| 1729 | 1730 | return; |
| @@ -1735,7 +1736,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) · 5 unmodified lines | ||
| 1735 | 1736 | |
| 1736 | 1737 | memset(opt, 0, sizeof(struct ip_options)); |
| 1737 | 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 | 1744 | return; |
| 1740 | 1745 | |
| 1741 | 1746 | if (gateway) |
| @@ -6124,7 +6124,11 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) · 6123 unmodified lines | ||
| 6124 | 6124 | { |
| 6125 | 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 | 6133 | /* Reset rtx states to prevent spurious retransmits_timed_out() */ |
| 6130 | 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 | 183 | retv = -EBUSY; |
| 184 | 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 | 191 | break; |
| 188 | − | |
| 192 | + } else { | |
| 193 | + break; | |
| 194 | + } | |
| 189 | 195 | if (sk->sk_state != TCP_ESTABLISHED) { |
| 190 | 196 | retv = -ENOTCONN; |
| 191 | 197 | break; |
| @@ -2959,7 +2959,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 2958 unmodified lines | ||
| 2959 | 2959 | (auth_transaction == 2 && |
| 2960 | 2960 | ifmgd->auth_data->expected_transaction == 2)) { |
| 2961 | 2961 | if (!ieee80211_mark_sta_auth(sdata, bssid)) |
| 2962 | − goto out_err; | |
| 2962 | + return; /* ignore frame -- wait for timeout */ | |
| 2963 | 2963 | } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && |
| 2964 | 2964 | auth_transaction == 2) { |
| 2965 | 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 | 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 | 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 | 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 | 4118 | if (sdata != sta->sdata && |
| 4119 | 4119 | (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) |
| 4120 | 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 | 551 | static int __mptcp_init_sock(struct sock *sk) |
| 547 | 552 | { |
| 548 | 553 | struct mptcp_sock *msk = mptcp_sk(sk); |
| @@ -551,6 +556,7 @@ static int __mptcp_init_sock(struct sock *sk) · 2 unmodified lines | ||
| 551 | 556 | __set_bit(MPTCP_SEND_SPACE, &msk->flags); |
| 552 | 557 | |
| 553 | 558 | msk->first = NULL; |
| 559 | + inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss; | |
| 554 | 560 | |
| 555 | 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 | 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 | 740 | int |
| 727 | 741 | ip_set_test(ip_set_id_t index, const struct sk_buff *skb, |
| 728 | 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 | 758 | if (ret == -EAGAIN) { |
| 745 | 759 | /* Type requests element to be completed */ |
| 746 | 760 | pr_debug("element must be completed, ADD is triggered\n"); |
| 747 | − spin_lock_bh(&set->lock); | |
| 761 | + ip_set_lock(set); | |
| 748 | 762 | set->variant->kadt(set, skb, par, IPSET_ADD, opt); |
| 749 | − spin_unlock_bh(&set->lock); | |
| 763 | + ip_set_unlock(set); | |
| 750 | 764 | ret = 1; |
| 751 | 765 | } else { |
| 752 | 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 | 789 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 776 | 790 | return -IPSET_ERR_TYPE_MISMATCH; |
| 777 | 791 | |
| 778 | − spin_lock_bh(&set->lock); | |
| 792 | + ip_set_lock(set); | |
| 779 | 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 | 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 | 811 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 798 | 812 | return -IPSET_ERR_TYPE_MISMATCH; |
| 799 | 813 | |
| 800 | − spin_lock_bh(&set->lock); | |
| 814 | + ip_set_lock(set); | |
| 801 | 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 | 818 | return ret; |
| 805 | 819 | } |
| @@ -1264,9 +1278,9 @@ ip_set_flush_set(struct ip_set *set) · 458 unmodified lines | ||
| 1264 | 1278 | { |
| 1265 | 1279 | pr_debug("set: %s\n", set->name); |
| 1266 | 1280 | |
| 1267 | − spin_lock_bh(&set->lock); | |
| 1281 | + ip_set_lock(set); | |
| 1268 | 1282 | set->variant->flush(set); |
| 1269 | − spin_unlock_bh(&set->lock); | |
| 1283 | + ip_set_unlock(set); | |
| 1270 | 1284 | } |
| 1271 | 1285 | |
| 1272 | 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 | 1727 | bool eexist = flags & IPSET_FLAG_EXIST, retried = false; |
| 1714 | 1728 | |
| 1715 | 1729 | do { |
| 1716 | − spin_lock_bh(&set->lock); | |
| 1730 | + ip_set_lock(set); | |
| 1717 | 1731 | ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried); |
| 1718 | − spin_unlock_bh(&set->lock); | |
| 1732 | + ip_set_unlock(set); | |
| 1719 | 1733 | retried = true; |
| 1720 | 1734 | } while (ret == -EAGAIN && |
| 1721 | 1735 | set->variant->resize && |
| @@ -7,13 +7,21 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/rcupdate.h> |
| 8 | 8 | #include <linux/jhash.h> |
| 9 | 9 | #include <linux/types.h> |
| 10 | +#include <linux/netfilter/nfnetlink.h> | |
| 10 | 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_protected(p, set) \ | |
| 14 | − __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock)) | |
| 15 | − | |
| 16 | −#define rcu_dereference_bh_nfnl(p) rcu_dereference_bh_check(p, 1) | |
| 13 | +#define __ipset_dereference(p) \ | |
| 14 | + rcu_dereference_protected(p, 1) | |
| 15 | +#define ipset_dereference_nfnl(p) \ | |
| 16 | + rcu_dereference_protected(p, \ | |
| 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 | 26 | /* Hashing which uses arrays to resolve clashing. The hash table is resized |
| 19 | 27 | * (doubled) when searching becomes too long. |
| @@ -72,11 +80,35 @@ struct hbucket { · 52 unmodified lines | ||
| 72 | 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 | 105 | /* The hash table: the table size stored here in order to make resizing easy */ |
| 76 | 106 | struct htable { |
| 77 | 107 | atomic_t ref; /* References for resizing */ |
| 78 | − atomic_t uref; /* References for dumping */ | |
| 108 | + atomic_t uref; /* References for dumping and gc */ | |
| 79 | 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 | 112 | struct hbucket __rcu *bucket[0]; /* hashtable buckets */ |
| 81 | 113 | }; |
| 82 | 114 | |
| @@ -162,6 +194,10 @@ htable_bits(u32 hashsize) · 79 unmodified lines | ||
| 162 | 194 | #define NLEN 0 |
| 163 | 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 | 201 | #endif /* _IP_SET_HASH_GEN_H */ |
| 166 | 202 | |
| 167 | 203 | #ifndef MTYPE |
| @@ -205,10 +241,12 @@ htable_bits(u32 hashsize) · 37 unmodified lines | ||
| 205 | 241 | #undef mtype_test_cidrs |
| 206 | 242 | #undef mtype_test |
| 207 | 243 | #undef mtype_uref |
| 208 | −#undef mtype_expire | |
| 209 | 244 | #undef mtype_resize |
| 245 | +#undef mtype_ext_size | |
| 246 | +#undef mtype_resize_ad | |
| 210 | 247 | #undef mtype_head |
| 211 | 248 | #undef mtype_list |
| 249 | +#undef mtype_gc_do | |
| 212 | 250 | #undef mtype_gc |
| 213 | 251 | #undef mtype_gc_init |
| 214 | 252 | #undef mtype_variant |
| @@ -247,10 +285,12 @@ htable_bits(u32 hashsize) · 32 unmodified lines | ||
| 247 | 285 | #define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs) |
| 248 | 286 | #define mtype_test IPSET_TOKEN(MTYPE, _test) |
| 249 | 287 | #define mtype_uref IPSET_TOKEN(MTYPE, _uref) |
| 250 | −#define mtype_expire IPSET_TOKEN(MTYPE, _expire) | |
| 251 | 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 | 291 | #define mtype_head IPSET_TOKEN(MTYPE, _head) |
| 253 | 292 | #define mtype_list IPSET_TOKEN(MTYPE, _list) |
| 293 | +#define mtype_gc_do IPSET_TOKEN(MTYPE, _gc_do) | |
| 254 | 294 | #define mtype_gc IPSET_TOKEN(MTYPE, _gc) |
| 255 | 295 | #define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) |
| 256 | 296 | #define mtype_variant IPSET_TOKEN(MTYPE, _variant) |
| @@ -275,8 +315,7 @@ htable_bits(u32 hashsize) · 18 unmodified lines | ||
| 275 | 315 | /* The generic hash structure */ |
| 276 | 316 | struct htype { |
| 277 | 317 | struct htable __rcu *table; /* the hash table */ |
| 278 | − struct timer_list gc; /* garbage collection when timeout enabled */ | |
| 279 | − struct ip_set *set; /* attached to this ip_set */ | |
| 318 | + struct htable_gc gc; /* gc workqueue */ | |
| 280 | 319 | u32 maxelem; /* max elements in the hash */ |
| 281 | 320 | u32 initval; /* random jhash init value */ |
| 282 | 321 | #ifdef IP_SET_HASH_WITH_MARKMASK |
| @@ -288,21 +327,33 @@ struct htype { · 5 unmodified lines | ||
| 288 | 327 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 289 | 328 | u8 netmask; /* netmask value for subnets to store */ |
| 290 | 329 | #endif |
| 330 | + struct list_head ad; /* Resize add|del backlist */ | |
| 291 | 331 | struct mtype_elem next; /* temporary storage for uadd */ |
| 292 | 332 | #ifdef IP_SET_HASH_WITH_NETS |
| 293 | 333 | struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */ |
| 294 | 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 | 347 | #ifdef IP_SET_HASH_WITH_NETS |
| 298 | 348 | /* Network cidr size book keeping when the hash stores different |
| 299 | 349 | * sized networks. cidr == real cidr + 1 to support /0. |
| 300 | 350 | */ |
| 301 | 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 | 354 | int i, j; |
| 305 | 355 | |
| 356 | + spin_lock_bh(&set->lock); | |
| 306 | 357 | /* Add in increasing prefix order, so larger cidr first */ |
| 307 | 358 | for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) { |
| 308 | 359 | if (j != -1) { |
| @@ -311,7 +362,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) · 2 unmodified lines | ||
| 311 | 362 | j = i; |
| 312 | 363 | } else if (h->nets[i].cidr[n] == cidr) { |
| 313 | 364 | h->nets[CIDR_POS(cidr)].nets[n]++; |
| 314 | − return; | |
| 365 | + goto unlock; | |
| 315 | 366 | } |
| 316 | 367 | } |
| 317 | 368 | if (j != -1) { |
| @@ -320,24 +371,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n) · 2 unmodified lines | ||
| 320 | 371 | } |
| 321 | 372 | h->nets[i].cidr[n] = cidr; |
| 322 | 373 | h->nets[CIDR_POS(cidr)].nets[n] = 1; |
| 374 | +unlock: | |
| 375 | + spin_unlock_bh(&set->lock); | |
| 323 | 376 | } |
| 324 | 377 | |
| 325 | 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 | 381 | u8 i, j, net_end = NLEN - 1; |
| 329 | 382 | |
| 383 | + spin_lock_bh(&set->lock); | |
| 330 | 384 | for (i = 0; i < NLEN; i++) { |
| 331 | 385 | if (h->nets[i].cidr[n] != cidr) |
| 332 | 386 | continue; |
| 333 | 387 | h->nets[CIDR_POS(cidr)].nets[n]--; |
| 334 | 388 | if (h->nets[CIDR_POS(cidr)].nets[n] > 0) |
| 335 | − return; | |
| 389 | + goto unlock; | |
| 336 | 390 | for (j = i; j < net_end && h->nets[j].cidr[n]; j++) |
| 337 | 391 | h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; |
| 338 | 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 | 398 | #endif |
| 343 | 399 | |
| @@ -345,7 +401,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n) · 1 unmodified line | ||
| 345 | 401 | static size_t |
| 346 | 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 | 407 | /* Get the ith element from the array block n */ |
| @@ -369,24 +425,29 @@ mtype_flush(struct ip_set *set) · 17 unmodified lines | ||
| 369 | 425 | struct htype *h = set->data; |
| 370 | 426 | struct htable *t; |
| 371 | 427 | struct hbucket *n; |
| 372 | − u32 i; | |
| 373 | − | |
| 374 | − t = ipset_dereference_protected(h->table, set); | |
| 375 | − for (i = 0; i < jhash_size(t->htable_bits); i++) { | |
| 376 | − n = __ipset_dereference_protected(hbucket(t, i), 1); | |
| 377 | − if (!n) | |
| 378 | − continue; | |
| 379 | − if (set->extensions & IPSET_EXT_DESTROY) | |
| 380 | − mtype_ext_cleanup(set, n); | |
| 381 | − /* FIXME: use slab cache */ | |
| 382 | − rcu_assign_pointer(hbucket(t, i), NULL); | |
| 383 | − kfree_rcu(n, rcu); | |
| 428 | + u32 r, i; | |
| 429 | + | |
| 430 | + t = ipset_dereference_nfnl(h->table); | |
| 431 | + for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) { | |
| 432 | + spin_lock_bh(&t->hregion[r].lock); | |
| 433 | + for (i = ahash_bucket_start(r, t->htable_bits); | |
| 434 | + i < ahash_bucket_end(r, t->htable_bits); i++) { | |
| 435 | + n = __ipset_dereference(hbucket(t, i)); | |
| 436 | + if (!n) | |
| 437 | + continue; | |
| 438 | + if (set->extensions & IPSET_EXT_DESTROY) | |
| 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 | 448 | #ifdef IP_SET_HASH_WITH_NETS |
| 386 | 449 | memset(h->nets, 0, sizeof(h->nets)); |
| 387 | 450 | #endif |
| 388 | − set->elements = 0; | |
| 389 | − set->ext_size = 0; | |
| 390 | 451 | } |
| 391 | 452 | |
| 392 | 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 | 458 | u32 i; |
| 398 | 459 | |
| 399 | 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 | 462 | if (!n) |
| 402 | 463 | continue; |
| 403 | 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 | 467 | kfree(n); |
| 407 | 468 | } |
| 408 | 469 | |
| 470 | + ip_set_free(t->hregion); | |
| 409 | 471 | ip_set_free(t); |
| 410 | 472 | } |
| 411 | 473 | |
| @@ -414,28 +476,21 @@ static void · 2 unmodified lines | ||
| 414 | 476 | mtype_destroy(struct ip_set *set) |
| 415 | 477 | { |
| 416 | 478 | struct htype *h = set->data; |
| 479 | + struct list_head *l, *lt; | |
| 417 | 480 | |
| 418 | 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, | |
| 422 | − __ipset_dereference_protected(h->table, 1), true); | |
| 484 | + mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true); | |
| 485 | + list_for_each_safe(l, lt, &h->ad) { | |
| 486 | + list_del(l); | |
| 487 | + kfree(l); | |
| 488 | + } | |
| 423 | 489 | kfree(h); |
| 424 | 490 | |
| 425 | 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 | 494 | static bool |
| 440 | 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 | 509 | a->extensions == b->extensions; |
| 455 | 510 | } |
| 456 | 511 | |
| 457 | −/* Delete expired elements from the hashtable */ | |
| 458 | 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 | 515 | struct hbucket *n, *tmp; |
| 463 | 516 | struct mtype_elem *data; |
| 464 | 517 | u32 i, j, d; |
| @@ -466,10 +519,12 @@ mtype_expire(struct ip_set *set, struct htype *h) · 1 unmodified line | ||
| 466 | 519 | #ifdef IP_SET_HASH_WITH_NETS |
| 467 | 520 | u8 k; |
| 468 | 521 | #endif |
| 522 | + u8 htable_bits = t->htable_bits; | |
| 469 | 523 | |
| 470 | − t = ipset_dereference_protected(h->table, set); | |
| 471 | − for (i = 0; i < jhash_size(t->htable_bits); i++) { | |
| 472 | − n = __ipset_dereference_protected(hbucket(t, i), 1); | |
| 524 | + spin_lock_bh(&t->hregion[r].lock); | |
| 525 | + for (i = ahash_bucket_start(r, htable_bits); | |
| 526 | + i < ahash_bucket_end(r, htable_bits); i++) { | |
| 527 | + n = __ipset_dereference(hbucket(t, i)); | |
| 473 | 528 | if (!n) |
| 474 | 529 | continue; |
| 475 | 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 | 540 | smp_mb__after_atomic(); |
| 486 | 541 | #ifdef IP_SET_HASH_WITH_NETS |
| 487 | 542 | for (k = 0; k < IPSET_NET_COUNT; k++) |
| 488 | − mtype_del_cidr(h, | |
| 543 | + mtype_del_cidr(set, h, | |
| 489 | 544 | NCIDR_PUT(DCIDR_GET(data->cidr, k)), |
| 490 | 545 | k); |
| 491 | 546 | #endif |
| 547 | + t->hregion[r].elements--; | |
| 492 | 548 | ip_set_ext_destroy(set, data); |
| 493 | − set->elements--; | |
| 494 | 549 | d++; |
| 495 | 550 | } |
| 496 | 551 | if (d >= AHASH_INIT_SIZE) { |
| 497 | 552 | if (d >= n->size) { |
| 553 | + t->hregion[r].ext_size -= | |
| 554 | + ext_size(n->size, dsize); | |
| 498 | 555 | rcu_assign_pointer(hbucket(t, i), NULL); |
| 499 | 556 | kfree_rcu(n, rcu); |
| 500 | 557 | continue; |
| 501 | 558 | } |
| 502 | 559 | tmp = kzalloc(sizeof(*tmp) + |
| 503 | − (n->size - AHASH_INIT_SIZE) * dsize, | |
| 504 | − GFP_ATOMIC); | |
| 560 | + (n->size - AHASH_INIT_SIZE) * dsize, | |
| 561 | + GFP_ATOMIC); | |
| 505 | 562 | if (!tmp) |
| 506 | − /* Still try to delete expired elements */ | |
| 563 | + /* Still try to delete expired elements. */ | |
| 507 | 564 | continue; |
| 508 | 565 | tmp->size = n->size - AHASH_INIT_SIZE; |
| 509 | 566 | for (j = 0, d = 0; j < n->pos; j++) { |
| 510 | 567 | if (!test_bit(j, n->used)) |
| 511 | 568 | continue; |
| 512 | 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 | 572 | set_bit(d, tmp->used); |
| 515 | 573 | d++; |
| 516 | 574 | } |
| 517 | 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 | 578 | rcu_assign_pointer(hbucket(t, i), tmp); |
| 520 | 579 | kfree_rcu(n, rcu); |
| 521 | 580 | } |
| 522 | 581 | } |
| 582 | + spin_unlock_bh(&t->hregion[r].lock); | |
| 523 | 583 | } |
| 524 | 584 | |
| 525 | 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); | |
| 529 | − struct ip_set *set = h->set; | |
| 588 | + struct htable_gc *gc; | |
| 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 | 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 | 610 | spin_unlock_bh(&set->lock); |
| 535 | 611 | |
| 536 | − h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; | |
| 537 | − add_timer(&h->gc); | |
| 612 | + mtype_gc_do(set, h, t, r); | |
| 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 | 637 | /* Resize a hash: create a new hash table with doubling the hashsize |
| 541 | 638 | * and inserting the elements to it. Repeat until we succeed or |
| 542 | 639 | * fail due to memory pressures. |
| @@ -547,7 +644,7 @@ mtype_resize(struct ip_set *set, bool retried) · 4 unmodified lines | ||
| 547 | 644 | struct htype *h = set->data; |
| 548 | 645 | struct htable *t, *orig; |
| 549 | 646 | u8 htable_bits; |
| 550 | − size_t extsize, dsize = set->dsize; | |
| 647 | + size_t dsize = set->dsize; | |
| 551 | 648 | #ifdef IP_SET_HASH_WITH_NETS |
| 552 | 649 | u8 flags; |
| 553 | 650 | struct mtype_elem *tmp; |
| @@ -555,7 +652,9 @@ mtype_resize(struct ip_set *set, bool retried) · 1 unmodified line | ||
| 555 | 652 | struct mtype_elem *data; |
| 556 | 653 | struct mtype_elem *d; |
| 557 | 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 | 658 | int ret; |
| 560 | 659 | |
| 561 | 660 | #ifdef IP_SET_HASH_WITH_NETS |
| @@ -563,10 +662,8 @@ mtype_resize(struct ip_set *set, bool retried) · 1 unmodified line | ||
| 563 | 662 | if (!tmp) |
| 564 | 663 | return -ENOMEM; |
| 565 | 664 | #endif |
| 566 | − rcu_read_lock_bh(); | |
| 567 | − orig = rcu_dereference_bh_nfnl(h->table); | |
| 665 | + orig = ipset_dereference_bh_nfnl(h->table); | |
| 568 | 666 | htable_bits = orig->htable_bits; |
| 569 | − rcu_read_unlock_bh(); | |
| 570 | 667 | |
| 571 | 668 | retry: |
| 572 | 669 | ret = 0; |
| @@ -583,88 +680,124 @@ retry: · 10 unmodified lines | ||
| 583 | 680 | ret = -ENOMEM; |
| 584 | 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 | 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); | |
| 589 | − orig = __ipset_dereference_protected(h->table, 1); | |
| 590 | − /* There can't be another parallel resizing, but dumping is possible */ | |
| 694 | + /* There can't be another parallel resizing, | |
| 695 | + * but dumping, gc, kernel side add/del are possible | |
| 696 | + */ | |
| 697 | + orig = ipset_dereference_bh_nfnl(h->table); | |
| 591 | 698 | atomic_set(&orig->ref, 1); |
| 592 | 699 | atomic_inc(&orig->uref); |
| 593 | − extsize = 0; | |
| 594 | 700 | pr_debug("attempt to resize set %s from %u to %u, t %p\n", |
| 595 | 701 | set->name, orig->htable_bits, htable_bits, orig); |
| 596 | − for (i = 0; i < jhash_size(orig->htable_bits); i++) { | |
| 597 | − n = __ipset_dereference_protected(hbucket(orig, i), 1); | |
| 598 | − if (!n) | |
| 599 | − continue; | |
| 600 | − for (j = 0; j < n->pos; j++) { | |
| 601 | − if (!test_bit(j, n->used)) | |
| 702 | + for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) { | |
| 703 | + /* Expire may replace a hbucket with another one */ | |
| 704 | + rcu_read_lock_bh(); | |
| 705 | + for (i = ahash_bucket_start(r, orig->htable_bits); | |
| 706 | + i < ahash_bucket_end(r, orig->htable_bits); i++) { | |
| 707 | + n = __ipset_dereference(hbucket(orig, i)); | |
| 708 | + if (!n) | |
| 602 | 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 | 716 | #ifdef IP_SET_HASH_WITH_NETS |
| 605 | − /* We have readers running parallel with us, | |
| 606 | − * so the live data cannot be modified. | |
| 607 | − */ | |
| 608 | − flags = 0; | |
| 609 | − memcpy(tmp, data, dsize); | |
| 610 | − data = tmp; | |
| 611 | − mtype_data_reset_flags(data, &flags); | |
| 717 | + /* We have readers running parallel with us, | |
| 718 | + * so the live data cannot be modified. | |
| 719 | + */ | |
| 720 | + flags = 0; | |
| 721 | + memcpy(tmp, data, dsize); | |
| 722 | + data = tmp; | |
| 723 | + mtype_data_reset_flags(data, &flags); | |
| 612 | 724 | #endif |
| 613 | − key = HKEY(data, h->initval, htable_bits); | |
| 614 | − m = __ipset_dereference_protected(hbucket(t, key), 1); | |
| 615 | − if (!m) { | |
| 616 | − m = kzalloc(sizeof(*m) + | |
| 725 | + key = HKEY(data, h->initval, htable_bits); | |
| 726 | + m = __ipset_dereference(hbucket(t, key)); | |
| 727 | + nr = ahash_region(key, htable_bits); | |
| 728 | + if (!m) { | |
| 729 | + m = kzalloc(sizeof(*m) + | |
| 617 | 730 | AHASH_INIT_SIZE * dsize, |
| 618 | 731 | GFP_ATOMIC); |
| 619 | − if (!m) { | |
| 620 | − ret = -ENOMEM; | |
| 621 | − goto cleanup; | |
| 622 | − } | |
| 623 | − m->size = AHASH_INIT_SIZE; | |
| 624 | − extsize += ext_size(AHASH_INIT_SIZE, dsize); | |
| 625 | − RCU_INIT_POINTER(hbucket(t, key), m); | |
| 626 | − } else if (m->pos >= m->size) { | |
| 627 | − struct hbucket *ht; | |
| 628 | − | |
| 629 | − if (m->size >= AHASH_MAX(h)) { | |
| 630 | − ret = -EAGAIN; | |
| 631 | − } else { | |
| 632 | − ht = kzalloc(sizeof(*ht) + | |
| 732 | + if (!m) { | |
| 733 | + ret = -ENOMEM; | |
| 734 | + goto cleanup; | |
| 735 | + } | |
| 736 | + m->size = AHASH_INIT_SIZE; | |
| 737 | + t->hregion[nr].ext_size += | |
| 738 | + ext_size(AHASH_INIT_SIZE, | |
| 739 | + dsize); | |
| 740 | + RCU_INIT_POINTER(hbucket(t, key), m); | |
| 741 | + } else if (m->pos >= m->size) { | |
| 742 | + struct hbucket *ht; | |
| 743 | + | |
| 744 | + if (m->size >= AHASH_MAX(h)) { | |
| 745 | + ret = -EAGAIN; | |
| 746 | + } else { | |
| 747 | + ht = kzalloc(sizeof(*ht) + | |
| 633 | 748 | (m->size + AHASH_INIT_SIZE) |
| 634 | 749 | * dsize, |
| 635 | 750 | GFP_ATOMIC); |
| 636 | − if (!ht) | |
| 637 | − ret = -ENOMEM; | |
| 751 | + if (!ht) | |
| 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) | |
| 640 | − goto cleanup; | |
| 641 | − memcpy(ht, m, sizeof(struct hbucket) + | |
| 642 | − m->size * dsize); | |
| 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); | |
| 766 | + d = ahash_data(m, m->pos, dsize); | |
| 767 | + memcpy(d, data, dsize); | |
| 768 | + set_bit(m->pos++, m->used); | |
| 769 | + t->hregion[nr].elements++; | |
| 652 | 770 | #ifdef IP_SET_HASH_WITH_NETS |
| 653 | − mtype_data_reset_flags(d, &flags); | |
| 771 | + mtype_data_reset_flags(d, &flags); | |
| 654 | 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 | 781 | /* Give time to other readers of the set */ |
| 663 | 782 | synchronize_rcu(); |
| 664 | 783 | |
| 665 | 784 | pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, |
| 666 | 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 | 801 | if (atomic_dec_and_test(&orig->uref)) { |
| 669 | 802 | pr_debug("Table destroy by resize %p\n", orig); |
| 670 | 803 | mtype_ahash_destroy(set, orig, false); |
| @@ -677,15 +810,44 @@ out: · 6 unmodified lines | ||
| 677 | 810 | return ret; |
| 678 | 811 | |
| 679 | 812 | cleanup: |
| 813 | + rcu_read_unlock_bh(); | |
| 680 | 814 | atomic_set(&orig->ref, 0); |
| 681 | 815 | atomic_dec(&orig->uref); |
| 682 | − spin_unlock_bh(&set->lock); | |
| 683 | 816 | mtype_ahash_destroy(set, t, false); |
| 684 | 817 | if (ret == -EAGAIN) |
| 685 | 818 | goto retry; |
| 686 | 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 | 851 | /* Add an element to a hash and update the internal counters when succeeded, |
| 690 | 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 | 860 | const struct mtype_elem *d = value; |
| 699 | 861 | struct mtype_elem *data; |
| 700 | 862 | struct hbucket *n, *old = ERR_PTR(-ENOENT); |
| 701 | − int i, j = -1; | |
| 863 | + int i, j = -1, ret; | |
| 702 | 864 | bool flag_exist = flags & IPSET_FLAG_EXIST; |
| 703 | 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) { | |
| 707 | − if (SET_WITH_TIMEOUT(set)) | |
| 708 | − /* FIXME: when set is full, we slow down here */ | |
| 709 | − mtype_expire(set, h); | |
| 710 | − if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set)) | |
| 868 | + rcu_read_lock_bh(); | |
| 869 | + t = rcu_dereference_bh(h->table); | |
| 870 | + key = HKEY(value, h->initval, t->htable_bits); | |
| 871 | + r = ahash_region(key, t->htable_bits); | |
| 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 | 887 | forceadd = true; |
| 712 | 888 | } |
| 889 | + rcu_read_unlock_bh(); | |
| 713 | 890 | |
| 714 | − t = ipset_dereference_protected(h->table, set); | |
| 715 | − key = HKEY(value, h->initval, t->htable_bits); | |
| 716 | − n = __ipset_dereference_protected(hbucket(t, key), 1); | |
| 891 | + spin_lock_bh(&t->hregion[r].lock); | |
| 892 | + n = rcu_dereference_bh(hbucket(t, key)); | |
| 717 | 893 | if (!n) { |
| 718 | − if (forceadd || set->elements >= h->maxelem) | |
| 894 | + if (forceadd || elements >= maxelem) | |
| 719 | 895 | goto set_full; |
| 720 | 896 | old = NULL; |
| 721 | 897 | n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize, |
| 722 | 898 | GFP_ATOMIC); |
| 723 | − if (!n) | |
| 724 | − return -ENOMEM; | |
| 899 | + if (!n) { | |
| 900 | + ret = -ENOMEM; | |
| 901 | + goto unlock; | |
| 902 | + } | |
| 725 | 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 | 906 | goto copy_elem; |
| 728 | 907 | } |
| 729 | 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 | 917 | data = ahash_data(n, i, set->dsize); |
| 739 | 918 | if (mtype_data_equal(data, d, &multi)) { |
| 740 | − if (flag_exist || | |
| 741 | − (SET_WITH_TIMEOUT(set) && | |
| 742 | − ip_set_timeout_expired(ext_timeout(data, set)))) { | |
| 919 | + if (flag_exist || SET_ELEM_EXPIRED(set, data)) { | |
| 743 | 920 | /* Just the extensions could be overwritten */ |
| 744 | 921 | j = i; |
| 745 | 922 | goto overwrite_extensions; |
| 746 | 923 | } |
| 747 | − return -IPSET_ERR_EXIST; | |
| 924 | + ret = -IPSET_ERR_EXIST; | |
| 925 | + goto unlock; | |
| 748 | 926 | } |
| 749 | 927 | /* Reuse first timed out entry */ |
| 750 | − if (SET_WITH_TIMEOUT(set) && | |
| 751 | − ip_set_timeout_expired(ext_timeout(data, set)) && | |
| 752 | − j == -1) { | |
| 928 | + if (SET_ELEM_EXPIRED(set, data) && j == -1) { | |
| 753 | 929 | j = i; |
| 754 | 930 | reuse = true; |
| 755 | 931 | } |
| 756 | 932 | } |
| 757 | 933 | if (reuse || forceadd) { |
| 934 | + if (j == -1) | |
| 935 | + j = 0; | |
| 758 | 936 | data = ahash_data(n, j, set->dsize); |
| 759 | 937 | if (!deleted) { |
| 760 | 938 | #ifdef IP_SET_HASH_WITH_NETS |
| 761 | 939 | for (i = 0; i < IPSET_NET_COUNT; i++) |
| 762 | − mtype_del_cidr(h, | |
| 940 | + mtype_del_cidr(set, h, | |
| 763 | 941 | NCIDR_PUT(DCIDR_GET(data->cidr, i)), |
| 764 | 942 | i); |
| 765 | 943 | #endif |
| 766 | 944 | ip_set_ext_destroy(set, data); |
| 767 | − set->elements--; | |
| 945 | + t->hregion[r].elements--; | |
| 768 | 946 | } |
| 769 | 947 | goto copy_data; |
| 770 | 948 | } |
| 771 | − if (set->elements >= h->maxelem) | |
| 949 | + if (elements >= maxelem) | |
| 772 | 950 | goto set_full; |
| 773 | 951 | /* Create a new slot */ |
| 774 | 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 | 954 | if (n->size >= AHASH_MAX(h)) { |
| 777 | 955 | /* Trigger rehashing */ |
| 778 | 956 | mtype_data_next(&h->next, d); |
| 779 | − return -EAGAIN; | |
| 957 | + ret = -EAGAIN; | |
| 958 | + goto resize; | |
| 780 | 959 | } |
| 781 | 960 | old = n; |
| 782 | 961 | n = kzalloc(sizeof(*n) + |
| 783 | 962 | (old->size + AHASH_INIT_SIZE) * set->dsize, |
| 784 | 963 | GFP_ATOMIC); |
| 785 | − if (!n) | |
| 786 | − return -ENOMEM; | |
| 964 | + if (!n) { | |
| 965 | + ret = -ENOMEM; | |
| 966 | + goto unlock; | |
| 967 | + } | |
| 787 | 968 | memcpy(n, old, sizeof(struct hbucket) + |
| 788 | 969 | old->size * set->dsize); |
| 789 | 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 | 975 | copy_elem: |
| 794 | 976 | j = n->pos++; |
| 795 | 977 | data = ahash_data(n, j, set->dsize); |
| 796 | 978 | copy_data: |
| 797 | − set->elements++; | |
| 979 | + t->hregion[r].elements++; | |
| 798 | 980 | #ifdef IP_SET_HASH_WITH_NETS |
| 799 | 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 | 983 | #endif |
| 802 | 984 | memcpy(data, d, sizeof(struct mtype_elem)); |
| 803 | 985 | overwrite_extensions: |
| @@ -820,13 +1002,41 @@ overwrite_extensions: · 16 unmodified lines | ||
| 820 | 1002 | if (old) |
| 821 | 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 | 1027 | set_full: |
| 826 | 1028 | if (net_ratelimit()) |
| 827 | 1029 | pr_warn("Set %s is full, maxelem %u reached\n", |
| 828 | − set->name, h->maxelem); | |
| 829 | − return -IPSET_ERR_HASH_FULL; | |
| 1030 | + set->name, maxelem); | |
| 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 | 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 | 1050 | const struct mtype_elem *d = value; |
| 841 | 1051 | struct mtype_elem *data; |
| 842 | 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 | 1055 | u32 key, multi = 0; |
| 845 | 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 | 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 | 1070 | if (!n) |
| 851 | 1071 | goto out; |
| 852 | 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 | 1077 | data = ahash_data(n, i, dsize); |
| 858 | 1078 | if (!mtype_data_equal(data, d, &multi)) |
| 859 | 1079 | continue; |
| 860 | − if (SET_WITH_TIMEOUT(set) && | |
| 861 | − ip_set_timeout_expired(ext_timeout(data, set))) | |
| 1080 | + if (SET_ELEM_EXPIRED(set, data)) | |
| 862 | 1081 | goto out; |
| 863 | 1082 | |
| 864 | 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 | 1085 | smp_mb__after_atomic(); |
| 867 | 1086 | if (i + 1 == n->pos) |
| 868 | 1087 | n->pos--; |
| 869 | − set->elements--; | |
| 1088 | + t->hregion[r].elements--; | |
| 870 | 1089 | #ifdef IP_SET_HASH_WITH_NETS |
| 871 | 1090 | for (j = 0; j < IPSET_NET_COUNT; j++) |
| 872 | − mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)), | |
| 873 | − j); | |
| 1091 | + mtype_del_cidr(set, h, | |
| 1092 | + NCIDR_PUT(DCIDR_GET(d->cidr, j)), j); | |
| 874 | 1093 | #endif |
| 875 | 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 | 1109 | for (; i < n->pos; i++) { |
| 878 | 1110 | if (!test_bit(i, n->used)) |
| 879 | 1111 | k++; |
| 880 | 1112 | } |
| 881 | 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 | 1115 | rcu_assign_pointer(hbucket(t, key), NULL); |
| 884 | 1116 | kfree_rcu(n, rcu); |
| 885 | 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 | 1130 | k++; |
| 899 | 1131 | } |
| 900 | 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 | 1135 | rcu_assign_pointer(hbucket(t, key), tmp); |
| 903 | 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 | 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 | 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 | 1234 | int i, ret = 0; |
| 992 | 1235 | u32 key, multi = 0; |
| 993 | 1236 | |
| 1237 | + rcu_read_lock_bh(); | |
| 994 | 1238 | t = rcu_dereference_bh(h->table); |
| 995 | 1239 | #ifdef IP_SET_HASH_WITH_NETS |
| 996 | 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 | 1266 | goto out; |
| 1023 | 1267 | } |
| 1024 | 1268 | out: |
| 1269 | + rcu_read_unlock_bh(); | |
| 1025 | 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 | 1278 | const struct htable *t; |
| 1034 | 1279 | struct nlattr *nested; |
| 1035 | 1280 | size_t memsize; |
| 1281 | + u32 elements = 0; | |
| 1282 | + size_t ext_size = 0; | |
| 1036 | 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 | 1285 | rcu_read_lock_bh(); |
| 1051 | − t = rcu_dereference_bh_nfnl(h->table); | |
| 1052 | − memsize = mtype_ahash_memsize(h, t) + set->ext_size; | |
| 1286 | + t = rcu_dereference_bh(h->table); | |
| 1287 | + mtype_ext_size(set, &elements, &ext_size); | |
| 1288 | + memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size; | |
| 1053 | 1289 | htable_bits = t->htable_bits; |
| 1054 | 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 | 1307 | #endif |
| 1072 | 1308 | if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) || |
| 1073 | 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 | 1311 | goto nla_put_failure; |
| 1076 | 1312 | if (unlikely(ip_set_put_flags(skb, set))) |
| 1077 | 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 | 1328 | if (start) { |
| 1093 | 1329 | rcu_read_lock_bh(); |
| 1094 | − t = rcu_dereference_bh_nfnl(h->table); | |
| 1330 | + t = ipset_dereference_bh_nfnl(h->table); | |
| 1095 | 1331 | atomic_inc(&t->uref); |
| 1096 | 1332 | cb->args[IPSET_CB_PRIVATE] = (unsigned long)t; |
| 1097 | 1333 | rcu_read_unlock_bh(); |
| 1098 | 1334 | } else if (cb->args[IPSET_CB_PRIVATE]) { |
| 1099 | 1335 | t = (struct htable *)cb->args[IPSET_CB_PRIVATE]; |
| 1100 | 1336 | if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) { |
| 1101 | − /* Resizing didn't destroy the hash table */ | |
| 1102 | − pr_debug("Table destroy by dump: %p\n", t); | |
| 1337 | + pr_debug("Table destroy after resize " | |
| 1338 | + " by dump: %p\n", t); | |
| 1103 | 1339 | mtype_ahash_destroy(set, t, false); |
| 1104 | 1340 | } |
| 1105 | 1341 | cb->args[IPSET_CB_PRIVATE] = 0; |
| @@ -1141,8 +1377,7 @@ mtype_list(const struct ip_set *set, · 35 unmodified lines | ||
| 1141 | 1377 | if (!test_bit(i, n->used)) |
| 1142 | 1378 | continue; |
| 1143 | 1379 | e = ahash_data(n, i, set->dsize); |
| 1144 | − if (SET_WITH_TIMEOUT(set) && | |
| 1145 | − ip_set_timeout_expired(ext_timeout(e, set))) | |
| 1380 | + if (SET_ELEM_EXPIRED(set, e)) | |
| 1146 | 1381 | continue; |
| 1147 | 1382 | pr_debug("list hash %lu hbucket %p i %u, data %p\n", |
| 1148 | 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 | 1443 | .uref = mtype_uref, |
| 1209 | 1444 | .resize = mtype_resize, |
| 1210 | 1445 | .same_set = mtype_same_set, |
| 1446 | + .region_lock = true, | |
| 1211 | 1447 | }; |
| 1212 | 1448 | |
| 1213 | 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 | 1462 | size_t hsize; |
| 1227 | 1463 | struct htype *h; |
| 1228 | 1464 | struct htable *t; |
| 1465 | + u32 i; | |
| 1229 | 1466 | |
| 1230 | 1467 | pr_debug("Create set %s with family %s\n", |
| 1231 | 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 | 1531 | kfree(h); |
| 1295 | 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 | 1543 | h->maxelem = maxelem; |
| 1298 | 1544 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 1299 | 1545 | h->netmask = netmask; |
| @@ -1304,9 +1550,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, · 4 unmodified lines | ||
| 1304 | 1550 | get_random_bytes(&h->initval, sizeof(h->initval)); |
| 1305 | 1551 | |
| 1306 | 1552 | t->htable_bits = hbits; |
| 1553 | + t->maxelem = h->maxelem / ahash_numof_locks(hbits); | |
| 1307 | 1554 | RCU_INIT_POINTER(h->table, t); |
| 1308 | 1555 | |
| 1309 | − h->set = set; | |
| 1556 | + INIT_LIST_HEAD(&h->ad); | |
| 1310 | 1557 | set->data = h; |
| 1311 | 1558 | #ifndef IP_SET_PROTO_UNDEF |
| 1312 | 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 | 1576 | #ifndef IP_SET_PROTO_UNDEF |
| 1330 | 1577 | if (set->family == NFPROTO_IPV4) |
| 1331 | 1578 | #endif |
| 1332 | − IPSET_TOKEN(HTYPE, 4_gc_init)(set, | |
| 1333 | − IPSET_TOKEN(HTYPE, 4_gc)); | |
| 1579 | + IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc); | |
| 1334 | 1580 | #ifndef IP_SET_PROTO_UNDEF |
| 1335 | 1581 | else |
| 1336 | − IPSET_TOKEN(HTYPE, 6_gc_init)(set, | |
| 1337 | − IPSET_TOKEN(HTYPE, 6_gc)); | |
| 1582 | + IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc); | |
| 1338 | 1583 | #endif |
| 1339 | 1584 | } |
| 1340 | 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 | 1766 | static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, |
| 1767 | 1767 | const struct nft_set_elem *elem) |
| 1768 | 1768 | { |
| 1769 | − const u8 *data = (const u8 *)elem->key.val.data; | |
| 1770 | 1769 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1771 | 1770 | struct nft_pipapo_match *m = priv->clone; |
| 1771 | + struct nft_pipapo_elem *e = elem->priv; | |
| 1772 | 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 | 1777 | e = pipapo_get(net, set, data, 0); |
| 1776 | 1778 | if (IS_ERR(e)) |
| @@ -402,15 +402,6 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) · 401 unmodified lines | ||
| 402 | 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 | 405 | static struct xt_hashlimit_htable *htable_find_get(struct net *net, |
| 415 | 406 | const char *name, |
| 416 | 407 | u_int8_t family) |
| @@ -432,8 +423,13 @@ static void htable_put(struct xt_hashlimit_htable *hinfo) · 15 unmodified lines | ||
| 432 | 423 | { |
| 433 | 424 | if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) { |
| 434 | 425 | hlist_del(&hinfo->node); |
| 426 | + htable_remove_proc_entry(hinfo); | |
| 435 | 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 | 498 | err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr, |
| 499 | 499 | family->policy, validate, extack); |
| 500 | − if (err && parallel) { | |
| 501 | − kfree(attrbuf); | |
| 500 | + if (err) { | |
| 501 | + if (parallel) | |
| 502 | + kfree(attrbuf); | |
| 502 | 503 | return ERR_PTR(err); |
| 503 | 504 | } |
| 504 | 505 | return attrbuf; |
| @@ -186,6 +186,7 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act) · 185 unmodified lines | ||
| 186 | 186 | + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */ |
| 187 | 187 | + cookie_len /* TCA_ACT_COOKIE */ |
| 188 | 188 | + nla_total_size(0) /* TCA_ACT_STATS nested */ |
| 189 | + + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */ | |
| 189 | 190 | /* TCA_STATS_BASIC */ |
| 190 | 191 | + nla_total_size_64bit(sizeof(struct gnet_stats_basic)) |
| 191 | 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 | 512 | static int smc_connect_abort(struct smc_sock *smc, int reason_code, |
| 513 | 513 | int local_contact) |
| 514 | 514 | { |
| 515 | + bool is_smcd = smc->conn.lgr->is_smcd; | |
| 516 | + | |
| 515 | 517 | if (local_contact == SMC_FIRST_CONTACT) |
| 516 | − smc_lgr_forget(smc->conn.lgr); | |
| 517 | − if (smc->conn.lgr->is_smcd) | |
| 518 | + smc_lgr_cleanup_early(&smc->conn); | |
| 519 | + else | |
| 520 | + smc_conn_free(&smc->conn); | |
| 521 | + if (is_smcd) | |
| 518 | 522 | /* there is only one lgr role for SMC-D; use server lock */ |
| 519 | 523 | mutex_unlock(&smc_server_lgr_pending); |
| 520 | 524 | else |
| 521 | 525 | mutex_unlock(&smc_client_lgr_pending); |
| 522 | 526 | |
| 523 | − smc_conn_free(&smc->conn); | |
| 524 | 527 | smc->connect_nonblock = 0; |
| 525 | 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 | 1094 | if (newsmcsk->sk_state == SMC_INIT) |
| 1092 | 1095 | sock_put(&new_smc->sk); /* passive closing */ |
| 1093 | 1096 | newsmcsk->sk_state = SMC_CLOSED; |
| 1094 | − smc_conn_free(&new_smc->conn); | |
| 1095 | 1097 | |
| 1096 | 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 | 1105 | /* RDMA setup failed, switch back to TCP */ |
| 1104 | 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 | 1110 | if (reason_code < 0) { /* error, no fallback possible */ |
| 1107 | 1111 | smc_listen_out_err(new_smc); |
| 1108 | 1112 | return; |
| 1109 | 1113 | } |
| 1110 | − smc_conn_free(&new_smc->conn); | |
| 1111 | 1114 | smc_switch_to_fallback(new_smc); |
| 1112 | 1115 | new_smc->fallback_rsn = reason_code; |
| 1113 | 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 | 1173 | new_smc->conn.lgr->vlan_id, |
| 1171 | 1174 | new_smc->conn.lgr->smcd)) { |
| 1172 | 1175 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
| 1173 | − smc_lgr_forget(new_smc->conn.lgr); | |
| 1174 | − smc_conn_free(&new_smc->conn); | |
| 1176 | + smc_lgr_cleanup_early(&new_smc->conn); | |
| 1177 | + else | |
| 1178 | + smc_conn_free(&new_smc->conn); | |
| 1175 | 1179 | return SMC_CLC_DECL_SMCDNOTALK; |
| 1176 | 1180 | } |
| 1177 | 1181 | |
| 1178 | 1182 | /* Create send and receive buffers */ |
| 1179 | 1183 | if (smc_buf_create(new_smc, true)) { |
| 1180 | 1184 | if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
| 1181 | − smc_lgr_forget(new_smc->conn.lgr); | |
| 1182 | − smc_conn_free(&new_smc->conn); | |
| 1185 | + smc_lgr_cleanup_early(&new_smc->conn); | |
| 1186 | + else | |
| 1187 | + smc_conn_free(&new_smc->conn); | |
| 1183 | 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 | 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 | 177 | /* Send delete link, either as client to request the initiation |
| 166 | 178 | * of the DELETE LINK sequence from server; or as server to |
| 167 | 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 | 296 | struct smc_clc_msg_local; |
| 297 | 297 | |
| 298 | 298 | void smc_lgr_forget(struct smc_link_group *lgr); |
| 299 | +void smc_lgr_cleanup_early(struct smc_connection *conn); | |
| 299 | 300 | void smc_lgr_terminate(struct smc_link_group *lgr, bool soft); |
| 300 | 301 | void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); |
| 301 | 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 | 318 | void smc_conn_free(struct smc_connection *conn); |
| 318 | 319 | int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini); |
| 319 | −void smcd_conn_free(struct smc_connection *conn); | |
| 320 | 320 | void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr); |
| 321 | 321 | int smc_core_init(void); |
| 322 | 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 | 573 | struct smc_ib_device *smcibdev; |
| 574 | 574 | |
| 575 | 575 | smcibdev = ib_get_client_data(ibdev, &smc_ib_client); |
| 576 | + if (!smcibdev || smcibdev->ibdev != ibdev) | |
| 577 | + return; | |
| 576 | 578 | ib_set_client_data(ibdev, &smc_ib_client, NULL); |
| 577 | 579 | spin_lock(&smc_ib_devices.lock); |
| 578 | 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 | 682 | return 0; |
| 683 | 683 | } |
| 684 | 684 | |
| 685 | +#ifdef CONFIG_PROC_FS | |
| 685 | 686 | static void unix_show_fdinfo(struct seq_file *m, struct socket *sock) |
| 686 | 687 | { |
| 687 | 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 | 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 | 700 | static const struct proto_ops unix_stream_ops = { |
| 697 | 701 | .family = PF_UNIX, |
| @@ -451,6 +451,12 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk) · 450 unmodified lines | ||
| 451 | 451 | if (vsk->transport == new_transport) |
| 452 | 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 | 460 | vsk->transport->release(vsk); |
| 455 | 461 | vsock_deassign_transport(vsk); |
| 456 | 462 | } |
| @@ -753,20 +759,18 @@ static void __vsock_release(struct sock *sk, int level) · 296 unmodified lines | ||
| 753 | 759 | vsk = vsock_sk(sk); |
| 754 | 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 | 762 | /* When "level" is SINGLE_DEPTH_NESTING, use the nested |
| 765 | 763 | * version to avoid the warning "possible recursive locking |
| 766 | 764 | * detected". When "level" is 0, lock_sock_nested(sk, level) |
| 767 | 765 | * is the same as lock_sock(sk). |
| 768 | 766 | */ |
| 769 | 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 | 774 | sock_orphan(sk); |
| 771 | 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 | 527 | static void hvs_release(struct vsock_sock *vsk) |
| 528 | 528 | { |
| 529 | − struct sock *sk = sk_vsock(vsk); | |
| 530 | 529 | bool remove_sock; |
| 531 | 530 | |
| 532 | − lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | |
| 533 | 531 | remove_sock = hvs_close_lock_held(vsk); |
| 534 | − release_sock(sk); | |
| 535 | 532 | if (remove_sock) |
| 536 | 533 | vsock_remove_sock(vsk); |
| 537 | 534 | } |
| @@ -829,7 +829,6 @@ void virtio_transport_release(struct vsock_sock *vsk) · 828 unmodified lines | ||
| 829 | 829 | struct sock *sk = &vsk->sk; |
| 830 | 830 | bool remove_sock = true; |
| 831 | 831 | |
| 832 | − lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | |
| 833 | 832 | if (sk->sk_type == SOCK_STREAM) |
| 834 | 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 | 836 | list_del(&pkt->list); |
| 838 | 837 | virtio_transport_free_pkt(pkt); |
| 839 | 838 | } |
| 840 | − release_sock(sk); | |
| 841 | 839 | |
| 842 | 840 | if (remove_sock) |
| 843 | 841 | vsock_remove_sock(vsk); |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/netlink.h> |
| 21 | 21 | #include <linux/nospec.h> |
| 22 | 22 | #include <linux/etherdevice.h> |
| 23 | +#include <linux/if_vlan.h> | |
| 23 | 24 | #include <net/net_namespace.h> |
| 24 | 25 | #include <net/genetlink.h> |
| 25 | 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 | 4801 | err = nl80211_parse_he_obss_pd( |
| 4801 | 4802 | info->attrs[NL80211_ATTR_HE_OBSS_PD], |
| 4802 | 4803 | ¶ms.he_obss_pd); |
| 4803 | − if (err) | |
| 4804 | − return err; | |
| 4804 | + goto out; | |
| 4805 | 4805 | } |
| 4806 | 4806 | |
| 4807 | 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 | 4824 | wdev_unlock(wdev); |
| 4825 | 4825 | |
| 4826 | +out: | |
| 4826 | 4827 | kfree(params.acl); |
| 4827 | 4828 | |
| 4828 | 4829 | return err; |
| @@ -2276,7 +2276,7 @@ static void handle_channel_custom(struct wiphy *wiphy, · 2275 unmodified lines | ||
| 2276 | 2276 | break; |
| 2277 | 2277 | } |
| 2278 | 2278 | |
| 2279 | − if (IS_ERR(reg_rule)) { | |
| 2279 | + if (IS_ERR_OR_NULL(reg_rule)) { | |
| 2280 | 2280 | pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", |
| 2281 | 2281 | chan->center_freq); |
| 2282 | 2282 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { |
| @@ -13,11 +13,12 @@ · 12 unmodified lines | ||
| 13 | 13 | KSELFTEST_SKIP=4 |
| 14 | 14 | |
| 15 | 15 | # Available test groups: |
| 16 | +# - reported_issues: check for issues that were reported in the past | |
| 16 | 17 | # - correctness: check that packets match given entries, and only those |
| 17 | 18 | # - concurrency: attempt races between insertion, deletion and lookup |
| 18 | 19 | # - timeout: check that packets match entries until they expire |
| 19 | 20 | # - performance: estimate matching rate, compare with rbtree and hash baselines |
| 20 | −TESTS="correctness concurrency timeout" | |
| 21 | +TESTS="reported_issues correctness concurrency timeout" | |
| 21 | 22 | [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance" |
| 22 | 23 | |
| 23 | 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 | 26 | net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port |
| 26 | 27 | net_port_mac_proto_net" |
| 27 | 28 | |
| 29 | +# Reported bugs, also described by TYPE_ variables below | |
| 30 | +BUGS="flush_remove_add" | |
| 31 | + | |
| 28 | 32 | # List of possible paths to pktgen script from kernel tree for performance tests |
| 29 | 33 | PKTGEN_SCRIPT_PATHS=" |
| 30 | 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 | 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 | 340 | # Set template for all tests, types and rules are filled in depending on test |
| 331 | 341 | set_template=' |
| 332 | 342 | flush ruleset |
| @@ -440,6 +450,8 @@ setup_set() { · 107 unmodified lines | ||
| 440 | 450 | |
| 441 | 451 | # Check that at least one of the needed tools is available |
| 442 | 452 | check_tools() { |
| 453 | + [ -z "${tools}" ] && return 0 | |
| 454 | + | |
| 443 | 455 | __tools= |
| 444 | 456 | for tool in ${tools}; do |
| 445 | 457 | if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \ |
| @@ -1025,7 +1037,7 @@ format_noconcat() { · 579 unmodified lines | ||
| 1025 | 1037 | add() { |
| 1026 | 1038 | if ! nft add element inet filter test "${1}"; then |
| 1027 | 1039 | err "Failed to add ${1} given ruleset:" |
| 1028 | − err "$(nft list ruleset -a)" | |
| 1040 | + err "$(nft -a list ruleset)" | |
| 1029 | 1041 | return 1 |
| 1030 | 1042 | fi |
| 1031 | 1043 | } |
| @@ -1045,7 +1057,7 @@ add_perf() { · 13 unmodified lines | ||
| 1045 | 1057 | add_perf_norange() { |
| 1046 | 1058 | if ! nft add element netdev perf norange "${1}"; then |
| 1047 | 1059 | err "Failed to add ${1} given ruleset:" |
| 1048 | − err "$(nft list ruleset -a)" | |
| 1060 | + err "$(nft -a list ruleset)" | |
| 1049 | 1061 | return 1 |
| 1050 | 1062 | fi |
| 1051 | 1063 | } |
| @@ -1054,7 +1066,7 @@ add_perf_norange() { · 2 unmodified lines | ||
| 1054 | 1066 | add_perf_noconcat() { |
| 1055 | 1067 | if ! nft add element netdev perf noconcat "${1}"; then |
| 1056 | 1068 | err "Failed to add ${1} given ruleset:" |
| 1057 | − err "$(nft list ruleset -a)" | |
| 1069 | + err "$(nft -a list ruleset)" | |
| 1058 | 1070 | return 1 |
| 1059 | 1071 | fi |
| 1060 | 1072 | } |
| @@ -1063,7 +1075,7 @@ add_perf_noconcat() { · 2 unmodified lines | ||
| 1063 | 1075 | del() { |
| 1064 | 1076 | if ! nft delete element inet filter test "${1}"; then |
| 1065 | 1077 | err "Failed to delete ${1} given ruleset:" |
| 1066 | − err "$(nft list ruleset -a)" | |
| 1078 | + err "$(nft -a list ruleset)" | |
| 1067 | 1079 | return 1 |
| 1068 | 1080 | fi |
| 1069 | 1081 | } |
| @@ -1134,7 +1146,7 @@ send_match() { · 64 unmodified lines | ||
| 1134 | 1146 | err " $(for f in ${src}; do |
| 1135 | 1147 | eval format_\$f "${2}"; printf ' '; done)" |
| 1136 | 1148 | err "should have matched ruleset:" |
| 1137 | − err "$(nft list ruleset -a)" | |
| 1149 | + err "$(nft -a list ruleset)" | |
| 1138 | 1150 | return 1 |
| 1139 | 1151 | fi |
| 1140 | 1152 | nft reset counter inet filter test >/dev/null |
| @@ -1160,7 +1172,7 @@ send_nomatch() { · 19 unmodified lines | ||
| 1160 | 1172 | err " $(for f in ${src}; do |
| 1161 | 1173 | eval format_\$f "${2}"; printf ' '; done)" |
| 1162 | 1174 | err "should not have matched ruleset:" |
| 1163 | − err "$(nft list ruleset -a)" | |
| 1175 | + err "$(nft -a list ruleset)" | |
| 1164 | 1176 | return 1 |
| 1165 | 1177 | fi |
| 1166 | 1178 | } |
| @@ -1430,6 +1442,23 @@ test_performance() { · 263 unmodified lines | ||
| 1430 | 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 | 1462 | # Run everything in a separate network namespace |
| 1434 | 1463 | [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } |
| 1435 | 1464 | tmp="$(mktemp)" |
| @@ -1438,9 +1467,15 @@ trap cleanup EXIT · 2 unmodified lines | ||
| 1438 | 1467 | # Entry point for test runs |
| 1439 | 1468 | passed=0 |
| 1440 | 1469 | for name in ${TESTS}; do |
| 1441 | − printf "TEST: %s\n" "${name}" | |
| 1442 | − for type in ${TYPES}; do | |
| 1443 | − eval desc=\$TYPE_"${type}" | |
| 1470 | + printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')" | |
| 1471 | + if [ "${name}" = "reported_issues" ]; then | |
| 1472 | + SUBTESTS="${BUGS}" | |
| 1473 | + else | |
| 1474 | + SUBTESTS="${TYPES}" | |
| 1475 | + fi | |
| 1476 | + | |
| 1477 | + for subtest in ${SUBTESTS}; do | |
| 1478 | + eval desc=\$TYPE_"${subtest}" | |
| 1444 | 1479 | IFS=' |
| 1445 | 1480 | ' |
| 1446 | 1481 | for __line in ${desc}; do |