Commit 2d44c6f6 authored by Ofir Bitton's avatar Ofir Bitton Committed by Oded Gabbay

habanalabs: enable all IRQs for user interrupt support

In order to support user interrupts, driver must enable all MSI-X
interrupts for any case user will trigger them. We differentiate
between a valid user interrupt and a non valid one.
Signed-off-by: default avatarOfir Bitton <obitton@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 5d6a198f
...@@ -1251,7 +1251,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset, ...@@ -1251,7 +1251,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
*/ */
int hl_device_init(struct hl_device *hdev, struct class *hclass) int hl_device_init(struct hl_device *hdev, struct class *hclass)
{ {
int i, rc, cq_cnt, cq_ready_cnt; int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
char *name; char *name;
bool add_cdev_sysfs_on_err = false; bool add_cdev_sysfs_on_err = false;
...@@ -1340,6 +1340,19 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) ...@@ -1340,6 +1340,19 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
hdev->completion_queue[i].cq_idx = i; hdev->completion_queue[i].cq_idx = i;
} }
user_interrupt_cnt = hdev->asic_prop.user_interrupt_count;
if (user_interrupt_cnt) {
hdev->user_interrupt = kcalloc(user_interrupt_cnt,
sizeof(*hdev->user_interrupt),
GFP_KERNEL);
if (!hdev->user_interrupt) {
rc = -ENOMEM;
goto cq_fini;
}
}
/* /*
* Initialize the event queue. Must be done before hw_init, * Initialize the event queue. Must be done before hw_init,
* because there the address of the event queue is being * because there the address of the event queue is being
...@@ -1348,7 +1361,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) ...@@ -1348,7 +1361,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
rc = hl_eq_init(hdev, &hdev->event_queue); rc = hl_eq_init(hdev, &hdev->event_queue);
if (rc) { if (rc) {
dev_err(hdev->dev, "failed to initialize event queue\n"); dev_err(hdev->dev, "failed to initialize event queue\n");
goto cq_fini; goto user_interrupts_fini;
} }
/* MMU S/W must be initialized before kernel context is created */ /* MMU S/W must be initialized before kernel context is created */
...@@ -1486,6 +1499,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) ...@@ -1486,6 +1499,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
hl_mmu_fini(hdev); hl_mmu_fini(hdev);
eq_fini: eq_fini:
hl_eq_fini(hdev, &hdev->event_queue); hl_eq_fini(hdev, &hdev->event_queue);
user_interrupts_fini:
kfree(hdev->user_interrupt);
cq_fini: cq_fini:
for (i = 0 ; i < cq_ready_cnt ; i++) for (i = 0 ; i < cq_ready_cnt ; i++)
hl_cq_fini(hdev, &hdev->completion_queue[i]); hl_cq_fini(hdev, &hdev->completion_queue[i]);
...@@ -1625,6 +1640,7 @@ void hl_device_fini(struct hl_device *hdev) ...@@ -1625,6 +1640,7 @@ void hl_device_fini(struct hl_device *hdev)
for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
hl_cq_fini(hdev, &hdev->completion_queue[i]); hl_cq_fini(hdev, &hdev->completion_queue[i]);
kfree(hdev->completion_queue); kfree(hdev->completion_queue);
kfree(hdev->user_interrupt);
hl_hw_queues_destroy(hdev); hl_hw_queues_destroy(hdev);
......
...@@ -412,6 +412,7 @@ struct hl_mmu_properties { ...@@ -412,6 +412,7 @@ struct hl_mmu_properties {
* @first_available_user_msix_interrupt: first available msix interrupt * @first_available_user_msix_interrupt: first available msix interrupt
* reserved for the user * reserved for the user
* @first_available_cq: first available CQ for the user. * @first_available_cq: first available CQ for the user.
* @user_interrupt_count: number of user interrupts.
* @tpc_enabled_mask: which TPCs are enabled. * @tpc_enabled_mask: which TPCs are enabled.
* @completion_queues_count: number of completion queues. * @completion_queues_count: number of completion queues.
* @fw_security_disabled: true if security measures are disabled in firmware, * @fw_security_disabled: true if security measures are disabled in firmware,
...@@ -475,6 +476,7 @@ struct asic_fixed_properties { ...@@ -475,6 +476,7 @@ struct asic_fixed_properties {
u16 first_available_user_mon[HL_MAX_DCORES]; u16 first_available_user_mon[HL_MAX_DCORES];
u16 first_available_user_msix_interrupt; u16 first_available_user_msix_interrupt;
u16 first_available_cq[HL_MAX_DCORES]; u16 first_available_cq[HL_MAX_DCORES];
u16 user_interrupt_count;
u8 tpc_enabled_mask; u8 tpc_enabled_mask;
u8 completion_queues_count; u8 completion_queues_count;
u8 fw_security_disabled; u8 fw_security_disabled;
...@@ -689,6 +691,16 @@ struct hl_cq { ...@@ -689,6 +691,16 @@ struct hl_cq {
atomic_t free_slots_cnt; atomic_t free_slots_cnt;
}; };
/**
* struct hl_user_interrupt - holds user interrupt information
* @hdev: pointer to the device structure
* @interrupt_id: msix interrupt id
*/
struct hl_user_interrupt {
struct hl_device *hdev;
u32 interrupt_id;
};
/** /**
* struct hl_eq - describes the event queue (single one per device) * struct hl_eq - describes the event queue (single one per device)
* @hdev: pointer to the device structure * @hdev: pointer to the device structure
...@@ -1821,6 +1833,7 @@ struct hl_mmu_funcs { ...@@ -1821,6 +1833,7 @@ struct hl_mmu_funcs {
* @asic_name: ASIC specific name. * @asic_name: ASIC specific name.
* @asic_type: ASIC specific type. * @asic_type: ASIC specific type.
* @completion_queue: array of hl_cq. * @completion_queue: array of hl_cq.
* @user_interrupt: array of hl_user_interrupt.
* @cq_wq: work queues of completion queues for executing work in process * @cq_wq: work queues of completion queues for executing work in process
* context. * context.
* @eq_wq: work queue of event queue for executing work in process context. * @eq_wq: work queue of event queue for executing work in process context.
...@@ -1937,6 +1950,7 @@ struct hl_device { ...@@ -1937,6 +1950,7 @@ struct hl_device {
char status[HL_DEV_STS_MAX][HL_STR_MAX]; char status[HL_DEV_STS_MAX][HL_STR_MAX];
enum hl_asic_type asic_type; enum hl_asic_type asic_type;
struct hl_cq *completion_queue; struct hl_cq *completion_queue;
struct hl_user_interrupt *user_interrupt;
struct workqueue_struct **cq_wq; struct workqueue_struct **cq_wq;
struct workqueue_struct *eq_wq; struct workqueue_struct *eq_wq;
struct hl_ctx *kernel_ctx; struct hl_ctx *kernel_ctx;
...@@ -2158,6 +2172,8 @@ void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q); ...@@ -2158,6 +2172,8 @@ void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q);
void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q); void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q);
irqreturn_t hl_irq_handler_cq(int irq, void *arg); irqreturn_t hl_irq_handler_cq(int irq, void *arg);
irqreturn_t hl_irq_handler_eq(int irq, void *arg); irqreturn_t hl_irq_handler_eq(int irq, void *arg);
irqreturn_t hl_irq_handler_user_cq(int irq, void *arg);
irqreturn_t hl_irq_handler_default(int irq, void *arg);
u32 hl_cq_inc_ptr(u32 ptr); u32 hl_cq_inc_ptr(u32 ptr);
int hl_asid_init(struct hl_device *hdev); int hl_asid_init(struct hl_device *hdev);
......
...@@ -137,6 +137,46 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg) ...@@ -137,6 +137,46 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/**
* hl_irq_handler_user_cq - irq handler for user completion queues
*
* @irq: irq number
* @arg: pointer to user interrupt structure
*
*/
irqreturn_t hl_irq_handler_user_cq(int irq, void *arg)
{
struct hl_user_interrupt *user_cq = arg;
struct hl_device *hdev = user_cq->hdev;
u32 interrupt_id = user_cq->interrupt_id;
dev_info(hdev->dev,
"got user completion interrupt id %u",
interrupt_id);
return IRQ_HANDLED;
}
/**
* hl_irq_handler_default - default irq handler
*
* @irq: irq number
* @arg: pointer to user interrupt structure
*
*/
irqreturn_t hl_irq_handler_default(int irq, void *arg)
{
struct hl_user_interrupt *user_interrupt = arg;
struct hl_device *hdev = user_interrupt->hdev;
u32 interrupt_id = user_interrupt->interrupt_id;
dev_err(hdev->dev,
"got invalid user interrupt %u",
interrupt_id);
return IRQ_HANDLED;
}
/** /**
* hl_irq_handler_eq - irq handler for event queue * hl_irq_handler_eq - irq handler for event queue
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment