1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

adapt to mainline kernel changes

This commit is contained in:
internal 2023-05-05 13:08:01 +02:00
parent 626aa6d7be
commit e9399971f8
12 changed files with 279 additions and 128 deletions

View File

@ -1,19 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dmxdev.c - DVB demultiplexer device * dmxdev.c - DVB demultiplexer device
* *
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/ */
#define pr_fmt(fmt) "dmxdev: " fmt #define pr_fmt(fmt) "dmxdev: " fmt
@ -369,23 +359,23 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
static void dvb_dmxdev_filter_timeout(struct timer_list *t) static void dvb_dmxdev_filter_timeout(struct timer_list *t)
{ {
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer); struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
dmxdevfilter->buffer.error = -ETIMEDOUT; dmxdevfilter->buffer.error = -ETIMEDOUT;
spin_lock_irq(&dmxdevfilter->dev->lock); spin_lock_irq(&dmxdevfilter->dev->lock);
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock);
wake_up(&dmxdevfilter->buffer.queue); wake_up(&dmxdevfilter->buffer.queue);
} }
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
{ {
struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
del_timer(&dmxdevfilter->timer); del_timer(&dmxdevfilter->timer);
if (para->timeout) { if (para->timeout) {
dmxdevfilter->timer.expires = dmxdevfilter->timer.expires =
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
add_timer(&dmxdevfilter->timer); add_timer(&dmxdevfilter->timer);
} }
} }
@ -404,7 +394,7 @@ static void dvb_dmxdev_filter_timeout(unsigned long data)
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
{ {
struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
del_timer(&dmxdevfilter->timer); del_timer(&dmxdevfilter->timer);
if (para->timeout) { if (para->timeout) {
dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
@ -415,6 +405,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
} }
} }
#endif #endif
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter, struct dmx_section_filter *filter,
@ -475,14 +466,14 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed, struct dmx_ts_feed *feed,
u32 *buffer_flags) u32 *buffer_flags)
{ {
struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
#ifdef CONFIG_DVB_MMAP #ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx; struct dvb_vb2_ctx *ctx;
#endif #endif
struct dvb_ringbuffer *buffer;
int ret; int ret;
spin_lock(&dmxdevfilter->dev->lock); spin_lock(&dmxdevfilter->dev->lock);
@ -849,6 +840,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
if (mutex_lock_interruptible(&dmxdev->mutex)) if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS; return -ERESTARTSYS;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
for (i = 0; i < dmxdev->filternum; i++) for (i = 0; i < dmxdev->filternum; i++)
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
break; break;
@ -1485,7 +1481,7 @@ static const struct dvb_device dvbdev_dvr = {
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{ {
int i; int i, ret;
if (dmxdev->demux->open(dmxdev->demux) < 0) if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS; return -EUSERS;
@ -1508,21 +1504,36 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
DMXDEV_STATE_FREE); DMXDEV_STATE_FREE);
} }
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
DVB_DEVICE_DEMUX, dmxdev->filternum); DVB_DEVICE_DEMUX, dmxdev->filternum);
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, if (ret < 0)
goto err_register_dvbdev;
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum); dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
if (ret < 0)
goto err_register_dvr_dvbdev;
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
return 0; return 0;
err_register_dvr_dvbdev:
dvb_unregister_device(dmxdev->dvbdev);
err_register_dvbdev:
vfree(dmxdev->filter);
dmxdev->filter = NULL;
return ret;
} }
EXPORT_SYMBOL(dvb_dmxdev_init); EXPORT_SYMBOL(dvb_dmxdev_init);
void dvb_dmxdev_release(struct dmxdev *dmxdev) void dvb_dmxdev_release(struct dmxdev *dmxdev)
{ {
mutex_lock(&dmxdev->mutex);
dmxdev->exit = 1; dmxdev->exit = 1;
mutex_unlock(&dmxdev->mutex);
if (dmxdev->dvbdev->users > 1) { if (dmxdev->dvbdev->users > 1) {
wait_event(dmxdev->dvbdev->wait_queue, wait_event(dmxdev->dvbdev->wait_queue,
dmxdev->dvbdev->users == 1); dmxdev->dvbdev->users == 1);

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* dvb_ca.c: generic DVB functions for EN50221 CAM interfaces * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
* *
@ -164,7 +164,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca)
{ {
unsigned int i; unsigned int i;
dvb_free_device(ca->dvbdev); dvb_device_put(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++) for (i = 0; i < ca->slot_count; i++)
vfree(ca->slot_info[i].rx_buffer.data); vfree(ca->slot_info[i].rx_buffer.data);

View File

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dvb_demux.c - DVB kernel demux API * dvb_demux.c - DVB kernel demux API
* *
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/ */
#define pr_fmt(fmt) "dvb_demux: " fmt #define pr_fmt(fmt) "dvb_demux: " fmt
@ -256,7 +246,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
{ {
struct dvb_demux *demux = feed->demux; struct dvb_demux *demux = feed->demux;
struct dmx_section_feed *sec = &feed->feed.sec; struct dmx_section_feed *sec = &feed->feed.sec;
u16 limit, seclen, n; u16 limit, seclen;
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0; return 0;
@ -285,7 +275,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
/* to be sure always set secbuf */ /* to be sure always set secbuf */
sec->secbuf = sec->secbuf_base + sec->secbufp; sec->secbuf = sec->secbuf_base + sec->secbufp;
for (n = 0; sec->secbufp + 2 < limit; n++) { while (sec->secbufp + 2 < limit) {
seclen = section_length(sec->secbuf); seclen = section_length(sec->secbuf);
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|| seclen + sec->secbufp > limit) || seclen + sec->secbufp > limit)
@ -489,8 +479,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
} }
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n", dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid], pid, demux->cnt_storage[pid],
buf[3] & 0xf); buf[3] & 0xf);
demux->cnt_storage[pid] = buf[3] & 0xf; demux->cnt_storage[pid] = buf[3] & 0xf;
} }
} }

View File

@ -141,7 +141,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv) if (fepriv)
dvb_free_device(fepriv->dvbdev); dvb_device_put(fepriv->dvbdev);
dvb_frontend_invoke_release(fe, fe->ops.release); dvb_frontend_invoke_release(fe, fe->ops.release);
@ -924,6 +924,7 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
/* If the standard is for satellite, convert frequencies to kHz */ /* If the standard is for satellite, convert frequencies to kHz */
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -949,6 +950,7 @@ static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe)
u32 step = max(fe_step, tuner_step); u32 step = max(fe_step, tuner_step);
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -980,6 +982,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
/* range check: symbol rate */ /* range check: symbol rate */
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -1047,6 +1050,10 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
c->input = NO_INPUT; c->input = NO_INPUT;
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
c->modulation = QPSK;
c->rolloff = ROLLOFF_20;
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -1839,6 +1846,7 @@ static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
} else { } else {
/* default values */ /* default values */
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_ISDBS: case SYS_ISDBS:
@ -2312,6 +2320,9 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
case SYS_DVBC_ANNEX_C: case SYS_DVBC_ANNEX_C:
rolloff = 113; rolloff = 113;
break; break;
case SYS_DSS:
rolloff = 120;
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_TURBO: case SYS_TURBO:
case SYS_ISDBS: case SYS_ISDBS:
@ -2582,8 +2593,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_DISEQC_SEND_BURST: case FE_DISEQC_SEND_BURST:
if (fe->ops.diseqc_send_burst) { if (fe->ops.diseqc_send_burst) {
err = fe->ops.diseqc_send_burst(fe, err = fe->ops.diseqc_send_burst(fe, (long)parg);
(enum fe_sec_mini_cmd)parg);
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2591,9 +2601,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_TONE: case FE_SET_TONE:
if (fe->ops.set_tone) { if (fe->ops.set_tone) {
err = fe->ops.set_tone(fe, fepriv->tone = (long)parg;
(enum fe_sec_tone_mode)parg); err = fe->ops.set_tone(fe, fepriv->tone);
fepriv->tone = (enum fe_sec_tone_mode)parg;
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2601,9 +2610,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_VOLTAGE: case FE_SET_VOLTAGE:
if (fe->ops.set_voltage) { if (fe->ops.set_voltage) {
err = fe->ops.set_voltage(fe, fepriv->voltage = (long)parg;
(enum fe_sec_voltage)parg); err = fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->voltage = (enum fe_sec_voltage)parg;
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2767,7 +2775,6 @@ typedef unsigned int __poll_t;
#define EPOLLOUT POLLOUT #define EPOLLOUT POLLOUT
#endif #endif
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
@ -2796,7 +2803,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
if (fe->exit == DVB_FE_DEVICE_REMOVED) if (fe->exit == DVB_FE_DEVICE_REMOVED)
return -ENODEV; return -ENODEV;
if (adapter->mfe_shared) { if (adapter->mfe_shared == 2) {
mutex_lock(&adapter->mfe_lock);
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
if (adapter->mfe_dvbdev &&
!adapter->mfe_dvbdev->writers) {
mutex_unlock(&adapter->mfe_lock);
return -EBUSY;
}
adapter->mfe_dvbdev = dvbdev;
}
} else if (adapter->mfe_shared) {
mutex_lock(&adapter->mfe_lock); mutex_lock(&adapter->mfe_lock);
if (!adapter->mfe_dvbdev) if (!adapter->mfe_dvbdev)
@ -2974,7 +2991,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
else if (fe->ops.tuner_ops.sleep) else if (fe->ops.tuner_ops.sleep)
ret = fe->ops.tuner_ops.sleep(fe); ret = fe->ops.tuner_ops.sleep(fe);
if (fe->ops.sleep) if (fe->ops.suspend)
ret = fe->ops.suspend(fe);
else if (fe->ops.sleep)
ret = fe->ops.sleep(fe); ret = fe->ops.sleep(fe);
return ret; return ret;
@ -2990,7 +3009,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
fe->id); fe->id);
fe->exit = DVB_FE_DEVICE_RESUME; fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init) if (fe->ops.resume)
ret = fe->ops.resume(fe);
else if (fe->ops.init)
ret = fe->ops.init(fe); ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.resume) if (fe->ops.tuner_ops.resume)
@ -3024,6 +3045,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
.name = fe->ops.info.name, .name = fe->ops.info.name,
#endif #endif
}; };
int ret;
dev_dbg(dvb->device, "%s:\n", __func__); dev_dbg(dvb->device, "%s:\n", __func__);
@ -3053,8 +3075,14 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
fe->dvb = dvb; fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF; fepriv->inversion = INVERSION_OFF;
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0); fe, DVB_DEVICE_FRONTEND, 0);
if (ret) {
dvb_frontend_put(fe);
mutex_unlock(&frontend_mutex);
return ret;
}
dev_info(fe->dvb->device, dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n", "DVB: registering adapter %i frontend %i (%s)...\n",

View File

@ -60,6 +60,9 @@
#include <media/dvb_demux.h> #include <media/dvb_demux.h>
#include <media/dvb_net.h> #include <media/dvb_net.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
#include <linux/nospec.h>
#endif
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{ {
@ -661,8 +664,8 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
h->ts_remain, h->ts_remain,
h->ts_remain > 2 ? h->ts_remain > 2 ?
*(unsigned short *)h->from_where : 0); *(unsigned short *)h->from_where : 0);
#ifdef DVB_ULE_DEBUG #ifdef DVB_ULE_DEBUG
hexdump(iov[0].iov_base, iov[0].iov_len); hexdump(iov[0].iov_base, iov[0].iov_len);
hexdump(iov[1].iov_base, iov[1].iov_len); hexdump(iov[1].iov_base, iov[1].iov_len);
hexdump(iov[2].iov_base, iov[2].iov_len); hexdump(iov[2].iov_base, iov[2].iov_len);
@ -678,8 +681,8 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
hexdump(ule_where - TS_SZ, TS_SZ); hexdump(ule_where - TS_SZ, TS_SZ);
} }
ule_dump = 1; ule_dump = 1;
#endif #endif
h->dev->stats.rx_errors++; h->dev->stats.rx_errors++;
h->dev->stats.rx_crc_errors++; h->dev->stats.rx_crc_errors++;
dev_kfree_skb(h->priv->ule_skb); dev_kfree_skb(h->priv->ule_skb);
@ -1062,7 +1065,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i; int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev); struct dvb_net_priv *priv = netdev_priv(dev);
struct dmx_demux *demux = priv->demux; struct dmx_demux *demux = priv->demux;
const unsigned char *mac = (unsigned char *) dev->dev_addr; const unsigned char *mac = (const unsigned char *) dev->dev_addr;
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode); netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
@ -1483,14 +1486,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev; struct net_device *netdev;
struct dvb_net_priv *priv_data; struct dvb_net_priv *priv_data;
struct dvb_net_if *dvbnetif = parg; struct dvb_net_if *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || if (if_num >= DVB_NET_DEVICES_MAX) {
!dvbnet->state[dvbnetif->if_num]) { ret = -EINVAL;
goto ioctl_error;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
#endif
if (!dvbnet->state[if_num]) {
ret = -EINVAL; ret = -EINVAL;
goto ioctl_error; goto ioctl_error;
} }
netdev = dvbnet->device[dvbnetif->if_num]; netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev); priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid; dvbnetif->pid=priv_data->pid;
@ -1543,14 +1553,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev; struct net_device *netdev;
struct dvb_net_priv *priv_data; struct dvb_net_priv *priv_data;
struct __dvb_net_if_old *dvbnetif = parg; struct __dvb_net_if_old *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || if (if_num >= DVB_NET_DEVICES_MAX) {
!dvbnet->state[dvbnetif->if_num]) { ret = -EINVAL;
goto ioctl_error;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
#endif
if (!dvbnet->state[if_num]) {
ret = -EINVAL; ret = -EINVAL;
goto ioctl_error; goto ioctl_error;
} }
netdev = dvbnet->device[dvbnetif->if_num]; netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev); priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid; dvbnetif->pid=priv_data->pid;

View File

@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
* this pairs with smp_store_release() in dvb_ringbuffer_write(), * this pairs with smp_store_release() in dvb_ringbuffer_write(),
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
* *
* for memory barriers also see Documentation/core-api/circular-buffers.txt * for memory barriers also see Documentation/core-api/circular-buffers.rst
*/ */
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite)); return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
#endif #endif
@ -75,7 +75,7 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
{ {
ssize_t free; ssize_t free;
/* ACCESS_ONCE() to load read pointer on writer side /* READ_ONCE() to load read pointer on writer side
* this pairs with smp_store_release() in dvb_ringbuffer_read(), * this pairs with smp_store_release() in dvb_ringbuffer_read(),
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
* or dvb_ringbuffer_reset() * or dvb_ringbuffer_reset()
@ -171,7 +171,7 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
#else #else
/* smp_store_release() for read pointer update to ensure /* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete, * that buf is not overwritten until read is complete,
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() * this pairs with READ_ONCE() in dvb_ringbuffer_free()
*/ */
smp_store_release(&rbuf->pread, 0); smp_store_release(&rbuf->pread, 0);
#endif #endif
@ -203,7 +203,7 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
#else #else
/* smp_store_release() for read pointer update to ensure /* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete, * that buf is not overwritten until read is complete,
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() * this pairs with READ_ONCE() in dvb_ringbuffer_free()
*/ */
smp_store_release(&rbuf->pread, 0); smp_store_release(&rbuf->pread, 0);
#endif #endif
@ -391,7 +391,7 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
} }
consumed = idx - rbuf->pread; consumed = (idx - rbuf->pread);
if (consumed < 0) if (consumed < 0)
consumed += rbuf->size; consumed += rbuf->size;

View File

@ -5,10 +5,6 @@
* Copyright (C) 2015 Samsung Electronics * Copyright (C) 2015 Samsung Electronics
* *
* Author: jh1009.sung@samsung.com * Author: jh1009.sung@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/ */
#include <linux/err.h> #include <linux/err.h>
@ -358,6 +354,12 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{ {
struct vb2_queue *q = &ctx->vb_q;
if (b->index >= q->num_buffers) {
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
return -EINVAL;
}
vb2_core_querybuf(&ctx->vb_q, b->index, b); vb2_core_querybuf(&ctx->vb_q, b->index, b);
dprintk(3, "[%s] index=%d\n", ctx->name, b->index); dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
return 0; return 0;
@ -382,8 +384,13 @@ int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{ {
struct vb2_queue *q = &ctx->vb_q;
int ret; int ret;
if (b->index >= q->num_buffers) {
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
return -EINVAL;
}
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL); ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
if (ret) { if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name, dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,

View File

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dvbdev.c * dvbdev.c
* *
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/ */
#define pr_fmt(fmt) "dvbdev: " fmt #define pr_fmt(fmt) "dvbdev: " fmt
@ -118,7 +108,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
new_fops = fops_get(dvbdev->fops); new_fops = fops_get(dvbdev->fops);
if (!new_fops) if (!new_fops)
goto fail; goto fail;
file->private_data = dvbdev; file->private_data = dvb_device_get(dvbdev);
replace_fops(file, new_fops); replace_fops(file, new_fops);
if (file->f_op->open) if (file->f_op->open)
err = file->f_op->open(inode, file); err = file->f_op->open(inode, file);
@ -182,6 +172,9 @@ int dvb_generic_release(struct inode *inode, struct file *file)
} }
dvbdev->users++; dvbdev->users++;
dvb_device_put(dvbdev);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_generic_release); EXPORT_SYMBOL(dvb_generic_release);
@ -264,7 +257,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
static int dvb_create_tsout_entity(struct dvb_device *dvbdev, static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
const char *name, int npads) const char *name, int npads)
{ {
int i, ret = 0; int i;
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads), dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
GFP_KERNEL); GFP_KERNEL);
@ -281,6 +274,7 @@ static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
for (i = 0; i < npads; i++) { for (i = 0; i < npads; i++) {
struct media_pad *pads = &dvbdev->tsout_pads[i]; struct media_pad *pads = &dvbdev->tsout_pads[i];
struct media_entity *entity = &dvbdev->tsout_entity[i]; struct media_entity *entity = &dvbdev->tsout_entity[i];
int ret;
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
if (!entity->name) if (!entity->name)
@ -353,6 +347,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
GFP_KERNEL); GFP_KERNEL);
if (!dvbdev->pads) { if (!dvbdev->pads) {
kfree(dvbdev->entity); kfree(dvbdev->entity);
dvbdev->entity = NULL;
return -ENOMEM; return -ENOMEM;
} }
} }
@ -499,6 +494,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
} }
memcpy(dvbdev, template, sizeof(struct dvb_device)); memcpy(dvbdev, template, sizeof(struct dvb_device));
kref_init(&dvbdev->ref);
dvbdev->type = type; dvbdev->type = type;
dvbdev->id = id; dvbdev->id = id;
dvbdev->adapter = adap; dvbdev->adapter = adap;
@ -529,7 +525,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
#endif #endif
dvbdev->minor = minor; dvbdev->minor = minor;
dvb_minors[minor] = dvbdev; dvb_minors[minor] = dvb_device_get(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
@ -574,6 +570,7 @@ void dvb_remove_device(struct dvb_device *dvbdev)
down_write(&minor_rwsem); down_write(&minor_rwsem);
dvb_minors[dvbdev->minor] = NULL; dvb_minors[dvbdev->minor] = NULL;
dvb_device_put(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
dvb_media_device_free(dvbdev); dvb_media_device_free(dvbdev);
@ -585,21 +582,34 @@ void dvb_remove_device(struct dvb_device *dvbdev)
EXPORT_SYMBOL(dvb_remove_device); EXPORT_SYMBOL(dvb_remove_device);
void dvb_free_device(struct dvb_device *dvbdev) static void dvb_free_device(struct kref *ref)
{ {
if (!dvbdev) struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
return;
kfree (dvbdev->fops); kfree (dvbdev->fops);
kfree (dvbdev); kfree (dvbdev);
} }
EXPORT_SYMBOL(dvb_free_device);
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
{
kref_get(&dvbdev->ref);
return dvbdev;
}
EXPORT_SYMBOL(dvb_device_get);
void dvb_device_put(struct dvb_device *dvbdev)
{
if (dvbdev)
kref_put(&dvbdev->ref, dvb_free_device);
}
void dvb_unregister_device(struct dvb_device *dvbdev) void dvb_unregister_device(struct dvb_device *dvbdev)
{ {
dvb_remove_device(dvbdev); dvb_remove_device(dvbdev);
dvb_free_device(dvbdev); dvb_device_put(dvbdev);
} }
EXPORT_SYMBOL(dvb_unregister_device); EXPORT_SYMBOL(dvb_unregister_device);
@ -1041,9 +1051,13 @@ EXPORT_SYMBOL_GPL(dvb_module_release);
#endif #endif
#endif #endif
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
#else
static int dvb_uevent(const struct device *dev, struct kobj_uevent_env *env)
#endif
{ {
struct dvb_device *dvbdev = dev_get_drvdata(dev); const struct dvb_device *dvbdev = dev_get_drvdata(dev);
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
@ -1051,9 +1065,13 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0; return 0;
} }
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static char *dvb_devnode(struct device *dev, umode_t *mode) static char *dvb_devnode(struct device *dev, umode_t *mode)
#else
static char *dvb_devnode(const struct device *dev, umode_t *mode)
#endif
{ {
struct dvb_device *dvbdev = dev_get_drvdata(dev); const struct dvb_device *dvbdev = dev_get_drvdata(dev);
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);

View File

@ -280,7 +280,28 @@ enum fe_spectral_inversion {
* @FEC_3_5: Forward Error Correction Code 3/5 * @FEC_3_5: Forward Error Correction Code 3/5
* @FEC_9_10: Forward Error Correction Code 9/10 * @FEC_9_10: Forward Error Correction Code 9/10
* @FEC_2_5: Forward Error Correction Code 2/5 * @FEC_2_5: Forward Error Correction Code 2/5
* * @FEC_1_3: Forward Error Correction Code 1/3
* @FEC_1_4: Forward Error Correction Code 1/4
* @FEC_5_9: Forward Error Correction Code 5/9
* @FEC_7_9: Forward Error Correction Code 7/9
* @FEC_8_15: Forward Error Correction Code 8/15
* @FEC_11_15: Forward Error Correction Code 11/15
* @FEC_13_18: Forward Error Correction Code 13/18
* @FEC_9_20: Forward Error Correction Code 9/20
* @FEC_11_20: Forward Error Correction Code 11/20
* @FEC_23_36: Forward Error Correction Code 23/36
* @FEC_25_36: Forward Error Correction Code 25/36
* @FEC_13_45: Forward Error Correction Code 13/45
* @FEC_26_45: Forward Error Correction Code 26/45
* @FEC_28_45: Forward Error Correction Code 28/45
* @FEC_32_45: Forward Error Correction Code 32/45
* @FEC_77_90: Forward Error Correction Code 77/90
* @FEC_11_45: Forward Error Correction Code 11/45
* @FEC_4_15: Forward Error Correction Code 4/15
* @FEC_14_45: Forward Error Correction Code 14/45
* @FEC_7_15: Forward Error Correction Code 7/15
* @FEC_29_45: Forward Error Correction Code 29/45
* @FEC_31_45: Forward Error Correction Code 31/45
* Please note that not all FEC types are supported by a given standard. * Please note that not all FEC types are supported by a given standard.
*/ */
enum fe_code_rate { enum fe_code_rate {
@ -297,8 +318,28 @@ enum fe_code_rate {
FEC_3_5, FEC_3_5,
FEC_9_10, FEC_9_10,
FEC_2_5, FEC_2_5,
FEC_1_4,
FEC_1_3, FEC_1_3,
FEC_1_4,
FEC_5_9,
FEC_7_9,
FEC_8_15,
FEC_11_15,
FEC_13_18,
FEC_9_20,
FEC_11_20,
FEC_23_36,
FEC_25_36,
FEC_13_45,
FEC_26_45,
FEC_28_45,
FEC_32_45,
FEC_77_90,
FEC_11_45,
FEC_4_15,
FEC_14_45,
FEC_7_15,
FEC_29_45,
FEC_31_45,
}; };
/** /**
@ -317,6 +358,16 @@ enum fe_code_rate {
* @APSK_32: 32-APSK modulation * @APSK_32: 32-APSK modulation
* @DQPSK: DQPSK modulation * @DQPSK: DQPSK modulation
* @QAM_4_NR: 4-QAM-NR modulation * @QAM_4_NR: 4-QAM-NR modulation
* @QAM_1024: 1024-QAM modulation
* @QAM_4096: 4096-QAM modulation
* @APSK_8_L: 8APSK-L modulation
* @APSK_16_L: 16APSK-L modulation
* @APSK_32_L: 32APSK-L modulation
* @APSK_64: 64APSK modulation
* @APSK_64_L: 64APSK-L modulation
* @APSK_128: 128APSK modulation
* @APSK_256: 256APSK modulation
* @APSK_256_L: 256APSK-L modulation
* *
* Please note that not all modulations are supported by a given standard. * Please note that not all modulations are supported by a given standard.
* *
@ -336,9 +387,16 @@ enum fe_modulation {
APSK_32, APSK_32,
DQPSK, DQPSK,
QAM_4_NR, QAM_4_NR,
QAM_1024,
QAM_4096,
APSK_8_L,
APSK_16_L,
APSK_32_L,
APSK_64, APSK_64,
APSK_64_L,
APSK_128, APSK_128,
APSK_256, APSK_256,
APSK_256_L,
}; };
/** /**
@ -393,6 +451,7 @@ enum fe_transmit_mode {
* @GUARD_INTERVAL_PN420: PN length 420 (1/4) * @GUARD_INTERVAL_PN420: PN length 420 (1/4)
* @GUARD_INTERVAL_PN595: PN length 595 (1/6) * @GUARD_INTERVAL_PN595: PN length 595 (1/6)
* @GUARD_INTERVAL_PN945: PN length 945 (1/9) * @GUARD_INTERVAL_PN945: PN length 945 (1/9)
* @GUARD_INTERVAL_1_64: Guard interval 1/64
* *
* Please note that not all guard intervals are supported by a given standard. * Please note that not all guard intervals are supported by a given standard.
*/ */
@ -408,6 +467,7 @@ enum fe_guard_interval {
GUARD_INTERVAL_PN420, GUARD_INTERVAL_PN420,
GUARD_INTERVAL_PN595, GUARD_INTERVAL_PN595,
GUARD_INTERVAL_PN945, GUARD_INTERVAL_PN945,
GUARD_INTERVAL_1_64,
}; };
/** /**
@ -561,6 +621,9 @@ enum fe_pilot {
* @ROLLOFF_20: Roloff factor: α=20% * @ROLLOFF_20: Roloff factor: α=20%
* @ROLLOFF_25: Roloff factor: α=25% * @ROLLOFF_25: Roloff factor: α=25%
* @ROLLOFF_AUTO: Auto-detect the roloff factor. * @ROLLOFF_AUTO: Auto-detect the roloff factor.
* @ROLLOFF_15: Rolloff factor: α=15%
* @ROLLOFF_10: Rolloff factor: α=10%
* @ROLLOFF_5: Rolloff factor: α=5%
* *
* .. note: * .. note:
* *
@ -587,6 +650,8 @@ enum fe_rolloff {
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM) * Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
* @SYS_DVBC_ANNEX_C: * @SYS_DVBC_ANNEX_C:
* Cable TV: DVB-C following ITU-T J.83 Annex C spec * Cable TV: DVB-C following ITU-T J.83 Annex C spec
* @SYS_DVBC2:
* Cable TV: DVB-C2
* @SYS_ISDBC: * @SYS_ISDBC:
* Cable TV: ISDB-C (no drivers yet) * Cable TV: ISDB-C (no drivers yet)
* @SYS_DVBT: * @SYS_DVBT:
@ -604,7 +669,7 @@ enum fe_rolloff {
* @SYS_DVBS: * @SYS_DVBS:
* Satellite TV: DVB-S * Satellite TV: DVB-S
* @SYS_DVBS2: * @SYS_DVBS2:
* Satellite TV: DVB-S2 * Satellite TV: DVB-S2 and DVB-S2X
* @SYS_TURBO: * @SYS_TURBO:
* Satellite TV: DVB-S Turbo * Satellite TV: DVB-S Turbo
* @SYS_ISDBS: * @SYS_ISDBS:
@ -714,7 +779,7 @@ enum atscmh_rs_frame_mode {
}; };
/** /**
* enum atscmh_rs_code_mode * enum atscmh_rs_code_mode - ATSC-M/H Reed Solomon modes
* @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187). * @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187). * @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187). * @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
@ -755,8 +820,8 @@ enum fecap_scale_params {
* struct dtv_stats - Used for reading a DTV status property * struct dtv_stats - Used for reading a DTV status property
* *
* @scale: * @scale:
* Filled with enum fecap_scale_params - the scale in usage * Filled with enum fecap_scale_params - the scale in usage
* for that parameter * for that parameter
* *
* @svalue: * @svalue:
* integer value of the measure, for %FE_SCALE_DECIBEL, * integer value of the measure, for %FE_SCALE_DECIBEL,

View File

@ -369,6 +369,10 @@ struct dvb_frontend_internal_info {
* allocated by the driver. * allocated by the driver.
* @init: callback function used to initialize the tuner device. * @init: callback function used to initialize the tuner device.
* @sleep: callback function used to put the tuner to sleep. * @sleep: callback function used to put the tuner to sleep.
* @suspend: callback function used to inform that the Kernel will
* suspend.
* @resume: callback function used to inform that the Kernel is
* resuming from suspend.
* @write: callback function used by some demod legacy drivers to * @write: callback function used by some demod legacy drivers to
* allow other drivers to write data into their registers. * allow other drivers to write data into their registers.
* Should not be used on new drivers. * Should not be used on new drivers.
@ -438,7 +442,6 @@ struct dvb_frontend_internal_info {
* @analog_ops: pointer to &struct analog_demod_ops * @analog_ops: pointer to &struct analog_demod_ops
*/ */
struct dvb_frontend_ops { struct dvb_frontend_ops {
struct dvb_frontend_internal_info info; struct dvb_frontend_internal_info info;
u8 delsys[MAX_DELSYS]; u8 delsys[MAX_DELSYS];
@ -449,6 +452,8 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe); int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe); int (*sleep)(struct dvb_frontend* fe);
int (*suspend)(struct dvb_frontend *fe);
int (*resume)(struct dvb_frontend *fe);
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len); int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
@ -765,7 +770,8 @@ void dvb_frontend_detach(struct dvb_frontend *fe);
* &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise, * &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise,
* it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available. * it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available.
* *
* It will also call &dvb_frontend_ops.sleep\(\) to put the demod to suspend. * It will also call &dvb_frontend_ops.suspend\(\) to put the demod to suspend,
* if available. Otherwise it will call &dvb_frontend_ops.sleep\(\).
* *
* The drivers should also call dvb_frontend_suspend\(\) as part of their * The drivers should also call dvb_frontend_suspend\(\) as part of their
* handler for the &device_driver.suspend\(\). * handler for the &device_driver.suspend\(\).
@ -779,7 +785,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe);
* *
* This function resumes the usual operation of the tuner after resume. * This function resumes the usual operation of the tuner after resume.
* *
* In order to resume the frontend, it calls the demod &dvb_frontend_ops.init\(\). * In order to resume the frontend, it calls the demod
* &dvb_frontend_ops.resume\(\) if available. Otherwise it calls demod
* &dvb_frontend_ops.init\(\).
* *
* If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it. * If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it.
* Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available. * Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.

View File

@ -214,7 +214,7 @@ extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
* @buf: Buffer to write. * @buf: Buffer to write.
* @len: Length of buffer (currently limited to 65535 bytes max). * @len: Length of buffer (currently limited to 65535 bytes max).
* *
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EINVAL.
*/ */
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
size_t len); size_t len);

View File

@ -35,7 +35,7 @@
#endif #endif
#endif #endif
#define DVB_MAX_ADAPTERS 64 #define DVB_MAX_ADAPTERS 64
#define DVB_UNSET (-1) #define DVB_UNSET (-1)
@ -96,7 +96,11 @@ struct dvb_frontend;
* @device: pointer to struct device * @device: pointer to struct device
* @module: pointer to struct module * @module: pointer to struct module
* @mfe_shared: indicates mutually exclusive frontends. * @mfe_shared: indicates mutually exclusive frontends.
* Use of this flag is currently deprecated. * 1 = legacy exclusion behavior: blocking any open() call
* 2 = enhanced exclusion behavior, emulating the standard
* behavior of busy frontends: allowing read-only sharing
* and otherwise returning immediately with -EBUSY when any
* of the frontends is already opened with write access.
* @mfe_dvbdev: Frontend device in use, in the case of MFE * @mfe_dvbdev: Frontend device in use, in the case of MFE
* @mfe_lock: Lock to prevent using the other frontends when MFE is * @mfe_lock: Lock to prevent using the other frontends when MFE is
* used. * used.
@ -135,6 +139,7 @@ struct dvb_adapter {
* struct dvb_device - represents a DVB device node * struct dvb_device - represents a DVB device node
* *
* @list_head: List head with all DVB devices * @list_head: List head with all DVB devices
* @ref: reference counter
* @fops: pointer to struct file_operations * @fops: pointer to struct file_operations
* @adapter: pointer to the adapter that holds this device node * @adapter: pointer to the adapter that holds this device node
* @type: type of the device, as defined by &enum dvb_device_type. * @type: type of the device, as defined by &enum dvb_device_type.
@ -165,6 +170,7 @@ struct dvb_adapter {
*/ */
struct dvb_device { struct dvb_device {
struct list_head list_head; struct list_head list_head;
struct kref ref;
const struct file_operations *fops; const struct file_operations *fops;
struct dvb_adapter *adapter; struct dvb_adapter *adapter;
enum dvb_device_type type; enum dvb_device_type type;
@ -196,6 +202,20 @@ struct dvb_device {
void *priv; void *priv;
}; };
/**
* dvb_device_get - Increase dvb_device reference
*
* @dvbdev: pointer to struct dvb_device
*/
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
/**
* dvb_device_put - Decrease dvb_device reference
*
* @dvbdev: pointer to struct dvb_device
*/
void dvb_device_put(struct dvb_device *dvbdev);
/** /**
* dvb_register_adapter - Registers a new DVB adapter * dvb_register_adapter - Registers a new DVB adapter
* *
@ -240,29 +260,16 @@ int dvb_register_device(struct dvb_adapter *adap,
/** /**
* dvb_remove_device - Remove a registered DVB device * dvb_remove_device - Remove a registered DVB device
* *
* This does not free memory. To do that, call dvb_free_device(). * This does not free memory. dvb_free_device() will do that when
* reference counter is empty
* *
* @dvbdev: pointer to struct dvb_device * @dvbdev: pointer to struct dvb_device
*/ */
void dvb_remove_device(struct dvb_device *dvbdev); void dvb_remove_device(struct dvb_device *dvbdev);
/**
* dvb_free_device - Free memory occupied by a DVB device.
*
* Call dvb_unregister_device() before calling this function.
*
* @dvbdev: pointer to struct dvb_device
*/
void dvb_free_device(struct dvb_device *dvbdev);
/** /**
* dvb_unregister_device - Unregisters a DVB device * dvb_unregister_device - Unregisters a DVB device
* *
* This is a combination of dvb_remove_device() and dvb_free_device().
* Using this function is usually a mistake, and is often an indicator
* for a use-after-free bug (when a userspace process keeps a file
* handle to a detached device).
*
* @dvbdev: pointer to struct dvb_device * @dvbdev: pointer to struct dvb_device
*/ */
void dvb_unregister_device(struct dvb_device *dvbdev); void dvb_unregister_device(struct dvb_device *dvbdev);