Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Peter Ujfalusi
On 09/22/16 13:45, Mugunthan V N wrote:
>>> +   if (!dma->chan)
>>> +   return -ENODEV;
>>> +
>>> +   /* RX buffer */
>>> +   dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>>> + >addr, GFP_KERNEL);
>>> +   if (!dma->buf)
>>> +   goto err;
>>> +
>>> +   dev_dbg_ratelimited(adc_dev->mfd_tscadc->dev, "got dma channel\n");
>>
>> Do we need _ratelimited? AFAICS, this print is called only once.
> 
> True, will change to dev_dbg.

It would be better to remove it. It gives no useful debuggin information apart
from the fact that the driver did not failed to probe.

-- 
Péter


Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Peter Ujfalusi
On 09/22/16 13:45, Mugunthan V N wrote:
>>> +   if (!dma->chan)
>>> +   return -ENODEV;
>>> +
>>> +   /* RX buffer */
>>> +   dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>>> + >addr, GFP_KERNEL);
>>> +   if (!dma->buf)
>>> +   goto err;
>>> +
>>> +   dev_dbg_ratelimited(adc_dev->mfd_tscadc->dev, "got dma channel\n");
>>
>> Do we need _ratelimited? AFAICS, this print is called only once.
> 
> True, will change to dev_dbg.

It would be better to remove it. It gives no useful debuggin information apart
from the fact that the driver did not failed to probe.

-- 
Péter


Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Mugunthan V N
On Thursday 22 September 2016 11:48 AM, Vignesh R wrote:
> 
> 
> On Wednesday 21 September 2016 09:41 PM, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N 
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c  | 160 
>> ++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c 
>> b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include 
>>  #include 
>>  
>> +#include 
>> +#include 
>> +
>> +#define DMA_BUFFER_SIZE SZ_2K
>> +
>> +struct tiadc_dma {
>> +/* Filter function */
>> +dma_filter_fn   fn;
>> +/* Parameter to the filter function */
>> +void*param;
> 
> These will not be needed with newer APIs (see below)
> 
>> +struct dma_slave_config conf;
>> +struct dma_chan *chan;
>> +dma_addr_t  addr;
>> +dma_cookie_tcookie;
>> +u8  *buf;
>> +boolvalid_buf_seg;
>> +int buf_offset;
>> +u8  fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  struct ti_tscadc_dev *mfd_tscadc;
>> +struct tiadc_dma dma;
>>  struct mutex fifo1_lock; /* to protect fifo access */
>>  int channels;
>> +int total_ch_enabled;
>>  u8 channel_line[8];
>>  u8 channel_step[8];
>>  int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  u16 *data = adc_dev->data;
>>  
>>  fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  for (k = 0; k < fifo1count; k = k + i) {
>>  for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void 
>> *private)
>>  return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +struct iio_dev *indio_dev = param;
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +u8 *data;
>> +int i;
>> +
>> +data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
>> +dma->valid_buf_seg = !dma->valid_buf_seg;
>> +
>> +for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +iio_push_to_buffers(indio_dev, data);
>> +data += indio_dev->scan_bytes;
>> +}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +struct dma_async_tx_descriptor *desc;
>> +
>> +dma->valid_buf_seg = false;
>> +dma->fifo_thresh = FIFO1_THRESHOLD;
>> +/*
>> + * Make the fifo thresh as the multiple of total number of
>> + * channels enabled, so make sure that that cyclic DMA period
>> + * length is also a multiple of total number of channels
>> + * enabled. This ensures that no invalid data is reported
>> + * to the stack via iio_push_to_buffers().
>> + */
>> +dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
> 
> Can we use rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled)?
> 
>> +dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> +/* Make sure that period length is multiple of fifo thresh level */
>> +dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
>> +  sizeof(u16));
>> +
> 
> Can we use rounddown()?

Will change this in next version.

