Commit 26972696 authored by Alexandra Winter's avatar Alexandra Winter Committed by Paolo Abeni
Browse files

dibs: Register ism as dibs device



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: default avatarAlexandra Winter <wintera@linux.ibm.com>
Link: https://patch.msgid.link/20250918110500.1731261-6-wintera@linux.ibm.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent d324a2ca
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -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));
+1 −1
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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>
+52 −31
Original line number Diff line number Diff line
@@ -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 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	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);
+38 −0
Original line number Diff line number Diff line
@@ -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 */
Loading