From 09e5ba4ee118f7019157062184aeeb6c83e2f8be Mon Sep 17 00:00:00 2001 From: anupam roy Date: Tue, 18 Oct 2011 21:11:18 +0530 Subject: CG2900 FM Radio: Improper RDS Thread handling. This patch fixes the thread leak issue from CG2900 FM kernel driver by proper handling of RDS threads. ST-Ericsson Linux next: NA ST-Ericsson ID: 365795 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I277dae0e74f4115db2b0f734dd7f6361678b9502 Signed-off-by: anupam roy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34400 Reviewed-by: QATOOLS Reviewed-by: Anurag SRIVASTAVA Reviewed-by: Johan PALMAEUS Reviewed-by: Hemant GUPTA --- drivers/media/radio/CG2900/cg2900_fm_api.c | 62 ++++++++++++++++----------- drivers/media/radio/CG2900/cg2900_fm_driver.c | 5 +++ 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/drivers/media/radio/CG2900/cg2900_fm_api.c b/drivers/media/radio/CG2900/cg2900_fm_api.c index ad9ab8de282..c18caffdaa7 100644 --- a/drivers/media/radio/CG2900/cg2900_fm_api.c +++ b/drivers/media/radio/CG2900/cg2900_fm_api.c @@ -584,6 +584,24 @@ error: return result; } +/** + * cg2900_fm_check_rds_status()- Checks whether RDS was On previously + * + * This method is called on receiving interrupt for Seek Completion, + * Scan completion and Block Scan completion. It will check whether RDS + * was forcefully disabled before the above operations started and if the + * previous RDS state was true, then RDS will be enabled back + */ +static void cg2900_fm_check_rds_status(void) +{ + FM_INFO_REPORT("cg2900_fm_check_rds_status"); + if (fm_prev_rds_status) { + /* Restart RDS if it was active previously */ + cg2900_fm_rds_on(); + fm_prev_rds_status = false; + } +} + /** * cg2900_fm_driver_callback()- Callback function indicating the event. * @@ -631,6 +649,7 @@ static void cg2900_fm_driver_callback( break; case FMD_EVENT_SEEK_COMPLETED: FM_DEBUG_REPORT("FMD_EVENT_SEEK_COMPLETED"); + cg2900_fm_check_rds_status(); skb = alloc_skb(SKB_FM_INTERRUPT_DATA, GFP_KERNEL); if (!skb) { @@ -645,6 +664,7 @@ static void cg2900_fm_driver_callback( break; case FMD_EVENT_SCAN_BAND_COMPLETED: FM_DEBUG_REPORT("FMD_EVENT_SCAN_BAND_COMPLETED"); + cg2900_fm_check_rds_status(); skb = alloc_skb(SKB_FM_INTERRUPT_DATA, GFP_KERNEL); if (!skb) { @@ -659,6 +679,7 @@ static void cg2900_fm_driver_callback( break; case FMD_EVENT_BLOCK_SCAN_COMPLETED: FM_DEBUG_REPORT("FMD_EVENT_BLOCK_SCAN_COMPLETED"); + cg2900_fm_check_rds_status(); skb = alloc_skb(SKB_FM_INTERRUPT_DATA, GFP_KERNEL); if (!skb) { @@ -830,6 +851,7 @@ int cg2900_fm_init(void) fm_event = CG2900_EVENT_NO_EVENT; fm_state = CG2900_FM_STATE_INITIALIZED; fm_mode = CG2900_FM_IDLE_MODE; + fm_prev_rds_status = false; error: FM_DEBUG_REPORT("cg2900_fm_init: returning %d", @@ -1473,6 +1495,7 @@ int cg2900_fm_search_up_freq(void) if (0 != result) { FM_ERR_REPORT("cg2900_fm_search_up_freq: " "Error Code %d", (unsigned int)result); + cg2900_fm_check_rds_status(); result = -EINVAL; goto error; } @@ -1513,6 +1536,7 @@ int cg2900_fm_search_down_freq(void) if (0 != result) { FM_ERR_REPORT("cg2900_fm_search_down_freq: " "Error Code %d", (unsigned int)result); + cg2900_fm_check_rds_status(); result = -EINVAL; goto error; } @@ -1553,6 +1577,7 @@ int cg2900_fm_start_band_scan(void) if (0 != result) { FM_ERR_REPORT("cg2900_fm_start_band_scan: " "Error Code %d", (unsigned int)result); + cg2900_fm_check_rds_status(); result = -EINVAL; goto error; } @@ -1685,11 +1710,6 @@ int cg2900_fm_get_scan_result( } } } - if (fm_prev_rds_status) { - /* Restart RDS if it was active earlier */ - result = cg2900_fm_rds_on(); - fm_prev_rds_status = false; - } error: FM_DEBUG_REPORT("cg2900_fm_get_scan_result: returning %d", @@ -1739,6 +1759,7 @@ int cg2900_fm_start_block_scan( if (0 != result) { FM_ERR_REPORT("cg2900_fm_start_block_scan: " "Error Code %d", (unsigned int)result); + cg2900_fm_check_rds_status(); result = -EINVAL; goto error; } @@ -1791,13 +1812,7 @@ int cg2900_fm_get_block_scan_result( = rssi[5]; } } - if (CG2900_FM_RX_MODE == fm_mode) { - if (fm_prev_rds_status) { - /* Restart RDS if it was active earlier*/ - result = cg2900_fm_rds_on(); - fm_prev_rds_status = false; - } - } else if (CG2900_FM_TX_MODE == fm_mode) { + if (CG2900_FM_TX_MODE == fm_mode) { FM_DEBUG_REPORT("cg2900_fm_get_block_scan_result:" " Sending Set fmd_tx_set_pa"); @@ -2441,7 +2456,12 @@ int cg2900_fm_rds_on(void) int result; FM_INFO_REPORT("cg2900_fm_rds_on"); - + if (fm_rds_status) { + result = 0; + FM_DEBUG_REPORT("cg2900_fm_rds_on: rds is on " + "return result = %d", result); + return result; + } if (CG2900_FM_STATE_SWITCHED_ON != fm_state) { FM_ERR_REPORT("cg2900_fm_rds_on: " "Invalid state of FM Driver = %d", fm_state); @@ -2635,11 +2655,6 @@ int cg2900_fm_get_frequency( *freq = currentFreq * FREQUENCY_CONVERTOR_KHZ_HZ; FM_DEBUG_REPORT("cg2900_fm_get_frequency: " "Current Frequency = %d Hz", *freq); - if (fm_prev_rds_status) { - /* Restart RDS if it was active earlier */ - cg2900_fm_rds_on(); - fm_prev_rds_status = false; - } error: FM_DEBUG_REPORT("cg2900_fm_get_frequency: returning %d", @@ -2688,18 +2703,17 @@ int cg2900_fm_set_frequency( result = fmd_tx_set_frequency( new_freq / FREQUENCY_CONVERTOR_KHZ_HZ); } + if (fm_prev_rds_status) { + /* Restart RDS if it was active earlier */ + cg2900_fm_rds_on(); + fm_prev_rds_status = false; + } if (result != 0) { FM_ERR_REPORT("cg2900_fm_set_frequency: " "fmd_rx_set_frequency failed %x", (unsigned int)result); result = -EINVAL; goto error; - } else { - if (fm_prev_rds_status) { - /* Restart RDS if it was active earlier */ - cg2900_fm_rds_on(); - fm_prev_rds_status = false; - } } if (CG2900_FM_TX_MODE == fm_mode) { diff --git a/drivers/media/radio/CG2900/cg2900_fm_driver.c b/drivers/media/radio/CG2900/cg2900_fm_driver.c index 1d3a2552da2..4b1d39839ae 100644 --- a/drivers/media/radio/CG2900/cg2900_fm_driver.c +++ b/drivers/media/radio/CG2900/cg2900_fm_driver.c @@ -1154,6 +1154,8 @@ static int fmd_rds_thread( /* Give 100 ms for context switching */ schedule_timeout_interruptible(msecs_to_jiffies(100)); } + /* Always signal the rds_sem semaphore before exiting */ + fmd_set_rds_sem(); FM_DEBUG_REPORT("fmd_rds_thread Exiting!!!"); return 0; } @@ -4667,6 +4669,9 @@ void fmd_stop_rds_thread(void) sema_init(&rds_sem, 0); cb_rds_func = NULL; rds_thread_required = false; + /* Wait for RDS thread to exit gracefully */ + fmd_get_rds_sem(); + if (rds_thread_task) rds_thread_task = NULL; } -- cgit v1.2.3