> 
>> +dma->conf.src_maxburst = dma->fifo_thresh + 1;
>> +dmaengine_slave_config(dma->chan, >conf);
>> +
>> +desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
>> + dma->buf_offset * 2,
>> + dma->buf_offset, DMA_DEV_TO_MEM,
>> + DMA_PREP_INTERRUPT);
>> +if (!desc)
>> +return -EBUSY;
>> +
>> +desc->callback = tiadc_dma_rx_complete;
>> +desc->callback_param = indio_dev;
>> +
>> +dma->cookie = dmaengine_submit(desc);
>> +
>> +dma_async_issue_pending(dma->chan);
>> +
>> +tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
>> +tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
>> +tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
>> +
>> +return 0;
>> +}
>> +
>>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  {
>>  struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev 
>> *indio_dev)
>>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  {

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Mugunthan V N
On Thursday 22 September 2016 11:48 AM, Vignesh R wrote:
> 
> 
> On Wednesday 21 September 2016 09:41 PM, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N 
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c  | 160 
>> ++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c 
>> b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include 
>>  #include 
>>  
>> +#include 
>> +#include 
>> +
>> +#define DMA_BUFFER_SIZE SZ_2K
>> +
>> +struct tiadc_dma {
>> +/* Filter function */
>> +dma_filter_fn   fn;
>> +/* Parameter to the filter function */
>> +void*param;
> 
> These will not be needed with newer APIs (see below)
> 
>> +struct dma_slave_config conf;
>> +struct dma_chan *chan;
>> +dma_addr_t  addr;
>> +dma_cookie_tcookie;
>> +u8  *buf;
>> +boolvalid_buf_seg;
>> +int buf_offset;
>> +u8  fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  struct ti_tscadc_dev *mfd_tscadc;
>> +struct tiadc_dma dma;
>>  struct mutex fifo1_lock; /* to protect fifo access */
>>  int channels;
>> +int total_ch_enabled;
>>  u8 channel_line[8];
>>  u8 channel_step[8];
>>  int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  u16 *data = adc_dev->data;
>>  
>>  fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  for (k = 0; k < fifo1count; k = k + i) {
>>  for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void 
>> *private)
>>  return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +struct iio_dev *indio_dev = param;
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +u8 *data;
>> +int i;
>> +
>> +data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
>> +dma->valid_buf_seg = !dma->valid_buf_seg;
>> +
>> +for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +iio_push_to_buffers(indio_dev, data);
>> +data += indio_dev->scan_bytes;
>> +}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +struct dma_async_tx_descriptor *desc;
>> +
>> +dma->valid_buf_seg = false;
>> +dma->fifo_thresh = FIFO1_THRESHOLD;
>> +/*
>> + * Make the fifo thresh as the multiple of total number of
>> + * channels enabled, so make sure that that cyclic DMA period
>> + * length is also a multiple of total number of channels
>> + * enabled. This ensures that no invalid data is reported
>> + * to the stack via iio_push_to_buffers().
>> + */
>> +dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
> 
> Can we use rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled)?
> 
>> +dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> +/* Make sure that period length is multiple of fifo thresh level */
>> +dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
>> +  sizeof(u16));
>> +
> 
> Can we use rounddown()?

Will change this in next version.

> 
>> +dma->conf.src_maxburst = dma->fifo_thresh + 1;
>> +dmaengine_slave_config(dma->chan, >conf);
>> +
>> +desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
>> + dma->buf_offset * 2,
>> + dma->buf_offset, DMA_DEV_TO_MEM,
>> + DMA_PREP_INTERRUPT);
>> +if (!desc)
>> +return -EBUSY;
>> +
>> +desc->callback = tiadc_dma_rx_complete;
>> +desc->callback_param = indio_dev;
>> +
>> +dma->cookie = dmaengine_submit(desc);
>> +
>> +dma_async_issue_pending(dma->chan);
>> +
>> +tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
>> +tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
>> +tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
>> +
>> +return 0;
>> +}
>> +
>>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  {
>>  struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev 
>> *indio_dev)
>>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  {
>>  struct 

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Mugunthan V N
On Thursday 22 September 2016 12:50 PM, Peter Ujfalusi wrote:
> On 09/21/16 19:11, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N 
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c  | 160 
>> ++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c 
>> b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include 
>>  #include 
>>  
>> +#include 
>> +#include 
>> +
>> +#define DMA_BUFFER_SIZE SZ_2K
>> +
>> +struct tiadc_dma {
>> +/* Filter function */
>> +dma_filter_fn   fn;
>> +/* Parameter to the filter function */
>> +void*param;
>> +struct dma_slave_config conf;
>> +struct dma_chan *chan;
>> +dma_addr_t  addr;
>> +dma_cookie_tcookie;
>> +u8  *buf;
>> +boolvalid_buf_seg;
>> +int buf_offset;
>> +u8  fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  struct ti_tscadc_dev *mfd_tscadc;
>> +struct tiadc_dma dma;
>>  struct mutex fifo1_lock; /* to protect fifo access */
>>  int channels;
>> +int total_ch_enabled;
>>  u8 channel_line[8];
>>  u8 channel_step[8];
>>  int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  u16 *data = adc_dev->data;
>>  
>>  fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  for (k = 0; k < fifo1count; k = k + i) {
>>  for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void 
>> *private)
>>  return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +struct iio_dev *indio_dev = param;
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +u8 *data;
>> +int i;
>> +
>> +data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
> 
> bool valid_buf_seg ? The buffer segment is valid or not valid? Which buffer
> segment is valid when valid_buf_seg is true?
> 
> I know what this is doing, but it is logically not correct.
> 
> Instead you could have:
> 
> int current_period; /* The period the DMA is working on */
> 
> When you start the DMA:
> dma->current_period = 0; /* We start to fill period 0 */
> 
> In here:
> 
> u8 *data = dma->buf + (dma->current_period * dma_period_size);
> 
>> +dma->valid_buf_seg = !dma->valid_buf_seg;
> 
> /* Currently we have only two periods, so we can just */
> dma->current_period = !dma->current_period;
> /* or */
> dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
> 
> I think this would make it better to follow and if later you figure that you
> want three or more periods instead of the two, it is going to be easier to add
> that.

Okay, will change this in next version patch.

> 
>> +
>> +for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +iio_push_to_buffers(indio_dev, data);
>> +data += indio_dev->scan_bytes;
>> +}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +struct dma_async_tx_descriptor *desc;
>> +
>> +dma->valid_buf_seg = false;
>> +dma->fifo_thresh = FIFO1_THRESHOLD;
> 
> FIFO1_THRESHOLD is defined as 19 in the global header file, so
> if you have 2 channels enabled the trigger comes when the FIFO have 10
> samples/ch, in case of all 8 channels enabled you will round it down the
> trigger comes when you have 2 samples/ch.
> 
> Would not be better to try to use high threshold for the FIFO to reduce the
> number of DMA requests needed runtime?
> 
> It is OK as it is at the moment, but I think it would make sense to try to
> maximize the FIFO usage.

I had already tried with higher values, It works fine. Just don't want
to change the non-DMA implementation as I am not aware of any
limitations why at the first place they have used fifo threshold as 19.

> 
>> +/*
>> + * Make the fifo thresh as the multiple of total number of
>> + * channels enabled, so make sure that that cyclic DMA period
>> + * length is also a multiple of total number of channels
>> + * enabled. This ensures that no invalid data is reported
>> + * to the stack via iio_push_to_buffers().
>> + */
>> +dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
>> +dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> 

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Mugunthan V N
On Thursday 22 September 2016 12:50 PM, Peter Ujfalusi wrote:
> On 09/21/16 19:11, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N 
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c  | 160 
>> ++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c 
>> b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include 
>>  #include 
>>  
>> +#include 
>> +#include 
>> +
>> +#define DMA_BUFFER_SIZE SZ_2K
>> +
>> +struct tiadc_dma {
>> +/* Filter function */
>> +dma_filter_fn   fn;
>> +/* Parameter to the filter function */
>> +void*param;
>> +struct dma_slave_config conf;
>> +struct dma_chan *chan;
>> +dma_addr_t  addr;
>> +dma_cookie_tcookie;
>> +u8  *buf;
>> +boolvalid_buf_seg;
>> +int buf_offset;
>> +u8  fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  struct ti_tscadc_dev *mfd_tscadc;
>> +struct tiadc_dma dma;
>>  struct mutex fifo1_lock; /* to protect fifo access */
>>  int channels;
>> +int total_ch_enabled;
>>  u8 channel_line[8];
>>  u8 channel_step[8];
>>  int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  u16 *data = adc_dev->data;
>>  
>>  fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  for (k = 0; k < fifo1count; k = k + i) {
>>  for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void 
>> *private)
>>  return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +struct iio_dev *indio_dev = param;
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +u8 *data;
>> +int i;
>> +
>> +data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
> 
> bool valid_buf_seg ? The buffer segment is valid or not valid? Which buffer
> segment is valid when valid_buf_seg is true?
> 
> I know what this is doing, but it is logically not correct.
> 
> Instead you could have:
> 
> int current_period; /* The period the DMA is working on */
> 
> When you start the DMA:
> dma->current_period = 0; /* We start to fill period 0 */
> 
> In here:
> 
> u8 *data = dma->buf + (dma->current_period * dma_period_size);
> 
>> +dma->valid_buf_seg = !dma->valid_buf_seg;
> 
> /* Currently we have only two periods, so we can just */
> dma->current_period = !dma->current_period;
> /* or */
> dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
> 
> I think this would make it better to follow and if later you figure that you
> want three or more periods instead of the two, it is going to be easier to add
> that.

Okay, will change this in next version patch.

> 
>> +
>> +for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +iio_push_to_buffers(indio_dev, data);
>> +data += indio_dev->scan_bytes;
>> +}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +struct tiadc_dma *dma = _dev->dma;
>> +struct dma_async_tx_descriptor *desc;
>> +
>> +dma->valid_buf_seg = false;
>> +dma->fifo_thresh = FIFO1_THRESHOLD;
> 
> FIFO1_THRESHOLD is defined as 19 in the global header file, so
> if you have 2 channels enabled the trigger comes when the FIFO have 10
> samples/ch, in case of all 8 channels enabled you will round it down the
> trigger comes when you have 2 samples/ch.
> 
> Would not be better to try to use high threshold for the FIFO to reduce the
> number of DMA requests needed runtime?
> 
> It is OK as it is at the moment, but I think it would make sense to try to
> maximize the FIFO usage.

I had already tried with higher values, It works fine. Just don't want
to change the non-DMA implementation as I am not aware of any
limitations why at the first place they have used fifo threshold as 19.

> 
>> +/*
>> + * Make the fifo thresh as the multiple of total number of
>> + * channels enabled, so make sure that that cyclic DMA period
>> + * length is also a multiple of total number of channels
>> + * enabled. This ensures that no invalid data is reported
>> + * to the stack via iio_push_to_buffers().
>> + */
>> +dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
>> +dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> +/* Make sure 

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Peter Ujfalusi
On 09/21/16 19:11, Mugunthan V N wrote:
> This patch adds the required pieces to ti_am335x_adc driver for
> DMA support
> 
> Signed-off-by: Mugunthan V N 
> ---
>  drivers/iio/adc/ti_am335x_adc.c  | 160 
> ++-
>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>  2 files changed, 164 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index c3cfacca..89d0b07 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -30,10 +30,32 @@
>  #include 
>  #include 
>  
> +#include 
> +#include 
> +
> +#define DMA_BUFFER_SIZE  SZ_2K
> +
> +struct tiadc_dma {
> + /* Filter function */
> + dma_filter_fn   fn;
> + /* Parameter to the filter function */
> + void*param;
> + struct dma_slave_config conf;
> + struct dma_chan *chan;
> + dma_addr_t  addr;
> + dma_cookie_tcookie;
> + u8  *buf;
> + boolvalid_buf_seg;
> + int buf_offset;
> + u8  fifo_thresh;
> +};
> +
>  struct tiadc_device {
>   struct ti_tscadc_dev *mfd_tscadc;
> + struct tiadc_dma dma;
>   struct mutex fifo1_lock; /* to protect fifo access */
>   int channels;
> + int total_ch_enabled;
>   u8 channel_line[8];
>   u8 channel_step[8];
>   int buffer_en_ch_steps;
> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   u16 *data = adc_dev->data;
>  
>   fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +
>   for (k = 0; k < fifo1count; k = k + i) {
>   for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>   read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   return IRQ_HANDLED;
>  }
>  
> +static void tiadc_dma_rx_complete(void *param)
> +{
> + struct iio_dev *indio_dev = param;
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + u8 *data;
> + int i;
> +
> + data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;

bool valid_buf_seg ? The buffer segment is valid or not valid? Which buffer
segment is valid when valid_buf_seg is true?

I know what this is doing, but it is logically not correct.

Instead you could have:

int current_period; /* The period the DMA is working on */

When you start the DMA:
dma->current_period = 0; /* We start to fill period 0 */

In here:

u8 *data = dma->buf + (dma->current_period * dma_period_size);

> + dma->valid_buf_seg = !dma->valid_buf_seg;

/* Currently we have only two periods, so we can just */
dma->current_period = !dma->current_period;
/* or */
dma->current_period = 1 - dma->current_period; /* swap the buffer ID */

I think this would make it better to follow and if later you figure that you
want three or more periods instead of the two, it is going to be easier to add
that.

> +
> + for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
> + iio_push_to_buffers(indio_dev, data);
> + data += indio_dev->scan_bytes;
> + }
> +}
> +
> +static int tiadc_start_dma(struct iio_dev *indio_dev)
> +{
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + struct dma_async_tx_descriptor *desc;
> +
> + dma->valid_buf_seg = false;
> + dma->fifo_thresh = FIFO1_THRESHOLD;

FIFO1_THRESHOLD is defined as 19 in the global header file, so
if you have 2 channels enabled the trigger comes when the FIFO have 10
samples/ch, in case of all 8 channels enabled you will round it down the
trigger comes when you have 2 samples/ch.

Would not be better to try to use high threshold for the FIFO to reduce the
number of DMA requests needed runtime?

It is OK as it is at the moment, but I think it would make sense to try to
maximize the FIFO usage.

> + /*
> +  * Make the fifo thresh as the multiple of total number of
> +  * channels enabled, so make sure that that cyclic DMA period
> +  * length is also a multiple of total number of channels
> +  * enabled. This ensures that no invalid data is reported
> +  * to the stack via iio_push_to_buffers().
> +  */
> + dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
> + dma->buf_offset = DMA_BUFFER_SIZE / 2;
> + /* Make sure that period length is multiple of fifo thresh level */
> + dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
> +   sizeof(u16));
> +
> + dma->conf.src_maxburst = dma->fifo_thresh + 1;
> + dmaengine_slave_config(dma->chan, >conf);
> +
> + desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
> +  dma->buf_offset * 2,
> 

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Peter Ujfalusi
On 09/21/16 19:11, Mugunthan V N wrote:
> This patch adds the required pieces to ti_am335x_adc driver for
> DMA support
> 
> Signed-off-by: Mugunthan V N 
> ---
>  drivers/iio/adc/ti_am335x_adc.c  | 160 
> ++-
>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>  2 files changed, 164 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index c3cfacca..89d0b07 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -30,10 +30,32 @@
>  #include 
>  #include 
>  
> +#include 
> +#include 
> +
> +#define DMA_BUFFER_SIZE  SZ_2K
> +
> +struct tiadc_dma {
> + /* Filter function */
> + dma_filter_fn   fn;
> + /* Parameter to the filter function */
> + void*param;
> + struct dma_slave_config conf;
> + struct dma_chan *chan;
> + dma_addr_t  addr;
> + dma_cookie_tcookie;
> + u8  *buf;
> + boolvalid_buf_seg;
> + int buf_offset;
> + u8  fifo_thresh;
> +};
> +
>  struct tiadc_device {
>   struct ti_tscadc_dev *mfd_tscadc;
> + struct tiadc_dma dma;
>   struct mutex fifo1_lock; /* to protect fifo access */
>   int channels;
> + int total_ch_enabled;
>   u8 channel_line[8];
>   u8 channel_step[8];
>   int buffer_en_ch_steps;
> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   u16 *data = adc_dev->data;
>  
>   fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +
>   for (k = 0; k < fifo1count; k = k + i) {
>   for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>   read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   return IRQ_HANDLED;
>  }
>  
> +static void tiadc_dma_rx_complete(void *param)
> +{
> + struct iio_dev *indio_dev = param;
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + u8 *data;
> + int i;
> +
> + data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;

bool valid_buf_seg ? The buffer segment is valid or not valid? Which buffer
segment is valid when valid_buf_seg is true?

I know what this is doing, but it is logically not correct.

Instead you could have:

int current_period; /* The period the DMA is working on */

When you start the DMA:
dma->current_period = 0; /* We start to fill period 0 */

In here:

u8 *data = dma->buf + (dma->current_period * dma_period_size);

> + dma->valid_buf_seg = !dma->valid_buf_seg;

/* Currently we have only two periods, so we can just */
dma->current_period = !dma->current_period;
/* or */
dma->current_period = 1 - dma->current_period; /* swap the buffer ID */

I think this would make it better to follow and if later you figure that you
want three or more periods instead of the two, it is going to be easier to add
that.

> +
> + for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
> + iio_push_to_buffers(indio_dev, data);
> + data += indio_dev->scan_bytes;
> + }
> +}
> +
> +static int tiadc_start_dma(struct iio_dev *indio_dev)
> +{
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + struct dma_async_tx_descriptor *desc;
> +
> + dma->valid_buf_seg = false;
> + dma->fifo_thresh = FIFO1_THRESHOLD;

FIFO1_THRESHOLD is defined as 19 in the global header file, so
if you have 2 channels enabled the trigger comes when the FIFO have 10
samples/ch, in case of all 8 channels enabled you will round it down the
trigger comes when you have 2 samples/ch.

Would not be better to try to use high threshold for the FIFO to reduce the
number of DMA requests needed runtime?

It is OK as it is at the moment, but I think it would make sense to try to
maximize the FIFO usage.

> + /*
> +  * Make the fifo thresh as the multiple of total number of
> +  * channels enabled, so make sure that that cyclic DMA period
> +  * length is also a multiple of total number of channels
> +  * enabled. This ensures that no invalid data is reported
> +  * to the stack via iio_push_to_buffers().
> +  */
> + dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
> + dma->buf_offset = DMA_BUFFER_SIZE / 2;
> + /* Make sure that period length is multiple of fifo thresh level */
> + dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
> +   sizeof(u16));
> +
> + dma->conf.src_maxburst = dma->fifo_thresh + 1;
> + dmaengine_slave_config(dma->chan, >conf);
> +
> + desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
> +  dma->buf_offset * 2,
> + 

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Vignesh R


