mirror of
https://github.com/torvalds/linux.git
synced 2026-10-17 22:40:03 +02:00
As the mailbox is setup, initialize the core. This makes use of the send and receive mailbox message framework for virtchnl communication between the driver and device Control Plane (CP). To start with, driver confirms the virtchnl version with the CP. Once that is done, it requests and gets the required capabilities and resources needed such as max vectors, queues, vports etc. Use a unified way of handling the virtchnl messages, where a single function handles all related memory management and the caller only provides the callbacks to fill the send buffer and to handle the response. Place generic control queue message handling separately to facilitate the addition of protocols other than virtchannel in the future. Co-developed-by: Amritha Nambiar <amritha.nambiar@intel.com> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com> Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@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>
142 lines
3.8 KiB
C
142 lines
3.8 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/* Copyright (C) 2025 Intel Corporation */
|
|
|
|
#include "ixd.h"
|
|
#include "ixd_ctlq.h"
|
|
#include "ixd_virtchnl.h"
|
|
|
|
#define IXD_CTLQ_RX_TASK_DELAY_JIFFIES msecs_to_jiffies(300)
|
|
|
|
/**
|
|
* ixd_ctlq_clean_sq - Clean the send control queue after sending the message
|
|
* @adapter: The adapter that sent the messages
|
|
* @force: Clean regardless of send status
|
|
*
|
|
* Free the libie send resources after sending the message and handling
|
|
* the response.
|
|
*/
|
|
void ixd_ctlq_clean_sq(struct ixd_adapter *adapter, bool force)
|
|
{
|
|
libie_ctlq_xn_send_clean(adapter->asq, kfree, force);
|
|
}
|
|
|
|
/**
|
|
* ixd_ctlq_init_sparams - Initialize control queue send parameters
|
|
* @adapter: The adapter with initialized mailbox
|
|
* @sparams: Parameters to initialize
|
|
* @msg_buf: DMA-mappable pointer to the message being sent
|
|
* @msg_size: Message size
|
|
*/
|
|
static void ixd_ctlq_init_sparams(struct ixd_adapter *adapter,
|
|
struct libie_ctlq_xn_send_params *sparams,
|
|
void *msg_buf, size_t msg_size)
|
|
{
|
|
*sparams = (struct libie_ctlq_xn_send_params) {
|
|
.rel_tx_buf = kfree,
|
|
.xnm = adapter->xnm,
|
|
.ctlq = adapter->asq,
|
|
.timeout_ms = IXD_CTLQ_TIMEOUT,
|
|
.send_buf = (struct kvec) {
|
|
.iov_base = msg_buf,
|
|
.iov_len = msg_size,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* ixd_ctlq_do_req - Perform a standard virtchnl request
|
|
* @adapter: The adapter with initialized mailbox
|
|
* @req: virtchnl request description
|
|
*
|
|
* Return: %0 if a message was sent and received a response
|
|
* that was successfully handled by the custom callback,
|
|
* negative error otherwise.
|
|
*/
|
|
int ixd_ctlq_do_req(struct ixd_adapter *adapter, const struct ixd_ctlq_req *req)
|
|
{
|
|
u8 onstack_send_buff[LIBIE_CP_TX_COPYBREAK] __aligned_largest = {};
|
|
struct libie_ctlq_xn_send_params send_params = {};
|
|
struct kvec *recv_mem;
|
|
void *send_buff;
|
|
int err;
|
|
|
|
send_buff = libie_cp_can_send_onstack(req->send_size) ?
|
|
&onstack_send_buff : kzalloc(req->send_size, GFP_KERNEL);
|
|
if (!send_buff)
|
|
return -ENOMEM;
|
|
|
|
ixd_ctlq_init_sparams(adapter, &send_params, send_buff,
|
|
req->send_size);
|
|
|
|
send_params.chnl_opcode = req->opcode;
|
|
|
|
if (req->send_buff_init)
|
|
req->send_buff_init(adapter, send_buff, req->ctx);
|
|
|
|
ixd_ctlq_clean_sq(adapter, false);
|
|
err = libie_ctlq_xn_send(&send_params);
|
|
if (err)
|
|
return err;
|
|
|
|
recv_mem = &send_params.recv_mem;
|
|
if (req->recv_process)
|
|
err = req->recv_process(adapter, recv_mem->iov_base,
|
|
recv_mem->iov_len, req->ctx);
|
|
|
|
libie_ctlq_release_rx_buf(recv_mem);
|
|
|
|
return err;
|
|
}
|
|
|
|
/**
|
|
* ixd_ctlq_handle_msg - Default control queue message handler
|
|
* @ctx: Control plane communication context
|
|
* @msg: Message received
|
|
*/
|
|
static void ixd_ctlq_handle_msg(struct libie_ctlq_ctx *ctx,
|
|
struct libie_ctlq_msg *msg)
|
|
{
|
|
struct ixd_adapter *adapter = pci_get_drvdata(ctx->mmio_info.pdev);
|
|
|
|
if (ixd_vc_can_handle_msg(msg))
|
|
ixd_vc_recv_event_msg(adapter, msg);
|
|
else
|
|
dev_dbg_ratelimited(ixd_to_dev(adapter),
|
|
"Received an unsupported opcode 0x%x from the CP\n",
|
|
msg->chnl_opcode);
|
|
|
|
libie_ctlq_release_rx_buf(&msg->recv_mem);
|
|
}
|
|
|
|
/**
|
|
* ixd_ctlq_recv_mb_msg - Receive a potential message over mailbox periodically
|
|
* @adapter: The adapter with initialized mailbox
|
|
*/
|
|
static void ixd_ctlq_recv_mb_msg(struct ixd_adapter *adapter)
|
|
{
|
|
struct libie_ctlq_xn_recv_params xn_params = {
|
|
.xnm = adapter->xnm,
|
|
.ctlq = adapter->arq,
|
|
.ctlq_msg_handler = ixd_ctlq_handle_msg,
|
|
.budget = LIBIE_CTLQ_MAX_XN_ENTRIES,
|
|
};
|
|
|
|
libie_ctlq_xn_recv(&xn_params);
|
|
}
|
|
|
|
/**
|
|
* ixd_ctlq_rx_task - Periodically check for mailbox responses and events
|
|
* @work: work handle
|
|
*/
|
|
void ixd_ctlq_rx_task(struct work_struct *work)
|
|
{
|
|
struct ixd_adapter *adapter;
|
|
|
|
adapter = container_of(work, struct ixd_adapter, mbx_task.work);
|
|
|
|
queue_delayed_work(system_dfl_wq, &adapter->mbx_task,
|
|
IXD_CTLQ_RX_TASK_DELAY_JIFFIES);
|
|
|
|
ixd_ctlq_recv_mb_msg(adapter);
|
|
}
|