| .. | .. |
|---|
| 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 | |
|---|