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/firmware/arm_scmi/bus.c | 101 ++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 80 insertions(+), 21 deletions(-)
diff --git a/kernel/drivers/firmware/arm_scmi/bus.c b/kernel/drivers/firmware/arm_scmi/bus.c
index 33d1a6c..10234e0 100644
--- a/kernel/drivers/firmware/arm_scmi/bus.c
+++ b/kernel/drivers/firmware/arm_scmi/bus.c
@@ -16,7 +16,7 @@
#include "common.h"
static DEFINE_IDA(scmi_bus_id);
-static DEFINE_IDR(scmi_protocols);
+static DEFINE_IDR(scmi_available_protocols);
static DEFINE_SPINLOCK(protocol_lock);
static const struct scmi_device_id *
@@ -51,13 +51,53 @@
return 0;
}
-static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle)
+static int scmi_match_by_id_table(struct device *dev, void *data)
{
- scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id);
+ struct scmi_device *sdev = to_scmi_dev(dev);
+ struct scmi_device_id *id_table = data;
- if (unlikely(!fn))
- return -EINVAL;
- return fn(handle);
+ return sdev->protocol_id == id_table->protocol_id &&
+ !strcmp(sdev->name, id_table->name);
+}
+
+struct scmi_device *scmi_find_child_dev(struct device *parent,
+ int prot_id, const char *name)
+{
+ struct scmi_device_id id_table;
+ struct device *dev;
+
+ id_table.protocol_id = prot_id;
+ id_table.name = name;
+
+ dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
+ if (!dev)
+ return NULL;
+
+ return to_scmi_dev(dev);
+}
+
+const struct scmi_protocol *scmi_get_protocol(int protocol_id)
+{
+ const struct scmi_protocol *proto;
+
+ proto = idr_find(&scmi_available_protocols, protocol_id);
+ if (!proto || !try_module_get(proto->owner)) {
+ pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
+ return NULL;
+ }
+
+ pr_debug("GOT SCMI Protocol 0x%x\n", protocol_id);
+
+ return proto;
+}
+
+void scmi_put_protocol(int protocol_id)
+{
+ const struct scmi_protocol *proto;
+
+ proto = idr_find(&scmi_available_protocols, protocol_id);
+ if (proto)
+ module_put(proto->owner);
}
static int scmi_dev_probe(struct device *dev)
@@ -65,7 +105,6 @@
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
struct scmi_device *scmi_dev = to_scmi_dev(dev);
const struct scmi_device_id *id;
- int ret;
id = scmi_dev_match_id(scmi_dev, scmi_drv);
if (!id)
@@ -73,10 +112,6 @@
if (!scmi_dev->handle)
return -EPROBE_DEFER;
-
- ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
- if (ret)
- return ret;
return scmi_drv->probe(scmi_dev);
}
@@ -107,6 +142,10 @@
if (!driver->probe)
return -EINVAL;
+ retval = scmi_request_protocol_device(driver->id_table);
+ if (retval)
+ return retval;
+
driver->driver.bus = &scmi_bus_type;
driver->driver.name = driver->name;
driver->driver.owner = owner;
@@ -123,6 +162,7 @@
void scmi_driver_unregister(struct scmi_driver *driver)
{
driver_unregister(&driver->driver);
+ scmi_unrequest_protocol_device(driver->id_table);
}
EXPORT_SYMBOL_GPL(scmi_driver_unregister);
@@ -188,26 +228,45 @@
scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
}
-int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
+int scmi_protocol_register(const struct scmi_protocol *proto)
{
int ret;
- spin_lock(&protocol_lock);
- ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
- GFP_ATOMIC);
- spin_unlock(&protocol_lock);
- if (ret != protocol_id)
- pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
+ if (!proto) {
+ pr_err("invalid protocol\n");
+ return -EINVAL;
+ }
- return ret;
+ if (!proto->init_instance) {
+ pr_err("missing .init() for protocol 0x%x\n", proto->id);
+ return -EINVAL;
+ }
+
+ spin_lock(&protocol_lock);
+ ret = idr_alloc(&scmi_available_protocols, (void *)proto,
+ proto->id, proto->id + 1, GFP_ATOMIC);
+ spin_unlock(&protocol_lock);
+ if (ret != proto->id) {
+ pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n",
+ proto->id, ret);
+ return ret;
+ }
+
+ pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(scmi_protocol_register);
-void scmi_protocol_unregister(int protocol_id)
+void scmi_protocol_unregister(const struct scmi_protocol *proto)
{
spin_lock(&protocol_lock);
- idr_remove(&scmi_protocols, protocol_id);
+ idr_remove(&scmi_available_protocols, proto->id);
spin_unlock(&protocol_lock);
+
+ pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id);
+
+ return;
}
EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
--
Gitblit v1.6.2