diff options
39 files changed, 580 insertions, 563 deletions
diff --git a/Documentation/networking/policy-routing.txt b/Documentation/networking/policy-routing.txt deleted file mode 100644 index 36f6936d7f21..000000000000 --- a/Documentation/networking/policy-routing.txt +++ /dev/null @@ -1,150 +0,0 @@ -Classes -------- - - "Class" is a complete routing table in common sense. - I.e. it is tree of nodes (destination prefix, tos, metric) - with attached information: gateway, device etc. - This tree is looked up as specified in RFC1812 5.2.4.3 - 1. Basic match - 2. Longest match - 3. Weak TOS. - 4. Metric. (should not be in kernel space, but they are) - 5. Additional pruning rules. (not in kernel space). - - We have two special type of nodes: - REJECT - abort route lookup and return an error value. - THROW - abort route lookup in this class. - - - Currently the number of classes is limited to 255 - (0 is reserved for "not specified class") - - Three classes are builtin: - - RT_CLASS_LOCAL=255 - local interface addresses, - broadcasts, nat addresses. - - RT_CLASS_MAIN=254 - all normal routes are put there - by default. - - RT_CLASS_DEFAULT=253 - if ip_fib_model==1, then - normal default routes are put there, if ip_fib_model==2 - all gateway routes are put there. - - -Rules ------ - Rule is a record of (src prefix, src interface, tos, dst prefix) - with attached information. - - Rule types: - RTP_ROUTE - lookup in attached class - RTP_NAT - lookup in attached class and if a match is found, - translate packet source address. - RTP_MASQUERADE - lookup in attached class and if a match is found, - masquerade packet as sourced by us. - RTP_DROP - silently drop the packet. - RTP_REJECT - drop the packet and send ICMP NET UNREACHABLE. - RTP_PROHIBIT - drop the packet and send ICMP COMM. ADM. PROHIBITED. - - Rule flags: - RTRF_LOG - log route creations. - RTRF_VALVE - One way route (used with masquerading) - -Default setup: - -root@amber:/pub/ip-routing # iproute -r -Kernel routing policy rules -Pref Source Destination TOS Iface Cl - 0 default default 00 * 255 - 254 default default 00 * 254 - 255 default default 00 * 253 - - -Lookup algorithm ----------------- - - We scan rules list, and if a rule is matched, apply it. - If a route is found, return it. - If it is not found or a THROW node was matched, continue - to scan rules. - -Applications ------------- - -1. Just ignore classes. All the routes are put into MAIN class - (and/or into DEFAULT class). - - HOWTO: iproute add PREFIX [ tos TOS ] [ gw GW ] [ dev DEV ] - [ metric METRIC ] [ reject ] ... (look at iproute utility) - - or use route utility from current net-tools. - -2. Opposite case. Just forget all that you know about routing - tables. Every rule is supplied with its own gateway, device - info. record. This approach is not appropriate for automated - route maintenance, but it is ideal for manual configuration. - - HOWTO: iproute addrule [ from PREFIX ] [ to PREFIX ] [ tos TOS ] - [ dev INPUTDEV] [ pref PREFERENCE ] route [ gw GATEWAY ] - [ dev OUTDEV ] ..... - - Warning: As of now the size of the routing table in this - approach is limited to 256. If someone likes this model, I'll - relax this limitation. - -3. OSPF classes (see RFC1583, RFC1812 E.3.3) - Very clean, stable and robust algorithm for OSPF routing - domains. Unfortunately, it is not widely used in the Internet. - - Proposed setup: - 255 local addresses - 254 interface routes - 253 ASE routes with external metric - 252 ASE routes with internal metric - 251 inter-area routes - 250 intra-area routes for 1st area - 249 intra-area routes for 2nd area - etc. - - Rules: - iproute addrule class 253 - iproute addrule class 252 - iproute addrule class 251 - iproute addrule to a-prefix-for-1st-area class 250 - iproute addrule to another-prefix-for-1st-area class 250 - ... - iproute addrule to a-prefix-for-2nd-area class 249 - ... - - Area classes must be terminated with reject record. - iproute add default reject class 250 - iproute add default reject class 249 - ... - -4. The Variant Router Requirements Algorithm (RFC1812 E.3.2) - Create 16 classes for different TOS values. - It is a funny, but pretty useless algorithm. - I listed it just to show the power of new routing code. - -5. All the variety of combinations...... - - -GATED ------ - - Gated does not understand classes, but it will work - happily in MAIN+DEFAULT. All policy routes can be set - and maintained manually. - -IMPORTANT NOTE --------------- - route.c has a compilation time switch CONFIG_IP_LOCAL_RT_POLICY. - If it is set, locally originated packets are routed - using all the policy list. This is not very convenient and - pretty ambiguous when used with NAT and masquerading. - I set it to FALSE by default. - - -Alexey Kuznetov diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts index dd3525a0f06a..9bd9a0e90034 100644 --- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts +++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts @@ -106,7 +106,7 @@ &emac { phy-handle = <&int_mii_phy>; - phy-mode = "mii"; + phy-mode = "internal"; allwinner,leds-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts index 78f6c24952dd..5c5ba806e2f1 100644 --- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts +++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts @@ -49,7 +49,7 @@ &emac { phy-handle = <&int_mii_phy>; - phy-mode = "mii"; + phy-mode = "internal"; allwinner,leds-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts index cedd326b6089..77c861deb658 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts @@ -111,7 +111,7 @@ &emac { phy-handle = <&int_mii_phy>; - phy-mode = "mii"; + phy-mode = "internal"; allwinner,leds-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts index 6880268e8b87..27e7ef4e42f2 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts @@ -100,7 +100,7 @@ &emac { phy-handle = <&int_mii_phy>; - phy-mode = "mii"; + phy-mode = "internal"; allwinner,leds-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts index 52e65755c51a..fecebb43506a 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts @@ -112,7 +112,7 @@ &emac { phy-handle = <&int_mii_phy>; - phy-mode = "mii"; + phy-mode = "internal"; allwinner,leds-active-low; status = "okay"; }; diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 8ca683396fcc..a12d603d41c6 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -464,7 +464,7 @@ const struct bond_opt_value *bond_opt_get_val(unsigned int option, u64 val) /* Searches for a value in opt's values[] table which matches the flagmask */ static const struct bond_opt_value *bond_opt_get_flags(const struct bond_option *opt, - u32 flagmask) + u32 flagmask) { int i; @@ -744,14 +744,14 @@ static int bond_option_mode_set(struct bonding *bond, const struct bond_opt_value *newval) { if (!bond_mode_uses_arp(newval->value) && bond->params.arp_interval) { - netdev_info(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n", - newval->string); + netdev_dbg(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n", + newval->string); /* disable arp monitoring */ bond->params.arp_interval = 0; /* set miimon to default value */ bond->params.miimon = BOND_DEFAULT_MIIMON; - netdev_info(bond->dev, "Setting MII monitoring interval to %d\n", - bond->params.miimon); + netdev_dbg(bond->dev, "Setting MII monitoring interval to %d\n", + bond->params.miimon); } /* don't cache arp_validate between modes */ @@ -794,7 +794,7 @@ static int bond_option_active_slave_set(struct bonding *bond, block_netpoll_tx(); /* check to see if we are clearing active */ if (!slave_dev) { - netdev_info(bond->dev, "Clearing current active slave\n"); + netdev_dbg(bond->dev, "Clearing current active slave\n"); RCU_INIT_POINTER(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { @@ -805,13 +805,13 @@ static int bond_option_active_slave_set(struct bonding *bond, if (new_active == old_active) { /* do nothing */ - netdev_info(bond->dev, "%s is already the current active slave\n", - new_active->dev->name); + netdev_dbg(bond->dev, "%s is already the current active slave\n", + new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && bond_slave_is_up(new_active)) { - netdev_info(bond->dev, "Setting %s as active slave\n", - new_active->dev->name); + netdev_dbg(bond->dev, "Setting %s as active slave\n", + new_active->dev->name); bond_change_active_slave(bond, new_active); } else { netdev_err(bond->dev, "Could not set %s as active slave; either %s is down or the link is down\n", @@ -833,17 +833,17 @@ static int bond_option_active_slave_set(struct bonding *bond, static int bond_option_miimon_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting MII monitoring interval to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting MII monitoring interval to %llu\n", + newval->value); bond->params.miimon = newval->value; if (bond->params.updelay) - netdev_info(bond->dev, "Note: Updating updelay (to %d) since it is a multiple of the miimon value\n", - bond->params.updelay * bond->params.miimon); + netdev_dbg(bond->dev, "Note: Updating updelay (to %d) since it is a multiple of the miimon value\n", + bond->params.updelay * bond->params.miimon); if (bond->params.downdelay) - netdev_info(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n", - bond->params.downdelay * bond->params.miimon); + netdev_dbg(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n", + bond->params.downdelay * bond->params.miimon); if (newval->value && bond->params.arp_interval) { - netdev_info(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n"); + netdev_dbg(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n"); bond->params.arp_interval = 0; if (bond->params.arp_validate) bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; @@ -885,8 +885,8 @@ static int bond_option_updelay_set(struct bonding *bond, bond->params.miimon); } bond->params.updelay = value / bond->params.miimon; - netdev_info(bond->dev, "Setting up delay to %d\n", - bond->params.updelay * bond->params.miimon); + netdev_dbg(bond->dev, "Setting up delay to %d\n", + bond->params.updelay * bond->params.miimon); return 0; } @@ -907,8 +907,8 @@ static int bond_option_downdelay_set(struct bonding *bond, bond->params.miimon); } bond->params.downdelay = value / bond->params.miimon; - netdev_info(bond->dev, "Setting down delay to %d\n", - bond->params.downdelay * bond->params.miimon); + netdev_dbg(bond->dev, "Setting down delay to %d\n", + bond->params.downdelay * bond->params.miimon); return 0; } @@ -916,8 +916,8 @@ static int bond_option_downdelay_set(struct bonding *bond, static int bond_option_use_carrier_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting use_carrier to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting use_carrier to %llu\n", + newval->value); bond->params.use_carrier = newval->value; return 0; @@ -930,16 +930,16 @@ static int bond_option_use_carrier_set(struct bonding *bond, static int bond_option_arp_interval_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting ARP monitoring interval to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting ARP monitoring interval to %llu\n", + newval->value); bond->params.arp_interval = newval->value; if (newval->value) { if (bond->params.miimon) { - netdev_info(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n"); + netdev_dbg(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n"); bond->params.miimon = 0; } if (!bond->params.arp_targets[0]) - netdev_info(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n"); + netdev_dbg(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n"); } if (bond->dev->flags & IFF_UP) { /* If the interface is up, we may need to fire off @@ -1000,7 +1000,7 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target) return -EINVAL; } - netdev_info(bond->dev, "Adding ARP target %pI4\n", &target); + netdev_dbg(bond->dev, "Adding ARP target %pI4\n", &target); _bond_options_arp_ip_target_set(bond, ind, target, jiffies); @@ -1036,7 +1036,7 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target) if (ind == 0 && !targets[1] && bond->params.arp_interval) netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n"); - netdev_info(bond->dev, "Removing ARP target %pI4\n", &target); + netdev_dbg(bond->dev, "Removing ARP target %pI4\n", &target); bond_for_each_slave(bond, slave, iter) { targets_rx = slave->target_last_arp_rx; @@ -1088,8 +1088,8 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond, static int bond_option_arp_validate_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting arp_validate to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting arp_validate to %s (%llu)\n", + newval->string, newval->value); if (bond->dev->flags & IFF_UP) { if (!newval->value) @@ -1105,8 +1105,8 @@ static int bond_option_arp_validate_set(struct bonding *bond, static int bond_option_arp_all_targets_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting arp_all_targets to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting arp_all_targets to %s (%llu)\n", + newval->string, newval->value); bond->params.arp_all_targets = newval->value; return 0; @@ -1126,7 +1126,7 @@ static int bond_option_primary_set(struct bonding *bond, *p = '\0'; /* check to see if we are clearing primary */ if (!strlen(primary)) { - netdev_info(bond->dev, "Setting primary slave to None\n"); + netdev_dbg(bond->dev, "Setting primary slave to None\n"); RCU_INIT_POINTER(bond->primary_slave, NULL); memset(bond->params.primary, 0, sizeof(bond->params.primary)); bond_select_active_slave(bond); @@ -1135,8 +1135,8 @@ static int bond_option_primary_set(struct bonding *bond, bond_for_each_slave(bond, slave, iter) { if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) { - netdev_info(bond->dev, "Setting %s as primary slave\n", - slave->dev->name); + netdev_dbg(bond->dev, "Setting %s as primary slave\n", + slave->dev->name); rcu_assign_pointer(bond->primary_slave, slave); strcpy(bond->params.primary, slave->dev->name); bond_select_active_slave(bond); @@ -1145,15 +1145,15 @@ static int bond_option_primary_set(struct bonding *bond, } if (rtnl_dereference(bond->primary_slave)) { - netdev_info(bond->dev, "Setting primary slave to None\n"); + netdev_dbg(bond->dev, "Setting primary slave to None\n"); RCU_INIT_POINTER(bond->primary_slave, NULL); bond_select_active_slave(bond); } strncpy(bond->params.primary, primary, IFNAMSIZ); bond->params.primary[IFNAMSIZ - 1] = 0; - netdev_info(bond->dev, "Recording %s as primary, but it has not been enslaved to %s yet\n", - primary, bond->dev->name); + netdev_dbg(bond->dev, "Recording %s as primary, but it has not been enslaved to %s yet\n", + primary, bond->dev->name); out: unblock_netpoll_tx(); @@ -1164,8 +1164,8 @@ out: static int bond_option_primary_reselect_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting primary_reselect to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting primary_reselect to %s (%llu)\n", + newval->string, newval->value); bond->params.primary_reselect = newval->value; block_netpoll_tx(); @@ -1178,8 +1178,8 @@ static int bond_option_primary_reselect_set(struct bonding *bond, static int bond_option_fail_over_mac_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting fail_over_mac to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting fail_over_mac to %s (%llu)\n", + newval->string, newval->value); bond->params.fail_over_mac = newval->value; return 0; @@ -1188,8 +1188,8 @@ static int bond_option_fail_over_mac_set(struct bonding *bond, static int bond_option_xmit_hash_policy_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting xmit hash policy to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting xmit hash policy to %s (%llu)\n", + newval->string, newval->value); bond->params.xmit_policy = newval->value; return 0; @@ -1198,8 +1198,8 @@ static int bond_option_xmit_hash_policy_set(struct bonding *bond, static int bond_option_resend_igmp_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting resend_igmp to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting resend_igmp to %llu\n", + newval->value); bond->params.resend_igmp = newval->value; return 0; @@ -1237,8 +1237,8 @@ static int bond_option_all_slaves_active_set(struct bonding *bond, static int bond_option_min_links_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting min links value to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting min links value to %llu\n", + newval->value); bond->params.min_links = newval->value; bond_set_carrier(bond); @@ -1256,6 +1256,8 @@ static int bond_option_lp_interval_set(struct bonding *bond, static int bond_option_pps_set(struct bonding *bond, const struct bond_opt_value *newval) { + netdev_dbg(bond->dev, "Setting packets per slave to %llu\n", + newval->value); bond->params.packets_per_slave = newval->value; if (newval->value > 0) { bond->params.reciprocal_packets_per_slave = @@ -1274,8 +1276,8 @@ static int bond_option_pps_set(struct bonding *bond, static int bond_option_lacp_rate_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting LACP rate to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting LACP rate to %s (%llu)\n", + newval->string, newval->value); bond->params.lacp_fast = newval->value; bond_3ad_update_lacp_rate(bond); @@ -1285,8 +1287,8 @@ static int bond_option_lacp_rate_set(struct bonding *bond, static int bond_option_ad_select_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting ad_select to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting ad_select to %s (%llu)\n", + newval->string, newval->value); bond->params.ad_select = newval->value; return 0; @@ -1347,7 +1349,7 @@ out: return ret; err_no_cmd: - netdev_info(bond->dev, "invalid input for queue_id set\n"); + netdev_dbg(bond->dev, "invalid input for queue_id set\n"); ret = -EPERM; goto out; @@ -1369,20 +1371,20 @@ static int bond_option_slaves_set(struct bonding *bond, dev = __dev_get_by_name(dev_net(bond->dev), ifname); if (!dev) { - netdev_info(bond->dev, "interface %s does not exist!\n", - ifname); + netdev_dbg(bond->dev, "interface %s does not exist!\n", + ifname); ret = -ENODEV; goto out; } switch (command[0]) { case '+': - netdev_info(bond->dev, "Adding slave %s\n", dev->name); + netdev_dbg(bond->dev, "Adding slave %s\n", dev->name); ret = bond_enslave(bond->dev, dev); break; case '-': - netdev_info(bond->dev, "Removing slave %s\n", dev->name); + netdev_dbg(bond->dev, "Removing slave %s\n", dev->name); ret = bond_release(bond->dev, dev); break; @@ -1402,8 +1404,8 @@ err_no_cmd: static int bond_option_tlb_dynamic_lb_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting dynamic-lb to %s (%llu)\n", - newval->string, newval->value); + netdev_dbg(bond->dev, "Setting dynamic-lb to %s (%llu)\n", + newval->string, newval->value); bond->params.tlb_dynamic_lb = newval->value; return 0; @@ -1412,8 +1414,8 @@ static int bond_option_tlb_dynamic_lb_set(struct bonding *bond, static int bond_option_ad_actor_sys_prio_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting ad_actor_sys_prio to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting ad_actor_sys_prio to %llu\n", + newval->value); bond->params.ad_actor_sys_prio = newval->value; bond_3ad_update_ad_actor_settings(bond); @@ -1442,7 +1444,7 @@ static int bond_option_ad_actor_system_set(struct bonding *bond, if (!is_valid_ether_addr(mac)) goto err; - netdev_info(bond->dev, "Setting ad_actor_system to %pM\n", mac); + netdev_dbg(bond->dev, "Setting ad_actor_system to %pM\n", mac); ether_addr_copy(bond->params.ad_actor_system, mac); bond_3ad_update_ad_actor_settings(bond); @@ -1456,8 +1458,8 @@ err: static int bond_option_ad_user_port_key_set(struct bonding *bond, const struct bond_opt_value *newval) { - netdev_info(bond->dev, "Setting ad_user_port_key to %llu\n", - newval->value); + netdev_dbg(bond->dev, "Setting ad_user_port_key to %llu\n", + newval->value); bond->params.ad_user_port_key = newval->value; return 0; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 7e913d8331c3..8c9986f3fc01 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2252,7 +2252,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, if (atl1c_tx_map(adapter, skb, tpd, type) < 0) { netif_info(adapter, tx_done, adapter->netdev, - "tx-skb droppted due to dma error\n"); + "tx-skb dropped due to dma error\n"); /* roll back tpd/buffer */ atl1c_tx_rollback(adapter, tpd, type); dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 573755b0a51b..49b80da51ba7 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -227,15 +227,14 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic) nic->speed = mbx.link_status.speed; nic->mac_type = mbx.link_status.mac_type; if (nic->link_up) { - netdev_info(nic->netdev, "%s: Link is Up %d Mbps %s\n", - nic->netdev->name, nic->speed, + netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n", + nic->speed, nic->duplex == DUPLEX_FULL ? - "Full duplex" : "Half duplex"); + "Full" : "Half"); netif_carrier_on(nic->netdev); netif_tx_start_all_queues(nic->netdev); } else { - netdev_info(nic->netdev, "%s: Link is Down\n", - nic->netdev->name); + netdev_info(nic->netdev, "Link is Down\n"); netif_carrier_off(nic->netdev); netif_tx_stop_all_queues(nic->netdev); } @@ -721,8 +720,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, return; if (netif_msg_pktdata(nic)) { - netdev_info(nic->netdev, "%s: skb 0x%p, len=%d\n", netdev->name, - skb, skb->len); + netdev_info(nic->netdev, "skb 0x%p, len=%d\n", skb, skb->len); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); } @@ -854,10 +852,8 @@ done: netif_tx_wake_queue(txq); nic = nic->pnicvf; this_cpu_inc(nic->drv_stats->txq_wake); - if (netif_msg_tx_err(nic)) - netdev_warn(netdev, - "%s: Transmit queue wakeup SQ%d\n", - netdev->name, txq_idx); + netif_warn(nic, tx_err, netdev, + "Transmit queue wakeup SQ%d\n", txq_idx); } } @@ -928,9 +924,8 @@ static void nicvf_handle_qs_err(unsigned long data) static void nicvf_dump_intr_status(struct nicvf *nic) { - if (netif_msg_intr(nic)) - netdev_info(nic->netdev, "%s: interrupt status 0x%llx\n", - nic->netdev->name, nicvf_reg_read(nic, NIC_VF_INT)); + netif_info(nic, intr, nic->netdev, "interrupt status 0x%llx\n", + nicvf_reg_read(nic, NIC_VF_INT)); } static irqreturn_t nicvf_misc_intr_handler(int irq, void *nicvf_irq) @@ -1212,10 +1207,8 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev) netif_tx_wake_queue(txq); } else { this_cpu_inc(nic->drv_stats->txq_stop); - if (netif_msg_tx_err(nic)) - netdev_warn(netdev, - "%s: Transmit ring full, stopping SQ%d\n", - netdev->name, qid); + netif_warn(nic, tx_err, netdev, + "Transmit ring full, stopping SQ%d\n", qid); } return NETDEV_TX_BUSY; } @@ -1600,9 +1593,7 @@ static void nicvf_tx_timeout(struct net_device *dev) { struct nicvf *nic = netdev_priv(dev); - if (netif_msg_tx_err(nic)) - netdev_warn(dev, "%s: Transmit timed out, resetting\n", - dev->name); + netif_warn(nic, tx_err, dev, "Transmit timed out, resetting\n"); this_cpu_inc(nic->drv_stats->tx_timeout); schedule_work(&nic->reset_task); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 2b181762ad49..d4496e9afcdf 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1811,11 +1811,9 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx) /* Check for errors in the receive cmp.queue entry */ int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx) { - if (netif_msg_rx_err(nic)) - netdev_err(nic->netdev, - "%s: RX error CQE err_level 0x%x err_opcode 0x%x\n", - nic->netdev->name, - cqe_rx->err_level, cqe_rx->err_opcode); + netif_err(nic, rx_err, nic->netdev, + "RX error CQE err_level 0x%x err_opcode 0x%x\n", + cqe_rx->err_level, cqe_rx->err_opcode); switch (cqe_rx->err_opcode) { case CQ_RX_ERROP_RE_PARTIAL: diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index c1af47e45d3f..674773b28b2e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -3280,7 +3280,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) mlx4_dbg(dev, - "updating vf %d port %d no link state HW enforcment\n", + "updating vf %d port %d no link state HW enforcement\n", vf, port); return 0; } diff --git a/drivers/net/ethernet/netronome/Kconfig b/drivers/net/ethernet/netronome/Kconfig index 0d5a7b9203a4..0e331e2f685a 100644 --- a/drivers/net/ethernet/netronome/Kconfig +++ b/drivers/net/ethernet/netronome/Kconfig @@ -25,6 +25,16 @@ config NFP cards working as a advanced Ethernet NIC. It works with both SR-IOV physical and virtual functions. +config NFP_APP_FLOWER + bool "NFP4000/NFP6000 TC Flower offload support" + depends on NFP + depends on NET_SWITCHDEV + ---help--- + Enable driver support for TC Flower offload on NFP4000 and NFP6000. + Say Y, if you are planning to make use of TC Flower offload + either directly, with Open vSwitch, or any other way. Note that + TC Flower offload requires specific FW to work. + config NFP_DEBUG bool "Debug support for Netronome(R) NFP4000/NFP6000 NIC drivers" depends on NFP diff --git a/drivers/net/ethernet/netronome/nfp/Makefile b/drivers/net/ethernet/netronome/nfp/Makefile index 10b556b2c59d..43bdbc228969 100644 --- a/drivers/net/ethernet/netronome/nfp/Makefile +++ b/drivers/net/ethernet/netronome/nfp/Makefile @@ -27,10 +27,14 @@ nfp-objs := \ nfp_port.o \ bpf/main.o \ bpf/offload.o \ - flower/cmsg.o \ - flower/main.o \ nic/main.o +ifeq ($(CONFIG_NFP_APP_FLOWER),y) +nfp-objs += \ + flower/cmsg.o \ + flower/main.o +endif + ifeq ($(CONFIG_BPF_SYSCALL),y) nfp-objs += \ bpf/verifier.o \ diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index 7761be436726..916a6196d2ba 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -79,9 +79,8 @@ nfp_flower_cmsg_alloc(struct nfp_app *app, unsigned int size, return skb; } -int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok) +int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok) { - struct nfp_repr *repr = netdev_priv(netdev); struct nfp_flower_cmsg_portmod *msg; struct sk_buff *skb; @@ -94,7 +93,7 @@ int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok) msg->portnum = cpu_to_be32(repr->dst->u.port_info.port_id); msg->reserved = 0; msg->info = carrier_ok; - msg->mtu = cpu_to_be16(netdev->mtu); + msg->mtu = cpu_to_be16(repr->netdev->mtu); nfp_ctrl_tx(repr->app->ctrl, skb); diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 2eeddada7f4d..c10ae7631941 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -110,7 +110,7 @@ nfp_flower_cmsg_pcie_port(u8 nfp_pcie, enum nfp_flower_cmsg_port_vnic_type type, NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT); } -int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok); +int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok); void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb); #endif diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 8e5ca6b4bb33..ab68a8f58862 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -104,51 +104,30 @@ nfp_flower_repr_get(struct nfp_app *app, u32 port_id) return reprs->reprs[port]; } -static void -nfp_flower_repr_netdev_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) -{ - struct nfp_repr *repr = netdev_priv(netdev); - enum nfp_repr_type type; - u32 port_id; - u8 port = 0; - - port_id = repr->dst->u.port_info.port_id; - type = nfp_flower_repr_get_type_and_port(repr->app, port_id, &port); - nfp_repr_get_stats64(repr->app, type, port, stats); -} - -static int nfp_flower_repr_netdev_open(struct net_device *netdev) +static int +nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr) { int err; - err = nfp_flower_cmsg_portmod(netdev, true); + err = nfp_flower_cmsg_portmod(repr, true); if (err) return err; - netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); + netif_carrier_on(repr->netdev); + netif_tx_wake_all_queues(repr->netdev); return 0; } -static int nfp_flower_repr_netdev_stop(struct net_device *netdev) +static int +nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr) { - netif_carrier_off(netdev); - netif_tx_disable(netdev); + netif_carrier_off(repr->netdev); + netif_tx_disable(repr->netdev); - return nfp_flower_cmsg_portmod(netdev, false); + return nfp_flower_cmsg_portmod(repr, false); } -static const struct net_device_ops nfp_flower_repr_netdev_ops = { - .ndo_open = nfp_flower_repr_netdev_open, - .ndo_stop = nfp_flower_repr_netdev_stop, - .ndo_start_xmit = nfp_repr_xmit, - .ndo_get_stats64 = nfp_flower_repr_netdev_get_stats64, - .ndo_has_offload_stats = nfp_repr_has_offload_stats, - .ndo_get_offload_stats = nfp_repr_get_offload_stats, -}; - static void nfp_flower_sriov_disable(struct nfp_app *app) { nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); @@ -162,14 +141,19 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp); struct nfp_flower_priv *priv = app->priv; struct nfp_reprs *reprs, *old_reprs; + enum nfp_port_type port_type; const u8 queue = 0; int i, err; + port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT : + NFP_PORT_VF_PORT; + reprs = nfp_reprs_alloc(cnt); if (!reprs) return -ENOMEM; for (i = 0; i < cnt; i++) { + struct nfp_port *port; u32 port_id; reprs->reprs[i] = nfp_repr_alloc(app); @@ -178,15 +162,24 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, goto err_reprs_clean; } + port = nfp_port_alloc(app, port_type, reprs->reprs[i]); + if (repr_type == NFP_REPR_TYPE_PF) { + port->pf_id = i; + } else { + port->pf_id = 0; /* For now we only support 1 PF */ + port->vf_id = i; + } + eth_hw_addr_random(reprs->reprs[i]); port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type, i, queue); err = nfp_repr_init(app, reprs->reprs[i], - &nfp_flower_repr_netdev_ops, - port_id, NULL, priv->nn->dp.netdev); - if (err) + port_id, port, priv->nn->dp.netdev); + if (err) { + nfp_port_free(port); goto err_reprs_clean; + } nfp_info(app->cpp, "%s%d Representor(%s) created\n", repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i, @@ -260,7 +253,6 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port); err = nfp_repr_init(app, reprs->reprs[phys_port], - &nfp_flower_repr_netdev_ops, cmsg_port_id, port, priv->nn->dp.netdev); if (err) { nfp_port_free(port); @@ -296,26 +288,16 @@ static int nfp_flower_start(struct nfp_app *app) NFP_REPR_TYPE_PF, 1); } -static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn) -{ - kfree(app->priv); - app->priv = NULL; -} - static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id) { - struct nfp_flower_priv *priv; + struct nfp_flower_priv *priv = app->priv; if (id > 0) { nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n"); goto err_invalid_port; } - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - app->priv = priv; priv->nn = nn; eth_hw_addr_random(nn->dp.netdev); @@ -347,9 +329,19 @@ static int nfp_flower_init(struct nfp_app *app) return -EINVAL; } + app->priv = kzalloc(sizeof(struct nfp_flower_priv), GFP_KERNEL); + if (!app->priv) + return -ENOMEM; + return 0; } +static void nfp_flower_clean(struct nfp_app *app) +{ + kfree(app->priv); + app->priv = NULL; +} + const struct nfp_app_type app_flower = { .id = NFP_APP_FLOWER_NIC, .name = "flower", @@ -358,9 +350,12 @@ const struct nfp_app_type app_flower = { .extra_cap = nfp_flower_extra_cap, .init = nfp_flower_init, + .clean = nfp_flower_clean, .vnic_init = nfp_flower_vnic_init, - .vnic_clean = nfp_flower_vnic_clean, + + .repr_open = nfp_flower_repr_netdev_open, + .repr_stop = nfp_flower_repr_netdev_stop, .start = nfp_flower_start, .stop = nfp_flower_stop, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c index 5620de05c996..c704c022574f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c @@ -43,7 +43,9 @@ static const struct nfp_app_type *apps[] = { &app_nic, &app_bpf, +#ifdef CONFIG_NFP_APP_FLOWER &app_flower, +#endif }; const char *nfp_app_mip_name(struct nfp_app *app) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h index ae2d02753d1a..5d714e10d9a9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h @@ -47,6 +47,7 @@ struct sk_buff; struct nfp_app; struct nfp_cpp; struct nfp_pf; +struct nfp_repr; struct nfp_net; enum nfp_app_id { @@ -66,10 +67,13 @@ extern const struct nfp_app_type app_flower; * @ctrl_has_meta: control messages have prepend of type:5/port:CTRL * * Callbacks - * @init: perform basic app checks + * @init: perform basic app checks and init + * @clean: clean app state * @extra_cap: extra capabilities string * @vnic_init: init vNICs (assign port types, etc.) * @vnic_clean: clean up app's vNIC state + * @repr_open: representor netdev open callback + * @repr_stop: representor netdev stop callback * @start: start application logic * @stop: stop application logic * @ctrl_msg_rx: control message handler @@ -88,6 +92,7 @@ struct nfp_app_type { bool ctrl_has_meta; int (*init)(struct nfp_app *app); + void (*clean)(struct nfp_app *app); const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn); @@ -95,6 +100,9 @@ struct nfp_app_type { unsigned int id); void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn); + int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr); + int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr); + int (*start)(struct nfp_app *app); void (*stop)(struct nfp_app *app); @@ -144,6 +152,12 @@ static inline int nfp_app_init(struct nfp_app *app) return app->type->init(app); } +static inline void nfp_app_clean(struct nfp_app *app) +{ + if (app->type->clean) + app->type->clean(app); +} + static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id) { @@ -156,6 +170,20 @@ static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn) app->type->vnic_clean(app, nn); } +static inline int nfp_app_repr_open(struct nfp_app *app, struct nfp_repr *repr) +{ + if (!app->type->repr_open) + return -EINVAL; + return app->type->repr_open(app, repr); +} + +static inline int nfp_app_repr_stop(struct nfp_app *app, struct nfp_repr *repr) +{ + if (!app->type->repr_stop) + return -EINVAL; + return app->type->repr_stop(app, repr); +} + static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl) { app->ctrl = ctrl; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c index 748e54cc885e..d67969d3e484 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c @@ -107,17 +107,18 @@ static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs) goto err_unlock; } - err = nfp_app_sriov_enable(pf->app, num_vfs); + err = pci_enable_sriov(pdev, num_vfs); if (err) { - dev_warn(&pdev->dev, "App specific PCI sriov configuration failed: %d\n", - err); + dev_warn(&pdev->dev, "Failed to enable PCI SR-IOV: %d\n", err); goto err_unlock; } - err = pci_enable_sriov(pdev, num_vfs); + err = nfp_app_sriov_enable(pf->app, num_vfs); if (err) { - dev_warn(&pdev->dev, "Failed to enable PCI sriov: %d\n", err); - goto err_app_sriov_disable; + dev_warn(&pdev->dev, + "App specific PCI SR-IOV configuration failed: %d\n", + err); + goto err_sriov_disable; } pf->num_vfs = num_vfs; @@ -127,8 +128,8 @@ static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs) mutex_unlock(&pf->lock); return num_vfs; -err_app_sriov_disable: - nfp_app_sriov_disable(pf->app); +err_sriov_disable: + pci_disable_sriov(pdev); err_unlock: mutex_unlock(&pf->lock); return err; @@ -136,17 +137,20 @@ err_unlock: return 0; } -static int __nfp_pcie_sriov_disable(struct pci_dev *pdev) +static int nfp_pcie_sriov_disable(struct pci_dev *pdev) { #ifdef CONFIG_PCI_IOV struct nfp_pf *pf = pci_get_drvdata(pdev); + mutex_lock(&pf->lock); + /* If the VFs are assigned we cannot shut down SR-IOV without * causing issues, so just leave the hardware available but * disabled */ if (pci_vfs_assigned(pdev)) { dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n"); + mutex_unlock(&pf->lock); return -EPERM; } @@ -156,20 +160,10 @@ static int __nfp_pcie_sriov_disable(struct pci_dev *pdev) pci_disable_sriov(pdev); dev_dbg(&pdev->dev, "Removed VFs.\n"); -#endif - return 0; -} - -static int nfp_pcie_sriov_disable(struct pci_dev *pdev) -{ - struct nfp_pf *pf = pci_get_drvdata(pdev); - int err; - mutex_lock(&pf->lock); - err = __nfp_pcie_sriov_disable(pdev); mutex_unlock(&pf->lock); - - return err; +#endif + return 0; } static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs) @@ -382,6 +376,12 @@ static int nfp_pci_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, pf); pf->pdev = pdev; + pf->wq = alloc_workqueue("nfp-%s", 0, 2, pci_name(pdev)); + if (!pf->wq) { + err = -ENOMEM; + goto err_pci_priv_unset; + } + pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev); if (IS_ERR_OR_NULL(pf->cpp)) { err = PTR_ERR(pf->cpp); @@ -414,6 +414,14 @@ static int nfp_pci_probe(struct pci_dev *pdev, if (err) goto err_fw_unload; + pf->num_vfs = pci_num_vf(pdev); + if (pf->num_vfs > pf->limit_vfs) { + dev_err(&pdev->dev, + "Error: %d VFs already enabled, but loaded FW can only support %d\n", + pf->num_vfs, pf->limit_vfs); + goto err_fw_unload; + } + err = nfp_net_pci_probe(pf); if (err) goto err_sriov_unlimit; @@ -443,6 +451,8 @@ err_hwinfo_free: kfree(pf->hwinfo); nfp_cpp_free(pf->cpp); err_disable_msix: + destroy_workqueue(pf->wq); +err_pci_priv_unset: pci_set_drvdata(pdev, NULL); mutex_destroy(&pf->lock); devlink_free(devlink); @@ -463,11 +473,11 @@ static void nfp_pci_remove(struct pci_dev *pdev) devlink = priv_to_devlink(pf); + nfp_net_pci_remove(pf); + nfp_pcie_sriov_disable(pdev); pci_sriov_set_totalvfs(pf->pdev, 0); - nfp_net_pci_remove(pf); - devlink_unregister(devlink); kfree(pf->rtbl); @@ -475,6 +485,7 @@ static void nfp_pci_remove(struct pci_dev *pdev) if (pf->fw_loaded) nfp_fw_unload(pf); + destroy_workqueue(pf->wq); pci_set_drvdata(pdev, NULL); kfree(pf->hwinfo); nfp_cpp_free(pf->cpp); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h index edc14dc78674..a08cfba7e68e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h @@ -89,6 +89,7 @@ struct nfp_rtsym_table; * @num_vnics: Number of vNICs spawned * @vnics: Linked list of vNIC structures (struct nfp_net) * @ports: Linked list of port structures (struct nfp_port) + * @wq: Workqueue for running works which need to grab @lock * @port_refresh_work: Work entry for taking netdevs out * @lock: Protects all fields which may change after probe */ @@ -131,7 +132,10 @@ struct nfp_pf { struct list_head vnics; struct list_head ports; + + struct workqueue_struct *wq; struct work_struct port_refresh_work; + struct mutex lock; }; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index cfcbc3b9a9aa..c85a2f18c4df 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -81,58 +81,6 @@ static int nfp_is_ready(struct nfp_pf *pf) } /** - * nfp_net_map_area() - Help function to map an area - * @cpp: NFP CPP handler - * @name: Name for the area - * @target: CPP target - * @addr: CPP address - * @size: Size of the area - * @area: Area handle (returned). - * - * This function is primarily to simplify the code in the main probe - * function. To undo the effect of this functions call - * @nfp_cpp_area_release_free(*area); - * - * Return: Pointer to memory mapped area or ERR_PTR - */ -static u8 __iomem *nfp_net_map_area(struct nfp_cpp *cpp, - const char *name, int isl, int target, - unsigned long long addr, unsigned long size, - struct nfp_cpp_area **area) -{ - u8 __iomem *res; - u32 dest; - int err; - - dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, isl); - - *area = nfp_cpp_area_alloc_with_name(cpp, dest, name, addr, size); - if (!*area) { - err = -EIO; - goto err_area; - } - - err = nfp_cpp_area_acquire(*area); - if (err < 0) - goto err_acquire; - - res = nfp_cpp_area_iomem(*area); - if (!res) { - err = -EIO; - goto err_map; - } - - return res; - -err_map: - nfp_cpp_area_release(*area); -err_acquire: - nfp_cpp_area_free(*area); -err_area: - return (u8 __iomem *)ERR_PTR(err); -} - -/** * nfp_net_get_mac_addr() - Get the MAC address. * @pf: NFP PF handle * @port: NFP port structure @@ -226,31 +174,12 @@ static u8 __iomem * nfp_net_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt, unsigned int min_size, struct nfp_cpp_area **area) { - const struct nfp_rtsym *sym; char pf_symbol[256]; - u8 __iomem *mem; snprintf(pf_symbol, sizeof(pf_symbol), sym_fmt, nfp_cppcore_pcie_unit(pf->cpp)); - sym = nfp_rtsym_lookup(pf->rtbl, pf_symbol); - if (!sym) - return (u8 __iomem *)ERR_PTR(-ENOENT); - - if (sym->size < min_size) { - nfp_err(pf->cpp, "PF symbol %s too small\n", pf_symbol); - return (u8 __iomem *)ERR_PTR(-EINVAL); - } - - mem = nfp_net_map_area(pf->cpp, name, sym->domain, sym->target, - sym->addr, sym->size, area); - if (IS_ERR(mem)) { - nfp_err(pf->cpp, "Failed to map PF symbol %s: %ld\n", - pf_symbol, PTR_ERR(mem)); - return mem; - } - - return mem; + return nfp_rtsym_map(pf->rtbl, pf_symbol, name, min_size, area); } static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn) @@ -485,7 +414,7 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride) if (IS_ERR(ctrl_bar)) { nfp_err(pf->cpp, "Failed to find data vNIC memory symbol\n"); err = PTR_ERR(ctrl_bar); - goto err_free; + goto err_app_clean; } pf->ctrl_vnic = nfp_net_pf_alloc_vnic(pf, false, ctrl_bar, qc_bar, @@ -499,8 +428,11 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride) err_unmap: nfp_cpp_area_release_free(pf->ctrl_vnic_bar); +err_app_clean: + nfp_app_clean(pf->app); err_free: nfp_app_free(pf->app); + pf->app = NULL; return err; } @@ -510,6 +442,7 @@ static void nfp_net_pf_app_clean(struct nfp_pf *pf) nfp_net_pf_free_vnic(pf, pf->ctrl_vnic); nfp_cpp_area_release_free(pf->ctrl_vnic_bar); } + nfp_app_clean(pf->app); nfp_app_free(pf->app); pf->app = NULL; } @@ -555,8 +488,16 @@ static int nfp_net_pf_app_start(struct nfp_pf *pf) if (err) goto err_ctrl_stop; + if (pf->num_vfs) { + err = nfp_app_sriov_enable(pf->app, pf->num_vfs); + if (err) + goto err_app_stop; + } + return 0; +err_app_stop: + nfp_app_stop(pf->app); err_ctrl_stop: nfp_net_pf_app_stop_ctrl(pf); return err; @@ -564,6 +505,8 @@ err_ctrl_stop: static void nfp_net_pf_app_stop(struct nfp_pf *pf) { + if (pf->num_vfs) + nfp_app_sriov_disable(pf->app); nfp_app_stop(pf->app); nfp_net_pf_app_stop_ctrl(pf); } @@ -580,26 +523,22 @@ static void nfp_net_pci_unmap_mem(struct nfp_pf *pf) static int nfp_net_pci_map_mem(struct nfp_pf *pf) { - u32 ctrl_bar_sz; u8 __iomem *mem; + u32 min_size; int err; - ctrl_bar_sz = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE; + min_size = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE; mem = nfp_net_pf_map_rtsym(pf, "net.ctrl", "_pf%d_net_bar0", - ctrl_bar_sz, &pf->data_vnic_bar); + min_size, &pf->data_vnic_bar); if (IS_ERR(mem)) { nfp_err(pf->cpp, "Failed to find data vNIC memory symbol\n"); - err = PTR_ERR(mem); - if (!pf->fw_loaded && err == -ENOENT) - err = -EPROBE_DEFER; - return err; + return PTR_ERR(mem); } - pf->mac_stats_mem = nfp_net_pf_map_rtsym(pf, "net.macstats", - "_mac_stats", - NFP_MAC_STATS_SIZE * - (pf->eth_tbl->max_index + 1), - &pf->mac_stats_bar); + min_size = NFP_MAC_STATS_SIZE * (pf->eth_tbl->max_index + 1); + pf->mac_stats_mem = nfp_rtsym_map(pf->rtbl, "_mac_stats", + "net.macstats", min_size, + &pf->mac_stats_bar); if (IS_ERR(pf->mac_stats_mem)) { if (PTR_ERR(pf->mac_stats_mem) != -ENOENT) { err = PTR_ERR(pf->mac_stats_mem); @@ -620,7 +559,7 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf) pf->vf_cfg_mem = NULL; } - mem = nfp_net_map_area(pf->cpp, "net.qc", 0, 0, + mem = nfp_cpp_map_area(pf->cpp, "net.qc", 0, 0, NFP_PCIE_QUEUE(0), NFP_QCP_QUEUE_AREA_SZ, &pf->qc_area); if (IS_ERR(mem)) { @@ -743,7 +682,7 @@ void nfp_net_refresh_port_table(struct nfp_port *port) set_bit(NFP_PORT_CHANGED, &port->flags); - schedule_work(&pf->port_refresh_work); + queue_work(pf->wq, &pf->port_refresh_work); } int nfp_net_refresh_eth_port(struct nfp_port *port) @@ -786,6 +725,12 @@ int nfp_net_pci_probe(struct nfp_pf *pf) return -EINVAL; } + if (!pf->rtbl) { + nfp_err(pf->cpp, "No %s, giving up.\n", + pf->fw_loaded ? "symbol table" : "firmware found"); + return -EPROBE_DEFER; + } + mutex_lock(&pf->lock); pf->max_data_vnics = nfp_net_pf_get_num_ports(pf); if ((int)pf->max_data_vnics < 0) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 44adcc5df11e..046b89eb4cf2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -37,6 +37,7 @@ #include <net/dst_metadata.h> #include "nfpcore/nfp_cpp.h" +#include "nfpcore/nfp_nsp.h" #include "nfp_app.h" #include "nfp_main.h" #include "nfp_net_ctrl.h" @@ -135,25 +136,34 @@ nfp_repr_pf_get_stats64(const struct nfp_app *app, u8 pf, stats->rx_dropped = readq(mem + NFP_NET_CFG_STATS_TX_DISCARDS); } -void -nfp_repr_get_stats64(const struct nfp_app *app, enum nfp_repr_type type, - u8 port, struct rtnl_link_stats64 *stats) +static void +nfp_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) { - switch (type) { - case NFP_REPR_TYPE_PHYS_PORT: - nfp_repr_phy_port_get_stats64(app, port, stats); + struct nfp_repr *repr = netdev_priv(netdev); + struct nfp_eth_table_port *eth_port; + struct nfp_app *app = repr->app; + + if (WARN_ON(!repr->port)) + return; + + switch (repr->port->type) { + case NFP_PORT_PHYS_PORT: + eth_port = __nfp_port_get_eth_port(repr->port); + if (!eth_port) + break; + nfp_repr_phy_port_get_stats64(app, eth_port->index, stats); break; - case NFP_REPR_TYPE_PF: - nfp_repr_pf_get_stats64(app, port, stats); + case NFP_PORT_PF_PORT: + nfp_repr_pf_get_stats64(app, repr->port->pf_id, stats); break; - case NFP_REPR_TYPE_VF: - nfp_repr_vf_get_stats64(app, port, stats); + case NFP_PORT_VF_PORT: + nfp_repr_vf_get_stats64(app, repr->port->vf_id, stats); default: break; } } -bool +static bool nfp_repr_has_offload_stats(const struct net_device *dev, int attr_id) { switch (attr_id) { @@ -196,8 +206,9 @@ nfp_repr_get_host_stats64(const struct net_device *netdev, return 0; } -int nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev, - void *stats) +static int +nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev, + void *stats) { switch (attr_id) { case IFLA_OFFLOAD_XSTATS_CPU_HIT: @@ -207,7 +218,7 @@ int nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev, return -EINVAL; } -netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev) +static netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev) { struct nfp_repr *repr = netdev_priv(netdev); unsigned int len = skb->len; @@ -224,6 +235,30 @@ netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev) return ret; } +static int nfp_repr_stop(struct net_device *netdev) +{ + struct nfp_repr *repr = netdev_priv(netdev); + + return nfp_app_repr_stop(repr->app, repr); +} + +static int nfp_repr_open(struct net_device *netdev) +{ + struct nfp_repr *repr = netdev_priv(netdev); + + return nfp_app_repr_open(repr->app, repr); +} + +const struct net_device_ops nfp_repr_netdev_ops = { + .ndo_open = nfp_repr_open, + .ndo_stop = nfp_repr_stop, + .ndo_start_xmit = nfp_repr_xmit, + .ndo_get_stats64 = nfp_repr_get_stats64, + .ndo_has_offload_stats = nfp_repr_has_offload_stats, + .ndo_get_offload_stats = nfp_repr_get_offload_stats, + .ndo_get_phys_port_name = nfp_port_get_phys_port_name, +}; + static void nfp_repr_clean(struct nfp_repr *repr) { unregister_netdev(repr->netdev); @@ -248,8 +283,8 @@ static void nfp_repr_set_lockdep_class(struct net_device *dev) } int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, - const struct net_device_ops *netdev_ops, u32 cmsg_port_id, - struct nfp_port *port, struct net_device *pf_netdev) + u32 cmsg_port_id, struct nfp_port *port, + struct net_device *pf_netdev) { struct nfp_repr *repr = netdev_priv(netdev); int err; @@ -263,7 +298,7 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, repr->dst->u.port_info.port_id = cmsg_port_id; repr->dst->u.port_info.lower_dev = pf_netdev; - netdev->netdev_ops = netdev_ops; + netdev->netdev_ops = &nfp_repr_netdev_ops; err = register_netdev(netdev); if (err) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.h b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.h index c5ed6611f708..6a6727816010 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.h @@ -97,16 +97,15 @@ enum nfp_repr_type { }; #define NFP_REPR_TYPE_MAX (__NFP_REPR_TYPE_MAX - 1) +extern const struct net_device_ops nfp_repr_netdev_ops; + +static inline bool nfp_netdev_is_nfp_repr(struct net_device *netdev) +{ + return netdev->netdev_ops == &nfp_repr_netdev_ops; +} + void nfp_repr_inc_rx_stats(struct net_device *netdev, unsigned int len); -void -nfp_repr_get_stats64(const struct nfp_app *app, enum nfp_repr_type type, - u8 port, struct rtnl_link_stats64 *stats); -bool nfp_repr_has_offload_stats(const struct net_device *dev, int attr_id); -int nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev, - void *stats); -netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev); int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, - const struct net_device_ops *netdev_ops, u32 cmsg_port_id, struct nfp_port *port, struct net_device *pf_netdev); struct net_device *nfp_repr_alloc(struct nfp_app *app); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c index 19bceeb82225..0b44952945d8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c @@ -42,13 +42,21 @@ struct nfp_port *nfp_port_from_netdev(struct net_device *netdev) { - struct nfp_net *nn; + if (nfp_netdev_is_nfp_net(netdev)) { + struct nfp_net *nn = netdev_priv(netdev); - if (WARN_ON(!nfp_netdev_is_nfp_net(netdev))) - return NULL; - nn = netdev_priv(netdev); + return nn->port; + } + + if (nfp_netdev_is_nfp_repr(netdev)) { + struct nfp_repr *repr = netdev_priv(netdev); + + return repr->port; + } + + WARN(1, "Unknown netdev type for nfp_port\n"); - return nn->port; + return NULL; } struct nfp_port * @@ -98,15 +106,31 @@ nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len) int n; port = nfp_port_from_netdev(netdev); - eth_port = __nfp_port_get_eth_port(port); - if (!eth_port) + if (!port) return -EOPNOTSUPP; - if (!eth_port->is_split) - n = snprintf(name, len, "p%d", eth_port->label_port); - else - n = snprintf(name, len, "p%ds%d", eth_port->label_port, - eth_port->label_subport); + switch (port->type) { + case NFP_PORT_PHYS_PORT: + eth_port = __nfp_port_get_eth_port(port); + if (!eth_port) + return -EOPNOTSUPP; + + if (!eth_port->is_split) + n = snprintf(name, len, "p%d", eth_port->label_port); + else + n = snprintf(name, len, "p%ds%d", eth_port->label_port, + eth_port->label_subport); + break; + case NFP_PORT_PF_PORT: + n = snprintf(name, len, "pf%d", port->pf_id); + break; + case NFP_PORT_VF_PORT: + n = snprintf(name, len, "pf%dvf%d", port->pf_id, port->vf_id); + break; + default: + return -EOPNOTSUPP; + } + if (n >= len) return -EINVAL; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h index f472bea4ec2b..57d852a4ca59 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h @@ -47,10 +47,14 @@ struct nfp_port; * state when port disappears because of FW fault or config * change * @NFP_PORT_PHYS_PORT: external NIC port + * @NFP_PORT_PF_PORT: logical port of PCI PF + * @NFP_PORT_VF_PORT: logical port of PCI VF */ enum nfp_port_type { NFP_PORT_INVALID, NFP_PORT_PHYS_PORT, + NFP_PORT_PF_PORT, + NFP_PORT_VF_PORT, }; /** @@ -72,6 +76,8 @@ enum nfp_port_flags { * @dl_port: devlink port structure * @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry + * @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3) + * @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id * @port_list: entry on pf's list of ports */ struct nfp_port { @@ -84,8 +90,18 @@ struct nfp_port { struct devlink_port dl_port; - unsigned int eth_id; - struct nfp_eth_table_port *eth_port; + union { + /* NFP_PORT_PHYS_PORT */ + struct { + unsigned int eth_id; + struct nfp_eth_table_port *eth_port; + }; + /* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */ + struct { + unsigned int pf_id; + unsigned int vf_id; + }; + }; struct list_head port_list; }; diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h index 25a967158ce9..5798adc57cbc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h @@ -230,6 +230,9 @@ struct nfp_cpp_area *nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, struct nfp_cpp_area *nfp_cpp_area_alloc(struct nfp_cpp *cpp, u32 cpp_id, unsigned long long address, unsigned long size); +struct nfp_cpp_area * +nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, const char *name, u32 cpp_id, + unsigned long long address, unsigned long size); void nfp_cpp_area_free(struct nfp_cpp_area *area); int nfp_cpp_area_acquire(struct nfp_cpp_area *area); int nfp_cpp_area_acquire_nonblocking(struct nfp_cpp_area *area); @@ -239,8 +242,6 @@ int nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset, void *buffer, size_t length); int nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset, const void *buffer, size_t length); -int nfp_cpp_area_check_range(struct nfp_cpp_area *area, - unsigned long long offset, unsigned long size); const char *nfp_cpp_area_name(struct nfp_cpp_area *cpp_area); void *nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area); struct nfp_cpp *nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area); @@ -278,6 +279,10 @@ int nfp_cpp_readq(struct nfp_cpp *cpp, u32 cpp_id, int nfp_cpp_writeq(struct nfp_cpp *cpp, u32 cpp_id, unsigned long long address, u64 value); +u8 __iomem * +nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, int domain, int target, + u64 addr, unsigned long size, struct nfp_cpp_area **area); + struct nfp_cpp_mutex; int nfp_cpp_mutex_init(struct nfp_cpp *cpp, int target, diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c index 9b69dcf87be9..04dd5758ecf5 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c @@ -361,6 +361,41 @@ nfp_cpp_area_alloc(struct nfp_cpp *cpp, u32 dest, } /** + * nfp_cpp_area_alloc_acquire() - allocate a new CPP area and lock it down + * @cpp: CPP handle + * @name: Name of region + * @dest: CPP id + * @address: Start address on CPP target + * @size: Size of area + * + * Allocate and initialize a CPP area structure, and lock it down so + * that it can be accessed directly. + * + * NOTE: @address and @size must be 32-bit aligned values. + * + * NOTE: The area must also be 'released' when the structure is freed. + * + * Return: NFP CPP Area handle, or NULL + */ +struct nfp_cpp_area * +nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, const char *name, u32 dest, + unsigned long long address, unsigned long size) +{ + struct nfp_cpp_area *area; + + area = nfp_cpp_area_alloc_with_name(cpp, dest, name, address, size); + if (!area) + return NULL; + + if (nfp_cpp_area_acquire(area)) { + nfp_cpp_area_free(area); + return NULL; + } + + return area; +} + +/** * nfp_cpp_area_free() - free up the CPP area * @area: CPP area handle * @@ -536,27 +571,6 @@ int nfp_cpp_area_write(struct nfp_cpp_area *area, } /** - * nfp_cpp_area_check_range() - check if address range fits in CPP area - * @area: CPP area handle - * @offset: offset into CPP target - * @length: size of address range in bytes - * - * Check if address range fits within CPP area. Return 0 if area - * fits or -EFAULT on error. - * - * Return: 0, or -ERRNO - */ -int nfp_cpp_area_check_range(struct nfp_cpp_area *area, - unsigned long long offset, unsigned long length) -{ - if (offset < area->offset || - offset + length > area->offset + area->size) - return -EFAULT; - - return 0; -} - -/** * nfp_cpp_area_name() - return name of a CPP area * @cpp_area: CPP area handle * diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c index 0ba0379b8f75..ab86bceb93f2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c @@ -279,3 +279,43 @@ exit_release: return err; } + +/** + * nfp_cpp_map_area() - Helper function to map an area + * @cpp: NFP CPP handler + * @name: Name for the area + * @domain: CPP domain + * @target: CPP target + * @addr: CPP address + * @size: Size of the area + * @area: Area handle (output) + * + * Map an area of IOMEM access. To undo the effect of this function call + * @nfp_cpp_area_release_free(*area). + * + * Return: Pointer to memory mapped area or ERR_PTR + */ +u8 __iomem * +nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, int domain, int target, + u64 addr, unsigned long size, struct nfp_cpp_area **area) +{ + u8 __iomem *res; + u32 dest; + + dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain); + + *area = nfp_cpp_area_alloc_acquire(cpp, name, dest, addr, size); + if (!*area) + goto err_eio; + + res = nfp_cpp_area_iomem(*area); + if (!res) + goto err_release_free; + + return res; + +err_release_free: + nfp_cpp_area_release_free(*area); +err_eio: + return (u8 __iomem *)ERR_PTR(-EIO); +} diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h index d27d29782a12..c9724fb7ea4b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h @@ -97,7 +97,11 @@ int nfp_rtsym_count(struct nfp_rtsym_table *rtbl); const struct nfp_rtsym *nfp_rtsym_get(struct nfp_rtsym_table *rtbl, int idx); const struct nfp_rtsym * nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name); + u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name, int *error); +u8 __iomem * +nfp_rtsym_map(struct nfp_rtsym_table *rtbl, const char *name, const char *id, + unsigned int min_size, struct nfp_cpp_area **area); #endif /* NFP_NFFW_H */ diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c index 203f9cbae0fb..ecda474ac7c3 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c @@ -289,3 +289,30 @@ exit: return ~0ULL; return val; } + +u8 __iomem * +nfp_rtsym_map(struct nfp_rtsym_table *rtbl, const char *name, const char *id, + unsigned int min_size, struct nfp_cpp_area **area) +{ + const struct nfp_rtsym *sym; + u8 __iomem *mem; + + sym = nfp_rtsym_lookup(rtbl, name); + if (!sym) + return (u8 __iomem *)ERR_PTR(-ENOENT); + + if (sym->size < min_size) { + nfp_err(rtbl->cpp, "Symbol %s too small\n", name); + return (u8 __iomem *)ERR_PTR(-EINVAL); + } + + mem = nfp_cpp_map_area(rtbl->cpp, id, sym->domain, sym->target, + sym->addr, sym->size, area); + if (IS_ERR(mem)) { + nfp_err(rtbl->cpp, "Failed to map symbol %s: %ld\n", + name, PTR_ERR(mem)); + return mem; + } + + return mem; +} diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index fffd6d5fc907..6c2d1da05588 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -638,7 +638,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) { struct sunxi_priv_data *gmac = priv->plat->bsp_priv; struct device_node *node = priv->device->of_node; - int ret; + int ret, phy_interface; u32 reg, val; regmap_read(gmac->regmap, SYSCON_EMAC_REG, &val); @@ -718,7 +718,11 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) if (gmac->variant->support_rmii) reg &= ~SYSCON_RMII_EN; - switch (priv->plat->interface) { + phy_interface = priv->plat->interface; + /* if PHY is internal, select the mode (xMII) used by the SoC */ + if (gmac->use_internal_phy) + phy_interface = gmac->variant->internal_phy; + switch (phy_interface) { case PHY_INTERFACE_MODE_MII: /* default */ break; @@ -932,7 +936,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) } plat_dat->interface = of_get_phy_mode(dev->of_node); - if (plat_dat->interface == gmac->variant->internal_phy) { + if (plat_dat->interface == PHY_INTERFACE_MODE_INTERNAL) { dev_info(&pdev->dev, "Will use internal PHY\n"); gmac->use_internal_phy = true; gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0); diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index b7a0f5eeab62..1850e348f555 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1236,6 +1236,7 @@ static inline int cpsw_tx_packet_submit(struct cpsw_priv *priv, { struct cpsw_common *cpsw = priv->cpsw; + skb_tx_timestamp(skb); return cpdma_chan_submit(txch, skb, skb->data, skb->len, priv->emac_port + cpsw->data.dual_emac); } @@ -1597,6 +1598,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; + struct cpts *cpts = cpsw->cpts; struct netdev_queue *txq; struct cpdma_chan *txch; int ret, q_idx; @@ -1608,11 +1610,9 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, } if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && - cpts_is_tx_enabled(cpsw->cpts)) + cpts_is_tx_enabled(cpts) && cpts_can_timestamp(cpts, skb)) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - skb_tx_timestamp(skb); - q_idx = skb_get_queue_mapping(skb); if (q_idx >= cpsw->tx_ch_num) q_idx = q_idx % cpsw->tx_ch_num; diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h index c96eca2b1b46..01ea82ba9cdc 100644 --- a/drivers/net/ethernet/ti/cpts.h +++ b/drivers/net/ethernet/ti/cpts.h @@ -30,6 +30,7 @@ #include <linux/of.h> #include <linux/ptp_clock_kernel.h> #include <linux/skbuff.h> +#include <linux/ptp_classify.h> #include <linux/timecounter.h> struct cpsw_cpts { @@ -155,6 +156,16 @@ static inline bool cpts_is_tx_enabled(struct cpts *cpts) return !!cpts->tx_enable; } +static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ + unsigned int class = ptp_classify_raw(skb); + + if (class == PTP_CLASS_NONE) + return false; + + return true; +} + #else struct cpts; @@ -203,6 +214,11 @@ static inline bool cpts_is_tx_enabled(struct cpts *cpts) { return false; } + +static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ + return false; +} #endif diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 0847a8f48cfe..28cb38af1a34 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2503,24 +2503,8 @@ static bool gbe_need_txtstamp(struct gbe_intf *gbe_intf, const struct netcp_packet *p_info) { struct sk_buff *skb = p_info->skb; - unsigned int class = ptp_classify_raw(skb); - if (class == PTP_CLASS_NONE) - return false; - - switch (class) { - case PTP_CLASS_V1_IPV4: - case PTP_CLASS_V1_IPV6: - case PTP_CLASS_V2_IPV4: - case PTP_CLASS_V2_IPV6: - case PTP_CLASS_V2_L2: - case (PTP_CLASS_V2_VLAN | PTP_CLASS_L2): - case (PTP_CLASS_V2_VLAN | PTP_CLASS_IPV4): - case (PTP_CLASS_V2_VLAN | PTP_CLASS_IPV6): - return true; - } - - return false; + return cpts_can_timestamp(gbe_intf->gbe_dev->cpts, skb); } static int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf, diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0dafd8e6c665..fd0ff97e3d81 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2727,7 +2727,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[], } if (tb[IFLA_MTU]) { - u32 mtu = nla_get_u32(data[IFLA_MTU]); + u32 mtu = nla_get_u32(tb[IFLA_MTU]); if (mtu < ETH_MIN_MTU || mtu > ETH_MAX_MTU) return -EINVAL; diff --git a/include/net/udp.h b/include/net/udp.h index 1468dbd0f09a..972ce4baab6b 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -302,6 +302,67 @@ struct sock *__udp6_lib_lookup(struct net *net, struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport); +/* UDP uses skb->dev_scratch to cache as much information as possible and avoid + * possibly multiple cache miss on dequeue() + */ +#if BITS_PER_LONG == 64 + +/* truesize, len and the bit needed to compute skb_csum_unnecessary will be on + * cold cache lines at recvmsg time. + * skb->len can be stored on 16 bits since the udp header has been already + * validated and pulled. + */ +struct udp_dev_scratch { + u32 truesize; + u16 len; + bool is_linear; + bool csum_unnecessary; +}; + +static inline unsigned int udp_skb_len(struct sk_buff *skb) +{ + return ((struct udp_dev_scratch *)&skb->dev_scratch)->len; +} + +static inline bool udp_skb_csum_unnecessary(struct sk_buff *skb) +{ + return ((struct udp_dev_scratch *)&skb->dev_scratch)->csum_unnecessary; +} + +static inline bool udp_skb_is_linear(struct sk_buff *skb) +{ + return ((struct udp_dev_scratch *)&skb->dev_scratch)->is_linear; +} + +#else +static inline unsigned int udp_skb_len(struct sk_buff *skb) +{ + return skb->len; +} + +static inline bool udp_skb_csum_unnecessary(struct sk_buff *skb) +{ + return skb_csum_unnecessary(skb); +} + +static inline bool udp_skb_is_linear(struct sk_buff *skb) +{ + return !skb_is_nonlinear(skb); +} +#endif + +static inline int copy_linear_skb(struct sk_buff *skb, int len, int off, + struct iov_iter *to) +{ + int n, copy = len - off; + + n = copy_to_iter(skb->data + off, copy, to); + if (n == copy) + return 0; + + return -EFAULT; +} + /* * SNMP statistics for UDP and UDP-Lite */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 058f509ca98e..4c88d20d91d4 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3062,6 +3062,11 @@ static int do_tcp_getsockopt(struct sock *sk, int level, if (get_user(len, optlen)) return -EFAULT; len = min_t(unsigned int, len, TCP_ULP_NAME_MAX); + if (!icsk->icsk_ulp_ops) { + if (put_user(0, optlen)) + return -EFAULT; + return 0; + } if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, icsk->icsk_ulp_ops->name, len)) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 47c7aa0501af..86fad2a14ac4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1163,24 +1163,7 @@ out: return ret; } -/* Copy as much information as possible into skb->dev_scratch to avoid - * possibly multiple cache miss on dequeue(); - */ #if BITS_PER_LONG == 64 - -/* we can store multiple info here: truesize, len and the bit needed to - * compute skb_csum_unnecessary will be on cold cache lines at recvmsg - * time. - * skb->len can be stored on 16 bits since the udp header has been already - * validated and pulled. - */ -struct udp_dev_scratch { - u32 truesize; - u16 len; - bool is_linear; - bool csum_unnecessary; -}; - static void udp_set_dev_scratch(struct sk_buff *skb) { struct udp_dev_scratch *scratch; @@ -1197,22 +1180,6 @@ static int udp_skb_truesize(struct sk_buff *skb) { return ((struct udp_dev_scratch *)&skb->dev_scratch)->truesize; } - -static unsigned int udp_skb_len(struct sk_buff *skb) -{ - return ((struct udp_dev_scratch *)&skb->dev_scratch)->len; -} - -static bool udp_skb_csum_unnecessary(struct sk_buff *skb) -{ - return ((struct udp_dev_scratch *)&skb->dev_scratch)->csum_unnecessary; -} - -static bool udp_skb_is_linear(struct sk_buff *skb) -{ - return ((struct udp_dev_scratch *)&skb->dev_scratch)->is_linear; -} - #else static void udp_set_dev_scratch(struct sk_buff *skb) { @@ -1223,21 +1190,6 @@ static int udp_skb_truesize(struct sk_buff *skb) { return skb->dev_scratch; } - -static unsigned int udp_skb_len(struct sk_buff *skb) -{ - return skb->len; -} - -static bool udp_skb_csum_unnecessary(struct sk_buff *skb) -{ - return skb_csum_unnecessary(skb); -} - -static bool udp_skb_is_linear(struct sk_buff *skb) -{ - return !skb_is_nonlinear(skb); -} #endif /* fully reclaim rmem/fwd memory allocated for skb */ @@ -1598,18 +1550,6 @@ busy_check: } EXPORT_SYMBOL_GPL(__skb_recv_udp); -static int copy_linear_skb(struct sk_buff *skb, int len, int off, - struct iov_iter *to) -{ - int n, copy = len - off; - - n = copy_to_iter(skb->data + off, copy, to); - if (n == copy) - return 0; - - return -EFAULT; -} - /* * This should be easy, if there is something there we * return it, otherwise we block. diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d1d728805729..450829dd6384 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -362,7 +362,7 @@ try_again: if (!skb) return err; - ulen = skb->len; + ulen = udp_skb_len(skb); copied = len; if (copied > ulen - off) copied = ulen - off; @@ -379,14 +379,18 @@ try_again: if (copied < ulen || peeking || (is_udplite && UDP_SKB_CB(skb)->partial_cov)) { - checksum_valid = !udp_lib_checksum_complete(skb); + checksum_valid = udp_skb_csum_unnecessary(skb) || + !__udp_lib_checksum_complete(skb); if (!checksum_valid) goto csum_copy_err; } - if (checksum_valid || skb_csum_unnecessary(skb)) - err = skb_copy_datagram_msg(skb, off, msg, copied); - else { + if (checksum_valid || udp_skb_csum_unnecessary(skb)) { + if (udp_skb_is_linear(skb)) + err = copy_linear_skb(skb, copied, off, &msg->msg_iter); + else + err = skb_copy_datagram_msg(skb, off, msg, copied); + } else { err = skb_copy_and_csum_datagram_msg(skb, off, msg); if (err == -EINVAL) goto csum_copy_err; |