[PATCH] DVB: Fix locking problems and code cleanup

Fix locking problems and code cleanup

Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Andrew de Quincey and committed by Linus Torvalds ded92846 69459f3d

+23 -46
+23 -46
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
··· 35 35 #include <linux/moduleparam.h> 36 36 #include <linux/vmalloc.h> 37 37 #include <linux/delay.h> 38 - #include <linux/rwsem.h> 38 + #include <linux/spinlock.h> 39 39 #include <linux/sched.h> 40 40 41 41 #include "dvb_ca_en50221.h" ··· 110 110 111 111 /* size of the buffer to use when talking to the CAM */ 112 112 int link_buf_size; 113 - 114 - /* semaphore for syncing access to slot structure */ 115 - struct rw_semaphore sem; 116 113 117 114 /* buffer for incoming packets */ 118 115 struct dvb_ringbuffer rx_buffer; ··· 599 602 if (ebuf == NULL) { 600 603 int buf_free; 601 604 602 - down_read(&ca->slot_info[slot].sem); 603 605 if (ca->slot_info[slot].rx_buffer.data == NULL) { 604 - up_read(&ca->slot_info[slot].sem); 605 606 status = -EIO; 606 607 goto exit; 607 608 } 608 609 buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); 609 - up_read(&ca->slot_info[slot].sem); 610 610 611 611 if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { 612 612 status = -EAGAIN; ··· 674 680 675 681 /* OK, add it to the receive buffer, or copy into external buffer if supplied */ 676 682 if (ebuf == NULL) { 677 - down_read(&ca->slot_info[slot].sem); 678 683 if (ca->slot_info[slot].rx_buffer.data == NULL) { 679 - up_read(&ca->slot_info[slot].sem); 680 684 status = -EIO; 681 685 goto exit; 682 686 } 683 687 dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); 684 - up_read(&ca->slot_info[slot].sem); 685 688 } else { 686 689 memcpy(ebuf, buf, bytes_read); 687 690 } ··· 793 802 { 794 803 dprintk("%s\n", __FUNCTION__); 795 804 796 - down_write(&ca->slot_info[slot].sem); 797 805 ca->pub->slot_shutdown(ca->pub, slot); 798 806 ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; 799 - vfree(ca->slot_info[slot].rx_buffer.data); 800 - ca->slot_info[slot].rx_buffer.data = NULL; 801 - up_write(&ca->slot_info[slot].sem); 802 807 803 808 /* need to wake up all processes to check if they're now 804 809 trying to write to a defunct CAM */ ··· 880 893 881 894 case DVB_CA_SLOTSTATE_RUNNING: 882 895 if (ca->open) 883 - dvb_ca_en50221_read_data(ca, slot, NULL, 0); 896 + dvb_ca_en50221_thread_wakeup(ca); 884 897 break; 885 898 } 886 899 } ··· 1114 1127 break; 1115 1128 } 1116 1129 1117 - rxbuf = vmalloc(RX_BUFFER_SIZE); 1118 - if (rxbuf == NULL) { 1119 - printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); 1120 - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; 1121 - dvb_ca_en50221_thread_update_delay(ca); 1122 - break; 1130 + if (ca->slot_info[slot].rx_buffer.data == NULL) { 1131 + rxbuf = vmalloc(RX_BUFFER_SIZE); 1132 + if (rxbuf == NULL) { 1133 + printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); 1134 + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; 1135 + dvb_ca_en50221_thread_update_delay(ca); 1136 + break; 1137 + } 1138 + dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); 1123 1139 } 1124 - down_write(&ca->slot_info[slot].sem); 1125 - dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); 1126 - up_write(&ca->slot_info[slot].sem); 1127 1140 1128 1141 ca->pub->slot_ts_enable(ca->pub, slot); 1129 1142 ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; ··· 1135 1148 if (!ca->open) 1136 1149 continue; 1137 1150 1138 - // no need to poll if the CAM supports IRQs 1139 - if (ca->slot_info[slot].da_irq_supported) 1140 - break; 1141 - 1142 - // poll mode 1151 + // poll slots for data 1143 1152 pktcount = 0; 1144 1153 while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { 1145 1154 if (!ca->open) ··· 1350 1367 /** 1351 1368 * Condition for waking up in dvb_ca_en50221_io_read_condition 1352 1369 */ 1353 - static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *result, int *_slot) 1370 + static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, 1371 + int *result, int *_slot) 1354 1372 { 1355 1373 int slot; 1356 1374 int slot_count = 0; 1357 1375 int idx; 1358 - int fraglen; 1376 + size_t fraglen; 1359 1377 int connection_id = -1; 1360 1378 int found = 0; 1361 1379 u8 hdr[2]; ··· 1366 1382 if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) 1367 1383 goto nextslot; 1368 1384 1369 - down_read(&ca->slot_info[slot].sem); 1370 - 1371 1385 if (ca->slot_info[slot].rx_buffer.data == NULL) { 1372 - up_read(&ca->slot_info[slot].sem); 1373 1386 return 0; 1374 1387 } 1375 1388 ··· 1384 1403 idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); 1385 1404 } 1386 1405 1387 - if (!found) 1388 - up_read(&ca->slot_info[slot].sem); 1389 - 1390 - nextslot: 1406 + nextslot: 1391 1407 slot = (slot + 1) % ca->slot_count; 1392 1408 slot_count++; 1393 1409 } ··· 1489 1511 goto exit; 1490 1512 status = pktlen; 1491 1513 1492 - exit: 1493 - up_read(&ca->slot_info[slot].sem); 1514 + exit: 1494 1515 return status; 1495 1516 } 1496 1517 ··· 1521 1544 for (i = 0; i < ca->slot_count; i++) { 1522 1545 1523 1546 if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { 1524 - down_write(&ca->slot_info[i].sem); 1525 1547 if (ca->slot_info[i].rx_buffer.data != NULL) { 1548 + /* it is safe to call this here without locks because 1549 + * ca->open == 0. Data is not read in this case */ 1526 1550 dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); 1527 1551 } 1528 - up_write(&ca->slot_info[i].sem); 1529 1552 } 1530 1553 } 1531 1554 ··· 1584 1607 dprintk("%s\n", __FUNCTION__); 1585 1608 1586 1609 if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { 1587 - up_read(&ca->slot_info[slot].sem); 1588 1610 mask |= POLLIN; 1589 1611 } 1590 1612 ··· 1595 1619 poll_wait(file, &ca->wait_queue, wait); 1596 1620 1597 1621 if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { 1598 - up_read(&ca->slot_info[slot].sem); 1599 1622 mask |= POLLIN; 1600 1623 } 1601 1624 ··· 1684 1709 ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; 1685 1710 atomic_set(&ca->slot_info[i].camchange_count, 0); 1686 1711 ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; 1687 - init_rwsem(&ca->slot_info[i].sem); 1688 1712 } 1689 1713 1690 1714 if (signal_pending(current)) { ··· 1703 1729 ca->thread_pid = ret; 1704 1730 return 0; 1705 1731 1706 - error: 1732 + error: 1707 1733 if (ca != NULL) { 1708 1734 if (ca->dvbdev != NULL) 1709 1735 dvb_unregister_device(ca->dvbdev); ··· 1745 1771 1746 1772 for (i = 0; i < ca->slot_count; i++) { 1747 1773 dvb_ca_en50221_slot_shutdown(ca, i); 1774 + if (ca->slot_info[i].rx_buffer.data != NULL) { 1775 + vfree(ca->slot_info[i].rx_buffer.data); 1776 + } 1748 1777 } 1749 1778 kfree(ca->slot_info); 1750 1779 dvb_unregister_device(ca->dvbdev);