Author: davidcs
Date: Wed Apr 19 03:02:23 2017
New Revision: 317113
URL: https://svnweb.freebsd.org/changeset/base/317113

Log:
  MFC r316309
  Add support for optional Soft LRO

Modified:
  stable/9/sys/dev/qlxgbe/ql_hw.c
  stable/9/sys/dev/qlxgbe/ql_hw.h
  stable/9/sys/dev/qlxgbe/ql_isr.c
  stable/9/sys/dev/qlxgbe/ql_os.c
Directory Properties:
  stable/9/   (props changed)
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/qlxgbe/ql_hw.c
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_hw.c     Wed Apr 19 02:59:26 2017        
(r317112)
+++ stable/9/sys/dev/qlxgbe/ql_hw.c     Wed Apr 19 03:02:23 2017        
(r317113)
@@ -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: stable/9/sys/dev/qlxgbe/ql_hw.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_hw.h     Wed Apr 19 02:59:26 2017        
(r317112)
+++ stable/9/sys/dev/qlxgbe/ql_hw.h     Wed Apr 19 03:02:23 2017        
(r317113)
@@ -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: stable/9/sys/dev/qlxgbe/ql_isr.c
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_isr.c    Wed Apr 19 02:59:26 2017        
(r317112)
+++ stable/9/sys/dev/qlxgbe/ql_isr.c    Wed Apr 19 03:02:23 2017        
(r317113)
@@ -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;
@@ -161,7 +164,22 @@ qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_
        mpf->m_pkthdr.flowid = sgc->rss_hash;
        mpf->m_flags |= M_FLOWID;
 
-       (*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);
@@ -703,6 +721,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: stable/9/sys/dev/qlxgbe/ql_os.c
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_os.c     Wed Apr 19 02:59:26 2017        
(r317112)
+++ stable/9/sys/dev/qlxgbe/ql_os.c     Wed Apr 19 03:02:23 2017        
(r317113)
@@ -1077,6 +1077,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);
@@ -1518,7 +1520,6 @@ qla_qflush(struct ifnet *ifp)
         return;
 }
 
-
 static void
 qla_stop(qla_host_t *ha)
 {
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to