]> www.infradead.org Git - users/hch/misc.git/commitdiff
dibs: Register ism as dibs device
authorAlexandra Winter <wintera@linux.ibm.com>
Thu, 18 Sep 2025 11:04:51 +0000 (13:04 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 23 Sep 2025 09:13:21 +0000 (11:13 +0200)
Register ism devices with the dibs layer. Follow-on patches will move
functionality to the dibs layer.

As DIBS is only a shim layer without any dependencies, we can depend ISM
on DIBS without adding indirect dependencies. A follow-on patch will
remove implication of SMC by ISM.

Define struct dibs_dev. Follow-on patches will move more content into
dibs_dev.  The goal of follow-on patches is that ism_dev will only
contain fields that are special for this device driver. The same concept
will apply to other dibs device drivers.

Define dibs_dev_alloc(), dibs_dev_add() and dibs_dev_del() to be called
by dibs device drivers and call them from ism_drv.c
Use ism_dev.dibs for a pointer to dibs_dev.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Link: https://patch.msgid.link/20250918110500.1731261-6-wintera@linux.ibm.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/dibs/dibs_main.c
drivers/s390/net/Kconfig
drivers/s390/net/ism.h
drivers/s390/net/ism_drv.c
include/linux/dibs.h
include/linux/ism.h

index a5d2be9c324674ddac2f26da8083e1df25b45350..2f420e077417ac25945d56b0709a378c4e14a6ea 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/dibs.h>
 
@@ -21,6 +22,15 @@ MODULE_LICENSE("GPL");
 static struct dibs_client *clients[MAX_DIBS_CLIENTS];
 static u8 max_client;
 static DEFINE_MUTEX(clients_lock);
+struct dibs_dev_list {
+       struct list_head list;
+       struct mutex mutex; /* protects dibs device list */
+};
+
+static struct dibs_dev_list dibs_dev_list = {
+       .list = LIST_HEAD_INIT(dibs_dev_list.list),
+       .mutex = __MUTEX_INITIALIZER(dibs_dev_list.mutex),
+};
 
 int dibs_register_client(struct dibs_client *client)
 {
@@ -56,6 +66,34 @@ int dibs_unregister_client(struct dibs_client *client)
 }
 EXPORT_SYMBOL_GPL(dibs_unregister_client);
 
+struct dibs_dev *dibs_dev_alloc(void)
+{
+       struct dibs_dev *dibs;
+
+       dibs = kzalloc(sizeof(*dibs), GFP_KERNEL);
+
+       return dibs;
+}
+EXPORT_SYMBOL_GPL(dibs_dev_alloc);
+
+int dibs_dev_add(struct dibs_dev *dibs)
+{
+       mutex_lock(&dibs_dev_list.mutex);
+       list_add(&dibs->list, &dibs_dev_list.list);
+       mutex_unlock(&dibs_dev_list.mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dibs_dev_add);
+
+void dibs_dev_del(struct dibs_dev *dibs)
+{
+       mutex_lock(&dibs_dev_list.mutex);
+       list_del_init(&dibs->list);
+       mutex_unlock(&dibs_dev_list.mutex);
+}
+EXPORT_SYMBOL_GPL(dibs_dev_del);
+
 static int __init dibs_init(void)
 {
        memset(clients, 0, sizeof(clients));
index 2b43f6f283622f41c910ec4e688acb1c27982942..92985f595d59bf19c729840e72d915c8479a2908 100644 (file)
@@ -81,7 +81,7 @@ config CCWGROUP
 
 config ISM
        tristate "Support for ISM vPCI Adapter"
-       depends on PCI
+       depends on PCI && DIBS
        imply SMC
        default n
        help
index b5b03db52fce44ac333a3365a08b171225c82d92..3078779fa71e359580068b1d61eb0253f76c75ea 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/dibs.h>
 #include <linux/ism.h>
 #include <net/smc.h>
 #include <asm/pci_insn.h>
index 6cd60b1743156f62c9fc96e35fe1adf8c7b77b23..8ecd0cccc7e8ec92b21fb4937d4c099b56fdb4dc 100644 (file)
@@ -599,8 +599,39 @@ static void ism_dev_release(struct device *dev)
        kfree(ism);
 }
 
+static void ism_dev_exit(struct ism_dev *ism)
+{
+       struct pci_dev *pdev = ism->pdev;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ism->lock, flags);
+       for (i = 0; i < max_client; ++i)
+               ism->subs[i] = NULL;
+       spin_unlock_irqrestore(&ism->lock, flags);
+
+       mutex_lock(&ism_dev_list.mutex);
+       mutex_lock(&clients_lock);
+       for (i = 0; i < max_client; ++i) {
+               if (clients[i])
+                       clients[i]->remove(ism);
+       }
+       mutex_unlock(&clients_lock);
+
+       if (ism_v2_capable)
+               ism_del_vlan_id(ism, ISM_RESERVED_VLANID);
+       unregister_ieq(ism);
+       unregister_sba(ism);
+       free_irq(pci_irq_vector(pdev, 0), ism);
+       kfree(ism->sba_client_arr);
+       pci_free_irq_vectors(pdev);
+       list_del_init(&ism->list);
+       mutex_unlock(&ism_dev_list.mutex);
+}
+
 static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       struct dibs_dev *dibs;
        struct ism_dev *ism;
        int ret;
 
@@ -636,12 +667,28 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dma_set_max_seg_size(&pdev->dev, SZ_1M);
        pci_set_master(pdev);
 
+       dibs = dibs_dev_alloc();
+       if (!dibs) {
+               ret = -ENOMEM;
+               goto err_resource;
+       }
+       ism->dibs = dibs;
+
        ret = ism_dev_init(ism);
        if (ret)
-               goto err_resource;
+               goto err_dibs;
+
+       ret = dibs_dev_add(dibs);
+       if (ret)
+               goto err_ism;
 
        return 0;
 
+err_ism:
+       ism_dev_exit(ism);
+err_dibs:
+       /* pairs with dibs_dev_alloc() */
+       kfree(dibs);
 err_resource:
        pci_release_mem_regions(pdev);
 err_disable:
@@ -655,41 +702,15 @@ err_dev:
        return ret;
 }
 
-static void ism_dev_exit(struct ism_dev *ism)
-{
-       struct pci_dev *pdev = ism->pdev;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&ism->lock, flags);
-       for (i = 0; i < max_client; ++i)
-               ism->subs[i] = NULL;
-       spin_unlock_irqrestore(&ism->lock, flags);
-
-       mutex_lock(&ism_dev_list.mutex);
-       mutex_lock(&clients_lock);
-       for (i = 0; i < max_client; ++i) {
-               if (clients[i])
-                       clients[i]->remove(ism);
-       }
-       mutex_unlock(&clients_lock);
-
-       if (ism_v2_capable)
-               ism_del_vlan_id(ism, ISM_RESERVED_VLANID);
-       unregister_ieq(ism);
-       unregister_sba(ism);
-       free_irq(pci_irq_vector(pdev, 0), ism);
-       kfree(ism->sba_client_arr);
-       pci_free_irq_vectors(pdev);
-       list_del_init(&ism->list);
-       mutex_unlock(&ism_dev_list.mutex);
-}
-
 static void ism_remove(struct pci_dev *pdev)
 {
        struct ism_dev *ism = dev_get_drvdata(&pdev->dev);
+       struct dibs_dev *dibs = ism->dibs;
 
+       dibs_dev_del(dibs);
        ism_dev_exit(ism);
+       /* pairs with dibs_dev_alloc() */
+       kfree(dibs);
 
        pci_release_mem_regions(pdev);
        pci_disable_device(pdev);
index 7bedeaf52c1bd3c3a89128a518f99aa8dd3e3160..c12db19c98c066ab1776bb3a74a706ebd1f48d8b 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _DIBS_H
 #define _DIBS_H
 
+#include <linux/device.h>
 /* DIBS - Direct Internal Buffer Sharing - concept
  * -----------------------------------------------
  * In the case of multiple system sharing the same hardware, dibs fabrics can
@@ -62,4 +63,41 @@ int dibs_register_client(struct dibs_client *client);
  */
 int dibs_unregister_client(struct dibs_client *client);
 
+/* DIBS devices
+ * ------------
+ */
+struct dibs_dev {
+       struct list_head list;
+};
+
+/* ------- End of client-only functions ----------- */
+
+/*
+ * Functions to be called by dibs device drivers:
+ */
+/**
+ * dibs_dev_alloc() - allocate and reference device structure
+ *
+ * The following fields will be valid upon successful return: dev
+ * NOTE: Use put_device(dibs_get_dev(@dibs)) to give up your reference instead
+ * of freeing @dibs @dev directly once you have successfully called this
+ * function.
+ * Return: Pointer to dibs device structure
+ */
+struct dibs_dev *dibs_dev_alloc(void);
+/**
+ * dibs_dev_add() - register with dibs layer and all clients
+ * @dibs: dibs device
+ *
+ * The following fields must be valid upon entry: dev, ops, drv_priv
+ * All fields will be valid upon successful return.
+ * Return: zero on success
+ */
+int dibs_dev_add(struct dibs_dev *dibs);
+/**
+ * dibs_dev_del() - unregister from dibs layer and all clients
+ * @dibs: dibs device
+ */
+void dibs_dev_del(struct dibs_dev *dibs);
+
 #endif /* _DIBS_H */
index 8358b4cd7ba6ae4645e76faad5192aa285c13894..9a53d3c48c1645a5c7a69620f256e1fee7e9aaed 100644 (file)
@@ -30,6 +30,7 @@ struct ism_dev {
        spinlock_t lock; /* protects the ism device */
        spinlock_t cmd_lock; /* serializes cmds */
        struct list_head list;
+       struct dibs_dev *dibs;
        struct pci_dev *pdev;
 
        struct ism_sba *sba;