aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-usb
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-01-21 09:19:16 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-01-21 10:46:56 -0500
commita2c35d346d9e9555db930f9035d0e628bf7f3393 (patch)
tree2e85950dd0631538796f5d0e4c1492f4a67265bf /drivers/media/dvb/dvb-usb
parent04e3ece7153054e2694a882f6ffa54941574049c (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.c122
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
55struct az6007_device_state { 55struct 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
69static struct drxk_config terratec_h7_drxk = { 63static 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 */ 104static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
111static 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
133static int az6007_write(struct usb_device *udev, u8 req, u16 value, 126static 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
142static 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
170static 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
161static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 186static 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)
218static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) 245static 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
231static 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
243static int az6007_frontend_attach(struct dvb_usb_adapter *adap) 258static 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
261static int az6007_tuner_attach(struct dvb_usb_adapter *adap) 276static 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
286int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) 294int 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 }
440err: 442err:
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;
486static int az6007_usb_probe(struct usb_interface *intf, 488static 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);