diff options
| -rw-r--r-- | drivers/staging/comedi/drivers/amplc_dio200.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 8eb67651486a..bf27617aa62d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c | |||
| @@ -460,6 +460,7 @@ struct dio200_subdev_8254 { | |||
| 460 | int has_clk_gat_sce; | 460 | int has_clk_gat_sce; |
| 461 | unsigned clock_src[3]; /* Current clock sources */ | 461 | unsigned clock_src[3]; /* Current clock sources */ |
| 462 | unsigned gate_src[3]; /* Current gate sources */ | 462 | unsigned gate_src[3]; /* Current gate sources */ |
| 463 | spinlock_t spinlock; | ||
| 463 | }; | 464 | }; |
| 464 | 465 | ||
| 465 | struct dio200_subdev_intr { | 466 | struct dio200_subdev_intr { |
| @@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s, | |||
| 1042 | { | 1043 | { |
| 1043 | struct dio200_subdev_8254 *subpriv = s->private; | 1044 | struct dio200_subdev_8254 *subpriv = s->private; |
| 1044 | int chan = CR_CHAN(insn->chanspec); | 1045 | int chan = CR_CHAN(insn->chanspec); |
| 1046 | unsigned long flags; | ||
| 1045 | 1047 | ||
| 1048 | spin_lock_irqsave(&subpriv->spinlock, flags); | ||
| 1046 | data[0] = i8254_read(subpriv->iobase, 0, chan); | 1049 | data[0] = i8254_read(subpriv->iobase, 0, chan); |
| 1050 | spin_unlock_irqrestore(&subpriv->spinlock, flags); | ||
| 1047 | 1051 | ||
| 1048 | return 1; | 1052 | return 1; |
| 1049 | } | 1053 | } |
| @@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s, | |||
| 1057 | { | 1061 | { |
| 1058 | struct dio200_subdev_8254 *subpriv = s->private; | 1062 | struct dio200_subdev_8254 *subpriv = s->private; |
| 1059 | int chan = CR_CHAN(insn->chanspec); | 1063 | int chan = CR_CHAN(insn->chanspec); |
| 1064 | unsigned long flags; | ||
| 1060 | 1065 | ||
| 1066 | spin_lock_irqsave(&subpriv->spinlock, flags); | ||
| 1061 | i8254_write(subpriv->iobase, 0, chan, data[0]); | 1067 | i8254_write(subpriv->iobase, 0, chan, data[0]); |
| 1068 | spin_unlock_irqrestore(&subpriv->spinlock, flags); | ||
| 1062 | 1069 | ||
| 1063 | return 1; | 1070 | return 1; |
| 1064 | } | 1071 | } |
| @@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, | |||
| 1151 | struct comedi_insn *insn, unsigned int *data) | 1158 | struct comedi_insn *insn, unsigned int *data) |
| 1152 | { | 1159 | { |
| 1153 | struct dio200_subdev_8254 *subpriv = s->private; | 1160 | struct dio200_subdev_8254 *subpriv = s->private; |
| 1154 | int ret; | 1161 | int ret = 0; |
| 1155 | int chan = CR_CHAN(insn->chanspec); | 1162 | int chan = CR_CHAN(insn->chanspec); |
| 1163 | unsigned long flags; | ||
| 1156 | 1164 | ||
| 1165 | spin_lock_irqsave(&subpriv->spinlock, flags); | ||
| 1157 | switch (data[0]) { | 1166 | switch (data[0]) { |
| 1158 | case INSN_CONFIG_SET_COUNTER_MODE: | 1167 | case INSN_CONFIG_SET_COUNTER_MODE: |
| 1159 | ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); | 1168 | ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); |
| 1160 | if (ret < 0) | 1169 | if (ret < 0) |
| 1161 | return -EINVAL; | 1170 | ret = -EINVAL; |
| 1162 | break; | 1171 | break; |
| 1163 | case INSN_CONFIG_8254_READ_STATUS: | 1172 | case INSN_CONFIG_8254_READ_STATUS: |
| 1164 | data[1] = i8254_status(subpriv->iobase, 0, chan); | 1173 | data[1] = i8254_status(subpriv->iobase, 0, chan); |
| @@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, | |||
| 1166 | case INSN_CONFIG_SET_GATE_SRC: | 1175 | case INSN_CONFIG_SET_GATE_SRC: |
| 1167 | ret = dio200_set_gate_src(subpriv, chan, data[2]); | 1176 | ret = dio200_set_gate_src(subpriv, chan, data[2]); |
| 1168 | if (ret < 0) | 1177 | if (ret < 0) |
| 1169 | return -EINVAL; | 1178 | ret = -EINVAL; |
| 1170 | break; | 1179 | break; |
| 1171 | case INSN_CONFIG_GET_GATE_SRC: | 1180 | case INSN_CONFIG_GET_GATE_SRC: |
| 1172 | ret = dio200_get_gate_src(subpriv, chan); | 1181 | ret = dio200_get_gate_src(subpriv, chan); |
| 1173 | if (ret < 0) | 1182 | if (ret < 0) { |
| 1174 | return -EINVAL; | 1183 | ret = -EINVAL; |
| 1184 | break; | ||
| 1185 | } | ||
| 1175 | data[2] = ret; | 1186 | data[2] = ret; |
| 1176 | break; | 1187 | break; |
| 1177 | case INSN_CONFIG_SET_CLOCK_SRC: | 1188 | case INSN_CONFIG_SET_CLOCK_SRC: |
| 1178 | ret = dio200_set_clock_src(subpriv, chan, data[1]); | 1189 | ret = dio200_set_clock_src(subpriv, chan, data[1]); |
| 1179 | if (ret < 0) | 1190 | if (ret < 0) |
| 1180 | return -EINVAL; | 1191 | ret = -EINVAL; |
| 1181 | break; | 1192 | break; |
| 1182 | case INSN_CONFIG_GET_CLOCK_SRC: | 1193 | case INSN_CONFIG_GET_CLOCK_SRC: |
| 1183 | ret = dio200_get_clock_src(subpriv, chan, &data[2]); | 1194 | ret = dio200_get_clock_src(subpriv, chan, &data[2]); |
| 1184 | if (ret < 0) | 1195 | if (ret < 0) { |
| 1185 | return -EINVAL; | 1196 | ret = -EINVAL; |
| 1197 | break; | ||
| 1198 | } | ||
| 1186 | data[1] = ret; | 1199 | data[1] = ret; |
| 1187 | break; | 1200 | break; |
| 1188 | default: | 1201 | default: |
| 1189 | return -EINVAL; | 1202 | ret = -EINVAL; |
| 1190 | break; | 1203 | break; |
| 1191 | } | 1204 | } |
| 1192 | return insn->n; | 1205 | spin_unlock_irqrestore(&subpriv->spinlock, flags); |
| 1206 | return ret < 0 ? ret : insn->n; | ||
| 1193 | } | 1207 | } |
| 1194 | 1208 | ||
| 1195 | /* | 1209 | /* |
| @@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, | |||
| 1222 | s->insn_write = dio200_subdev_8254_write; | 1236 | s->insn_write = dio200_subdev_8254_write; |
| 1223 | s->insn_config = dio200_subdev_8254_config; | 1237 | s->insn_config = dio200_subdev_8254_config; |
| 1224 | 1238 | ||
| 1239 | spin_lock_init(&subpriv->spinlock); | ||
| 1225 | subpriv->iobase = offset + iobase; | 1240 | subpriv->iobase = offset + iobase; |
| 1226 | subpriv->has_clk_gat_sce = has_clk_gat_sce; | 1241 | subpriv->has_clk_gat_sce = has_clk_gat_sce; |
| 1227 | if (has_clk_gat_sce) { | 1242 | if (has_clk_gat_sce) { |
