staging/rdma/hfi1: Method to toggle "fast ECN" detection
authorVennila Megavannan <vennila.megavannan@intel.com>
Wed, 3 Feb 2016 22:32:57 +0000 (14:32 -0800)
committerDoug Ledford <dledford@redhat.com>
Fri, 11 Mar 2016 01:37:50 +0000 (20:37 -0500)
Add a per port sysfs paramter to toggle cc_prescan/Fast ECN Detection and
remove the Kconfig option which was previously used to control this.

While am updating the sysfs documentation, fix the name of CCMgtA.

Reviewed-by: Arthur Kepner <arthur.kepner@intel.com>
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Vennila Megavannan <vennila.megavannan@intel.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Documentation/infiniband/sysfs.txt
drivers/staging/rdma/hfi1/Kconfig
drivers/staging/rdma/hfi1/driver.c
drivers/staging/rdma/hfi1/hfi.h
drivers/staging/rdma/hfi1/sysfs.c

index 9028b025501a6e4fab03a3e4be152c8fbbc6694c..3ecf0c3a133fb6a50cd40b42d0d8b87a2d1c99b9 100644 (file)
@@ -78,9 +78,10 @@ HFI1
    chip_reset - diagnostic (root only)
    boardversion - board version
    ports/1/
-          CMgtA/
+          CCMgtA/
                cc_settings_bin - CCA tables used by PSM2
                cc_table_bin
+               cc_prescan - enable prescaning for faster BECN response
           sc2v/ - 32 files (0 - 31) used to translate sl->vl
           sl2sc/ - 32 files (0 - 31) used to translate sl->sc
           vl2mtu/ - 16 (0 - 15) files used to determine MTU for vl
index 846c240c80aa1230b62a8084f3d3c18e5a82f583..3e668d852f03029985b131544d67b2b47fe45376 100644 (file)
@@ -26,13 +26,3 @@ config SDMA_VERBOSITY
        ---help---
        This is a configuration flag to enable verbose
        SDMA debug
-config PRESCAN_RXQ
-       bool "Enable prescanning of the RX queue for ECNs"
-       depends on INFINIBAND_HFI1
-       default n
-       ---help---
-       This option toggles the prescanning of the receive queue for
-       Explicit Congestion Notifications. If an ECN is detected, it
-       is processed as quickly as possible, the ECN is toggled off.
-       After the prescanning step, the receive queue is processed as
-       usual.
index d848cc01f07a1e2f3f7b320681c6e8cfd71e1cb3..59ce85f8d155b42c1c0f3dd220451f09c367019a 100644 (file)
@@ -453,11 +453,6 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
        packet->rcv_flags = 0;
 }
 
-#ifndef CONFIG_PRESCAN_RXQ
-static void prescan_rxq(struct hfi1_packet *packet) {}
-#else /* !CONFIG_PRESCAN_RXQ */
-static int prescan_receive_queue;
-
 static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr,
                        struct hfi1_other_headers *ohdr,
                        u64 rhf, u32 bth1, struct ib_grh *grh)
@@ -581,15 +576,19 @@ static inline void update_ps_mdata(struct ps_mdata *mdata,
  * containing Excplicit Congestion Notifications (FECNs, or BECNs).
  * When an ECN is found, process the Congestion Notification, and toggle
  * it off.
+ * This is declared as a macro to allow quick checking of the port to avoid
+ * the overhead of a function call if not enabled.
  */
-static void prescan_rxq(struct hfi1_packet *packet)
+#define prescan_rxq(rcd, packet) \
+       do { \
+               if (rcd->ppd->cc_prescan) \
+                       __prescan_rxq(packet); \
+       } while (0)
+static void __prescan_rxq(struct hfi1_packet *packet)
 {
        struct hfi1_ctxtdata *rcd = packet->rcd;
        struct ps_mdata mdata;
 
-       if (!prescan_receive_queue)
-               return;
-
        init_ps_mdata(&mdata, packet);
 
        while (1) {
@@ -653,7 +652,6 @@ next:
                update_ps_mdata(&mdata, rcd);
        }
 }
-#endif /* CONFIG_PRESCAN_RXQ */
 
 static inline int skip_rcv_packet(struct hfi1_packet *packet, int thread)
 {
@@ -819,7 +817,7 @@ int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd, int thread)
                goto bail;
        }
 
