cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iavf_client.c (15325B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright(c) 2013 - 2018 Intel Corporation. */
      3
      4#include <linux/list.h>
      5#include <linux/errno.h>
      6
      7#include "iavf.h"
      8#include "iavf_prototype.h"
      9#include "iavf_client.h"
     10
     11static
     12const char iavf_client_interface_version_str[] = IAVF_CLIENT_VERSION_STR;
     13static struct iavf_client *vf_registered_client;
     14static LIST_HEAD(iavf_devices);
     15static DEFINE_MUTEX(iavf_device_mutex);
     16
     17static u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
     18				     struct iavf_client *client,
     19				     u8 *msg, u16 len);
     20
     21static int iavf_client_setup_qvlist(struct iavf_info *ldev,
     22				    struct iavf_client *client,
     23				    struct iavf_qvlist_info *qvlist_info);
     24
     25static struct iavf_ops iavf_lan_ops = {
     26	.virtchnl_send = iavf_client_virtchnl_send,
     27	.setup_qvlist = iavf_client_setup_qvlist,
     28};
     29
     30/**
     31 * iavf_client_get_params - retrieve relevant client parameters
     32 * @vsi: VSI with parameters
     33 * @params: client param struct
     34 **/
     35static
     36void iavf_client_get_params(struct iavf_vsi *vsi, struct iavf_params *params)
     37{
     38	int i;
     39
     40	memset(params, 0, sizeof(struct iavf_params));
     41	params->mtu = vsi->netdev->mtu;
     42	params->link_up = vsi->back->link_up;
     43
     44	for (i = 0; i < IAVF_MAX_USER_PRIORITY; i++) {
     45		params->qos.prio_qos[i].tc = 0;
     46		params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
     47	}
     48}
     49
     50/**
     51 * iavf_notify_client_message - call the client message receive callback
     52 * @vsi: the VSI associated with this client
     53 * @msg: message buffer
     54 * @len: length of message
     55 *
     56 * If there is a client to this VSI, call the client
     57 **/
     58void iavf_notify_client_message(struct iavf_vsi *vsi, u8 *msg, u16 len)
     59{
     60	struct iavf_client_instance *cinst;
     61
     62	if (!vsi)
     63		return;
     64
     65	cinst = vsi->back->cinst;
     66	if (!cinst || !cinst->client || !cinst->client->ops ||
     67	    !cinst->client->ops->virtchnl_receive) {
     68		dev_dbg(&vsi->back->pdev->dev,
     69			"Cannot locate client instance virtchnl_receive function\n");
     70		return;
     71	}
     72	cinst->client->ops->virtchnl_receive(&cinst->lan_info,  cinst->client,
     73					     msg, len);
     74}
     75
     76/**
     77 * iavf_notify_client_l2_params - call the client notify callback
     78 * @vsi: the VSI with l2 param changes
     79 *
     80 * If there is a client to this VSI, call the client
     81 **/
     82void iavf_notify_client_l2_params(struct iavf_vsi *vsi)
     83{
     84	struct iavf_client_instance *cinst;
     85	struct iavf_params params;
     86
     87	if (!vsi)
     88		return;
     89
     90	cinst = vsi->back->cinst;
     91
     92	if (!cinst || !cinst->client || !cinst->client->ops ||
     93	    !cinst->client->ops->l2_param_change) {
     94		dev_dbg(&vsi->back->pdev->dev,
     95			"Cannot locate client instance l2_param_change function\n");
     96		return;
     97	}
     98	iavf_client_get_params(vsi, &params);
     99	cinst->lan_info.params = params;
    100	cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
    101					    &params);
    102}
    103
    104/**
    105 * iavf_notify_client_open - call the client open callback
    106 * @vsi: the VSI with netdev opened
    107 *
    108 * If there is a client to this netdev, call the client with open
    109 **/
    110void iavf_notify_client_open(struct iavf_vsi *vsi)
    111{
    112	struct iavf_adapter *adapter = vsi->back;
    113	struct iavf_client_instance *cinst = adapter->cinst;
    114	int ret;
    115
    116	if (!cinst || !cinst->client || !cinst->client->ops ||
    117	    !cinst->client->ops->open) {
    118		dev_dbg(&vsi->back->pdev->dev,
    119			"Cannot locate client instance open function\n");
    120		return;
    121	}
    122	if (!(test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state))) {
    123		ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
    124		if (!ret)
    125			set_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
    126	}
    127}
    128
    129/**
    130 * iavf_client_release_qvlist - send a message to the PF to release iwarp qv map
    131 * @ldev: pointer to L2 context.
    132 *
    133 * Return 0 on success or < 0 on error
    134 **/
    135static int iavf_client_release_qvlist(struct iavf_info *ldev)
    136{
    137	struct iavf_adapter *adapter = ldev->vf;
    138	enum iavf_status err;
    139
    140	if (adapter->aq_required)
    141		return -EAGAIN;
    142
    143	err = iavf_aq_send_msg_to_pf(&adapter->hw,
    144				     VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
    145				     IAVF_SUCCESS, NULL, 0, NULL);
    146
    147	if (err)
    148		dev_err(&adapter->pdev->dev,
    149			"Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
    150			err, adapter->hw.aq.asq_last_status);
    151
    152	return err;
    153}
    154
    155/**
    156 * iavf_notify_client_close - call the client close callback
    157 * @vsi: the VSI with netdev closed
    158 * @reset: true when close called due to reset pending
    159 *
    160 * If there is a client to this netdev, call the client with close
    161 **/
    162void iavf_notify_client_close(struct iavf_vsi *vsi, bool reset)
    163{
    164	struct iavf_adapter *adapter = vsi->back;
    165	struct iavf_client_instance *cinst = adapter->cinst;
    166
    167	if (!cinst || !cinst->client || !cinst->client->ops ||
    168	    !cinst->client->ops->close) {
    169		dev_dbg(&vsi->back->pdev->dev,
    170			"Cannot locate client instance close function\n");
    171		return;
    172	}
    173	cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
    174	iavf_client_release_qvlist(&cinst->lan_info);
    175	clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
    176}
    177
    178/**
    179 * iavf_client_add_instance - add a client instance to the instance list
    180 * @adapter: pointer to the board struct
    181 *
    182 * Returns cinst ptr on success, NULL on failure
    183 **/
    184static struct iavf_client_instance *
    185iavf_client_add_instance(struct iavf_adapter *adapter)
    186{
    187	struct iavf_client_instance *cinst = NULL;
    188	struct iavf_vsi *vsi = &adapter->vsi;
    189	struct netdev_hw_addr *mac = NULL;
    190	struct iavf_params params;
    191
    192	if (!vf_registered_client)
    193		goto out;
    194
    195	if (adapter->cinst) {
    196		cinst = adapter->cinst;
    197		goto out;
    198	}
    199
    200	cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
    201	if (!cinst)
    202		goto out;
    203
    204	cinst->lan_info.vf = (void *)adapter;
    205	cinst->lan_info.netdev = vsi->netdev;
    206	cinst->lan_info.pcidev = adapter->pdev;
    207	cinst->lan_info.fid = 0;
    208	cinst->lan_info.ftype = IAVF_CLIENT_FTYPE_VF;
    209	cinst->lan_info.hw_addr = adapter->hw.hw_addr;
    210	cinst->lan_info.ops = &iavf_lan_ops;
    211	cinst->lan_info.version.major = IAVF_CLIENT_VERSION_MAJOR;
    212	cinst->lan_info.version.minor = IAVF_CLIENT_VERSION_MINOR;
    213	cinst->lan_info.version.build = IAVF_CLIENT_VERSION_BUILD;
    214	iavf_client_get_params(vsi, &params);
    215	cinst->lan_info.params = params;
    216	set_bit(__IAVF_CLIENT_INSTANCE_NONE, &cinst->state);
    217
    218	cinst->lan_info.msix_count = adapter->num_iwarp_msix;
    219	cinst->lan_info.msix_entries =
    220			&adapter->msix_entries[adapter->iwarp_base_vector];
    221
    222	mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
    223			       struct netdev_hw_addr, list);
    224	if (mac)
    225		ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
    226	else
    227		dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
    228
    229	cinst->client = vf_registered_client;
    230	adapter->cinst = cinst;
    231out:
    232	return cinst;
    233}
    234
    235/**
    236 * iavf_client_del_instance - removes a client instance from the list
    237 * @adapter: pointer to the board struct
    238 *
    239 **/
    240static
    241void iavf_client_del_instance(struct iavf_adapter *adapter)
    242{
    243	kfree(adapter->cinst);
    244	adapter->cinst = NULL;
    245}
    246
    247/**
    248 * iavf_client_subtask - client maintenance work
    249 * @adapter: board private structure
    250 **/
    251void iavf_client_subtask(struct iavf_adapter *adapter)
    252{
    253	struct iavf_client *client = vf_registered_client;
    254	struct iavf_client_instance *cinst;
    255	int ret = 0;
    256
    257	if (adapter->state < __IAVF_DOWN)
    258		return;
    259
    260	/* first check client is registered */
    261	if (!client)
    262		return;
    263
    264	/* Add the client instance to the instance list */
    265	cinst = iavf_client_add_instance(adapter);
    266	if (!cinst)
    267		return;
    268
    269	dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
    270		 client->name);
    271
    272	if (!test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
    273		/* Send an Open request to the client */
    274
    275		if (client->ops && client->ops->open)
    276			ret = client->ops->open(&cinst->lan_info, client);
    277		if (!ret)
    278			set_bit(__IAVF_CLIENT_INSTANCE_OPENED,
    279				&cinst->state);
    280		else
    281			/* remove client instance */
    282			iavf_client_del_instance(adapter);
    283	}
    284}
    285
    286/**
    287 * iavf_lan_add_device - add a lan device struct to the list of lan devices
    288 * @adapter: pointer to the board struct
    289 *
    290 * Returns 0 on success or none 0 on error
    291 **/
    292int iavf_lan_add_device(struct iavf_adapter *adapter)
    293{
    294	struct iavf_device *ldev;
    295	int ret = 0;
    296
    297	mutex_lock(&iavf_device_mutex);
    298	list_for_each_entry(ldev, &iavf_devices, list) {
    299		if (ldev->vf == adapter) {
    300			ret = -EEXIST;
    301			goto out;
    302		}
    303	}
    304	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
    305	if (!ldev) {
    306		ret = -ENOMEM;
    307		goto out;
    308	}
    309	ldev->vf = adapter;
    310	INIT_LIST_HEAD(&ldev->list);
    311	list_add(&ldev->list, &iavf_devices);
    312	dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
    313		 adapter->hw.bus.bus_id, adapter->hw.bus.device,
    314		 adapter->hw.bus.func);
    315
    316	/* Since in some cases register may have happened before a device gets
    317	 * added, we can schedule a subtask to go initiate the clients.
    318	 */
    319	adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
    320
    321out:
    322	mutex_unlock(&iavf_device_mutex);
    323	return ret;
    324}
    325
    326/**
    327 * iavf_lan_del_device - removes a lan device from the device list
    328 * @adapter: pointer to the board struct
    329 *
    330 * Returns 0 on success or non-0 on error
    331 **/
    332int iavf_lan_del_device(struct iavf_adapter *adapter)
    333{
    334	struct iavf_device *ldev, *tmp;
    335	int ret = -ENODEV;
    336
    337	mutex_lock(&iavf_device_mutex);
    338	list_for_each_entry_safe(ldev, tmp, &iavf_devices, list) {
    339		if (ldev->vf == adapter) {
    340			dev_info(&adapter->pdev->dev,
    341				 "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
    342				 adapter->hw.bus.bus_id, adapter->hw.bus.device,
    343				 adapter->hw.bus.func);
    344			list_del(&ldev->list);
    345			kfree(ldev);
    346			ret = 0;
    347			break;
    348		}
    349	}
    350
    351	mutex_unlock(&iavf_device_mutex);
    352	return ret;
    353}
    354
    355/**
    356 * iavf_client_release - release client specific resources
    357 * @client: pointer to the registered client
    358 *
    359 **/
    360static void iavf_client_release(struct iavf_client *client)
    361{
    362	struct iavf_client_instance *cinst;
    363	struct iavf_device *ldev;
    364	struct iavf_adapter *adapter;
    365
    366	mutex_lock(&iavf_device_mutex);
    367	list_for_each_entry(ldev, &iavf_devices, list) {
    368		adapter = ldev->vf;
    369		cinst = adapter->cinst;
    370		if (!cinst)
    371			continue;
    372		if (test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
    373			if (client->ops && client->ops->close)
    374				client->ops->close(&cinst->lan_info, client,
    375						   false);
    376			iavf_client_release_qvlist(&cinst->lan_info);
    377			clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
    378
    379			dev_warn(&adapter->pdev->dev,
    380				 "Client %s instance closed\n", client->name);
    381		}
    382		/* delete the client instance */
    383		iavf_client_del_instance(adapter);
    384		dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
    385			 client->name);
    386	}
    387	mutex_unlock(&iavf_device_mutex);
    388}
    389
    390/**
    391 * iavf_client_prepare - prepare client specific resources
    392 * @client: pointer to the registered client
    393 *
    394 **/
    395static void iavf_client_prepare(struct iavf_client *client)
    396{
    397	struct iavf_device *ldev;
    398	struct iavf_adapter *adapter;
    399
    400	mutex_lock(&iavf_device_mutex);
    401	list_for_each_entry(ldev, &iavf_devices, list) {
    402		adapter = ldev->vf;
    403		/* Signal the watchdog to service the client */
    404		adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
    405	}
    406	mutex_unlock(&iavf_device_mutex);
    407}
    408
    409/**
    410 * iavf_client_virtchnl_send - send a message to the PF instance
    411 * @ldev: pointer to L2 context.
    412 * @client: Client pointer.
    413 * @msg: pointer to message buffer
    414 * @len: message length
    415 *
    416 * Return 0 on success or < 0 on error
    417 **/
    418static u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
    419				     struct iavf_client *client,
    420				     u8 *msg, u16 len)
    421{
    422	struct iavf_adapter *adapter = ldev->vf;
    423	enum iavf_status err;
    424
    425	if (adapter->aq_required)
    426		return -EAGAIN;
    427
    428	err = iavf_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
    429				     IAVF_SUCCESS, msg, len, NULL);
    430	if (err)
    431		dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
    432			err, adapter->hw.aq.asq_last_status);
    433
    434	return err;
    435}
    436
    437/**
    438 * iavf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
    439 * @ldev: pointer to L2 context.
    440 * @client: Client pointer.
    441 * @qvlist_info: queue and vector list
    442 *
    443 * Return 0 on success or < 0 on error
    444 **/
    445static int iavf_client_setup_qvlist(struct iavf_info *ldev,
    446				    struct iavf_client *client,
    447				    struct iavf_qvlist_info *qvlist_info)
    448{
    449	struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
    450	struct iavf_adapter *adapter = ldev->vf;
    451	struct iavf_qv_info *qv_info;
    452	enum iavf_status err;
    453	u32 v_idx, i;
    454	size_t msg_size;
    455
    456	if (adapter->aq_required)
    457		return -EAGAIN;
    458
    459	/* A quick check on whether the vectors belong to the client */
    460	for (i = 0; i < qvlist_info->num_vectors; i++) {
    461		qv_info = &qvlist_info->qv_info[i];
    462		if (!qv_info)
    463			continue;
    464		v_idx = qv_info->v_idx;
    465		if ((v_idx >=
    466		    (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
    467		    (v_idx < adapter->iwarp_base_vector))
    468			return -EINVAL;
    469	}
    470
    471	v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
    472	msg_size = struct_size(v_qvlist_info, qv_info,
    473			       v_qvlist_info->num_vectors - 1);
    474
    475	adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
    476	err = iavf_aq_send_msg_to_pf(&adapter->hw,
    477				VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP, IAVF_SUCCESS,
    478				(u8 *)v_qvlist_info, msg_size, NULL);
    479
    480	if (err) {
    481		dev_err(&adapter->pdev->dev,
    482			"Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
    483			err, adapter->hw.aq.asq_last_status);
    484		goto out;
    485	}
    486
    487	err = -EBUSY;
    488	for (i = 0; i < 5; i++) {
    489		msleep(100);
    490		if (!(adapter->client_pending &
    491		      BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
    492			err = 0;
    493			break;
    494		}
    495	}
    496out:
    497	return err;
    498}
    499
    500/**
    501 * iavf_register_client - Register a iavf client driver with the L2 driver
    502 * @client: pointer to the iavf_client struct
    503 *
    504 * Returns 0 on success or non-0 on error
    505 **/
    506int iavf_register_client(struct iavf_client *client)
    507{
    508	int ret = 0;
    509
    510	if (!client) {
    511		ret = -EIO;
    512		goto out;
    513	}
    514
    515	if (strlen(client->name) == 0) {
    516		pr_info("iavf: Failed to register client with no name\n");
    517		ret = -EIO;
    518		goto out;
    519	}
    520
    521	if (vf_registered_client) {
    522		pr_info("iavf: Client %s has already been registered!\n",
    523			client->name);
    524		ret = -EEXIST;
    525		goto out;
    526	}
    527
    528	if ((client->version.major != IAVF_CLIENT_VERSION_MAJOR) ||
    529	    (client->version.minor != IAVF_CLIENT_VERSION_MINOR)) {
    530		pr_info("iavf: Failed to register client %s due to mismatched client interface version\n",
    531			client->name);
    532		pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
    533			client->version.major, client->version.minor,
    534			client->version.build,
    535			iavf_client_interface_version_str);
    536		ret = -EIO;
    537		goto out;
    538	}
    539
    540	vf_registered_client = client;
    541
    542	iavf_client_prepare(client);
    543
    544	pr_info("iavf: Registered client %s with return code %d\n",
    545		client->name, ret);
    546out:
    547	return ret;
    548}
    549EXPORT_SYMBOL(iavf_register_client);
    550
    551/**
    552 * iavf_unregister_client - Unregister a iavf client driver with the L2 driver
    553 * @client: pointer to the iavf_client struct
    554 *
    555 * Returns 0 on success or non-0 on error
    556 **/
    557int iavf_unregister_client(struct iavf_client *client)
    558{
    559	int ret = 0;
    560
    561	/* When a unregister request comes through we would have to send
    562	 * a close for each of the client instances that were opened.
    563	 * client_release function is called to handle this.
    564	 */
    565	iavf_client_release(client);
    566
    567	if (vf_registered_client != client) {
    568		pr_info("iavf: Client %s has not been registered\n",
    569			client->name);
    570		ret = -ENODEV;
    571		goto out;
    572	}
    573	vf_registered_client = NULL;
    574	pr_info("iavf: Unregistered client %s\n", client->name);
    575out:
    576	return ret;
    577}
    578EXPORT_SYMBOL(iavf_unregister_client);