@@ -2229,83 +2229,6 @@ int idpf_send_add_queues_msg(struct idpf_adapter *adapter,
return err;
}
-/**
- * idpf_create_vectors_info - Save vectors information from firmware
- * @info: parsed information is stored here
- * @caps: virtchannel capabilities
- * @vectors: vector information from firmware to be parsed
- * @num_vectors: number of vectors
- *
- * Returns 0 on success, negative on failure.
- */
-static int idpf_create_vectors_info(struct libie_irq_info *info,
- const struct virtchnl2_get_capabilities *caps,
- const struct virtchnl2_alloc_vectors *vectors,
- const u16 num_vectors)
-{
- const struct virtchnl2_vector_chunks *chunks = &vectors->vchunks;
- int all_vectors = num_vectors + IDPF_MBX_Q_VEC;
- struct libie_hw_vector *vector;
- int reg_cnt;
-
- if (le16_to_cpu(vectors->num_vectors) < num_vectors)
- return -EINVAL;
-
- info->vectors = kzalloc_objs(*info->vectors, all_vectors);
- if (!info->vectors)
- return -ENOMEM;
- /* Mailbox irq information are stored in different places. Fill index 0
- * of our vectors info with capabilities and rest with information
- * from vector chunks.
- */
- vector = &info->vectors[0];
- vector->idx = le16_to_cpu(caps->mailbox_vector_id);
- vector->regs.dyn_ctl = le32_to_cpu(caps->mailbox_dyn_ctl);
- reg_cnt = IDPF_MBX_Q_VEC;
-
- for (int i = 0; i < le16_to_cpu(chunks->num_vchunks); i++) {
- const struct virtchnl2_vector_chunk *chunk = &chunks->vchunks[i];
- u32 dyn_spacing, itrn_spacing;
- struct libie_vec_regs reg_val;
- u16 vec_id;
-
- reg_val.dyn_ctl = le32_to_cpu(chunk->dynctl_reg_start);
- reg_val.itrn = le32_to_cpu(chunk->itrn_reg_start);
- reg_val.itrn_index_spacing =
- le32_to_cpu(chunk->itrn_index_spacing);
-
- dyn_spacing = le32_to_cpu(chunk->dynctl_reg_spacing);
- itrn_spacing = le32_to_cpu(chunk->itrn_reg_spacing);
- vec_id = le16_to_cpu(chunk->start_vector_id);
-
- for (int j = 0; j < le16_to_cpu(chunk->num_vectors); j++) {
- if (reg_cnt >= all_vectors)
- break;
-
- vector = &info->vectors[reg_cnt];
-
- vector->regs = reg_val;
- vector->idx = vec_id;
-
- reg_val.dyn_ctl += dyn_spacing;
- reg_val.itrn += itrn_spacing;
-
- vec_id += 1;
- reg_cnt += 1;
- }
- }
-
- if (reg_cnt != all_vectors) {
- kfree(info->vectors);
- info->vectors = NULL;
- return -EINVAL;
- }
-
- info->num = num_vectors + IDPF_MBX_Q_VEC;
-
- return 0;
-}
-
/**
* idpf_send_alloc_vectors_msg - Send virtchnl alloc vectors message
* @adapter: Driver specific private structure
@@ -2350,8 +2273,8 @@ int idpf_send_alloc_vectors_msg(struct idpf_adapter *adapter, u16 num_vectors)
goto free_rx_buf;
}
- err = idpf_create_vectors_info(&adapter->irq_info, &adapter->caps,
- rcvd_vec, num_vectors);
+ err = libie_irq_create_info(&adapter->irq_info, &adapter->caps,
+ rcvd_vec, num_vectors);
if (err)
idpf_send_dealloc_vectors_msg(adapter);
@@ -2378,9 +2301,7 @@ int idpf_send_dealloc_vectors_msg(struct idpf_adapter *adapter)
int buf_size, err;
/* dealloc vectors can fail, but irq_info still needs to be cleaned */
- kfree(adapter->irq_info.vectors);
- adapter->irq_info.vectors = NULL;
- adapter->irq_info.num = 0;
+ libie_irq_destroy_info(&adapter->irq_info);
buf_size = struct_size(&ac->vchunks, vchunks,
le16_to_cpu(ac->vchunks.num_vchunks));
@@ -2,6 +2,7 @@
/* Copyright (C) 2025 Intel Corporation */
#include <linux/net/intel/libie/irq.h>
+#include <linux/net/intel/virtchnl2.h>
/**
* libie_irq_init - init irq for whole device
@@ -250,6 +251,97 @@ int libie_irq_reserve(struct libie_irq *irq)
}
EXPORT_SYMBOL_NS_GPL(libie_irq_reserve, "LIBIE_IRQ");
+/**
+ * libie_irq_create_info - Save vectors information from firmware
+ * @info: parsed information is stored here
+ * @caps: virtchannel capabilities
+ * @vectors: vector information from firmware to be parsed
+ * @num_vectors: number of vectors
+ *
+ * Return: 0 on success, negative on failure.
+ */
+int libie_irq_create_info(struct libie_irq_info *info,
+ const struct virtchnl2_get_capabilities *caps,
+ const struct virtchnl2_alloc_vectors *vectors,
+ const u16 num_vectors)
+{
+ const struct virtchnl2_vector_chunks *chunks = &vectors->vchunks;
+ struct libie_hw_vector *vector;
+ const int mb_vectors = 1;
+ int reg_cnt, all_vectors;
+
+ if (le16_to_cpu(vectors->num_vectors) < num_vectors)
+ return -EINVAL;
+
+ all_vectors = num_vectors + mb_vectors;
+ info->vectors = kzalloc_objs(*info->vectors, all_vectors);
+ if (!info->vectors)
+ return -ENOMEM;
+ /* Mailbox irq information are stored in different places. Fill index 0
+ * of our vectors info with capabilities and rest with information
+ * from vector chunks.
+ */
+ vector = &info->vectors[0];
+ vector->idx = le16_to_cpu(caps->mailbox_vector_id);
+ vector->regs.dyn_ctl = le32_to_cpu(caps->mailbox_dyn_ctl);
+ reg_cnt = mb_vectors;
+
+ for (int i = 0; i < le16_to_cpu(chunks->num_vchunks); i++) {
+ const struct virtchnl2_vector_chunk *chunk = &chunks->vchunks[i];
+ u32 dyn_spacing, itrn_spacing;
+ struct libie_vec_regs reg_val;
+ u16 vec_id;
+
+ reg_val.dyn_ctl = le32_to_cpu(chunk->dynctl_reg_start);
+ reg_val.itrn = le32_to_cpu(chunk->itrn_reg_start);
+ reg_val.itrn_index_spacing =
+ le32_to_cpu(chunk->itrn_index_spacing);
+
+ dyn_spacing = le32_to_cpu(chunk->dynctl_reg_spacing);
+ itrn_spacing = le32_to_cpu(chunk->itrn_reg_spacing);
+ vec_id = le16_to_cpu(chunk->start_vector_id);
+
+ for (int j = 0; j < le16_to_cpu(chunk->num_vectors); j++) {
+ if (reg_cnt >= all_vectors)
+ break;
+
+ vector = &info->vectors[reg_cnt];
+
+ vector->regs = reg_val;
+ vector->idx = vec_id;
+
+ reg_val.dyn_ctl += dyn_spacing;
+ reg_val.itrn += itrn_spacing;
+
+ vec_id += 1;
+ reg_cnt += 1;
+ }
+ }
+
+ if (reg_cnt != all_vectors) {
+ kfree(info->vectors);
+ info->vectors = NULL;
+ return -EINVAL;
+ }
+
+ info->num = all_vectors;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(libie_irq_create_info, "LIBIE_IRQ");
+
+/**
+ * libie_irq_destroy_info - free memory allocated during building irq_info
+ * @info: libie_irq_info struct to be freed
+ */
+void libie_irq_destroy_info(struct libie_irq_info *info)
+{
+ kfree(info->vectors);
+ info->vectors = NULL;
+ info->num = 0;
+}
+EXPORT_SYMBOL_NS_GPL(libie_irq_destroy_info, "LIBIE_IRQ");
+
/* Module */
MODULE_DESCRIPTION("Helper functions for managing MSI-X in driver");
@@ -105,5 +105,14 @@ struct msi_map libie_irq_alloc(struct libie_irq *irq, enum libie_irq_type type);
void libie_irq_free(struct libie_irq *irq, struct msi_map map);
int libie_irq_reserve(struct libie_irq *irq);
void libie_put_irq(struct libie_irq *irq, unsigned int index);
+/* IPU specific functions. */
+struct virtchnl2_get_capabilities;
+struct virtchnl2_alloc_vectors;
+
+void libie_irq_destroy_info(struct libie_irq_info *info);
+int libie_irq_create_info(struct libie_irq_info *info,
+ const struct virtchnl2_get_capabilities *caps,
+ const struct virtchnl2_alloc_vectors *vectors,
+ const u16 num_vectors);
#endif /* __LIBIE_IRQ_H */