]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
scsi: hisi_sas: Add support for interrupt coalescing for v3 hw
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / hisi_sas / hisi_sas_v3_hw.c
index 546eaf99ffc426ef39fb1593cfc2590e60dd2f8a..6ebb220767a3e33f612566d4ee0e286c04380174 100644 (file)
@@ -2105,9 +2105,109 @@ static ssize_t intr_conv_v3_hw_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(intr_conv_v3_hw);
 
+static void config_intr_coal_v3_hw(struct hisi_hba *hisi_hba)
+{
+       /* config those registers between enable and disable PHYs */
+       hisi_sas_stop_phys(hisi_hba);
+
+       if (hisi_hba->intr_coal_ticks == 0 ||
+           hisi_hba->intr_coal_count == 0) {
+               hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
+               hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1);
+               hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1);
+       } else {
+               hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3);
+               hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME,
+                                hisi_hba->intr_coal_ticks);
+               hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT,
+                                hisi_hba->intr_coal_count);
+       }
+       phys_init_v3_hw(hisi_hba);
+}
+
+static ssize_t intr_coal_ticks_v3_hw_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct hisi_hba *hisi_hba = shost_priv(shost);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n",
+                        hisi_hba->intr_coal_ticks);
+}
+
+static ssize_t intr_coal_ticks_v3_hw_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct hisi_hba *hisi_hba = shost_priv(shost);
+       u32 intr_coal_ticks;
+       int ret;
+
+       ret = kstrtou32(buf, 10, &intr_coal_ticks);
+       if (ret) {
+               dev_err(dev, "Input data of interrupt coalesce unmatch\n");
+               return -EINVAL;
+       }
+
+       if (intr_coal_ticks >= BIT(24)) {
+               dev_err(dev, "intr_coal_ticks must be less than 2^24!\n");
+               return -EINVAL;
+       }
+
+       hisi_hba->intr_coal_ticks = intr_coal_ticks;
+
+       config_intr_coal_v3_hw(hisi_hba);
+
+       return count;
+}
+static DEVICE_ATTR_RW(intr_coal_ticks_v3_hw);
+
+static ssize_t intr_coal_count_v3_hw_show(struct device *dev,
+                                         struct device_attribute
+                                         *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct hisi_hba *hisi_hba = shost_priv(shost);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n",
+                        hisi_hba->intr_coal_count);
+}
+
+static ssize_t intr_coal_count_v3_hw_store(struct device *dev,
+               struct device_attribute
+               *attr, const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct hisi_hba *hisi_hba = shost_priv(shost);
+       u32 intr_coal_count;
+       int ret;
+
+       ret = kstrtou32(buf, 10, &intr_coal_count);
+       if (ret) {
+               dev_err(dev, "Input data of interrupt coalesce unmatch\n");
+               return -EINVAL;
+       }
+
+       if (intr_coal_count >= BIT(8)) {
+               dev_err(dev, "intr_coal_count must be less than 2^8!\n");
+               return -EINVAL;
+       }
+
+       hisi_hba->intr_coal_count = intr_coal_count;
+
+       config_intr_coal_v3_hw(hisi_hba);
+
+       return count;
+}
+static DEVICE_ATTR_RW(intr_coal_count_v3_hw);
+
 struct device_attribute *host_attrs_v3_hw[] = {
        &dev_attr_phy_event_threshold,
        &dev_attr_intr_conv_v3_hw,
+       &dev_attr_intr_coal_ticks_v3_hw,
+       &dev_attr_intr_coal_count_v3_hw,
        NULL
 };