diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-21 09:19:16 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-21 10:46:56 -0500 |
commit | a2c35d346d9e9555db930f9035d0e628bf7f3393 (patch) | |
tree | 2e85950dd0631538796f5d0e4c1492f4a67265bf /drivers/media/dvb/dvb-usb | |
parent | 04e3ece7153054e2694a882f6ffa54941574049c (diff) |
[media] az6007: Protect read/write calls with a mutex
This will avoid interference with CI and IR I/O operations.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/dvb-usb')
-rw-r--r-- | drivers/media/dvb/dvb-usb/az6007.c | 122 |
1 files changed, 62 insertions, 60 deletions
diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 534d3267c86e..6177332a7a0e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c | |||
@@ -53,17 +53,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
53 | #define AZ6007_READ_IR 0xb4 | 53 | #define AZ6007_READ_IR 0xb4 |
54 | 54 | ||
55 | struct az6007_device_state { | 55 | struct az6007_device_state { |
56 | struct dvb_ca_en50221 ca; | 56 | struct mutex mutex; |
57 | struct mutex ca_mutex; | 57 | struct dvb_ca_en50221 ca; |
58 | unsigned warm : 1; | 58 | unsigned warm:1; |
59 | |||
60 | /* Due to DRX-K - probably need changes */ | ||
61 | int (*gate_ctrl) (struct dvb_frontend *, int); | 59 | int (*gate_ctrl) (struct dvb_frontend *, int); |
62 | bool tuner_attached; | ||
63 | |||
64 | unsigned char data[4096]; | 60 | unsigned char data[4096]; |
65 | |||
66 | struct usb_data_stream *stream; | ||
67 | }; | 61 | }; |
68 | 62 | ||
69 | static struct drxk_config terratec_h7_drxk = { | 63 | static struct drxk_config terratec_h7_drxk = { |
@@ -107,8 +101,7 @@ static struct mt2063_config az6007_mt2063_config = { | |||
107 | .refclock = 36125000, | 101 | .refclock = 36125000, |
108 | }; | 102 | }; |
109 | 103 | ||
110 | /* check for mutex FIXME */ | 104 | static int __az6007_read(struct usb_device *udev, u8 req, u16 value, |
111 | static int az6007_read(struct usb_device *udev, u8 req, u16 value, | ||
112 | u16 index, u8 *b, int blen) | 105 | u16 index, u8 *b, int blen) |
113 | { | 106 | { |
114 | int ret; | 107 | int ret; |
@@ -130,7 +123,23 @@ static int az6007_read(struct usb_device *udev, u8 req, u16 value, | |||
130 | return ret; | 123 | return ret; |
131 | } | 124 | } |
132 | 125 | ||
133 | static int az6007_write(struct usb_device *udev, u8 req, u16 value, | 126 | static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, |
127 | u16 index, u8 *b, int blen) | ||
128 | { | ||
129 | struct az6007_device_state *st = d->priv; | ||
130 | int ret; | ||
131 | |||
132 | if (mutex_lock_interruptible(&st->mutex) < 0) | ||
133 | return -EAGAIN; | ||
134 | |||
135 | ret = __az6007_read(d->udev, req, value, index, b, blen); | ||
136 | |||
137 | mutex_unlock(&st->mutex); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static int __az6007_write(struct usb_device *udev, u8 req, u16 value, | ||
134 | u16 index, u8 *b, int blen) | 143 | u16 index, u8 *b, int blen) |
135 | { | 144 | { |
136 | int ret; | 145 | int ret; |
@@ -158,11 +167,29 @@ static int az6007_write(struct usb_device *udev, u8 req, u16 value, | |||
158 | return 0; | 167 | return 0; |
159 | } | 168 | } |
160 | 169 | ||
170 | static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, | ||
171 | u16 index, u8 *b, int blen) | ||
172 | { | ||
173 | struct az6007_device_state *st = d->priv; | ||
174 | int ret; | ||
175 | |||
176 | if (mutex_lock_interruptible(&st->mutex) < 0) | ||
177 | return -EAGAIN; | ||
178 | |||
179 | ret = __az6007_write(d->udev, req, value, index, b, blen); | ||
180 | |||
181 | mutex_unlock(&st->mutex); | ||
182 | |||
183 | return ret; | ||
184 | } | ||
185 | |||
161 | static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 186 | static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
162 | { | 187 | { |
188 | struct dvb_usb_device *d = adap->dev; | ||
189 | |||
163 | deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); | 190 | deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); |
164 | 191 | ||
165 | return az6007_write(adap->dev->udev, 0xbc, onoff, 0, NULL, 0); | 192 | return az6007_write(d, 0xbc, onoff, 0, NULL, 0); |
166 | } | 193 | } |
167 | 194 | ||
168 | /* keys for the enclosed remote control */ | 195 | /* keys for the enclosed remote control */ |
@@ -185,7 +212,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) | |||
185 | */ | 212 | */ |
186 | return 0; | 213 | return 0; |
187 | 214 | ||
188 | az6007_read(d->udev, AZ6007_READ_IR, 0, 0, key, 10); | 215 | az6007_read(d, AZ6007_READ_IR, 0, 0, key, 10); |
189 | 216 | ||
190 | if (key[1] == 0x44) { | 217 | if (key[1] == 0x44) { |
191 | *state = REMOTE_NO_KEY_PRESSED; | 218 | *state = REMOTE_NO_KEY_PRESSED; |
@@ -218,7 +245,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) | |||
218 | static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) | 245 | static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) |
219 | { | 246 | { |
220 | int ret; | 247 | int ret; |
221 | ret = az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); | 248 | ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, mac, 6); |
222 | 249 | ||
223 | if (ret > 0) | 250 | if (ret > 0) |
224 | deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", | 251 | deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", |
@@ -228,18 +255,6 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) | |||
228 | return ret; | 255 | return ret; |
229 | } | 256 | } |
230 | 257 | ||
231 | static int az6007_led_on_off(struct usb_interface *intf, int onoff) | ||
232 | { | ||
233 | struct usb_device *udev = interface_to_usbdev(intf); | ||
234 | int ret; | ||
235 | |||
236 | /* TS through */ | ||
237 | ret = az6007_write(udev, AZ6007_POWER, onoff, 0, NULL, 0); | ||
238 | if (ret < 0) | ||
239 | err("%s failed with error %d", __func__, ret); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | 258 | static int az6007_frontend_attach(struct dvb_usb_adapter *adap) |
244 | { | 259 | { |
245 | struct az6007_device_state *st = adap->dev->priv; | 260 | struct az6007_device_state *st = adap->dev->priv; |
@@ -260,11 +275,6 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | |||
260 | 275 | ||
261 | static int az6007_tuner_attach(struct dvb_usb_adapter *adap) | 276 | static int az6007_tuner_attach(struct dvb_usb_adapter *adap) |
262 | { | 277 | { |
263 | struct az6007_device_state *st = adap->dev->priv; | ||
264 | |||
265 | if (st->tuner_attached) | ||
266 | return 0; | ||
267 | |||
268 | deb_info("attaching tuner mt2063"); | 278 | deb_info("attaching tuner mt2063"); |
269 | 279 | ||
270 | /* Attach mt2063 to DVB-C frontend */ | 280 | /* Attach mt2063 to DVB-C frontend */ |
@@ -278,53 +288,45 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) | |||
278 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) | 288 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) |
279 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); | 289 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); |
280 | 290 | ||
281 | st->tuner_attached = true; | ||
282 | |||
283 | return 0; | 291 | return 0; |
284 | } | 292 | } |
285 | 293 | ||
286 | int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) | 294 | int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) |
287 | { | 295 | { |
288 | struct az6007_device_state *st = d->priv; | 296 | struct az6007_device_state *st = d->priv; |
289 | struct usb_device *udev = d->udev; | ||
290 | int ret; | 297 | int ret; |
291 | 298 | ||
292 | deb_info("%s()\n", __func__); | 299 | deb_info("%s()\n", __func__); |
293 | 300 | ||
294 | if (!st->warm) { | 301 | if (!st->warm) { |
295 | u8 data[6]; | 302 | mutex_init(&st->mutex); |
296 | 303 | ||
297 | az6007_read(udev, FX2_OED, 1, 0, data, 1); /* {0x01} */ | 304 | ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); |
298 | az6007_read(udev, AZ6007_READ_DATA, 0, 8160, data, 1); /* {0x20} */ | ||
299 | az6007_read(udev, AZ6007_READ_DATA, 0, 0, data, 5); /* {0x00, 0x00, 0x00, 0x00, 0x0a} */ | ||
300 | az6007_read(udev, AZ6007_READ_DATA, 0, 4080, data, 6); /* {0x00, 0x08, 0x00, 0x0c, 0x22, 0x38} */ | ||
301 | |||
302 | ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); | ||
303 | if (ret < 0) | 305 | if (ret < 0) |
304 | return ret; | 306 | return ret; |
305 | msleep(60); | 307 | msleep(60); |
306 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | 308 | ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); |
307 | if (ret < 0) | 309 | if (ret < 0) |
308 | return ret; | 310 | return ret; |
309 | msleep(100); | 311 | msleep(100); |
310 | ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); | 312 | ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); |
311 | if (ret < 0) | 313 | if (ret < 0) |
312 | return ret; | 314 | return ret; |
313 | msleep(20); | 315 | msleep(20); |
314 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | 316 | ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); |
315 | if (ret < 0) | 317 | if (ret < 0) |
316 | return ret; | 318 | return ret; |
317 | 319 | ||
318 | msleep(400); | 320 | msleep(400); |
319 | ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); | 321 | ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); |
320 | if (ret < 0) | 322 | if (ret < 0) |
321 | return ret; | 323 | return ret; |
322 | msleep (150); | 324 | msleep (150); |
323 | ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); | 325 | ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); |
324 | if (ret < 0) | 326 | if (ret < 0) |
325 | return ret; | 327 | return ret; |
326 | msleep (430); | 328 | msleep (430); |
327 | ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); | 329 | ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); |
328 | if (ret < 0) | 330 | if (ret < 0) |
329 | return ret; | 331 | return ret; |
330 | 332 | ||
@@ -336,8 +338,8 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
336 | if (!onoff) | 338 | if (!onoff) |
337 | return 0; | 339 | return 0; |
338 | 340 | ||
339 | az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); | 341 | az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); |
340 | az6007_write(udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); | 342 | az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); |
341 | 343 | ||
342 | return 0; | 344 | return 0; |
343 | } | 345 | } |
@@ -355,7 +357,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
355 | int length; | 357 | int length; |
356 | u8 req, addr; | 358 | u8 req, addr; |
357 | 359 | ||
358 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 360 | if (mutex_lock_interruptible(&st->mutex) < 0) |
359 | return -EAGAIN; | 361 | return -EAGAIN; |
360 | 362 | ||
361 | for (i = 0; i < num; i++) { | 363 | for (i = 0; i < num; i++) { |
@@ -379,7 +381,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
379 | value = addr | (1 << 8); | 381 | value = addr | (1 << 8); |
380 | length = 6 + msgs[i + 1].len; | 382 | length = 6 + msgs[i + 1].len; |
381 | len = msgs[i + 1].len; | 383 | len = msgs[i + 1].len; |
382 | ret = az6007_read(d->udev, req, value, index, st->data, | 384 | ret = __az6007_read(d->udev, req, value, index, st->data, |
383 | length); | 385 | length); |
384 | if (ret >= len) { | 386 | if (ret >= len) { |
385 | for (j = 0; j < len; j++) { | 387 | for (j = 0; j < len; j++) { |
@@ -410,7 +412,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
410 | if (dvb_usb_az6007_debug & 2) | 412 | if (dvb_usb_az6007_debug & 2) |
411 | printk(KERN_CONT "0x%02x ", st->data[j]); | 413 | printk(KERN_CONT "0x%02x ", st->data[j]); |
412 | } | 414 | } |
413 | ret = az6007_write(d->udev, req, value, index, st->data, | 415 | ret = __az6007_write(d->udev, req, value, index, st->data, |
414 | length); | 416 | length); |
415 | } else { | 417 | } else { |
416 | /* read bytes */ | 418 | /* read bytes */ |
@@ -423,7 +425,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
423 | value = addr; | 425 | value = addr; |
424 | length = msgs[i].len + 6; | 426 | length = msgs[i].len + 6; |
425 | len = msgs[i].len; | 427 | len = msgs[i].len; |
426 | ret = az6007_read(d->udev, req, value, index, st->data, | 428 | ret = __az6007_read(d->udev, req, value, index, st->data, |
427 | length); | 429 | length); |
428 | for (j = 0; j < len; j++) { | 430 | for (j = 0; j < len; j++) { |
429 | msgs[i].buf[j] = st->data[j + 5]; | 431 | msgs[i].buf[j] = st->data[j + 5]; |
@@ -438,7 +440,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
438 | goto err; | 440 | goto err; |
439 | } | 441 | } |
440 | err: | 442 | err: |
441 | mutex_unlock(&d->i2c_mutex); | 443 | mutex_unlock(&st->mutex); |
442 | 444 | ||
443 | if (ret < 0) { | 445 | if (ret < 0) { |
444 | info("%s ERROR: %i", __func__, ret); | 446 | info("%s ERROR: %i", __func__, ret); |
@@ -465,16 +467,16 @@ int az6007_identify_state(struct usb_device *udev, | |||
465 | u8 mac[6]; | 467 | u8 mac[6]; |
466 | 468 | ||
467 | /* Try to read the mac address */ | 469 | /* Try to read the mac address */ |
468 | ret = az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); | 470 | ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); |
469 | if (ret == 6) | 471 | if (ret == 6) |
470 | *cold = 0; | 472 | *cold = 0; |
471 | else | 473 | else |
472 | *cold = 1; | 474 | *cold = 1; |
473 | 475 | ||
474 | if (*cold) { | 476 | if (*cold) { |
475 | az6007_write(udev, 0x09, 1, 0, NULL, 0); | 477 | __az6007_write(udev, 0x09, 1, 0, NULL, 0); |
476 | az6007_write(udev, 0x00, 0, 0, NULL, 0); | 478 | __az6007_write(udev, 0x00, 0, 0, NULL, 0); |
477 | az6007_write(udev, 0x00, 0, 0, NULL, 0); | 479 | __az6007_write(udev, 0x00, 0, 0, NULL, 0); |
478 | } | 480 | } |
479 | 481 | ||
480 | deb_info("Device is on %s state\n", *cold? "warm" : "cold"); | 482 | deb_info("Device is on %s state\n", *cold? "warm" : "cold"); |
@@ -486,7 +488,7 @@ static struct dvb_usb_device_properties az6007_properties; | |||
486 | static int az6007_usb_probe(struct usb_interface *intf, | 488 | static int az6007_usb_probe(struct usb_interface *intf, |
487 | const struct usb_device_id *id) | 489 | const struct usb_device_id *id) |
488 | { | 490 | { |
489 | az6007_led_on_off(intf, 0); | 491 | struct usb_device *udev = interface_to_usbdev(intf); |
490 | 492 | ||
491 | return dvb_usb_device_init(intf, &az6007_properties, | 493 | return dvb_usb_device_init(intf, &az6007_properties, |
492 | THIS_MODULE, NULL, adapter_nr); | 494 | THIS_MODULE, NULL, adapter_nr); |