162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2013 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/list.h>
562306a36Sopenharmony_ci#include <linux/errno.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "iavf.h"
862306a36Sopenharmony_ci#include "iavf_prototype.h"
962306a36Sopenharmony_ci#include "iavf_client.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic
1262306a36Sopenharmony_ciconst char iavf_client_interface_version_str[] = IAVF_CLIENT_VERSION_STR;
1362306a36Sopenharmony_cistatic struct iavf_client *vf_registered_client;
1462306a36Sopenharmony_cistatic LIST_HEAD(iavf_devices);
1562306a36Sopenharmony_cistatic DEFINE_MUTEX(iavf_device_mutex);
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
1862306a36Sopenharmony_ci				     struct iavf_client *client,
1962306a36Sopenharmony_ci				     u8 *msg, u16 len);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int iavf_client_setup_qvlist(struct iavf_info *ldev,
2262306a36Sopenharmony_ci				    struct iavf_client *client,
2362306a36Sopenharmony_ci				    struct iavf_qvlist_info *qvlist_info);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic struct iavf_ops iavf_lan_ops = {
2662306a36Sopenharmony_ci	.virtchnl_send = iavf_client_virtchnl_send,
2762306a36Sopenharmony_ci	.setup_qvlist = iavf_client_setup_qvlist,
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/**
3162306a36Sopenharmony_ci * iavf_client_get_params - retrieve relevant client parameters
3262306a36Sopenharmony_ci * @vsi: VSI with parameters
3362306a36Sopenharmony_ci * @params: client param struct
3462306a36Sopenharmony_ci **/
3562306a36Sopenharmony_cistatic
3662306a36Sopenharmony_civoid iavf_client_get_params(struct iavf_vsi *vsi, struct iavf_params *params)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	int i;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	memset(params, 0, sizeof(struct iavf_params));
4162306a36Sopenharmony_ci	params->mtu = vsi->netdev->mtu;
4262306a36Sopenharmony_ci	params->link_up = vsi->back->link_up;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	for (i = 0; i < IAVF_MAX_USER_PRIORITY; i++) {
4562306a36Sopenharmony_ci		params->qos.prio_qos[i].tc = 0;
4662306a36Sopenharmony_ci		params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/**
5162306a36Sopenharmony_ci * iavf_notify_client_message - call the client message receive callback
5262306a36Sopenharmony_ci * @vsi: the VSI associated with this client
5362306a36Sopenharmony_ci * @msg: message buffer
5462306a36Sopenharmony_ci * @len: length of message
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci * If there is a client to this VSI, call the client
5762306a36Sopenharmony_ci **/
5862306a36Sopenharmony_civoid iavf_notify_client_message(struct iavf_vsi *vsi, u8 *msg, u16 len)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	struct iavf_client_instance *cinst;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (!vsi)
6362306a36Sopenharmony_ci		return;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	cinst = vsi->back->cinst;
6662306a36Sopenharmony_ci	if (!cinst || !cinst->client || !cinst->client->ops ||
6762306a36Sopenharmony_ci	    !cinst->client->ops->virtchnl_receive) {
6862306a36Sopenharmony_ci		dev_dbg(&vsi->back->pdev->dev,
6962306a36Sopenharmony_ci			"Cannot locate client instance virtchnl_receive function\n");
7062306a36Sopenharmony_ci		return;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	cinst->client->ops->virtchnl_receive(&cinst->lan_info,  cinst->client,
7362306a36Sopenharmony_ci					     msg, len);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/**
7762306a36Sopenharmony_ci * iavf_notify_client_l2_params - call the client notify callback
7862306a36Sopenharmony_ci * @vsi: the VSI with l2 param changes
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * If there is a client to this VSI, call the client
8162306a36Sopenharmony_ci **/
8262306a36Sopenharmony_civoid iavf_notify_client_l2_params(struct iavf_vsi *vsi)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct iavf_client_instance *cinst;
8562306a36Sopenharmony_ci	struct iavf_params params;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (!vsi)
8862306a36Sopenharmony_ci		return;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	cinst = vsi->back->cinst;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if (!cinst || !cinst->client || !cinst->client->ops ||
9362306a36Sopenharmony_ci	    !cinst->client->ops->l2_param_change) {
9462306a36Sopenharmony_ci		dev_dbg(&vsi->back->pdev->dev,
9562306a36Sopenharmony_ci			"Cannot locate client instance l2_param_change function\n");
9662306a36Sopenharmony_ci		return;
9762306a36Sopenharmony_ci	}
9862306a36Sopenharmony_ci	iavf_client_get_params(vsi, &params);
9962306a36Sopenharmony_ci	cinst->lan_info.params = params;
10062306a36Sopenharmony_ci	cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
10162306a36Sopenharmony_ci					    &params);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/**
10562306a36Sopenharmony_ci * iavf_notify_client_open - call the client open callback
10662306a36Sopenharmony_ci * @vsi: the VSI with netdev opened
10762306a36Sopenharmony_ci *
10862306a36Sopenharmony_ci * If there is a client to this netdev, call the client with open
10962306a36Sopenharmony_ci **/
11062306a36Sopenharmony_civoid iavf_notify_client_open(struct iavf_vsi *vsi)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct iavf_adapter *adapter = vsi->back;
11362306a36Sopenharmony_ci	struct iavf_client_instance *cinst = adapter->cinst;
11462306a36Sopenharmony_ci	int ret;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	if (!cinst || !cinst->client || !cinst->client->ops ||
11762306a36Sopenharmony_ci	    !cinst->client->ops->open) {
11862306a36Sopenharmony_ci		dev_dbg(&vsi->back->pdev->dev,
11962306a36Sopenharmony_ci			"Cannot locate client instance open function\n");
12062306a36Sopenharmony_ci		return;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci	if (!(test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state))) {
12362306a36Sopenharmony_ci		ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
12462306a36Sopenharmony_ci		if (!ret)
12562306a36Sopenharmony_ci			set_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/**
13062306a36Sopenharmony_ci * iavf_client_release_qvlist - send a message to the PF to release rdma qv map
13162306a36Sopenharmony_ci * @ldev: pointer to L2 context.
13262306a36Sopenharmony_ci *
13362306a36Sopenharmony_ci * Return 0 on success or < 0 on error
13462306a36Sopenharmony_ci **/
13562306a36Sopenharmony_cistatic int iavf_client_release_qvlist(struct iavf_info *ldev)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	struct iavf_adapter *adapter = ldev->vf;
13862306a36Sopenharmony_ci	enum iavf_status err;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	if (adapter->aq_required)
14162306a36Sopenharmony_ci		return -EAGAIN;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	err = iavf_aq_send_msg_to_pf(&adapter->hw,
14462306a36Sopenharmony_ci				     VIRTCHNL_OP_RELEASE_RDMA_IRQ_MAP,
14562306a36Sopenharmony_ci				     IAVF_SUCCESS, NULL, 0, NULL);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	if (err)
14862306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
14962306a36Sopenharmony_ci			"Unable to send RDMA vector release message to PF, error %d, aq status %d\n",
15062306a36Sopenharmony_ci			err, adapter->hw.aq.asq_last_status);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return err;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci * iavf_notify_client_close - call the client close callback
15762306a36Sopenharmony_ci * @vsi: the VSI with netdev closed
15862306a36Sopenharmony_ci * @reset: true when close called due to reset pending
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * If there is a client to this netdev, call the client with close
16162306a36Sopenharmony_ci **/
16262306a36Sopenharmony_civoid iavf_notify_client_close(struct iavf_vsi *vsi, bool reset)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct iavf_adapter *adapter = vsi->back;
16562306a36Sopenharmony_ci	struct iavf_client_instance *cinst = adapter->cinst;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	if (!cinst || !cinst->client || !cinst->client->ops ||
16862306a36Sopenharmony_ci	    !cinst->client->ops->close) {
16962306a36Sopenharmony_ci		dev_dbg(&vsi->back->pdev->dev,
17062306a36Sopenharmony_ci			"Cannot locate client instance close function\n");
17162306a36Sopenharmony_ci		return;
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci	cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
17462306a36Sopenharmony_ci	iavf_client_release_qvlist(&cinst->lan_info);
17562306a36Sopenharmony_ci	clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/**
17962306a36Sopenharmony_ci * iavf_client_add_instance - add a client instance to the instance list
18062306a36Sopenharmony_ci * @adapter: pointer to the board struct
18162306a36Sopenharmony_ci *
18262306a36Sopenharmony_ci * Returns cinst ptr on success, NULL on failure
18362306a36Sopenharmony_ci **/
18462306a36Sopenharmony_cistatic struct iavf_client_instance *
18562306a36Sopenharmony_ciiavf_client_add_instance(struct iavf_adapter *adapter)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct iavf_client_instance *cinst = NULL;
18862306a36Sopenharmony_ci	struct iavf_vsi *vsi = &adapter->vsi;
18962306a36Sopenharmony_ci	struct netdev_hw_addr *mac = NULL;
19062306a36Sopenharmony_ci	struct iavf_params params;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (!vf_registered_client)
19362306a36Sopenharmony_ci		goto out;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	if (adapter->cinst) {
19662306a36Sopenharmony_ci		cinst = adapter->cinst;
19762306a36Sopenharmony_ci		goto out;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
20162306a36Sopenharmony_ci	if (!cinst)
20262306a36Sopenharmony_ci		goto out;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	cinst->lan_info.vf = (void *)adapter;
20562306a36Sopenharmony_ci	cinst->lan_info.netdev = vsi->netdev;
20662306a36Sopenharmony_ci	cinst->lan_info.pcidev = adapter->pdev;
20762306a36Sopenharmony_ci	cinst->lan_info.fid = 0;
20862306a36Sopenharmony_ci	cinst->lan_info.ftype = IAVF_CLIENT_FTYPE_VF;
20962306a36Sopenharmony_ci	cinst->lan_info.hw_addr = adapter->hw.hw_addr;
21062306a36Sopenharmony_ci	cinst->lan_info.ops = &iavf_lan_ops;
21162306a36Sopenharmony_ci	cinst->lan_info.version.major = IAVF_CLIENT_VERSION_MAJOR;
21262306a36Sopenharmony_ci	cinst->lan_info.version.minor = IAVF_CLIENT_VERSION_MINOR;
21362306a36Sopenharmony_ci	cinst->lan_info.version.build = IAVF_CLIENT_VERSION_BUILD;
21462306a36Sopenharmony_ci	iavf_client_get_params(vsi, &params);
21562306a36Sopenharmony_ci	cinst->lan_info.params = params;
21662306a36Sopenharmony_ci	set_bit(__IAVF_CLIENT_INSTANCE_NONE, &cinst->state);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	cinst->lan_info.msix_count = adapter->num_rdma_msix;
21962306a36Sopenharmony_ci	cinst->lan_info.msix_entries =
22062306a36Sopenharmony_ci			&adapter->msix_entries[adapter->rdma_base_vector];
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
22362306a36Sopenharmony_ci			       struct netdev_hw_addr, list);
22462306a36Sopenharmony_ci	if (mac)
22562306a36Sopenharmony_ci		ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
22662306a36Sopenharmony_ci	else
22762306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	cinst->client = vf_registered_client;
23062306a36Sopenharmony_ci	adapter->cinst = cinst;
23162306a36Sopenharmony_ciout:
23262306a36Sopenharmony_ci	return cinst;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/**
23662306a36Sopenharmony_ci * iavf_client_del_instance - removes a client instance from the list
23762306a36Sopenharmony_ci * @adapter: pointer to the board struct
23862306a36Sopenharmony_ci *
23962306a36Sopenharmony_ci **/
24062306a36Sopenharmony_cistatic
24162306a36Sopenharmony_civoid iavf_client_del_instance(struct iavf_adapter *adapter)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	kfree(adapter->cinst);
24462306a36Sopenharmony_ci	adapter->cinst = NULL;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/**
24862306a36Sopenharmony_ci * iavf_client_subtask - client maintenance work
24962306a36Sopenharmony_ci * @adapter: board private structure
25062306a36Sopenharmony_ci **/
25162306a36Sopenharmony_civoid iavf_client_subtask(struct iavf_adapter *adapter)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	struct iavf_client *client = vf_registered_client;
25462306a36Sopenharmony_ci	struct iavf_client_instance *cinst;
25562306a36Sopenharmony_ci	int ret = 0;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	if (adapter->state < __IAVF_DOWN)
25862306a36Sopenharmony_ci		return;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	/* first check client is registered */
26162306a36Sopenharmony_ci	if (!client)
26262306a36Sopenharmony_ci		return;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	/* Add the client instance to the instance list */
26562306a36Sopenharmony_ci	cinst = iavf_client_add_instance(adapter);
26662306a36Sopenharmony_ci	if (!cinst)
26762306a36Sopenharmony_ci		return;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
27062306a36Sopenharmony_ci		 client->name);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	if (!test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
27362306a36Sopenharmony_ci		/* Send an Open request to the client */
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		if (client->ops && client->ops->open)
27662306a36Sopenharmony_ci			ret = client->ops->open(&cinst->lan_info, client);
27762306a36Sopenharmony_ci		if (!ret)
27862306a36Sopenharmony_ci			set_bit(__IAVF_CLIENT_INSTANCE_OPENED,
27962306a36Sopenharmony_ci				&cinst->state);
28062306a36Sopenharmony_ci		else
28162306a36Sopenharmony_ci			/* remove client instance */
28262306a36Sopenharmony_ci			iavf_client_del_instance(adapter);
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci/**
28762306a36Sopenharmony_ci * iavf_lan_add_device - add a lan device struct to the list of lan devices
28862306a36Sopenharmony_ci * @adapter: pointer to the board struct
28962306a36Sopenharmony_ci *
29062306a36Sopenharmony_ci * Returns 0 on success or none 0 on error
29162306a36Sopenharmony_ci **/
29262306a36Sopenharmony_ciint iavf_lan_add_device(struct iavf_adapter *adapter)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct iavf_device *ldev;
29562306a36Sopenharmony_ci	int ret = 0;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	mutex_lock(&iavf_device_mutex);
29862306a36Sopenharmony_ci	list_for_each_entry(ldev, &iavf_devices, list) {
29962306a36Sopenharmony_ci		if (ldev->vf == adapter) {
30062306a36Sopenharmony_ci			ret = -EEXIST;
30162306a36Sopenharmony_ci			goto out;
30262306a36Sopenharmony_ci		}
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
30562306a36Sopenharmony_ci	if (!ldev) {
30662306a36Sopenharmony_ci		ret = -ENOMEM;
30762306a36Sopenharmony_ci		goto out;
30862306a36Sopenharmony_ci	}
30962306a36Sopenharmony_ci	ldev->vf = adapter;
31062306a36Sopenharmony_ci	INIT_LIST_HEAD(&ldev->list);
31162306a36Sopenharmony_ci	list_add(&ldev->list, &iavf_devices);
31262306a36Sopenharmony_ci	dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
31362306a36Sopenharmony_ci		 adapter->hw.bus.bus_id, adapter->hw.bus.device,
31462306a36Sopenharmony_ci		 adapter->hw.bus.func);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* Since in some cases register may have happened before a device gets
31762306a36Sopenharmony_ci	 * added, we can schedule a subtask to go initiate the clients.
31862306a36Sopenharmony_ci	 */
31962306a36Sopenharmony_ci	adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ciout:
32262306a36Sopenharmony_ci	mutex_unlock(&iavf_device_mutex);
32362306a36Sopenharmony_ci	return ret;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci/**
32762306a36Sopenharmony_ci * iavf_lan_del_device - removes a lan device from the device list
32862306a36Sopenharmony_ci * @adapter: pointer to the board struct
32962306a36Sopenharmony_ci *
33062306a36Sopenharmony_ci * Returns 0 on success or non-0 on error
33162306a36Sopenharmony_ci **/
33262306a36Sopenharmony_ciint iavf_lan_del_device(struct iavf_adapter *adapter)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	struct iavf_device *ldev, *tmp;
33562306a36Sopenharmony_ci	int ret = -ENODEV;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	mutex_lock(&iavf_device_mutex);
33862306a36Sopenharmony_ci	list_for_each_entry_safe(ldev, tmp, &iavf_devices, list) {
33962306a36Sopenharmony_ci		if (ldev->vf == adapter) {
34062306a36Sopenharmony_ci			dev_info(&adapter->pdev->dev,
34162306a36Sopenharmony_ci				 "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
34262306a36Sopenharmony_ci				 adapter->hw.bus.bus_id, adapter->hw.bus.device,
34362306a36Sopenharmony_ci				 adapter->hw.bus.func);
34462306a36Sopenharmony_ci			list_del(&ldev->list);
34562306a36Sopenharmony_ci			kfree(ldev);
34662306a36Sopenharmony_ci			ret = 0;
34762306a36Sopenharmony_ci			break;
34862306a36Sopenharmony_ci		}
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	mutex_unlock(&iavf_device_mutex);
35262306a36Sopenharmony_ci	return ret;
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci/**
35662306a36Sopenharmony_ci * iavf_client_release - release client specific resources
35762306a36Sopenharmony_ci * @client: pointer to the registered client
35862306a36Sopenharmony_ci *
35962306a36Sopenharmony_ci **/
36062306a36Sopenharmony_cistatic void iavf_client_release(struct iavf_client *client)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	struct iavf_client_instance *cinst;
36362306a36Sopenharmony_ci	struct iavf_device *ldev;
36462306a36Sopenharmony_ci	struct iavf_adapter *adapter;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	mutex_lock(&iavf_device_mutex);
36762306a36Sopenharmony_ci	list_for_each_entry(ldev, &iavf_devices, list) {
36862306a36Sopenharmony_ci		adapter = ldev->vf;
36962306a36Sopenharmony_ci		cinst = adapter->cinst;
37062306a36Sopenharmony_ci		if (!cinst)
37162306a36Sopenharmony_ci			continue;
37262306a36Sopenharmony_ci		if (test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
37362306a36Sopenharmony_ci			if (client->ops && client->ops->close)
37462306a36Sopenharmony_ci				client->ops->close(&cinst->lan_info, client,
37562306a36Sopenharmony_ci						   false);
37662306a36Sopenharmony_ci			iavf_client_release_qvlist(&cinst->lan_info);
37762306a36Sopenharmony_ci			clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci			dev_warn(&adapter->pdev->dev,
38062306a36Sopenharmony_ci				 "Client %s instance closed\n", client->name);
38162306a36Sopenharmony_ci		}
38262306a36Sopenharmony_ci		/* delete the client instance */
38362306a36Sopenharmony_ci		iavf_client_del_instance(adapter);
38462306a36Sopenharmony_ci		dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
38562306a36Sopenharmony_ci			 client->name);
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci	mutex_unlock(&iavf_device_mutex);
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/**
39162306a36Sopenharmony_ci * iavf_client_prepare - prepare client specific resources
39262306a36Sopenharmony_ci * @client: pointer to the registered client
39362306a36Sopenharmony_ci *
39462306a36Sopenharmony_ci **/
39562306a36Sopenharmony_cistatic void iavf_client_prepare(struct iavf_client *client)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	struct iavf_device *ldev;
39862306a36Sopenharmony_ci	struct iavf_adapter *adapter;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	mutex_lock(&iavf_device_mutex);
40162306a36Sopenharmony_ci	list_for_each_entry(ldev, &iavf_devices, list) {
40262306a36Sopenharmony_ci		adapter = ldev->vf;
40362306a36Sopenharmony_ci		/* Signal the watchdog to service the client */
40462306a36Sopenharmony_ci		adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci	mutex_unlock(&iavf_device_mutex);
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci/**
41062306a36Sopenharmony_ci * iavf_client_virtchnl_send - send a message to the PF instance
41162306a36Sopenharmony_ci * @ldev: pointer to L2 context.
41262306a36Sopenharmony_ci * @client: Client pointer.
41362306a36Sopenharmony_ci * @msg: pointer to message buffer
41462306a36Sopenharmony_ci * @len: message length
41562306a36Sopenharmony_ci *
41662306a36Sopenharmony_ci * Return 0 on success or < 0 on error
41762306a36Sopenharmony_ci **/
41862306a36Sopenharmony_cistatic u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
41962306a36Sopenharmony_ci				     struct iavf_client *client,
42062306a36Sopenharmony_ci				     u8 *msg, u16 len)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	struct iavf_adapter *adapter = ldev->vf;
42362306a36Sopenharmony_ci	enum iavf_status err;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	if (adapter->aq_required)
42662306a36Sopenharmony_ci		return -EAGAIN;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	err = iavf_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_RDMA,
42962306a36Sopenharmony_ci				     IAVF_SUCCESS, msg, len, NULL);
43062306a36Sopenharmony_ci	if (err)
43162306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Unable to send RDMA message to PF, error %d, aq status %d\n",
43262306a36Sopenharmony_ci			err, adapter->hw.aq.asq_last_status);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return err;
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci/**
43862306a36Sopenharmony_ci * iavf_client_setup_qvlist - send a message to the PF to setup rdma qv map
43962306a36Sopenharmony_ci * @ldev: pointer to L2 context.
44062306a36Sopenharmony_ci * @client: Client pointer.
44162306a36Sopenharmony_ci * @qvlist_info: queue and vector list
44262306a36Sopenharmony_ci *
44362306a36Sopenharmony_ci * Return 0 on success or < 0 on error
44462306a36Sopenharmony_ci **/
44562306a36Sopenharmony_cistatic int iavf_client_setup_qvlist(struct iavf_info *ldev,
44662306a36Sopenharmony_ci				    struct iavf_client *client,
44762306a36Sopenharmony_ci				    struct iavf_qvlist_info *qvlist_info)
44862306a36Sopenharmony_ci{
44962306a36Sopenharmony_ci	struct virtchnl_rdma_qvlist_info *v_qvlist_info;
45062306a36Sopenharmony_ci	struct iavf_adapter *adapter = ldev->vf;
45162306a36Sopenharmony_ci	struct iavf_qv_info *qv_info;
45262306a36Sopenharmony_ci	enum iavf_status err;
45362306a36Sopenharmony_ci	u32 v_idx, i;
45462306a36Sopenharmony_ci	size_t msg_size;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	if (adapter->aq_required)
45762306a36Sopenharmony_ci		return -EAGAIN;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	/* A quick check on whether the vectors belong to the client */
46062306a36Sopenharmony_ci	for (i = 0; i < qvlist_info->num_vectors; i++) {
46162306a36Sopenharmony_ci		qv_info = &qvlist_info->qv_info[i];
46262306a36Sopenharmony_ci		if (!qv_info)
46362306a36Sopenharmony_ci			continue;
46462306a36Sopenharmony_ci		v_idx = qv_info->v_idx;
46562306a36Sopenharmony_ci		if ((v_idx >=
46662306a36Sopenharmony_ci		    (adapter->rdma_base_vector + adapter->num_rdma_msix)) ||
46762306a36Sopenharmony_ci		    (v_idx < adapter->rdma_base_vector))
46862306a36Sopenharmony_ci			return -EINVAL;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	v_qvlist_info = (struct virtchnl_rdma_qvlist_info *)qvlist_info;
47262306a36Sopenharmony_ci	msg_size = virtchnl_struct_size(v_qvlist_info, qv_info,
47362306a36Sopenharmony_ci					v_qvlist_info->num_vectors);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP);
47662306a36Sopenharmony_ci	err = iavf_aq_send_msg_to_pf(&adapter->hw,
47762306a36Sopenharmony_ci				VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP, IAVF_SUCCESS,
47862306a36Sopenharmony_ci				(u8 *)v_qvlist_info, msg_size, NULL);
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (err) {
48162306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
48262306a36Sopenharmony_ci			"Unable to send RDMA vector config message to PF, error %d, aq status %d\n",
48362306a36Sopenharmony_ci			err, adapter->hw.aq.asq_last_status);
48462306a36Sopenharmony_ci		goto out;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	err = -EBUSY;
48862306a36Sopenharmony_ci	for (i = 0; i < 5; i++) {
48962306a36Sopenharmony_ci		msleep(100);
49062306a36Sopenharmony_ci		if (!(adapter->client_pending &
49162306a36Sopenharmony_ci		      BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP))) {
49262306a36Sopenharmony_ci			err = 0;
49362306a36Sopenharmony_ci			break;
49462306a36Sopenharmony_ci		}
49562306a36Sopenharmony_ci	}
49662306a36Sopenharmony_ciout:
49762306a36Sopenharmony_ci	return err;
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci/**
50162306a36Sopenharmony_ci * iavf_register_client - Register a iavf client driver with the L2 driver
50262306a36Sopenharmony_ci * @client: pointer to the iavf_client struct
50362306a36Sopenharmony_ci *
50462306a36Sopenharmony_ci * Returns 0 on success or non-0 on error
50562306a36Sopenharmony_ci **/
50662306a36Sopenharmony_ciint iavf_register_client(struct iavf_client *client)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	int ret = 0;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (!client) {
51162306a36Sopenharmony_ci		ret = -EIO;
51262306a36Sopenharmony_ci		goto out;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	if (strlen(client->name) == 0) {
51662306a36Sopenharmony_ci		pr_info("iavf: Failed to register client with no name\n");
51762306a36Sopenharmony_ci		ret = -EIO;
51862306a36Sopenharmony_ci		goto out;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	if (vf_registered_client) {
52262306a36Sopenharmony_ci		pr_info("iavf: Client %s has already been registered!\n",
52362306a36Sopenharmony_ci			client->name);
52462306a36Sopenharmony_ci		ret = -EEXIST;
52562306a36Sopenharmony_ci		goto out;
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if ((client->version.major != IAVF_CLIENT_VERSION_MAJOR) ||
52962306a36Sopenharmony_ci	    (client->version.minor != IAVF_CLIENT_VERSION_MINOR)) {
53062306a36Sopenharmony_ci		pr_info("iavf: Failed to register client %s due to mismatched client interface version\n",
53162306a36Sopenharmony_ci			client->name);
53262306a36Sopenharmony_ci		pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
53362306a36Sopenharmony_ci			client->version.major, client->version.minor,
53462306a36Sopenharmony_ci			client->version.build,
53562306a36Sopenharmony_ci			iavf_client_interface_version_str);
53662306a36Sopenharmony_ci		ret = -EIO;
53762306a36Sopenharmony_ci		goto out;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	vf_registered_client = client;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	iavf_client_prepare(client);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	pr_info("iavf: Registered client %s with return code %d\n",
54562306a36Sopenharmony_ci		client->name, ret);
54662306a36Sopenharmony_ciout:
54762306a36Sopenharmony_ci	return ret;
54862306a36Sopenharmony_ci}
54962306a36Sopenharmony_ciEXPORT_SYMBOL(iavf_register_client);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci/**
55262306a36Sopenharmony_ci * iavf_unregister_client - Unregister a iavf client driver with the L2 driver
55362306a36Sopenharmony_ci * @client: pointer to the iavf_client struct
55462306a36Sopenharmony_ci *
55562306a36Sopenharmony_ci * Returns 0 on success or non-0 on error
55662306a36Sopenharmony_ci **/
55762306a36Sopenharmony_ciint iavf_unregister_client(struct iavf_client *client)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	int ret = 0;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	/* When a unregister request comes through we would have to send
56262306a36Sopenharmony_ci	 * a close for each of the client instances that were opened.
56362306a36Sopenharmony_ci	 * client_release function is called to handle this.
56462306a36Sopenharmony_ci	 */
56562306a36Sopenharmony_ci	iavf_client_release(client);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if (vf_registered_client != client) {
56862306a36Sopenharmony_ci		pr_info("iavf: Client %s has not been registered\n",
56962306a36Sopenharmony_ci			client->name);
57062306a36Sopenharmony_ci		ret = -ENODEV;
57162306a36Sopenharmony_ci		goto out;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci	vf_registered_client = NULL;
57462306a36Sopenharmony_ci	pr_info("iavf: Unregistered client %s\n", client->name);
57562306a36Sopenharmony_ciout:
57662306a36Sopenharmony_ci	return ret;
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ciEXPORT_SYMBOL(iavf_unregister_client);
579