mirror of
https://github.com/torvalds/linux.git
synced 2026-10-17 22:40:03 +02:00
Enable initial support for the devlink interface with the ixd driver. The
ixd hardware is a single function PCIe device. So, the PCIe adapter gets
its own devlink instance to manage device-wide resources or configuration.
$ devlink dev show
pci/0000:83:00.6
$ devlink dev info pci/0000:83:00.6
pci/0000:83:00.6:
driver ixd
serial_number 00-a0-c9-ff-ff-23-45-67
versions:
fixed:
device.type MEV
running:
fw.mgmt.api 2.0
Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Tested-by: Bharath R <Bharath.r@intel.com>
Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
174 lines
4.5 KiB
C
174 lines
4.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/* Copyright (C) 2025 Intel Corporation */
|
|
|
|
#include "ixd.h"
|
|
#include "ixd_ctlq.h"
|
|
#include "ixd_devlink.h"
|
|
#include "ixd_virtchnl.h"
|
|
|
|
#define IXD_DFLT_MBX_Q_LEN 64
|
|
|
|
/**
|
|
* ixd_init_ctlq_create_info - Initialize control queue info for creation
|
|
* @info: destination
|
|
* @type: type of the queue to create
|
|
* @ctlq_reg: register assigned to the control queue
|
|
*/
|
|
static void ixd_init_ctlq_create_info(struct libie_ctlq_create_info *info,
|
|
enum libie_ctlq_type type,
|
|
const struct libie_ctlq_reg *ctlq_reg)
|
|
{
|
|
*info = (struct libie_ctlq_create_info) {
|
|
.type = type,
|
|
.id = -1,
|
|
.reg = *ctlq_reg,
|
|
.len = IXD_DFLT_MBX_Q_LEN,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* ixd_init_libie_xn_params - Initialize xn transaction manager creation info
|
|
* @params: destination
|
|
* @adapter: adapter info struct
|
|
* @ctlqs: list of the managed queues to create
|
|
* @num_queues: length of the queue list
|
|
*/
|
|
static void ixd_init_libie_xn_params(struct libie_ctlq_xn_init_params *params,
|
|
struct ixd_adapter *adapter,
|
|
struct libie_ctlq_create_info *ctlqs,
|
|
uint num_queues)
|
|
{
|
|
*params = (struct libie_ctlq_xn_init_params){
|
|
.cctlq_info = ctlqs,
|
|
.ctx = &adapter->cp_ctx,
|
|
.num_qs = num_queues,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* ixd_adapter_fill_dflt_ctlqs - Find default control queues and store them
|
|
* @adapter: adapter info struct
|
|
*/
|
|
static void ixd_adapter_fill_dflt_ctlqs(struct ixd_adapter *adapter)
|
|
{
|
|
adapter->arq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_RX,
|
|
LIBIE_CTLQ_MBX_ID);
|
|
adapter->asq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_TX,
|
|
LIBIE_CTLQ_MBX_ID);
|
|
}
|
|
|
|
/**
|
|
* ixd_deinit_dflt_mbx - Deinitialize default mailbox
|
|
* @adapter: adapter info struct
|
|
*/
|
|
void ixd_deinit_dflt_mbx(struct ixd_adapter *adapter)
|
|
{
|
|
cancel_delayed_work_sync(&adapter->mbx_task);
|
|
|
|
if (adapter->xnm)
|
|
libie_ctlq_xn_shutdown(adapter->xnm);
|
|
|
|
if (adapter->asq)
|
|
ixd_ctlq_clean_sq(adapter, true);
|
|
|
|
if (adapter->xnm)
|
|
libie_ctlq_xn_deinit(adapter->xnm, &adapter->cp_ctx);
|
|
|
|
adapter->arq = NULL;
|
|
adapter->asq = NULL;
|
|
adapter->xnm = NULL;
|
|
}
|
|
|
|
/**
|
|
* ixd_init_dflt_mbx - Setup default mailbox parameters and make request
|
|
* @adapter: adapter info struct
|
|
*
|
|
* Return: %0 on success, negative errno code on failure
|
|
*/
|
|
int ixd_init_dflt_mbx(struct ixd_adapter *adapter)
|
|
{
|
|
struct libie_ctlq_create_info ctlqs_info[2];
|
|
struct libie_ctlq_xn_init_params xn_params;
|
|
struct libie_ctlq_reg ctlq_reg_tx;
|
|
struct libie_ctlq_reg ctlq_reg_rx;
|
|
int err;
|
|
|
|
ixd_ctlq_reg_init(adapter, &ctlq_reg_tx, &ctlq_reg_rx);
|
|
ixd_init_ctlq_create_info(&ctlqs_info[0], LIBIE_CTLQ_TYPE_TX,
|
|
&ctlq_reg_tx);
|
|
ixd_init_ctlq_create_info(&ctlqs_info[1], LIBIE_CTLQ_TYPE_RX,
|
|
&ctlq_reg_rx);
|
|
ixd_init_libie_xn_params(&xn_params, adapter, ctlqs_info,
|
|
ARRAY_SIZE(ctlqs_info));
|
|
err = libie_ctlq_xn_init(&xn_params);
|
|
if (err)
|
|
return err;
|
|
adapter->xnm = xn_params.xnm;
|
|
|
|
ixd_adapter_fill_dflt_ctlqs(adapter);
|
|
|
|
if (!adapter->asq || !adapter->arq) {
|
|
ixd_deinit_dflt_mbx(adapter);
|
|
return -ENOENT;
|
|
}
|
|
|
|
queue_delayed_work(system_dfl_wq, &adapter->mbx_task, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* ixd_init_task - Initialize after reset
|
|
* @work: init work struct
|
|
*/
|
|
void ixd_init_task(struct work_struct *work)
|
|
{
|
|
struct ixd_adapter *adapter;
|
|
int err;
|
|
|
|
adapter = container_of(work, struct ixd_adapter,
|
|
init_task.init_work.work);
|
|
|
|
if (!ixd_check_reset_complete(adapter)) {
|
|
if (++adapter->init_task.reset_retries < 10)
|
|
queue_delayed_work(system_dfl_wq,
|
|
&adapter->init_task.init_work,
|
|
IXD_INIT_TASK_DELAY_JIFFIES);
|
|
else
|
|
dev_err(ixd_to_dev(adapter),
|
|
"Device reset failed. The driver was unable to contact the device's firmware. Check that the FW is running.\n");
|
|
return;
|
|
}
|
|
|
|
adapter->init_task.reset_retries = 0;
|
|
err = ixd_init_dflt_mbx(adapter);
|
|
if (err) {
|
|
dev_err(ixd_to_dev(adapter),
|
|
"Failed to initialize the default mailbox: %pe\n",
|
|
ERR_PTR(err));
|
|
return;
|
|
}
|
|
|
|
err = ixd_vc_dev_init(adapter);
|
|
if (!err) {
|
|
adapter->init_task.vc_retries = 0;
|
|
adapter->init_task.success = true;
|
|
ixd_devlink_register(adapter);
|
|
return;
|
|
}
|
|
|
|
libie_ctlq_xn_shutdown(adapter->xnm);
|
|
ixd_trigger_reset(adapter);
|
|
ixd_deinit_dflt_mbx(adapter);
|
|
if (++adapter->init_task.vc_retries > 5 ||
|
|
(err != -ETIMEDOUT && err != -EAGAIN && err != -EBUSY)) {
|
|
dev_err(ixd_to_dev(adapter),
|
|
"Failed to establish mailbox communication with the hardware: %pe\n",
|
|
ERR_PTR(err));
|
|
return;
|
|
}
|
|
|
|
queue_delayed_work(system_dfl_wq, &adapter->init_task.init_work,
|
|
IXD_INIT_TASK_DELAY_JIFFIES);
|
|
}
|