From edef8e6b0dd9d33d13058ef5697e77d1b4e73d24 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 16 Dec 2020 22:41:48 +0100 Subject: [PATCH] drivers/interrupt_controller: Expanding VT-D public API Adding a way to pre-install the irg/vector on an irte and a way to get an irte based on irq/vector. Signed-off-by: Tomasz Bursztyka --- drivers/interrupt_controller/intc_intel_vtd.c | 88 ++++++++++- drivers/interrupt_controller/intc_intel_vtd.h | 3 + .../drivers/interrupt_controller/intel_vtd.h | 139 ++++++++++++++++++ 3 files changed, 229 insertions(+), 1 deletion(-) diff --git a/drivers/interrupt_controller/intc_intel_vtd.c b/drivers/interrupt_controller/intc_intel_vtd.c index 4012f5def2b..60082f9d8ad 100644 --- a/drivers/interrupt_controller/intc_intel_vtd.c +++ b/drivers/interrupt_controller/intc_intel_vtd.c @@ -104,6 +104,82 @@ static int vtd_ictl_remap(const struct device *dev, return 0; } +static int vtd_ictl_set_irte_vector(const struct device *dev, + uint8_t irte_idx, + uint16_t vector) +{ + struct vtd_ictl_data *data = dev->data; + + data->vectors[irte_idx] = vector; + + return 0; +} + +static int vtd_ictl_get_irte_by_vector(const struct device *dev, + uint16_t vector) +{ + struct vtd_ictl_data *data = dev->data; + int irte_idx; + + for (irte_idx = 0; irte_idx < IRTE_NUM; irte_idx++) { + if (data->vectors[irte_idx] == vector) { + return irte_idx; + } + } + + return -EINVAL; +} + +static uint16_t vtd_ictl_get_irte_vector(const struct device *dev, + uint8_t irte_idx) +{ + struct vtd_ictl_data *data = dev->data; + + return data->vectors[irte_idx]; +} + +static int vtd_ictl_set_irte_irq(const struct device *dev, + uint8_t irte_idx, + unsigned int irq) +{ + struct vtd_ictl_data *data = dev->data; + + data->irqs[irte_idx] = irq; + + return 0; +} + +static int vtd_ictl_get_irte_by_irq(const struct device *dev, + unsigned int irq) +{ + struct vtd_ictl_data *data = dev->data; + int irte_idx; + + for (irte_idx = 0; irte_idx < IRTE_NUM; irte_idx++) { + if (data->irqs[irte_idx] == irq) { + return irte_idx; + } + } + + return -EINVAL; +} + +static void vtd_ictl_set_irte_msi(const struct device *dev, + uint8_t irte_idx, bool msi) +{ + struct vtd_ictl_data *data = dev->data; + + data->msi[irte_idx] = msi; +} + +static bool vtd_ictl_irte_is_msi(const struct device *dev, + uint8_t irte_idx) +{ + struct vtd_ictl_data *data = dev->data; + + return data->msi[irte_idx]; +} + static int vtd_ictl_init(const struct device *dev) { struct vtd_ictl_data *data = dev->data; @@ -142,9 +218,19 @@ static const struct vtd_driver_api vtd_api = { .allocate_entries = vtd_ictl_allocate_entries, .remap_msi = vtd_ictl_remap_msi, .remap = vtd_ictl_remap, + .set_irte_vector = vtd_ictl_set_irte_vector, + .get_irte_by_vector = vtd_ictl_get_irte_by_vector, + .get_irte_vector = vtd_ictl_get_irte_vector, + .set_irte_irq = vtd_ictl_set_irte_irq, + .get_irte_by_irq = vtd_ictl_get_irte_by_irq, + .set_irte_msi = vtd_ictl_set_irte_msi, + .irte_is_msi = vtd_ictl_irte_is_msi }; -static struct vtd_ictl_data vtd_ictl_data_0; +static struct vtd_ictl_data vtd_ictl_data_0 = { + .irqs = { -EINVAL }, + .vectors = { -EINVAL }, +}; static const struct vtd_ictl_cfg vtd_ictl_cfg_0 = { DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)), diff --git a/drivers/interrupt_controller/intc_intel_vtd.h b/drivers/interrupt_controller/intc_intel_vtd.h index 353d8283f0c..894d7dac48d 100644 --- a/drivers/interrupt_controller/intc_intel_vtd.h +++ b/drivers/interrupt_controller/intc_intel_vtd.h @@ -48,6 +48,9 @@ struct vtd_irte { struct vtd_ictl_data { struct vtd_irte irte[IRTE_NUM]; + int irqs[IRTE_NUM]; + int vectors[IRTE_NUM]; + bool msi[IRTE_NUM]; int irte_num_used; }; diff --git a/include/drivers/interrupt_controller/intel_vtd.h b/include/drivers/interrupt_controller/intel_vtd.h index a2d043e8c02..d7db136603d 100644 --- a/include/drivers/interrupt_controller/intel_vtd.h +++ b/include/drivers/interrupt_controller/intel_vtd.h @@ -20,10 +20,41 @@ typedef int (*vtd_remap_f)(const struct device *dev, uint16_t vector, uint32_t flags); +typedef int (*vtd_set_irte_vector_f)(const struct device *dev, + uint8_t irte_idx, + uint16_t vector); + +typedef int (*vtd_get_irte_by_vector_f)(const struct device *dev, + uint16_t vector); + +typedef uint16_t (*vtd_get_irte_vector_f)(const struct device *dev, + uint8_t irte_idx); + +typedef int (*vtd_set_irte_irq_f)(const struct device *dev, + uint8_t irte_idx, + unsigned int irq); + +typedef int (*vtd_get_irte_by_irq_f)(const struct device *dev, + unsigned int irq); + +typedef void (*vtd_set_irte_msi_f)(const struct device *dev, + uint8_t irte_idx, + bool msi); + +typedef bool (*vtd_irte_is_msi_f)(const struct device *dev, + uint8_t irte_idx); + struct vtd_driver_api { vtd_alloc_entries_f allocate_entries; vtd_remap_msi_f remap_msi; vtd_remap_f remap; + vtd_set_irte_vector_f set_irte_vector; + vtd_get_irte_by_vector_f get_irte_by_vector; + vtd_get_irte_vector_f get_irte_vector; + vtd_set_irte_irq_f set_irte_irq; + vtd_get_irte_by_irq_f get_irte_by_irq; + vtd_set_irte_msi_f set_irte_msi; + vtd_irte_is_msi_f irte_is_msi; }; /** @@ -85,5 +116,113 @@ static inline int vtd_remap(const struct device *dev, return api->remap(dev, irte_idx, vector, flags); } +/** + * @brief Set the vector on the allocated irte + * + * @param dev Pointer to the device structure for the driver instance + * @param irte_idx A previoulsy allocated irte entry index number + * @param vector An allocated interrupt vector + * + * @return 0, a negative errno otherwise + */ +static inline int vtd_set_irte_vector(const struct device *dev, + uint8_t irte_idx, + uint16_t vector) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->set_irte_vector(dev, irte_idx, vector); +} + +/** + * @brief Get the irte allocated for the given vector + * + * @param dev Pointer to the device structure for the driver instance + * @param vector An allocated interrupt vector + * + * @return 0 or positive value on success, a negative errno otherwise + */ +static inline int vtd_get_irte_by_vector(const struct device *dev, + uint16_t vector) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->get_irte_by_vector(dev, vector); +} + +/** + * @brief Get the vector given to the IRTE + * + * @param dev Pointer to the device structure for the driver instance + * @param irte_idx A previoulsy allocated irte entry index number + * + * @return the vector set to this IRTE + */ +static inline uint16_t vtd_get_irte_vector(const struct device *dev, + uint8_t irte_idx) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->get_irte_vector(dev, irte_idx); +} + +/** + * @brief Set the irq on the allocated irte + * + * @param dev Pointer to the device structure for the driver instance + * @param irte_idx A previoulsy allocated irte entry index number + * @param irq A valid IRQ number + * + * @return 0, a negative errno otherwise + */ +static inline int vtd_set_irte_irq(const struct device *dev, + uint8_t irte_idx, + unsigned int irq) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->set_irte_irq(dev, irte_idx, irq); +} + +/** + * @brief Get the irte allocated for the given irq + * + * @param dev Pointer to the device structure for the driver instance + * @param irq A valid IRQ number + * + * @return 0 or positive value on success, a negative errno otherwise + */ +static inline int vtd_get_irte_by_irq(const struct device *dev, + unsigned int irq) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->get_irte_by_irq(dev, irq); +} + +static inline void vtd_set_irte_msi(const struct device *dev, + uint8_t irte_idx, + bool msi) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->set_irte_msi(dev, irte_idx, msi); +} + +static inline bool vtd_irte_is_msi(const struct device *dev, + uint8_t irte_idx) +{ + const struct vtd_driver_api *api = + (const struct vtd_driver_api *)dev->api; + + return api->irte_is_msi(dev, irte_idx); +} + #endif /* ZEPHYR_INCLUDE_DRIVERS_INTEL_VTD_H_ */