On Wednesday 21 September 2016 09:41 PM, Mugunthan V N wrote:
> This patch adds the required pieces to ti_am335x_adc driver for
> DMA support
> 
> Signed-off-by: Mugunthan V N 
> ---
>  drivers/iio/adc/ti_am335x_adc.c  | 160 
> ++-
>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>  2 files changed, 164 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index c3cfacca..89d0b07 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -30,10 +30,32 @@
>  #include 
>  #include 
>  
> +#include 
> +#include 
> +
> +#define DMA_BUFFER_SIZE  SZ_2K
> +
> +struct tiadc_dma {
> + /* Filter function */
> + dma_filter_fn   fn;
> + /* Parameter to the filter function */
> + void*param;

These will not be needed with newer APIs (see below)

> + struct dma_slave_config conf;
> + struct dma_chan *chan;
> + dma_addr_t  addr;
> + dma_cookie_tcookie;
> + u8  *buf;
> + boolvalid_buf_seg;
> + int buf_offset;
> + u8  fifo_thresh;
> +};
> +
>  struct tiadc_device {
>   struct ti_tscadc_dev *mfd_tscadc;
> + struct tiadc_dma dma;
>   struct mutex fifo1_lock; /* to protect fifo access */
>   int channels;
> + int total_ch_enabled;
>   u8 channel_line[8];
>   u8 channel_step[8];
>   int buffer_en_ch_steps;
> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   u16 *data = adc_dev->data;
>  
>   fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +
>   for (k = 0; k < fifo1count; k = k + i) {
>   for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>   read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   return IRQ_HANDLED;
>  }
>  
> +static void tiadc_dma_rx_complete(void *param)
> +{
> + struct iio_dev *indio_dev = param;
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + u8 *data;
> + int i;
> +
> + data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
> + dma->valid_buf_seg = !dma->valid_buf_seg;
> +
> + for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
> + iio_push_to_buffers(indio_dev, data);
> + data += indio_dev->scan_bytes;
> + }
> +}
> +
> +static int tiadc_start_dma(struct iio_dev *indio_dev)
> +{
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + struct dma_async_tx_descriptor *desc;
> +
> + dma->valid_buf_seg = false;
> + dma->fifo_thresh = FIFO1_THRESHOLD;
> + /*
> +  * Make the fifo thresh as the multiple of total number of
> +  * channels enabled, so make sure that that cyclic DMA period
> +  * length is also a multiple of total number of channels
> +  * enabled. This ensures that no invalid data is reported
> +  * to the stack via iio_push_to_buffers().
> +  */
> + dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;

Can we use rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled)?

> + dma->buf_offset = DMA_BUFFER_SIZE / 2;
> + /* Make sure that period length is multiple of fifo thresh level */
> + dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
> +   sizeof(u16));
> +

Can we use rounddown()?

> + dma->conf.src_maxburst = dma->fifo_thresh + 1;
> + dmaengine_slave_config(dma->chan, >conf);
> +
> + desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
> +  dma->buf_offset * 2,
> +  dma->buf_offset, DMA_DEV_TO_MEM,
> +  DMA_PREP_INTERRUPT);
> + if (!desc)
> + return -EBUSY;
> +
> + desc->callback = tiadc_dma_rx_complete;
> + desc->callback_param = indio_dev;
> +
> + dma->cookie = dmaengine_submit(desc);
> +
> + dma_async_issue_pending(dma->chan);
> +
> + tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
> + tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
> + tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
> +
> + return 0;
> +}
> +
>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>  {
>   struct tiadc_device *adc_dev = iio_priv(indio_dev);
> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev 
> *indio_dev)
>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>  {
>   struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
>   unsigned int enb = 0;
>   u8 bit;
> + u32 irq_enable;
>  
>  

Re: [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support

2016-09-22 Thread Vignesh R


On Wednesday 21 September 2016 09:41 PM, Mugunthan V N wrote:
> This patch adds the required pieces to ti_am335x_adc driver for
> DMA support
> 
> Signed-off-by: Mugunthan V N 
> ---
>  drivers/iio/adc/ti_am335x_adc.c  | 160 
> ++-
>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>  2 files changed, 164 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index c3cfacca..89d0b07 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -30,10 +30,32 @@
>  #include 
>  #include 
>  
> +#include 
> +#include 
> +
> +#define DMA_BUFFER_SIZE  SZ_2K
> +
> +struct tiadc_dma {
> + /* Filter function */
> + dma_filter_fn   fn;
> + /* Parameter to the filter function */
> + void*param;

These will not be needed with newer APIs (see below)

> + struct dma_slave_config conf;
> + struct dma_chan *chan;
> + dma_addr_t  addr;
> + dma_cookie_tcookie;
> + u8  *buf;
> + boolvalid_buf_seg;
> + int buf_offset;
> + u8  fifo_thresh;
> +};
> +
>  struct tiadc_device {
>   struct ti_tscadc_dev *mfd_tscadc;
> + struct tiadc_dma dma;
>   struct mutex fifo1_lock; /* to protect fifo access */
>   int channels;
> + int total_ch_enabled;
>   u8 channel_line[8];
>   u8 channel_step[8];
>   int buffer_en_ch_steps;
> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   u16 *data = adc_dev->data;
>  
>   fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +
>   for (k = 0; k < fifo1count; k = k + i) {
>   for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>   read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>   return IRQ_HANDLED;
>  }
>  
> +static void tiadc_dma_rx_complete(void *param)
> +{
> + struct iio_dev *indio_dev = param;
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + u8 *data;
> + int i;
> +
> + data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
> + dma->valid_buf_seg = !dma->valid_buf_seg;
> +
> + for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
> + iio_push_to_buffers(indio_dev, data);
> + data += indio_dev->scan_bytes;
> + }
> +}
> +
> +static int tiadc_start_dma(struct iio_dev *indio_dev)
> +{
> + struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
> + struct dma_async_tx_descriptor *desc;
> +
> + dma->valid_buf_seg = false;
> + dma->fifo_thresh = FIFO1_THRESHOLD;
> + /*
> +  * Make the fifo thresh as the multiple of total number of
> +  * channels enabled, so make sure that that cyclic DMA period
> +  * length is also a multiple of total number of channels
> +  * enabled. This ensures that no invalid data is reported
> +  * to the stack via iio_push_to_buffers().
> +  */
> + dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;

Can we use rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled)?

> + dma->buf_offset = DMA_BUFFER_SIZE / 2;
> + /* Make sure that period length is multiple of fifo thresh level */
> + dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
> +   sizeof(u16));
> +

Can we use rounddown()?

> + dma->conf.src_maxburst = dma->fifo_thresh + 1;
> + dmaengine_slave_config(dma->chan, >conf);
> +
> + desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
> +  dma->buf_offset * 2,
> +  dma->buf_offset, DMA_DEV_TO_MEM,
> +  DMA_PREP_INTERRUPT);
> + if (!desc)
> + return -EBUSY;
> +
> + desc->callback = tiadc_dma_rx_complete;
> + desc->callback_param = indio_dev;
> +
> + dma->cookie = dmaengine_submit(desc);
> +
> + dma_async_issue_pending(dma->chan);
> +
> + tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
> + tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
> + tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
> +
> + return 0;
> +}
> +
>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>  {
>   struct tiadc_device *adc_dev = iio_priv(indio_dev);
> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev 
> *indio_dev)
>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>  {
>   struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = _dev->dma;
>   unsigned int enb = 0;
>   u8 bit;
> + u32 irq_enable;
>  
>