.. | .. |
---|
151 | 151 | |
---|
152 | 152 | /* mutex serializing ioctls */ |
---|
153 | 153 | struct mutex ioctl_mutex; |
---|
| 154 | + |
---|
| 155 | + /* A mutex used when a device is disconnected */ |
---|
| 156 | + struct mutex remove_mutex; |
---|
| 157 | + |
---|
| 158 | + /* Whether the device is disconnected */ |
---|
| 159 | + int exit; |
---|
154 | 160 | }; |
---|
155 | 161 | |
---|
156 | 162 | static void dvb_ca_private_free(struct dvb_ca_private *ca) |
---|
157 | 163 | { |
---|
158 | 164 | unsigned int i; |
---|
159 | 165 | |
---|
160 | | - dvb_free_device(ca->dvbdev); |
---|
| 166 | + dvb_device_put(ca->dvbdev); |
---|
161 | 167 | for (i = 0; i < ca->slot_count; i++) |
---|
162 | 168 | vfree(ca->slot_info[i].rx_buffer.data); |
---|
163 | 169 | |
---|
.. | .. |
---|
187 | 193 | static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, |
---|
188 | 194 | u8 *ebuf, int ecount); |
---|
189 | 195 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, |
---|
190 | | - u8 *ebuf, int ecount); |
---|
| 196 | + u8 *ebuf, int ecount, int size_write_flag); |
---|
191 | 197 | |
---|
192 | 198 | /** |
---|
193 | 199 | * Safely find needle in haystack. |
---|
.. | .. |
---|
370 | 376 | ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10); |
---|
371 | 377 | if (ret) |
---|
372 | 378 | return ret; |
---|
373 | | - ret = dvb_ca_en50221_write_data(ca, slot, buf, 2); |
---|
| 379 | + ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW); |
---|
374 | 380 | if (ret != 2) |
---|
375 | 381 | return -EIO; |
---|
376 | 382 | ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); |
---|
.. | .. |
---|
778 | 784 | * @buf: The data in this buffer is treated as a complete link-level packet to |
---|
779 | 785 | * be written. |
---|
780 | 786 | * @bytes_write: Size of ebuf. |
---|
| 787 | + * @size_write_flag: A flag on Command Register which says whether the link size |
---|
| 788 | + * information will be writen or not. |
---|
781 | 789 | * |
---|
782 | 790 | * return: Number of bytes written, or < 0 on error. |
---|
783 | 791 | */ |
---|
784 | 792 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, |
---|
785 | | - u8 *buf, int bytes_write) |
---|
| 793 | + u8 *buf, int bytes_write, int size_write_flag) |
---|
786 | 794 | { |
---|
787 | 795 | struct dvb_ca_slot *sl = &ca->slot_info[slot]; |
---|
788 | 796 | int status; |
---|
.. | .. |
---|
817 | 825 | |
---|
818 | 826 | /* OK, set HC bit */ |
---|
819 | 827 | status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, |
---|
820 | | - IRQEN | CMDREG_HC); |
---|
| 828 | + IRQEN | CMDREG_HC | size_write_flag); |
---|
821 | 829 | if (status) |
---|
822 | 830 | goto exit; |
---|
823 | 831 | |
---|
.. | .. |
---|
1505 | 1513 | |
---|
1506 | 1514 | mutex_lock(&sl->slot_lock); |
---|
1507 | 1515 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, |
---|
1508 | | - fraglen + 2); |
---|
| 1516 | + fraglen + 2, 0); |
---|
1509 | 1517 | mutex_unlock(&sl->slot_lock); |
---|
1510 | 1518 | if (status == (fraglen + 2)) { |
---|
1511 | 1519 | written = 1; |
---|
.. | .. |
---|
1706 | 1714 | |
---|
1707 | 1715 | dprintk("%s\n", __func__); |
---|
1708 | 1716 | |
---|
1709 | | - if (!try_module_get(ca->pub->owner)) |
---|
| 1717 | + mutex_lock(&ca->remove_mutex); |
---|
| 1718 | + |
---|
| 1719 | + if (ca->exit) { |
---|
| 1720 | + mutex_unlock(&ca->remove_mutex); |
---|
| 1721 | + return -ENODEV; |
---|
| 1722 | + } |
---|
| 1723 | + |
---|
| 1724 | + if (!try_module_get(ca->pub->owner)) { |
---|
| 1725 | + mutex_unlock(&ca->remove_mutex); |
---|
1710 | 1726 | return -EIO; |
---|
| 1727 | + } |
---|
1711 | 1728 | |
---|
1712 | 1729 | err = dvb_generic_open(inode, file); |
---|
1713 | 1730 | if (err < 0) { |
---|
1714 | 1731 | module_put(ca->pub->owner); |
---|
| 1732 | + mutex_unlock(&ca->remove_mutex); |
---|
1715 | 1733 | return err; |
---|
1716 | 1734 | } |
---|
1717 | 1735 | |
---|
.. | .. |
---|
1736 | 1754 | |
---|
1737 | 1755 | dvb_ca_private_get(ca); |
---|
1738 | 1756 | |
---|
| 1757 | + mutex_unlock(&ca->remove_mutex); |
---|
1739 | 1758 | return 0; |
---|
1740 | 1759 | } |
---|
1741 | 1760 | |
---|
.. | .. |
---|
1755 | 1774 | |
---|
1756 | 1775 | dprintk("%s\n", __func__); |
---|
1757 | 1776 | |
---|
| 1777 | + mutex_lock(&ca->remove_mutex); |
---|
| 1778 | + |
---|
1758 | 1779 | /* mark the CA device as closed */ |
---|
1759 | 1780 | ca->open = 0; |
---|
1760 | 1781 | dvb_ca_en50221_thread_update_delay(ca); |
---|
.. | .. |
---|
1764 | 1785 | module_put(ca->pub->owner); |
---|
1765 | 1786 | |
---|
1766 | 1787 | dvb_ca_private_put(ca); |
---|
| 1788 | + |
---|
| 1789 | + if (dvbdev->users == 1 && ca->exit == 1) { |
---|
| 1790 | + mutex_unlock(&ca->remove_mutex); |
---|
| 1791 | + wake_up(&dvbdev->wait_queue); |
---|
| 1792 | + } else { |
---|
| 1793 | + mutex_unlock(&ca->remove_mutex); |
---|
| 1794 | + } |
---|
1767 | 1795 | |
---|
1768 | 1796 | return err; |
---|
1769 | 1797 | } |
---|
.. | .. |
---|
1888 | 1916 | } |
---|
1889 | 1917 | |
---|
1890 | 1918 | mutex_init(&ca->ioctl_mutex); |
---|
| 1919 | + mutex_init(&ca->remove_mutex); |
---|
1891 | 1920 | |
---|
1892 | 1921 | if (signal_pending(current)) { |
---|
1893 | 1922 | ret = -EINTR; |
---|
.. | .. |
---|
1930 | 1959 | |
---|
1931 | 1960 | dprintk("%s\n", __func__); |
---|
1932 | 1961 | |
---|
| 1962 | + mutex_lock(&ca->remove_mutex); |
---|
| 1963 | + ca->exit = 1; |
---|
| 1964 | + mutex_unlock(&ca->remove_mutex); |
---|
| 1965 | + |
---|
| 1966 | + if (ca->dvbdev->users < 1) |
---|
| 1967 | + wait_event(ca->dvbdev->wait_queue, |
---|
| 1968 | + ca->dvbdev->users == 1); |
---|
| 1969 | + |
---|
1933 | 1970 | /* shutdown the thread if there was one */ |
---|
1934 | 1971 | kthread_stop(ca->thread); |
---|
1935 | 1972 | |
---|