diff --git a/arch/risc-v/src/esp32c3/esp_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp_wifi_adapter.c index 30be4f099dc..b95031714a6 100644 --- a/arch/risc-v/src/esp32c3/esp_wifi_adapter.c +++ b/arch/risc-v/src/esp32c3/esp_wifi_adapter.c @@ -558,6 +558,7 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { intr_handle_t handle; + vector_desc_t *desc; int irq = ESP_SOURCE2IRQ(intr_source); esp_err_t err; @@ -569,26 +570,40 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, esprv_int_set_priority(intr_num, intr_prio); esprv_int_set_type(intr_num, INTR_TYPE_LEVEL); - handle = kmm_calloc(1, sizeof(intr_handle_data_t)); - if (handle == NULL) - { - wlerr("Failed to kmm_calloc\n"); - return; - } - - handle->vector_desc = get_desc_for_int(intr_num, cpu_no); - if (handle->vector_desc == NULL) + desc = get_desc_for_int(intr_num, cpu_no); + if (desc == NULL) { wlerr("get_desc_for_int failed\n"); - kmm_free(handle); return; } + /* The Wi-Fi driver calls this on every esp_wifi_start(), not only on + * the first one, and nothing clears the handle in between (see + * clear_intr_wrapper()). Reuse the registered handle: a new one would + * be refused by esp_set_handle() and leaked. + */ + + handle = esp_get_handle(cpu_no, irq); + if (handle == IRQ_UNMAPPED) + { + handle = kmm_calloc(1, sizeof(intr_handle_data_t)); + if (handle == NULL) + { + wlerr("Failed to kmm_calloc\n"); + return; + } + + /* Register the handle - it contains all needed information + * (cpuint, cpu) + */ + + esp_set_handle(cpu_no, irq, handle); + } + + handle->vector_desc = desc; handle->vector_desc->source = intr_source; handle->shared_vector_desc = NULL; - esp_set_handle(cpu_no, irq, handle); - err = esp_intr_set_in_iram(handle, false); if (err != ESP_OK) { diff --git a/arch/risc-v/src/esp32c6/esp_wifi_adapter.c b/arch/risc-v/src/esp32c6/esp_wifi_adapter.c index f770a0f2e2b..c18f7122f37 100644 --- a/arch/risc-v/src/esp32c6/esp_wifi_adapter.c +++ b/arch/risc-v/src/esp32c6/esp_wifi_adapter.c @@ -591,6 +591,7 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { intr_handle_t handle; + vector_desc_t *desc; int irq = ESP_SOURCE2IRQ(intr_source); esp_err_t err; @@ -602,26 +603,40 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, esprv_int_set_priority(intr_num, intr_prio); esprv_int_set_type(intr_num, INTR_TYPE_LEVEL); - handle = kmm_calloc(1, sizeof(intr_handle_data_t)); - if (handle == NULL) - { - wlerr("Failed to kmm_calloc\n"); - return; - } - - handle->vector_desc = get_desc_for_int(intr_num, cpu_no); - if (handle->vector_desc == NULL) + desc = get_desc_for_int(intr_num, cpu_no); + if (desc == NULL) { wlerr("get_desc_for_int failed\n"); - kmm_free(handle); return; } + /* The Wi-Fi driver calls this on every esp_wifi_start(), not only on + * the first one, and nothing clears the handle in between (see + * clear_intr_wrapper()). Reuse the registered handle: a new one would + * be refused by esp_set_handle() and leaked. + */ + + handle = esp_get_handle(cpu_no, irq); + if (handle == IRQ_UNMAPPED) + { + handle = kmm_calloc(1, sizeof(intr_handle_data_t)); + if (handle == NULL) + { + wlerr("Failed to kmm_calloc\n"); + return; + } + + /* Register the handle - it contains all needed information + * (cpuint, cpu) + */ + + esp_set_handle(cpu_no, irq, handle); + } + + handle->vector_desc = desc; handle->vector_desc->source = intr_source; handle->shared_vector_desc = NULL; - esp_set_handle(cpu_no, irq, handle); - err = esp_intr_set_in_iram(handle, false); if (err != ESP_OK) { diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index 2b60394f1d7..0bbf485a303 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -1765,6 +1765,7 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { intr_handle_t handle; + vector_desc_t *desc; int irq = ESP_SOURCE2IRQ(intr_source); esp_err_t err; @@ -1774,28 +1775,40 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num); - handle = kmm_calloc(1, sizeof(intr_handle_data_t)); - if (handle == NULL) - { - wlerr("Failed to kmm_calloc\n"); - return; - } - - handle->vector_desc = get_desc_for_int(intr_num, cpu_no); - if (handle->vector_desc == NULL) + desc = get_desc_for_int(intr_num, cpu_no); + if (desc == NULL) { wlerr("get_desc_for_int failed\n"); - kmm_free(handle); return; } + /* The Wi-Fi driver calls this on every esp_wifi_start(), not only on + * the first one, and nothing clears the handle in between (see + * clear_intr_wrapper()). Reuse the registered handle: a new one would + * be refused by esp_set_handle() and leaked. + */ + + handle = esp_get_handle(cpu_no, irq); + if (handle == IRQ_UNMAPPED) + { + handle = kmm_calloc(1, sizeof(intr_handle_data_t)); + if (handle == NULL) + { + wlerr("Failed to kmm_calloc\n"); + return; + } + + /* Register the handle - it contains all needed information + * (cpuint, cpu) + */ + + esp_set_handle(cpu_no, irq, handle); + } + + handle->vector_desc = desc; handle->vector_desc->source = intr_source; handle->shared_vector_desc = NULL; - /* Register the handle - it contains all needed information (cpuint, cpu) */ - - esp_set_handle(cpu_no, irq, handle); - err = esp_intr_set_in_iram(handle, false); if (err != OK) { diff --git a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c index 58fea3062b2..bc1a44a7a66 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c +++ b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c @@ -1623,6 +1623,7 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { intr_handle_t handle; + vector_desc_t *desc; int irq = ESP_SOURCE2IRQ(intr_source); esp_err_t err; @@ -1632,28 +1633,40 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num); - handle = kmm_calloc(1, sizeof(intr_handle_data_t)); - if (handle == NULL) - { - wlerr("Failed to kmm_calloc\n"); - return; - } - - handle->vector_desc = get_desc_for_int(intr_num, cpu_no); - if (handle->vector_desc == NULL) + desc = get_desc_for_int(intr_num, cpu_no); + if (desc == NULL) { wlerr("get_desc_for_int failed\n"); - kmm_free(handle); return; } + /* The Wi-Fi driver calls this on every esp_wifi_start(), not only on + * the first one, and nothing clears the handle in between (see + * clear_intr_wrapper()). Reuse the registered handle: a new one would + * be refused by esp_set_handle() and leaked. + */ + + handle = esp_get_handle(cpu_no, irq); + if (handle == IRQ_UNMAPPED) + { + handle = kmm_calloc(1, sizeof(intr_handle_data_t)); + if (handle == NULL) + { + wlerr("Failed to kmm_calloc\n"); + return; + } + + /* Register the handle - it contains all needed information + * (cpuint, cpu) + */ + + esp_set_handle(cpu_no, irq, handle); + } + + handle->vector_desc = desc; handle->vector_desc->source = intr_source; handle->shared_vector_desc = NULL; - /* Register the handle - it contains all needed information (cpuint, cpu) */ - - esp_set_handle(cpu_no, irq, handle); - err = esp_intr_set_in_iram(handle, false); if (err != OK) { diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c index ca7f5dfced1..278fa70bc3a 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c @@ -1755,6 +1755,7 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { intr_handle_t handle; + vector_desc_t *desc; int irq = ESP_SOURCE2IRQ(intr_source); esp_err_t err; @@ -1764,28 +1765,40 @@ static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num); - handle = kmm_calloc(1, sizeof(intr_handle_data_t)); - if (handle == NULL) - { - wlerr("Failed to kmm_calloc\n"); - return; - } - - handle->vector_desc = get_desc_for_int(intr_num, cpu_no); - if (handle->vector_desc == NULL) + desc = get_desc_for_int(intr_num, cpu_no); + if (desc == NULL) { wlerr("get_desc_for_int failed\n"); - kmm_free(handle); return; } + /* The Wi-Fi driver calls this on every esp_wifi_start(), not only on + * the first one, and nothing clears the handle in between (see + * clear_intr_wrapper()). Reuse the registered handle: a new one would + * be refused by esp_set_handle() and leaked. + */ + + handle = esp_get_handle(cpu_no, irq); + if (handle == IRQ_UNMAPPED) + { + handle = kmm_calloc(1, sizeof(intr_handle_data_t)); + if (handle == NULL) + { + wlerr("Failed to kmm_calloc\n"); + return; + } + + /* Register the handle - it contains all needed information + * (cpuint, cpu) + */ + + esp_set_handle(cpu_no, irq, handle); + } + + handle->vector_desc = desc; handle->vector_desc->source = intr_source; handle->shared_vector_desc = NULL; - /* Register the handle - it contains all needed information (cpuint, cpu) */ - - esp_set_handle(cpu_no, irq, handle); - err = esp_intr_set_in_iram(handle, false); if (err != OK) {