提交 21e98932 编写于 作者: L Linus Torvalds

Merge git://git.infradead.org/users/willy/linux-nvme

Pull NVMe driver fixes from Matthew Wilcox:
 "Now that actual hardware has been released (don't have any yet
  myself), people are starting to want some of these fixes merged."

Willy doesn't have hardware? Guys...

* git://git.infradead.org/users/willy/linux-nvme:
  NVMe: Cancel outstanding IOs on queue deletion
  NVMe: Free admin queue memory on initialisation failure
  NVMe: Use ida for nvme device instance
  NVMe: Fix whitespace damage in nvme_init
  NVMe: handle allocation failure in nvme_map_user_pages()
  NVMe: Fix uninitialized iod compiler warning
  NVMe: Do not set IO queue depth beyond device max
  NVMe: Set block queue max sectors
  NVMe: use namespace id for nvme_get_features
  NVMe: replace nvme_ns with nvme_dev for user admin
  NVMe: Fix nvme module init when nvme_major is set
  NVMe: Set request queue logical block size
...@@ -79,6 +79,7 @@ struct nvme_dev { ...@@ -79,6 +79,7 @@ struct nvme_dev {
char serial[20]; char serial[20];
char model[40]; char model[40];
char firmware_rev[8]; char firmware_rev[8];
u32 max_hw_sectors;
}; };
/* /*
...@@ -835,15 +836,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns, ...@@ -835,15 +836,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
} }
static int nvme_get_features(struct nvme_dev *dev, unsigned fid, static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
unsigned dword11, dma_addr_t dma_addr) unsigned nsid, dma_addr_t dma_addr)
{ {
struct nvme_command c; struct nvme_command c;
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));
c.features.opcode = nvme_admin_get_features; c.features.opcode = nvme_admin_get_features;
c.features.nsid = cpu_to_le32(nsid);
c.features.prp1 = cpu_to_le64(dma_addr); c.features.prp1 = cpu_to_le64(dma_addr);
c.features.fid = cpu_to_le32(fid); c.features.fid = cpu_to_le32(fid);
c.features.dword11 = cpu_to_le32(dword11);
return nvme_submit_admin_cmd(dev, &c, NULL); return nvme_submit_admin_cmd(dev, &c, NULL);
} }
...@@ -862,11 +863,51 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid, ...@@ -862,11 +863,51 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
return nvme_submit_admin_cmd(dev, &c, result); return nvme_submit_admin_cmd(dev, &c, result);
} }
/**
* nvme_cancel_ios - Cancel outstanding I/Os
* @queue: The queue to cancel I/Os on
* @timeout: True to only cancel I/Os which have timed out
*/
static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
{
int depth = nvmeq->q_depth - 1;
struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
unsigned long now = jiffies;
int cmdid;
for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
void *ctx;
nvme_completion_fn fn;
static struct nvme_completion cqe = {
.status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1,
};
if (timeout && !time_after(now, info[cmdid].timeout))
continue;
dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
ctx = cancel_cmdid(nvmeq, cmdid, &fn);
fn(nvmeq->dev, ctx, &cqe);
}
}
static void nvme_free_queue_mem(struct nvme_queue *nvmeq)
{
dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
(void *)nvmeq->cqes, nvmeq->cq_dma_addr);
dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
nvmeq->sq_cmds, nvmeq->sq_dma_addr);
kfree(nvmeq);
}
static void nvme_free_queue(struct nvme_dev *dev, int qid) static void nvme_free_queue(struct nvme_dev *dev, int qid)
{ {
struct nvme_queue *nvmeq = dev->queues[qid]; struct nvme_queue *nvmeq = dev->queues[qid];
int vector = dev->entry[nvmeq->cq_vector].vector; int vector = dev->entry[nvmeq->cq_vector].vector;
spin_lock_irq(&nvmeq->q_lock);
nvme_cancel_ios(nvmeq, false);
spin_unlock_irq(&nvmeq->q_lock);
irq_set_affinity_hint(vector, NULL); irq_set_affinity_hint(vector, NULL);
free_irq(vector, nvmeq); free_irq(vector, nvmeq);
...@@ -876,18 +917,15 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid) ...@@ -876,18 +917,15 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid)
adapter_delete_cq(dev, qid); adapter_delete_cq(dev, qid);
} }
dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), nvme_free_queue_mem(nvmeq);
(void *)nvmeq->cqes, nvmeq->cq_dma_addr);
dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
nvmeq->sq_cmds, nvmeq->sq_dma_addr);
kfree(nvmeq);
} }
static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
int depth, int vector) int depth, int vector)
{ {
struct device *dmadev = &dev->pci_dev->dev; struct device *dmadev = &dev->pci_dev->dev;
unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info)); unsigned extra = DIV_ROUND_UP(depth, 8) + (depth *
sizeof(struct nvme_cmd_info));
struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL);
if (!nvmeq) if (!nvmeq)
return NULL; return NULL;
...@@ -975,7 +1013,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, ...@@ -975,7 +1013,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
{ {
int result; int result = 0;
u32 aqa; u32 aqa;
u64 cap; u64 cap;
unsigned long timeout; unsigned long timeout;
...@@ -1005,17 +1043,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) ...@@ -1005,17 +1043,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
dev->db_stride = NVME_CAP_STRIDE(cap); dev->db_stride = NVME_CAP_STRIDE(cap);
while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
msleep(100); msleep(100);
if (fatal_signal_pending(current)) if (fatal_signal_pending(current))
return -EINTR; result = -EINTR;
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
dev_err(&dev->pci_dev->dev, dev_err(&dev->pci_dev->dev,
"Device not ready; aborting initialisation\n"); "Device not ready; aborting initialisation\n");
return -ENODEV; result = -ENODEV;
} }
} }
if (result) {
nvme_free_queue_mem(nvmeq);
return result;
}
result = queue_request_irq(dev, nvmeq, "nvme admin"); result = queue_request_irq(dev, nvmeq, "nvme admin");
dev->queues[0] = nvmeq; dev->queues[0] = nvmeq;
return result; return result;
...@@ -1037,6 +1080,8 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write, ...@@ -1037,6 +1080,8 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
offset = offset_in_page(addr); offset = offset_in_page(addr);
count = DIV_ROUND_UP(offset + length, PAGE_SIZE); count = DIV_ROUND_UP(offset + length, PAGE_SIZE);
pages = kcalloc(count, sizeof(*pages), GFP_KERNEL); pages = kcalloc(count, sizeof(*pages), GFP_KERNEL);
if (!pages)
return ERR_PTR(-ENOMEM);
err = get_user_pages_fast(addr, count, 1, pages); err = get_user_pages_fast(addr, count, 1, pages);
if (err < count) { if (err < count) {
...@@ -1146,14 +1191,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) ...@@ -1146,14 +1191,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
return status; return status;
} }
static int nvme_user_admin_cmd(struct nvme_ns *ns, static int nvme_user_admin_cmd(struct nvme_dev *dev,
struct nvme_admin_cmd __user *ucmd) struct nvme_admin_cmd __user *ucmd)
{ {
struct nvme_dev *dev = ns->dev;
struct nvme_admin_cmd cmd; struct nvme_admin_cmd cmd;
struct nvme_command c; struct nvme_command c;
int status, length; int status, length;
struct nvme_iod *iod; struct nvme_iod *uninitialized_var(iod);
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
...@@ -1204,7 +1248,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, ...@@ -1204,7 +1248,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
case NVME_IOCTL_ID: case NVME_IOCTL_ID:
return ns->ns_id; return ns->ns_id;
case NVME_IOCTL_ADMIN_CMD: case NVME_IOCTL_ADMIN_CMD:
return nvme_user_admin_cmd(ns, (void __user *)arg); return nvme_user_admin_cmd(ns->dev, (void __user *)arg);
case NVME_IOCTL_SUBMIT_IO: case NVME_IOCTL_SUBMIT_IO:
return nvme_submit_io(ns, (void __user *)arg); return nvme_submit_io(ns, (void __user *)arg);
default: default:
...@@ -1218,26 +1262,6 @@ static const struct block_device_operations nvme_fops = { ...@@ -1218,26 +1262,6 @@ static const struct block_device_operations nvme_fops = {
.compat_ioctl = nvme_ioctl, .compat_ioctl = nvme_ioctl,
}; };
static void nvme_timeout_ios(struct nvme_queue *nvmeq)
{
int depth = nvmeq->q_depth - 1;
struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
unsigned long now = jiffies;
int cmdid;
for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
void *ctx;
nvme_completion_fn fn;
static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, };
if (!time_after(now, info[cmdid].timeout))
continue;
dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid);
ctx = cancel_cmdid(nvmeq, cmdid, &fn);
fn(nvmeq->dev, ctx, &cqe);
}
}
static void nvme_resubmit_bios(struct nvme_queue *nvmeq) static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
{ {
while (bio_list_peek(&nvmeq->sq_cong)) { while (bio_list_peek(&nvmeq->sq_cong)) {
...@@ -1269,7 +1293,7 @@ static int nvme_kthread(void *data) ...@@ -1269,7 +1293,7 @@ static int nvme_kthread(void *data)
spin_lock_irq(&nvmeq->q_lock); spin_lock_irq(&nvmeq->q_lock);
if (nvme_process_cq(nvmeq)) if (nvme_process_cq(nvmeq))
printk("process_cq did something\n"); printk("process_cq did something\n");
nvme_timeout_ios(nvmeq); nvme_cancel_ios(nvmeq, true);
nvme_resubmit_bios(nvmeq); nvme_resubmit_bios(nvmeq);
spin_unlock_irq(&nvmeq->q_lock); spin_unlock_irq(&nvmeq->q_lock);
} }
...@@ -1339,6 +1363,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid, ...@@ -1339,6 +1363,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
ns->disk = disk; ns->disk = disk;
lbaf = id->flbas & 0xf; lbaf = id->flbas & 0xf;
ns->lba_shift = id->lbaf[lbaf].ds; ns->lba_shift = id->lbaf[lbaf].ds;
blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
if (dev->max_hw_sectors)
blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
disk->major = nvme_major; disk->major = nvme_major;
disk->minors = NVME_MINORS; disk->minors = NVME_MINORS;
...@@ -1383,7 +1410,7 @@ static int set_queue_count(struct nvme_dev *dev, int count) ...@@ -1383,7 +1410,7 @@ static int set_queue_count(struct nvme_dev *dev, int count)
static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
{ {
int result, cpu, i, nr_io_queues, db_bar_size; int result, cpu, i, nr_io_queues, db_bar_size, q_depth;
nr_io_queues = num_online_cpus(); nr_io_queues = num_online_cpus();
result = set_queue_count(dev, nr_io_queues); result = set_queue_count(dev, nr_io_queues);
...@@ -1429,9 +1456,10 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) ...@@ -1429,9 +1456,10 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
cpu = cpumask_next(cpu, cpu_online_mask); cpu = cpumask_next(cpu, cpu_online_mask);
} }
q_depth = min_t(int, NVME_CAP_MQES(readq(&dev->bar->cap)) + 1,
NVME_Q_DEPTH);
for (i = 0; i < nr_io_queues; i++) { for (i = 0; i < nr_io_queues; i++) {
dev->queues[i + 1] = nvme_create_queue(dev, i + 1, dev->queues[i + 1] = nvme_create_queue(dev, i + 1, q_depth, i);
NVME_Q_DEPTH, i);
if (IS_ERR(dev->queues[i + 1])) if (IS_ERR(dev->queues[i + 1]))
return PTR_ERR(dev->queues[i + 1]); return PTR_ERR(dev->queues[i + 1]);
dev->queue_count++; dev->queue_count++;
...@@ -1480,6 +1508,10 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) ...@@ -1480,6 +1508,10 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
if (ctrl->mdts) {
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
}
id_ns = mem; id_ns = mem;
for (i = 1; i <= nn; i++) { for (i = 1; i <= nn; i++) {
...@@ -1523,8 +1555,6 @@ static int nvme_dev_remove(struct nvme_dev *dev) ...@@ -1523,8 +1555,6 @@ static int nvme_dev_remove(struct nvme_dev *dev)
list_del(&dev->node); list_del(&dev->node);
spin_unlock(&dev_list_lock); spin_unlock(&dev_list_lock);
/* TODO: wait all I/O finished or cancel them */
list_for_each_entry_safe(ns, next, &dev->namespaces, list) { list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
list_del(&ns->list); list_del(&ns->list);
del_gendisk(ns->disk); del_gendisk(ns->disk);
...@@ -1560,15 +1590,33 @@ static void nvme_release_prp_pools(struct nvme_dev *dev) ...@@ -1560,15 +1590,33 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
dma_pool_destroy(dev->prp_small_pool); dma_pool_destroy(dev->prp_small_pool);
} }
/* XXX: Use an ida or something to let remove / add work correctly */ static DEFINE_IDA(nvme_instance_ida);
static void nvme_set_instance(struct nvme_dev *dev)
static int nvme_set_instance(struct nvme_dev *dev)
{ {
static int instance; int instance, error;
dev->instance = instance++;
do {
if (!ida_pre_get(&nvme_instance_ida, GFP_KERNEL))
return -ENODEV;
spin_lock(&dev_list_lock);
error = ida_get_new(&nvme_instance_ida, &instance);
spin_unlock(&dev_list_lock);
} while (error == -EAGAIN);
if (error)
return -ENODEV;
dev->instance = instance;
return 0;
} }
static void nvme_release_instance(struct nvme_dev *dev) static void nvme_release_instance(struct nvme_dev *dev)
{ {
spin_lock(&dev_list_lock);
ida_remove(&nvme_instance_ida, dev->instance);
spin_unlock(&dev_list_lock);
} }
static int __devinit nvme_probe(struct pci_dev *pdev, static int __devinit nvme_probe(struct pci_dev *pdev,
...@@ -1601,7 +1649,10 @@ static int __devinit nvme_probe(struct pci_dev *pdev, ...@@ -1601,7 +1649,10 @@ static int __devinit nvme_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
nvme_set_instance(dev); result = nvme_set_instance(dev);
if (result)
goto disable;
dev->entry[0].vector = pdev->irq; dev->entry[0].vector = pdev->irq;
result = nvme_setup_prp_pools(dev); result = nvme_setup_prp_pools(dev);
...@@ -1704,15 +1755,17 @@ static struct pci_driver nvme_driver = { ...@@ -1704,15 +1755,17 @@ static struct pci_driver nvme_driver = {
static int __init nvme_init(void) static int __init nvme_init(void)
{ {
int result = -EBUSY; int result;
nvme_thread = kthread_run(nvme_kthread, NULL, "nvme"); nvme_thread = kthread_run(nvme_kthread, NULL, "nvme");
if (IS_ERR(nvme_thread)) if (IS_ERR(nvme_thread))
return PTR_ERR(nvme_thread); return PTR_ERR(nvme_thread);
nvme_major = register_blkdev(nvme_major, "nvme"); result = register_blkdev(nvme_major, "nvme");
if (nvme_major <= 0) if (result < 0)
goto kill_kthread; goto kill_kthread;
else if (result > 0)
nvme_major = result;
result = pci_register_driver(&nvme_driver); result = pci_register_driver(&nvme_driver);
if (result) if (result)
......
...@@ -35,8 +35,10 @@ struct nvme_bar { ...@@ -35,8 +35,10 @@ struct nvme_bar {
__u64 acq; /* Admin CQ Base Address */ __u64 acq; /* Admin CQ Base Address */
}; };
#define NVME_CAP_MQES(cap) ((cap) & 0xffff)
#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) #define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
enum { enum {
NVME_CC_ENABLE = 1 << 0, NVME_CC_ENABLE = 1 << 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册