From: Alan Brady <alan.brady@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net-next 06/19] iecm: add virtchnl messages for queues
Date: Thu, 27 Jan 2022 16:09:56 -0800 [thread overview]
Message-ID: <20220128001009.721392-7-alan.brady@intel.com> (raw)
In-Reply-To: <20220128001009.721392-1-alan.brady@intel.com>
This continues adding virtchnl messages. This largely relates to adding
messages needed to negotiate and setup traffic queues.
Signed-off-by: Phani Burra <phani.r.burra@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
Signed-off-by: Alice Michael <alice.michael@intel.com>
Signed-off-by: Alan Brady <alan.brady@intel.com>
---
drivers/net/ethernet/intel/iecm/iecm_lib.c | 14 +
drivers/net/ethernet/intel/iecm/iecm_txrx.c | 161 +++
.../net/ethernet/intel/iecm/iecm_virtchnl.c | 1127 ++++++++++++++++-
drivers/net/ethernet/intel/include/iecm.h | 22 +
.../net/ethernet/intel/include/iecm_txrx.h | 196 +++
5 files changed, 1505 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/intel/iecm/iecm_lib.c b/drivers/net/ethernet/intel/iecm/iecm_lib.c
index e2e523f0700e..4e9cc7f2d138 100644
--- a/drivers/net/ethernet/intel/iecm/iecm_lib.c
+++ b/drivers/net/ethernet/intel/iecm/iecm_lib.c
@@ -90,6 +90,20 @@ static void iecm_vport_rel_all(struct iecm_adapter *adapter)
adapter->num_alloc_vport = 0;
}
+/**
+ * iecm_vport_set_hsplit - enable or disable header split on a given vport
+ * @vport: virtual port
+ * @ena: flag controlling header split, On (true) or Off (false)
+ */
+void iecm_vport_set_hsplit(struct iecm_vport *vport, bool ena)
+{
+ if (iecm_is_cap_ena_all(vport->adapter, IECM_HSPLIT_CAPS,
+ IECM_CAP_HSPLIT) &&
+ iecm_is_queue_model_split(vport->rxq_model))
+ set_bit(__IECM_PRIV_FLAGS_HDR_SPLIT,
+ vport->adapter->config_data.user_flags);
+}
+
/**
* iecm_vport_alloc - Allocates the next available struct vport in the adapter
* @adapter: board private structure
diff --git a/drivers/net/ethernet/intel/iecm/iecm_txrx.c b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
index 2f5c16a28266..2dfb0be002e3 100644
--- a/drivers/net/ethernet/intel/iecm/iecm_txrx.c
+++ b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
@@ -20,3 +20,164 @@ iecm_vport_intr_clean_queues(int __always_unused irq, void *data)
return IRQ_HANDLED;
}
+/**
+ * iecm_vport_init_num_qs - Initialize number of queues
+ * @vport: vport to initialize queues
+ * @vport_msg: data to be filled into vport
+ */
+void iecm_vport_init_num_qs(struct iecm_vport *vport, struct virtchnl2_create_vport *vport_msg)
+{
+ vport->num_txq = le16_to_cpu(vport_msg->num_tx_q);
+ vport->num_rxq = le16_to_cpu(vport_msg->num_rx_q);
+ /* number of txqs and rxqs in config data will be zeros only in the
+ * driver load path and we dont update them there after
+ */
+ if (!vport->adapter->config_data.num_req_tx_qs &&
+ !vport->adapter->config_data.num_req_rx_qs) {
+ vport->adapter->config_data.num_req_tx_qs =
+ le16_to_cpu(vport_msg->num_tx_q);
+ vport->adapter->config_data.num_req_rx_qs =
+ le16_to_cpu(vport_msg->num_rx_q);
+ }
+
+ if (iecm_is_queue_model_split(vport->txq_model))
+ vport->num_complq = le16_to_cpu(vport_msg->num_tx_complq);
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ vport->num_bufq = le16_to_cpu(vport_msg->num_rx_bufq);
+}
+
+/**
+ * iecm_vport_calc_num_q_desc - Calculate number of queue groups
+ * @vport: vport to calculate q groups for
+ */
+void iecm_vport_calc_num_q_desc(struct iecm_vport *vport)
+{
+ int num_req_txq_desc = vport->adapter->config_data.num_req_txq_desc;
+ int num_req_rxq_desc = vport->adapter->config_data.num_req_rxq_desc;
+ int num_bufqs = vport->num_bufqs_per_qgrp;
+ int i = 0;
+
+ vport->complq_desc_count = 0;
+ if (num_req_txq_desc) {
+ vport->txq_desc_count = num_req_txq_desc;
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ vport->complq_desc_count = num_req_txq_desc;
+ if (vport->complq_desc_count < IECM_MIN_TXQ_COMPLQ_DESC)
+ vport->complq_desc_count =
+ IECM_MIN_TXQ_COMPLQ_DESC;
+ }
+ } else {
+ vport->txq_desc_count =
+ IECM_DFLT_TX_Q_DESC_COUNT;
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ vport->complq_desc_count =
+ IECM_DFLT_TX_COMPLQ_DESC_COUNT;
+ }
+ }
+
+ if (num_req_rxq_desc)
+ vport->rxq_desc_count = num_req_rxq_desc;
+ else
+ vport->rxq_desc_count = IECM_DFLT_RX_Q_DESC_COUNT;
+
+ for (i = 0; i < num_bufqs; i++) {
+ if (!vport->bufq_desc_count[i])
+ vport->bufq_desc_count[i] =
+ IECM_RX_BUFQ_DESC_COUNT(vport->rxq_desc_count,
+ num_bufqs);
+ }
+}
+EXPORT_SYMBOL(iecm_vport_calc_num_q_desc);
+
+/**
+ * iecm_vport_calc_total_qs - Calculate total number of queues
+ * @adapter: private data struct
+ * @vport_msg: message to fill with data
+ */
+void iecm_vport_calc_total_qs(struct iecm_adapter *adapter,
+ struct virtchnl2_create_vport *vport_msg)
+{
+ unsigned int num_req_tx_qs = adapter->config_data.num_req_tx_qs;
+ unsigned int num_req_rx_qs = adapter->config_data.num_req_rx_qs;
+ int dflt_splitq_txq_grps, dflt_singleq_txqs;
+ int dflt_splitq_rxq_grps, dflt_singleq_rxqs;
+ int num_txq_grps, num_rxq_grps;
+ int num_cpus;
+ u16 max_q;
+
+ /* Restrict num of queues to cpus online as a default configuration to
+ * give best performance. User can always override to a max number
+ * of queues via ethtool.
+ */
+ num_cpus = num_online_cpus();
+ max_q = adapter->max_queue_limit;
+
+ dflt_splitq_txq_grps = min_t(int, max_q, num_cpus);
+ dflt_singleq_txqs = min_t(int, max_q, num_cpus);
+ dflt_splitq_rxq_grps = min_t(int, max_q, num_cpus);
+ dflt_singleq_rxqs = min_t(int, max_q, num_cpus);
+
+ if (iecm_is_queue_model_split(le16_to_cpu(vport_msg->txq_model))) {
+ num_txq_grps = num_req_tx_qs ? num_req_tx_qs : dflt_splitq_txq_grps;
+ vport_msg->num_tx_complq = cpu_to_le16(num_txq_grps *
+ IECM_COMPLQ_PER_GROUP);
+ vport_msg->num_tx_q = cpu_to_le16(num_txq_grps *
+ IECM_DFLT_SPLITQ_TXQ_PER_GROUP);
+ } else {
+ num_txq_grps = IECM_DFLT_SINGLEQ_TX_Q_GROUPS;
+ vport_msg->num_tx_q =
+ cpu_to_le16(num_txq_grps *
+ (num_req_tx_qs ? num_req_tx_qs :
+ dflt_singleq_txqs));
+ vport_msg->num_tx_complq = 0;
+ }
+ if (iecm_is_queue_model_split(le16_to_cpu(vport_msg->rxq_model))) {
+ num_rxq_grps = num_req_rx_qs ? num_req_rx_qs : dflt_splitq_rxq_grps;
+ vport_msg->num_rx_bufq =
+ cpu_to_le16(num_rxq_grps *
+ IECM_MAX_BUFQS_PER_RXQ_GRP);
+
+ vport_msg->num_rx_q = cpu_to_le16(num_rxq_grps *
+ IECM_DFLT_SPLITQ_RXQ_PER_GROUP);
+ } else {
+ num_rxq_grps = IECM_DFLT_SINGLEQ_RX_Q_GROUPS;
+ vport_msg->num_rx_bufq = 0;
+ vport_msg->num_rx_q =
+ cpu_to_le16(num_rxq_grps *
+ (num_req_rx_qs ? num_req_rx_qs :
+ dflt_singleq_rxqs));
+ }
+}
+
+/**
+ * iecm_vport_calc_num_q_groups - Calculate number of queue groups
+ * @vport: vport to calculate q groups for
+ */
+void iecm_vport_calc_num_q_groups(struct iecm_vport *vport)
+{
+ if (iecm_is_queue_model_split(vport->txq_model))
+ vport->num_txq_grp = vport->num_txq;
+ else
+ vport->num_txq_grp = IECM_DFLT_SINGLEQ_TX_Q_GROUPS;
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ vport->num_rxq_grp = vport->num_rxq;
+ else
+ vport->num_rxq_grp = IECM_DFLT_SINGLEQ_RX_Q_GROUPS;
+}
+EXPORT_SYMBOL(iecm_vport_calc_num_q_groups);
+
+/**
+ * iecm_vport_calc_num_q_vec - Calculate total number of vectors required for
+ * this vport
+ * @vport: virtual port
+ *
+ */
+void iecm_vport_calc_num_q_vec(struct iecm_vport *vport)
+{
+ if (iecm_is_queue_model_split(vport->txq_model))
+ vport->num_q_vectors = vport->num_txq_grp;
+ else
+ vport->num_q_vectors = vport->num_txq;
+}
+EXPORT_SYMBOL(iecm_vport_calc_num_q_vec);
diff --git a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
index aae06064d706..d8152e657e24 100644
--- a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
+++ b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
@@ -859,6 +859,48 @@ static int iecm_recv_get_caps_msg(struct iecm_adapter *adapter)
sizeof(struct virtchnl2_get_capabilities));
}
+/**
+ * iecm_get_reg_intr_vecs - Get vector queue register offset
+ * @vport: virtual port structure
+ * @reg_vals: Register offsets to store in
+ * @num_vecs: Number of vector registers
+ *
+ * Returns number of regsiters that got populated
+ */
+int iecm_get_reg_intr_vecs(struct iecm_vport *vport,
+ struct iecm_vec_regs *reg_vals, int num_vecs)
+{
+ struct virtchnl2_vector_chunks *chunks;
+ struct iecm_vec_regs reg_val;
+ u16 num_vchunks, num_vec;
+ int num_regs = 0, i, j;
+
+ chunks = &vport->adapter->req_vec_chunks->vchunks;
+ num_vchunks = le16_to_cpu(chunks->num_vchunks);
+
+ for (j = 0; j < num_vchunks; j++) {
+ struct virtchnl2_vector_chunk *chunk = &chunks->vchunks[j];
+
+ num_vec = le16_to_cpu(chunk->num_vectors);
+ reg_val.dyn_ctl_reg = le32_to_cpu(chunk->dynctl_reg_start);
+ reg_val.itrn_reg = le32_to_cpu(chunk->itrn_reg_start);
+ for (i = 0; i < num_vec; i++) {
+ if (num_regs == num_vecs)
+ break;
+ reg_vals[i].dyn_ctl_reg = reg_val.dyn_ctl_reg;
+ reg_vals[i].itrn_reg = reg_val.itrn_reg;
+ reg_val.dyn_ctl_reg +=
+ le32_to_cpu(chunk->dynctl_reg_spacing);
+ reg_val.itrn_reg +=
+ le32_to_cpu(chunk->itrn_reg_spacing);
+ num_regs++;
+ }
+ }
+
+ return num_regs;
+}
+EXPORT_SYMBOL(iecm_get_reg_intr_vecs);
+
/**
* iecm_send_create_vport_msg - Send virtchnl create vport message
* @adapter: Driver specific private structure
@@ -869,8 +911,36 @@ static int iecm_recv_get_caps_msg(struct iecm_adapter *adapter)
*/
static int iecm_send_create_vport_msg(struct iecm_adapter *adapter)
{
- /* stub */
- return 0;
+ struct virtchnl2_create_vport *vport_msg;
+ int buf_size;
+
+ buf_size = sizeof(struct virtchnl2_create_vport);
+ if (!adapter->vport_params_reqd[0]) {
+ adapter->vport_params_reqd[0] = kzalloc(buf_size, GFP_KERNEL);
+ if (!adapter->vport_params_reqd[0])
+ return -ENOMEM;
+ }
+
+ vport_msg = (struct virtchnl2_create_vport *)
+ adapter->vport_params_reqd[0];
+ vport_msg->vport_type = cpu_to_le16(VIRTCHNL2_VPORT_TYPE_DEFAULT);
+
+ if (test_bit(__IECM_REQ_TX_SPLITQ, adapter->flags))
+ vport_msg->txq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SPLIT);
+ else
+ vport_msg->txq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SINGLE);
+
+ if (test_bit(__IECM_REQ_RX_SPLITQ, adapter->flags))
+ vport_msg->rxq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SPLIT);
+ else
+ vport_msg->rxq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SINGLE);
+
+ adapter->dev_ops.vc_ops.init_max_queues(adapter);
+
+ iecm_vport_calc_total_qs(adapter, vport_msg);
+
+ return iecm_send_mb_msg(adapter, VIRTCHNL2_OP_CREATE_VPORT, buf_size,
+ (u8 *)vport_msg);
}
/**
@@ -884,7 +954,25 @@ static int iecm_send_create_vport_msg(struct iecm_adapter *adapter)
static int iecm_recv_create_vport_msg(struct iecm_adapter *adapter,
int *vport_id)
{
- /* stub */
+ struct virtchnl2_create_vport *vport_msg;
+ int err;
+
+ if (!adapter->vport_params_recvd[0]) {
+ adapter->vport_params_recvd[0] = kzalloc(IECM_DFLT_MBX_BUF_SIZE,
+ GFP_KERNEL);
+ if (!adapter->vport_params_recvd[0])
+ return -ENOMEM;
+ }
+
+ vport_msg = (struct virtchnl2_create_vport *)
+ adapter->vport_params_recvd[0];
+
+ err = iecm_recv_mb_msg(adapter, VIRTCHNL2_OP_CREATE_VPORT, vport_msg,
+ IECM_DFLT_MBX_BUF_SIZE);
+ if (err)
+ return err;
+
+ *vport_id = le32_to_cpu(vport_msg->vport_id);
return 0;
}
@@ -966,6 +1054,920 @@ int iecm_wait_for_event(struct iecm_adapter *adapter,
}
EXPORT_SYMBOL(iecm_wait_for_event);
+/**
+ * iecm_wait_for_marker_event - wait for software marker response
+ * @vport: virtual port data structure
+ *
+ * Returns 0 success, negative on failure.
+ **/
+static int iecm_wait_for_marker_event(struct iecm_vport *vport)
+{
+ int event = 0;
+ int i;
+
+ for (i = 0; i < vport->num_txq; i++)
+ set_bit(__IECM_Q_SW_MARKER, vport->txqs[i]->flags);
+
+ event = wait_event_timeout(vport->adapter->sw_marker_wq,
+ test_and_clear_bit(__IECM_SW_MARKER,
+ vport->adapter->flags),
+ msecs_to_jiffies(500));
+ if (event)
+ return 0;
+ return -ETIMEDOUT;
+}
+
+/**
+ * iecm_send_destroy_vport_msg - Send virtchnl destroy vport message
+ * @vport: virtual port data structure
+ *
+ * Send virtchnl destroy vport message. Returns 0 on success, negative on
+ * failure.
+ */
+int iecm_send_destroy_vport_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_vport v_id;
+ int err;
+
+ v_id.vport_id = cpu_to_le32(vport->vport_id);
+
+ err = iecm_send_mb_msg(adapter, VIRTCHNL2_OP_DESTROY_VPORT,
+ sizeof(v_id), (u8 *)&v_id);
+ if (err)
+ return err;
+
+ return iecm_min_wait_for_event(adapter, IECM_VC_DESTROY_VPORT,
+ IECM_VC_DESTROY_VPORT_ERR);
+}
+
+/**
+ * iecm_send_enable_vport_msg - Send virtchnl enable vport message
+ * @vport: virtual port data structure
+ *
+ * Send enable vport virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+int iecm_send_enable_vport_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_vport v_id;
+ int err;
+
+ v_id.vport_id = cpu_to_le32(vport->vport_id);
+
+ err = iecm_send_mb_msg(adapter, VIRTCHNL2_OP_ENABLE_VPORT,
+ sizeof(v_id), (u8 *)&v_id);
+ if (err)
+ return err;
+
+ return iecm_wait_for_event(adapter, IECM_VC_ENA_VPORT,
+ IECM_VC_ENA_VPORT_ERR);
+}
+
+/**
+ * iecm_send_disable_vport_msg - Send virtchnl disable vport message
+ * @vport: virtual port data structure
+ *
+ * Send disable vport virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+int iecm_send_disable_vport_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_vport v_id;
+ int err;
+
+ v_id.vport_id = cpu_to_le32(vport->vport_id);
+
+ err = iecm_send_mb_msg(adapter, VIRTCHNL2_OP_DISABLE_VPORT,
+ sizeof(v_id), (u8 *)&v_id);
+ if (err)
+ return err;
+
+ return iecm_min_wait_for_event(adapter, IECM_VC_DIS_VPORT,
+ IECM_VC_DIS_VPORT_ERR);
+}
+
+/**
+ * iecm_send_config_tx_queues_msg - Send virtchnl config tx queues message
+ * @vport: virtual port data structure
+ *
+ * Send config tx queues virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+int iecm_send_config_tx_queues_msg(struct iecm_vport *vport)
+{
+ struct virtchnl2_config_tx_queues *ctq = NULL;
+ int config_data_size, chunk_size, buf_size = 0;
+ int totqs, num_msgs, num_chunks;
+ struct virtchnl2_txq_info *qi;
+ int err = 0, i, k = 0;
+ bool alloc = false;
+
+ totqs = vport->num_txq + vport->num_complq;
+ qi = kcalloc(totqs, sizeof(struct virtchnl2_txq_info), GFP_KERNEL);
+ if (!qi)
+ return -ENOMEM;
+
+ /* Populate the queue info buffer with all queue context info */
+ for (i = 0; i < vport->num_txq_grp; i++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+ int j;
+
+ for (j = 0; j < tx_qgrp->num_txq; j++, k++) {
+ qi[k].queue_id =
+ cpu_to_le32(tx_qgrp->txqs[j]->q_id);
+ qi[k].model =
+ cpu_to_le16(vport->txq_model);
+ qi[k].type =
+ cpu_to_le32(tx_qgrp->txqs[j]->q_type);
+ qi[k].ring_len =
+ cpu_to_le16(tx_qgrp->txqs[j]->desc_count);
+ qi[k].dma_ring_addr =
+ cpu_to_le64(tx_qgrp->txqs[j]->dma);
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ struct iecm_queue *q = tx_qgrp->txqs[j];
+
+ qi[k].tx_compl_queue_id =
+ cpu_to_le16(tx_qgrp->complq->q_id);
+
+ if (test_bit(__IECM_Q_FLOW_SCH_EN, q->flags))
+ qi[k].sched_mode =
+ cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_FLOW);
+ else
+ qi[k].sched_mode =
+ cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_QUEUE);
+ } else {
+ qi[k].sched_mode =
+ cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_QUEUE);
+ }
+ }
+
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ qi[k].queue_id =
+ cpu_to_le32(tx_qgrp->complq->q_id);
+ qi[k].model =
+ cpu_to_le16(vport->txq_model);
+ qi[k].type =
+ cpu_to_le32(tx_qgrp->complq->q_type);
+ qi[k].ring_len =
+ cpu_to_le16(tx_qgrp->complq->desc_count);
+ qi[k].dma_ring_addr =
+ cpu_to_le64(tx_qgrp->complq->dma);
+ k++;
+ }
+ }
+
+ /* Make sure accounting agrees */
+ if (k != totqs) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ /* Chunk up the queue contexts into multiple messages to avoid
+ * sending a control queue message buffer that is too large
+ */
+ config_data_size = sizeof(struct virtchnl2_config_tx_queues);
+ chunk_size = sizeof(struct virtchnl2_txq_info);
+
+ num_chunks = IECM_NUM_CHUNKS_PER_MSG(config_data_size, chunk_size) + 1;
+ if (totqs < num_chunks)
+ num_chunks = totqs;
+
+ num_msgs = totqs / num_chunks;
+ if (totqs % num_chunks)
+ num_msgs++;
+
+ for (i = 0, k = 0; i < num_msgs; i++) {
+ if (!ctq || alloc) {
+ buf_size = (chunk_size * (num_chunks - 1)) +
+ config_data_size;
+ kfree(ctq);
+ ctq = kzalloc(buf_size, GFP_KERNEL);
+ if (!ctq) {
+ err = -ENOMEM;
+ goto error;
+ }
+ } else {
+ memset(ctq, 0, buf_size);
+ }
+
+ ctq->vport_id = cpu_to_le32(vport->vport_id);
+ ctq->num_qinfo = cpu_to_le16(num_chunks);
+ memcpy(ctq->qinfo, &qi[k], chunk_size * num_chunks);
+
+ err = iecm_send_mb_msg(vport->adapter,
+ VIRTCHNL2_OP_CONFIG_TX_QUEUES,
+ buf_size, (u8 *)ctq);
+ if (err)
+ goto mbx_error;
+
+ err = iecm_wait_for_event(vport->adapter, IECM_VC_CONFIG_TXQ,
+ IECM_VC_CONFIG_TXQ_ERR);
+ if (err)
+ goto mbx_error;
+
+ k += num_chunks;
+ totqs -= num_chunks;
+ if (totqs < num_chunks) {
+ num_chunks = totqs;
+ alloc = true;
+ }
+ }
+
+mbx_error:
+ kfree(ctq);
+error:
+ kfree(qi);
+ return err;
+}
+
+/**
+ * iecm_send_config_rx_queues_msg - Send virtchnl config rx queues message
+ * @vport: virtual port data structure
+ *
+ * Send config rx queues virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+int iecm_send_config_rx_queues_msg(struct iecm_vport *vport)
+{
+ struct virtchnl2_config_rx_queues *crq = NULL;
+ int config_data_size, chunk_size, buf_size = 0;
+ int totqs, num_msgs, num_chunks;
+ struct virtchnl2_rxq_info *qi;
+ int err = 0, i, k = 0;
+ bool alloc = false;
+
+ totqs = vport->num_rxq + vport->num_bufq;
+ qi = kcalloc(totqs, sizeof(struct virtchnl2_rxq_info), GFP_KERNEL);
+ if (!qi)
+ return -ENOMEM;
+
+ /* Populate the queue info buffer with all queue context info */
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+ int num_rxq;
+ int j;
+
+ if (iecm_is_queue_model_split(vport->rxq_model)) {
+ for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) {
+ struct iecm_queue *bufq =
+ &rx_qgrp->splitq.bufq_sets[j].bufq;
+
+ qi[k].queue_id =
+ cpu_to_le32(bufq->q_id);
+ qi[k].model =
+ cpu_to_le16(vport->rxq_model);
+ qi[k].type =
+ cpu_to_le32(bufq->q_type);
+ qi[k].desc_ids =
+ cpu_to_le64(VIRTCHNL2_RXDID_1_FLEX_SPLITQ_M);
+ qi[k].ring_len =
+ cpu_to_le16(bufq->desc_count);
+ qi[k].dma_ring_addr =
+ cpu_to_le64(bufq->dma);
+ qi[k].data_buffer_size =
+ cpu_to_le32(bufq->rx_buf_size);
+ qi[k].buffer_notif_stride =
+ bufq->rx_buf_stride;
+ qi[k].rx_buffer_low_watermark =
+ cpu_to_le16(bufq->rx_buffer_low_watermark);
+ }
+ }
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ num_rxq = rx_qgrp->splitq.num_rxq_sets;
+ else
+ num_rxq = rx_qgrp->singleq.num_rxq;
+
+ for (j = 0; j < num_rxq; j++, k++) {
+ struct iecm_queue *rxq;
+
+ if (iecm_is_queue_model_split(vport->rxq_model)) {
+ rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq;
+ qi[k].rx_bufq1_id =
+ cpu_to_le16(rxq->rxq_grp->splitq.bufq_sets[0].bufq.q_id);
+ qi[k].rx_bufq2_id =
+ cpu_to_le16(rxq->rxq_grp->splitq.bufq_sets[1].bufq.q_id);
+ qi[k].hdr_buffer_size =
+ cpu_to_le16(rxq->rx_hbuf_size);
+ qi[k].rx_buffer_low_watermark =
+ cpu_to_le16(rxq->rx_buffer_low_watermark);
+
+ if (rxq->rx_hsplit_en) {
+ qi[k].qflags =
+ cpu_to_le16(VIRTCHNL2_RXQ_HDR_SPLIT);
+ qi[k].hdr_buffer_size =
+ cpu_to_le16(rxq->rx_hbuf_size);
+ }
+ } else {
+ rxq = rx_qgrp->singleq.rxqs[j];
+ }
+
+ qi[k].queue_id =
+ cpu_to_le32(rxq->q_id);
+ qi[k].model =
+ cpu_to_le16(vport->rxq_model);
+ qi[k].type =
+ cpu_to_le32(rxq->q_type);
+ qi[k].ring_len =
+ cpu_to_le16(rxq->desc_count);
+ qi[k].dma_ring_addr =
+ cpu_to_le64(rxq->dma);
+ qi[k].max_pkt_size =
+ cpu_to_le32(rxq->rx_max_pkt_size);
+ qi[k].data_buffer_size =
+ cpu_to_le32(rxq->rx_buf_size);
+ qi[k].qflags |=
+ cpu_to_le16(VIRTCHNL2_RX_DESC_SIZE_32BYTE);
+ qi[k].desc_ids =
+ cpu_to_le64(rxq->rxdids);
+ }
+ }
+
+ /* Make sure accounting agrees */
+ if (k != totqs) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ /* Chunk up the queue contexts into multiple messages to avoid
+ * sending a control queue message buffer that is too large
+ */
+ config_data_size = sizeof(struct virtchnl2_config_rx_queues);
+ chunk_size = sizeof(struct virtchnl2_rxq_info);
+
+ num_chunks = IECM_NUM_CHUNKS_PER_MSG(config_data_size, chunk_size) + 1;
+ if (totqs < num_chunks)
+ num_chunks = totqs;
+
+ num_msgs = totqs / num_chunks;
+ if (totqs % num_chunks)
+ num_msgs++;
+
+ for (i = 0, k = 0; i < num_msgs; i++) {
+ if (!crq || alloc) {
+ buf_size = (chunk_size * (num_chunks - 1)) +
+ config_data_size;
+ kfree(crq);
+ crq = kzalloc(buf_size, GFP_KERNEL);
+ if (!crq) {
+ err = -ENOMEM;
+ goto error;
+ }
+ } else {
+ memset(crq, 0, buf_size);
+ }
+
+ crq->vport_id = cpu_to_le32(vport->vport_id);
+ crq->num_qinfo = cpu_to_le16(num_chunks);
+ memcpy(crq->qinfo, &qi[k], chunk_size * num_chunks);
+
+ err = iecm_send_mb_msg(vport->adapter,
+ VIRTCHNL2_OP_CONFIG_RX_QUEUES,
+ buf_size, (u8 *)crq);
+ if (err)
+ goto mbx_error;
+
+ err = iecm_wait_for_event(vport->adapter, IECM_VC_CONFIG_RXQ,
+ IECM_VC_CONFIG_RXQ_ERR);
+ if (err)
+ goto mbx_error;
+
+ k += num_chunks;
+ totqs -= num_chunks;
+ if (totqs < num_chunks) {
+ num_chunks = totqs;
+ alloc = true;
+ }
+ }
+
+mbx_error:
+ kfree(crq);
+error:
+ kfree(qi);
+ return err;
+}
+
+/**
+ * iecm_send_ena_dis_queues_msg - Send virtchnl enable or disable
+ * queues message
+ * @vport: virtual port data structure
+ * @vc_op: virtchnl op code to send
+ *
+ * Send enable or disable queues virtchnl message. Returns 0 on success,
+ * negative on failure.
+ */
+static int iecm_send_ena_dis_queues_msg(struct iecm_vport *vport,
+ enum virtchnl_ops vc_op)
+{
+ int num_msgs, num_chunks, config_data_size, chunk_size;
+ int num_txq, num_rxq, num_q, buf_size, err = 0;
+ struct virtchnl2_del_ena_dis_queues *eq = NULL;
+ struct virtchnl2_queue_chunk *qc;
+ bool alloc = false;
+ int i, j, k = 0;
+
+ /* validate virtchnl op */
+ switch (vc_op) {
+ case VIRTCHNL2_OP_ENABLE_QUEUES:
+ case VIRTCHNL2_OP_DISABLE_QUEUES:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ num_txq = vport->num_txq + vport->num_complq;
+ num_rxq = vport->num_rxq + vport->num_bufq;
+ num_q = num_txq + num_rxq;
+ buf_size = sizeof(struct virtchnl2_queue_chunk) * (num_q);
+ qc = kzalloc(buf_size, GFP_KERNEL);
+ if (!qc)
+ return -ENOMEM;
+
+ for (i = 0; i < vport->num_txq_grp; i++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+
+ for (j = 0; j < tx_qgrp->num_txq; j++, k++) {
+ qc[k].type = cpu_to_le32(tx_qgrp->txqs[j]->q_type);
+ qc[k].start_queue_id =
+ cpu_to_le32(tx_qgrp->txqs[j]->q_id);
+ qc[k].num_queues = cpu_to_le32(1);
+ }
+ }
+ if (vport->num_txq != k) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ for (i = 0; i < vport->num_txq_grp; i++, k++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+
+ qc[k].type = cpu_to_le32(tx_qgrp->complq->q_type);
+ qc[k].start_queue_id =
+ cpu_to_le32(tx_qgrp->complq->q_id);
+ qc[k].num_queues = cpu_to_le32(1);
+ }
+ if (vport->num_complq != (k - vport->num_txq)) {
+ err = -EINVAL;
+ goto error;
+ }
+ }
+
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ num_rxq = rx_qgrp->splitq.num_rxq_sets;
+ else
+ num_rxq = rx_qgrp->singleq.num_rxq;
+
+ for (j = 0; j < num_rxq; j++, k++) {
+ if (iecm_is_queue_model_split(vport->rxq_model)) {
+ qc[k].start_queue_id =
+ cpu_to_le32(rx_qgrp->splitq.rxq_sets[j]->rxq.q_id);
+ qc[k].type =
+ cpu_to_le32(rx_qgrp->splitq.rxq_sets[j]->rxq.q_type);
+ } else {
+ qc[k].start_queue_id =
+ cpu_to_le32(rx_qgrp->singleq.rxqs[j]->q_id);
+ qc[k].type =
+ cpu_to_le32(rx_qgrp->singleq.rxqs[j]->q_type);
+ }
+ qc[k].num_queues = cpu_to_le32(1);
+ }
+ }
+ if (vport->num_rxq != k - (vport->num_txq + vport->num_complq)) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ if (iecm_is_queue_model_split(vport->rxq_model)) {
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+
+ for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) {
+ struct iecm_queue *q = &rx_qgrp->splitq.bufq_sets[j].bufq;
+
+ qc[k].type = cpu_to_le32(q->q_type);
+ qc[k].start_queue_id = cpu_to_le32(q->q_id);
+ qc[k].num_queues = cpu_to_le32(1);
+ }
+ }
+ if (vport->num_bufq != k - (vport->num_txq +
+ vport->num_complq +
+ vport->num_rxq)) {
+ err = -EINVAL;
+ goto error;
+ }
+ }
+
+ /* Chunk up the queue info into multiple messages */
+ config_data_size = sizeof(struct virtchnl2_del_ena_dis_queues);
+ chunk_size = sizeof(struct virtchnl2_queue_chunk);
+
+ num_chunks = IECM_NUM_CHUNKS_PER_MSG(config_data_size, chunk_size) + 1;
+ if (num_q < num_chunks)
+ num_chunks = num_q;
+
+ num_msgs = num_q / num_chunks;
+ if (num_q % num_chunks)
+ num_msgs++;
+
+ for (i = 0, k = 0; i < num_msgs; i++) {
+ if (!eq || alloc) {
+ buf_size = (chunk_size * (num_chunks - 1)) +
+ config_data_size;
+ kfree(eq);
+ eq = kzalloc(buf_size, GFP_KERNEL);
+ if (!eq) {
+ err = -ENOMEM;
+ goto error;
+ }
+ } else {
+ memset(eq, 0, buf_size);
+ }
+ eq->vport_id = cpu_to_le32(vport->vport_id);
+ eq->chunks.num_chunks = cpu_to_le16(num_chunks);
+ memcpy(eq->chunks.chunks, &qc[k], chunk_size * num_chunks);
+
+ err = iecm_send_mb_msg(vport->adapter, vc_op, buf_size,
+ (u8 *)eq);
+ if (err)
+ goto mbx_error;
+ k += num_chunks;
+ num_q -= num_chunks;
+ if (num_q < num_chunks) {
+ num_chunks = num_q;
+ alloc = true;
+ }
+ }
+mbx_error:
+ kfree(eq);
+error:
+ kfree(qc);
+ return err;
+}
+
+/**
+ * iecm_send_map_unmap_queue_vector_msg - Send virtchnl map or unmap queue
+ * vector message
+ * @vport: virtual port data structure
+ * @map: true for map and false for unmap
+ *
+ * Send map or unmap queue vector virtchnl message. Returns 0 on success,
+ * negative on failure.
+ */
+int iecm_send_map_unmap_queue_vector_msg(struct iecm_vport *vport, bool map)
+{
+ int num_msgs, num_chunks, config_data_size, chunk_size;
+ struct virtchnl2_queue_vector_maps *vqvm = NULL;
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_queue_vector *vqv;
+ int buf_size, num_q, err = 0;
+ bool alloc = false;
+ int i, j, k = 0;
+
+ num_q = vport->num_txq + vport->num_rxq;
+
+ buf_size = sizeof(struct virtchnl2_queue_vector) * num_q;
+ vqv = kzalloc(buf_size, GFP_KERNEL);
+ if (!vqv)
+ return -ENOMEM;
+
+ for (i = 0; i < vport->num_txq_grp; i++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+
+ for (j = 0; j < tx_qgrp->num_txq; j++, k++) {
+ vqv[k].queue_type = cpu_to_le32(tx_qgrp->txqs[j]->q_type);
+ vqv[k].queue_id = cpu_to_le32(tx_qgrp->txqs[j]->q_id);
+
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ vqv[k].vector_id =
+ cpu_to_le16(tx_qgrp->complq->q_vector->v_idx);
+ vqv[k].itr_idx =
+ cpu_to_le32(tx_qgrp->complq->q_vector->tx_itr_idx);
+ } else {
+ vqv[k].vector_id =
+ cpu_to_le16(tx_qgrp->txqs[j]->q_vector->v_idx);
+ vqv[k].itr_idx =
+ cpu_to_le32(tx_qgrp->txqs[j]->q_vector->tx_itr_idx);
+ }
+ }
+ }
+
+ if (vport->num_txq != k) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+ int num_rxq;
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ num_rxq = rx_qgrp->splitq.num_rxq_sets;
+ else
+ num_rxq = rx_qgrp->singleq.num_rxq;
+
+ for (j = 0; j < num_rxq; j++, k++) {
+ struct iecm_queue *rxq;
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq;
+ else
+ rxq = rx_qgrp->singleq.rxqs[j];
+
+ vqv[k].queue_type = cpu_to_le32(rxq->q_type);
+ vqv[k].queue_id = cpu_to_le32(rxq->q_id);
+ vqv[k].vector_id = cpu_to_le16(rxq->q_vector->v_idx);
+ vqv[k].itr_idx = cpu_to_le32(rxq->q_vector->rx_itr_idx);
+ }
+ }
+
+ if (iecm_is_queue_model_split(vport->txq_model)) {
+ if (vport->num_rxq != k - vport->num_complq) {
+ err = -EINVAL;
+ goto error;
+ }
+ } else {
+ if (vport->num_rxq != k - vport->num_txq) {
+ err = -EINVAL;
+ goto error;
+ }
+ }
+
+ /* Chunk up the vector info into multiple messages */
+ config_data_size = sizeof(struct virtchnl2_queue_vector_maps);
+ chunk_size = sizeof(struct virtchnl2_queue_vector);
+
+ num_chunks = IECM_NUM_CHUNKS_PER_MSG(config_data_size, chunk_size) + 1;
+ if (num_q < num_chunks)
+ num_chunks = num_q;
+
+ num_msgs = num_q / num_chunks;
+ if (num_q % num_chunks)
+ num_msgs++;
+
+ for (i = 0, k = 0; i < num_msgs; i++) {
+ if (!vqvm || alloc) {
+ buf_size = (chunk_size * (num_chunks - 1)) +
+ config_data_size;
+ kfree(vqvm);
+ vqvm = kzalloc(buf_size, GFP_KERNEL);
+ if (!vqvm) {
+ err = -ENOMEM;
+ goto error;
+ }
+ } else {
+ memset(vqvm, 0, buf_size);
+ }
+ vqvm->vport_id = cpu_to_le32(vport->vport_id);
+ vqvm->num_qv_maps = cpu_to_le16(num_chunks);
+ memcpy(vqvm->qv_maps, &vqv[k], chunk_size * num_chunks);
+
+ if (map) {
+ err = iecm_send_mb_msg(adapter,
+ VIRTCHNL2_OP_MAP_QUEUE_VECTOR,
+ buf_size, (u8 *)vqvm);
+ if (!err)
+ err = iecm_wait_for_event(adapter,
+ IECM_VC_MAP_IRQ,
+ IECM_VC_MAP_IRQ_ERR);
+ } else {
+ err = iecm_send_mb_msg(adapter,
+ VIRTCHNL2_OP_UNMAP_QUEUE_VECTOR,
+ buf_size, (u8 *)vqvm);
+ if (!err)
+ err =
+ iecm_min_wait_for_event(adapter,
+ IECM_VC_UNMAP_IRQ,
+ IECM_VC_UNMAP_IRQ_ERR);
+ }
+ if (err)
+ goto mbx_error;
+
+ k += num_chunks;
+ num_q -= num_chunks;
+ if (num_q < num_chunks) {
+ num_chunks = num_q;
+ alloc = true;
+ }
+ }
+mbx_error:
+ kfree(vqvm);
+error:
+ kfree(vqv);
+ return err;
+}
+EXPORT_SYMBOL(iecm_send_map_unmap_queue_vector_msg);
+
+/**
+ * iecm_send_enable_queues_msg - send enable queues virtchnl message
+ * @vport: Virtual port private data structure
+ *
+ * Will send enable queues virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+static int iecm_send_enable_queues_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ int err;
+
+ err = iecm_send_ena_dis_queues_msg(vport,
+ VIRTCHNL2_OP_ENABLE_QUEUES);
+ if (err)
+ return err;
+
+ return iecm_wait_for_event(adapter, IECM_VC_ENA_QUEUES,
+ IECM_VC_ENA_QUEUES_ERR);
+}
+
+/**
+ * iecm_send_disable_queues_msg - send disable queues virtchnl message
+ * @vport: Virtual port private data structure
+ *
+ * Will send disable queues virtchnl message. Returns 0 on success, negative
+ * on failure.
+ */
+static int iecm_send_disable_queues_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ int err;
+
+ err = iecm_send_ena_dis_queues_msg(vport,
+ VIRTCHNL2_OP_DISABLE_QUEUES);
+ if (err)
+ return err;
+
+ err = iecm_min_wait_for_event(adapter, IECM_VC_DIS_QUEUES,
+ IECM_VC_DIS_QUEUES_ERR);
+ if (err)
+ return err;
+
+ return iecm_wait_for_marker_event(vport);
+}
+
+/**
+ * iecm_convert_reg_to_queue_chunks - Copy queue chunk information to the right
+ * structure
+ * @dchunks: Destination chunks to store data to
+ * @schunks: Source chunks to copy data from
+ * @num_chunks: number of chunks to copy
+ */
+static void
+iecm_convert_reg_to_queue_chunks(struct virtchnl2_queue_chunk *dchunks,
+ struct virtchnl2_queue_reg_chunk *schunks,
+ u16 num_chunks)
+{
+ u16 i;
+
+ for (i = 0; i < num_chunks; i++) {
+ dchunks[i].type = schunks[i].type;
+ dchunks[i].start_queue_id = schunks[i].start_queue_id;
+ dchunks[i].num_queues = schunks[i].num_queues;
+ }
+}
+
+/**
+ * iecm_send_delete_queues_msg - send delete queues virtchnl message
+ * @vport: Virtual port private data structure
+ *
+ * Will send delete queues virtchnl message. Return 0 on success, negative on
+ * failure.
+ */
+int iecm_send_delete_queues_msg(struct iecm_vport *vport)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_create_vport *vport_params;
+ struct virtchnl2_queue_reg_chunks *chunks;
+ struct virtchnl2_del_ena_dis_queues *eq;
+ int buf_size, err;
+ u16 num_chunks;
+
+ if (vport->adapter->config_data.req_qs_chunks) {
+ struct virtchnl2_add_queues *vc_aq =
+ (struct virtchnl2_add_queues *)
+ vport->adapter->config_data.req_qs_chunks;
+ chunks = &vc_aq->chunks;
+ } else {
+ vport_params = (struct virtchnl2_create_vport *)
+ vport->adapter->vport_params_recvd[0];
+ chunks = &vport_params->chunks;
+ }
+
+ num_chunks = le16_to_cpu(chunks->num_chunks);
+ buf_size = sizeof(struct virtchnl2_del_ena_dis_queues) +
+ (sizeof(struct virtchnl2_queue_chunk) *
+ (num_chunks - 1));
+
+ eq = kzalloc(buf_size, GFP_KERNEL);
+ if (!eq)
+ return -ENOMEM;
+
+ eq->vport_id = cpu_to_le32(vport->vport_id);
+ eq->chunks.num_chunks = cpu_to_le16(num_chunks);
+
+ iecm_convert_reg_to_queue_chunks(eq->chunks.chunks, chunks->chunks,
+ num_chunks);
+
+ err = iecm_send_mb_msg(vport->adapter, VIRTCHNL2_OP_DEL_QUEUES,
+ buf_size, (u8 *)eq);
+ if (err)
+ goto error;
+
+ err = iecm_min_wait_for_event(adapter, IECM_VC_DEL_QUEUES,
+ IECM_VC_DEL_QUEUES_ERR);
+error:
+ kfree(eq);
+ return err;
+}
+
+/**
+ * iecm_send_config_queues_msg - Send config queues virtchnl message
+ * @vport: Virtual port private data structure
+ *
+ * Will send config queues virtchnl message. Returns 0 on success, negative on
+ * failure.
+ */
+static int iecm_send_config_queues_msg(struct iecm_vport *vport)
+{
+ int err;
+
+ err = iecm_send_config_tx_queues_msg(vport);
+ if (err)
+ return err;
+
+ return iecm_send_config_rx_queues_msg(vport);
+}
+
+/**
+ * iecm_send_add_queues_msg - Send virtchnl add queues message
+ * @vport: Virtual port private data structure
+ * @num_tx_q: number of transmit queues
+ * @num_complq: number of transmit completion queues
+ * @num_rx_q: number of receive queues
+ * @num_rx_bufq: number of receive buffer queues
+ *
+ * Returns 0 on success, negative on failure.
+ */
+int iecm_send_add_queues_msg(struct iecm_vport *vport, u16 num_tx_q,
+ u16 num_complq, u16 num_rx_q, u16 num_rx_bufq)
+{
+ struct iecm_adapter *adapter = vport->adapter;
+ struct virtchnl2_add_queues aq = {0};
+ struct virtchnl2_add_queues *vc_msg;
+ int size, err;
+
+ vc_msg = (struct virtchnl2_add_queues *)adapter->vc_msg;
+
+ aq.vport_id = cpu_to_le32(vport->vport_id);
+ aq.num_tx_q = cpu_to_le16(num_tx_q);
+ aq.num_tx_complq = cpu_to_le16(num_complq);
+ aq.num_rx_q = cpu_to_le16(num_rx_q);
+ aq.num_rx_bufq = cpu_to_le16(num_rx_bufq);
+
+ err = iecm_send_mb_msg(adapter,
+ VIRTCHNL2_OP_ADD_QUEUES,
+ sizeof(struct virtchnl2_add_queues), (u8 *)&aq);
+ if (err)
+ return err;
+
+ err = iecm_wait_for_event(adapter, IECM_VC_ADD_QUEUES,
+ IECM_VC_ADD_QUEUES_ERR);
+ if (err)
+ return err;
+
+ kfree(adapter->config_data.req_qs_chunks);
+ adapter->config_data.req_qs_chunks = NULL;
+
+ /* compare vc_msg num queues with vport num queues */
+ if (le16_to_cpu(vc_msg->num_tx_q) != num_tx_q ||
+ le16_to_cpu(vc_msg->num_rx_q) != num_rx_q ||
+ le16_to_cpu(vc_msg->num_tx_complq) != num_complq ||
+ le16_to_cpu(vc_msg->num_rx_bufq) != num_rx_bufq) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ size = sizeof(struct virtchnl2_add_queues) +
+ ((le16_to_cpu(vc_msg->chunks.num_chunks) - 1) *
+ sizeof(struct virtchnl2_queue_reg_chunk));
+ adapter->config_data.req_qs_chunks =
+ kzalloc(size, GFP_KERNEL);
+ if (!adapter->config_data.req_qs_chunks) {
+ err = -ENOMEM;
+ goto error;
+ }
+ memcpy(adapter->config_data.req_qs_chunks,
+ adapter->vc_msg, size);
+error:
+ clear_bit(__IECM_VC_MSG_PENDING, adapter->flags);
+ return err;
+}
+
/**
* iecm_find_ctlq - Given a type and id, find ctlq info
* @hw: hardware struct
@@ -1217,6 +2219,13 @@ static void iecm_vport_init(struct iecm_vport *vport,
/*Initialize Tx and Rx profiles for Dynamic Interrupt Moderation */
memcpy(vport->rx_itr_profile, rx_itr, IECM_DIM_PROFILE_SLOTS);
memcpy(vport->tx_itr_profile, tx_itr, IECM_DIM_PROFILE_SLOTS);
+
+ iecm_vport_set_hsplit(vport, true);
+
+ iecm_vport_init_num_qs(vport, vport_msg);
+ iecm_vport_calc_num_q_desc(vport);
+ iecm_vport_calc_num_q_groups(vport);
+ iecm_vport_calc_num_q_vec(vport);
}
/**
@@ -1316,8 +2325,82 @@ static int
__iecm_vport_queue_ids_init(struct iecm_vport *vport, u32 *qids,
int num_qids, u32 q_type)
{
- /* stub */
- return 0;
+ struct iecm_queue *q;
+ int i, j, k = 0;
+
+ switch (q_type) {
+ case VIRTCHNL2_QUEUE_TYPE_TX:
+ for (i = 0; i < vport->num_txq_grp; i++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+
+ for (j = 0; j < tx_qgrp->num_txq; j++) {
+ if (k < num_qids) {
+ tx_qgrp->txqs[j]->q_id = qids[k];
+ tx_qgrp->txqs[j]->q_type =
+ VIRTCHNL2_QUEUE_TYPE_TX;
+ k++;
+ } else {
+ break;
+ }
+ }
+ }
+ break;
+ case VIRTCHNL2_QUEUE_TYPE_RX:
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+ int num_rxq;
+
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ num_rxq = rx_qgrp->splitq.num_rxq_sets;
+ else
+ num_rxq = rx_qgrp->singleq.num_rxq;
+
+ for (j = 0; j < num_rxq && k < num_qids; j++, k++) {
+ if (iecm_is_queue_model_split(vport->rxq_model))
+ q = &rx_qgrp->splitq.rxq_sets[j]->rxq;
+ else
+ q = rx_qgrp->singleq.rxqs[j];
+ q->q_id = qids[k];
+ q->q_type = VIRTCHNL2_QUEUE_TYPE_RX;
+ }
+ }
+ break;
+ case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:
+ for (i = 0; i < vport->num_txq_grp; i++) {
+ struct iecm_txq_group *tx_qgrp = &vport->txq_grps[i];
+
+ if (k < num_qids) {
+ tx_qgrp->complq->q_id = qids[k];
+ tx_qgrp->complq->q_type =
+ VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
+ k++;
+ } else {
+ break;
+ }
+ }
+ break;
+ case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:
+ for (i = 0; i < vport->num_rxq_grp; i++) {
+ struct iecm_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+
+ for (j = 0; j < vport->num_bufqs_per_qgrp; j++) {
+ if (k < num_qids) {
+ q = &rx_qgrp->splitq.bufq_sets[j].bufq;
+ q->q_id = qids[k];
+ q->q_type =
+ VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
+ k++;
+ } else {
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return k;
}
/**
@@ -1425,6 +2508,20 @@ static bool iecm_is_capability_ena(struct iecm_adapter *adapter, bool all,
return !!(*cap_field & flag);
}
+/**
+ * iecm_get_reserved_vectors - Default implementation to get reserved vectors
+ * @adapter: Private data struct
+ *
+ * Return number of vectors reserved
+ */
+static u16 iecm_get_reserved_vectors(struct iecm_adapter *adapter)
+{
+ struct virtchnl2_get_capabilities *caps;
+
+ caps = (struct virtchnl2_get_capabilities *)adapter->caps;
+ return le16_to_cpu(caps->num_allocated_vectors);
+}
+
/**
* iecm_vc_ops_init - Initialize virtchnl common api
* @adapter: Driver specific private structure
@@ -1441,16 +2538,16 @@ void iecm_vc_ops_init(struct iecm_adapter *adapter)
vc_ops->vport_queue_ids_init = iecm_vport_queue_ids_init;
vc_ops->get_caps = iecm_send_get_caps_msg;
vc_ops->is_cap_ena = iecm_is_capability_ena;
- vc_ops->get_reserved_vecs = NULL;
- vc_ops->config_queues = NULL;
- vc_ops->enable_queues = NULL;
- vc_ops->disable_queues = NULL;
- vc_ops->add_queues = NULL;
- vc_ops->delete_queues = NULL;
- vc_ops->irq_map_unmap = NULL;
- vc_ops->enable_vport = NULL;
- vc_ops->disable_vport = NULL;
- vc_ops->destroy_vport = NULL;
+ vc_ops->get_reserved_vecs = iecm_get_reserved_vectors;
+ vc_ops->config_queues = iecm_send_config_queues_msg;
+ vc_ops->enable_queues = iecm_send_enable_queues_msg;
+ vc_ops->disable_queues = iecm_send_disable_queues_msg;
+ vc_ops->add_queues = iecm_send_add_queues_msg;
+ vc_ops->delete_queues = iecm_send_delete_queues_msg;
+ vc_ops->irq_map_unmap = iecm_send_map_unmap_queue_vector_msg;
+ vc_ops->enable_vport = iecm_send_enable_vport_msg;
+ vc_ops->disable_vport = iecm_send_disable_vport_msg;
+ vc_ops->destroy_vport = iecm_send_destroy_vport_msg;
vc_ops->get_ptype = NULL;
vc_ops->get_set_rss_key = NULL;
vc_ops->get_set_rss_lut = NULL;
diff --git a/drivers/net/ethernet/intel/include/iecm.h b/drivers/net/ethernet/intel/include/iecm.h
index 994664dfe419..8dd6272db7d3 100644
--- a/drivers/net/ethernet/intel/include/iecm.h
+++ b/drivers/net/ethernet/intel/include/iecm.h
@@ -432,6 +432,8 @@ struct iecm_adapter {
u16 num_alloc_vport;
u16 next_vport; /* Next free slot in pf->vport[] - 0-based! */
+ u16 max_queue_limit; /* Max number of queues user can request */
+
struct delayed_work init_task; /* delayed init task */
struct workqueue_struct *init_wq;
u32 mb_wait_count;
@@ -510,6 +512,12 @@ static inline bool __iecm_is_cap_ena(struct iecm_adapter *adapter, bool all,
return adapter->dev_ops.vc_ops.is_cap_ena(adapter, all, field, flag);
}
+#define IECM_CAP_HSPLIT (\
+ VIRTCHNL2_CAP_RX_HSPLIT_AT_L2 |\
+ VIRTCHNL2_CAP_RX_HSPLIT_AT_L3 |\
+ VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V4 |\
+ VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V6)
+
/**
* iecm_is_reset_detected - check if we were reset at some point
* @adapter: driver specific private structure
@@ -530,6 +538,8 @@ int iecm_init_dflt_mbx(struct iecm_adapter *adapter);
void iecm_deinit_dflt_mbx(struct iecm_adapter *adapter);
void iecm_vc_ops_init(struct iecm_adapter *adapter);
int iecm_vc_core_init(struct iecm_adapter *adapter, int *vport_id);
+int iecm_get_reg_intr_vecs(struct iecm_vport *vport,
+ struct iecm_vec_regs *reg_vals, int num_vecs);
int iecm_wait_for_event(struct iecm_adapter *adapter,
enum iecm_vport_vc_state state,
enum iecm_vport_vc_state err_check);
@@ -537,6 +547,14 @@ int iecm_min_wait_for_event(struct iecm_adapter *adapter,
enum iecm_vport_vc_state state,
enum iecm_vport_vc_state err_check);
int iecm_send_get_caps_msg(struct iecm_adapter *adapter);
+int iecm_send_delete_queues_msg(struct iecm_vport *vport);
+int iecm_send_add_queues_msg(struct iecm_vport *vport, u16 num_tx_q,
+ u16 num_complq, u16 num_rx_q, u16 num_rx_bufq);
+int iecm_send_config_tx_queues_msg(struct iecm_vport *vport);
+int iecm_send_config_rx_queues_msg(struct iecm_vport *vport);
+int iecm_send_enable_vport_msg(struct iecm_vport *vport);
+int iecm_send_disable_vport_msg(struct iecm_vport *vport);
+int iecm_send_destroy_vport_msg(struct iecm_vport *vport);
int iecm_vport_params_buf_alloc(struct iecm_adapter *adapter);
void iecm_vport_params_buf_rel(struct iecm_adapter *adapter);
int iecm_get_vec_ids(struct iecm_adapter *adapter,
@@ -546,7 +564,11 @@ int iecm_recv_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
void *msg, int msg_size);
int iecm_send_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
u16 msg_size, u8 *msg);
+void iecm_vport_set_hsplit(struct iecm_vport *vport, bool ena);
+int iecm_send_enable_channels_msg(struct iecm_vport *vport);
+int iecm_send_disable_channels_msg(struct iecm_vport *vport);
int iecm_set_msg_pending(struct iecm_adapter *adapter,
struct iecm_ctlq_msg *ctlq_msg,
enum iecm_vport_vc_state err_enum);
+int iecm_send_map_unmap_queue_vector_msg(struct iecm_vport *vport, bool map);
#endif /* !_IECM_H_ */
diff --git a/drivers/net/ethernet/intel/include/iecm_txrx.h b/drivers/net/ethernet/intel/include/iecm_txrx.h
index e1348011c991..448cae0bf6e7 100644
--- a/drivers/net/ethernet/intel/include/iecm_txrx.h
+++ b/drivers/net/ethernet/intel/include/iecm_txrx.h
@@ -81,6 +81,22 @@
#define IECM_TX_COMPLQ_CLEAN_BUDGET 256
+enum iecm_queue_flags_t {
+ __IECM_Q_GEN_CHK,
+ __IECM_RFLQ_GEN_CHK,
+ __IECM_Q_FLOW_SCH_EN,
+ __IECM_Q_ETF_EN,
+ __IECM_Q_SW_MARKER,
+ __IECM_Q_VLAN_TAG_LOC_L2TAG1,
+ __IECM_Q_VLAN_TAG_LOC_L2TAG2,
+ __IECM_Q_FLAGS_NBITS,
+};
+
+struct iecm_vec_regs {
+ u32 dyn_ctl_reg;
+ u32 itrn_reg;
+};
+
struct iecm_intr_reg {
u32 dyn_ctl;
u32 dyn_ctl_intena_m;
@@ -122,6 +138,186 @@ struct iecm_q_vector {
char name[IECM_INT_NAME_STR_LEN];
};
+struct iecm_rx_queue_stats {
+ u64 packets;
+ u64 bytes;
+ u64 rsc_pkts;
+};
+
+struct iecm_tx_queue_stats {
+ u64 packets;
+ u64 bytes;
+ u64 lso_pkts;
+};
+
+union iecm_queue_stats {
+ struct iecm_rx_queue_stats rx;
+ struct iecm_tx_queue_stats tx;
+};
+
+/* queue associated with a vport */
+struct iecm_queue {
+ struct device *dev; /* Used for DMA mapping */
+ struct iecm_vport *vport; /* Backreference to associated vport */
+ union {
+ struct iecm_txq_group *txq_grp;
+ struct iecm_rxq_group *rxq_grp;
+ };
+ /* bufq: Used as group id, either 0 or 1, on clean Buf Q uses this
+ * index to determine which group of refill queues to clean.
+ * Bufqs are use in splitq only.
+ * txq: Index to map between Tx Q group and hot path Tx ptrs stored in
+ * vport. Used in both single Q/split Q
+ * rxq: Index to total rxq across groups, used for skb reporting
+ */
+ u16 idx;
+ /* Used for both Q models single and split. In split Q model relevant
+ * only to Tx Q and Rx Q
+ */
+ u8 __iomem *tail;
+ /* Used in both single and split Q. In single Q, Tx Q uses tx_buf and
+ * Rx Q uses rx_buf. In split Q, Tx Q uses tx_buf, Rx Q uses skb, and
+ * Buf Q uses rx_buf.
+ */
+ union {
+ struct iecm_tx_buf *tx_buf;
+ struct {
+ struct iecm_rx_buf *buf;
+ struct iecm_dma_mem **hdr_buf;
+ } rx_buf;
+ struct sk_buff *skb;
+ };
+ u16 q_type;
+ /* Queue id(Tx/Tx compl/Rx/Bufq) */
+ u32 q_id;
+ u16 desc_count; /* Number of descriptors */
+
+ /* Relevant in both split & single Tx Q & Buf Q*/
+ u16 next_to_use;
+ /* In split q model only relevant for Tx Compl Q and Rx Q */
+ u16 next_to_clean; /* used in interrupt processing */
+ /* Used only for Rx. In split Q model only relevant to Rx Q */
+ u16 next_to_alloc;
+ /* Generation bit check stored, as HW flips the bit at Queue end */
+ DECLARE_BITMAP(flags, __IECM_Q_FLAGS_NBITS);
+
+ union iecm_queue_stats q_stats;
+ struct u64_stats_sync stats_sync;
+
+ bool rx_hsplit_en;
+
+ u16 rx_hbuf_size; /* Header buffer size */
+ u16 rx_buf_size;
+ u16 rx_max_pkt_size;
+ u16 rx_buf_stride;
+ u8 rx_buffer_low_watermark;
+ u64 rxdids;
+ /* Used for both Q models single and split. In split Q model relavant
+ * only to Tx compl Q and Rx compl Q
+ */
+ struct iecm_q_vector *q_vector; /* Backreference to associated vector */
+ unsigned int size; /* length of descriptor ring in bytes */
+ dma_addr_t dma; /* physical address of ring */
+ void *desc_ring; /* Descriptor ring memory */
+
+ u16 tx_buf_key; /* 16 bit unique "identifier" (index)
+ * to be used as the completion tag when
+ * queue is using flow based scheduling
+ */
+ u16 tx_max_bufs; /* Max buffers that can be transmitted
+ * with scatter-gather
+ */
+ DECLARE_HASHTABLE(sched_buf_hash, 12);
+} ____cacheline_internodealigned_in_smp;
+
+/* Software queues are used in splitq mode to manage buffers between rxq
+ * producer and the bufq consumer. These are required in order to maintain a
+ * lockless buffer management system and are strictly software only constructs.
+ */
+struct iecm_sw_queue {
+ u16 next_to_clean ____cacheline_aligned_in_smp;
+ u16 next_to_alloc ____cacheline_aligned_in_smp;
+ u16 next_to_use ____cacheline_aligned_in_smp;
+ DECLARE_BITMAP(flags, __IECM_Q_FLAGS_NBITS)
+ ____cacheline_aligned_in_smp;
+ u16 *ring ____cacheline_aligned_in_smp;
+ u16 desc_count;
+ u16 buf_size;
+ struct device *dev;
+} ____cacheline_internodealigned_in_smp;
+
+/* Splitq only. iecm_rxq_set associates an rxq with at an array of refillqs.
+ * Each rxq needs a refillq to return used buffers back to the respective bufq.
+ * Bufqs then clean these refillqs for buffers to give to hardware.
+ */
+struct iecm_rxq_set {
+ struct iecm_queue rxq;
+ /* refillqs assoc with bufqX mapped to this rxq */
+ struct iecm_sw_queue *refillq0;
+ struct iecm_sw_queue *refillq1;
+};
+
+/* Splitq only. iecm_bufq_set associates a bufq to an array of refillqs.
+ * In this bufq_set, there will be one refillq for each rxq in this rxq_group.
+ * Used buffers received by rxqs will be put on refillqs which bufqs will
+ * clean to return new buffers back to hardware.
+ *
+ * Buffers needed by some number of rxqs associated in this rxq_group are
+ * managed by at most two bufqs (depending on performance configuration).
+ */
+struct iecm_bufq_set {
+ struct iecm_queue bufq;
+ /* This is always equal to num_rxq_sets in iecm_rxq_group */
+ int num_refillqs;
+ struct iecm_sw_queue *refillqs;
+};
+
+/* In singleq mode, an rxq_group is simply an array of rxqs. In splitq, a
+ * rxq_group contains all the rxqs, bufqs and refillqs needed to
+ * manage buffers in splitq mode.
+ */
+struct iecm_rxq_group {
+ struct iecm_vport *vport; /* back pointer */
+
+ union {
+ struct {
+ int num_rxq;
+ /* store queue pointers */
+ struct iecm_queue *rxqs[IECM_LARGE_MAX_Q];
+ } singleq;
+ struct {
+ int num_rxq_sets;
+ /* store queue pointers */
+ struct iecm_rxq_set *rxq_sets[IECM_LARGE_MAX_Q];
+ struct iecm_bufq_set *bufq_sets;
+ } splitq;
+ };
+};
+
+/* Between singleq and splitq, a txq_group is largely the same except for the
+ * complq. In splitq a single complq is responsible for handling completions
+ * for some number of txqs associated in this txq_group.
+ */
+struct iecm_txq_group {
+ struct iecm_vport *vport; /* back pointer */
+
+ int num_txq;
+ /* store queue pointers */
+ struct iecm_queue *txqs[IECM_LARGE_MAX_Q];
+
+ /* splitq only */
+ struct iecm_queue *complq;
+};
+
+struct iecm_adapter;
+
+void iecm_vport_init_num_qs(struct iecm_vport *vport,
+ struct virtchnl2_create_vport *vport_msg);
+void iecm_vport_calc_num_q_desc(struct iecm_vport *vport);
+void iecm_vport_calc_total_qs(struct iecm_adapter *adapter,
+ struct virtchnl2_create_vport *vport_msg);
+void iecm_vport_calc_num_q_groups(struct iecm_vport *vport);
+void iecm_vport_calc_num_q_vec(struct iecm_vport *vport);
irqreturn_t
iecm_vport_intr_clean_queues(int __always_unused irq, void *data);
#endif /* !_IECM_TXRX_H_ */
--
2.33.0
next prev parent reply other threads:[~2022-01-28 0:09 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-28 0:09 [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alan Brady
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 01/19] virtchnl: Add new virtchnl2 ops Alan Brady
2022-02-02 22:13 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 02/19] iecm: add basic module init and documentation Alan Brady
2022-01-28 11:56 ` Alexander Lobakin
2022-02-02 22:15 ` Brady, Alan
2022-02-01 19:44 ` Shannon Nelson
2022-02-03 3:08 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 03/19] iecm: add probe and remove Alan Brady
2022-02-01 20:02 ` Shannon Nelson
2022-02-03 3:13 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 04/19] iecm: add api_init and controlq init Alan Brady
2022-01-28 12:09 ` Alexander Lobakin
2022-02-02 22:16 ` Brady, Alan
2022-02-01 21:26 ` Shannon Nelson
2022-02-03 3:24 ` Brady, Alan
2022-02-03 3:40 ` Brady, Alan
2022-02-03 5:26 ` Shannon Nelson
2022-02-03 13:13 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 05/19] iecm: add vport alloc and virtchnl messages Alan Brady
2022-01-28 4:19 ` kernel test robot
2022-01-28 12:39 ` Alexander Lobakin
2022-02-02 22:23 ` Brady, Alan
2022-01-28 12:32 ` Alexander Lobakin
2022-02-02 22:21 ` Brady, Alan
2022-02-03 13:23 ` Alexander Lobakin
2022-01-28 0:09 ` Alan Brady [this message]
2022-01-28 13:03 ` [Intel-wired-lan] [PATCH net-next 06/19] iecm: add virtchnl messages for queues Alexander Lobakin
2022-02-02 22:48 ` Brady, Alan
2022-02-03 10:08 ` Maciej Fijalkowski
2022-02-03 14:09 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 07/19] iecm: finish virtchnl messages Alan Brady
2022-01-28 13:19 ` Alexander Lobakin
2022-02-02 23:06 ` Brady, Alan
2022-02-03 15:05 ` Alexander Lobakin
2022-02-03 15:16 ` Maciej Fijalkowski
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 08/19] iecm: add interrupts and configure netdev Alan Brady
2022-01-28 13:34 ` Alexander Lobakin
2022-02-02 23:17 ` Brady, Alan
2022-02-03 15:55 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 09/19] iecm: alloc vport TX resources Alan Brady
2022-02-02 23:45 ` Brady, Alan
2022-02-03 17:56 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 10/19] iecm: alloc vport RX resources Alan Brady
2022-01-28 14:16 ` Alexander Lobakin
2022-02-03 0:13 ` Brady, Alan
2022-02-03 18:29 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 11/19] iecm: add start_xmit and set_rx_mode Alan Brady
2022-01-28 16:35 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 12/19] iecm: finish netdev_ops Alan Brady
2022-01-28 17:06 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 13/19] iecm: implement splitq napi_poll Alan Brady
2022-01-28 5:21 ` kernel test robot
2022-01-28 17:44 ` Alexander Lobakin
2022-02-03 1:15 ` Brady, Alan
2022-01-28 17:38 ` Alexander Lobakin
2022-02-03 1:07 ` Brady, Alan
2022-02-04 11:50 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 14/19] iecm: implement singleq napi_poll Alan Brady
2022-01-28 17:57 ` Alexander Lobakin
2022-02-03 1:45 ` Brady, Alan
2022-02-03 19:05 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 15/19] iecm: implement ethtool callbacks Alan Brady
2022-01-28 18:13 ` Alexander Lobakin
2022-02-03 2:13 ` Brady, Alan
2022-02-03 19:54 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 16/19] iecm: implement flow director Alan Brady
2022-01-28 19:04 ` Alexander Lobakin
2022-02-03 2:41 ` Brady, Alan
2022-02-04 10:08 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 17/19] iecm: implement cloud filters Alan Brady
2022-01-28 19:38 ` Alexander Lobakin
2022-02-03 2:53 ` Brady, Alan
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 18/19] iecm: add advanced rss Alan Brady
2022-01-28 19:53 ` Alexander Lobakin
2022-02-03 2:55 ` Brady, Alan
2022-02-03 10:46 ` Maciej Fijalkowski
2022-02-04 10:22 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 19/19] idpf: introduce idpf driver Alan Brady
2022-01-28 20:08 ` Alexander Lobakin
2022-02-03 3:07 ` Brady, Alan
2022-02-04 10:35 ` Alexander Lobakin
2022-02-04 12:05 ` [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alexander Lobakin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220128001009.721392-7-alan.brady@intel.com \
--to=alan.brady@intel.com \
--cc=intel-wired-lan@osuosl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox