svn commit: r316309 - head/sys/dev/qlxgbe

David C Somayajulu davidcs at FreeBSD.org
Thu Mar 30 22:44:49 UTC 2017


Author: davidcs
Date: Thu Mar 30 22:43:32 2017
New Revision: 316309
URL: https://svnweb.freebsd.org/changeset/base/316309

Log:
  Add support for optional Soft LRO
  
  MFC after:5 days

Modified:
  head/sys/dev/qlxgbe/ql_hw.c
  head/sys/dev/qlxgbe/ql_hw.h
  head/sys/dev/qlxgbe/ql_isr.c
  head/sys/dev/qlxgbe/ql_os.c

Modified: head/sys/dev/qlxgbe/ql_hw.c
==============================================================================
--- head/sys/dev/qlxgbe/ql_hw.c	Thu Mar 30 22:26:15 2017	(r316308)
+++ head/sys/dev/qlxgbe/ql_hw.c	Thu Mar 30 22:43:32 2017	(r316309)
@@ -440,6 +440,17 @@ ql_hw_add_sysctls(qla_host_t *ha)
                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
 
+        ha->hw.enable_hw_lro = 1;
+
+        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
+                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+                OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
+                ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
+		"\t 1 : Hardware LRO if LRO is enabled\n"
+		"\t 0 : Software LRO if LRO is enabled\n"
+		"\t Any change requires ifconfig down/up to take effect\n"
+		"\t Note that LRO may be turned off/on via ifconfig\n");
+
 	ha->hw.mdump_active = 0;
         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@@ -2255,6 +2266,83 @@ qla_config_rss_ind_table(qla_host_t *ha)
 	return (0);
 }
 
+static int
+qla_config_soft_lro(qla_host_t *ha)
+{
+        int i;
+        qla_hw_t *hw = &ha->hw;
+        struct lro_ctrl *lro;
+
+        for (i = 0; i < hw->num_sds_rings; i++) {
+                lro = &hw->sds[i].lro;
+
+		bzero(lro, sizeof(struct lro_ctrl));
+
+#if (__FreeBSD_version >= 1100101)
+                if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
+                        device_printf(ha->pci_dev,
+				"%s: tcp_lro_init_args [%d] failed\n",
+                                __func__, i);
+                        return (-1);
+                }
+#else
+                if (tcp_lro_init(lro)) {
+                        device_printf(ha->pci_dev,
+				"%s: tcp_lro_init [%d] failed\n",
+                                __func__, i);
+                        return (-1);
+                }
+#endif /* #if (__FreeBSD_version >= 1100101) */
+
+                lro->ifp = ha->ifp;
+        }
+
+        QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
+        return (0);
+}
+
+static void
+qla_drain_soft_lro(qla_host_t *ha)
+{
+        int i;
+        qla_hw_t *hw = &ha->hw;
+        struct lro_ctrl *lro;
+
+       	for (i = 0; i < hw->num_sds_rings; i++) {
+               	lro = &hw->sds[i].lro;
+
+#if (__FreeBSD_version >= 1100101)
+		tcp_lro_flush_all(lro);
+#else
+                struct lro_entry *queued;
+
+		while ((!SLIST_EMPTY(&lro->lro_active))) {
+			queued = SLIST_FIRST(&lro->lro_active);
+			SLIST_REMOVE_HEAD(&lro->lro_active, next);
+			tcp_lro_flush(lro, queued);
+		}
+#endif /* #if (__FreeBSD_version >= 1100101) */
+	}
+
+	return;
+}
+
+static void
+qla_free_soft_lro(qla_host_t *ha)
+{
+        int i;
+        qla_hw_t *hw = &ha->hw;
+        struct lro_ctrl *lro;
+
+        for (i = 0; i < hw->num_sds_rings; i++) {
+               	lro = &hw->sds[i].lro;
+		tcp_lro_free(lro);
+	}
+
+	return;
+}
+
+
 /*
  * Name: ql_del_hw_if
  * Function: Destroys the hardware specific entities corresponding to an
@@ -2287,6 +2375,11 @@ ql_del_hw_if(qla_host_t *ha)
 		ha->hw.flags.init_intr_cnxt = 0;
 	}
 
+	if (ha->hw.enable_soft_lro) {
+		qla_drain_soft_lro(ha);
+		qla_free_soft_lro(ha);
+	}
+
 	return;
 }
 
@@ -2309,7 +2402,6 @@ qla_confirm_9kb_enable(qla_host_t *ha)
 	return;
 }
 
-
 /*
  * Name: ql_init_hw_if
  * Function: Creates the hardware specific entities corresponding to an
@@ -2416,8 +2508,19 @@ ql_init_hw_if(qla_host_t *ha)
 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
 		return (-1);
 
-	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
-		return (-1);
+	if (ha->ifp->if_capenable & IFCAP_LRO) {
+		if (ha->hw.enable_hw_lro) {
+			ha->hw.enable_soft_lro = 0;
+
+			if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
+				return (-1);
+		} else {
+			ha->hw.enable_soft_lro = 1;
+
+			if (qla_config_soft_lro(ha))
+				return (-1);
+		}
+	}
 
         if (qla_init_nic_func(ha))
                 return (-1);

Modified: head/sys/dev/qlxgbe/ql_hw.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_hw.h	Thu Mar 30 22:26:15 2017	(r316308)
+++ head/sys/dev/qlxgbe/ql_hw.h	Thu Mar 30 22:43:32 2017	(r316309)
@@ -1674,6 +1674,8 @@ typedef struct _qla_hw {
 	uint32_t	max_tx_segs;
 	uint32_t	min_lro_pkt_size;
 	
+	uint32_t        enable_hw_lro;
+	uint32_t        enable_soft_lro;
 	uint32_t        enable_9kb;
 
 	uint32_t	user_pri_nic;

Modified: head/sys/dev/qlxgbe/ql_isr.c
==============================================================================
--- head/sys/dev/qlxgbe/ql_isr.c	Thu Mar 30 22:26:15 2017	(r316308)
+++ head/sys/dev/qlxgbe/ql_isr.c	Thu Mar 30 22:43:32 2017	(r316309)
@@ -68,6 +68,9 @@ qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_
 	uint32_t		i, rem_len = 0;
 	uint32_t		r_idx = 0;
 	qla_rx_ring_t		*rx_ring;
+	struct lro_ctrl		*lro;
+
+	lro = &ha->hw.sds[sds_idx].lro;
 
 	if (ha->hw.num_rds_rings > 1)
 		r_idx = sds_idx;
@@ -166,7 +169,22 @@ qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_
 	M_HASHTYPE_SET(mpf, M_HASHTYPE_NONE);
 #endif /* #if __FreeBSD_version >= 1100000 */
 
