From patchwork Wed Aug 31 07:28:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Walter X-Patchwork-Id: 664424 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sPHYx2g9Sz9sC3 for ; Wed, 31 Aug 2016 17:48:21 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bf0Eo-0003U5-FO; Wed, 31 Aug 2016 07:47:10 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bezyf-00067e-Hm for linux-mtd@bombadil.infradead.org; Wed, 31 Aug 2016 07:30:29 +0000 Received: from mail.sigma-star.at ([95.130.255.111]) by casper.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bezyb-0008WF-CJ for linux-mtd@lists.infradead.org; Wed, 31 Aug 2016 07:30:28 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by mail.sigma-star.at (Postfix) with ESMTP id 2844E24E0005; Wed, 31 Aug 2016 09:29:41 +0200 (CEST) X-Virus-Scanned: amavisd-new at mail.sigma-star.at Received: from dw (unknown [82.150.214.13]) by mail.sigma-star.at (Postfix) with ESMTPSA id 7F8A824E0002; Wed, 31 Aug 2016 09:29:39 +0200 (CEST) Received: by dw (sSMTP sendmail emulation); Wed, 31 Aug 2016 09:29:40 +0200 From: Daniel Walter To: linux-mtd@lists.infradead.org Subject: [PATCH 21/46] mtd: nandsim: Implement preliminary destructor function Date: Wed, 31 Aug 2016 09:28:28 +0200 Message-Id: <20160831072853.27822-22-dwalter@sigma-star.at> X-Mailer: git-send-email 2.8.3 In-Reply-To: <20160831072853.27822-1-dwalter@sigma-star.at> References: <20160831072853.27822-1-dwalter@sigma-star.at> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160831_083025_600049_104E9AD1 X-CRM114-Status: GOOD ( 22.65 ) X-Spam-Score: -3.4 (---) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-3.4 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -1.5 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Weinberger , linux-kernel@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Richard Weinberger This function will be used via ioctl() to remove nandsim instances. Signed-off-by: Richard Weinberger --- drivers/mtd/nand/nandsim.c | 80 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/mtd/nandsim.h | 2 +- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 344f5c4..f8b9e76 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -328,7 +329,10 @@ struct ns_file_data { */ struct nandsim { unsigned int index; + unsigned int refcnt; + spinlock_t refcnt_lock; struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS]; + bool destroying; unsigned int nbparts; uint busw; /* flash chip bus width (8 or 16) */ @@ -2509,6 +2513,41 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req) return ns->index; } +static int ns_ctrl_destroy_instance(struct ns_destroy_instance_req *req) +{ + struct mtd_info *nsmtd; + int id = req->id, ret = 0; + struct nand_chip *chip; + struct nandsim *ns; + + if (id < 0 || id >= NS_MAX_DEVICES) + return -EINVAL; + + mutex_lock(&ns_mtd_mutex); + nsmtd = ns_mtds[id]; + if (nsmtd) { + chip = mtd_to_nand(nsmtd); + ns = nand_get_controller_data(chip); + spin_lock(&ns->refcnt_lock); + if (ns->refcnt > 0) { + ret = -EBUSY; + spin_unlock(&ns->refcnt_lock); + goto out; + } + ns->destroying = true; + spin_unlock(&ns->refcnt_lock); + ret = ns_destroy_instance(nsmtd); + if (ret) + goto out; + ns_mtds[id] = NULL; + } + +out: + mutex_unlock(&ns_mtd_mutex); + + return ret; +} + static long ns_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2543,6 +2582,32 @@ static struct miscdevice nandsim_ctrl_cdev = { .fops = &nansim_ctrl_fops, }; +static void ns_put_device(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); + + spin_lock(&ns->refcnt_lock); + ns->refcnt -= 1; + spin_unlock(&ns->refcnt_lock); +} + +static int ns_get_device(struct mtd_info *mtd) +{ + int ret = 0; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); + + spin_lock(&ns->refcnt_lock); + if (ns->destroying) + ret = -EBUSY; + else + ns->refcnt += 1; + spin_unlock(&ns->refcnt_lock); + + return ret; +} + struct mtd_info *ns_new_instance(struct nandsim_params *nsparam) { struct nand_chip *chip; @@ -2587,6 +2652,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam) INIT_LIST_HEAD(&nand->grave_pages); INIT_LIST_HEAD(&nand->weak_pages); INIT_LIST_HEAD(&nand->weak_blocks); + spin_lock_init(&nand->refcnt_lock); /* * Register simulator's callbacks. @@ -2637,6 +2703,8 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam) } nsmtd->owner = THIS_MODULE; + nsmtd->_get_device = ns_get_device; + nsmtd->_put_device = ns_put_device; if ((retval = parse_weakblocks(nand, nsparam->weakblocks)) != 0) goto error; @@ -2750,11 +2818,15 @@ error: } EXPORT_SYMBOL_GPL(ns_new_instance); -void ns_destroy_instance(struct mtd_info *nsmtd) +int ns_destroy_instance(struct mtd_info *nsmtd) { + int i, ret; struct nand_chip *chip = mtd_to_nand(nsmtd); struct nandsim *ns = nand_get_controller_data(chip); - int i; + + ret = __nand_release(nsmtd); + if (ret) + return ret; nandsim_debugfs_remove(ns); free_lists(ns); @@ -2763,6 +2835,8 @@ void ns_destroy_instance(struct mtd_info *nsmtd) for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) kfree(ns->partitions[i].name); kfree(mtd_to_nand(nsmtd)); /* Free other structures */ + + return 0; } EXPORT_SYMBOL_GPL(ns_destroy_instance); @@ -2773,7 +2847,7 @@ static void ns_destroy_all(void) mutex_lock(&ns_mtd_mutex); for (i = 0; i < NS_MAX_DEVICES; i++) if (ns_mtds[i]) - ns_destroy_instance(ns_mtds[i]); + WARN_ON(ns_destroy_instance(ns_mtds[i]) != 0); mutex_unlock(&ns_mtd_mutex); } diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h index 6e3b4a2..a0ca0fb 100644 --- a/include/linux/mtd/nandsim.h +++ b/include/linux/mtd/nandsim.h @@ -75,7 +75,7 @@ struct ns_backend_ops { }; struct mtd_info *ns_new_instance(struct nandsim_params *nsparam); -void ns_destroy_instance(struct mtd_info *nsmtd); +int ns_destroy_instance(struct mtd_info *nsmtd); struct nandsim_geom *nandsim_get_geom(struct nandsim *ns); struct nandsim_regs *nandsim_get_regs(struct nandsim *ns); void nandsim_set_backend_data(struct nandsim *ns, void *data);