diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 50283f4e8d..2e847a1766 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -3,7 +3,7 @@ /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include @@ -2865,21 +2865,22 @@ static struct ipa3_rx_pkt_wrapper * ipa3_get_free_page int ipa_register_notifier(void *fn_ptr) { + struct ipa_notifier_block_data *ipa_notifier_block; if (fn_ptr == NULL) return -EFAULT; spin_lock(&ipa3_ctx->notifier_lock); - atomic_set(&ipa3_ctx->stats.num_buff_above_thresh_for_def_pipe_notified, 0); - atomic_set(&ipa3_ctx->stats.num_buff_above_thresh_for_coal_pipe_notified, 0); - atomic_set(&ipa3_ctx->stats.num_buff_below_thresh_for_def_pipe_notified, 0); - atomic_set(&ipa3_ctx->stats.num_buff_below_thresh_for_coal_pipe_notified, 0); - ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr; - if (!ipa3_ctx->ipa_rmnet_notifier_enabled) - raw_notifier_chain_register(ipa3_ctx->ipa_rmnet_notifier_list_internal, - &ipa3_ctx->ipa_rmnet_notifier); - else { - IPAWANERR("rcvd notifier reg again, changing the cb function\n"); - ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr; + ipa_notifier_block = (struct ipa_notifier_block_data *)kzalloc(sizeof(struct ipa_notifier_block_data), GFP_KERNEL); + if (ipa_notifier_block == NULL) { + IPAWANERR("Buffer threshold notifier failure\n"); + spin_unlock(&ipa3_ctx->notifier_lock); + return -EFAULT; } + ipa_notifier_block->ipa_rmnet_notifier.notifier_call = fn_ptr; + list_add(&ipa_notifier_block->entry, &ipa3_ctx->notifier_block_list_head); + raw_notifier_chain_register(ipa3_ctx->ipa_rmnet_notifier_list_internal, + &ipa_notifier_block->ipa_rmnet_notifier); + IPAWANERR("Registered noifier for buffer threshold\n"); + ipa3_ctx->ipa_rmnet_notifier_enabled = true; spin_unlock(&ipa3_ctx->notifier_lock); return 0; @@ -2888,16 +2889,24 @@ EXPORT_SYMBOL(ipa_register_notifier); int ipa_unregister_notifier(void *fn_ptr) { + struct ipa_notifier_block_data *ipa_notifier_block, *temp; if (fn_ptr == NULL) return -EFAULT; spin_lock(&ipa3_ctx->notifier_lock); - ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr; - if (ipa3_ctx->ipa_rmnet_notifier_enabled) - raw_notifier_chain_unregister(ipa3_ctx->ipa_rmnet_notifier_list_internal, - &ipa3_ctx->ipa_rmnet_notifier); - else IPAWANERR("rcvd notifier unreg again\n"); - ipa3_ctx->ipa_rmnet_notifier_enabled = false; + /* Find the client pointer, unregister and remove from the list */ + list_for_each_entry_safe(ipa_notifier_block, temp, &ipa3_ctx->notifier_block_list_head, entry) { + if (ipa_notifier_block->ipa_rmnet_notifier.notifier_call == fn_ptr) { + raw_notifier_chain_unregister(ipa3_ctx->ipa_rmnet_notifier_list_internal, + &ipa_notifier_block->ipa_rmnet_notifier); + list_del(&ipa_notifier_block->entry); + kfree(ipa_notifier_block); + IPAWANERR("Client removed from list and unregistered succesfully\n"); + spin_unlock(&ipa3_ctx->notifier_lock); + return 0; + } + } spin_unlock(&ipa3_ctx->notifier_lock); + IPAWANERR("Unable to find the client in the list\n"); return 0; } EXPORT_SYMBOL(ipa_unregister_notifier); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index a6c9d83b2a..96f23bdf5e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2,7 +2,7 @@ /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _IPA3_I_H_ @@ -2122,6 +2122,11 @@ struct ipa_minidump_data { }; #endif +struct ipa_notifier_block_data { + struct list_head entry; + struct notifier_block ipa_rmnet_notifier; +}; + /* Peripheral stats for Q6, should be in the same order, defined by Q6 */ enum ipa_per_stats_type_e { IPA_PER_STATS_TYPE_NUM_PERS, @@ -2564,7 +2569,7 @@ struct ipa3_context { u64 gsi_msi_addr; spinlock_t notifier_lock; struct raw_notifier_head *ipa_rmnet_notifier_list_internal; - struct notifier_block ipa_rmnet_notifier; + struct list_head notifier_block_list_head; bool ipa_rmnet_notifier_enabled; bool buff_above_thresh_for_def_pipe_notified; bool buff_above_thresh_for_coal_pipe_notified;