aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-core/dvb_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/dvb-core/dvb_net.c')
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 76e9c36597eb..4ebf33a5ffa2 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -174,7 +174,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
struct ethhdr *eth;
unsigned char *rawp;
- skb->mac.raw=skb->data;
+ skb_reset_mac_header(skb);
skb_pull(skb,dev->hard_header_len);
eth = eth_hdr(skb);
@@ -600,6 +600,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Check CRC32, we've got it in our skb already. */
unsigned short ulen = htons(priv->ule_sndu_len);
unsigned short utype = htons(priv->ule_sndu_type);
+ const u8 *tail;
struct kvec iov[3] = {
{ &ulen, sizeof ulen },
{ &utype, sizeof utype },
@@ -613,10 +614,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
}
ule_crc = iov_crc32(ule_crc, iov, 3);
- expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 |
- *((u8 *)priv->ule_skb->tail - 3) << 16 |
- *((u8 *)priv->ule_skb->tail - 2) << 8 |
- *((u8 *)priv->ule_skb->tail - 1);
+ tail = skb_tail_pointer(priv->ule_skb);
+ expected_crc = *(tail - 4) << 24 |
+ *(tail - 3) << 16 |
+ *(tail - 2) << 8 |
+ *(tail - 1);
if (ule_crc != expected_crc) {
printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
@@ -695,7 +697,9 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
}
else
{
- memcpy(dest_addr, priv->ule_skb->data, ETH_ALEN);
+ skb_copy_from_linear_data(priv->ule_skb,
+ dest_addr,
+ ETH_ALEN);
skb_pull(priv->ule_skb, ETH_ALEN);
}
}
@@ -1435,11 +1439,36 @@ static int dvb_net_ioctl(struct inode *inode, struct file *file,
return dvb_usercopy(inode, file, cmd, arg, dvb_net_do_ioctl);
}
+static int dvb_net_close(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_net *dvbnet = dvbdev->priv;
+
+ if (!dvbdev)
+ return -ENODEV;
+
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ dvbdev->readers++;
+ } else {
+ dvbdev->writers++;
+ }
+
+ dvbdev->users++;
+
+ if(dvbdev->users == 1 && dvbnet->exit==1) {
+ fops_put(file->f_op);
+ file->f_op = NULL;
+ wake_up(&dvbdev->wait_queue);
+ }
+ return 0;
+}
+
+
static struct file_operations dvb_net_fops = {
.owner = THIS_MODULE,
.ioctl = dvb_net_ioctl,
.open = dvb_generic_open,
- .release = dvb_generic_release,
+ .release = dvb_net_close,
};
static struct dvb_device dvbdev_net = {
@@ -1454,6 +1483,11 @@ void dvb_net_release (struct dvb_net *dvbnet)
{
int i;
+ dvbnet->exit = 1;
+ if (dvbnet->dvbdev->users < 1)
+ wait_event(dvbnet->dvbdev->wait_queue,
+ dvbnet->dvbdev->users==1);
+
dvb_unregister_device(dvbnet->dvbdev);
for (i=0; i<DVB_NET_DEVICES_MAX; i++) {