From 15d73bf7b6943d1a7b4c41802fb44bdd7989f4ba Mon Sep 17 00:00:00 2001 From: Pradeep Gopanapalli Date: Tue, 1 Nov 2016 19:34:29 +0000 Subject: [PATCH] xsigo: Optimizing Transmit completions Orabug: 24928865 Added a timer for polling Transmit completion and removed polling completion from a thread context. Seeing Good Performance improvments with the changes. In some cases uVNIC is seeing 10% increase in throughput Reported-by: Pradeep Gopanapalli Signed-off-by: Pradeep Gopanapalli Reviewed-by: sajid zia --- drivers/infiniband/ulp/xsigo/xscore/Makefile | 2 +- drivers/infiniband/ulp/xsigo/xsvhba/Makefile | 2 +- drivers/infiniband/ulp/xsigo/xsvnic/Makefile | 2 +- drivers/infiniband/ulp/xsigo/xve/Makefile | 2 +- drivers/infiniband/ulp/xsigo/xve/xve.h | 6 ++- drivers/infiniband/ulp/xsigo/xve/xve_ib.c | 53 +++++++++++++------ drivers/infiniband/ulp/xsigo/xve/xve_main.c | 28 +++++----- .../infiniband/ulp/xsigo/xve/xve_multicast.c | 10 ++-- drivers/infiniband/ulp/xsigo/xve/xve_stats.c | 5 +- 9 files changed, 68 insertions(+), 42 deletions(-) diff --git a/drivers/infiniband/ulp/xsigo/xscore/Makefile b/drivers/infiniband/ulp/xsigo/xscore/Makefile index 59f4757d18ed..06e05f91bd64 100644 --- a/drivers/infiniband/ulp/xsigo/xscore/Makefile +++ b/drivers/infiniband/ulp/xsigo/xscore/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_INFINIBAND_XSCORE) := xscore.o xscore-y := xscore_impl.o xs_ud.o xscore_api.o xsmp.o \ xscore_stats.o xscore_uadm.o -ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8029\" +ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8031\" ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT diff --git a/drivers/infiniband/ulp/xsigo/xsvhba/Makefile b/drivers/infiniband/ulp/xsigo/xsvhba/Makefile index 7900b401d044..08e128851670 100644 --- a/drivers/infiniband/ulp/xsigo/xsvhba/Makefile +++ b/drivers/infiniband/ulp/xsigo/xsvhba/Makefile @@ -3,7 +3,7 @@ xsvhba-y := vhba_main.o vhba_xsmp.o vhba_create.o vhba_init.o vhba_delete.o \ vhba_attr.o vhba_wq.o vhba_proc.o vhba_stats.o vhba_ib.o \ vhba_scsi_intf.o vhba_align.o -ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8029\" +ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8031\" ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT diff --git a/drivers/infiniband/ulp/xsigo/xsvnic/Makefile b/drivers/infiniband/ulp/xsigo/xsvnic/Makefile index f9e33c532184..3f4edcdcc46c 100644 --- a/drivers/infiniband/ulp/xsigo/xsvnic/Makefile +++ b/drivers/infiniband/ulp/xsigo/xsvnic/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_INFINIBAND_XSVNIC) := xsvnic.o xsvnic-y := xsvnic_main.o xsvnic_stats.o -ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8029\" +ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8031\" ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT diff --git a/drivers/infiniband/ulp/xsigo/xve/Makefile b/drivers/infiniband/ulp/xsigo/xve/Makefile index 50b46acbcb5c..1f038eabdbc4 100644 --- a/drivers/infiniband/ulp/xsigo/xve/Makefile +++ b/drivers/infiniband/ulp/xsigo/xve/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_INFINIBAND_XVE) := xve.o xve-y := xve_main.o xve_verbs.o xve_multicast.o xve_ib.o xve_tables.o \ xve_ethtool.o xve_cm.o xve_stats.o -ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8029\" +ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8031\" ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT diff --git a/drivers/infiniband/ulp/xsigo/xve/xve.h b/drivers/infiniband/ulp/xsigo/xve/xve.h index a31f5219003b..1be1cd700641 100644 --- a/drivers/infiniband/ulp/xsigo/xve/xve.h +++ b/drivers/infiniband/ulp/xsigo/xve/xve.h @@ -236,6 +236,7 @@ enum { XVE_TX_DROP_OPER_DOWN_COUNT, XVE_TX_SKB_ALLOC_ERROR_COUNTER, XVE_TX_RING_FULL_COUNTER, + XVE_TX_WMARK_REACH_COUNTER, XVE_TX_WAKE_UP_COUNTER, XVE_TX_QUEUE_STOP_COUNTER, XVE_RX_SKB_COUNTER, @@ -292,6 +293,7 @@ enum { XVE_TX_UD_COUNTER, XVE_TX_RC_COUNTER, XVE_TX_MCAST_PKT, + XVE_TX_BCAST_PKT, XVE_TX_MCAST_ARP_QUERY, XVE_TX_MCAST_NDP_QUERY, XVE_TX_MCAST_ARP_VLAN_QUERY, @@ -707,6 +709,7 @@ struct xve_dev_priv { struct net_device_stats stats; struct napi_struct napi; struct xve_ethtool_st ethtool; + struct timer_list poll_timer; u8 lro_mode; struct xve_lro lro; unsigned long flags; @@ -1179,7 +1182,8 @@ void xve_remove_fwt_entry(struct xve_dev_priv *priv, void xve_fwt_entry_free(struct xve_dev_priv *priv, struct xve_fwt_entry *fwt_entry); -int xve_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); +int xve_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb, + u8 bcast); void xve_advert_mcast_join(struct xve_dev_priv *priv); int xve_mcast_start_thread(struct net_device *dev); int xve_mcast_stop_thread(struct net_device *dev, int flush); diff --git a/drivers/infiniband/ulp/xsigo/xve/xve_ib.c b/drivers/infiniband/ulp/xsigo/xve/xve_ib.c index 73c71114ab5c..08c3850a20ff 100644 --- a/drivers/infiniband/ulp/xsigo/xve/xve_ib.c +++ b/drivers/infiniband/ulp/xsigo/xve/xve_ib.c @@ -694,17 +694,31 @@ void xve_data_recv_handler(struct xve_dev_priv *priv) } } -void xve_send_comp_handler(struct ib_cq *cq, void *dev_ptr) +static void xve_ib_tx_timer_func(unsigned long ctx) { - struct xve_dev_priv *priv = netdev_priv((struct net_device *)dev_ptr); + struct net_device *dev = (struct net_device *)ctx; + struct xve_dev_priv *priv = netdev_priv(dev); unsigned long flags = 0; + netif_tx_lock(dev); spin_lock_irqsave(&priv->lock, flags); if (test_bit(XVE_OPER_UP, &priv->state) && - !test_bit(XVE_DELETING, &priv->state)) { + !test_bit(XVE_DELETING, &priv->state)) { poll_tx(priv); } spin_unlock_irqrestore(&priv->lock, flags); + if (netif_queue_stopped(dev)) + mod_timer(&priv->poll_timer, jiffies + 1); + + netif_tx_unlock(dev); +} + + +void xve_send_comp_handler(struct ib_cq *cq, void *dev_ptr) +{ + struct xve_dev_priv *priv = netdev_priv((struct net_device *)dev_ptr); + + mod_timer(&priv->poll_timer, jiffies); } static inline int post_send(struct xve_dev_priv *priv, @@ -761,8 +775,10 @@ static inline int post_send(struct xve_dev_priv *priv, /* Always called with priv->lock held * type argument is used to differentiate between the GATEWAY * and UVNIC packet. - * 1 -> GATEWAY PACKET * 0 -> normal UVNIC PACKET + * 1 -> GATEWAY Broadcast PACKET + * 2 -> Sending Queued PACKET + * 3 -> Path Not found PACKET */ int xve_send(struct net_device *dev, struct sk_buff *skb, struct xve_ah *address, u32 qpn, int type) @@ -772,6 +788,7 @@ int xve_send(struct net_device *dev, struct sk_buff *skb, int hlen; void *phead; int ret = NETDEV_TX_OK; + u8 packet_sent = 0; if (skb_is_gso(skb)) { hlen = skb_transport_offset(skb) + tcp_hdrlen(skb); @@ -843,16 +860,6 @@ int xve_send(struct net_device *dev, struct sk_buff *skb, netif_stop_queue(dev); } - if (netif_queue_stopped(dev)) { - int rc; - - rc = ib_req_notify_cq(priv->send_cq, - IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS); - if (rc < 0) - xve_warn(priv, "request notify on send CQ failed\n"); - else if (rc) - poll_tx(priv); - } skb_orphan(skb); skb_dst_drop(skb); @@ -874,17 +881,24 @@ int xve_send(struct net_device *dev, struct sk_buff *skb, --priv->tx_outstanding; priv->counters[XVE_TX_RING_FULL_COUNTER]++; xve_put_ah_refcnt(address); + xve_free_txbuf_memory(priv, tx_req); if (netif_queue_stopped(dev)) { priv->counters[XVE_TX_WAKE_UP_COUNTER]++; netif_wake_queue(dev); } - xve_free_txbuf_memory(priv, tx_req); - } else + } else { + packet_sent = 1; ++priv->tx_head; + } priv->send_hbeat_flag = 0; - if (unlikely(priv->tx_outstanding > SENDQ_LOW_WMARK)) + if (unlikely(priv->tx_outstanding > SENDQ_LOW_WMARK)) { + priv->counters[XVE_TX_WMARK_REACH_COUNTER]++; poll_tx(priv); + } + + if (packet_sent) + priv->counters[XVE_TX_COUNTER]++; return ret; } @@ -1157,6 +1171,8 @@ int xve_ib_dev_stop(struct net_device *dev, int flush) xve_debug(DEBUG_IBDEV_INFO, priv, "%s All sends and receives done\n", __func__); timeout: + xve_warn(priv, "Deleting TX timer"); + del_timer_sync(&priv->poll_timer); qp_attr.qp_state = IB_QPS_RESET; if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) xve_warn(priv, "Failed to modify QP to RESET state\n"); @@ -1184,6 +1200,9 @@ int xve_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return -ENODEV; } + setup_timer(&priv->poll_timer, xve_ib_tx_timer_func, + (unsigned long)dev); + if (dev->flags & IFF_UP) { if (xve_ib_dev_open(dev) != 0) { xve_transport_dev_cleanup(dev); diff --git a/drivers/infiniband/ulp/xsigo/xve/xve_main.c b/drivers/infiniband/ulp/xsigo/xve/xve_main.c index 45b1e2d9b3fa..53f93f8718ea 100644 --- a/drivers/infiniband/ulp/xsigo/xve/xve_main.c +++ b/drivers/infiniband/ulp/xsigo/xve/xve_main.c @@ -622,7 +622,7 @@ static void path_rec_completion(int status, skb->dev = dev; xve_get_ah_refcnt(path->ah); /* Sending the queued GATEWAY Packet */ - ret = xve_send(dev, skb, path->ah, priv->gw.t_data_qp, 1); + ret = xve_send(dev, skb, path->ah, priv->gw.t_data_qp, 2); if (ret == NETDEV_TX_BUSY) { xve_warn(priv, "send queue full full, dropping packet for %s\n", priv->xve_name); @@ -892,9 +892,15 @@ static int xve_start_xmit(struct sk_buff *skb, struct net_device *dev) fwt_entry = xve_fwt_lookup(&priv->xve_fwt, eth_hdr(skb)->h_dest, vlan_tag, 0); if (!fwt_entry) { - if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { + if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) { + ret = xve_mcast_send(dev, + (void *)priv->bcast_mgid.raw, skb, 1); + priv->counters[XVE_TX_BCAST_PKT]++; + goto stats; + } else if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { + /* For Now Send Multicast Packet to G/W also */ ret = xve_mcast_send(dev, - (void *)priv->bcast_mgid.raw, skb); + (void *)priv->bcast_mgid.raw, skb, 1); priv->counters[XVE_TX_MCAST_PKT]++; goto stats; } else { @@ -920,7 +926,7 @@ static int xve_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bcast_skb != NULL) ret = xve_mcast_send(dev, (void *)priv->bcast_mgid. - raw, bcast_skb); + raw, bcast_skb, 1); /* * Now send the original packet also to over broadcast * Later add counters for flood mode @@ -928,7 +934,7 @@ static int xve_start_xmit(struct sk_buff *skb, struct net_device *dev) if (xve_is_edr(priv) || len < XVE_UD_MTU(priv->max_ib_mtu)) { ret = xve_mcast_send(dev, - (void *)priv->bcast_mgid.raw, skb); + (void *)priv->bcast_mgid.raw, skb, 1); priv->counters[XVE_TX_MCAST_FLOOD_UD]++; } else { if (xve_flood_rc) { @@ -982,7 +988,7 @@ static int xve_start_xmit(struct sk_buff *skb, struct net_device *dev) xve_debug(DEBUG_SEND_INFO, priv, "%s path ah is %p\n", __func__, path->ah); xve_get_ah_refcnt(path->ah); - ret = xve_send(dev, skb, path->ah, fwt_entry->dqpn, 0); + ret = xve_send(dev, skb, path->ah, fwt_entry->dqpn, 3); priv->counters[XVE_TX_UD_COUNTER]++; goto stats; } @@ -1001,7 +1007,6 @@ static int xve_start_xmit(struct sk_buff *skb, struct net_device *dev) stats: INC_TX_PKT_STATS(priv, dev); INC_TX_BYTE_STATS(priv, dev, len); - priv->counters[XVE_TX_COUNTER]++; free_fwt_ctx: if (path) xve_put_path(path, 0); @@ -1601,15 +1606,6 @@ static int xve_state_machine(struct xve_dev_priv *priv) handle_action_flags(priv); if (priv->send_hbeat_flag) { - unsigned long flags = 0; - - if (unlikely(priv->tx_outstanding > SENDQ_LOW_WMARK)) { - netif_tx_lock(priv->netdev); - spin_lock_irqsave(&priv->lock, flags); - poll_tx(priv); - spin_unlock_irqrestore(&priv->lock, flags); - netif_tx_unlock(priv->netdev); - } if (xve_is_ovn(priv)) xve_send_hbeat(priv); } diff --git a/drivers/infiniband/ulp/xsigo/xve/xve_multicast.c b/drivers/infiniband/ulp/xsigo/xve/xve_multicast.c index a753a6e5f47e..917ceafe74db 100644 --- a/drivers/infiniband/ulp/xsigo/xve/xve_multicast.c +++ b/drivers/infiniband/ulp/xsigo/xve/xve_multicast.c @@ -667,7 +667,8 @@ static int xve_mcast_leave(struct net_device *dev, struct xve_mcast *mcast) return 0; } -int xve_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) +int xve_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb, + u8 broadcast) { struct xve_dev_priv *priv = netdev_priv(dev); struct xve_mcast *mcast; @@ -681,11 +682,14 @@ int xve_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) return ret; } - if (xve_is_uplink(priv) && xve_gw_linkup(priv)) { + if (broadcast && (xve_is_uplink(priv) && xve_gw_linkup(priv))) { struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); - if (nskb) + if (nskb) { ret = xve_gw_send(dev, nskb); + if (ret != NETDEV_TX_OK) + return ret; + } } mcast = __xve_mcast_find(dev, mgid); diff --git a/drivers/infiniband/ulp/xsigo/xve/xve_stats.c b/drivers/infiniband/ulp/xsigo/xve/xve_stats.c index 4a426b6a23af..77f833576747 100755 --- a/drivers/infiniband/ulp/xsigo/xve/xve_stats.c +++ b/drivers/infiniband/ulp/xsigo/xve/xve_stats.c @@ -73,6 +73,7 @@ static char *counter_name[XVE_MAX_COUNTERS] = { "tx drop oper down count:\t", "tx drop skb error count:\t", "tx drop ring full count:\t", + "tx ring wmark reached count:\t", "tx wake up count\t\t", "tx queue stop count:\t\t", "rx_skb_count:\t\t\t", @@ -126,6 +127,7 @@ static char *counter_name[XVE_MAX_COUNTERS] = { "tx ud count:\t\t\t", "tx rc count:\t\t\t", "tx mcast count:\t\t\t", + "tx broadcast count:\t\t\t", "tx arp count:\t\t\t", "tx ndp count:\t\t\t", "tx arp vlan count:\t\t", @@ -146,7 +148,7 @@ static char *counter_name[XVE_MAX_COUNTERS] = { "ib lid_active count:\t\t", "ib pkey_change count:\t\t", "ib invalid count:\t\t", - "uplink unicast:\t\t\t", + "tx uplink broadcast:\t\t\t", "Heartbeat Count(0x8919):\t\t", "Link State message count:\t", "RX frames without GRH\t\t", @@ -468,6 +470,7 @@ static int xve_proc_read_device(struct seq_file *m, void *data) seq_printf(m, "Receive Queue size: \t\t%d\n", vp->xve_recvq_size); seq_printf(m, "Transmit Queue size: \t\t%d\n", vp->xve_sendq_size); + seq_printf(m, "Completion Queue size: \t\t%d\n", vp->xve_max_send_cqe); if (vp->cm_supported) { seq_printf(m, "Num of cm frags: \t\t%d\n", vp->cm.num_frags); -- 2.50.1