Merge tag 'libnvdimm-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm updayes from Vishal Verma: "You'd normally receive this pull request from Dan Williams, but he's busy watching a newborn (Congrats Dan!), so I'm watching libnvdimm this cycle. This adds a new feature in libnvdimm - 'Runtime Firmware Activation', and a few small cleanups and fixes in libnvdimm and DAX. I'd originally intended to make separate topic-based pull requests - one for libnvdimm, and one for DAX, but some of the DAX material fell out since it wasn't quite ready. Summary: - add 'Runtime Firmware Activation' support for NVDIMMs that advertise the relevant capability - misc libnvdimm and DAX cleanups" * tag 'libnvdimm-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr libnvdimm/security: the 'security' attr never show 'overwrite' state libnvdimm/security: fix a typo ACPI: NFIT: Fix ARS zero-sized allocation dax: Fix incorrect argument passed to xas_set_err() ACPI: NFIT: Add runtime firmware activate support PM, libnvdimm: Add runtime firmware activation support libnvdimm: Convert to DEVICE_ATTR_ADMIN_RO() drivers/dax: Expand lock scope to cover the use of addresses fs/dax: Remove unused size parameter dax: print error message by pr_info() in __generic_fsdax_supported() driver-core: Introduce DEVICE_ATTR_ADMIN_{RO,RW} tools/testing/nvdimm: Emulate firmware activation commands tools/testing/nvdimm: Prepare nfit_ctl_test() for ND_CMD_CALL emulation tools/testing/nvdimm: Add command debug messages tools/testing/nvdimm: Cleanup dimm index passing ACPI: NFIT: Define runtime firmware activation commands ACPI: NFIT: Move bus_dsm_mask out of generic nvdimm_bus_descriptor libnvdimm: Validate command family indices
This commit is contained in:
@@ -173,6 +173,9 @@ struct nfit_test_fw {
|
||||
u64 version;
|
||||
u32 size_received;
|
||||
u64 end_time;
|
||||
bool armed;
|
||||
bool missed_activate;
|
||||
unsigned long last_activate;
|
||||
};
|
||||
|
||||
struct nfit_test {
|
||||
@@ -345,7 +348,7 @@ static int nd_intel_test_finish_fw(struct nfit_test *t,
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (fw->state == FW_STATE_UPDATED) {
|
||||
/* update already done, need cold boot */
|
||||
/* update already done, need activation */
|
||||
nd_cmd->status = 0x20007;
|
||||
return 0;
|
||||
}
|
||||
@@ -430,6 +433,7 @@ static int nd_intel_test_finish_query(struct nfit_test *t,
|
||||
}
|
||||
dev_dbg(dev, "%s: transition out verify\n", __func__);
|
||||
fw->state = FW_STATE_UPDATED;
|
||||
fw->missed_activate = false;
|
||||
/* fall through */
|
||||
case FW_STATE_UPDATED:
|
||||
nd_cmd->status = 0;
|
||||
@@ -1178,6 +1182,134 @@ static int nd_intel_test_cmd_master_secure_erase(struct nfit_test *t,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long last_activate;
|
||||
|
||||
static int nvdimm_bus_intel_fw_activate_businfo(struct nfit_test *t,
|
||||
struct nd_intel_bus_fw_activate_businfo *nd_cmd,
|
||||
unsigned int buf_len)
|
||||
{
|
||||
int i, armed = 0;
|
||||
int state;
|
||||
u64 tmo;
|
||||
|
||||
for (i = 0; i < NUM_DCR; i++) {
|
||||
struct nfit_test_fw *fw = &t->fw[i];
|
||||
|
||||
if (fw->armed)
|
||||
armed++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate 3 second activation max, and 1 second incremental
|
||||
* quiesce time per dimm requiring multiple activates to get all
|
||||
* DIMMs updated.
|
||||
*/
|
||||
if (armed)
|
||||
state = ND_INTEL_FWA_ARMED;
|
||||
else if (!last_activate || time_after(jiffies, last_activate + 3 * HZ))
|
||||
state = ND_INTEL_FWA_IDLE;
|
||||
else
|
||||
state = ND_INTEL_FWA_BUSY;
|
||||
|
||||
tmo = armed * USEC_PER_SEC;
|
||||
*nd_cmd = (struct nd_intel_bus_fw_activate_businfo) {
|
||||
.capability = ND_INTEL_BUS_FWA_CAP_FWQUIESCE
|
||||
| ND_INTEL_BUS_FWA_CAP_OSQUIESCE
|
||||
| ND_INTEL_BUS_FWA_CAP_RESET,
|
||||
.state = state,
|
||||
.activate_tmo = tmo,
|
||||
.cpu_quiesce_tmo = tmo,
|
||||
.io_quiesce_tmo = tmo,
|
||||
.max_quiesce_tmo = 3 * USEC_PER_SEC,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvdimm_bus_intel_fw_activate(struct nfit_test *t,
|
||||
struct nd_intel_bus_fw_activate *nd_cmd,
|
||||
unsigned int buf_len)
|
||||
{
|
||||
struct nd_intel_bus_fw_activate_businfo info;
|
||||
u32 status = 0;
|
||||
int i;
|
||||
|
||||
nvdimm_bus_intel_fw_activate_businfo(t, &info, sizeof(info));
|
||||
if (info.state == ND_INTEL_FWA_BUSY)
|
||||
status = ND_INTEL_BUS_FWA_STATUS_BUSY;
|
||||
else if (info.activate_tmo > info.max_quiesce_tmo)
|
||||
status = ND_INTEL_BUS_FWA_STATUS_TMO;
|
||||
else if (info.state == ND_INTEL_FWA_IDLE)
|
||||
status = ND_INTEL_BUS_FWA_STATUS_NOARM;
|
||||
|
||||
dev_dbg(&t->pdev.dev, "status: %d\n", status);
|
||||
nd_cmd->status = status;
|
||||
if (status && status != ND_INTEL_BUS_FWA_STATUS_TMO)
|
||||
return 0;
|
||||
|
||||
last_activate = jiffies;
|
||||
for (i = 0; i < NUM_DCR; i++) {
|
||||
struct nfit_test_fw *fw = &t->fw[i];
|
||||
|
||||
if (!fw->armed)
|
||||
continue;
|
||||
if (fw->state != FW_STATE_UPDATED)
|
||||
fw->missed_activate = true;
|
||||
else
|
||||
fw->state = FW_STATE_NEW;
|
||||
fw->armed = false;
|
||||
fw->last_activate = last_activate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_cmd_fw_activate_dimminfo(struct nfit_test *t,
|
||||
struct nd_intel_fw_activate_dimminfo *nd_cmd,
|
||||
unsigned int buf_len, int dimm)
|
||||
{
|
||||
struct nd_intel_bus_fw_activate_businfo info;
|
||||
struct nfit_test_fw *fw = &t->fw[dimm];
|
||||
u32 result, state;
|
||||
|
||||
nvdimm_bus_intel_fw_activate_businfo(t, &info, sizeof(info));
|
||||
|
||||
if (info.state == ND_INTEL_FWA_BUSY)
|
||||
state = ND_INTEL_FWA_BUSY;
|
||||
else if (info.state == ND_INTEL_FWA_IDLE)
|
||||
state = ND_INTEL_FWA_IDLE;
|
||||
else if (fw->armed)
|
||||
state = ND_INTEL_FWA_ARMED;
|
||||
else
|
||||
state = ND_INTEL_FWA_IDLE;
|
||||
|
||||
result = ND_INTEL_DIMM_FWA_NONE;
|
||||
if (last_activate && fw->last_activate == last_activate &&
|
||||
state == ND_INTEL_FWA_IDLE) {
|
||||
if (fw->missed_activate)
|
||||
result = ND_INTEL_DIMM_FWA_NOTSTAGED;
|
||||
else
|
||||
result = ND_INTEL_DIMM_FWA_SUCCESS;
|
||||
}
|
||||
|
||||
*nd_cmd = (struct nd_intel_fw_activate_dimminfo) {
|
||||
.result = result,
|
||||
.state = state,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_cmd_fw_activate_arm(struct nfit_test *t,
|
||||
struct nd_intel_fw_activate_arm *nd_cmd,
|
||||
unsigned int buf_len, int dimm)
|
||||
{
|
||||
struct nfit_test_fw *fw = &t->fw[dimm];
|
||||
|
||||
fw->armed = nd_cmd->activate_arm == ND_INTEL_DIMM_FWA_ARM;
|
||||
nd_cmd->status = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
|
||||
{
|
||||
@@ -1192,6 +1324,29 @@ static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
|
||||
return i;
|
||||
}
|
||||
|
||||
static void nfit_ctl_dbg(struct acpi_nfit_desc *acpi_desc,
|
||||
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
|
||||
unsigned int func = cmd;
|
||||
unsigned int family = 0;
|
||||
|
||||
if (cmd == ND_CMD_CALL) {
|
||||
struct nd_cmd_pkg *pkg = buf;
|
||||
|
||||
len = pkg->nd_size_in;
|
||||
family = pkg->nd_family;
|
||||
buf = pkg->nd_payload;
|
||||
func = pkg->nd_command;
|
||||
}
|
||||
dev_dbg(&t->pdev.dev, "%s family: %d cmd: %d: func: %d input length: %d\n",
|
||||
nvdimm ? nvdimm_name(nvdimm) : "bus", family, cmd, func,
|
||||
len);
|
||||
print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 16, 4,
|
||||
buf, min(len, 256u), true);
|
||||
}
|
||||
|
||||
static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
|
||||
unsigned int buf_len, int *cmd_rc)
|
||||
@@ -1205,6 +1360,8 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
cmd_rc = &__cmd_rc;
|
||||
*cmd_rc = 0;
|
||||
|
||||
nfit_ctl_dbg(acpi_desc, nvdimm, cmd, buf, buf_len);
|
||||
|
||||
if (nvdimm) {
|
||||
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
|
||||
unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
|
||||
@@ -1224,6 +1381,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
i = get_dimm(nfit_mem, func);
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i >= NUM_DCR) {
|
||||
dev_WARN_ONCE(&t->pdev.dev, 1,
|
||||
"ND_CMD_CALL only valid for nfit_test0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (func) {
|
||||
case NVDIMM_INTEL_GET_SECURITY_STATE:
|
||||
@@ -1252,11 +1414,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
break;
|
||||
case NVDIMM_INTEL_OVERWRITE:
|
||||
rc = nd_intel_test_cmd_overwrite(t,
|
||||
buf, buf_len, i - t->dcr_idx);
|
||||
buf, buf_len, i);
|
||||
break;
|
||||
case NVDIMM_INTEL_QUERY_OVERWRITE:
|
||||
rc = nd_intel_test_cmd_query_overwrite(t,
|
||||
buf, buf_len, i - t->dcr_idx);
|
||||
buf, buf_len, i);
|
||||
break;
|
||||
case NVDIMM_INTEL_SET_MASTER_PASSPHRASE:
|
||||
rc = nd_intel_test_cmd_master_set_pass(t,
|
||||
@@ -1266,54 +1428,59 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
rc = nd_intel_test_cmd_master_secure_erase(t,
|
||||
buf, buf_len, i);
|
||||
break;
|
||||
case NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO:
|
||||
rc = nd_intel_test_cmd_fw_activate_dimminfo(
|
||||
t, buf, buf_len, i);
|
||||
break;
|
||||
case NVDIMM_INTEL_FW_ACTIVATE_ARM:
|
||||
rc = nd_intel_test_cmd_fw_activate_arm(
|
||||
t, buf, buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_ENABLE_LSS_STATUS:
|
||||
rc = nd_intel_test_cmd_set_lss_status(t,
|
||||
buf, buf_len);
|
||||
break;
|
||||
case ND_INTEL_FW_GET_INFO:
|
||||
rc = nd_intel_test_get_fw_info(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_FW_START_UPDATE:
|
||||
rc = nd_intel_test_start_update(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_FW_SEND_DATA:
|
||||
rc = nd_intel_test_send_data(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_FW_FINISH_UPDATE:
|
||||
rc = nd_intel_test_finish_fw(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_FW_FINISH_QUERY:
|
||||
rc = nd_intel_test_finish_query(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
buf_len, i);
|
||||
break;
|
||||
case ND_INTEL_SMART:
|
||||
rc = nfit_test_cmd_smart(buf, buf_len,
|
||||
&t->smart[i - t->dcr_idx]);
|
||||
&t->smart[i]);
|
||||
break;
|
||||
case ND_INTEL_SMART_THRESHOLD:
|
||||
rc = nfit_test_cmd_smart_threshold(buf,
|
||||
buf_len,
|
||||
&t->smart_threshold[i -
|
||||
t->dcr_idx]);
|
||||
&t->smart_threshold[i]);
|
||||
break;
|
||||
case ND_INTEL_SMART_SET_THRESHOLD:
|
||||
rc = nfit_test_cmd_smart_set_threshold(buf,
|
||||
buf_len,
|
||||
&t->smart_threshold[i -
|
||||
t->dcr_idx],
|
||||
&t->smart[i - t->dcr_idx],
|
||||
&t->smart_threshold[i],
|
||||
&t->smart[i],
|
||||
&t->pdev.dev, t->dimm_dev[i]);
|
||||
break;
|
||||
case ND_INTEL_SMART_INJECT:
|
||||
rc = nfit_test_cmd_smart_inject(buf,
|
||||
buf_len,
|
||||
&t->smart_threshold[i -
|
||||
t->dcr_idx],
|
||||
&t->smart[i - t->dcr_idx],
|
||||
&t->smart_threshold[i],
|
||||
&t->smart[i],
|
||||
&t->pdev.dev, t->dimm_dev[i]);
|
||||
break;
|
||||
default:
|
||||
@@ -1353,9 +1520,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
if (!nd_desc)
|
||||
return -ENOTTY;
|
||||
|
||||
if (cmd == ND_CMD_CALL) {
|
||||
if (cmd == ND_CMD_CALL && call_pkg->nd_family
|
||||
== NVDIMM_BUS_FAMILY_NFIT) {
|
||||
func = call_pkg->nd_command;
|
||||
|
||||
buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
|
||||
buf = (void *) call_pkg->nd_payload;
|
||||
|
||||
@@ -1379,7 +1546,26 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
} else if (cmd == ND_CMD_CALL && call_pkg->nd_family
|
||||
== NVDIMM_BUS_FAMILY_INTEL) {
|
||||
func = call_pkg->nd_command;
|
||||
buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
|
||||
buf = (void *) call_pkg->nd_payload;
|
||||
|
||||
switch (func) {
|
||||
case NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO:
|
||||
rc = nvdimm_bus_intel_fw_activate_businfo(t,
|
||||
buf, buf_len);
|
||||
return rc;
|
||||
case NVDIMM_BUS_INTEL_FW_ACTIVATE:
|
||||
rc = nvdimm_bus_intel_fw_activate(t, buf,
|
||||
buf_len);
|
||||
return rc;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
} else if (cmd == ND_CMD_CALL)
|
||||
return -ENOTTY;
|
||||
|
||||
if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
|
||||
return -ENOTTY;
|
||||
@@ -1805,6 +1991,7 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
struct acpi_nfit_flush_address *flush;
|
||||
struct acpi_nfit_capabilities *pcap;
|
||||
unsigned int offset = 0, i;
|
||||
unsigned long *acpi_mask;
|
||||
|
||||
/*
|
||||
* spa0 (interleave first half of dimm0 and dimm1, note storage
|
||||
@@ -2507,10 +2694,10 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_dsm_mask);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_dsm_mask);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_dsm_mask);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_dsm_mask);
|
||||
set_bit(ND_INTEL_FW_GET_INFO, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_START_UPDATE, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_SEND_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
@@ -2531,6 +2718,12 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
&acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(NVDIMM_INTEL_MASTER_SECURE_ERASE,
|
||||
&acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(NVDIMM_INTEL_FW_ACTIVATE_ARM, &acpi_desc->dimm_cmd_force_en);
|
||||
|
||||
acpi_mask = &acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL];
|
||||
set_bit(NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO, acpi_mask);
|
||||
set_bit(NVDIMM_BUS_INTEL_FW_ACTIVATE, acpi_mask);
|
||||
}
|
||||
|
||||
static void nfit_test1_setup(struct nfit_test *t)
|
||||
@@ -2699,14 +2892,18 @@ static int nfit_ctl_test(struct device *dev)
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
const u64 test_val = 0x0123456789abcdefULL;
|
||||
unsigned long mask, cmd_size, offset;
|
||||
union {
|
||||
struct nd_cmd_get_config_size cfg_size;
|
||||
struct nd_cmd_clear_error clear_err;
|
||||
struct nd_cmd_ars_status ars_stat;
|
||||
struct nd_cmd_ars_cap ars_cap;
|
||||
char buf[sizeof(struct nd_cmd_ars_status)
|
||||
+ sizeof(struct nd_ars_record)];
|
||||
} cmds;
|
||||
struct nfit_ctl_test_cmd {
|
||||
struct nd_cmd_pkg pkg;
|
||||
union {
|
||||
struct nd_cmd_get_config_size cfg_size;
|
||||
struct nd_cmd_clear_error clear_err;
|
||||
struct nd_cmd_ars_status ars_stat;
|
||||
struct nd_cmd_ars_cap ars_cap;
|
||||
struct nd_intel_bus_fw_activate_businfo fwa_info;
|
||||
char buf[sizeof(struct nd_cmd_ars_status)
|
||||
+ sizeof(struct nd_ars_record)];
|
||||
};
|
||||
} cmd;
|
||||
|
||||
adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
|
||||
if (!adev)
|
||||
@@ -2731,11 +2928,15 @@ static int nfit_ctl_test(struct device *dev)
|
||||
.module = THIS_MODULE,
|
||||
.provider_name = "ACPI.NFIT",
|
||||
.ndctl = acpi_nfit_ctl,
|
||||
.bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_SET
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_CLEAR
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_GET,
|
||||
.bus_family_mask = 1UL << NVDIMM_BUS_FAMILY_NFIT
|
||||
| 1UL << NVDIMM_BUS_FAMILY_INTEL,
|
||||
},
|
||||
.bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_SET
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_CLEAR
|
||||
| 1UL << NFIT_CMD_ARS_INJECT_GET,
|
||||
.family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL] =
|
||||
NVDIMM_BUS_INTEL_FW_ACTIVATE_CMDMASK,
|
||||
.dev = &adev->dev,
|
||||
};
|
||||
|
||||
@@ -2766,21 +2967,21 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
|
||||
/* basic checkout of a typical 'get config size' command */
|
||||
cmd_size = sizeof(cmds.cfg_size);
|
||||
cmds.cfg_size = (struct nd_cmd_get_config_size) {
|
||||
cmd_size = sizeof(cmd.cfg_size);
|
||||
cmd.cfg_size = (struct nd_cmd_get_config_size) {
|
||||
.status = 0,
|
||||
.config_size = SZ_128K,
|
||||
.max_xfer = SZ_4K,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, nvdimm, ND_CMD_GET_CONFIG_SIZE,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc || cmds.cfg_size.status != 0
|
||||
|| cmds.cfg_size.config_size != SZ_128K
|
||||
|| cmds.cfg_size.max_xfer != SZ_4K) {
|
||||
if (rc < 0 || cmd_rc || cmd.cfg_size.status != 0
|
||||
|| cmd.cfg_size.config_size != SZ_128K
|
||||
|| cmd.cfg_size.max_xfer != SZ_4K) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
__func__, __LINE__, rc, cmd_rc);
|
||||
return -EIO;
|
||||
@@ -2789,14 +2990,14 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
/* test ars_status with zero output */
|
||||
cmd_size = offsetof(struct nd_cmd_ars_status, address);
|
||||
cmds.ars_stat = (struct nd_cmd_ars_status) {
|
||||
cmd.ars_stat = (struct nd_cmd_ars_status) {
|
||||
.out_length = 0,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
@@ -2806,16 +3007,16 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
|
||||
/* test ars_cap with benign extended status */
|
||||
cmd_size = sizeof(cmds.ars_cap);
|
||||
cmds.ars_cap = (struct nd_cmd_ars_cap) {
|
||||
cmd_size = sizeof(cmd.ars_cap);
|
||||
cmd.ars_cap = (struct nd_cmd_ars_cap) {
|
||||
.status = ND_ARS_PERSISTENT << 16,
|
||||
};
|
||||
offset = offsetof(struct nd_cmd_ars_cap, status);
|
||||
rc = setup_result(cmds.buf + offset, cmd_size - offset);
|
||||
rc = setup_result(cmd.buf + offset, cmd_size - offset);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_CAP,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
@@ -2825,19 +3026,19 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
|
||||
/* test ars_status with 'status' trimmed from 'out_length' */
|
||||
cmd_size = sizeof(cmds.ars_stat) + sizeof(struct nd_ars_record);
|
||||
cmds.ars_stat = (struct nd_cmd_ars_status) {
|
||||
cmd_size = sizeof(cmd.ars_stat) + sizeof(struct nd_ars_record);
|
||||
cmd.ars_stat = (struct nd_cmd_ars_status) {
|
||||
.out_length = cmd_size - 4,
|
||||
};
|
||||
record = &cmds.ars_stat.records[0];
|
||||
record = &cmd.ars_stat.records[0];
|
||||
*record = (struct nd_ars_record) {
|
||||
.length = test_val,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc || record->length != test_val) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
@@ -2847,19 +3048,19 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
|
||||
/* test ars_status with 'Output (Size)' including 'status' */
|
||||
cmd_size = sizeof(cmds.ars_stat) + sizeof(struct nd_ars_record);
|
||||
cmds.ars_stat = (struct nd_cmd_ars_status) {
|
||||
cmd_size = sizeof(cmd.ars_stat) + sizeof(struct nd_ars_record);
|
||||
cmd.ars_stat = (struct nd_cmd_ars_status) {
|
||||
.out_length = cmd_size,
|
||||
};
|
||||
record = &cmds.ars_stat.records[0];
|
||||
record = &cmd.ars_stat.records[0];
|
||||
*record = (struct nd_ars_record) {
|
||||
.length = test_val,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc || record->length != test_val) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
@@ -2869,15 +3070,15 @@ static int nfit_ctl_test(struct device *dev)
|
||||
|
||||
|
||||
/* test extended status for get_config_size results in failure */
|
||||
cmd_size = sizeof(cmds.cfg_size);
|
||||
cmds.cfg_size = (struct nd_cmd_get_config_size) {
|
||||
cmd_size = sizeof(cmd.cfg_size);
|
||||
cmd.cfg_size = (struct nd_cmd_get_config_size) {
|
||||
.status = 1 << 16,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, nvdimm, ND_CMD_GET_CONFIG_SIZE,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
|
||||
if (rc < 0 || cmd_rc >= 0) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
@@ -2886,16 +3087,46 @@ static int nfit_ctl_test(struct device *dev)
|
||||
}
|
||||
|
||||
/* test clear error */
|
||||
cmd_size = sizeof(cmds.clear_err);
|
||||
cmds.clear_err = (struct nd_cmd_clear_error) {
|
||||
cmd_size = sizeof(cmd.clear_err);
|
||||
cmd.clear_err = (struct nd_cmd_clear_error) {
|
||||
.length = 512,
|
||||
.cleared = 512,
|
||||
};
|
||||
rc = setup_result(cmds.buf, cmd_size);
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_CLEAR_ERROR,
|
||||
cmds.buf, cmd_size, &cmd_rc);
|
||||
cmd.buf, cmd_size, &cmd_rc);
|
||||
if (rc < 0 || cmd_rc) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
__func__, __LINE__, rc, cmd_rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* test firmware activate bus info */
|
||||
cmd_size = sizeof(cmd.fwa_info);
|
||||
cmd = (struct nfit_ctl_test_cmd) {
|
||||
.pkg = {
|
||||
.nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO,
|
||||
.nd_family = NVDIMM_BUS_FAMILY_INTEL,
|
||||
.nd_size_out = cmd_size,
|
||||
.nd_fw_size = cmd_size,
|
||||
},
|
||||
.fwa_info = {
|
||||
.state = ND_INTEL_FWA_IDLE,
|
||||
.capability = ND_INTEL_BUS_FWA_CAP_FWQUIESCE
|
||||
| ND_INTEL_BUS_FWA_CAP_OSQUIESCE,
|
||||
.activate_tmo = 1,
|
||||
.cpu_quiesce_tmo = 1,
|
||||
.io_quiesce_tmo = 1,
|
||||
.max_quiesce_tmo = 1,
|
||||
},
|
||||
};
|
||||
rc = setup_result(cmd.buf, cmd_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_CALL,
|
||||
&cmd, sizeof(cmd.pkg) + cmd_size, &cmd_rc);
|
||||
if (rc < 0 || cmd_rc) {
|
||||
dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
|
||||
__func__, __LINE__, rc, cmd_rc);
|
||||
|
Reference in New Issue
Block a user