Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
Pull block fixes from Jens Axboe:
 "A set of fixes that missed the merge window, mostly due to me being
  away around that time.

  Nothing major here, a mix of nvme cleanups and fixes, and one fix for
  the badblocks handling"

* 'for-linus' of git://git.kernel.dk/linux-block:
  nvmet: use symbolic constants for CNS values
  nvme: use symbolic constants for CNS values
  nvme.h: add an enum for cns values
  nvme.h: don't use uuid_be
  nvme.h: resync with nvme-cli
  nvme: Add tertiary number to NVME_VS
  nvme : Add sysfs entry for NVMe CMBs when appropriate
  nvme: don't schedule multiple resets
  nvme: Delete created IO queues on reset
  nvme: Stop probing a removed device
  badblocks: fix overlapping check for clearing
  • Loading branch information
torvalds committed Oct 21, 2016
2 parents e59f30b + e9c9346 commit ecd06f2
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 49 deletions.
6 changes: 4 additions & 2 deletions block/badblocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
* current range. Earlier ranges could also overlap,
* but only this one can overlap the end of the range.
*/
if (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) {
if ((BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) &&
(BB_OFFSET(p[lo]) < target)) {
/* Partial overlap, leave the tail of this range */
int ack = BB_ACK(p[lo]);
sector_t a = BB_OFFSET(p[lo]);
Expand All @@ -377,7 +378,8 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
lo--;
}
while (lo >= 0 &&
BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
(BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) &&
(BB_OFFSET(p[lo]) < target)) {
/* This range does overlap */
if (BB_OFFSET(p[lo]) < s) {
/* Keep the early parts of this range. */
Expand Down
14 changes: 8 additions & 6 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)

/* gcc-4.4.4 (at least) has issues with initializers and anon unions */
c.identify.opcode = nvme_admin_identify;
c.identify.cns = cpu_to_le32(1);
c.identify.cns = cpu_to_le32(NVME_ID_CNS_CTRL);

*id = kmalloc(sizeof(struct nvme_id_ctrl), GFP_KERNEL);
if (!*id)
Expand All @@ -572,7 +572,7 @@ static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *n
struct nvme_command c = { };

c.identify.opcode = nvme_admin_identify;
c.identify.cns = cpu_to_le32(2);
c.identify.cns = cpu_to_le32(NVME_ID_CNS_NS_ACTIVE_LIST);
c.identify.nsid = cpu_to_le32(nsid);
return nvme_submit_sync_cmd(dev->admin_q, &c, ns_list, 0x1000);
}
Expand Down Expand Up @@ -900,9 +900,9 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
return -ENODEV;
}

if (ns->ctrl->vs >= NVME_VS(1, 1))
if (ns->ctrl->vs >= NVME_VS(1, 1, 0))
memcpy(ns->eui, (*id)->eui64, sizeof(ns->eui));
if (ns->ctrl->vs >= NVME_VS(1, 2))
if (ns->ctrl->vs >= NVME_VS(1, 2, 0))
memcpy(ns->uuid, (*id)->nguid, sizeof(ns->uuid));

return 0;
Expand Down Expand Up @@ -1086,6 +1086,8 @@ static int nvme_wait_ready(struct nvme_ctrl *ctrl, u64 cap, bool enabled)
int ret;

while ((ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &csts)) == 0) {
if (csts == ~0)
return -ENODEV;
if ((csts & NVME_CSTS_RDY) == bit)
break;

Expand Down Expand Up @@ -1240,7 +1242,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
}
page_shift = NVME_CAP_MPSMIN(cap) + 12;

if (ctrl->vs >= NVME_VS(1, 1))
if (ctrl->vs >= NVME_VS(1, 1, 0))
ctrl->subsystem = NVME_CAP_NSSRC(cap);

ret = nvme_identify_ctrl(ctrl, &id);
Expand Down Expand Up @@ -1840,7 +1842,7 @@ static void nvme_scan_work(struct work_struct *work)
return;

nn = le32_to_cpu(id->nn);
if (ctrl->vs >= NVME_VS(1, 1) &&
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
!(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
if (!nvme_scan_ns_list(ctrl, nn))
goto done;
Expand Down
77 changes: 54 additions & 23 deletions drivers/nvme/host/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct nvme_dev {
dma_addr_t cmb_dma_addr;
u64 cmb_size;
u32 cmbsz;
u32 cmbloc;
struct nvme_ctrl ctrl;
struct completion ioq_wait;
};
Expand Down Expand Up @@ -893,7 +894,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
"I/O %d QID %d timeout, reset controller\n",
req->tag, nvmeq->qid);
nvme_dev_disable(dev, false);
queue_work(nvme_workq, &dev->reset_work);
nvme_reset(dev);

/*
* Mark the request as handled, since the inline shutdown
Expand Down Expand Up @@ -1214,7 +1215,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
u64 cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
struct nvme_queue *nvmeq;

dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1) ?
dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1, 0) ?
NVME_CAP_NSSRC(cap) : 0;

if (dev->subsystem &&
Expand Down Expand Up @@ -1291,7 +1292,7 @@ static void nvme_watchdog_timer(unsigned long data)

/* Skip controllers under certain specific conditions. */
if (nvme_should_reset(dev, csts)) {
if (queue_work(nvme_workq, &dev->reset_work))
if (!nvme_reset(dev))
dev_warn(dev->dev,
"Failed status: 0x%x, reset controller.\n",
csts);
Expand Down Expand Up @@ -1331,28 +1332,37 @@ static int nvme_create_io_queues(struct nvme_dev *dev)
return ret >= 0 ? 0 : ret;
}

static ssize_t nvme_cmb_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct nvme_dev *ndev = to_nvme_dev(dev_get_drvdata(dev));

return snprintf(buf, PAGE_SIZE, "cmbloc : x%08x\ncmbsz : x%08x\n",
ndev->cmbloc, ndev->cmbsz);
}
static DEVICE_ATTR(cmb, S_IRUGO, nvme_cmb_show, NULL);

static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
{
u64 szu, size, offset;
u32 cmbloc;
resource_size_t bar_size;
struct pci_dev *pdev = to_pci_dev(dev->dev);
void __iomem *cmb;
dma_addr_t dma_addr;

if (!use_cmb_sqes)
return NULL;

dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ);
if (!(NVME_CMB_SZ(dev->cmbsz)))
return NULL;
dev->cmbloc = readl(dev->bar + NVME_REG_CMBLOC);

cmbloc = readl(dev->bar + NVME_REG_CMBLOC);
if (!use_cmb_sqes)
return NULL;

szu = (u64)1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz));
size = szu * NVME_CMB_SZ(dev->cmbsz);
offset = szu * NVME_CMB_OFST(cmbloc);
bar_size = pci_resource_len(pdev, NVME_CMB_BIR(cmbloc));
offset = szu * NVME_CMB_OFST(dev->cmbloc);
bar_size = pci_resource_len(pdev, NVME_CMB_BIR(dev->cmbloc));

if (offset > bar_size)
return NULL;
Expand All @@ -1365,7 +1375,7 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
if (size > bar_size - offset)
size = bar_size - offset;

dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(cmbloc)) + offset;
dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(dev->cmbloc)) + offset;
cmb = ioremap_wc(dma_addr, size);
if (!cmb)
return NULL;
Expand Down Expand Up @@ -1511,9 +1521,9 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
return 0;
}

static void nvme_disable_io_queues(struct nvme_dev *dev)
static void nvme_disable_io_queues(struct nvme_dev *dev, int queues)
{
int pass, queues = dev->online_queues - 1;
int pass;
unsigned long timeout;
u8 opcode = nvme_admin_delete_sq;

Expand Down Expand Up @@ -1616,9 +1626,25 @@ static int nvme_pci_enable(struct nvme_dev *dev)
dev->q_depth);
}

if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2))
/*
* CMBs can currently only exist on >=1.2 PCIe devices. We only
* populate sysfs if a CMB is implemented. Note that we add the
* CMB attribute to the nvme_ctrl kobj which removes the need to remove
* it on exit. Since nvme_dev_attrs_group has no name we can pass
* NULL as final argument to sysfs_add_file_to_group.
*/

if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2, 0)) {
dev->cmb = nvme_map_cmb(dev);

if (dev->cmbsz) {
if (sysfs_add_file_to_group(&dev->ctrl.device->kobj,
&dev_attr_cmb.attr, NULL))
dev_warn(dev->dev,
"failed to add sysfs attribute for CMB\n");
}
}

pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
return 0;
Expand Down Expand Up @@ -1649,7 +1675,7 @@ static void nvme_pci_disable(struct nvme_dev *dev)

static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
{
int i;
int i, queues;
u32 csts = -1;

del_timer_sync(&dev->watchdog_timer);
Expand All @@ -1660,6 +1686,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
csts = readl(dev->bar + NVME_REG_CSTS);
}

queues = dev->online_queues - 1;
for (i = dev->queue_count - 1; i > 0; i--)
nvme_suspend_queue(dev->queues[i]);

Expand All @@ -1671,7 +1698,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
if (dev->queue_count)
nvme_suspend_queue(dev->queues[0]);
} else {
nvme_disable_io_queues(dev);
nvme_disable_io_queues(dev, queues);
nvme_disable_admin_queue(dev, shutdown);
}
nvme_pci_disable(dev);
Expand Down Expand Up @@ -1818,11 +1845,10 @@ static int nvme_reset(struct nvme_dev *dev)
{
if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
return -ENODEV;

if (work_busy(&dev->reset_work))
return -ENODEV;
if (!queue_work(nvme_workq, &dev->reset_work))
return -EBUSY;

flush_work(&dev->reset_work);
return 0;
}

