update adc driver modify 'sync_read bug'

This commit is contained in:
kfx 2011-03-22 08:46:37 +08:00
parent 03f73ff658
commit 164ed84c3e
3 changed files with 60 additions and 22 deletions

View File

@ -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);

View File

@ -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;
struct adc_test_data *test = 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);
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);

View File

@ -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 {