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