Received: by 2002:a25:b794:0:0:0:0:0 with SMTP id n20csp6889200ybh; Thu, 8 Aug 2019 07:13:48 -0700 (PDT) X-Google-Smtp-Source: APXvYqxG/7AEy1c/nAbk4Dl6YvWp89TM5UdxWu6IPO0ZTxgqAvMLRJODm7K3b6lmYQ/404VPU3qJ X-Received: by 2002:a17:90a:2525:: with SMTP id j34mr4409494pje.11.1565273628303; Thu, 08 Aug 2019 07:13:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565273628; cv=none; d=google.com; s=arc-20160816; b=f8ML2UyjJcvKwoALjkicRaTyqMkV44/RzGHTHxvCVgxpZWG1kbM0USPMnn1fJ5Hk7l E8oAt9b+J9P+Mwge2IOm2Ca8oQXKlzSUKifaiRezDnwv2/5HieQYmx+EVzSOS4EiZY9y 7nerFba4JtMhcBoz+ddv8cIeEN+VrlD2PM00bkWZNHxEYCrOgW+CU/2eoSTSmVPnq2P6 RJ5Ew6aOGzY2l/SEXmbOZa5CRkxsl0kzod1Ie3CgP678Cceuqlz22gg4owdmmhteJBYe 69+sgSR7MRvF+n7rIuMFVNMw5chAM4N+mrS/Y7nSK8TG1XaoEIAt9BV62fc6yv8POAUN 34ng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=NNVZgrjZAoC1yeVxZddqbJGZYNnHMsHA3+Hp07xldq0=; b=G0/q8DVHzS3UOG/ChL3J3GhZRAztLURh4P2uoOVvD1EyzzcQPhGy6UovMQApmgYaAy U1ON4K7AAtb67k77lzyrKRfPTPB2PzYSFTRbokKfEwSIKrzAaoqIvRa8J3dnnLWzMkE7 vBzOyM+mI7UkXiaDVGHErVoBpJc2CFY67z2SV6JSR8P6n54c7/OXyqM20YvH1Z4syTnq RQ+T1Acs0c/MsO42xF9/aGHa5W2T3+YeqNJuJsUBXnDxCDK//jwBGpqQIBeoU1ieGcgt yOhHBB1F56/GD3ZcUrtLTnfD46wz+tsSLDWBSwy4EJL+N6OETTKyfMzD/ZqWw4cZQjIa aumQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=U2dCAgfB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q26si31918715pgt.233.2019.08.08.07.13.32; Thu, 08 Aug 2019 07:13:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=U2dCAgfB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2403825AbfHHOMH (ORCPT + 99 others); Thu, 8 Aug 2019 10:12:07 -0400 Received: from mail-ua1-f66.google.com ([209.85.222.66]:34482 "EHLO mail-ua1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390098AbfHHOMH (ORCPT ); Thu, 8 Aug 2019 10:12:07 -0400 Received: by mail-ua1-f66.google.com with SMTP id c4so9644612uad.1 for ; Thu, 08 Aug 2019 07:12:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=NNVZgrjZAoC1yeVxZddqbJGZYNnHMsHA3+Hp07xldq0=; b=U2dCAgfBv1ightu3KHjqo2GKg/cQiEULplV60BxGmuGUlnybV+X5qzQUdY6zWlVITq 5qBX/5wWKwqO50qy9jj4+hMUAr/lfCs4dhN/4rkiu15xsmJaVHphvoLaIa0FGdBtNWHd hrzoA6QVIfJa7SuIWIw1+b3vtB40SgbW38CTunEdCfb0XRbmEXl0FrQtxKntt5N5XNzt UkbSwiy6WSTp0z5NjPkU7CizrKEXsLkQC86s8VgOrSLXQKyFqM3jMEOhhQnaWforefCY u83npG1wOnOSlR05wu5yo2UxL51t5pDpXAefK7Y+RjPOZ3A/lUUXu3WRQ7o4JNpxZ2Do rhTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=NNVZgrjZAoC1yeVxZddqbJGZYNnHMsHA3+Hp07xldq0=; b=IDJ/P4M/mWicaCDCUlothf441szVCpIWPuMhJGaCD9/bTNHVdnPtOy6HxfsP1gz9Ql rkb+67E2OFIr27BRXIFbwgNN+Lx6oFXWBsQXxXnAlWqBe6pGGfvACsBnqtmD6NMPvOR3 rDaY+2BjHp8RGkMNhMbs8JK5FaGV+nS53fXYM87RPxGS/oxUHJu2kFb8uS84FLhMso/4 Opvtq/2SaqAmNxWSGmeqrTQpSJEsWjMW1a9Oq1y9Zn5SyXTDcq4Sub1tzHIGF7QjTSjq 3BvA26Rb0fKNj4BYtFn18oDRHvCy4BDDxAsAtPdE0mCIU9qxPFkGKZxP23TCHctzA89W HOpQ== X-Gm-Message-State: APjAAAVHYW/gd3cbQBLMJaF6qfw5Jbs7CCpiNIq4uJ6Peig3DIgce3CO wAuzOkraS0RL+LX1nH+1T4vUvt/9f95W8Evr6/MlxQ== X-Received: by 2002:ab0:20cc:: with SMTP id z12mr7849404ual.32.1565273525864; Thu, 08 Aug 2019 07:12:05 -0700 (PDT) MIME-Version: 1.0 References: <20190808122422.28521-1-ttayar@habana.ai> In-Reply-To: <20190808122422.28521-1-ttayar@habana.ai> From: Oded Gabbay Date: Thu, 8 Aug 2019 17:11:39 +0300 Message-ID: Subject: Re: [PATCH] habanalabs: Expose devices after initialization is done To: Tomer Tayar Cc: "linux-kernel@vger.kernel.org" Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Aug 8, 2019 at 3:25 PM Tomer Tayar wrote: > > The char devices are currently exposed to user before the device and > driver initialization are done. > This patch moves the cdev and device adding to the system to the end of > the initialization sequence, while keeping the creation of the > structures at the beginning to allow the usage of dev_*(). > > Signed-off-by: Tomer Tayar > --- > drivers/misc/habanalabs/device.c | 163 ++++++++++++++++++--------- > drivers/misc/habanalabs/habanalabs.h | 2 + > 2 files changed, 111 insertions(+), 54 deletions(-) > > diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c > index efde1fe7d286..9a5926888b99 100644 > --- a/drivers/misc/habanalabs/device.c > +++ b/drivers/misc/habanalabs/device.c > @@ -151,50 +151,94 @@ static const struct file_operations hl_ctrl_ops = { > .compat_ioctl = hl_ioctl_control > }; > > +static void device_release_func(struct device *dev) > +{ > + kfree(dev); > +} > + > /* > - * device_setup_cdev - setup cdev and device for habanalabs device > + * device_init_cdev - Initialize cdev and device for habanalabs device > * > * @hdev: pointer to habanalabs device structure > * @hclass: pointer to the class object of the device > * @minor: minor number of the specific device > * @fpos: file operations to install for this device > * @name: name of the device as it will appear in the filesystem > - * @cdev: pointer to the char device object that will be created > - * @dev: pointer to the device object that will be created > + * @cdev: pointer to the char device object that will be initialized > + * @dev: pointer to the device object that will be initialized > * > - * Create a cdev and a Linux device for habanalabs's device. Need to be > - * called at the end of the habanalabs device initialization process, > - * because this function exposes the device to the user > + * Initialize a cdev and a Linux device for habanalabs's device. > */ > -static int device_setup_cdev(struct hl_device *hdev, struct class *hclass, > +static int device_init_cdev(struct hl_device *hdev, struct class *hclass, > int minor, const struct file_operations *fops, > char *name, struct cdev *cdev, > struct device **dev) > { > - int err, devno = MKDEV(hdev->major, minor); > - > cdev_init(cdev, fops); > cdev->owner = THIS_MODULE; > - err = cdev_add(cdev, devno, 1); > - if (err) { > - pr_err("Failed to add char device %s\n", name); > - return err; > + > + *dev = kzalloc(sizeof(**dev), GFP_KERNEL); > + if (!*dev) > + return -ENOMEM; > + > + device_initialize(*dev); > + (*dev)->devt = MKDEV(hdev->major, minor); > + (*dev)->class = hclass; > + (*dev)->release = device_release_func; > + dev_set_drvdata(*dev, hdev); > + dev_set_name(*dev, "%s", name); > + > + return 0; > +} > + > +static int device_cdev_sysfs_add(struct hl_device *hdev) > +{ > + int rc; > + > + rc = cdev_device_add(&hdev->cdev, hdev->dev); > + if (rc) { > + dev_err(hdev->dev, > + "failed to add a char device to the system\n"); > + return rc; > } > > - *dev = device_create(hclass, NULL, devno, NULL, "%s", name); > - if (IS_ERR(*dev)) { > - pr_err("Failed to create device %s\n", name); > - err = PTR_ERR(*dev); > - goto err_device_create; > + rc = cdev_device_add(&hdev->cdev_ctrl, hdev->dev_ctrl); > + if (rc) { > + dev_err(hdev->dev, > + "failed to add a control char device to the system\n"); > + goto delete_cdev_device; > } > > - dev_set_drvdata(*dev, hdev); > + /* hl_sysfs_init() must be done after adding the device to the system */ > + rc = hl_sysfs_init(hdev); > + if (rc) { > + dev_err(hdev->dev, "failed to initialize sysfs\n"); > + goto delete_ctrl_cdev_device; > + } > + > + hdev->cdev_sysfs_created = true; > > return 0; > > -err_device_create: > - cdev_del(cdev); > - return err; > +delete_ctrl_cdev_device: > + cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl); > +delete_cdev_device: > + cdev_device_del(&hdev->cdev, hdev->dev); > + return rc; > +} > + > +static void device_cdev_sysfs_del(struct hl_device *hdev) > +{ > + /* device_release() won't be called so must free devices explicitly */ > + if (!hdev->cdev_sysfs_created) { > + kfree(hdev->dev_ctrl); > + kfree(hdev->dev); > + return; > + } > + > + hl_sysfs_fini(hdev); > + cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl); > + cdev_device_del(&hdev->cdev, hdev->dev); > } > > /* > @@ -898,13 +942,16 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > { > int i, rc, cq_ready_cnt; > char *name; > + bool add_cdev_sysfs_on_err = false; > > name = kasprintf(GFP_KERNEL, "hl%d", hdev->id / 2); > - if (!name) > - return -ENOMEM; > + if (!name) { > + rc = -ENOMEM; > + goto out_disabled; > + } > > - /* Create device */ > - rc = device_setup_cdev(hdev, hclass, hdev->id, &hl_ops, name, > + /* Initialize cdev and device structures */ > + rc = device_init_cdev(hdev, hclass, hdev->id, &hl_ops, name, > &hdev->cdev, &hdev->dev); > > kfree(name); > @@ -915,22 +962,22 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->id / 2); > if (!name) { > rc = -ENOMEM; > - goto release_device; > + goto free_dev; > } > > - /* Create control device */ > - rc = device_setup_cdev(hdev, hclass, hdev->id_control, &hl_ctrl_ops, > + /* Initialize cdev and device structures for control device */ > + rc = device_init_cdev(hdev, hclass, hdev->id_control, &hl_ctrl_ops, > name, &hdev->cdev_ctrl, &hdev->dev_ctrl); > > kfree(name); > > if (rc) > - goto release_device; > + goto free_dev; > > /* Initialize ASIC function pointers and perform early init */ > rc = device_early_init(hdev); > if (rc) > - goto release_control_device; > + goto free_dev_ctrl; > > /* > * Start calling ASIC initialization. First S/W then H/W and finally > @@ -1016,12 +1063,6 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > goto release_ctx; > } > > - rc = hl_sysfs_init(hdev); > - if (rc) { > - dev_err(hdev->dev, "failed to initialize sysfs\n"); > - goto free_cb_pool; > - } > - > hl_debugfs_add_device(hdev); > > if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) { > @@ -1030,6 +1071,12 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > hdev->asic_funcs->hw_fini(hdev, true); > } > > + /* > + * From this point, in case of an error, add char devices and create > + * sysfs nodes as part of the error flow, to allow debugging. > + */ > + add_cdev_sysfs_on_err = true; > + > rc = hdev->asic_funcs->hw_init(hdev); > if (rc) { > dev_err(hdev->dev, "failed to initialize the H/W\n"); > @@ -1066,9 +1113,24 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > } > > /* > - * hl_hwmon_init must be called after device_late_init, because only > + * Expose devices and sysfs nodes to user. > + * From here there is no need to add char devices and create sysfs nodes > + * in case of an error. > + */ > + add_cdev_sysfs_on_err = false; > + rc = device_cdev_sysfs_add(hdev); > + if (rc) { > + dev_err(hdev->dev, > + "Failed to add char devices and sysfs nodes\n"); > + rc = 0; > + goto out_disabled; > + } > + > + /* > + * hl_hwmon_init() must be called after device_late_init(), because only > * there we get the information from the device about which > - * hwmon-related sensors the device supports > + * hwmon-related sensors the device supports. > + * Furthermore, it must be done after adding the device to the system. > */ > rc = hl_hwmon_init(hdev); > if (rc) { > @@ -1084,8 +1146,6 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > > return 0; > > -free_cb_pool: > - hl_cb_pool_fini(hdev); > release_ctx: > if (hl_ctx_put(hdev->kernel_ctx) != 1) > dev_err(hdev->dev, > @@ -1106,14 +1166,14 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) > hdev->asic_funcs->sw_fini(hdev); > early_fini: > device_early_fini(hdev); > -release_control_device: > - device_destroy(hclass, hdev->dev_ctrl->devt); > - cdev_del(&hdev->cdev_ctrl); > -release_device: > - device_destroy(hclass, hdev->dev->devt); > - cdev_del(&hdev->cdev); > +free_dev_ctrl: > + kfree(hdev->dev_ctrl); > +free_dev: > + kfree(hdev->dev); > out_disabled: > hdev->disabled = true; > + if (add_cdev_sysfs_on_err) > + device_cdev_sysfs_add(hdev); > if (hdev->pdev) > dev_err(&hdev->pdev->dev, > "Failed to initialize hl%d. Device is NOT usable !\n", > @@ -1179,8 +1239,6 @@ void hl_device_fini(struct hl_device *hdev) > > hl_debugfs_remove_device(hdev); > > - hl_sysfs_fini(hdev); > - > /* > * Halt the engines and disable interrupts so we won't get any more > * completions from H/W and we won't have any accesses from the > @@ -1223,11 +1281,8 @@ void hl_device_fini(struct hl_device *hdev) > > device_early_fini(hdev); > > - /* Hide device from user */ > - device_destroy(hdev->dev_ctrl->class, hdev->dev_ctrl->devt); > - cdev_del(&hdev->cdev_ctrl); > - device_destroy(hdev->dev->class, hdev->dev->devt); > - cdev_del(&hdev->cdev); > + /* Hide devices and sysfs nodes from user */ > + device_cdev_sysfs_del(hdev); > > pr_info("removed device successfully\n"); > } > diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h > index aaaa29d98901..1bb181285589 100644 > --- a/drivers/misc/habanalabs/habanalabs.h > +++ b/drivers/misc/habanalabs/habanalabs.h > @@ -1216,6 +1216,7 @@ struct hl_device_reset_work { > * @dma_mask: the dma mask that was set for this device > * @in_debug: is device under debug. This, together with fpriv_list, enforces > * that only a single user is configuring the debug infrastructure. > + * @cdev_sysfs_created: were char devices and sysfs nodes created. > */ > struct hl_device { > struct pci_dev *pdev; > @@ -1291,6 +1292,7 @@ struct hl_device { > u8 device_cpu_disabled; > u8 dma_mask; > u8 in_debug; > + u8 cdev_sysfs_created; > > /* Parameters for bring-up */ > u8 mmu_enable; > -- > 2.17.1 > This patch is: Reviewed-by: Oded Gabbay