-       prescan_rxq(&packet);
+       prescan_rxq(rcd, &packet);
 
        while (last == RCV_PKT_OK) {
                last = process_rcv_packet(&packet, thread);
@@ -850,7 +848,7 @@ int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd, int thread)
        }
        smp_rmb();  /* prevent speculative reads of dma'ed hdrq */
 
-       prescan_rxq(&packet);
+       prescan_rxq(rcd, &packet);
 
        while (last == RCV_PKT_OK) {
                last = process_rcv_packet(&packet, thread);
@@ -961,7 +959,7 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread)
                }
        }
 
-       prescan_rxq(&packet);
+       prescan_rxq(rcd, &packet);
 
        while (last == RCV_PKT_OK) {
 
index 76c369a498301821741c8044cf2efb550ff06745..d19d6b72352dc3f753853bc80b1f879957f50ad3 100644 (file)
@@ -734,6 +734,8 @@ struct hfi1_pportdata {
        /* Error events that will cause a port bounce. */
        u32 port_error_action;
        struct work_struct linkstate_active_work;
+       /* Does this port need to prescan for FECNs */
+       bool cc_prescan;
 };
 
 typedef int (*rhf_rcv_function_ptr)(struct hfi1_packet *packet);
index d05b9f37da0a4f5ebc54576a3c0516927fe9dc81..f1d47e7f31d27842e157ba05fc708b140f2242eb 100644 (file)
@@ -99,10 +99,6 @@ static void port_release(struct kobject *kobj)
        /* nothing to do since memory is freed by hfi1_free_devdata() */
 }
 
-static struct kobj_type port_cc_ktype = {
-       .release = port_release,
-};
-
 static struct bin_attribute cc_table_bin_attr = {
        .attr = {.name = "cc_table_bin", .mode = 0444},
        .read = read_cc_table_bin,
@@ -151,6 +147,68 @@ static struct bin_attribute cc_setting_bin_attr = {
        .size = PAGE_SIZE,
 };
 
+struct hfi1_port_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct hfi1_pportdata *, char *);
+       ssize_t (*store)(struct hfi1_pportdata *, const char *, size_t);
+};
+
+static ssize_t cc_prescan_show(struct hfi1_pportdata *ppd, char *buf)
+{
+       return sprintf(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
+}
+
+static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf,
+                               size_t count)
+{
+       if (!memcmp(buf, "on", 2))
+               ppd->cc_prescan = true;
+       else if (!memcmp(buf, "off", 3))
+               ppd->cc_prescan = false;
+
+       return count;
+}
+
+static struct hfi1_port_attr cc_prescan_attr =
+               __ATTR(cc_prescan, 0600, cc_prescan_show, cc_prescan_store);
+
+static ssize_t cc_attr_show(struct kobject *kobj, struct attribute *attr,
+                           char *buf)
+{
+       struct hfi1_port_attr *port_attr =
+               container_of(attr, struct hfi1_port_attr, attr);
+       struct hfi1_pportdata *ppd =
+               container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
+
+       return port_attr->show(ppd, buf);
+}
+
+static ssize_t cc_attr_store(struct kobject *kobj, struct attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct hfi1_port_attr *port_attr =
+               container_of(attr, struct hfi1_port_attr, attr);
+       struct hfi1_pportdata *ppd =
+               container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
+
+       return port_attr->store(ppd, buf, count);
+}
+
+static const struct sysfs_ops port_cc_sysfs_ops = {
+       .show = cc_attr_show,
+       .store = cc_attr_store
+};
+
+static struct attribute *port_cc_default_attributes[] = {
+       &cc_prescan_attr.attr
+};
+
+static struct kobj_type port_cc_ktype = {
+       .release = port_release,
+       .sysfs_ops = &port_cc_sysfs_ops,
+       .default_attrs = port_cc_default_attributes
+};
+
 /* Start sc2vl */
 #define HFI1_SC2VL_ATTR(N)                                 \
        static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \