Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a310acd7 authored by Stephan Günther's avatar Stephan Günther Committed by Jens Axboe
Browse files

NVMe: use split lo_hi_{read,write}q

Some controllers may require ordered split transfers even on 64bit
machines, e.g. Apple's NVMe controller as found in the MacBook8,1 and
MacBookAir7,1 (256/512GB models).

This patch enforces ordered split transfers on 64bit platforms, which
works around that issue for all controllers. As pointed out by Christoph
[1] there should be no performance impact due to that modification.

[1] http://lists.infradead.org/pipermail/linux-nvme/2015-November/002965.html



Signed-off-by: default avatarStephan Guenther <guenther@tum.de>
Signed-off-by: default avatarMaurice Leclaire <leclaire@in.tum.de>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>

Updated by me to explicitly use lo_hi_read/writeq instead of playing
define tricks.

Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 1fa8cc52
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -1725,7 +1725,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
{
{
	int result;
	int result;
	u32 aqa;
	u32 aqa;
	u64 cap = readq(&dev->bar->cap);
	u64 cap = lo_hi_readq(&dev->bar->cap);
	struct nvme_queue *nvmeq;
	struct nvme_queue *nvmeq;
	unsigned page_shift = PAGE_SHIFT;
	unsigned page_shift = PAGE_SHIFT;
	unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
	unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
@@ -1774,8 +1774,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
	dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
	dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;


	writel(aqa, &dev->bar->aqa);
	writel(aqa, &dev->bar->aqa);
	writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
	lo_hi_writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
	writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
	lo_hi_writeq(nvmeq->cq_dma_addr, &dev->bar->acq);


	result = nvme_enable_ctrl(dev, cap);
	result = nvme_enable_ctrl(dev, cap);
	if (result)
	if (result)
@@ -2606,7 +2606,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
	struct pci_dev *pdev = to_pci_dev(dev->dev);
	struct pci_dev *pdev = to_pci_dev(dev->dev);
	int res;
	int res;
	struct nvme_id_ctrl *ctrl;
	struct nvme_id_ctrl *ctrl;
	int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
	int shift = NVME_CAP_MPSMIN(lo_hi_readq(&dev->bar->cap)) + 12;


	res = nvme_identify_ctrl(dev, &ctrl);
	res = nvme_identify_ctrl(dev, &ctrl);
	if (res) {
	if (res) {
@@ -2697,7 +2697,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
			goto unmap;
			goto unmap;
	}
	}


	cap = readq(&dev->bar->cap);
	cap = lo_hi_readq(&dev->bar->cap);
	dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
	dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
	dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
	dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
	dev->dbs = ((void __iomem *)dev->bar) + 4096;
	dev->dbs = ((void __iomem *)dev->bar) + 4096;
@@ -2760,7 +2760,7 @@ static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
			 * queues than admin tags.
			 * queues than admin tags.
			 */
			 */
			set_current_state(TASK_RUNNING);
			set_current_state(TASK_RUNNING);
			nvme_disable_ctrl(dev, readq(&dev->bar->cap));
			nvme_disable_ctrl(dev, lo_hi_readq(&dev->bar->cap));
			nvme_clear_queue(dev->queues[0]);
			nvme_clear_queue(dev->queues[0]);
			flush_kthread_worker(dq->worker);
			flush_kthread_worker(dq->worker);
			nvme_disable_queue(dev, 0);
			nvme_disable_queue(dev, 0);