forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/media/dvb-core/dvb_ca_en50221.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
34 *
....@@ -11,18 +12,6 @@
1112 *
1213 * Copyright (C) 1999-2002 Ralph Metzler
1314 * & 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
2615 */
2716
2817 #define pr_fmt(fmt) "dvb_ca_en50221: " fmt
....@@ -162,13 +151,19 @@
162151
163152 /* mutex serializing ioctls */
164153 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;
165160 };
166161
167162 static void dvb_ca_private_free(struct dvb_ca_private *ca)
168163 {
169164 unsigned int i;
170165
171
- dvb_free_device(ca->dvbdev);
166
+ dvb_device_put(ca->dvbdev);
172167 for (i = 0; i < ca->slot_count; i++)
173168 vfree(ca->slot_info[i].rx_buffer.data);
174169
....@@ -198,7 +193,7 @@
198193 static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
199194 u8 *ebuf, int ecount);
200195 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);
202197
203198 /**
204199 * Safely find needle in haystack.
....@@ -381,7 +376,7 @@
381376 ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
382377 if (ret)
383378 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);
385380 if (ret != 2)
386381 return -EIO;
387382 ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
....@@ -789,11 +784,13 @@
789784 * @buf: The data in this buffer is treated as a complete link-level packet to
790785 * be written.
791786 * @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.
792789 *
793790 * return: Number of bytes written, or < 0 on error.
794791 */
795792 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)
797794 {
798795 struct dvb_ca_slot *sl = &ca->slot_info[slot];
799796 int status;
....@@ -828,7 +825,7 @@
828825
829826 /* OK, set HC bit */
830827 status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
831
- IRQEN | CMDREG_HC);
828
+ IRQEN | CMDREG_HC | size_write_flag);
832829 if (status)
833830 goto exit;
834831
....@@ -1516,7 +1513,7 @@
15161513
15171514 mutex_lock(&sl->slot_lock);
15181515 status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
1519
- fraglen + 2);
1516
+ fraglen + 2, 0);
15201517 mutex_unlock(&sl->slot_lock);
15211518 if (status == (fraglen + 2)) {
15221519 written = 1;
....@@ -1717,12 +1714,22 @@
17171714
17181715 dprintk("%s\n", __func__);
17191716
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);
17211726 return -EIO;
1727
+ }
17221728
17231729 err = dvb_generic_open(inode, file);
17241730 if (err < 0) {
17251731 module_put(ca->pub->owner);
1732
+ mutex_unlock(&ca->remove_mutex);
17261733 return err;
17271734 }
17281735
....@@ -1747,6 +1754,7 @@
17471754
17481755 dvb_ca_private_get(ca);
17491756
1757
+ mutex_unlock(&ca->remove_mutex);
17501758 return 0;
17511759 }
17521760
....@@ -1766,6 +1774,8 @@
17661774
17671775 dprintk("%s\n", __func__);
17681776
1777
+ mutex_lock(&ca->remove_mutex);
1778
+
17691779 /* mark the CA device as closed */
17701780 ca->open = 0;
17711781 dvb_ca_en50221_thread_update_delay(ca);
....@@ -1775,6 +1785,13 @@
17751785 module_put(ca->pub->owner);
17761786
17771787 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
+ }
17781795
17791796 return err;
17801797 }
....@@ -1797,15 +1814,14 @@
17971814
17981815 dprintk("%s\n", __func__);
17991816
1817
+ poll_wait(file, &ca->wait_queue, wait);
1818
+
18001819 if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1)
18011820 mask |= EPOLLIN;
18021821
18031822 /* if there is something, return now */
18041823 if (mask)
18051824 return mask;
1806
-
1807
- /* wait for something to happen */
1808
- poll_wait(file, &ca->wait_queue, wait);
18091825
18101826 if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1)
18111827 mask |= EPOLLIN;
....@@ -1900,6 +1916,7 @@
19001916 }
19011917
19021918 mutex_init(&ca->ioctl_mutex);
1919
+ mutex_init(&ca->remove_mutex);
19031920
19041921 if (signal_pending(current)) {
19051922 ret = -EINTR;
....@@ -1942,6 +1959,14 @@
19421959
19431960 dprintk("%s\n", __func__);
19441961
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
+
19451970 /* shutdown the thread if there was one */
19461971 kthread_stop(ca->thread);
19471972