summaryrefslogtreecommitdiff
path: root/drivers/dibs/dibs_main.c
diff options
context:
space:
mode:
authorAlexandra Winter <wintera@linux.ibm.com>2025-09-18 13:04:59 +0200
committerPaolo Abeni <pabeni@redhat.com>2025-09-23 11:13:22 +0200
commitcc21191b584c6f7836b0f10774f8278b7cbfba10 (patch)
treed32f1f225389ec6fb6368d637db3a32e79a1e736 /drivers/dibs/dibs_main.c
parent719c3b67bb7ea95bb8158b03c75641c8fc8f94a0 (diff)
dibs: Move data path to dibs layer
Use struct dibs_dmb instead of struct smc_dmb and move the corresponding client tables to dibs_dev. Leave driver specific implementation details like sba in the device drivers. Register and unregister dmbs via dibs_dev_ops. A dmb is dedicated to a single client, but a dibs device can have dmbs for more than one client. Trigger dibs clients via dibs_client_ops->handle_irq(), when data is received into a dmb. For dibs_loopback replace scheduling an smcd receive tasklet with calling dibs_client_ops->handle_irq(). For loopback devices attach_dmb(), detach_dmb() and move_data() need to access the dmb tables, so move those to dibs_dev_ops in this patch as well. Remove remaining definitions of smc_loopback as they are no longer required, now that everything is in dibs_loopback. Note that struct ism_client and struct ism_dev are still required in smc until a follow-on patch moves event handling to dibs. (Loopback does not use events). Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> Link: https://patch.msgid.link/20250918110500.1731261-14-wintera@linux.ibm.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/dibs/dibs_main.c')
-rw-r--r--drivers/dibs/dibs_main.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/dibs/dibs_main.c b/drivers/dibs/dibs_main.c
index f20ed0594a51..aacb3ea7825a 100644
--- a/drivers/dibs/dibs_main.c
+++ b/drivers/dibs/dibs_main.c
@@ -36,6 +36,16 @@ static struct dibs_dev_list dibs_dev_list = {
.mutex = __MUTEX_INITIALIZER(dibs_dev_list.mutex),
};
+static void dibs_setup_forwarding(struct dibs_client *client,
+ struct dibs_dev *dibs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dibs->lock, flags);
+ dibs->subs[client->id] = client;
+ spin_unlock_irqrestore(&dibs->lock, flags);
+}
+
int dibs_register_client(struct dibs_client *client)
{
struct dibs_dev *dibs;
@@ -60,6 +70,7 @@ int dibs_register_client(struct dibs_client *client)
list_for_each_entry(dibs, &dibs_dev_list.list, list) {
dibs->priv[i] = NULL;
client->ops->add_dev(dibs);
+ dibs_setup_forwarding(client, dibs);
}
}
mutex_unlock(&dibs_dev_list.mutex);
@@ -71,10 +82,25 @@ EXPORT_SYMBOL_GPL(dibs_register_client);
int dibs_unregister_client(struct dibs_client *client)
{
struct dibs_dev *dibs;
+ unsigned long flags;
+ int max_dmbs;
int rc = 0;
mutex_lock(&dibs_dev_list.mutex);
list_for_each_entry(dibs, &dibs_dev_list.list, list) {
+ spin_lock_irqsave(&dibs->lock, flags);
+ max_dmbs = dibs->ops->max_dmbs();
+ for (int i = 0; i < max_dmbs; ++i) {
+ if (dibs->dmb_clientid_arr[i] == client->id) {
+ WARN(1, "%s: attempt to unregister '%s' with registered dmb(s)\n",
+ __func__, client->name);
+ rc = -EBUSY;
+ goto err_reg_dmb;
+ }
+ }
+ /* Stop forwarding IRQs */
+ dibs->subs[client->id] = NULL;
+ spin_unlock_irqrestore(&dibs->lock, flags);
clients[client->id]->ops->del_dev(dibs);
dibs->priv[client->id] = NULL;
}
@@ -87,6 +113,11 @@ int dibs_unregister_client(struct dibs_client *client)
mutex_unlock(&dibs_dev_list.mutex);
return rc;
+
+err_reg_dmb:
+ spin_unlock_irqrestore(&dibs->lock, flags);
+ mutex_unlock(&dibs_dev_list.mutex);
+ return rc;
}
EXPORT_SYMBOL_GPL(dibs_unregister_client);
@@ -150,11 +181,19 @@ static const struct attribute_group dibs_dev_attr_group = {
int dibs_dev_add(struct dibs_dev *dibs)
{
+ int max_dmbs;
int i, ret;
+ max_dmbs = dibs->ops->max_dmbs();
+ spin_lock_init(&dibs->lock);
+ dibs->dmb_clientid_arr = kzalloc(max_dmbs, GFP_KERNEL);
+ if (!dibs->dmb_clientid_arr)
+ return -ENOMEM;
+ memset(dibs->dmb_clientid_arr, NO_DIBS_CLIENT, max_dmbs);
+
ret = device_add(&dibs->dev);
if (ret)
- return ret;
+ goto free_client_arr;
ret = sysfs_create_group(&dibs->dev.kobj, &dibs_dev_attr_group);
if (ret) {
@@ -164,8 +203,10 @@ int dibs_dev_add(struct dibs_dev *dibs)
mutex_lock(&dibs_dev_list.mutex);
mutex_lock(&clients_lock);
for (i = 0; i < max_client; ++i) {
- if (clients[i])
+ if (clients[i]) {
clients[i]->ops->add_dev(dibs);
+ dibs_setup_forwarding(clients[i], dibs);
+ }
}
mutex_unlock(&clients_lock);
list_add(&dibs->list, &dibs_dev_list.list);
@@ -175,6 +216,8 @@ int dibs_dev_add(struct dibs_dev *dibs)
err_device_del:
device_del(&dibs->dev);
+free_client_arr:
+ kfree(dibs->dmb_clientid_arr);
return ret;
}
@@ -182,8 +225,16 @@ EXPORT_SYMBOL_GPL(dibs_dev_add);
void dibs_dev_del(struct dibs_dev *dibs)
{
+ unsigned long flags;
int i;
+ sysfs_remove_group(&dibs->dev.kobj, &dibs_dev_attr_group);
+
+ spin_lock_irqsave(&dibs->lock, flags);
+ for (i = 0; i < MAX_DIBS_CLIENTS; ++i)
+ dibs->subs[i] = NULL;
+ spin_unlock_irqrestore(&dibs->lock, flags);
+
mutex_lock(&dibs_dev_list.mutex);
mutex_lock(&clients_lock);
for (i = 0; i < max_client; ++i) {
@@ -195,6 +246,7 @@ void dibs_dev_del(struct dibs_dev *dibs)
mutex_unlock(&dibs_dev_list.mutex);
device_del(&dibs->dev);
+ kfree(dibs->dmb_clientid_arr);
}
EXPORT_SYMBOL_GPL(dibs_dev_del);