summaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r--drivers/nvdimm/bus.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index cb2042a12b76..395a9fbbc69d 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -439,6 +439,12 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = {
439 .out_num = 3, 439 .out_num = 3,
440 .out_sizes = { 4, 4, UINT_MAX, }, 440 .out_sizes = { 4, 4, UINT_MAX, },
441 }, 441 },
442 [ND_CMD_CALL] = {
443 .in_num = 2,
444 .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
445 .out_num = 1,
446 .out_sizes = { UINT_MAX, },
447 },
442}; 448};
443 449
444const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd) 450const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd)
@@ -473,6 +479,12 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
473 .out_num = 3, 479 .out_num = 3,
474 .out_sizes = { 4, 4, 8, }, 480 .out_sizes = { 4, 4, 8, },
475 }, 481 },
482 [ND_CMD_CALL] = {
483 .in_num = 2,
484 .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
485 .out_num = 1,
486 .out_sizes = { UINT_MAX, },
487 },
476}; 488};
477 489
478const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd) 490const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd)
@@ -500,6 +512,10 @@ u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
500 struct nd_cmd_vendor_hdr *hdr = buf; 512 struct nd_cmd_vendor_hdr *hdr = buf;
501 513
502 return hdr->in_length; 514 return hdr->in_length;
515 } else if (cmd == ND_CMD_CALL) {
516 struct nd_cmd_pkg *pkg = buf;
517
518 return pkg->nd_size_in;
503 } 519 }
504 520
505 return UINT_MAX; 521 return UINT_MAX;
@@ -522,6 +538,12 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
522 return out_field[1]; 538 return out_field[1];
523 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) 539 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
524 return out_field[1] - 8; 540 return out_field[1] - 8;
541 else if (cmd == ND_CMD_CALL) {
542 struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;
543
544 return pkg->nd_size_out;
545 }
546
525 547
526 return UINT_MAX; 548 return UINT_MAX;
527} 549}
@@ -588,6 +610,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
588 unsigned int cmd = _IOC_NR(ioctl_cmd); 610 unsigned int cmd = _IOC_NR(ioctl_cmd);
589 void __user *p = (void __user *) arg; 611 void __user *p = (void __user *) arg;
590 struct device *dev = &nvdimm_bus->dev; 612 struct device *dev = &nvdimm_bus->dev;
613 struct nd_cmd_pkg pkg;
591 const char *cmd_name, *dimm_name; 614 const char *cmd_name, *dimm_name;
592 unsigned long cmd_mask; 615 unsigned long cmd_mask;
593 void *buf; 616 void *buf;
@@ -605,6 +628,11 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
605 dimm_name = "bus"; 628 dimm_name = "bus";
606 } 629 }
607 630
631 if (cmd == ND_CMD_CALL) {
632 if (copy_from_user(&pkg, p, sizeof(pkg)))
633 return -EFAULT;
634 }
635
608 if (!desc || (desc->out_num + desc->in_num == 0) || 636 if (!desc || (desc->out_num + desc->in_num == 0) ||
609 !test_bit(cmd, &cmd_mask)) 637 !test_bit(cmd, &cmd_mask))
610 return -ENOTTY; 638 return -ENOTTY;
@@ -616,6 +644,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
616 case ND_CMD_SET_CONFIG_DATA: 644 case ND_CMD_SET_CONFIG_DATA:
617 case ND_CMD_ARS_START: 645 case ND_CMD_ARS_START:
618 case ND_CMD_CLEAR_ERROR: 646 case ND_CMD_CLEAR_ERROR:
647 case ND_CMD_CALL:
619 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n", 648 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
620 nvdimm ? nvdimm_cmd_name(cmd) 649 nvdimm ? nvdimm_cmd_name(cmd)
621 : nvdimm_bus_cmd_name(cmd)); 650 : nvdimm_bus_cmd_name(cmd));
@@ -643,6 +672,16 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
643 in_len += in_size; 672 in_len += in_size;
644 } 673 }
645 674
675 if (cmd == ND_CMD_CALL) {
676 dev_dbg(dev, "%s:%s, idx: %llu, in: %zu, out: %zu, len %zu\n",
677 __func__, dimm_name, pkg.nd_command,
678 in_len, out_len, buf_len);
679
680 for (i = 0; i < ARRAY_SIZE(pkg.nd_reserved2); i++)
681 if (pkg.nd_reserved2[i])
682 return -EINVAL;
683 }
684
646 /* process an output envelope */ 685 /* process an output envelope */
647 for (i = 0; i < desc->out_num; i++) { 686 for (i = 0; i < desc->out_num; i++) {
648 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, 687 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,