Re: [PATCH v4 1/3] iio: add watermark logic to iio read and poll

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 3, 2015 at 7:46 PM, Lars-Peter Clausen <lars@xxxxxxxxxx> wrote:
> On 03/03/2015 05:21 PM, Octavian Purdila wrote:
> [...]

Hi Lars,

Thank you for the review!

>>
>> @@ -61,26 +64,48 @@ ssize_t iio_buffer_read_first_n_outer(struct file
>> *filp, char __user *buf,
>>         if (!rb || !rb->access->read_first_n)
>>                 return -EINVAL;
>>
>> -       do {
>> -               if (!iio_buffer_data_available(rb)) {
>> -                       if (filp->f_flags & O_NONBLOCK)
>> -                               return -EAGAIN;
>> +       /*
>> +        * If datum_size is 0 there will never be anything to read from
>> the
>> +        * buffer, so signal end of file now.
>> +        */
>> +       if (!datum_size)
>> +               return 0;
>>
>> +       to_read = min_t(size_t, n / datum_size, rb->watermark);
>
>
> I'd maybe call it wakeup_threshold.
>
>> +
>> +       do {
>> +               if (filp->f_flags & O_NONBLOCK) {
>> +                       if (!iio_buffer_data_available(rb)) {
>> +                               ret = -EAGAIN;
>> +                               break;
>> +                       }
>> +               } else {
>>                         ret = wait_event_interruptible(rb->pollq,
>> -                                       iio_buffer_data_available(rb) ||
>> -                                       indio_dev->info == NULL);
>> +                              iio_buffer_data_available(rb) >= to_read ||
>> +                                                      indio_dev->info ==
>> NULL);
>
>
> This needs also to evaluate to true if the buffer is disabled so we have a
> chance to read any amount residue sample that are less than watermark.
>

Good point.

>>                         if (ret)
>>                                 return ret;
>> -                       if (indio_dev->info == NULL)
>> -                               return -ENODEV;
>> +                       if (indio_dev->info == NULL) {
>> +                               ret = -ENODEV;
>> +                               break;
>> +                       }
>>                 }
>>
>> -               ret = rb->access->read_first_n(rb, n, buf);
>> -               if (ret == 0 && (filp->f_flags & O_NONBLOCK))
>> -                       ret = -EAGAIN;
>> -        } while (ret == 0);
>> +               ret = rb->access->read_first_n(rb, n, buf + count);
>> +               if (ret < 0)
>> +                       break;
>>
>> -       return ret;
>> +               count += ret;
>> +               n -= ret;
>> +               to_read -= ret / datum_size;
>
>
>
> This will underflow if there are more than watermark sample in the buffer
> and and more than watermark samples have been requested by userspace...
>
>
>> +        } while (to_read > 0);
>
>
> ... and then we get trapped in a very long loop.
>
> In my opinion there is no need to change the loop at all, only update the
> wakeup condition.
>

Correct, how did I miss that :/ I will rewrite the code to keep the
loop unchanged.

>> +
>> +       if (count)
>> +               return count;
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       return -EAGAIN;
>>   }
>>
>>   /**
>> @@ -96,9 +121,8 @@ unsigned int iio_buffer_poll(struct file *filp,
>>                 return -ENODEV;
>>
>>         poll_wait(filp, &rb->pollq, wait);
>> -       if (iio_buffer_data_available(rb))
>> +       if (iio_buffer_data_available(rb) >= rb->watermark)
>
>
> Same here needs to wakeup if the buffer is disabled and there is at least
> one sample.
>

Ok.

>>                 return POLLIN | POLLRDNORM;
>> -       /* need a way of knowing if there may be enough data... */
>>         return 0;
>>   }
>>
> [...]
>>
>> @@ -418,7 +443,16 @@ static ssize_t iio_buffer_write_length(struct device
>> *dev,
>>         }
>>         mutex_unlock(&indio_dev->mlock);
>>
>> -       return ret ? ret : len;
>> +       if (ret)
>> +               return ret;
>> +
>> +       if (buffer->length)
>> +               val = buffer->length;
>> +
>> +       if (val < buffer->watermark)
>> +               buffer->watermark = val;
>
>
> Needs to be inside the locked section.
>

Ok.

>> +
>> +       return len;
>>   }
>
> [...]
>>
>> +static ssize_t iio_buffer_store_watermark(struct device *dev,
>> +                                         struct device_attribute *attr,
>> +                                         const char *buf,
>> +                                         size_t len)
>> +{
>> +       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> +       struct iio_buffer *buffer = indio_dev->buffer;
>> +       unsigned int val;
>> +       int ret;
>> +
>> +       ret = kstrtouint(buf, 10, &val);
>> +       if (ret)
>> +               return ret;
>> +
>> +       if (val > buffer->length)
>
>
> Same here.

Ok.

>
>> +               return -EINVAL;
>> +
>> +       mutex_lock(&indio_dev->mlock);
>> +       if (iio_buffer_is_active(indio_dev->buffer)) {
>> +               ret = -EBUSY;
>> +               goto out;
>> +       }
>> +
>> +       buffer->watermark = val;
>
>
> We should probably reject 0.
>

I agree.

>> +       ret = 0;
>> +out:
>> +       mutex_unlock(&indio_dev->mlock);
>> +       return ret ? ret : len;
>> +}
>> +
>
> [...]
>>
>>   int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
>> @@ -944,8 +1022,18 @@ static const void *iio_demux(struct iio_buffer
>> *buffer,
>>   static int iio_push_to_buffer(struct iio_buffer *buffer, const void
>> *data)
>>   {
>>         const void *dataout = iio_demux(buffer, data);
>> +       int ret;
>> +
>> +       ret = buffer->access->store_to(buffer, dataout);
>> +       if (ret)
>> +               return ret;
>>
>> -       return buffer->access->store_to(buffer, dataout);
>> +       /*
>> +        * We can't just test for watermark to decide if we wake the poll
>> queue
>> +        * because read may request less samples than the watermark.
>> +        */
>> +       wake_up_interruptible(&buffer->pollq);
>
>
> What happened to poll parameters?
>

I don't understand you question, can you please elaborate?
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux