aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c35
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
465struct dio200_subdev_intr { 466struct 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) {