Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux-dvb] Re: [PATCH] fix oops from removing running dvb_net
> Thanks!
>
> I just tried the joint patch and unfortunately it has the same problems
> as the last version from Jon Burgess.
!!! There must be some systematic error maybe
> Steps to reproduce it:
> - apply the joint patch to current dvb-kernel, resolve the one
> conflict in av7110 manually (no big deal)
> - recompile & load the driver
>
> Now "szap" a channel, the usage count of "dvb-ttpci" stays 0! If you
> stop "szap", then the usage count drops to "-3" (ie. the number of
> filters that were set by "szap".)
I can't reproduce it this way! Do you use special szap or some
particular channel with certain properties (low/no signal)?
If I szap to some normal and active channel, the dvb-ttpci
usage count rises to 3 and after ctrl-c stopping szap it drops to 0
as it is expected. I will inspect the code for possible leakages
here is attached joint05a.patch, that should differ to the previous
patch only with the av7110 minor issue, however the -3 usagecount
fix you observed isn't attempted there but still we can try it
just to sync to the latest code
> Apparently the setting of the filters does not increase the usage counr. 8-/
that's right, filter usage is no more increasing count number, but the
true module inter-dependency as seen from dvb-core is used, following
the Jon's approach
Emard
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/b2c2/skystar2.c dvb-kernel/linux/drivers/media/dvb/b2c2/skystar2.c
--- dvb-kernel.orig/linux/drivers/media/dvb/b2c2/skystar2.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/b2c2/skystar2.c Sun Dec 28 01:27:58 2003
@@ -2243,7 +2243,7 @@ static int skystar2_probe(struct pci_dev
if (driver_initialize(pdev) != 0)
return -ENODEV;
- dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name);
+ dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name, THIS_MODULE);
if (dvb_adapter == NULL) {
printk("%s: Error registering DVB adapter\n", __FUNCTION__);
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c dvb-kernel/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- dvb-kernel.orig/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c Sun Dec 28 01:27:58 2003
@@ -321,7 +321,7 @@ static int __init dvb_bt8xx_load_card( s
}
- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name)) < 0) {
+ if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dmxdev.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dmxdev.c
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dmxdev.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dmxdev.c Sun Dec 28 01:27:58 2003
@@ -250,6 +250,7 @@ static int dvb_dvr_release(struct inode
}
}
up(&dmxdev->mutex);
+ dvb_device_release(dvbdev);
return 0;
}
@@ -992,8 +993,14 @@ static int dvb_demux_release(struct inod
{
struct dmxdev_filter *dmxdevfilter = dvb_dmxdev_file_to_filter(file);
struct dmxdev *dmxdev = dmxdevfilter->dev;
+ struct dvb_device *dvbdev= dmxdev->dvbdev;
+ int ret;
- return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
+ ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
+ if (!ret) {
+ dvb_device_release(dvbdev);
+ }
+ return ret;
}
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_net.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_net.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c Sun Dec 28 01:27:58 2003
@@ -306,7 +306,7 @@ static int dvb_net_feed_start(struct net
return 0;
}
-static void dvb_net_feed_stop(struct net_device *dev)
+static int dvb_net_feed_stop(struct net_device *dev)
{
struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
int i;
@@ -337,7 +337,11 @@ static void dvb_net_feed_stop(struct net
priv->demux->release_section_feed(priv->demux, priv->secfeed);
priv->secfeed=0;
} else
+ {
printk("%s: no feed to stop\n", dev->name);
+ return -1;
+ }
+ return 0;
}
@@ -360,7 +364,8 @@ static void wq_set_multicast_list (void
struct net_device *dev = data;
struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
- dvb_net_feed_stop(dev);
+ if(dvb_net_feed_stop(dev))
+ return; // no feed to stop
priv->rx_mode = RX_MODE_UNI;
@@ -387,8 +392,8 @@ static void wq_set_multicast_list (void
}
}
- dvb_net_feed_start(dev);
- }
+ dvb_net_feed_start(dev);
+}
static void dvb_net_set_multicast_list (struct net_device *dev)
@@ -592,6 +597,11 @@ static int dvb_net_remove_if(struct dvb_
if (priv->in_use)
return -EBUSY;
+ if (netif_running(&dvbnet->device[num]))
+ {
+ printk("dvb_net.c: WARNING attempt to remove netif in use\n");
+ return -EBUSY;
+ }
dvb_net_stop(&dvbnet->device[num]);
flush_scheduled_work();
kfree(priv);
@@ -637,9 +647,18 @@ static int dvb_net_do_ioctl(struct inode
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!dvbdev)
+ return -ENODEV;
+ if (!dvbdev->adapter)
+ return -ENODEV;
+ if (!try_module_get(dvbdev->adapter->module))
+ return -ENODEV;
result=dvb_net_add_if(dvbnet, dvbnetif->pid);
if (result<0)
+ {
+ module_put(dvbdev->adapter->module);
return result;
+ }
dvbnetif->if_num=result;
break;
}
@@ -649,19 +668,46 @@ static int dvb_net_do_ioctl(struct inode
struct dvb_net_priv *priv_data;
struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
- if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
- !dvbnet->state[dvbnetif->if_num])
+ if(dvbnetif->if_num >= DVB_NET_DEVICES_MAX)
return -EFAULT;
-
+ if(!dvbnet)
+ return -EFAULT;
+ if(!dvbnet->state)
+ return -EFAULT;
+ if(!dvbnet->state[dvbnetif->if_num])
+ return -EFAULT;
+ if(!dvbnet->device)
+ return -EFAULT;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
netdev=(struct net_device*)&dvbnet->device[dvbnetif->if_num];
+#else
+ netdev=(struct net_device*)dvbnet->device[dvbnetif->if_num];
+#endif
+ if(!netdev)
+ return -EFAULT;
priv_data=(struct dvb_net_priv*)netdev->priv;
dvbnetif->pid=priv_data->pid;
break;
}
case NET_REMOVE_IF:
+ {
+ unsigned int deviceno = (unsigned int) (long) parg;
+ int result;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- return dvb_net_remove_if(dvbnet, (int) (long) parg);
+
+ if(deviceno >= DVB_NET_DEVICES_MAX)
+ return -EFAULT;
+
+ if(!dvbnet->state[deviceno])
+ return -EFAULT;
+
+ result = dvb_net_remove_if(dvbnet, deviceno);
+ if(result == 0)
+ module_put(dvbdev->adapter->module);
+ return result;
+ }
default:
return -EINVAL;
}
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvbdev.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dvbdev.c
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvbdev.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvbdev.c Sun Dec 28 01:27:58 2003
@@ -79,26 +79,42 @@ static struct dvb_device* dvbdev_find_de
static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
+ struct file_operations *old_fops;
+ int err = -EOPNOTSUPP;
dvbdev = dvbdev_find_device (iminor(inode));
- if (dvbdev && dvbdev->fops) {
- int err = 0;
- struct file_operations *old_fops;
-
- file->private_data = dvbdev;
- old_fops = file->f_op;
- file->f_op = fops_get(dvbdev->fops);
- if(file->f_op->open)
- err = file->f_op->open(inode,file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
- return err;
+ if (!dvbdev)
+ return -ENODEV;
+ if (!dvbdev->fops)
+ return -ENODEV;
+ if (!dvbdev->adapter)
+ return -ENODEV;
+ if (!try_module_get(dvbdev->adapter->module))
+ return -ENODEV;
+
+ file->private_data = dvbdev;
+ old_fops = file->f_op;
+ file->f_op = fops_get(dvbdev->fops);
+ if(file->f_op->open)
+ err = file->f_op->open(inode,file);
+ if (err) {
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
+ module_put(dvbdev->adapter->module);
}
- return -ENODEV;
+ fops_put(old_fops);
+ return err;
+}
+
+/* Needs to be to drop module count when not
+ * using dvb_generic_release.
+ */
+void dvb_device_release(struct dvb_device *dvbdev)
+{
+ if (dvbdev && dvbdev->adapter) {
+ module_put(dvbdev->adapter->module);
+ }
}
@@ -150,6 +166,7 @@ int dvb_generic_release(struct inode *in
}
dvbdev->users++;
+ dvb_device_release(dvbdev);
return 0;
}
@@ -287,7 +304,8 @@ skip:
}
-int dvb_register_adapter(struct dvb_adapter **padap, const char *name)
+int dvb_register_adapter(struct dvb_adapter **padap, const char *name,
+ struct module *module)
{
struct dvb_adapter *adap;
int num;
@@ -321,6 +339,7 @@ int dvb_register_adapter(struct dvb_adap
#endif
adap->num = num;
adap->name = name;
+ adap->module = module;
list_add_tail (&adap->list_head, &dvb_adapter_list);
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvbdev.h dvb-kernel/linux/drivers/media/dvb/dvb-core/dvbdev.h
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvbdev.h Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvbdev.h Sun Dec 28 01:27:58 2003
@@ -52,6 +52,7 @@ struct dvb_adapter {
struct list_head device_list;
const char *name;
u8 proposed_mac [6];
+ struct module *module;
};
@@ -79,7 +80,10 @@ struct dvb_device {
};
-extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name);
+extern int dvb_register_adapter (struct dvb_adapter **padap,
+ const char *name,
+ struct module *module);
+
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
@@ -92,6 +96,7 @@ extern void dvb_unregister_device (struc
extern int dvb_generic_open (struct inode *inode, struct file *file);
extern int dvb_generic_release (struct inode *inode, struct file *file);
+extern void dvb_device_release(struct dvb_device *dvbdev);
extern int dvb_generic_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
#endif /* #ifndef _DVBDEV_H_ */
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/av7110.c dvb-kernel/linux/drivers/media/dvb/ttpci/av7110.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/av7110.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/av7110.c Sun Dec 28 01:30:04 2003
@@ -4604,7 +4604,7 @@ static int av7110_attach (struct saa7146
av7110->dev=(struct saa7146_dev *)dev;
(struct av7110*)dev->ext_priv = av7110;
- dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name);
+ dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, THIS_MODULE);
/* the Siemens DVB needs this if you want to have the i2c chips
get recognized before the main driver is fully loaded */
Only in dvb-kernel/linux/drivers/media/dvb/ttpci: av7110.c.orig
Only in dvb-kernel/linux/drivers/media/dvb/ttpci: av7110.c.rej
Only in dvb-kernel/linux/drivers/media/dvb/ttpci: av7110.c~
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-av.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget-av.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-av.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-av.c Sun Dec 28 01:27:58 2003
@@ -204,7 +204,7 @@ static int budget_av_attach (struct saa7
memset(budget_av, 0, sizeof(struct budget_av));
- if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
+ if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
kfree(budget_av);
return err;
}
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-ci.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget-ci.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-ci.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-ci.c Sun Dec 28 01:27:58 2003
@@ -250,7 +250,7 @@ static int budget_ci_attach (struct saa7
DEB_EE(("budget_ci: %p\n", budget_ci));
- if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) {
+ if ((err = ttpci_budget_init (&budget_ci->budget, dev, info, THIS_MODULE))) {
kfree (budget_ci);
return err;
}
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-core.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-core.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c Sun Dec 28 01:27:58 2003
@@ -195,7 +195,8 @@ static int master_xfer (struct dvb_i2c_b
int ttpci_budget_init (struct budget *budget,
struct saa7146_dev* dev,
- struct saa7146_pci_extension_data *info)
+ struct saa7146_pci_extension_data *info,
+ struct module *module)
{
int length = TS_WIDTH*TS_HEIGHT;
int ret = 0;
@@ -208,7 +209,7 @@ int ttpci_budget_init (struct budget *bu
budget->card = bi;
budget->dev = (struct saa7146_dev *) dev;
- dvb_register_adapter(&budget->dvb_adapter, budget->card->name);
+ dvb_register_adapter(&budget->dvb_adapter, budget->card->name, module);
/* set dd1 stream a & b */
saa7146_write(dev, DD1_STREAM_B, 0x00000000);
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-patch.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget-patch.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-patch.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-patch.c Sun Dec 28 01:27:58 2003
@@ -172,7 +172,7 @@ static int budget_patch_attach (struct s
DEB_EE(("budget: %p\n",budget));
- if ((err = ttpci_budget_init (budget, dev, info))) {
+ if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
kfree (budget);
return err;
}
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget.c Sun Dec 28 01:27:58 2003
@@ -154,7 +154,7 @@ static int budget_attach (struct saa7146
DEB_EE(("dev:%p, info:%p, budget:%p\n",dev,info,budget));
- if ((err = ttpci_budget_init (budget, dev, info))) {
+ if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
printk("==> failed\n");
kfree (budget);
return err;
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget.h dvb-kernel/linux/drivers/media/dvb/ttpci/budget.h
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget.h Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget.h Sun Dec 28 01:27:58 2003
@@ -77,7 +77,9 @@ static struct saa7146_pci_extension_data
extern int ttpci_budget_init (struct budget *budget,
struct saa7146_dev* dev,
- struct saa7146_pci_extension_data *info);
+ struct saa7146_pci_extension_data *info,
+ struct module *module);
+
extern int ttpci_budget_deinit (struct budget *budget);
extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr);
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c dvb-kernel/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Sun Dec 28 01:27:58 2003
@@ -1130,7 +1130,8 @@ static int ttusb_probe(struct usb_interf
up(&ttusb->sem);
dvb_register_adapter(&ttusb->adapter,
- "Technotrend/Hauppauge Nova-USB");
+ "Technotrend/Hauppauge Nova-USB",
+ THIS_MODULE);
dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0);
dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL,
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c dvb-kernel/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c Sun Dec 28 01:30:31 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c Sun Dec 28 01:27:58 2003
@@ -1149,7 +1149,7 @@ static int ttusb_dec_init_dvb(struct ttu
dprintk("%s\n", __FUNCTION__);
- if ((result = dvb_register_adapter(&dec->adapter, dec->model_name)) < 0) {
+ if ((result = dvb_register_adapter(&dec->adapter, dec->model_name, THIS_MODULE)) < 0) {
printk("%s: dvb_register_adapter failed: error %d\n",
__FUNCTION__, result);
Only in dvb-kernel/linux/drivers/media/dvb/ttusb-dec: ttusb_dec.c.orig
Home |
Main Index |
Thread Index