Expand All @@ -1846,7 +1872,12 @@ static int nvme_pci_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)

static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
{
return nvme_reset(to_nvme_dev(ctrl));
struct nvme_dev *dev = to_nvme_dev(ctrl);
int ret = nvme_reset(dev);

if (!ret)
flush_work(&dev->reset_work);
return ret;
}

static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
Expand Down Expand Up @@ -1940,7 +1971,7 @@ static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
if (prepare)
nvme_dev_disable(dev, false);
else
queue_work(nvme_workq, &dev->reset_work);
nvme_reset(dev);
}

static void nvme_shutdown(struct pci_dev *pdev)
Expand Down Expand Up @@ -2009,7 +2040,7 @@ static int nvme_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct nvme_dev *ndev = pci_get_drvdata(pdev);

queue_work(nvme_workq, &ndev->reset_work);
nvme_reset(ndev);
return 0;
}
#endif
Expand Down Expand Up @@ -2048,7 +2079,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)

dev_info(dev->ctrl.device, "restart after slot reset\n");
pci_restore_state(pdev);
queue_work(nvme_workq, &dev->reset_work);
nvme_reset(dev);
return PCI_ERS_RESULT_RECOVERED;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/nvme/host/scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ static int nvme_fill_device_id_eui64(struct nvme_ns *ns, struct sg_io_hdr *hdr,
eui = id_ns->eui64;
len = sizeof(id_ns->eui64);

if (ns->ctrl->vs >= NVME_VS(1, 2)) {
if (ns->ctrl->vs >= NVME_VS(1, 2, 0)) {
if (bitmap_empty(eui, len * 8)) {
eui = id_ns->nguid;
len = sizeof(id_ns->nguid);
Expand Down Expand Up @@ -679,7 +679,7 @@ static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
{
int res;

if (ns->ctrl->vs >= NVME_VS(1, 1)) {
if (ns->ctrl->vs >= NVME_VS(1, 1, 0)) {
res = nvme_fill_device_id_eui64(ns, hdr, resp, alloc_len);
if (res != -EOPNOTSUPP)
return res;
Expand Down
8 changes: 4 additions & 4 deletions drivers/nvme/target/admin-cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
*/

/* we support multiple ports and multiples hosts: */
id->mic = (1 << 0) | (1 << 1);
id->cmic = (1 << 0) | (1 << 1);

/* no limit on data transfer sizes for now */
id->mdts = 0;
Expand Down Expand Up @@ -511,13 +511,13 @@ int nvmet_parse_admin_cmd(struct nvmet_req *req)
case nvme_admin_identify:
req->data_len = 4096;
switch (le32_to_cpu(cmd->identify.cns)) {
case 0x00:
case NVME_ID_CNS_NS:
req->execute = nvmet_execute_identify_ns;
return 0;
case 0x01:
case NVME_ID_CNS_CTRL:
req->execute = nvmet_execute_identify_ctrl;
return 0;
case 0x02:
case NVME_ID_CNS_NS_ACTIVE_LIST:
req->execute = nvmet_execute_identify_nslist;
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvme/target/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
if (!subsys)
return NULL;

subsys->ver = (1 << 16) | (2 << 8) | 1; /* NVMe 1.2.1 */
subsys->ver = NVME_VS(1, 2, 1); /* NVMe 1.2.1 */

switch (type) {
case NVME_NQN_NVME:
Expand Down
4 changes: 2 additions & 2 deletions drivers/nvme/target/discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
/* we support only dynamic controllers */
e->cntlid = cpu_to_le16(NVME_CNTLID_DYNAMIC);
e->asqsz = cpu_to_le16(NVMF_AQ_DEPTH);
e->nqntype = type;
e->subtype = type;
memcpy(e->trsvcid, port->disc_addr.trsvcid, NVMF_TRSVCID_SIZE);
memcpy(e->traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
memcpy(e->tsas.common, port->disc_addr.tsas.common, NVMF_TSAS_SIZE);
Expand Down Expand Up @@ -187,7 +187,7 @@ int nvmet_parse_discovery_cmd(struct nvmet_req *req)
case nvme_admin_identify:
req->data_len = 4096;
switch (le32_to_cpu(cmd->identify.cns)) {
case 0x01:
case NVME_ID_CNS_CTRL:
req->execute =
nvmet_execute_identify_disc_ctrl;
return 0;
Expand Down
Loading

0 comments on commit ecd06f2

Please sign in to comment.