[PATCH 9/9] staging: comedi: put command channel list in async structure

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

 



`struct comedi_async` has a `struct comedi_cmd` embedded in it, which
includes a channel list pointer `chanlist` tagged as `__user`.  We want
to avoid mixing user-space pointers and kernel-space pointers.

Add an extra `chanlist` pointer to `struct comedi_async` to hold the
kernel copy of the channel list, and avoid using the one in the embedded
`struct comedi_cmd`.

This involves changes to the comedi core and most of the low-level
drivers that support asynchronous comedi commands.

Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
---
 drivers/staging/comedi/comedi_fops.c               | 15 ++--
 drivers/staging/comedi/comedidev.h                 |  1 +
 .../comedi/drivers/addi-data/hwdrv_apci3120.c      |  5 +-
 .../comedi/drivers/addi-data/hwdrv_apci3200.c      | 11 +--
 drivers/staging/comedi/drivers/adl_pci9111.c       |  5 +-
 drivers/staging/comedi/drivers/adl_pci9118.c       |  5 +-
 drivers/staging/comedi/drivers/adv_pci1710.c       |  5 +-
 drivers/staging/comedi/drivers/amplc_dio200.c      |  9 ++-
 drivers/staging/comedi/drivers/amplc_pci224.c      | 14 ++--
 drivers/staging/comedi/drivers/amplc_pci230.c      | 27 ++++---
 drivers/staging/comedi/drivers/cb_pcidas.c         | 19 ++---
 drivers/staging/comedi/drivers/cb_pcidas64.c       | 92 ++++++++++++----------
 drivers/staging/comedi/drivers/comedi_test.c       |  7 +-
 drivers/staging/comedi/drivers/das16.c             |  7 +-
 drivers/staging/comedi/drivers/das16m1.c           |  5 +-
 drivers/staging/comedi/drivers/das1800.c           | 20 ++---
 drivers/staging/comedi/drivers/das800.c            |  5 +-
 drivers/staging/comedi/drivers/dmm32at.c           | 10 ++-
 drivers/staging/comedi/drivers/dt2814.c            |  6 +-
 drivers/staging/comedi/drivers/dt282x.c            |  8 +-
 drivers/staging/comedi/drivers/dt3000.c            | 10 ++-
 drivers/staging/comedi/drivers/me4000.c            | 24 +++---
 drivers/staging/comedi/drivers/ni_at_a2150.c       |  7 +-
 drivers/staging/comedi/drivers/ni_atmio16d.c       |  8 +-
 drivers/staging/comedi/drivers/ni_labpc.c          | 11 +--
 drivers/staging/comedi/drivers/ni_mio_common.c     | 38 +++++----
 drivers/staging/comedi/drivers/pcl711.c            |  6 +-
 drivers/staging/comedi/drivers/pcl812.c            |  6 +-
 drivers/staging/comedi/drivers/pcl816.c            |  8 +-
 drivers/staging/comedi/drivers/pcl818.c            |  8 +-
 drivers/staging/comedi/drivers/pcmmio.c            | 17 ++--
 drivers/staging/comedi/drivers/pcmuio.c            | 17 ++--
 drivers/staging/comedi/drivers/quatech_daqp_cs.c   |  6 +-
 drivers/staging/comedi/drivers/rtd520.c            |  9 ++-
 drivers/staging/comedi/drivers/s626.c              | 23 +++---
 drivers/staging/comedi/drivers/usbdux.c            | 15 ++--
 drivers/staging/comedi/drivers/usbduxfast.c        | 24 +++---
 drivers/staging/comedi/drivers/usbduxsigma.c       | 10 ++-
 38 files changed, 297 insertions(+), 226 deletions(-)

diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index a2efe74..09ca61d 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1197,16 +1197,17 @@ static int do_cmd_ioctl(struct comedi_device *dev,
 
 	async->cmd = cmd;
 	async->cmd.data = NULL;
+	async->cmd.chanlist = NULL;
 	/* load channel/gain list */
-	async->cmd.chanlist =
+	async->chanlist =
 	    kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
-	if (!async->cmd.chanlist) {
+	if (!async->chanlist) {
 		DPRINTK("allocation failed\n");
 		ret = -ENOMEM;
 		goto cleanup;
 	}
 
-	if (copy_from_user(async->cmd.chanlist, user_chanlist,
+	if (copy_from_user(async->chanlist, user_chanlist,
 			   async->cmd.chanlist_len * sizeof(int))) {
 		DPRINTK("fault reading chanlist\n");
 		ret = -EFAULT;
@@ -1216,13 +1217,13 @@ static int do_cmd_ioctl(struct comedi_device *dev,
 	/* make sure each element in channel/gain list is valid */
 	ret = comedi_check_chanlist(s,
 				    async->cmd.chanlist_len,
-				    async->cmd.chanlist);
+				    async->chanlist);
 	if (ret < 0) {
 		DPRINTK("bad chanlist\n");
 		goto cleanup;
 	}
 
-	ret = s->do_cmdtest(dev, s, &async->cmd, async->cmd.chanlist);
+	ret = s->do_cmdtest(dev, s, &async->cmd, async->chanlist);
 
 	if (async->cmd.flags & TRIG_BOGUS || ret) {
 		DPRINTK("test returned %d\n", ret);
@@ -2024,8 +2025,8 @@ static void do_become_nonbusy(struct comedi_device *dev,
 	if (async) {
 		comedi_reset_async_buf(async);
 		async->inttrig = NULL;
-		kfree(async->cmd.chanlist);
-		async->cmd.chanlist = NULL;
+		kfree(async->chanlist);
+		async->chanlist = NULL;
 	} else {
 		dev_err(dev->class_dev,
 			"BUG: (?) do_become_nonbusy called with async=NULL\n");
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 4501cda..5a75fb3 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -169,6 +169,7 @@ struct comedi_async {
 	unsigned int events;	/* events that have occurred */
 
 	struct comedi_cmd cmd;
+	unsigned int *chanlist;
 
 	wait_queue_head_t wait_head;
 
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index ab1be36..7a9c98b 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -640,13 +640,14 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev,
 
 int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
 
 	/* loading private structure with cmd structure inputs */
 	devpriv->ui_AiFlags = cmd->flags;
 	devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
 	devpriv->ui_AiScanLength = cmd->scan_end_arg;
-	devpriv->pui_AiChannelList = cmd->chanlist;
+	devpriv->pui_AiChannelList = async->chanlist;
 
 	/* UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; */
 	devpriv->AiData = s->async->prealloc_buf;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 5d6e3b0..1bb6612 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -2811,7 +2811,8 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
 
 int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
 	unsigned int ui_Configuration = 0;
 	/* INT  i_CurrentSource = 0; */
 	unsigned int ui_Trigger = 0;
@@ -2823,10 +2824,10 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
 	unsigned int ui_DelayTime = 0;
 	unsigned int ui_DelayTimeBase = 0;
 	unsigned int ui_DelayMode = 0;
-	/* i_FirstChannel=cmd->chanlist[0]; */
-	/* i_LastChannel=cmd->chanlist[1]; */
-	s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
-	s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+	/* i_FirstChannel=async->chanlist[0]; */
+	/* i_LastChannel=async->chanlist[1]; */
+	s_BoardInfos[dev->minor].i_FirstChannel = async->chanlist[0];
+	s_BoardInfos[dev->minor].i_LastChannel = async->chanlist[1];
 	if (cmd->start_src == TRIG_EXT) {
 		ui_Trigger = 1;
 		ui_TriggerEdge = cmd->start_arg & 0xFFFF;
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index fce0dc9..6e433fb 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -500,6 +500,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 {
 	struct pci9111_private_data *dev_private = dev->private;
 	struct comedi_cmd *async_cmd = &s->async->cmd;
+	const unsigned int *chanlist = s->async->chanlist;
 
 	if (!dev->irq) {
 		comedi_error(dev,
@@ -515,7 +516,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 			dev->iobase + PCI9111_AI_CHANNEL_REG);
 		pci9111_autoscan_set(dev, true);
 	} else {
-		outb(CR_CHAN(async_cmd->chanlist[0]),
+		outb(CR_CHAN(chanlist[0]),
 			dev->iobase + PCI9111_AI_CHANNEL_REG);
 		pci9111_autoscan_set(dev, false);
 	}
@@ -523,7 +524,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 	/*  Set gain */
 	/*  This is the same gain on every channel */
 
-	outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
+	outb(CR_RANGE(chanlist[0]) & PCI9111_AI_RANGE_MASK,
 		dev->iobase + PCI9111_AI_RANGE_STAT_REG);
 
 	/* Set counter */
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index c674a18..77666fe 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -1615,7 +1615,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct boardtype *this_board = comedi_board(dev);
 	struct pci9118_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
 	unsigned int addchans = 0;
 	int ret = 0;
 
@@ -1623,7 +1624,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_n_chan = cmd->chanlist_len;
 	devpriv->ai_n_scanlen = cmd->scan_end_arg;
-	devpriv->ai_chanlist = cmd->chanlist;
+	devpriv->ai_chanlist = async->chanlist;
 	devpriv->ai_data = s->async->prealloc_buf;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
 	devpriv->ai_timer1 = 0;
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 37e558d..04db7be 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -1144,10 +1144,11 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
 static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pci1710_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
 
 	devpriv->ai_n_chan = cmd->chanlist_len;
-	devpriv->ai_chanlist = cmd->chanlist;
+	devpriv->ai_chanlist = async->chanlist;
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
 	devpriv->ai_data = s->async->prealloc_buf;
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index cb0fe2d..3a8c64d 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -580,7 +580,8 @@ static int dio200_start_intr(struct comedi_device *dev,
 	unsigned int n;
 	unsigned isn_bits;
 	struct dio200_subdev_intr *subpriv = s->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
 	int retval = 0;
 
 	if (!subpriv->continuous && subpriv->stopcount == 0) {
@@ -591,9 +592,9 @@ static int dio200_start_intr(struct comedi_device *dev,
 	} else {
 		/* Determine interrupt sources to enable. */
 		isn_bits = 0;
-		if (cmd->chanlist) {
+		if (async->chanlist) {
 			for (n = 0; n < cmd->chanlist_len; n++)
-				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
+				isn_bits |= (1U << CR_CHAN(async->chanlist[n]));
 		}
 		isn_bits &= subpriv->valid_isns;
 		/* Enable interrupt sources. */
@@ -705,7 +706,7 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
 				val = 0;
 				len = s->async->cmd.chanlist_len;
 				for (n = 0; n < len; n++) {
-					ch = CR_CHAN(s->async->cmd.chanlist[n]);
+					ch = CR_CHAN(s->async->chanlist[n]);
 					if (triggered & (1U << ch))
 						val |= (1U << n);
 				}
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 338316d..f996f1b 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -988,7 +988,9 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pci224_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int range;
 	unsigned int i, j;
 	unsigned int ch;
@@ -996,7 +998,7 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	unsigned long flags;
 
 	/* Cannot handle null/empty chanlist. */
-	if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
+	if (chanlist == NULL || cmd->chanlist_len == 0)
 		return -EINVAL;
 
 
@@ -1004,11 +1006,11 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->ao_enab = 0;
 
 	for (i = 0; i < cmd->chanlist_len; i++) {
-		ch = CR_CHAN(cmd->chanlist[i]);
+		ch = CR_CHAN(chanlist[i]);
 		devpriv->ao_enab |= 1U << ch;
 		rank = 0;
 		for (j = 0; j < cmd->chanlist_len; j++) {
-			if (CR_CHAN(cmd->chanlist[j]) < ch)
+			if (CR_CHAN(chanlist[j]) < ch)
 				rank++;
 
 		}
@@ -1019,7 +1021,7 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
 
 	/* Determine range and polarity.  All channels the same.  */
-	range = CR_RANGE(cmd->chanlist[0]);
+	range = CR_RANGE(chanlist[0]);
 
 	/*
 	 * Set DAC range and polarity.
@@ -1172,7 +1174,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 	/* The hardware expects 16-bit numbers. */
 	shift = 16 - thisboard->ao_bits;
 	/* Channels will be all bipolar or all unipolar. */
-	if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] &
+	if ((devpriv->hwrange[CR_RANGE(async->chanlist[0])] &
 	     PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
 		/* Unipolar */
 		offset = 0;
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 301367a..6a116d0 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -1225,6 +1225,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
 	int i, ret;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
 	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
 		return;
@@ -1238,7 +1239,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
 			return;
 		}
 		/* Write value to DAC. */
-		pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
+		pci230_ao_write_nofifo(dev, data, CR_CHAN(chanlist[i]));
 	}
 	async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
 	if (!devpriv->ao_continuous) {
@@ -1259,6 +1260,7 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
 	struct pci230_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int num_scans;
 	unsigned int room;
 	unsigned short dacstat;
@@ -1318,7 +1320,7 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
 
 				comedi_buf_get(async, &datum);
 				pci230_ao_write_fifo(dev, datum,
-						     CR_CHAN(cmd->chanlist[i]));
+						     CR_CHAN(chanlist[i]));
 			}
 		}
 		events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
@@ -1497,12 +1499,12 @@ static int pci230_ao_inttrig_start(struct comedi_device *dev,
 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pci230_private *devpriv = dev->private;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned short daccon;
 	unsigned int range;
 
-	/* Get the command. */
-	struct comedi_cmd *cmd = &s->async->cmd;
-
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		/* Claim Z2-CT1. */
 		if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
@@ -1522,7 +1524,7 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* Set range - see analogue output range table; 0 => unipolar 10V,
 	 * 1 => bipolar +/-10V range scale */
-	range = CR_RANGE(cmd->chanlist[0]);
+	range = CR_RANGE(chanlist[0]);
 	devpriv->ao_bipolar = pci230_ao_bipolar[range];
 	daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
 	/* Use DAC FIFO for hardware version 2 onwards. */
@@ -1532,7 +1534,7 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 		dacen = 0;
 		for (i = 0; i < cmd->chanlist_len; i++)
-			dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
+			dacen |= 1 << CR_CHAN(chanlist[i]);
 
 		/* Set channel scan list. */
 		outw(dacen, dev->iobase + PCI230P2_DACEN);
@@ -2396,10 +2398,9 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	unsigned int res_mask;
 	unsigned short adccon, adcen;
 	unsigned char zgat;
-
-	/* Get the command. */
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
 	/*
 	 * Determine which shared resources are needed.
@@ -2452,7 +2453,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	adccon = PCI230_ADC_FIFO_EN;
 	adcen = 0;
 
-	if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
+	if (CR_AREF(chanlist[0]) == AREF_DIFF) {
 		/* Differential - all channels must be differential. */
 		diff = 1;
 		adccon |= PCI230_ADC_IM_DIF;
@@ -2462,7 +2463,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		adccon |= PCI230_ADC_IM_SE;
 	}
 
-	range = CR_RANGE(cmd->chanlist[0]);
+	range = CR_RANGE(chanlist[0]);
 	devpriv->ai_bipolar = pci230_ai_bipolar[range];
 	if (devpriv->ai_bipolar)
 		adccon |= PCI230_ADC_IR_BIP;
@@ -2472,8 +2473,8 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	for (i = 0; i < cmd->chanlist_len; i++) {
 		unsigned int gainshift;
 
-		chan = CR_CHAN(cmd->chanlist[i]);
-		range = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		range = CR_RANGE(chanlist[i]);
 		if (diff) {
 			gainshift = 2 * chan;
 			if (devpriv->hwver == 0) {
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index ff505952..0868b5f 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -988,6 +988,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 	struct cb_pcidas_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int bits;
 	unsigned long flags;
 
@@ -999,14 +1000,14 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
 
 	/*  set mux limits, gain and pacer source */
-	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
-	    END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
-	    GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
+	bits = BEGIN_SCAN(CR_CHAN(chanlist[0])) |
+	    END_SCAN(CR_CHAN(chanlist[cmd->chanlist_len - 1])) |
+	    GAIN_BITS(CR_RANGE(chanlist[0]));
 	/*  set unipolar/bipolar */
-	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
+	if (CR_RANGE(chanlist[0]) & IS_UNIPOLAR)
 		bits |= UNIP;
 	/*  set singleended/differential */
-	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
+	if (CR_AREF(chanlist[0]) != AREF_DIFF)
 		bits |= SE;
 	/*  set pacer source */
 	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
@@ -1256,6 +1257,7 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
 	struct cb_pcidas_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int i;
 	unsigned long flags;
 
@@ -1264,11 +1266,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
 	for (i = 0; i < cmd->chanlist_len; i++) {
 		/*  enable channel */
 		devpriv->ao_control_bits |=
-		    DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
+		    DAC_CHAN_EN(CR_CHAN(chanlist[i]));
 		/*  set range */
-		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
-						      CR_RANGE(cmd->
-							       chanlist[i]));
+		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(chanlist[i]),
+						      CR_RANGE(chanlist[i]));
 	}
 
 	/*  disable analog out before settings pacer source and count values */
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 75c51f0..fb77a8a 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -2515,48 +2515,50 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
 	DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
 }
 
-static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
+static int use_internal_queue_6xxx(const unsigned int *chanlist,
+				   unsigned int chanlist_len)
 {
-	int i;
-	for (i = 0; i + 1 < cmd->chanlist_len; i++) {
-		if (CR_CHAN(cmd->chanlist[i + 1]) !=
-		    CR_CHAN(cmd->chanlist[i]) + 1)
+	unsigned int i;
+
+	for (i = 0; i + 1 < chanlist_len; i++) {
+		if (CR_CHAN(chanlist[i + 1]) != CR_CHAN(chanlist[i]) + 1)
 			return 0;
-		if (CR_RANGE(cmd->chanlist[i + 1]) !=
-		    CR_RANGE(cmd->chanlist[i]))
+		if (CR_RANGE(chanlist[i + 1]) != CR_RANGE(chanlist[i]))
 			return 0;
-		if (CR_AREF(cmd->chanlist[i + 1]) != CR_AREF(cmd->chanlist[i]))
+		if (CR_AREF(chanlist[i + 1]) != CR_AREF(chanlist[i]))
 			return 0;
 	}
 	return 1;
 }
 
 static int setup_channel_queue(struct comedi_device *dev,
-			       const struct comedi_cmd *cmd)
+			       const struct comedi_async *async)
 {
+	const struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned short bits;
 	int i;
 
 	if (board(dev)->layout != LAYOUT_4020) {
-		if (use_internal_queue_6xxx(cmd)) {
+		if (use_internal_queue_6xxx(chanlist, cmd->chanlist_len)) {
 			priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
 			writew(priv(dev)->hw_config_bits,
 			       priv(dev)->main_iobase + HW_CONFIG_REG);
 			bits = 0;
 			/*  set channel */
-			bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0]));
+			bits |= adc_chan_bits(CR_CHAN(chanlist[0]));
 			/*  set gain */
 			bits |= ai_range_bits_6xxx(dev,
-						   CR_RANGE(cmd->chanlist[0]));
+						   CR_RANGE(chanlist[0]));
 			/*  set single-ended / differential */
 			bits |= se_diff_bit_6xxx(dev,
-						 CR_AREF(cmd->chanlist[0]) ==
+						 CR_AREF(chanlist[0]) ==
 						 AREF_DIFF);
-			if (CR_AREF(cmd->chanlist[0]) == AREF_COMMON)
+			if (CR_AREF(chanlist[0]) == AREF_COMMON)
 				bits |= ADC_COMMON_BIT;
 			/*  set stop channel */
 			writew(adc_chan_bits
-			       (CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])),
+			       (CR_CHAN(chanlist[cmd->chanlist_len - 1])),
 			       priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
 			/*  set start channel, and rest of settings */
 			writew(bits,
@@ -2579,19 +2581,15 @@ static int setup_channel_queue(struct comedi_device *dev,
 			for (i = 0; i < cmd->chanlist_len; i++) {
 				bits = 0;
 				/*  set channel */
-				bits |=
-				    adc_chan_bits(CR_CHAN(cmd->chanlist[i]));
+				bits |= adc_chan_bits(CR_CHAN(chanlist[i]));
 				/*  set gain */
 				bits |= ai_range_bits_6xxx(dev,
-							   CR_RANGE(cmd->
-								    chanlist
-								    [i]));
+							CR_RANGE(chanlist[i]));
 				/*  set single-ended / differential */
 				bits |= se_diff_bit_6xxx(dev,
-							 CR_AREF(cmd->
-								 chanlist[i]) ==
+							 CR_AREF(chanlist[i]) ==
 							 AREF_DIFF);
-				if (CR_AREF(cmd->chanlist[i]) == AREF_COMMON)
+				if (CR_AREF(chanlist[i]) == AREF_COMMON)
 					bits |= ADC_COMMON_BIT;
 				/*  mark end of queue */
 				if (i == cmd->chanlist_len - 1)
@@ -2619,8 +2617,8 @@ static int setup_channel_queue(struct comedi_device *dev,
 		priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
 		/*  select ranges */
 		for (i = 0; i < cmd->chanlist_len; i++) {
-			unsigned int channel = CR_CHAN(cmd->chanlist[i]);
-			unsigned int range = CR_RANGE(cmd->chanlist[i]);
+			unsigned int channel = CR_CHAN(chanlist[i]);
+			unsigned int range = CR_RANGE(chanlist[i]);
 
 			if (range == 0)
 				priv(dev)->i2c_cal_range_bits |=
@@ -2671,6 +2669,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	uint32_t bits;
 	unsigned int i;
 	unsigned long flags;
@@ -2679,7 +2678,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	disable_ai_pacing(dev);
 	abort_dma(dev, 1);
 
-	retval = setup_channel_queue(dev, cmd);
+	retval = setup_channel_queue(dev, async);
 	if (retval < 0)
 		return retval;
 
@@ -2710,12 +2709,11 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 			priv(dev)->adc_control1_bits |= TWO_CHANNEL_4020_BITS;
 		priv(dev)->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK;
 		priv(dev)->adc_control1_bits |=
-		    adc_lo_chan_4020_bits(CR_CHAN(cmd->chanlist[0]));
+		    adc_lo_chan_4020_bits(CR_CHAN(chanlist[0]));
 		priv(dev)->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK;
 		priv(dev)->adc_control1_bits |=
-		    adc_hi_chan_4020_bits(CR_CHAN
-					  (cmd->
-					   chanlist[cmd->chanlist_len - 1]));
+		    adc_hi_chan_4020_bits(CR_CHAN(chanlist[cmd->chanlist_len
+							   - 1]));
 	}
 	writew(priv(dev)->adc_control1_bits,
 	       priv(dev)->main_iobase + ADC_CONTROL1_REG);
@@ -3247,15 +3245,16 @@ static void set_dac_control0_reg(struct comedi_device *dev,
 }
 
 static void set_dac_control1_reg(struct comedi_device *dev,
-				 const struct comedi_cmd *cmd)
+				 const unsigned int *chanlist,
+				 unsigned int chanlist_len)
 {
-	int i;
+	unsigned int i;
 
-	for (i = 0; i < cmd->chanlist_len; i++) {
+	for (i = 0; i < chanlist_len; i++) {
 		int channel, range;
 
-		channel = CR_CHAN(cmd->chanlist[i]);
-		range = CR_RANGE(cmd->chanlist[i]);
+		channel = CR_CHAN(chanlist[i]);
+		range = CR_RANGE(chanlist[i]);
 		set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, channel,
 				   range);
 	}
@@ -3265,13 +3264,14 @@ static void set_dac_control1_reg(struct comedi_device *dev,
 }
 
 static void set_dac_select_reg(struct comedi_device *dev,
-			       const struct comedi_cmd *cmd)
+			       const unsigned int *chanlist,
+			       unsigned int chanlist_len)
 {
 	uint16_t bits;
 	unsigned int first_channel, last_channel;
 
-	first_channel = CR_CHAN(cmd->chanlist[0]);
-	last_channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
+	first_channel = CR_CHAN(chanlist[0]);
+	last_channel = CR_CHAN(chanlist[chanlist_len - 1]);
 	if (last_channel < first_channel)
 		comedi_error(dev, "bug! last ao channel < first ao channel");
 
@@ -3404,18 +3404,24 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 
 static inline int external_ai_queue_in_use(struct comedi_device *dev)
 {
-	if (dev->read_subdev->busy)
+	struct comedi_subdevice *s = dev->read_subdev;
+
+	if (s->busy)
 		return 0;
 	if (board(dev)->layout == LAYOUT_4020)
 		return 0;
-	else if (use_internal_queue_6xxx(&dev->read_subdev->async->cmd))
+	else if (use_internal_queue_6xxx(s->async->chanlist,
+					 s->async->cmd.chanlist_len))
 		return 0;
 	return 1;
 }
 
 static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
+	unsigned int chanlist_len = cmd->chanlist_len;
 
 	if (external_ai_queue_in_use(dev)) {
 		warn_external_queue(dev);
@@ -3427,12 +3433,12 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	priv(dev)->ao_dma_index = 0;
 	priv(dev)->ao_count = cmd->stop_arg * cmd->chanlist_len;
 
-	set_dac_select_reg(dev, cmd);
+	set_dac_select_reg(dev, chanlist, chanlist_len);
 	set_dac_interval_regs(dev, cmd);
 	load_first_dma_descriptor(dev, 0, priv(dev)->ao_dma_desc_bus_addr |
 				  PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT);
 
-	set_dac_control1_reg(dev, cmd);
+	set_dac_control1_reg(dev, chanlist, chanlist_len);
 	s->async->inttrig = ao_inttrig;
 
 	return 0;
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index cb5fc87..d21b390 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -171,6 +171,7 @@ static void waveform_ai_interrupt(unsigned long arg)
 	struct waveform_private *devpriv = dev->private;
 	struct comedi_async *async = dev->read_subdev->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int i, j;
 	/* all times in microsec */
 	unsigned long elapsed_time;
@@ -193,10 +194,8 @@ static void waveform_ai_interrupt(unsigned long arg)
 		for (j = 0; j < cmd->chanlist_len; j++) {
 			cfc_write_to_buffer(dev->read_subdev,
 					    fake_waveform(dev,
-							  CR_CHAN(cmd->
-								  chanlist[j]),
-							  CR_RANGE(cmd->
-								   chanlist[j]),
+							  CR_CHAN(chanlist[j]),
+							  CR_RANGE(chanlist[j]),
 							  devpriv->
 							  usec_current +
 							  i *
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index b0bfacf..e30374a 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -617,6 +617,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 	const struct das16_board *board = comedi_board(dev);
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int byte;
 	unsigned long flags;
 	int range;
@@ -642,15 +643,15 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
 
 	/*  set scan limits */
-	byte = CR_CHAN(cmd->chanlist[0]);
-	byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
+	byte = CR_CHAN(chanlist[0]);
+	byte |= CR_CHAN(chanlist[cmd->chanlist_len - 1]) << 4;
 	outb(byte, dev->iobase + DAS16_MUX);
 
 	/* set gain (this is also burst rate register but according to
 	 * computer boards manual, burst rate does nothing, even on
 	 * keithley cards) */
 	if (board->ai_pg != das16_pg_none) {
-		range = CR_RANGE(cmd->chanlist[0]);
+		range = CR_RANGE(chanlist[0]);
 		outb((das16_gainlists[board->ai_pg])[range],
 		     dev->iobase + DAS16_GAIN);
 	}
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index abb9600..e95a462 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -314,6 +314,7 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
 {
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int byte, i;
 
 	if (dev->irq == 0) {
@@ -339,8 +340,8 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
 	for (i = 0; i < cmd->chanlist_len; i++) {
 		outb(i, dev->iobase + DAS16M1_QUEUE_ADDR);
 		byte =
-		    Q_CHAN(CR_CHAN(cmd->chanlist[i])) |
-		    Q_RANGE(CR_RANGE(cmd->chanlist[i]));
+		    Q_CHAN(CR_CHAN(chanlist[i])) |
+		    Q_RANGE(CR_RANGE(chanlist[i]));
 		outb(byte, dev->iobase + DAS16M1_QUEUE_DATA);
 	}
 
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 99aad86..f1437ce 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -981,7 +981,8 @@ static int control_a_bits(const struct comedi_cmd *cmd)
 }
 
 /* returns appropriate bits for control register c, depending on command */
-static int control_c_bits(const struct comedi_cmd *cmd)
+static int control_c_bits(const struct comedi_cmd *cmd,
+			  const unsigned int *chanlist)
 {
 	int control_c;
 	int aref;
@@ -989,14 +990,14 @@ static int control_c_bits(const struct comedi_cmd *cmd)
 	/* set clock source to internal or external, select analog reference,
 	 * select unipolar / bipolar
 	 */
-	aref = CR_AREF(cmd->chanlist[0]);
+	aref = CR_AREF(chanlist[0]);
 	control_c = UQEN;	/* enable upper qram addresses */
 	if (aref != AREF_DIFF)
 		control_c |= SD;
 	if (aref == AREF_COMMON)
 		control_c |= CMEN;
 	/* if a unipolar range was selected */
-	if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
+	if (CR_RANGE(chanlist[0]) & UNIPOLAR)
 		control_c |= UB;
 	switch (cmd->scan_begin_src) {
 	case TRIG_FOLLOW:	/*  not in burst mode */
@@ -1169,7 +1170,8 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 
 /* programs channel/gain list into card */
 static void program_chanlist(struct comedi_device *dev,
-			     const struct comedi_cmd *cmd)
+			     const struct comedi_cmd *cmd,
+			     const unsigned int *chanlist)
 {
 	int i, n, chan_range;
 	unsigned long irq_flags;
@@ -1184,9 +1186,8 @@ static void program_chanlist(struct comedi_device *dev,
 	/* make channel / gain list */
 	for (i = 0; i < n; i++) {
 		chan_range =
-		    CR_CHAN(cmd->chanlist[i]) |
-		    ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
-		     range_bitshift);
+		    CR_CHAN(chanlist[i]) |
+		    ((CR_RANGE(chanlist[i]) & range_mask) << range_bitshift);
 		outw(chan_range, dev->iobase + DAS1800_QRAM);
 	}
 	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
@@ -1203,6 +1204,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
 	int control_a, control_c;
 	struct comedi_async *async = s->async;
 	const struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
 	if (!dev->irq) {
 		comedi_error(dev,
@@ -1232,10 +1234,10 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
 
 	/*  determine proper bits for control registers */
 	control_a = control_a_bits(cmd);
-	control_c = control_c_bits(cmd);
+	control_c = control_c_bits(cmd, chanlist);
 
 	/* setup card and start */
-	program_chanlist(dev, cmd);
+	program_chanlist(dev, cmd, chanlist);
 	ret = setup_counters(dev, cmd);
 	if (ret < 0) {
 		comedi_error(dev, "Error setting up counters");
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 273602f..d711e77 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -736,6 +736,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
 	int conv_bits;
 	unsigned long irq_flags;
 	struct comedi_async *async = s->async;
+	const unsigned int *chanlist = async->chanlist;
 
 	if (!dev->irq) {
 		comedi_error(dev,
@@ -746,7 +747,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
 	disable_das800(dev);
 
 	/* set channel scan limits */
-	startChan = CR_CHAN(async->cmd.chanlist[0]);
+	startChan = CR_CHAN(chanlist[0]);
 	endChan = (startChan + async->cmd.chanlist_len - 1) % 8;
 	scan = (endChan << 3) | startChan;
 
@@ -756,7 +757,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
 	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 
 	/* set gain */
-	gain = CR_RANGE(async->cmd.chanlist[0]);
+	gain = CR_RANGE(chanlist[0]);
 	if (thisboard->resolution == 12 && gain > 0)
 		gain += 0x7;
 	gain &= 0xf;
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 0add8c3..78e9b0b 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -461,19 +461,21 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec)
 static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct dmm32at_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int i, range;
 	unsigned char chanlo, chanhi, status;
 
-	if (!cmd->chanlist)
+	if (!chanlist)
 		return -EINVAL;
 
 	/* get the channel list and range */
-	chanlo = CR_CHAN(cmd->chanlist[0]) & (s->n_chan - 1);
+	chanlo = CR_CHAN(chanlist[0]) & (s->n_chan - 1);
 	chanhi = chanlo + cmd->chanlist_len - 1;
 	if (chanhi >= s->n_chan)
 		return -EINVAL;
-	range = CR_RANGE(cmd->chanlist[0]);
+	range = CR_RANGE(chanlist[0]);
 
 	/* reset fifo */
 	outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL);
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 41d04d1..500b686 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -219,7 +219,9 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
 static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int chan;
 	int trigvar;
 
@@ -227,7 +229,7 @@ static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	    dt2814_ns_to_timer(&cmd->scan_begin_arg,
 			       cmd->flags & TRIG_ROUND_MASK);
 
-	chan = CR_CHAN(cmd->chanlist[0]);
+	chan = CR_CHAN(chanlist[0]);
 
 	devpriv->ntrig = cmd->stop_arg;
 	outb(chan | DT2814_ENB | (trigvar << 5), dev->iobase + DT2814_CSR);
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index c66a158..21544fb 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -523,7 +523,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
 }
 
 static void dt282x_load_changain(struct comedi_device *dev, int n,
-				 unsigned int *chanlist)
+				 const unsigned int *chanlist)
 {
 	unsigned int i;
 	unsigned int chan, range;
@@ -695,7 +695,9 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct dt282x_board *board = comedi_board(dev);
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int timer;
 
 	if (devpriv->usedma == 0) {
@@ -736,7 +738,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	devpriv->adcsr = 0;
 
-	dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist);
+	dt282x_load_changain(dev, cmd->chanlist_len, chanlist);
 
 	devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE;
 	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 3338bf6..35ff218 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -567,7 +567,9 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
 
 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int i;
 	unsigned int chan, range, aref;
 	unsigned int divider;
@@ -577,13 +579,13 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n");
 	for (i = 0; i < cmd->chanlist_len; i++) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		range = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		range = CR_RANGE(chanlist[i]);
 
 		writew((range << 6) | chan,
 		       devpriv->io_addr + DPR_ADC_buffer + i);
 	}
-	aref = CR_AREF(cmd->chanlist[0]);
+	aref = CR_AREF(chanlist[0]);
 
 	writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
 	dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 6efe5e4..af31958 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -763,18 +763,20 @@ static void ai_write_timer(struct comedi_device *dev,
 }
 
 static int ai_write_chanlist(struct comedi_device *dev,
-			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
+			     struct comedi_subdevice *s,
+			     const unsigned int *chanlist,
+			     unsigned int chanlist_len)
 {
 	unsigned int entry;
 	unsigned int chan;
 	unsigned int rang;
 	unsigned int aref;
-	int i;
+	unsigned int i;
 
-	for (i = 0; i < cmd->chanlist_len; i++) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		rang = CR_RANGE(cmd->chanlist[i]);
-		aref = CR_AREF(cmd->chanlist[i]);
+	for (i = 0; i < chanlist_len; i++) {
+		chan = CR_CHAN(chanlist[i]);
+		rang = CR_RANGE(chanlist[i]);
+		aref = CR_AREF(chanlist[i]);
 
 		entry = chan;
 
@@ -801,6 +803,7 @@ static int ai_write_chanlist(struct comedi_device *dev,
 static int ai_prepare(struct comedi_device *dev,
 		      struct comedi_subdevice *s,
 		      struct comedi_cmd *cmd,
+		      const unsigned int *chanlist,
 		      unsigned int init_ticks,
 		      unsigned int scan_ticks, unsigned int chan_ticks)
 {
@@ -860,7 +863,7 @@ static int ai_prepare(struct comedi_device *dev,
 	outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
 
 	/* Write the channel list */
-	ai_write_chanlist(dev, s, cmd);
+	ai_write_chanlist(dev, s, chanlist, cmd->chanlist_len);
 
 	return 0;
 }
@@ -872,7 +875,9 @@ static int me4000_ai_do_cmd(struct comedi_device *dev,
 	unsigned int init_ticks = 0;
 	unsigned int scan_ticks = 0;
 	unsigned int chan_ticks = 0;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
 	/* Reset the analog input */
 	err = me4000_ai_cancel(dev, s);
@@ -886,7 +891,8 @@ static int me4000_ai_do_cmd(struct comedi_device *dev,
 		return err;
 
 	/* Prepare the AI for acquisition */
-	err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
+	err = ai_prepare(dev, s, cmd, chanlist,
+			 init_ticks, scan_ticks, chan_ticks);
 	if (err)
 		return err;
 
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 9445f4b..fec0f82 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -450,6 +450,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned long lock_flags;
 	unsigned int old_config_bits = devpriv->config_bits;
 	unsigned int trigger_bits;
@@ -468,16 +469,16 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	outw(0, dev->iobase + FIFO_RESET_REG);
 
 	/* setup chanlist */
-	if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]),
+	if (a2150_set_chanlist(dev, CR_CHAN(chanlist[0]),
 			       cmd->chanlist_len) < 0)
 		return -1;
 
 	/*  setup ac/dc coupling */
-	if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
+	if (CR_AREF(chanlist[0]) == AREF_OTHER)
 		devpriv->config_bits |= AC0_BIT;
 	else
 		devpriv->config_bits &= ~AC0_BIT;
-	if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER)
+	if (CR_AREF(chanlist[2]) == AREF_OTHER)
 		devpriv->config_bits |= AC1_BIT;
 	else
 		devpriv->config_bits &= ~AC1_BIT;
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index e7d5759..e7825f0 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -346,7 +346,9 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 static int atmio16d_ai_cmd(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int timer, base_clock;
 	unsigned int sample_count, tmp, chan, gain;
 	int i;
@@ -370,8 +372,8 @@ static int atmio16d_ai_cmd(struct comedi_device *dev,
 
 	/* Setup the Mux-Gain Counter */
 	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		gain = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		gain = CR_RANGE(chanlist[i]);
 		outw(i, dev->iobase + MUX_CNTR_REG);
 		tmp = chan | (gain << 6);
 		if (i == cmd->scan_end_arg - 1)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 63c5111..7136ae5 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -1128,6 +1128,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	int ret;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	enum transfer_type xfer;
 	enum scan_mode mode;
 	unsigned long flags;
@@ -1137,8 +1138,8 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		return -1;
 	}
 
-	range = CR_RANGE(cmd->chanlist[0]);
-	aref = CR_AREF(cmd->chanlist[0]);
+	range = CR_RANGE(chanlist[0]);
+	aref = CR_AREF(chanlist[0]);
 
 	/* make sure board is disabled before setting up acquisition */
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -1195,7 +1196,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	} else
 		xfer = fifo_not_empty_transfer;
 	devpriv->current_transfer = xfer;
-	mode = labpc_ai_scan_mode(cmd, cmd->chanlist);
+	mode = labpc_ai_scan_mode(cmd, chanlist);
 
 	/*  setup command6 register for 1200 boards */
 	if (thisboard->register_layout == labpc_1200_layout) {
@@ -1232,9 +1233,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	/* setup channel list, etc (command1 register) */
 	devpriv->command1_bits = 0;
 	if (mode == MODE_MULT_CHAN_UP)
-		channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
+		channel = CR_CHAN(chanlist[cmd->chanlist_len - 1]);
 	else
-		channel = CR_CHAN(cmd->chanlist[0]);
+		channel = CR_CHAN(chanlist[0]);
 	/* munge channel bits for differential / scan disabled mode */
 	if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF)
 		channel *= 2;
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 54a2164..3606c0f 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -297,7 +297,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev);
 static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 			 unsigned int trignum);
 static void ni_load_channelgain_list(struct comedi_device *dev,
-				     unsigned int n_chan, unsigned int *list);
+				     unsigned int n_chan,
+				     const unsigned int *list);
 static void shutdown_ai_command(struct comedi_device *dev);
 
 static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -1262,6 +1263,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
 {
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int chan;
 	int i;
 	short d;
@@ -1275,7 +1277,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
 		if (err == 0)
 			break;
 
-		range = CR_RANGE(cmd->chanlist[chan]);
+		range = CR_RANGE(chanlist[chan]);
 
 		if (boardtype.reg_type & ni_reg_6xxx_mask) {
 			packed_data = d & 0xffff;
@@ -1901,7 +1903,7 @@ static void ni_prime_channelgain_list(struct comedi_device *dev)
 
 static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 					      unsigned int n_chan,
-					      unsigned int *list)
+					      const unsigned int *list)
 {
 	unsigned int chan, range, aref;
 	unsigned int i;
@@ -2006,7 +2008,8 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
  *       valid channels are 0-3
  */
 static void ni_load_channelgain_list(struct comedi_device *dev,
-				     unsigned int n_chan, unsigned int *list)
+				     unsigned int n_chan,
+				     const unsigned int *list)
 {
 	unsigned int chan, range, aref;
 	unsigned int i;
@@ -2383,7 +2386,9 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct comedi_cmd *cmd = &s->async->cmd;
+	const struct comedi_async *async = s->async;
+	const struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int timer;
 	int mode1 = 0;		/* mode1 is needed for both stop and convert */
 	int mode2 = 0;
@@ -2398,7 +2403,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	}
 	ni_clear_ai_fifo(dev);
 
-	ni_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
+	ni_load_channelgain_list(dev, cmd->chanlist_len, chanlist);
 
 	/* start configuration */
 	devpriv->stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register);
@@ -2860,6 +2865,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 			unsigned int chan_index)
 {
 	struct comedi_async *async = s->async;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int range;
 	unsigned int i;
 	unsigned int offset;
@@ -2868,7 +2874,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	offset = 1 << (boardtype.aobits - 1);
 	for (i = 0; i < length; i++) {
-		range = CR_RANGE(async->cmd.chanlist[chan_index]);
+		range = CR_RANGE(chanlist[chan_index]);
 		if (boardtype.ao_unipolar == 0 || (range & 1) == 0)
 			array[i] -= offset;
 #ifdef PCIDMA
@@ -2881,7 +2887,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
 					  struct comedi_subdevice *s,
-					  unsigned int chanspec[],
+					  const unsigned int chanspec[],
 					  unsigned int n_chans, int timed)
 {
 	unsigned int range;
@@ -2952,7 +2958,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
 
 static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 				     struct comedi_subdevice *s,
-				     unsigned int chanspec[],
+				     const unsigned int chanspec[],
 				     unsigned int n_chans)
 {
 	unsigned int range;
@@ -2997,8 +3003,8 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 
 static int ni_ao_config_chanlist(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 unsigned int chanspec[], unsigned int n_chans,
-				 int timed)
+				 const unsigned int chanspec[],
+				 unsigned int n_chans, int timed)
 {
 	if (boardtype.reg_type & ni_reg_m_series_mask)
 		return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans,
@@ -3153,7 +3159,9 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct comedi_cmd *cmd = &s->async->cmd;
+	const struct comedi_async *async = s->async;
+	const struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int bits;
 	int i;
 	unsigned trigvar;
@@ -3174,14 +3182,14 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		for (i = 0; i < cmd->chanlist_len; i++) {
 			int chan;
 
-			chan = CR_CHAN(cmd->chanlist[i]);
+			chan = CR_CHAN(chanlist[i]);
 			bits |= 1 << chan;
 			ao_win_out(chan, AO_Waveform_Generation_611x);
 		}
 		ao_win_out(bits, AO_Timed_611x);
 	}
 
-	ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
+	ni_ao_config_chanlist(dev, s, chanlist, cmd->chanlist_len, 1);
 
 	if (cmd->stop_src == TRIG_NONE) {
 		devpriv->ao_mode1 |= AO_Continuous;
@@ -3303,7 +3311,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 			bits |= AO_Number_Of_Channels(0);
 		} else {
 			bits |=
-			    AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0]));
+			    AO_Number_Of_Channels(CR_CHAN(chanlist[0]));
 		}
 		devpriv->stc_writew(dev, bits, AO_Output_Control_Register);
 	}
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 4acf5db..62127b4 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -368,9 +368,11 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	int timer1, timer2;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
-	pcl711_set_changain(dev, cmd->chanlist[0]);
+	pcl711_set_changain(dev, chanlist[0]);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		/*
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 44a0ad2..fc9ae5d 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -658,7 +658,9 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct pcl812_board *board = comedi_board(dev);
 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 
 	if (cmd->start_src != TRIG_NOW)
 		return -EINVAL;
@@ -690,7 +692,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
 
 	devpriv->ai_n_chan = cmd->chanlist_len;
-	memcpy(devpriv->ai_chanlist, cmd->chanlist,
+	memcpy(devpriv->ai_chanlist, chanlist,
 	       sizeof(unsigned int) * cmd->scan_end_arg);
 	/*  select first channel and range */
 	setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index af0cb088..8c9875b 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -582,7 +582,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct pcl816_board *board = comedi_board(dev);
 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	unsigned int seglen;
 
 	if (cmd->start_src != TRIG_NOW)
@@ -618,10 +620,10 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
 
-	seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
+	seglen = check_channel_list(dev, s, chanlist, cmd->chanlist_len);
 	if (seglen < 1)
 		return -EINVAL;
-	setup_channel_list(dev, s, cmd->chanlist, seglen);
+	setup_channel_list(dev, s, chanlist, seglen);
 	udelay(1);
 
 	devpriv->ai_n_chan = cmd->chanlist_len;
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 7d63fbd..d9d8290 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -310,7 +310,7 @@ struct pcl818_private {
 	unsigned int act_chanlist_pos;	/*  actual position in MUX list */
 	unsigned int ai_scans;	/*  len of scanlist */
 	unsigned int ai_n_chan;	/*  how many channels is measured */
-	unsigned int *ai_chanlist;	/*  actaul chanlist */
+	const unsigned int *ai_chanlist;	/*  actual chanlist */
 	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
 	short *ai_data;		/*  data buffer */
@@ -1377,12 +1377,14 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int retval;
 
 	dev_dbg(dev->class_dev, "pcl818_ai_cmd()\n");
 	devpriv->ai_n_chan = cmd->chanlist_len;
-	devpriv->ai_chanlist = cmd->chanlist;
+	devpriv->ai_chanlist = chanlist;
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
 	devpriv->ai_data = s->async->prealloc_buf;
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 2ab9cfc..e246c56 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -624,7 +624,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
 								for (n = 0;
 								     n < len;
 								     n++) {
-									ch = CR_CHAN(s->async->cmd.chanlist[n]);
+									ch = CR_CHAN(s->async->chanlist[n]);
 									if (mytrig & (1U << ch))
 										val |= (1U << n);
 								}
@@ -693,7 +693,9 @@ static int pcmmio_start_intr(struct comedi_device *dev,
 	} else {
 		unsigned bits = 0, pol_bits = 0, n;
 		int nports, firstport, asic, port;
-		struct comedi_cmd *cmd = &s->async->cmd;
+		struct comedi_async *async = s->async;
+		struct comedi_cmd *cmd = &async->cmd;
+		const unsigned int *chanlist = async->chanlist;
 
 		asic = subpriv->dio.intr.asic;
 		if (asic < 0)
@@ -703,13 +705,12 @@ static int pcmmio_start_intr(struct comedi_device *dev,
 		subpriv->dio.intr.active = 1;
 		nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT;
 		firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT;
-		if (cmd->chanlist) {
+		if (chanlist) {
 			for (n = 0; n < cmd->chanlist_len; n++) {
-				bits |= (1U << CR_CHAN(cmd->chanlist[n]));
-				pol_bits |= (CR_AREF(cmd->chanlist[n])
-					     || CR_RANGE(cmd->
-							 chanlist[n]) ? 1U : 0U)
-				    << CR_CHAN(cmd->chanlist[n]);
+				bits |= (1U << CR_CHAN(chanlist[n]));
+				pol_bits |= (CR_AREF(chanlist[n])
+					     || CR_RANGE(chanlist[n]) ? 1U : 0U)
+				    << CR_CHAN(chanlist[n]);
 			}
 		}
 		bits &= ((0x1 << subpriv->dio.intr.num_asic_chans) -
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 8a1f3ba..495923d 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -544,7 +544,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
 								for (n = 0;
 								     n < len;
 								     n++) {
-									ch = CR_CHAN(s->async->cmd.chanlist[n]);
+									ch = CR_CHAN(s->async->chanlist[n]);
 									if (mytrig & (1U << ch)) {
 										val |= (1U << n);
 									}
@@ -615,7 +615,9 @@ static int pcmuio_start_intr(struct comedi_device *dev,
 	} else {
 		unsigned bits = 0, pol_bits = 0, n;
 		int nports, firstport, asic, port;
-		struct comedi_cmd *cmd = &s->async->cmd;
+		struct comedi_async *async = s->async;
+		struct comedi_cmd *cmd = &async->cmd;
+		const unsigned int *chanlist = async->chanlist;
 
 		asic = subpriv->intr.asic;
 		if (asic < 0)
@@ -625,13 +627,12 @@ static int pcmuio_start_intr(struct comedi_device *dev,
 		subpriv->intr.active = 1;
 		nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
 		firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
-		if (cmd->chanlist) {
+		if (chanlist) {
 			for (n = 0; n < cmd->chanlist_len; n++) {
-				bits |= (1U << CR_CHAN(cmd->chanlist[n]));
-				pol_bits |= (CR_AREF(cmd->chanlist[n])
-					     || CR_RANGE(cmd->
-							 chanlist[n]) ? 1U : 0U)
-				    << CR_CHAN(cmd->chanlist[n]);
+				bits |= (1U << CR_CHAN(chanlist[n]));
+				pol_bits |= (CR_AREF(chanlist[n])
+					     || CR_RANGE(chanlist[n]) ? 1U : 0U)
+				    << CR_CHAN(chanlist[n]);
 			}
 		}
 		bits &= ((0x1 << subpriv->intr.num_asic_chans) -
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 56337fb..91bb314 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -582,7 +582,9 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
 static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct local_info_t *local = (struct local_info_t *)s->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int counter;
 	int scanlist_start_on_every_entry;
 	int threshold;
@@ -635,7 +637,7 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	for (i = 0; i < cmd->chanlist_len; i++) {
 
-		int chanspec = cmd->chanlist[i];
+		int chanspec = chanlist[i];
 
 		/* Program one scan list entry */
 
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 38db702..5e3c8cd 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -458,7 +458,8 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev,
   Setup the channel-gain table from a comedi list
 */
 static void rtd_load_channelgain_list(struct comedi_device *dev,
-				      unsigned int n_chan, unsigned int *list)
+				      unsigned int n_chan,
+				      const unsigned int *list)
 {
 	struct rtdPrivate *devpriv = dev->private;
 
@@ -1175,7 +1176,9 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct rtdPrivate *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	int timer;
 
 	/* stop anything currently running */
@@ -1210,7 +1213,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* start configuration */
 	/* load channel list and reset CGT */
-	rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
+	rtd_load_channelgain_list(dev, cmd->chanlist_len, chanlist);
 
 	/* setup the common case and override if needed */
 	if (cmd->chanlist_len > 1) {
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 8258edf8..ac02037 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1325,16 +1325,17 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 	return n;
 }
 
-static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
+static int s626_ai_load_polllist(uint8_t *ppl, const unsigned int *chanlist,
+				 unsigned int chanlist_len)
 {
 
-	int n;
+	unsigned int n;
 
-	for (n = 0; n < cmd->chanlist_len; n++) {
-		if (CR_RANGE((cmd->chanlist)[n]) == 0)
-			ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V);
+	for (n = 0; n < chanlist_len; n++) {
+		if (CR_RANGE(chanlist[n]) == 0)
+			ppl[n] = CR_CHAN(chanlist[n]) | RANGE_5V;
 		else
-			ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V);
+			ppl[n] = CR_CHAN(chanlist[n]) | RANGE_10V;
 	}
 	if (n != 0)
 		ppl[n - 1] |= EOPL;
@@ -1423,7 +1424,9 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 
 	uint8_t ppl[16];
-	struct comedi_cmd *cmd = &s->async->cmd;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	const unsigned int *chanlist = async->chanlist;
 	struct enc_private *k;
 	int tick;
 
@@ -1445,17 +1448,13 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	/* reset ai_cmd_running flag */
 	devpriv->ai_cmd_running = 0;
 
-	/*  test if cmd is valid */
-	if (cmd == NULL)
-		return -EINVAL;
-
 	if (dev->irq == 0) {
 		comedi_error(dev,
 			     "s626_ai_cmd: cannot run command without an irq");
 		return -EIO;
 	}
 
-	s626_ai_load_polllist(ppl, cmd);
+	s626_ai_load_polllist(ppl, chanlist, cmd->chanlist_len);
 	devpriv->ai_cmd_running = 1;
 	devpriv->ai_convert_count = 0;
 
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 34fc784..1d9403a 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -512,7 +512,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
 	n = s->async->cmd.chanlist_len;
 	for (i = 0; i < n; i++) {
 		/* transfer data */
-		if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
+		if (CR_RANGE(s->async->chanlist[i]) <= 1) {
 			err = comedi_buf_put
 			    (s->async,
 			     le16_to_cpu(this_usbduxsub->inBuffer[i]) ^ 0x800);
@@ -1194,6 +1194,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev,
 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned int *chanlist;
 	unsigned int chan, range;
 	int i, ret;
 	struct usbduxsub *this_usbduxsub = dev->private;
@@ -1221,11 +1222,11 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	}
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
-
+	chanlist = s->async->chanlist;
 	this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
 	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		range = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		range = CR_RANGE(chanlist[i]);
 		if (i >= NUMCHANNELS) {
 			dev_err(&this_usbduxsub->interface->dev,
 				"comedi%d: channel list too long\n",
@@ -1629,6 +1630,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned int *chanlist;
 	unsigned int chan, gain;
 	int i, ret;
 	struct usbduxsub *this_usbduxsub = dev->private;
@@ -1646,9 +1648,10 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
+	chanlist = s->async->chanlist;
 	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		gain = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		gain = CR_RANGE(chanlist[i]);
 		if (i >= NUMOUTCHANNELS) {
 			dev_err(&this_usbduxsub->interface->dev,
 				"comedi%d: %s: channel list too long\n",
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 4013b58..795a887 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -746,6 +746,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
 	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned int *chanlist;
 	unsigned int chan, gain, rngmask = 0xff;
 	int i, j, ret;
 	struct usbduxfastsub_s *udfs;
@@ -772,6 +773,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 	}
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
+	chanlist = s->async->chanlist;
 
 	/*
 	 * ignore the first buffers from the device if there
@@ -780,9 +782,9 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 	udfs->ignore = PACKETS_TO_IGNORE;
 
 	if (cmd->chanlist_len > 0) {
-		gain = CR_RANGE(cmd->chanlist[0]);
+		gain = CR_RANGE(chanlist[0]);
 		for (i = 0; i < cmd->chanlist_len; ++i) {
-			chan = CR_CHAN(cmd->chanlist[i]);
+			chan = CR_CHAN(chanlist[i]);
 			if (chan != i) {
 				printk(KERN_ERR "comedi%d: cmd is accepting "
 				       "only consecutive channels.\n",
@@ -790,7 +792,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 				up(&udfs->sem);
 				return -EINVAL;
 			}
-			if ((gain != CR_RANGE(cmd->chanlist[i]))
+			if ((gain != CR_RANGE(chanlist[i]))
 			    && (cmd->chanlist_len > 3)) {
 				printk(KERN_ERR "comedi%d: the gain must be"
 				       " the same for all channels.\n",
@@ -846,7 +848,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		 * one channel
 		 */
 
-		if (CR_RANGE(cmd->chanlist[0]) > 0)
+		if (CR_RANGE(chanlist[0]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
@@ -949,7 +951,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		 * commit data to the FIFO
 		 */
 
-		if (CR_RANGE(cmd->chanlist[0]) > 0)
+		if (CR_RANGE(chanlist[0]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
@@ -963,7 +965,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		/* we have 1 state with duration 1: state 0 */
 		steps_tmp = steps - 1;
 
-		if (CR_RANGE(cmd->chanlist[1]) > 0)
+		if (CR_RANGE(chanlist[1]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
@@ -993,7 +995,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		 */
 		steps_tmp = steps - 2;
 
-		if (CR_RANGE(cmd->chanlist[0]) > 0)
+		if (CR_RANGE(chanlist[0]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
@@ -1022,7 +1024,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		 * three channels
 		 */
 		for (j = 0; j < 1; j++) {
-			if (CR_RANGE(cmd->chanlist[j]) > 0)
+			if (CR_RANGE(chanlist[j]) > 0)
 				rngmask = 0xff - 0x04;
 			else
 				rngmask = 0xff;
@@ -1037,7 +1039,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 			udfs->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask;
 			udfs->dux_commands[LOGBASE + j * 2] = 0;
 
-			if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
+			if (CR_RANGE(chanlist[j + 1]) > 0)
 				rngmask = 0xff - 0x04;
 			else
 				rngmask = 0xff;
@@ -1063,7 +1065,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
 		udfs->dux_commands[LOGBASE + 4] = 0;
 
-		if (CR_RANGE(cmd->chanlist[0]) > 0)
+		if (CR_RANGE(chanlist[0]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
@@ -1082,7 +1084,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		udfs->dux_commands[LOGBASE + 6] = 0;
 
 	case 16:
-		if (CR_RANGE(cmd->chanlist[0]) > 0)
+		if (CR_RANGE(chanlist[0]) > 0)
 			rngmask = 0xff - 0x04;
 		else
 			rngmask = 0xff;
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index 9d60db8..5b46eb1 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1162,6 +1162,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev,
 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned int *chanlist;
 	unsigned int chan;
 	int i, ret;
 	struct usbduxsub *this_usbduxsub = dev->private;
@@ -1192,6 +1193,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	}
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
+	chanlist = s->async->chanlist;
 
 	/* first the number of channels per time step */
 	this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
@@ -1206,7 +1208,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	this_usbduxsub->dux_commands[4] = 0x00;
 
 	for (i = 0; i < cmd->chanlist_len; i++) {
-		chan = CR_CHAN(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
 		create_adc_command(chan, &muxsg0, &muxsg1);
 		if (i >= NUMCHANNELS) {
 			dev_err(&this_usbduxsub->interface->dev,
@@ -1693,6 +1695,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned int *chanlist;
 	unsigned int chan, gain;
 	int i, ret;
 	struct usbduxsub *this_usbduxsub = dev->private;
@@ -1710,9 +1713,10 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
+	chanlist = s->async->chanlist;
 	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		gain = CR_RANGE(cmd->chanlist[i]);
+		chan = CR_CHAN(chanlist[i]);
+		gain = CR_RANGE(chanlist[i]);
 		if (i >= NUMOUTCHANNELS) {
 			dev_err(&this_usbduxsub->interface->dev,
 				"comedi%d: %s: channel list too long\n",
-- 
1.7.12

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux