Skip to content

Commit

Permalink
NVMe: Implement doorbell stride capability
Browse files Browse the repository at this point in the history
The doorbell stride allows devices to spread out their doorbells instead
of packing them tightly.  This feature was added as part of ECN 003.

This patch also enables support for more than 512 queues :-)

Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
  • Loading branch information
Matthew Wilcox committed Nov 4, 2011
1 parent ce38c14 commit f1938f6
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
17 changes: 14 additions & 3 deletions drivers/block/nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct nvme_dev {
struct dma_pool *prp_small_pool;
int instance;
int queue_count;
int db_stride;
u32 ctrl_config;
struct msix_entry *entry;
struct nvme_bar __iomem *bar;
Expand Down Expand Up @@ -672,7 +673,7 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq)
if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
return IRQ_NONE;

writel(head, nvmeq->q_db + 1);
writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride));
nvmeq->cq_head = head;
nvmeq->cq_phase = phase;

Expand Down Expand Up @@ -889,7 +890,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
init_waitqueue_head(&nvmeq->sq_full);
init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread);
bio_list_init(&nvmeq->sq_cong);
nvmeq->q_db = &dev->dbs[qid * 2];
nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
nvmeq->q_depth = depth;
nvmeq->cq_vector = vector;

Expand Down Expand Up @@ -981,6 +982,7 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)

cap = readq(&dev->bar->cap);
timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
dev->db_stride = NVME_CAP_STRIDE(cap);

while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
msleep(100);
Expand Down Expand Up @@ -1357,7 +1359,7 @@ static int set_queue_count(struct nvme_dev *dev, int count)

static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
{
int result, cpu, i, nr_io_queues;
int result, cpu, i, nr_io_queues, db_bar_size;

nr_io_queues = num_online_cpus();
result = set_queue_count(dev, nr_io_queues);
Expand All @@ -1369,6 +1371,15 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
/* Deregister the admin queue's interrupt */
free_irq(dev->entry[0].vector, dev->queues[0]);

db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
if (db_bar_size > 8192) {
iounmap(dev->bar);
dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0),
db_bar_size);
dev->dbs = ((void __iomem *)dev->bar) + 4096;
dev->queues[0]->q_db = dev->dbs;
}

for (i = 0; i < nr_io_queues; i++)
dev->entry[i].entry = i;
for (;;) {
Expand Down
1 change: 1 addition & 0 deletions include/linux/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct nvme_bar {
};

#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)

enum {
NVME_CC_ENABLE = 1 << 0,
Expand Down

0 comments on commit f1938f6

Please sign in to comment.