IB/hfi1: Add sysfs entry to override SDMA interrupt affinity
authorTadeusz Struk <tadeusz.struk@intel.com>
Mon, 25 Jul 2016 20:39:27 +0000 (13:39 -0700)
committerDoug Ledford <dledford@redhat.com>
Tue, 2 Aug 2016 20:00:58 +0000 (16:00 -0400)
Add sysfs entry to allow user to override affinity for SDMA
engine interrupts.

Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/affinity.c
drivers/infiniband/hw/hfi1/affinity.h
drivers/infiniband/hw/hfi1/sysfs.c

index c9dcbd55883a9590698814e885ce57c5a48966ed..79575ee873f21af3361264b711419c267b6a23d0 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/topology.h>
 #include <linux/cpumask.h>
 #include <linux/module.h>
+#include <linux/cpumask.h>
 
 #include "hfi.h"
 #include "affinity.h"
@@ -673,3 +674,70 @@ void hfi1_put_proc_affinity(int cpu)
        }
        spin_unlock(&affinity->lock);
 }
+
+/* Prevents concurrent reads and writes of the sdma_affinity attrib */
+static DEFINE_MUTEX(sdma_affinity_mutex);
+
+int hfi1_set_sdma_affinity(struct hfi1_devdata *dd, const char *buf,
+                          size_t count)
+{
+       struct hfi1_affinity_node *entry;
+       struct cpumask mask;
+       int ret, i;
+
+       spin_lock(&node_affinity.lock);
+       entry = node_affinity_lookup(dd->node);
+       spin_unlock(&node_affinity.lock);
+
+       if (!entry)
+               return -EINVAL;
+
+       ret = cpulist_parse(buf, &mask);
+       if (ret)
+               return ret;
+
+       if (!cpumask_subset(&mask, cpu_online_mask) || cpumask_empty(&mask)) {
+               dd_dev_warn(dd, "Invalid CPU mask\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&sdma_affinity_mutex);
+       /* reset the SDMA interrupt affinity details */
+       init_cpu_mask_set(&entry->def_intr);
+       cpumask_copy(&entry->def_intr.mask, &mask);
+       /*
+        * Reassign the affinity for each SDMA interrupt.
+        */
+       for (i = 0; i < dd->num_msix_entries; i++) {
+               struct hfi1_msix_entry *msix;
+
+               msix = &dd->msix_entries[i];
+               if (msix->type != IRQ_SDMA)
+                       continue;
+
+               ret = hfi1_get_irq_affinity(dd, msix);
+
+               if (ret)
+                       break;
+       }
+
+       mutex_unlock(&sdma_affinity_mutex);
+       return ret ? ret : strnlen(buf, PAGE_SIZE);
+}
+
+int hfi1_get_sdma_affinity(struct hfi1_devdata *dd, char *buf)
+{
+       struct hfi1_affinity_node *entry;
+
+       spin_lock(&node_affinity.lock);
+       entry = node_affinity_lookup(dd->node);
+       spin_unlock(&node_affinity.lock);
+
+       if (!entry)
+               return -EINVAL;
+
+       mutex_lock(&sdma_affinity_mutex);
+       cpumap_print_to_pagebuf(true, buf, &entry->def_intr.mask);
+       mutex_unlock(&sdma_affinity_mutex);
+       return strnlen(buf, PAGE_SIZE);
+}
index f784de52e881a551881cd7f608a1490b04bec0ed..8879cf7a8cac54fede679918f835c2a180a5e962 100644 (file)
@@ -102,6 +102,10 @@ int hfi1_get_proc_affinity(int);
 /* Release a CPU used by a user process. */
 void hfi1_put_proc_affinity(int);
 
+int hfi1_get_sdma_affinity(struct hfi1_devdata *dd, char *buf);
+int hfi1_set_sdma_affinity(struct hfi1_devdata *dd, const char *buf,
+                          size_t count);
+
 struct hfi1_affinity_node {
        int node;
        struct cpu_mask_set def_intr;
index 91fc2aed6aed93dbfa3b5d2b8a197ce4537a67a9..74c84c655f7e5c18f2737adfd582429cbd99c2ca 100644 (file)
@@ -49,6 +49,7 @@
 #include "hfi.h"
 #include "mad.h"
 #include "trace.h"
+#include "affinity.h"
 
 /*
  * Start of per-port congestion control structures and support code
@@ -622,6 +623,27 @@ static ssize_t show_tempsense(struct device *device,
        return ret;
 }
 
+static ssize_t show_sdma_affinity(struct device *device,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct hfi1_ibdev *dev =
+               container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
+       struct hfi1_devdata *dd = dd_from_dev(dev);
+
+       return hfi1_get_sdma_affinity(dd, buf);
+}
+
+static ssize_t store_sdma_affinity(struct device *device,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       struct hfi1_ibdev *dev =
+               container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
+       struct hfi1_devdata *dd = dd_from_dev(dev);
+
+       return hfi1_set_sdma_affinity(dd, buf, count);
+}
+
 /*
  * end of per-unit (or driver, in some cases, but replicated
  * per unit) functions
@@ -636,6 +658,8 @@ static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
 static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
+static DEVICE_ATTR(sdma_affinity, S_IWUSR | S_IRUGO, show_sdma_affinity,
+                  store_sdma_affinity);
 
 static struct device_attribute *hfi1_attributes[] = {
        &dev_attr_hw_rev,
@@ -646,6 +670,7 @@ static struct device_attribute *hfi1_attributes[] = {
        &dev_attr_boardversion,
        &dev_attr_tempsense,
        &dev_attr_chip_reset,
+       &dev_attr_sdma_affinity,
 };
 
 int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,