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

dibs: Define dibs_client_ops and dibs_dev_ops

Move the device add() and remove() functions from ism_client to
dibs_client_ops and call add_dev()/del_dev() for ism devices and
dibs_loopback devices. dibs_client_ops->add_dev() = smcd_register_dev() for
the smc_dibs_client. This is the first step to handle ism and loopback
devices alike (as dibs devices) in the smc dibs client.

Define dibs_dev->ops and move smcd_ops->get_chid to
dibs_dev_ops->get_fabric_id() for ism and loopback devices. See below for
why this needs to be in the same patch as dibs_client_ops->add_dev().

The following changes contain intermediate steps, that will be obsoleted by
follow-on patches, once more functionality has been moved to dibs:

Use different smcd_ops and max_dmbs for ism and loopback. Follow-on patches
will change SMC-D to directly use dibs_ops instead of smcd_ops.

In smcd_register_dev() it is now necessary to identify a dibs_loopback
device before smcd_dev and smcd_ops->get_chid() are available. So provide
dibs_dev_ops->get_fabric_id() in this patch and evaluate it in
smc_ism_is_loopback().

Call smc_loopback_init() in smcd_register_dev() and call
smc_loopback_exit() in smcd_unregister_dev() to handle the functionality
that is still in smc_loopback. Follow-on patches will move all smc_loopback
code to dibs_loopback.

In smcd_[un]register_dev() use only ism device name, this will be replaced
by dibs device name by a follow-on patch.

End of changes with intermediate parts.

Allocate an smcd event workqueue for all dibs devices, although
dibs_loopback does not generate events.

Use kernel memory instead of devres memory for smcd_dev and smcd->conn.
Since commit a72178cf ("net/smc: Fix dependency of SMC on ISM") an ism
device and its driver can have a longer lifetime than the smc module, so
smc should not rely on devres to free its resources [1]. It is now the
responsibility of the smc client to free smcd and smcd->conn for all dibs
devices, ism devices as well as loopback. Call client->ops->del_dev() for
all existing dibs devices in dibs_unregister_client(), so all device
related structures can be freed in the client.

When dibs_unregister_client() is called in the context of smc_exit() or
smc_core_reboot_event(), these functions have already called
smc_lgrs_shutdown() which calls smc_smcd_terminate_all(smcd) and sets
going_away. This is done a second time in smcd_unregister_dev(). This is
analogous to how smcr is handled in these functions, by calling first
smc_lgrs_shutdown() and then smc_ib_unregister_client() >
smc_ib_remove_dev(), so leave it that way. It may be worth investigating,
whether smc_lgrs_shutdown() is still required or useful.

Remove CONFIG_SMC_LO. CONFIG_DIBS_LO now controls whether a dibs loopback
device exists or not.

Link: https://www.kernel.org/doc/Documentation/driver-model/devres.txt

 [1]
Signed-off-by: default avatarAlexandra Winter <wintera@linux.ibm.com>
Reviewed-by: default avatarMahanta Jambigi <mjambigi@linux.ibm.com>
Link: https://patch.msgid.link/20250918110500.1731261-8-wintera@linux.ibm.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent cb990a45
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -123,7 +123,6 @@ CONFIG_NET_KEY=m
CONFIG_DIBS=y
CONFIG_DIBS_LO=y
CONFIG_SMC_DIAG=m
CONFIG_SMC_LO=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
+0 −1
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@ CONFIG_NET_KEY=m
CONFIG_DIBS=y
CONFIG_DIBS_LO=y
CONFIG_SMC_DIAG=m
CONFIG_SMC_LO=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,15 @@
/* global loopback device */
static struct dibs_lo_dev *lo_dev;

static u16 dibs_lo_get_fabric_id(struct dibs_dev *dibs)
{
	return DIBS_LOOPBACK_FABRIC;
}

static const struct dibs_dev_ops dibs_lo_ops = {
	.get_fabric_id = dibs_lo_get_fabric_id,
};

static void dibs_lo_dev_exit(struct dibs_lo_dev *ldev)
{
	dibs_dev_del(ldev->dibs);
@@ -40,6 +49,8 @@ static int dibs_lo_dev_probe(void)
	}

	ldev->dibs = dibs;
	dibs->drv_priv = ldev;
	dibs->ops = &dibs_lo_ops;

	ret = dibs_dev_add(dibs);
	if (ret)
