From 95099d4622f8cb224d94e314c7a8e0df60b13f87 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 08:38:01 +0000
Subject: [PATCH] enable docker ppp
---
kernel/drivers/uio/uio_pdrv_genirq.c | 80 +++++++++++++++++++++++++--------------
1 files changed, 51 insertions(+), 29 deletions(-)
diff --git a/kernel/drivers/uio/uio_pdrv_genirq.c b/kernel/drivers/uio/uio_pdrv_genirq.c
index b58a504..63258b6 100644
--- a/kernel/drivers/uio/uio_pdrv_genirq.c
+++ b/kernel/drivers/uio/uio_pdrv_genirq.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/uio/uio_pdrv_genirq.c
*
@@ -8,10 +9,6 @@
* Based on uio_pdrv.c by Uwe Kleine-Koenig,
* Copyright (C) 2008 by Digi International Inc.
* All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
*/
#include <linux/platform_device.h>
@@ -23,6 +20,7 @@
#include <linux/stringify.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -102,15 +100,25 @@
return 0;
}
+static void uio_pdrv_genirq_cleanup(void *data)
+{
+ struct device *dev = data;
+
+ pm_runtime_disable(dev);
+}
+
static int uio_pdrv_genirq_probe(struct platform_device *pdev)
{
struct uio_info *uioinfo = dev_get_platdata(&pdev->dev);
+ struct device_node *node = pdev->dev.of_node;
struct uio_pdrv_genirq_platdata *priv;
struct uio_mem *uiomem;
int ret = -EINVAL;
int i;
- if (pdev->dev.of_node) {
+ if (node) {
+ const char *name;
+
/* alloc uioinfo for one device */
uioinfo = devm_kzalloc(&pdev->dev, sizeof(*uioinfo),
GFP_KERNEL);
@@ -118,7 +126,13 @@
dev_err(&pdev->dev, "unable to kmalloc\n");
return -ENOMEM;
}
- uioinfo->name = pdev->dev.of_node->name;
+
+ if (!of_property_read_string(node, "linux,uio-name", &name))
+ uioinfo->name = devm_kstrdup(&pdev->dev, name, GFP_KERNEL);
+ else
+ uioinfo->name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "%pOFn", node);
+
uioinfo->version = "devicetree";
/* Multiple IRQs are not supported */
}
@@ -146,13 +160,32 @@
priv->pdev = pdev;
if (!uioinfo->irq) {
- ret = platform_get_irq(pdev, 0);
+ ret = platform_get_irq_optional(pdev, 0);
uioinfo->irq = ret;
if (ret == -ENXIO)
uioinfo->irq = UIO_IRQ_NONE;
+ else if (ret == -EPROBE_DEFER)
+ return ret;
else if (ret < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n");
return ret;
+ }
+ }
+
+ if (uioinfo->irq) {
+ struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq);
+
+ /*
+ * If a level interrupt, dont do lazy disable. Otherwise the
+ * irq will fire again since clearing of the actual cause, on
+ * device level, is done in userspace
+ * irqd_is_level_type() isn't used since isn't valid until
+ * irq is configured.
+ */
+ if (irq_data &&
+ irqd_get_trigger_type(irq_data) & IRQ_TYPE_LEVEL_MASK) {
+ dev_dbg(&pdev->dev, "disable lazy unmask\n");
+ irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY);
}
}
@@ -172,8 +205,10 @@
}
uiomem->memtype = UIO_MEM_PHYS;
- uiomem->addr = r->start;
- uiomem->size = resource_size(r);
+ uiomem->addr = r->start & PAGE_MASK;
+ uiomem->offs = r->start & ~PAGE_MASK;
+ uiomem->size = (uiomem->offs + resource_size(r)
+ + PAGE_SIZE - 1) & PAGE_MASK;
uiomem->name = r->name;
++uiomem;
}
@@ -205,28 +240,16 @@
*/
pm_runtime_enable(&pdev->dev);
- ret = uio_register_device(&pdev->dev, priv->uioinfo);
- if (ret) {
- dev_err(&pdev->dev, "unable to register uio device\n");
- pm_runtime_disable(&pdev->dev);
+ ret = devm_add_action_or_reset(&pdev->dev, uio_pdrv_genirq_cleanup,
+ &pdev->dev);
+ if (ret)
return ret;
- }
- platform_set_drvdata(pdev, priv);
- return 0;
-}
+ ret = devm_uio_register_device(&pdev->dev, priv->uioinfo);
+ if (ret)
+ dev_err(&pdev->dev, "unable to register uio device\n");
-static int uio_pdrv_genirq_remove(struct platform_device *pdev)
-{
- struct uio_pdrv_genirq_platdata *priv = platform_get_drvdata(pdev);
-
- uio_unregister_device(priv->uioinfo);
- pm_runtime_disable(&pdev->dev);
-
- priv->uioinfo->handler = NULL;
- priv->uioinfo->irqcontrol = NULL;
-
- return 0;
+ return ret;
}
static int uio_pdrv_genirq_runtime_nop(struct device *dev)
@@ -263,7 +286,6 @@
static struct platform_driver uio_pdrv_genirq = {
.probe = uio_pdrv_genirq_probe,
- .remove = uio_pdrv_genirq_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &uio_pdrv_genirq_dev_pm_ops,
--
Gitblit v1.6.2