From 2df7b2d20622f98bca2f001bb0e8d8bee01782ac Mon Sep 17 00:00:00 2001 From: John Hurley Date: Thu, 2 Nov 2017 01:31:29 -0700 Subject: nfp: flower: app should use struct nfp_repr Ensure priv netdev data in flower app is cast to nfp_repr and not nfp_net as in other apps. Fixes: 363fc53b8b58 ("nfp: flower: Convert ndo_setup_tc offloads to block callbacks") Signed-off-by: John Hurley Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/offload.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 7c6cab176293..95c2b9284857 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -468,14 +468,14 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { - struct nfp_net *nn = cb_priv; + struct nfp_repr *repr = cb_priv; - if (!tc_can_offload(nn->dp.netdev)) + if (!tc_can_offload(repr->netdev)) return -EOPNOTSUPP; switch (type) { case TC_SETUP_CLSFLOWER: - return nfp_flower_repr_offload(nn->app, nn->port->netdev, + return nfp_flower_repr_offload(repr->app, repr->netdev, type_data); default: return -EOPNOTSUPP; @@ -485,7 +485,7 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, static int nfp_flower_setup_tc_block(struct net_device *netdev, struct tc_block_offload *f) { - struct nfp_net *nn = netdev_priv(netdev); + struct nfp_repr *repr = netdev_priv(netdev); if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) return -EOPNOTSUPP; @@ -494,11 +494,11 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev, case TC_BLOCK_BIND: return tcf_block_cb_register(f->block, nfp_flower_setup_tc_block_cb, - nn, nn); + repr, repr); case TC_BLOCK_UNBIND: tcf_block_cb_unregister(f->block, nfp_flower_setup_tc_block_cb, - nn); + repr); return 0; default: return -EOPNOTSUPP; -- cgit v1.2.3 From dc4646a950153242313ed340f0a404de38b21d5c Mon Sep 17 00:00:00 2001 From: John Hurley Date: Thu, 2 Nov 2017 01:31:30 -0700 Subject: nfp: flower: vxlan - ensure no sleep in atomic context Functions called by the netevent notifier must be in atomic context. Change the mutex to spinlock and ensure mem allocations are done with the atomic flag. Also, remove unnecessary locking after notifiers are unregistered. Signed-off-by: John Hurley Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 9 +++-- drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 2 +- drivers/net/ethernet/netronome/nfp/flower/main.h | 2 +- .../net/ethernet/netronome/nfp/flower/offload.c | 2 +- .../ethernet/netronome/nfp/flower/tunnel_conf.c | 47 +++++++++------------- 5 files changed, 28 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index 6b71c719deba..e98bb9cdb6a3 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -50,14 +50,14 @@ nfp_flower_cmsg_get_hdr(struct sk_buff *skb) struct sk_buff * nfp_flower_cmsg_alloc(struct nfp_app *app, unsigned int size, - enum nfp_flower_cmsg_type_port type) + enum nfp_flower_cmsg_type_port type, gfp_t flag) { struct nfp_flower_cmsg_hdr *ch; struct sk_buff *skb; size += NFP_FLOWER_CMSG_HLEN; - skb = nfp_app_ctrl_msg_alloc(app, size, GFP_KERNEL); + skb = nfp_app_ctrl_msg_alloc(app, size, flag); if (!skb) return NULL; @@ -78,7 +78,8 @@ nfp_flower_cmsg_mac_repr_start(struct nfp_app *app, unsigned int num_ports) unsigned int size; size = sizeof(*msg) + num_ports * sizeof(msg->ports[0]); - skb = nfp_flower_cmsg_alloc(app, size, NFP_FLOWER_CMSG_TYPE_MAC_REPR); + skb = nfp_flower_cmsg_alloc(app, size, NFP_FLOWER_CMSG_TYPE_MAC_REPR, + GFP_KERNEL); if (!skb) return NULL; @@ -109,7 +110,7 @@ int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok) struct sk_buff *skb; skb = nfp_flower_cmsg_alloc(repr->app, sizeof(*msg), - NFP_FLOWER_CMSG_TYPE_PORT_MOD); + NFP_FLOWER_CMSG_TYPE_PORT_MOD, GFP_KERNEL); if (!skb) return -ENOMEM; diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 64e87f8e7089..66070741d55f 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -458,6 +458,6 @@ void nfp_flower_cmsg_process_rx(struct work_struct *work); void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb); struct sk_buff * nfp_flower_cmsg_alloc(struct nfp_app *app, unsigned int size, - enum nfp_flower_cmsg_type_port type); + enum nfp_flower_cmsg_type_port type, gfp_t flag); #endif diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 12c319a219d8..c90e72b7ff5a 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -115,7 +115,7 @@ struct nfp_flower_priv { struct mutex nfp_mac_off_lock; struct mutex nfp_mac_index_lock; struct mutex nfp_ipv4_off_lock; - struct mutex nfp_neigh_off_lock; + spinlock_t nfp_neigh_off_lock; struct ida nfp_mac_off_ids; int nfp_mac_off_count; struct notifier_block nfp_tun_mac_nb; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 95c2b9284857..cdbb5464b790 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -95,7 +95,7 @@ nfp_flower_xmit_flow(struct net_device *netdev, nfp_flow->meta.mask_len >>= NFP_FL_LW_SIZ; nfp_flow->meta.act_len >>= NFP_FL_LW_SIZ; - skb = nfp_flower_cmsg_alloc(priv->app, tot_len, mtype); + skb = nfp_flower_cmsg_alloc(priv->app, tot_len, mtype, GFP_KERNEL); if (!skb) return -ENOMEM; diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index c495f8f38506..b03f22f29612 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -224,12 +224,13 @@ static bool nfp_tun_is_netdev_to_offload(struct net_device *netdev) } static int -nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata) +nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata, + gfp_t flag) { struct sk_buff *skb; unsigned char *msg; - skb = nfp_flower_cmsg_alloc(app, plen, mtype); + skb = nfp_flower_cmsg_alloc(app, plen, mtype, flag); if (!skb) return -ENOMEM; @@ -246,15 +247,15 @@ static bool nfp_tun_has_route(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_neigh_off_lock); + spin_lock_bh(&priv->nfp_neigh_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); return true; } } - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); return false; } @@ -264,24 +265,24 @@ static void nfp_tun_add_route_to_cache(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_neigh_off_lock); + spin_lock_bh(&priv->nfp_neigh_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); return; } } - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) { - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); nfp_flower_cmsg_warn(app, "Mem error when storing new route.\n"); return; } entry->ipv4_addr = ipv4_addr; list_add_tail(&entry->list, &priv->nfp_neigh_off_list); - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); } static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) @@ -290,7 +291,7 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_neigh_off_lock); + spin_lock_bh(&priv->nfp_neigh_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { @@ -299,12 +300,12 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) break; } } - mutex_unlock(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->nfp_neigh_off_lock); } static void nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app, - struct flowi4 *flow, struct neighbour *neigh) + struct flowi4 *flow, struct neighbour *neigh, gfp_t flag) { struct nfp_tun_neigh payload; @@ -334,7 +335,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app, send_msg: nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, sizeof(struct nfp_tun_neigh), - (unsigned char *)&payload); + (unsigned char *)&payload, flag); } static int @@ -385,7 +386,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event, #endif flow.flowi4_proto = IPPROTO_UDP; - nfp_tun_write_neigh(n->dev, app, &flow, n); + nfp_tun_write_neigh(n->dev, app, &flow, n, GFP_ATOMIC); return NOTIFY_OK; } @@ -423,7 +424,7 @@ void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb) ip_rt_put(rt); if (!n) goto route_fail_warning; - nfp_tun_write_neigh(n->dev, app, &flow, n); + nfp_tun_write_neigh(n->dev, app, &flow, n, GFP_KERNEL); neigh_release(n); return; @@ -456,7 +457,7 @@ static void nfp_tun_write_ipv4_list(struct nfp_app *app) nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(struct nfp_tun_ipv4_addr), - &payload); + &payload, GFP_KERNEL); } void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4) @@ -548,7 +549,7 @@ void nfp_tunnel_write_macs(struct nfp_app *app) } err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC, - pay_size, payload); + pay_size, payload, GFP_KERNEL); kfree(payload); @@ -729,7 +730,7 @@ int nfp_tunnel_config_start(struct nfp_app *app) INIT_LIST_HEAD(&priv->nfp_ipv4_off_list); /* Initialise priv data for neighbour offloading. */ - mutex_init(&priv->nfp_neigh_off_lock); + spin_lock_init(&priv->nfp_neigh_off_lock); INIT_LIST_HEAD(&priv->nfp_neigh_off_list); priv->nfp_tun_neigh_nb.notifier_call = nfp_tun_neigh_event_handler; @@ -769,43 +770,35 @@ void nfp_tunnel_config_stop(struct nfp_app *app) unregister_netevent_notifier(&priv->nfp_tun_neigh_nb); /* Free any memory that may be occupied by MAC list. */ - mutex_lock(&priv->nfp_mac_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) { mac_entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, list); list_del(&mac_entry->list); kfree(mac_entry); } - mutex_unlock(&priv->nfp_mac_off_lock); /* Free any memory that may be occupied by MAC index list. */ - mutex_lock(&priv->nfp_mac_index_lock); list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) { mac_idx = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); list_del(&mac_idx->list); kfree(mac_idx); } - mutex_unlock(&priv->nfp_mac_index_lock); ida_destroy(&priv->nfp_mac_off_ids); /* Free any memory that may be occupied by ipv4 list. */ - mutex_lock(&priv->nfp_ipv4_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) { ip_entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); list_del(&ip_entry->list); kfree(ip_entry); } - mutex_unlock(&priv->nfp_ipv4_off_lock); /* Free any memory that may be occupied by the route list. */ - mutex_lock(&priv->nfp_neigh_off_lock); list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { route_entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); list_del(&route_entry->list); kfree(route_entry); } - mutex_unlock(&priv->nfp_neigh_off_lock); } -- cgit v1.2.3 From f449657f83532807f388b9b99cf0c3f7be65eda9 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:31 -0700 Subject: nfp: bpf: reject TC offload if XDP loaded Recent TC changes dropped the check protecting us from trying to offload a TC program if XDP programs are already loaded. Fixes: 90d97315b3e7 ("nfp: bpf: Convert ndo_setup_tc offloads to block callbacks") Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/bpf/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index 04424db24b80..8e3e89cace8d 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c @@ -130,6 +130,9 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type, cls_bpf->common.protocol != htons(ETH_P_ALL) || cls_bpf->common.chain_index) return -EOPNOTSUPP; + if (nn->dp.bpf_offload_xdp) + return -EBUSY; + return nfp_net_bpf_offload(nn, cls_bpf); default: return -EOPNOTSUPP; -- cgit v1.2.3 From 2c4197a041dfbb5101aaa8be7b378ba69b91e765 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:32 -0700 Subject: nfp: reorganize the app table The app table is an unordered array right now. We have to search apps by ID. It also makes it harder to fall back to core NIC if advanced functions are not compiled into the kernel (e.g. eBPF). Make the table keyed by app id. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_app.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c index 5d9e2eba5b49..085c5151c601 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c @@ -43,10 +43,10 @@ #include "nfp_net_repr.h" static const struct nfp_app_type *apps[] = { - &app_nic, - &app_bpf, + [NFP_APP_CORE_NIC] = &app_nic, + [NFP_APP_BPF_NIC] = &app_bpf, #ifdef CONFIG_NFP_APP_FLOWER - &app_flower, + [NFP_APP_FLOWER_NIC] = &app_flower, #endif }; @@ -116,17 +116,13 @@ exit_unlock: struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id) { struct nfp_app *app; - unsigned int i; - for (i = 0; i < ARRAY_SIZE(apps); i++) - if (apps[i]->id == id) - break; - if (i == ARRAY_SIZE(apps)) { + if (id >= ARRAY_SIZE(apps) || !apps[id]) { nfp_err(pf->cpp, "failed to find app with ID 0x%02hhx\n", id); return ERR_PTR(-EINVAL); } - if (WARN_ON(!apps[i]->name || !apps[i]->vnic_alloc)) + if (WARN_ON(!apps[id]->name || !apps[id]->vnic_alloc)) return ERR_PTR(-EINVAL); app = kzalloc(sizeof(*app), GFP_KERNEL); @@ -136,7 +132,7 @@ struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id) app->pf = pf; app->cpp = pf->cpp; app->pdev = pf->pdev; - app->type = apps[i]; + app->type = apps[id]; return app; } -- cgit v1.2.3 From 43b45245e5a6c274f374ecb49e5bca39f28dbfad Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:33 -0700 Subject: nfp: bpf: fall back to core NIC app if BPF not selected If kernel config does not include BPF just replace the BPF app handler with the handler for basic NIC. The BPF app will now be built only if BPF infrastructure is selected in kernel config. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/Makefile | 4 ++-- drivers/net/ethernet/netronome/nfp/bpf/offload.c | 3 --- drivers/net/ethernet/netronome/nfp/nfp_app.c | 4 ++++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/Makefile b/drivers/net/ethernet/netronome/nfp/Makefile index bd3b2bd408bc..9e8d30cb1517 100644 --- a/drivers/net/ethernet/netronome/nfp/Makefile +++ b/drivers/net/ethernet/netronome/nfp/Makefile @@ -27,8 +27,6 @@ nfp-objs := \ nfp_net_sriov.o \ nfp_netvf_main.o \ nfp_port.o \ - bpf/main.o \ - bpf/offload.o \ nic/main.o ifeq ($(CONFIG_NFP_APP_FLOWER),y) @@ -44,6 +42,8 @@ endif ifeq ($(CONFIG_BPF_SYSCALL),y) nfp-objs += \ + bpf/main.o \ + bpf/offload.o \ bpf/verifier.o \ bpf/jit.o endif diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c index 63c8f7847054..6d576f631392 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c @@ -150,9 +150,6 @@ nfp_net_bpf_offload_prepare(struct nfp_net *nn, unsigned int max_mtu; int ret; - if (!IS_ENABLED(CONFIG_BPF_SYSCALL)) - return -EOPNOTSUPP; - ret = nfp_net_bpf_get_act(nn, cls_bpf); if (ret < 0) return ret; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c index 085c5151c601..3644d74fe304 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c @@ -44,7 +44,11 @@ static const struct nfp_app_type *apps[] = { [NFP_APP_CORE_NIC] = &app_nic, +#ifdef CONFIG_BPF_SYSCALL [NFP_APP_BPF_NIC] = &app_bpf, +#else + [NFP_APP_BPF_NIC] = &app_nic, +#endif #ifdef CONFIG_NFP_APP_FLOWER [NFP_APP_FLOWER_NIC] = &app_flower, #endif -- cgit v1.2.3 From 790a399171831d31c8016a27294ef69130d3e7cc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:34 -0700 Subject: nfp: switch to dev_alloc_page() Use the dev_alloc_page() networking helper to allocate pages for RX packets. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index eddf850a6a7f..7147335a8b36 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1212,7 +1212,7 @@ static void *nfp_net_napi_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) } else { struct page *page; - page = alloc_page(GFP_ATOMIC | __GFP_COLD); + page = dev_alloc_page(); frag = page ? page_address(page) : NULL; } if (!frag) { -- cgit v1.2.3 From 16f50cda06ae023cb7beb15c88233fc516c03a2a Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:35 -0700 Subject: nfp: use a counter instead of log message for allocation failures Add a counter incremented when allocation of replacement RX page fails. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 3 +++ drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 15 ++++++++++----- drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 12 +++++++----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index d51d8237b984..3d411f0d15b6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -394,6 +394,7 @@ struct nfp_net_rx_ring { * @tx_lso: Counter of LSO packets sent * @tx_errors: How many TX errors were encountered * @tx_busy: How often was TX busy (no space)? + * @rx_replace_buf_alloc_fail: Counter of RX buffer allocation failures * @irq_vector: Interrupt vector number (use for talking to the OS) * @handler: Interrupt handler for this ring vector * @name: Name of the interrupt vector @@ -437,6 +438,8 @@ struct nfp_net_r_vector { u64 hw_csum_tx_inner; u64 tx_gather; u64 tx_lso; + + u64 rx_replace_buf_alloc_fail; u64 tx_errors; u64 tx_busy; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 7147335a8b36..185a3dd35a3f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1209,15 +1209,15 @@ static void *nfp_net_napi_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) if (!dp->xdp_prog) { frag = napi_alloc_frag(dp->fl_bufsz); + if (unlikely(!frag)) + return NULL; } else { struct page *page; page = dev_alloc_page(); - frag = page ? page_address(page) : NULL; - } - if (!frag) { - nn_dp_warn(dp, "Failed to alloc receive page frag\n"); - return NULL; + if (unlikely(!page)) + return NULL; + frag = page_address(page); } *dma_addr = nfp_net_dma_map_rx(dp, frag); @@ -1514,6 +1514,11 @@ nfp_net_rx_drop(const struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec, { u64_stats_update_begin(&r_vec->rx_sync); r_vec->rx_drops++; + /* If we have both skb and rxbuf the replacement buffer allocation + * must have failed, count this as an alloc failure. + */ + if (skb && rxbuf) + r_vec->rx_replace_buf_alloc_fail++; u64_stats_update_end(&r_vec->rx_sync); /* skb is build based on the frag, free_skb() would free the frag diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index dc016dfec64d..6d5c376f0000 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -181,7 +181,7 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = { #define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats) #define NN_ET_SWITCH_STATS_LEN 9 -#define NN_ET_RVEC_GATHER_STATS 7 +#define NN_ET_RVEC_GATHER_STATS 8 static void nfp_net_get_nspinfo(struct nfp_app *app, char *version) { @@ -444,6 +444,7 @@ static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data) data = nfp_pr_et(data, "hw_rx_csum_ok"); data = nfp_pr_et(data, "hw_rx_csum_inner_ok"); data = nfp_pr_et(data, "hw_rx_csum_err"); + data = nfp_pr_et(data, "rx_replace_buf_alloc_fail"); data = nfp_pr_et(data, "hw_tx_csum"); data = nfp_pr_et(data, "hw_tx_inner_csum"); data = nfp_pr_et(data, "tx_gather"); @@ -468,16 +469,17 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) tmp[0] = nn->r_vecs[i].hw_csum_rx_ok; tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok; tmp[2] = nn->r_vecs[i].hw_csum_rx_error; + tmp[3] = nn->r_vecs[i].rx_replace_buf_alloc_fail; } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start)); do { start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync); data[1] = nn->r_vecs[i].tx_pkts; data[2] = nn->r_vecs[i].tx_busy; - tmp[3] = nn->r_vecs[i].hw_csum_tx; - tmp[4] = nn->r_vecs[i].hw_csum_tx_inner; - tmp[5] = nn->r_vecs[i].tx_gather; - tmp[6] = nn->r_vecs[i].tx_lso; + tmp[4] = nn->r_vecs[i].hw_csum_tx; + tmp[5] = nn->r_vecs[i].hw_csum_tx_inner; + tmp[6] = nn->r_vecs[i].tx_gather; + tmp[7] = nn->r_vecs[i].tx_lso; } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start)); data += 3; -- cgit v1.2.3 From 18f76191796ad478e42528cfafcae0b11d4c8db4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 2 Nov 2017 01:31:36 -0700 Subject: nfp: improve defines for constants in ethtool We split rvector stats into two categories - per queue and stats which are added up into one total counter. Improve the defines denoting their number. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 6d5c376f0000..c67b90c8d8b7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -181,7 +181,8 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = { #define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats) #define NN_ET_SWITCH_STATS_LEN 9 -#define NN_ET_RVEC_GATHER_STATS 8 +#define NN_RVEC_GATHER_STATS 8 +#define NN_RVEC_PER_Q_STATS 3 static void nfp_net_get_nspinfo(struct nfp_app *app, char *version) { @@ -427,7 +428,7 @@ static unsigned int nfp_vnic_get_sw_stats_count(struct net_device *netdev) { struct nfp_net *nn = netdev_priv(netdev); - return NN_ET_RVEC_GATHER_STATS + nn->dp.num_r_vecs * 3; + return NN_RVEC_GATHER_STATS + nn->dp.num_r_vecs * NN_RVEC_PER_Q_STATS; } static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data) @@ -455,9 +456,9 @@ static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data) static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) { - u64 gathered_stats[NN_ET_RVEC_GATHER_STATS] = {}; + u64 gathered_stats[NN_RVEC_GATHER_STATS] = {}; struct nfp_net *nn = netdev_priv(netdev); - u64 tmp[NN_ET_RVEC_GATHER_STATS]; + u64 tmp[NN_RVEC_GATHER_STATS]; unsigned int i, j; for (i = 0; i < nn->dp.num_r_vecs; i++) { @@ -482,13 +483,13 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) tmp[7] = nn->r_vecs[i].tx_lso; } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start)); - data += 3; + data += NN_RVEC_PER_Q_STATS; - for (j = 0; j < NN_ET_RVEC_GATHER_STATS; j++) + for (j = 0; j < NN_RVEC_GATHER_STATS; j++) gathered_stats[j] += tmp[j]; } - for (j = 0; j < NN_ET_RVEC_GATHER_STATS; j++) + for (j = 0; j < NN_RVEC_GATHER_STATS; j++) *data++ = gathered_stats[j]; return data; -- cgit v1.2.3