|
@@ -460,6 +460,7 @@ struct dio200_subdev_8254 {
|
|
|
int has_clk_gat_sce;
|
|
|
unsigned clock_src[3]; /* Current clock sources */
|
|
|
unsigned gate_src[3]; /* Current gate sources */
|
|
|
+ spinlock_t spinlock;
|
|
|
};
|
|
|
|
|
|
struct dio200_subdev_intr {
|
|
@@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
|
{
|
|
|
struct dio200_subdev_8254 *subpriv = s->private;
|
|
|
int chan = CR_CHAN(insn->chanspec);
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
+ spin_lock_irqsave(&subpriv->spinlock, flags);
|
|
|
data[0] = i8254_read(subpriv->iobase, 0, chan);
|
|
|
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
@@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
|
{
|
|
|
struct dio200_subdev_8254 *subpriv = s->private;
|
|
|
int chan = CR_CHAN(insn->chanspec);
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
+ spin_lock_irqsave(&subpriv->spinlock, flags);
|
|
|
i8254_write(subpriv->iobase, 0, chan, data[0]);
|
|
|
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
@@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
|
struct comedi_insn *insn, unsigned int *data)
|
|
|
{
|
|
|
struct dio200_subdev_8254 *subpriv = s->private;
|
|
|
- int ret;
|
|
|
+ int ret = 0;
|
|
|
int chan = CR_CHAN(insn->chanspec);
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
+ spin_lock_irqsave(&subpriv->spinlock, flags);
|
|
|
switch (data[0]) {
|
|
|
case INSN_CONFIG_SET_COUNTER_MODE:
|
|
|
ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
|
|
|
if (ret < 0)
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
break;
|
|
|
case INSN_CONFIG_8254_READ_STATUS:
|
|
|
data[1] = i8254_status(subpriv->iobase, 0, chan);
|
|
@@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
|
case INSN_CONFIG_SET_GATE_SRC:
|
|
|
ret = dio200_set_gate_src(subpriv, chan, data[2]);
|
|
|
if (ret < 0)
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
break;
|
|
|
case INSN_CONFIG_GET_GATE_SRC:
|
|
|
ret = dio200_get_gate_src(subpriv, chan);
|
|
|
- if (ret < 0)
|
|
|
- return -EINVAL;
|
|
|
+ if (ret < 0) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
data[2] = ret;
|
|
|
break;
|
|
|
case INSN_CONFIG_SET_CLOCK_SRC:
|
|
|
ret = dio200_set_clock_src(subpriv, chan, data[1]);
|
|
|
if (ret < 0)
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
break;
|
|
|
case INSN_CONFIG_GET_CLOCK_SRC:
|
|
|
ret = dio200_get_clock_src(subpriv, chan, &data[2]);
|
|
|
- if (ret < 0)
|
|
|
- return -EINVAL;
|
|
|
+ if (ret < 0) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
data[1] = ret;
|
|
|
break;
|
|
|
default:
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
break;
|
|
|
}
|
|
|
- return insn->n;
|
|
|
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
|
|
|
+ return ret < 0 ? ret : insn->n;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
|
s->insn_write = dio200_subdev_8254_write;
|
|
|
s->insn_config = dio200_subdev_8254_config;
|
|
|
|
|
|
+ spin_lock_init(&subpriv->spinlock);
|
|
|
subpriv->iobase = offset + iobase;
|
|
|
subpriv->has_clk_gat_sce = has_clk_gat_sce;
|
|
|
if (has_clk_gat_sce) {
|