From: kfx Date: Tue, 22 Mar 2011 00:46:37 +0000 (+0800) Subject: update adc driver modify 'sync_read bug' X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=164ed84c3e49d23873d62fde76145581bbcaff18;p=firefly-linux-kernel-4.4.55.git update adc driver modify 'sync_read bug' --- diff --git a/drivers/adc/core.c b/drivers/adc/core.c index 9ad1dae2e6ff..ce00e01c1c97 100755 --- a/drivers/adc/core.c +++ b/drivers/adc/core.c @@ -125,7 +125,7 @@ adc_sync_read_callback(struct adc_client *client, void *param, int result) int adc_sync_read(struct adc_client *client) { struct adc_request *req = NULL; - int err, tmo; + int err, tmo, tail; if(client == NULL) { printk(KERN_ERR "client point is NULL"); @@ -144,6 +144,7 @@ int adc_sync_read(struct adc_client *client) req->callback = adc_sync_read_callback; req->callback_param = req; req->client = client; + req->status = SYNC_READ; init_completion(&req->completion); err = adc_enqueue_request(client->adc, req); @@ -154,8 +155,14 @@ int adc_sync_read(struct adc_client *client) return err; } tmo = wait_for_completion_timeout(&req->completion,msecs_to_jiffies(100)); - if(tmo == 0) + kfree(req); + req = NULL; + if(tmo == 0) { + tail = (client->adc->queue_tail - 1) & (MAX_ADC_FIFO_DEPTH - 1); + client->adc->queue[tail] = NULL; + client->adc->queue_tail = tail; return -ETIMEDOUT; + } return client->result; } EXPORT_SYMBOL(adc_sync_read); @@ -181,6 +188,7 @@ int adc_async_read(struct adc_client *client) req->callback = client->callback; req->callback_param = client->callback_param; req->client = client; + req->status = ASYNC_READ; return adc_enqueue_request(client->adc, req); } @@ -206,7 +214,10 @@ void adc_core_irq_handle(struct adc_host *adc) trigger_next_adc_job_if_any(adc); req->callback(adc->cur, req->callback_param, res); - kfree(req); + if(req->status == ASYNC_READ) { + kfree(req); + req = NULL; + } } EXPORT_SYMBOL(adc_core_irq_handle); diff --git a/drivers/adc/plat/rk29_adc.c b/drivers/adc/plat/rk29_adc.c index 0ddbec289435..6bf01ba8c56f 100755 --- a/drivers/adc/plat/rk29_adc.c +++ b/drivers/adc/plat/rk29_adc.c @@ -66,31 +66,50 @@ static const struct adc_ops rk29_adc_ops = { .read = rk29_adc_read, }; #ifdef ADC_TEST +struct adc_test_data { + struct adc_client *client; + struct timer_list timer; + struct work_struct timer_work; +}; static void callback(struct adc_client *client, void *param, int result) { dev_info(client->adc->dev, "[chn%d] async_read = %d\n", client->chn, result); return; } +static void adc_timer(unsigned long data) +{ + //int sync_read = 0; + struct adc_test_data *test=(struct adc_test_data *)data; + + //sync_read = adc_sync_read(test->client); + //dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read); + schedule_work(&test->timer_work); + add_timer(&test->timer); +} +static void adc_timer_work(struct work_struct *work) +{ + int sync_read = 0; + struct adc_test_data *test = container_of(work, struct adc_test_data, + timer_work); + adc_async_read(test->client); + sync_read = adc_sync_read(test->client); + dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read); +} + static int rk29_adc_test(void) { - int sync_read = 0, i, j = 10; - struct adc_client *client =NULL; - - while(j--) - { - client = adc_register(i, callback, NULL); - adc_async_read(client); - mdelay(1000); - sync_read = adc_sync_read(client); - dev_info(client->adc->dev, "[chn%d] sync_read = %d\n", client->chn, sync_read); - adc_unregister(client); - mdelay(1000); - i++; - if(i >= 4) - i = 0; - } - adc_unregister(client); + struct adc_test_data *test = NULL; + + test = kzalloc(sizeof(struct adc_test_data), GFP_KERNEL); + + test->client = adc_register(0, callback, NULL); + INIT_WORK(&test->timer_work, adc_timer_work); + setup_timer(&test->timer, adc_timer, (unsigned long)test); + test->timer.expires = jiffies + 100; + add_timer(&test->timer); + return 0; + } #endif @@ -157,9 +176,6 @@ static int rk29_adc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "rk29 adc: driver initialized\n"); -#ifdef ADC_TEST - rk29_adc_test(); -#endif return 0; // err_iomap: // iounmap(dev->regs); @@ -243,4 +259,12 @@ module_exit(rk29_adc_exit); MODULE_DESCRIPTION("Driver for ADC"); MODULE_AUTHOR("kfx, kfx@rock-chips.com"); MODULE_LICENSE("GPL"); +static int __init adc_test_init(void) +{ +#ifdef ADC_TEST + rk29_adc_test(); +#endif + return 0; +} +module_init(adc_test_init); diff --git a/include/linux/adc.h b/include/linux/adc.h index fcef9923f78b..d9ed72afbe0f 100755 --- a/include/linux/adc.h +++ b/include/linux/adc.h @@ -31,6 +31,9 @@ struct adc_request { struct adc_client *client; /* Used in case of sync requests */ struct completion completion; +#define ASYNC_READ 0 +#define SYNC_READ 1 + int status; }; struct adc_host; struct adc_ops {