[PATCH v2] staging: comedi: adv_pci1710: fix analog output readback value

Ian Abbott abbotti at mev.co.uk
Thu Feb 6 09:52:51 UTC 2014


On 2014-02-05 21:59, H Hartley Sweeten wrote:
> The last value written to a analog output channel is cached in the
> private data of this driver for readback.
>
> Currently, the wrong value is cached in the (*insn_write) functions.
> The current code stores the data[n] value for readback afer the loop
> has written all the values. At this time 'n' points past the end of
> the data array.
>
> Fix the functions by using a local variable to hold the data being
> written to the analog output channel. This variable is then used
> after the loop is complete to store the readback value. The current
> value is retrieved before the loop in case no values are actually
> written..
>
> Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
> Cc: Ian Abbott <abbotti at mev.co.uk>
> Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> ---
>
> v2: also fix readback in pci1720_insn_write_ao() as pointed out by
>      Ian Abbott
>
>   drivers/staging/comedi/drivers/adv_pci1710.c | 17 ++++++++++++-----
>   1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
> index 69a8298..f9d6111 100644
> --- a/drivers/staging/comedi/drivers/adv_pci1710.c
> +++ b/drivers/staging/comedi/drivers/adv_pci1710.c
> @@ -494,6 +494,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
>   				 struct comedi_insn *insn, unsigned int *data)
>   {
>   	struct pci1710_private *devpriv = dev->private;
> +	unsigned int val;
>   	int n, chan, range, ofs;
>
>   	chan = CR_CHAN(insn->chanspec);
> @@ -509,11 +510,14 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
>   		outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
>   		ofs = PCI171x_DA1;
>   	}
> +	val = devpriv->ao_data[chan];
>
> -	for (n = 0; n < insn->n; n++)
> -		outw(data[n], dev->iobase + ofs);
> +	for (n = 0; n < insn->n; n++) {
> +		val = data[n];
> +		outw(val, dev->iobase + ofs);
> +	}
>
> -	devpriv->ao_data[chan] = data[n];
> +	devpriv->ao_data[chan] = val;
>
>   	return n;
>
> @@ -679,6 +683,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
>   				 struct comedi_insn *insn, unsigned int *data)
>   {
>   	struct pci1710_private *devpriv = dev->private;
> +	unsigned int val;
>   	int n, rangereg, chan;
>
>   	chan = CR_CHAN(insn->chanspec);
> @@ -688,13 +693,15 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
>   		outb(rangereg, dev->iobase + PCI1720_RANGE);
>   		devpriv->da_ranges = rangereg;
>   	}
> +	val = devpriv->ao_data[chan];
>
>   	for (n = 0; n < insn->n; n++) {
> -		outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
> +		val = data[n];
> +		outw(val, dev->iobase + PCI1720_DA0 + (chan << 1));
>   		outb(0, dev->iobase + PCI1720_SYNCOUT);	/*  update outputs */
>   	}
>
> -	devpriv->ao_data[chan] = data[n];
> +	devpriv->ao_data[chan] = val;
>
>   	return n;
>   }
>

I'd have done:

	if (n)
		devpriv->ao_data[chan] = val;

and initialized val to 0 (in case the compiler issues a false 
"uninitialized" warning), just because it seems a tad more optimizable 
that way.  It doesn't matter though; your way is fine too!

Reviewed-by: Ian Abbott <abbotti at mev.co.uk>

-- 
-=( Ian Abbott @ MEV Ltd.    E-mail: <abbotti at mev.co.uk>        )=-
-=( Tel: +44 (0)161 477 1898   FAX: +44 (0)161 718 3587         )=-


More information about the devel mailing list