Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp3403093pxk; Mon, 28 Sep 2020 17:15:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxpT51VZToabpvJpCipULWzSVYbE0awrxWu0tYnV3o48YKJu4cXz8Jo/X1Nj33cQoRzRg1C X-Received: by 2002:a17:906:82c1:: with SMTP id a1mr1261053ejy.270.1601338506172; Mon, 28 Sep 2020 17:15:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1601338506; cv=none; d=google.com; s=arc-20160816; b=gxQN/+P7OUj4t6D/hGhl5boaiciV8ArEyPohuUDAHkWCu9hwhSb2humifSmdqSw0Gj LXV2eovbpNKyE7Mevj3f7nm2fFk3QROefxJDvs8QGqCybHlRLEDpILid8bHsYn60/7ka DVOkAbHuxGQD15gU+W4Cw2oUlSFGkA9g/mWR1N8P/H7ohHDJCnJQQTRZpBmKMx1Ow1P6 KLlPkksX996M+golFx7LMUO3Ax/QnpDcG3bJQEgxjh3kDlNXsIQvNC/xIu79k/G6MH6q Cxc65/A7TOzZrpcXAB0D2ef3RGEsyU5r07n5GKHZgUMAF3m+3rLRFk92LpKeacSLxpXq W6hw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=nAlVsYeNqwn4BqRONXdvKvIvQ+/mvh/lMdzrxFVVa3s=; b=WFaKdWGlii81IYjO+Ew+gxXb6Vks9Q5NTAEpmDSWymxMrllV1EZXFQkjXifUvjE8Vo /eMVwbJH+Vphc470/PotkM9MR4Hyw+0kQE/rueVXXVlinPDt2JbfsvU3PGnwqc+gJ9VJ u8BpJGMNAszG1Zg4WCy4SuXsiOJkClg/R1+X23NPoYRUujwgWloNG309RlvBGs1WzkRe hDYODyodBTI1gSC4dKQDV8nsLrc4Huaf306bfCtUom/xek928L0k10S5J9ojXW6IbG8l Zc+AfIHUFvkq3UElklB1NO5B1ITZT8Ua/IUE+dh2H8pRk1URSfXnny9cEv5ecN4Gcfzp uTDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b=FDWjslW6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cf25si1725811ejb.67.2020.09.28.17.14.40; Mon, 28 Sep 2020 17:15:06 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b=FDWjslW6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727234AbgI2ANF (ORCPT + 99 others); Mon, 28 Sep 2020 20:13:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727077AbgI2AM7 (ORCPT ); Mon, 28 Sep 2020 20:12:59 -0400 Received: from mail-pj1-x1063.google.com (mail-pj1-x1063.google.com [IPv6:2607:f8b0:4864:20::1063]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B9BB3C0613D3 for ; Mon, 28 Sep 2020 17:12:59 -0700 (PDT) Received: by mail-pj1-x1063.google.com with SMTP id md22so2916392pjb.0 for ; Mon, 28 Sep 2020 17:12:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nAlVsYeNqwn4BqRONXdvKvIvQ+/mvh/lMdzrxFVVa3s=; b=FDWjslW66xA1bflf+j2+zlCJjdxP40PVbFcv+SjDOcfOALqUIDpFTadpdATJ5mCSCd Fuz0EXlpO16r8M7CmFSXYci65t3fD6f5oE1VdZZ8w52vlTMMHpoQKSnT/c4pOUo2J+xm BTQnmeUw/w9l40cWcy+o59Kf8xQWsDFMfztBs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nAlVsYeNqwn4BqRONXdvKvIvQ+/mvh/lMdzrxFVVa3s=; b=tt6Qx35kRNxZtkMcN9KZtg1LpelbRINRJsnYLpq7urp/QTZWjm+TDC8E0n6UoyjZp3 WVlu8Qdm4HQwgUDhO0W49+oWjnkpLGRQlX2I6OIR9hMuLuJ7Ylqi1Usij4pysjrANH/r A+1g78Iv2BuiBbxmS8yxTd1/OCIwM7eMDDL8WuGQCy5IlLimFe0Jtypoxd4LZt1V3PZv deKfqQchsbzhCCwdPY5itbIXpPSz2Rn2PS2TX3KwXo/rW4wpe5XOWB2yyU0jxpOqD0hr a6RhF+vCwA/MID6nPv8G5NDUC6kVzR0VUbCMMdyeWp+UsB8fe3xSzUeFlpusa4SeZTHP G+3w== X-Gm-Message-State: AOAM531vzdWJ9h/AIscBed8UiIqggSMLbpUKL9rrcSiZr/fgkESzTDfM jIYtzoblKXhqN7t0cjjgfhEdw8Tj02Z4M2Zt4sTrEHLqn+xl X-Received: by 2002:a17:902:7089:b029:d2:aa9a:beb7 with SMTP id z9-20020a1709027089b02900d2aa9abeb7mr90827plk.76.1601338379018; Mon, 28 Sep 2020 17:12:59 -0700 (PDT) Received: from lbrmn-lnxub113.broadcom.net ([192.19.228.250]) by smtp-relay.gmail.com with ESMTPS id t1sm1047973pjr.8.2020.09.28.17.12.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Sep 2020 17:12:58 -0700 (PDT) X-Relaying-Domain: broadcom.com From: Scott Branden To: Arnd Bergmann , Greg Kroah-Hartman , Scott Branden Cc: Kees Cook , linux-kernel@vger.kernel.org, bcm-kernel-feedback-list@broadcom.com, Desmond Yan Subject: [PATCH v4 07/16] misc: bcm-vk: add open/release Date: Mon, 28 Sep 2020 17:12:00 -0700 Message-Id: <20200929001209.16393-8-scott.branden@broadcom.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200929001209.16393-1-scott.branden@broadcom.com> References: <20200929001209.16393-1-scott.branden@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add open/release to replace private data with context for other methods to use. Reason for the context is because it is allowed for multiple sessions to open sysfs. For each file open, when upper layer queries the response, only those that are tied to a specified open should be returned. Co-developed-by: Desmond Yan Signed-off-by: Desmond Yan Signed-off-by: Scott Branden --- drivers/misc/bcm-vk/Makefile | 1 + drivers/misc/bcm-vk/bcm_vk.h | 14 ++++ drivers/misc/bcm-vk/bcm_vk_dev.c | 23 ++++++ drivers/misc/bcm-vk/bcm_vk_msg.c | 126 +++++++++++++++++++++++++++++++ drivers/misc/bcm-vk/bcm_vk_msg.h | 31 ++++++++ 5 files changed, 195 insertions(+) create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.h diff --git a/drivers/misc/bcm-vk/Makefile b/drivers/misc/bcm-vk/Makefile index e50aa3ca31e9..a2d1577663ec 100644 --- a/drivers/misc/bcm-vk/Makefile +++ b/drivers/misc/bcm-vk/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_BCM_VK) += bcm_vk.o bcm_vk-objs := \ bcm_vk_dev.o \ + bcm_vk_msg.o \ bcm_vk_tty.o diff --git a/drivers/misc/bcm-vk/bcm_vk.h b/drivers/misc/bcm-vk/bcm_vk.h index b1408daa7261..346508daa67f 100644 --- a/drivers/misc/bcm-vk/bcm_vk.h +++ b/drivers/misc/bcm-vk/bcm_vk.h @@ -7,12 +7,16 @@ #define BCM_VK_H #include +#include #include +#include #include #include #include #include +#include "bcm_vk_msg.h" + #define DRV_MODULE_NAME "bcm-vk" /* @@ -242,6 +246,13 @@ struct bcm_vk { struct workqueue_struct *tty_wq_thread; struct work_struct tty_wq_work; + /* Reference-counting to handle file operations */ + struct kref kref; + + spinlock_t ctx_lock; /* Spinlock for component context */ + struct bcm_vk_ctx ctx[VK_CMPT_CTX_MAX]; + struct bcm_vk_ht_entry pid_ht[VK_PID_HT_SZ]; + struct workqueue_struct *wq_thread; struct work_struct wq_work; /* work queue for deferred job */ unsigned long wq_offload[1]; /* various flags on wq requested */ @@ -302,6 +313,9 @@ static inline bool bcm_vk_msgq_marker_valid(struct bcm_vk *vk) return (rdy_marker == VK_BAR1_MSGQ_RDY_MARKER); } +int bcm_vk_open(struct inode *inode, struct file *p_file); +int bcm_vk_release(struct inode *inode, struct file *p_file); +void bcm_vk_release_data(struct kref *kref); int bcm_vk_auto_load_all_images(struct bcm_vk *vk); int bcm_vk_tty_init(struct bcm_vk *vk, char *name); void bcm_vk_tty_exit(struct bcm_vk *vk); diff --git a/drivers/misc/bcm-vk/bcm_vk_dev.c b/drivers/misc/bcm-vk/bcm_vk_dev.c index dfef9546c5a7..b9f095a7905b 100644 --- a/drivers/misc/bcm-vk/bcm_vk_dev.c +++ b/drivers/misc/bcm-vk/bcm_vk_dev.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -630,6 +631,12 @@ static int bcm_vk_trigger_reset(struct bcm_vk *vk) return 0; } +static const struct file_operations bcm_vk_fops = { + .owner = THIS_MODULE, + .open = bcm_vk_open, + .release = bcm_vk_release, +}; + static int bcm_vk_on_panic(struct notifier_block *nb, unsigned long e, void *p) { @@ -652,10 +659,13 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct miscdevice *misc_device; u32 boot_status; + /* allocate vk structure which is tied to kref for freeing */ vk = kzalloc(sizeof(*vk), GFP_KERNEL); if (!vk) return -ENOMEM; + kref_init(&vk->kref); + err = pci_enable_device(pdev); if (err) { dev_err(dev, "Cannot enable PCI device\n"); @@ -732,6 +742,7 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENOMEM; goto err_ida_remove; } + misc_device->fops = &bcm_vk_fops, err = misc_register(misc_device); if (err) { @@ -825,6 +836,16 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } +void bcm_vk_release_data(struct kref *kref) +{ + struct bcm_vk *vk = container_of(kref, struct bcm_vk, kref); + struct pci_dev *pdev = vk->pdev; + + dev_dbg(&pdev->dev, "BCM-VK:%d release data 0x%p\n", vk->devid, vk); + pci_dev_put(pdev); + kfree(vk); +} + static void bcm_vk_remove(struct pci_dev *pdev) { int i; @@ -872,6 +893,8 @@ static void bcm_vk_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_free_irq_vectors(pdev); pci_disable_device(pdev); + + kref_put(&vk->kref, bcm_vk_release_data); } static void bcm_vk_shutdown(struct pci_dev *pdev) diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.c b/drivers/misc/bcm-vk/bcm_vk_msg.c new file mode 100644 index 000000000000..eb261fb87c9d --- /dev/null +++ b/drivers/misc/bcm-vk/bcm_vk_msg.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018-2020 Broadcom. + */ + +#include "bcm_vk.h" +#include "bcm_vk_msg.h" + +/* + * allocate a ctx per file struct + */ +static struct bcm_vk_ctx *bcm_vk_get_ctx(struct bcm_vk *vk, const pid_t pid) +{ + u32 i; + struct bcm_vk_ctx *ctx = NULL; + u32 hash_idx = hash_32(pid, VK_PID_HT_SHIFT_BIT); + + spin_lock(&vk->ctx_lock); + + for (i = 0; i < ARRAY_SIZE(vk->ctx); i++) { + if (!vk->ctx[i].in_use) { + vk->ctx[i].in_use = true; + ctx = &vk->ctx[i]; + break; + } + } + + if (!ctx) { + dev_err(&vk->pdev->dev, "All context in use\n"); + + goto all_in_use_exit; + } + + /* set the pid and insert it to hash table */ + ctx->pid = pid; + ctx->hash_idx = hash_idx; + list_add_tail(&ctx->node, &vk->pid_ht[hash_idx].head); + + /* increase kref */ + kref_get(&vk->kref); + +all_in_use_exit: + spin_unlock(&vk->ctx_lock); + + return ctx; +} + +static int bcm_vk_free_ctx(struct bcm_vk *vk, struct bcm_vk_ctx *ctx) +{ + u32 idx; + u32 hash_idx; + pid_t pid; + struct bcm_vk_ctx *entry; + int count = 0; + + if (!ctx) { + dev_err(&vk->pdev->dev, "NULL context detected\n"); + return -EINVAL; + } + idx = ctx->idx; + pid = ctx->pid; + + spin_lock(&vk->ctx_lock); + + if (!vk->ctx[idx].in_use) { + dev_err(&vk->pdev->dev, "context[%d] not in use!\n", idx); + } else { + vk->ctx[idx].in_use = false; + vk->ctx[idx].miscdev = NULL; + + /* Remove it from hash list and see if it is the last one. */ + list_del(&ctx->node); + hash_idx = ctx->hash_idx; + list_for_each_entry(entry, &vk->pid_ht[hash_idx].head, node) { + if (entry->pid == pid) + count++; + } + } + + spin_unlock(&vk->ctx_lock); + + return count; +} +int bcm_vk_open(struct inode *inode, struct file *p_file) +{ + struct bcm_vk_ctx *ctx; + struct miscdevice *miscdev = (struct miscdevice *)p_file->private_data; + struct bcm_vk *vk = container_of(miscdev, struct bcm_vk, miscdev); + struct device *dev = &vk->pdev->dev; + int rc = 0; + + /* get a context and set it up for file */ + ctx = bcm_vk_get_ctx(vk, task_pid_nr(current)); + if (!ctx) { + dev_err(dev, "Error allocating context\n"); + rc = -ENOMEM; + } else { + /* + * set up context and replace private data with context for + * other methods to use. Reason for the context is because + * it is allowed for multiple sessions to open the sysfs, and + * for each file open, when upper layer query the response, + * only those that are tied to a specific open should be + * returned. The context->idx will be used for such binding + */ + ctx->miscdev = miscdev; + p_file->private_data = ctx; + dev_dbg(dev, "ctx_returned with idx %d, pid %d\n", + ctx->idx, ctx->pid); + } + return rc; +} + +int bcm_vk_release(struct inode *inode, struct file *p_file) +{ + int ret; + struct bcm_vk_ctx *ctx = p_file->private_data; + struct bcm_vk *vk = container_of(ctx->miscdev, struct bcm_vk, miscdev); + + ret = bcm_vk_free_ctx(vk, ctx); + + kref_put(&vk->kref, bcm_vk_release_data); + + return ret; +} + diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.h b/drivers/misc/bcm-vk/bcm_vk_msg.h new file mode 100644 index 000000000000..32516abcaf89 --- /dev/null +++ b/drivers/misc/bcm-vk/bcm_vk_msg.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2018-2020 Broadcom. + */ + +#ifndef BCM_VK_MSG_H +#define BCM_VK_MSG_H + +/* context per session opening of sysfs */ +struct bcm_vk_ctx { + struct list_head node; /* use for linkage in Hash Table */ + unsigned int idx; + bool in_use; + pid_t pid; + u32 hash_idx; + struct miscdevice *miscdev; +}; + +/* pid hash table entry */ +struct bcm_vk_ht_entry { + struct list_head head; +}; + +/* total number of supported ctx, 32 ctx each for 5 components */ +#define VK_CMPT_CTX_MAX (32 * 5) + +/* hash table defines to store the opened FDs */ +#define VK_PID_HT_SHIFT_BIT 7 /* 128 */ +#define VK_PID_HT_SZ BIT(VK_PID_HT_SHIFT_BIT) + +#endif -- 2.17.1