-	(*ifp->if_input)(ifp, mpf);
+	if (ha->hw.enable_soft_lro) {
+
+#if (__FreeBSD_version >= 1100101)
+
+		tcp_lro_queue_mbuf(lro, mpf);
+
+#else
+		if (tcp_lro_rx(lro, mpf, 0))
+			(*ifp->if_input)(ifp, mpf);
+
+#endif /* #if (__FreeBSD_version >= 1100101) */
+
+
+	} else {
+		(*ifp->if_input)(ifp, mpf);
+	}
 
 	if (sdsp->rx_free > ha->std_replenish)
 		qla_replenish_normal_rx(ha, sdsp, r_idx);
@@ -707,6 +725,28 @@ ql_rcv_isr(qla_host_t *ha, uint32_t sds_
 		}
 	}
 
+	if (ha->hw.enable_soft_lro) {
+		struct lro_ctrl		*lro;
+
+		lro = &ha->hw.sds[sds_idx].lro;
+
+#if (__FreeBSD_version >= 1100101)
+
+		tcp_lro_flush_all(lro);
+
+#else
+		struct lro_entry *queued;
+
+		while ((!SLIST_EMPTY(&lro->lro_active))) {
+			queued = SLIST_FIRST(&lro->lro_active);
+			SLIST_REMOVE_HEAD(&lro->lro_active, next);
+			tcp_lro_flush(lro, queued);
+		}
+
+#endif /* #if (__FreeBSD_version >= 1100101) */
+
+	}
+
 	if (ha->flags.stop_rcv)
 		goto ql_rcv_isr_exit;
 

Modified: head/sys/dev/qlxgbe/ql_os.c
==============================================================================
--- head/sys/dev/qlxgbe/ql_os.c	Thu Mar 30 22:26:15 2017	(r316308)
+++ head/sys/dev/qlxgbe/ql_os.c	Thu Mar 30 22:43:32 2017	(r316309)
@@ -1072,6 +1072,8 @@ qla_ioctl(struct ifnet *ifp, u_long cmd,
 			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 		if (mask & IFCAP_VLAN_HWTSO)
 			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
+		if (mask & IFCAP_LRO)
+			ifp->if_capenable ^= IFCAP_LRO;
 
 		if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
 			qla_init(ha);
@@ -1497,7 +1499,6 @@ qla_qflush(struct ifnet *ifp)
         return;
 }
 
-
 static void
 qla_stop(qla_host_t *ha)
 {


More information about the svn-src-all mailing list