+36 −0
Original line number Diff line number Diff line
@@ -36,8 +36,10 @@ static struct dibs_dev_list dibs_dev_list = {

int dibs_register_client(struct dibs_client *client)
{
	struct dibs_dev *dibs;
	int i, rc = -ENOSPC;

	mutex_lock(&dibs_dev_list.mutex);
	mutex_lock(&clients_lock);
	for (i = 0; i < MAX_DIBS_CLIENTS; ++i) {
		if (!clients[i]) {
@@ -51,19 +53,37 @@ int dibs_register_client(struct dibs_client *client)
	}
	mutex_unlock(&clients_lock);

	if (i < MAX_DIBS_CLIENTS) {
		/* initialize with all devices that we got so far */
		list_for_each_entry(dibs, &dibs_dev_list.list, list) {
			dibs->priv[i] = NULL;
			client->ops->add_dev(dibs);
		}
	}
	mutex_unlock(&dibs_dev_list.mutex);

	return rc;
}
EXPORT_SYMBOL_GPL(dibs_register_client);

int dibs_unregister_client(struct dibs_client *client)
{
	struct dibs_dev *dibs;
	int rc = 0;

	mutex_lock(&dibs_dev_list.mutex);
	list_for_each_entry(dibs, &dibs_dev_list.list, list) {
		clients[client->id]->ops->del_dev(dibs);
		dibs->priv[client->id] = NULL;
	}

	mutex_lock(&clients_lock);
	clients[client->id] = NULL;
	if (client->id + 1 == max_client)
		max_client--;
	mutex_unlock(&clients_lock);

	mutex_unlock(&dibs_dev_list.mutex);
	return rc;
}
EXPORT_SYMBOL_GPL(dibs_unregister_client);
@@ -80,7 +100,15 @@ EXPORT_SYMBOL_GPL(dibs_dev_alloc);

int dibs_dev_add(struct dibs_dev *dibs)
{
	int i;

	mutex_lock(&dibs_dev_list.mutex);
	mutex_lock(&clients_lock);
	for (i = 0; i < max_client; ++i) {
		if (clients[i])
			clients[i]->ops->add_dev(dibs);
	}
	mutex_unlock(&clients_lock);
	list_add(&dibs->list, &dibs_dev_list.list);
	mutex_unlock(&dibs_dev_list.mutex);

@@ -90,7 +118,15 @@ EXPORT_SYMBOL_GPL(dibs_dev_add);

void dibs_dev_del(struct dibs_dev *dibs)
{
	int i;

	mutex_lock(&dibs_dev_list.mutex);
	mutex_lock(&clients_lock);
	for (i = 0; i < max_client; ++i) {
		if (clients[i])
			clients[i]->ops->del_dev(dibs);
	}
	mutex_unlock(&clients_lock);
	list_del_init(&dibs->list);
	mutex_unlock(&dibs_dev_list.mutex);
}
+19 −24
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ int ism_register_client(struct ism_client *client)
		/* initialize with all devices that we got so far */
		list_for_each_entry(ism, &ism_dev_list.list, list) {
			ism->priv[i] = NULL;
			client->add(ism);
			ism_setup_forwarding(client, ism);
		}
	}
@@ -465,6 +464,16 @@ int ism_move(struct ism_dev *ism, u64 dmb_tok, unsigned int idx, bool sf,
}
EXPORT_SYMBOL_GPL(ism_move);

static u16 ism_get_chid(struct dibs_dev *dibs)
{
	struct ism_dev *ism = dibs->drv_priv;

	if (!ism || !ism->pdev)
		return 0;

	return to_zpci(ism->pdev)->pchid;
}

static void ism_handle_event(struct ism_dev *ism)
{
	struct ism_event *entry;
@@ -523,6 +532,10 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
	return IRQ_HANDLED;
}

static const struct dibs_dev_ops ism_ops = {
	.get_fabric_id = ism_get_chid,
};

static int ism_dev_init(struct ism_dev *ism)
{
	struct pci_dev *pdev = ism->pdev;
@@ -564,7 +577,6 @@ static int ism_dev_init(struct ism_dev *ism)
	mutex_lock(&clients_lock);
	for (i = 0; i < max_client; ++i) {
		if (clients[i]) {
			clients[i]->add(ism);
			ism_setup_forwarding(clients[i], ism);
		}
	}
@@ -611,12 +623,6 @@ static void ism_dev_exit(struct ism_dev *ism)
	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);
@@ -672,7 +678,10 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
		ret = -ENOMEM;
		goto err_resource;
	}
	/* set this up before we enable interrupts */
	ism->dibs = dibs;
	dibs->drv_priv = ism;
	dibs->ops = &ism_ops;

	ret = ism_dev_init(ism);
	if (ret)
@@ -857,19 +866,6 @@ static void smcd_get_local_gid(struct smcd_dev *smcd,
	smcd_gid->gid_ext = 0;
}

static u16 ism_get_chid(struct ism_dev *ism)
{
	if (!ism || !ism->pdev)
		return 0;

	return to_zpci(ism->pdev)->pchid;
}

static u16 smcd_get_chid(struct smcd_dev *smcd)
{
	return ism_get_chid(smcd->priv);
}

static inline struct device *smcd_get_dev(struct smcd_dev *dev)
{
	struct ism_dev *ism = dev->priv;
@@ -877,7 +873,7 @@ static inline struct device *smcd_get_dev(struct smcd_dev *dev)
	return &ism->dev;
}

static const struct smcd_ops ism_ops = {
static const struct smcd_ops ism_smcd_ops = {
	.query_remote_gid = smcd_query_rgid,
	.register_dmb = smcd_register_dmb,
	.unregister_dmb = smcd_unregister_dmb,
@@ -889,13 +885,12 @@ static const struct smcd_ops ism_ops = {
	.move_data = smcd_move,
	.supports_v2 = smcd_supports_v2,
	.get_local_gid = smcd_get_local_gid,
	.get_chid = smcd_get_chid,
	.get_dev = smcd_get_dev,
};

const struct smcd_ops *ism_get_smcd_ops(void)
{
	return &ism_ops;
	return &ism_smcd_ops;
}
EXPORT_SYMBOL_GPL(ism_get_smcd_ops);
#endif
Loading