.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * |
---|
12 | 13 | * Copyright (C) 1999-2002 Ralph Metzler |
---|
13 | 14 | * & Marcus Metzler for convergence integrated media GmbH |
---|
14 | | - * |
---|
15 | | - * This program is free software; you can redistribute it and/or |
---|
16 | | - * modify it under the terms of the GNU General Public License |
---|
17 | | - * as published by the Free Software Foundation; either version 2 |
---|
18 | | - * of the License, or (at your option) any later version. |
---|
19 | | - * |
---|
20 | | - * This program is distributed in the hope that it will be useful, |
---|
21 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
22 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
23 | | - * GNU General Public License for more details. |
---|
24 | | - * To obtain the license, point your browser to |
---|
25 | | - * http://www.gnu.org/copyleft/gpl.html |
---|
26 | 15 | */ |
---|
27 | 16 | |
---|
28 | 17 | #define pr_fmt(fmt) "dvb_ca_en50221: " fmt |
---|
.. | .. |
---|
162 | 151 | |
---|
163 | 152 | /* mutex serializing ioctls */ |
---|
164 | 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; |
---|
165 | 160 | }; |
---|
166 | 161 | |
---|
167 | 162 | static void dvb_ca_private_free(struct dvb_ca_private *ca) |
---|
168 | 163 | { |
---|
169 | 164 | unsigned int i; |
---|
170 | 165 | |
---|
171 | | - dvb_free_device(ca->dvbdev); |
---|
| 166 | + dvb_device_put(ca->dvbdev); |
---|
172 | 167 | for (i = 0; i < ca->slot_count; i++) |
---|
173 | 168 | vfree(ca->slot_info[i].rx_buffer.data); |
---|
174 | 169 | |
---|
.. | .. |
---|
198 | 193 | static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, |
---|
199 | 194 | u8 *ebuf, int ecount); |
---|
200 | 195 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, |
---|
201 | | - u8 *ebuf, int ecount); |
---|
| 196 | + u8 *ebuf, int ecount, int size_write_flag); |
---|
202 | 197 | |
---|
203 | 198 | /** |
---|
204 | 199 | * Safely find needle in haystack. |
---|
.. | .. |
---|
381 | 376 | ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10); |
---|
382 | 377 | if (ret) |
---|
383 | 378 | return ret; |
---|
384 | | - ret = dvb_ca_en50221_write_data(ca, slot, buf, 2); |
---|
| 379 | + ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW); |
---|
385 | 380 | if (ret != 2) |
---|
386 | 381 | return -EIO; |
---|
387 | 382 | ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); |
---|
.. | .. |
---|
789 | 784 | * @buf: The data in this buffer is treated as a complete link-level packet to |
---|
790 | 785 | * be written. |
---|
791 | 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. |
---|
792 | 789 | * |
---|
793 | 790 | * return: Number of bytes written, or < 0 on error. |
---|
794 | 791 | */ |
---|
795 | 792 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, |
---|
796 | | - u8 *buf, int bytes_write) |
---|
| 793 | + u8 *buf, int bytes_write, int size_write_flag) |
---|
797 | 794 | { |
---|
798 | 795 | struct dvb_ca_slot *sl = &ca->slot_info[slot]; |
---|
799 | 796 | int status; |
---|
.. | .. |
---|
828 | 825 | |
---|
829 | 826 | /* OK, set HC bit */ |
---|
830 | 827 | status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, |
---|
831 | | - IRQEN | CMDREG_HC); |
---|
| 828 | + IRQEN | CMDREG_HC | size_write_flag); |
---|
832 | 829 | if (status) |
---|
833 | 830 | goto exit; |
---|
834 | 831 | |
---|
.. | .. |
---|
1516 | 1513 | |
---|
1517 | 1514 | mutex_lock(&sl->slot_lock); |
---|
1518 | 1515 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, |
---|
1519 | | - fraglen + 2); |
---|
| 1516 | + fraglen + 2, 0); |
---|
1520 | 1517 | mutex_unlock(&sl->slot_lock); |
---|
1521 | 1518 | if (status == (fraglen + 2)) { |
---|
1522 | 1519 | written = 1; |
---|
.. | .. |
---|
1717 | 1714 | |
---|
1718 | 1715 | dprintk("%s\n", __func__); |
---|
1719 | 1716 | |
---|
1720 | | - 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); |
---|
1721 | 1726 | return -EIO; |
---|
| 1727 | + } |
---|
1722 | 1728 | |
---|
1723 | 1729 | err = dvb_generic_open(inode, file); |
---|
1724 | 1730 | if (err < 0) { |
---|
1725 | 1731 | module_put(ca->pub->owner); |
---|
| 1732 | + mutex_unlock(&ca->remove_mutex); |
---|
1726 | 1733 | return err; |
---|
1727 | 1734 | } |
---|
1728 | 1735 | |
---|
.. | .. |
---|
1747 | 1754 | |
---|
1748 | 1755 | dvb_ca_private_get(ca); |
---|
1749 | 1756 | |
---|
| 1757 | + mutex_unlock(&ca->remove_mutex); |
---|
1750 | 1758 | return 0; |
---|
1751 | 1759 | } |
---|
1752 | 1760 | |
---|
.. | .. |
---|
1766 | 1774 | |
---|
1767 | 1775 | dprintk("%s\n", __func__); |
---|
1768 | 1776 | |
---|
| 1777 | + mutex_lock(&ca->remove_mutex); |
---|
| 1778 | + |
---|
1769 | 1779 | /* mark the CA device as closed */ |
---|
1770 | 1780 | ca->open = 0; |
---|
1771 | 1781 | dvb_ca_en50221_thread_update_delay(ca); |
---|
.. | .. |
---|
1775 | 1785 | module_put(ca->pub->owner); |
---|
1776 | 1786 | |
---|
1777 | 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 | + } |
---|
1778 | 1795 | |
---|
1779 | 1796 | return err; |
---|
1780 | 1797 | } |
---|
.. | .. |
---|
1797 | 1814 | |
---|
1798 | 1815 | dprintk("%s\n", __func__); |
---|
1799 | 1816 | |
---|
| 1817 | + poll_wait(file, &ca->wait_queue, wait); |
---|
| 1818 | + |
---|
1800 | 1819 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) |
---|
1801 | 1820 | mask |= EPOLLIN; |
---|
1802 | 1821 | |
---|
1803 | 1822 | /* if there is something, return now */ |
---|
1804 | 1823 | if (mask) |
---|
1805 | 1824 | return mask; |
---|
1806 | | - |
---|
1807 | | - /* wait for something to happen */ |
---|
1808 | | - poll_wait(file, &ca->wait_queue, wait); |
---|
1809 | 1825 | |
---|
1810 | 1826 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) |
---|
1811 | 1827 | mask |= EPOLLIN; |
---|
.. | .. |
---|
1900 | 1916 | } |
---|
1901 | 1917 | |
---|
1902 | 1918 | mutex_init(&ca->ioctl_mutex); |
---|
| 1919 | + mutex_init(&ca->remove_mutex); |
---|
1903 | 1920 | |
---|
1904 | 1921 | if (signal_pending(current)) { |
---|
1905 | 1922 | ret = -EINTR; |
---|
.. | .. |
---|
1942 | 1959 | |
---|
1943 | 1960 | dprintk("%s\n", __func__); |
---|
1944 | 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 | + |
---|
1945 | 1970 | /* shutdown the thread if there was one */ |
---|
1946 | 1971 | kthread_stop(ca->thread); |
---|
1947 | 1972 | |
---|