From patchwork Wed Feb 24 02:17:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 8398191 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 702B79F52D for ; Wed, 24 Feb 2016 02:18:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 69A062034C for ; Wed, 24 Feb 2016 02:18:07 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5CD5F2034A for ; Wed, 24 Feb 2016 02:18:06 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 7702A1A1F80; Tue, 23 Feb 2016 18:18:09 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by ml01.01.org (Postfix) with ESMTP id 853241A1F9C for ; Tue, 23 Feb 2016 18:18:08 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 23 Feb 2016 18:18:06 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,492,1449561600"; d="scan'208";a="893246528" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.54.39.136]) by orsmga001.jf.intel.com with ESMTP; 23 Feb 2016 18:18:05 -0800 Subject: [PATCH 8/8] tools/testing/nvdimm: expand ars unit testing From: Dan Williams To: linux-nvdimm@lists.01.org Date: Tue, 23 Feb 2016 18:17:40 -0800 Message-ID: <20160224021740.22776.90857.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <20160224021655.22776.87952.stgit@dwillia2-desk3.amr.corp.intel.com> References: <20160224021655.22776.87952.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 Cc: linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Simulate platform-firmware-initiated and asynchronous scrub results. This injects poison in the middle of all nfit_test pmem address ranges. Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 112 +++++++++++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index a66842e61bbc..1555c09efba1 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -151,6 +151,11 @@ struct nfit_test { int (*alloc)(struct nfit_test *t); void (*setup)(struct nfit_test *t); int setup_hotplug; + struct ars_state { + struct nd_cmd_ars_status *ars_status; + unsigned long deadline; + spinlock_t lock; + } ars_state; }; static struct nfit_test *to_nfit_test(struct device *dev) @@ -232,30 +237,72 @@ static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, return 0; } -static int nfit_test_cmd_ars_start(struct nd_cmd_ars_start *nd_cmd, - unsigned int buf_len) +/* + * Initialize the ars_state to return an ars_result 1 second in the future with + * a 4K error range in the middle of the requested address range. + */ +static void post_ars_status(struct ars_state *ars_state, u64 addr, u64 len) { - if (buf_len < sizeof(*nd_cmd)) + struct nd_cmd_ars_status *ars_status; + struct nd_ars_record *ars_record; + + ars_state->deadline = jiffies + 1*HZ; + ars_status = ars_state->ars_status; + ars_status->status = 0; + ars_status->out_length = sizeof(struct nd_cmd_ars_status) + + sizeof(struct nd_ars_record); + ars_status->address = addr; + ars_status->length = len; + ars_status->type = ND_ARS_PERSISTENT; + ars_status->num_records = 1; + ars_record = &ars_status->records[0]; + ars_record->handle = 0; + ars_record->err_address = addr + len / 2; + ars_record->length = SZ_4K; +} + +static int nfit_test_cmd_ars_start(struct ars_state *ars_state, + struct nd_cmd_ars_start *ars_start, unsigned int buf_len, + int *cmd_rc) +{ + if (buf_len < sizeof(*ars_start)) return -EINVAL; - nd_cmd->status = 0; + spin_lock(&ars_state->lock); + if (time_before(jiffies, ars_state->deadline)) { + ars_start->status = NFIT_ARS_START_BUSY; + *cmd_rc = -EBUSY; + } else { + ars_start->status = 0; + ars_start->scrub_time = 1; + post_ars_status(ars_state, ars_start->address, + ars_start->length); + *cmd_rc = 0; + } + spin_unlock(&ars_state->lock); return 0; } -static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd, - unsigned int buf_len) +static int nfit_test_cmd_ars_status(struct ars_state *ars_state, + struct nd_cmd_ars_status *ars_status, unsigned int buf_len, + int *cmd_rc) { - if (buf_len < sizeof(*nd_cmd)) + if (buf_len < ars_state->ars_status->out_length) return -EINVAL; - nd_cmd->out_length = sizeof(struct nd_cmd_ars_status); - /* TODO: emit error records */ - nd_cmd->num_records = 0; - nd_cmd->address = 0; - nd_cmd->length = -1ULL; - nd_cmd->status = 0; - + spin_lock(&ars_state->lock); + if (time_before(jiffies, ars_state->deadline)) { + memset(ars_status, 0, buf_len); + ars_status->status = NFIT_ARS_STATUS_BUSY; + ars_status->out_length = sizeof(*ars_status); + *cmd_rc = -EBUSY; + } else { + memcpy(ars_status, ars_state->ars_status, + ars_state->ars_status->out_length); + *cmd_rc = 0; + } + spin_unlock(&ars_state->lock); return 0; } @@ -265,7 +312,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, { struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); - int i, rc = 0; + int i, rc = 0, __cmd_rc; + + if (!cmd_rc) + cmd_rc = &__cmd_rc; + *cmd_rc = 0; if (nvdimm) { struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); @@ -297,6 +348,8 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, return -ENOTTY; } } else { + struct ars_state *ars_state = &t->ars_state; + if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) return -ENOTTY; @@ -305,19 +358,18 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, rc = nfit_test_cmd_ars_cap(buf, buf_len); break; case ND_CMD_ARS_START: - rc = nfit_test_cmd_ars_start(buf, buf_len); + rc = nfit_test_cmd_ars_start(ars_state, buf, buf_len, + cmd_rc); break; case ND_CMD_ARS_STATUS: - rc = nfit_test_cmd_ars_status(buf, buf_len); + rc = nfit_test_cmd_ars_status(ars_state, buf, buf_len, + cmd_rc); break; default: return -ENOTTY; } } - /* TODO: error status tests */ - if (cmd_rc) - *cmd_rc = 0; return rc; } @@ -427,6 +479,18 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) return NULL; } +static int ars_state_init(struct device *dev, struct ars_state *ars_state) +{ + ars_state->ars_status = devm_kzalloc(dev, + sizeof(struct nd_cmd_ars_status) + + sizeof(struct nd_ars_record) * NFIT_TEST_ARS_RECORDS, + GFP_KERNEL); + if (!ars_state->ars_status) + return -ENOMEM; + spin_lock_init(&ars_state->lock); + return 0; +} + static int nfit_test0_alloc(struct nfit_test *t) { size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA @@ -476,7 +540,7 @@ static int nfit_test0_alloc(struct nfit_test *t) return -ENOMEM; } - return 0; + return ars_state_init(&t->pdev.dev, &t->ars_state); } static int nfit_test1_alloc(struct nfit_test *t) @@ -494,7 +558,7 @@ static int nfit_test1_alloc(struct nfit_test *t) if (!t->spa_set[0]) return -ENOMEM; - return 0; + return ars_state_init(&t->pdev.dev, &t->ars_state); } static void nfit_test0_setup(struct nfit_test *t) @@ -1157,6 +1221,8 @@ static void nfit_test0_setup(struct nfit_test *t) flush->hint_address[0] = t->flush_dma[4]; } + post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); + acpi_desc = &t->acpi_desc; set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); @@ -1218,6 +1284,8 @@ static void nfit_test1_setup(struct nfit_test *t) dcr->code = NFIT_FIC_BYTE; dcr->windows = 0; + post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); + acpi_desc = &t->acpi_desc; set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);