Commit 8d98416a authored by John Garry's avatar John Garry Committed by Jens Axboe
Browse files

scsi: hisi_sas: Switch v3 hw to MQ



Now that the block layer provides a shared tag, we can switch the driver
to expose all HW queues.

Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Tested-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Acked-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 64f1501b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@
#define _HISI_SAS_H_

#include <linux/acpi.h>
#include <linux/blk-mq.h>
#include <linux/blk-mq-pci.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/dmapool.h>
@@ -431,7 +433,6 @@ struct hisi_hba {
	u32 intr_coal_count;	/* Interrupt count to coalesce */

	int cq_nvecs;
	unsigned int *reply_map;

	/* bist */
	enum sas_linkrate debugfs_bist_linkrate;
+19 −17
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
	struct device *dev = hisi_hba->dev;
	int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
	int n_elem = 0, n_elem_dif = 0, n_elem_req = 0;
	struct scsi_cmnd *scmd = NULL;
	struct hisi_sas_dq *dq;
	unsigned long flags;
	int wr_q_index;
@@ -432,10 +433,23 @@ static int hisi_sas_task_prep(struct sas_task *task,
		return -ECOMM;
	}

	if (hisi_hba->reply_map) {
		int cpu = raw_smp_processor_id();
		unsigned int dq_index = hisi_hba->reply_map[cpu];
	if (task->uldd_task) {
		struct ata_queued_cmd *qc;

		if (dev_is_sata(device)) {
			qc = task->uldd_task;
			scmd = qc->scsicmd;
		} else {
			scmd = task->uldd_task;
		}
	}

	if (scmd) {
		unsigned int dq_index;
		u32 blk_tag;

		blk_tag = blk_mq_unique_tag(scmd->request);
		dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
		*dq_pointer = dq = &hisi_hba->dq[dq_index];
	} else {
		*dq_pointer = dq = sas_dev->dq;
@@ -464,21 +478,9 @@ static int hisi_sas_task_prep(struct sas_task *task,

	if (hisi_hba->hw->slot_index_alloc)
		rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device);
	else {
		struct scsi_cmnd *scsi_cmnd = NULL;

		if (task->uldd_task) {
			struct ata_queued_cmd *qc;
	else
		rc = hisi_sas_slot_index_alloc(hisi_hba, scmd);

			if (dev_is_sata(device)) {
				qc = task->uldd_task;
				scsi_cmnd = qc->scsicmd;
			} else {
				scsi_cmnd = task->uldd_task;
			}
		}
		rc  = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd);
	}
	if (rc < 0)
		goto err_out_dif_dma_unmap;

+35 −52
Original line number Diff line number Diff line
@@ -2362,51 +2362,16 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
	return IRQ_WAKE_THREAD;
}

static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs)
static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
{
	const struct cpumask *mask;
	int queue, cpu;

	for (queue = 0; queue < nvecs; queue++) {
		struct hisi_sas_cq *cq = &hisi_hba->cq[queue];

		mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue +
					    BASE_VECTORS_V3_HW);
		if (!mask)
			goto fallback;
		cq->irq_mask = mask;
		for_each_cpu(cpu, mask)
			hisi_hba->reply_map[cpu] = queue;
	}
	return;

fallback:
	for_each_possible_cpu(cpu)
		hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count;
	/* Don't clean all CQ masks */
}

static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;
	struct pci_dev *pdev = hisi_hba->pci_dev;
	int vectors, rc, i;
	int vectors;
	int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;

	if (auto_affine_msi_experimental) {
	struct Scsi_Host *shost = hisi_hba->shost;
	struct irq_affinity desc = {
		.pre_vectors = BASE_VECTORS_V3_HW,
	};

		dev_info(dev, "Enable MSI auto-affinity\n");

	min_msi = MIN_AFFINE_VECTORS_V3_HW;

		hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids,
						   sizeof(unsigned int),
						   GFP_KERNEL);
		if (!hisi_hba->reply_map)
			return -ENOMEM;
	vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
						 min_msi, max_msi,
						 PCI_IRQ_MSI |
@@ -2414,16 +2379,19 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
						 &desc);
	if (vectors < 0)
		return -ENOENT;
		setup_reply_map_v3_hw(hisi_hba, vectors - BASE_VECTORS_V3_HW);
	} else {
		min_msi = max_msi;
		vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi,
						max_msi, PCI_IRQ_MSI);
		if (vectors < 0)
			return vectors;
	}


	hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
	shost->nr_hw_queues = hisi_hba->cq_nvecs;

	return 0;
}

static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;
	struct pci_dev *pdev = hisi_hba->pci_dev;
	int rc, i;

	rc = devm_request_irq(dev, pci_irq_vector(pdev, 1),
			      int_phy_up_down_bcast_v3_hw, 0,
@@ -3072,6 +3040,15 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable)
	return 0;
}

static int hisi_sas_map_queues(struct Scsi_Host *shost)
{
	struct hisi_hba *hisi_hba = shost_priv(shost);
	struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];

	return blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev,
				     BASE_VECTORS_V3_HW);
}

static struct scsi_host_template sht_v3_hw = {
	.name			= DRV_NAME,
	.proc_name		= DRV_NAME,
@@ -3082,6 +3059,7 @@ static struct scsi_host_template sht_v3_hw = {
	.slave_configure	= hisi_sas_slave_configure,
	.scan_finished		= hisi_sas_scan_finished,
	.scan_start		= hisi_sas_scan_start,
	.map_queues		= hisi_sas_map_queues,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.this_id		= -1,
@@ -3098,6 +3076,7 @@ static struct scsi_host_template sht_v3_hw = {
	.shost_attrs		= host_attrs_v3_hw,
	.tag_alloc_policy	= BLK_TAG_ALLOC_RR,
	.host_reset             = hisi_sas_host_reset,
	.host_tagset		= 1,
};

static const struct hisi_sas_hw hisi_sas_v3_hw = {
@@ -3269,6 +3248,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	if (hisi_sas_debugfs_enable)
		hisi_sas_debugfs_init(hisi_hba);

	rc = interrupt_preinit_v3_hw(hisi_hba);
	if (rc)
		goto err_out_ha;
	dev_err(dev, "%d hw queues\n", shost->nr_hw_queues);
	rc = scsi_add_host(shost, dev);
	if (rc)
		goto err_out_ha;