+ if (weight > 0) {
+ for (i = 0; i < afu->num_hwqs; i++) {
+ hwq = get_hwq(afu, i);
+
+ irq_poll_init(&hwq->irqpoll, weight, cxlflash_irqpoll);
+ }
+ }
+
+ return count;
+}
+
+/**
+ * num_hwqs_show() - presents the number of hardware queues for the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the number of hardware queues.
+ * @buf: Buffer of length PAGE_SIZE to report back the number of hardware
+ * queues in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t num_hwqs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev));
+ struct afu *afu = cfg->afu;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", afu->num_hwqs);
+}
+
+/**
+ * num_hwqs_store() - sets the number of hardware queues for the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the number of hardware queues.
+ * @buf: Buffer of length PAGE_SIZE containing the number of hardware
+ * queues in ASCII.
+ * @count: Length of data resizing in @buf.
+ *
+ * n > 0: num_hwqs = n
+ * n = 0: num_hwqs = num_online_cpus()
+ * n < 0: num_online_cpus() / abs(n)
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t num_hwqs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev));
+ struct afu *afu = cfg->afu;
+ int rc;
+ int nhwqs, num_hwqs;
+
+ rc = kstrtoint(buf, 10, &nhwqs);
+ if (rc)
+ return -EINVAL;
+
+ if (nhwqs >= 1)
+ num_hwqs = nhwqs;
+ else if (nhwqs == 0)
+ num_hwqs = num_online_cpus();
+ else
+ num_hwqs = num_online_cpus() / abs(nhwqs);
+
+ afu->desired_hwqs = min(num_hwqs, CXLFLASH_MAX_HWQS);
+ WARN_ON_ONCE(afu->desired_hwqs == 0);
+
+retry:
+ switch (cfg->state) {
+ case STATE_NORMAL:
+ cfg->state = STATE_RESET;
+ drain_ioctls(cfg);
+ cxlflash_mark_contexts_error(cfg);
+ rc = afu_reset(cfg);
+ if (rc)
+ cfg->state = STATE_FAILTERM;
+ else
+ cfg->state = STATE_NORMAL;
+ wake_up_all(&cfg->reset_waitq);
+ break;
+ case STATE_RESET:
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
+ if (cfg->state == STATE_NORMAL)
+ goto retry;
+ default:
+ /* Ideally should not happen */
+ dev_err(dev, "%s: Device is not ready, state=%d\n",
+ __func__, cfg->state);
+ break;
+ }
+
+ return count;
+}
+
+static const char *hwq_mode_name[MAX_HWQ_MODE] = { "rr", "tag", "cpu" };
+
+/**
+ * hwq_mode_show() - presents the HWQ steering mode for the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the HWQ steering mode.
+ * @buf: Buffer of length PAGE_SIZE to report back the HWQ steering mode
+ * as a character string.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t hwq_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev));
+ struct afu *afu = cfg->afu;
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", hwq_mode_name[afu->hwq_mode]);
+}
+
+/**
+ * hwq_mode_store() - sets the HWQ steering mode for the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the HWQ steering mode.
+ * @buf: Buffer of length PAGE_SIZE containing the HWQ steering mode
+ * as a character string.
+ * @count: Length of data resizing in @buf.
+ *
+ * rr = Round-Robin
+ * tag = Block MQ Tagging
+ * cpu = CPU Affinity
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t hwq_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = shost_priv(shost);
+ struct device *cfgdev = &cfg->dev->dev;
+ struct afu *afu = cfg->afu;
+ int i;
+ u32 mode = MAX_HWQ_MODE;
+
+ for (i = 0; i < MAX_HWQ_MODE; i++) {
+ if (!strncmp(hwq_mode_name[i], buf, strlen(hwq_mode_name[i]))) {
+ mode = i;
+ break;
+ }
+ }
+
+ if (mode >= MAX_HWQ_MODE) {
+ dev_info(cfgdev, "Invalid HWQ steering mode.\n");
+ return -EINVAL;
+ }
+
+ if ((mode == HWQ_MODE_TAG) && !shost_use_blk_mq(shost)) {
+ dev_info(cfgdev, "SCSI-MQ is not enabled, use a different "
+ "HWQ steering mode.\n");
+ return -EINVAL;
+ }
+
+ afu->hwq_mode = mode;