From patchwork Thu Jun 22 02:15:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uma Krishnan X-Patchwork-Id: 9803329 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 37DD760329 for ; Thu, 22 Jun 2017 02:15:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2976328531 for ; Thu, 22 Jun 2017 02:15:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1DF8028539; Thu, 22 Jun 2017 02:15:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6423E28531 for ; Thu, 22 Jun 2017 02:15:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752105AbdFVCP2 (ORCPT ); Wed, 21 Jun 2017 22:15:28 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:40803 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751140AbdFVCP2 (ORCPT ); Wed, 21 Jun 2017 22:15:28 -0400 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v5M2En3b034875 for ; Wed, 21 Jun 2017 22:15:27 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0a-001b2d01.pphosted.com with ESMTP id 2b7w13m1tw-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 21 Jun 2017 22:15:27 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 21 Jun 2017 20:15:26 -0600 Received: from b03cxnp08026.gho.boulder.ibm.com (9.17.130.18) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 21 Jun 2017 20:15:23 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v5M2FLhd59703512; Wed, 21 Jun 2017 19:15:21 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 03D08BE04A; Wed, 21 Jun 2017 20:15:21 -0600 (MDT) Received: from p8tul1-build.aus.stglabs.ibm.com (unknown [9.3.141.206]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id 4D792BE03A; Wed, 21 Jun 2017 20:15:20 -0600 (MDT) From: Uma Krishnan To: linux-scsi@vger.kernel.org, James Bottomley , "Martin K. Petersen" , "Matthew R. Ochs" , "Manoj N. Kumar" Cc: linuxppc-dev@lists.ozlabs.org, Ian Munsie , Andrew Donnellan , Frederic Barrat , Christophe Lombard Subject: [PATCH 09/17] cxlflash: Create character device to provide host management interface Date: Wed, 21 Jun 2017 21:15:18 -0500 X-Mailer: git-send-email 2.1.0 In-Reply-To: <1498097563-8680-1-git-send-email-ukrishn@linux.vnet.ibm.com> References: <1498097563-8680-1-git-send-email-ukrishn@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17062202-0020-0000-0000-00000C368258 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00007269; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000214; SDB=6.00878072; UDB=6.00437482; IPR=6.00658212; BA=6.00005434; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00015913; XFM=3.00000015; UTC=2017-06-22 02:15:25 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17062202-0021-0000-0000-00005CE6E0B9 Message-Id: <1498097718-9006-1-git-send-email-ukrishn@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-06-22_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1703280000 definitions=main-1706220037 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The cxlflash driver currently lacks host management interface. Future devices supported by cxlflash will provide a variety of host-wide management functions. Examples include LUN provisioning, hardware debug support, and firmware download. In order to provide a way to manage the device, a character device will be created during probe of each adapter. This device will support a set of ioctls defined in the SISLite specification from which administrators can manage the adapter. Signed-off-by: Uma Krishnan Acked-by: Matthew R. Ochs --- drivers/scsi/cxlflash/common.h | 6 +- drivers/scsi/cxlflash/main.c | 207 ++++++++++++++++++++++++++++++++++++++++- drivers/scsi/cxlflash/main.h | 1 + 3 files changed, 212 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 11a5b0a..cbc0eb7 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -16,6 +16,7 @@ #define _CXLFLASH_COMMON_H #include +#include #include #include #include @@ -86,7 +87,8 @@ enum cxlflash_init_state { INIT_STATE_NONE, INIT_STATE_PCI, INIT_STATE_AFU, - INIT_STATE_SCSI + INIT_STATE_SCSI, + INIT_STATE_CDEV }; enum cxlflash_state { @@ -116,6 +118,8 @@ struct cxlflash_cfg { struct pci_device_id *dev_id; struct Scsi_Host *host; int num_fc_ports; + struct cdev cdev; + struct device *chardev; ulong cxlflash_regs_pci; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index ceb247b..0656dd2 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -34,6 +34,10 @@ MODULE_AUTHOR("Manoj N. Kumar "); MODULE_AUTHOR("Matthew R. Ochs "); MODULE_LICENSE("GPL"); +static struct class *cxlflash_class; +static u32 cxlflash_major; +static DECLARE_BITMAP(cxlflash_minor, CXLFLASH_MAX_ADAPTERS); + /** * process_cmd_err() - command error handler * @cmd: AFU command that experienced the error. @@ -863,6 +867,47 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait) } /** + * cxlflash_get_minor() - gets the first available minor number + * + * Return: Unique minor number that can be used to create the character device. + */ +static int cxlflash_get_minor(void) +{ + int minor; + long bit; + + bit = find_first_zero_bit(cxlflash_minor, CXLFLASH_MAX_ADAPTERS); + if (bit >= CXLFLASH_MAX_ADAPTERS) + return -1; + + minor = bit & MINORMASK; + set_bit(minor, cxlflash_minor); + return minor; +} + +/** + * cxlflash_put_minor() - releases the minor number + * @minor: Minor number that is no longer needed. + */ +static void cxlflash_put_minor(int minor) +{ + clear_bit(minor, cxlflash_minor); +} + +/** + * cxlflash_release_chrdev() - release the character device for the host + * @cfg: Internal structure associated with the host. + */ +static void cxlflash_release_chrdev(struct cxlflash_cfg *cfg) +{ + put_device(cfg->chardev); + device_unregister(cfg->chardev); + cfg->chardev = NULL; + cdev_del(&cfg->cdev); + cxlflash_put_minor(MINOR(cfg->cdev.dev)); +} + +/** * cxlflash_remove() - PCI entry point to tear down host * @pdev: PCI device associated with the host. * @@ -897,6 +942,8 @@ static void cxlflash_remove(struct pci_dev *pdev) cxlflash_stop_term_user_contexts(cfg); switch (cfg->init_state) { + case INIT_STATE_CDEV: + cxlflash_release_chrdev(cfg); case INIT_STATE_SCSI: cxlflash_term_local_luns(cfg); scsi_remove_host(cfg->host); @@ -3120,6 +3167,86 @@ static void cxlflash_worker_thread(struct work_struct *work) } /** + * cxlflash_chr_open() - character device open handler + * @inode: Device inode associated with this character device. + * @file: File pointer for this device. + * + * Only users with admin privileges are allowed to open the character device. + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_chr_open(struct inode *inode, struct file *file) +{ + struct cxlflash_cfg *cfg; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + cfg = container_of(inode->i_cdev, struct cxlflash_cfg, cdev); + file->private_data = cfg; + + return 0; +} + +/* + * Character device file operations + */ +static const struct file_operations cxlflash_chr_fops = { + .owner = THIS_MODULE, + .open = cxlflash_chr_open, +}; + +/** + * init_chrdev() - initialize the character device for the host + * @cfg: Internal structure associated with the host. + * + * Return: 0 on success, -errno on failure + */ +static int init_chrdev(struct cxlflash_cfg *cfg) +{ + struct device *dev = &cfg->dev->dev; + struct device *char_dev; + dev_t devno; + int minor; + int rc = 0; + + minor = cxlflash_get_minor(); + if (unlikely(minor < 0)) { + dev_err(dev, "%s: Exhausted allowed adapters\n", __func__); + rc = -ENOSPC; + goto out; + } + + devno = MKDEV(cxlflash_major, minor); + cdev_init(&cfg->cdev, &cxlflash_chr_fops); + + rc = cdev_add(&cfg->cdev, devno, 1); + if (rc) { + dev_err(dev, "%s: cdev_add failed rc=%d\n", __func__, rc); + goto err1; + } + + char_dev = device_create(cxlflash_class, NULL, devno, + NULL, "cxlflash%d", minor); + if (IS_ERR(char_dev)) { + rc = PTR_ERR(char_dev); + dev_err(dev, "%s: device_create failed rc=%d\n", + __func__, rc); + goto err2; + } + + cfg->chardev = char_dev; +out: + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); + return rc; +err2: + cdev_del(&cfg->cdev); +err1: + cxlflash_put_minor(minor); + goto out; +} + +/** * cxlflash_probe() - PCI entry point to add host * @pdev: PCI device associated with the host. * @dev_id: PCI device id associated with device. @@ -3229,6 +3356,13 @@ static int cxlflash_probe(struct pci_dev *pdev, } cfg->init_state = INIT_STATE_SCSI; + rc = init_chrdev(cfg); + if (rc) { + dev_err(dev, "%s: init_chrdev failed rc=%d\n", __func__, rc); + goto out_remove; + } + cfg->init_state = INIT_STATE_CDEV; + if (wq_has_sleeper(&cfg->reset_waitq)) { cfg->state = STATE_PROBED; wake_up_all(&cfg->reset_waitq); @@ -3331,6 +3465,63 @@ static void cxlflash_pci_resume(struct pci_dev *pdev) scsi_unblock_requests(cfg->host); } +/** + * cxlflash_devnode() - provides devtmpfs for devices in the cxlflash class + * @dev: Character device. + * @mode: Mode that can be used to verify access. + * + * Return: Allocated string describing the devtmpfs structure. + */ +static char *cxlflash_devnode(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cxlflash/%s", dev_name(dev)); +} + +/** + * cxlflash_class_init() - create character device class + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_class_init(void) +{ + dev_t devno; + int rc = 0; + + rc = alloc_chrdev_region(&devno, 0, CXLFLASH_MAX_ADAPTERS, "cxlflash"); + if (unlikely(rc)) { + pr_err("%s: alloc_chrdev_region failed rc=%d\n", __func__, rc); + goto out; + } + + cxlflash_major = MAJOR(devno); + + cxlflash_class = class_create(THIS_MODULE, "cxlflash"); + if (IS_ERR(cxlflash_class)) { + rc = PTR_ERR(cxlflash_class); + pr_err("%s: class_create failed rc=%d\n", __func__, rc); + goto err; + } + + cxlflash_class->devnode = cxlflash_devnode; +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +err: + unregister_chrdev_region(devno, CXLFLASH_MAX_ADAPTERS); + goto out; +} + +/** + * cxlflash_class_exit() - destroy character device class + */ +static void cxlflash_class_exit(void) +{ + dev_t devno = MKDEV(cxlflash_major, 0); + + class_destroy(cxlflash_class); + unregister_chrdev_region(devno, CXLFLASH_MAX_ADAPTERS); +} + static const struct pci_error_handlers cxlflash_err_handler = { .error_detected = cxlflash_pci_error_detected, .slot_reset = cxlflash_pci_slot_reset, @@ -3356,10 +3547,23 @@ static struct pci_driver cxlflash_driver = { */ static int __init init_cxlflash(void) { + int rc; + check_sizes(); cxlflash_list_init(); + rc = cxlflash_class_init(); + if (unlikely(rc)) + goto out; - return pci_register_driver(&cxlflash_driver); + rc = pci_register_driver(&cxlflash_driver); + if (unlikely(rc)) + goto err; +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +err: + cxlflash_class_exit(); + goto out; } /** @@ -3371,6 +3575,7 @@ static void __exit exit_cxlflash(void) cxlflash_free_errpage(); pci_unregister_driver(&cxlflash_driver); + cxlflash_class_exit(); } module_init(init_cxlflash); diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h index 49657f1..44c86c2 100644 --- a/drivers/scsi/cxlflash/main.h +++ b/drivers/scsi/cxlflash/main.h @@ -22,6 +22,7 @@ #define CXLFLASH_NAME "cxlflash" #define CXLFLASH_ADAPTER_NAME "IBM POWER CXL Flash Adapter" +#define CXLFLASH_MAX_ADAPTERS 32 #define PCI_DEVICE_ID_IBM_CORSA 0x04F0 #define PCI_DEVICE_ID_IBM_FLASH_GT 0x0600