From f5d374cc9de6fb9662b36c3e9af48c6abb6be743 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 10 Oct 2007 21:12:01 -0700 Subject: build: Handle kernel output directories correctly From: Trent Piepho Recent patches to try to handle kernel object file directories haven't been doing it correctly. This patch reworks the way the kernel location(s) are handled. KDIR et al are removed and replaced with two variables, SRCDIR and OUTDIR. SRCDIR is the location of: The main kernel Makefile The kernel headers The kernel source (if present) OUTDIR is the location of: The kernel .config file The kernel [qxm]conf binaries (if present) The following kernel situations should be handled correctly: 1. A kernel installed from source. One can specify the version via "make release VER=version". If VER is not specified, uname -r is used. This the default if make is run on a clean tree. OUTDIR is /lib/modules/$(VER)/build and SRCDIR is /lib/modules/$(VER)/source, which are both symlinks pointing to the same location. 2. A kernel installed from source which was was built with the "O=/output/directory" option to the kernel Makefile. The version is specified the same was as above. OUTDIR and SRCDIR are the same as above, except in this case they are symlinks to different directories. OUTDIR will be a link the the directory used in the "O=" option and SRCDIR will be the source location. 3. An installed binary kernel with only a kernel-headers package. The version can be specified the same way as above. OUTDIR will be /lib/modules/$(VER)/build and SRCDIR will be the same as OUTDIR, as no 'source' directory exists. The kernel source and Kconfig program are most likely not present. 4. An un-installed kernel source tree, for a kernel that was built without using the "O=/outdir/directory" option. The kernel does not need to be fully built, only the "modules_prepare" target needs to be built. The location of the tree is specified with "make release DIR=directory". Both SRCDIR and OUTDIR will be $(DIR). 5. An un-installed kernel source tree, for a kernel that was built using the "O=/output/directory" option. The location of the tree is specified using "make release DIR=/output/directory". Note that DIR is not the directory with the kernel source! It is set to the directory that was used with the O option when the kernel was built. The Makefile in this directory has a link back to the kernel source directory and the v4l-dvb build system will find this. OUTDIR will be the '/output/directory' and SRCDIR will be the location of the source that built it. All all these situation the v4l-dvb tree should build correctly and all the various scripts will work. In addition, if the binaries for the [qxm]conf programs are present, "make menuconfig", etc. will work as well. If the binaries are not present, but the source is, the Makefile will automatically build the binaries when "make menuconfig", etc. is used. The source should be present in all situation except (3), a kernel-headers only install. Note that if the kernel output directory (usually the same as the kernel source directory, except for (2) and (5)) is not writable, then building the Kconfig programs automatically will not be possible. Signed-off-by: Trent Piepho --- v4l/Makefile | 104 ++++++++++++++++++++++---------------------- v4l/Makefile.kernel | 3 +- v4l/scripts/make_kconfig.pl | 5 ++- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/v4l/Makefile b/v4l/Makefile index bb22f7e5d..d1d8056c2 100644 --- a/v4l/Makefile +++ b/v4l/Makefile @@ -3,46 +3,37 @@ obj = . endif ################################################# -# Version Check - -ifneq ($(KERNELRELEASE),) - +# This Makefile is used from two contexts. It is used directly when one runs +# 'make' from the v4l-dvb tree. It used used again when the kernel build +# process includes this file into the kernel Makefile. +ifneq ($(TOPDIR),) +# We are being include from the Kernel -include $(TOPDIR)/Rules.make - else +# We are running directly, not from the Kernel # take version info from last module build if available +# if .version doesn't exist, make will create it for us and restart -include $(obj)/.version ifneq ($(SRCDIR),) -KDIR := $(SRCDIR) -KDIR_OBJ := $(SRCDIR) - -else -ifneq ($(KERNELRELEASE),) -KDIR_BASE := /lib/modules/$(KERNELRELEASE) -else -KDIR_BASE := /lib/modules/$(shell uname -r|perl -ne 'if (/^([0-9]*)\.([0-9])*\.([0-9]*)(.*)$$/) { printf ("%s.%s.%s%s\n",$$1,$$2,$$3,$$4); };') + OUTDIR ?= $(SRCDIR) endif - -ifneq ($(wildcard $(KDIR_BASE)/source),) -KDIR := $(KDIR_BASE)/source -else -KDIR := $(KDIR_BASE)/build -endif - -KDIR_OBJ := $(KDIR_BASE)/build +OUTDIR ?= /lib/modules/$(KERNELRELEASE)/build +SRCDIR ?= /lib/modules/$(KERNELRELEASE)/source +ifeq ($(wildcard $(SRCDIR)/Makefile),) + # No kernel source, but headers should be in OUTDIR + SRCDIR := $(OUTDIR) endif - -endif +endif # TOPDIR ################################################# # default compilation rule default:: config-compat.h Makefile.media links $(obj)/.version oss - @if [ "x$(SRCDIR)" != x ]; then echo SRCDIR is $(SRCDIR) ; fi - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MYCFLAGS) O=$(KDIR_OBJ) modules + @echo Kernel build directory is $(OUTDIR) + $(MAKE) -C $(OUTDIR) SUBDIRS=$(PWD) $(MYCFLAGS) modules ./scripts/rmmod.pl check ################################################# # Object specific rules @@ -69,6 +60,12 @@ ifneq ($(filter $(no-makefile-media-targets), $(MAKECMDGOALS)),) endif endif +# If version not yet detected, we can't create/have these files yet +ifeq ($(KERNELRELEASE),) + makefile-media := 0 + dot-config := 0 +endif + ifeq ($(dot-config),1) -include $(obj)/.myconfig endif @@ -205,6 +202,9 @@ ifneq ($(KERNELRELEASE),) ifneq ($(SRCDIR),) @echo -e SRCDIR=$(SRCDIR)\\n >> $(obj)/.version endif +ifneq ($(OUTDIR),) + @echo -e OUTDIR=$(OUTDIR)\\n >> $(obj)/.version +endif else @echo "No version yet." @uname -r|perl -ne 'if (/^([0-9]*)\.([0-9])*\.([0-9]*)(.*)$$/) { printf ("VERSION=%s\nPATCHLEVEL:=%s\nSUBLEVEL:=%s\nKERNELRELEASE:=%s.%s.%s%s\n",$$1,$$2,$$3,$$1,$$2,$$3,$$4); };' > $(obj)/.version @@ -216,18 +216,21 @@ ifneq ($(VER),) @echo $(VER)|perl -ne 'if (/^([0-9]*)\.([0-9])*\.([0-9]*)(.*)$$/) { printf ("VERSION=%s\nPATCHLEVEL:=%s\nSUBLEVEL:=%s\nKERNELRELEASE:=%s.%s.%s%s\n",$$1,$$2,$$3,$$1,$$2,$$3,$$4); };' > $(obj)/.version else ifneq ($(DIR),) - @echo "Seeking for a version at $(DIR)/Makefile." + @echo "Searching $(DIR)/Makefile for kernel version." @perl \ - -e 'open IN,"$(DIR)/Makefile"; ' \ + -e '$$d="$(DIR)"; ' \ + -e 'S: open IN,"$$d/Makefile"; ' \ -e 'while () {' \ - -e ' if (/^VERSION\s*=\s*([0-9]+)/){ $$version=$$1; }' \ - -e ' elsif (/^PATCHLEVEL\s*=\s*([0-9]+)/){ $$level=$$1; }' \ - -e ' elsif (/^SUBLEVEL\s*=\s*([0-9]+)/){ $$sublevel=$$1; }' \ - -e ' elsif (/^EXTRAVERSION\s*=\s*([^\s]+)\n/){ $$extra=$$1; }' \ + -e ' if (/^VERSION\s*=\s*(\d+)/){ $$version=$$1; }' \ + -e ' elsif (/^PATCHLEVEL\s*=\s*(\d+)/){ $$level=$$1; }' \ + -e ' elsif (/^SUBLEVEL\s*=\s*(\d+)/){ $$sublevel=$$1; }' \ + -e ' elsif (/^EXTRAVERSION\s*=\s*(\S+)\n/){ $$extra=$$1; }' \ + -e ' elsif (/^KERNELSRC\s*:=\s*(\S.*)\n/){ $$o=$$d; $$d=$$1; goto S; }' \ -e '};' \ -e 'printf ("VERSION=%s\nPATCHLEVEL:=%s\nSUBLEVEL:=%s\nKERNELRELEASE:=%s.%s.%s%s\n",' \ -e ' $$version,$$level,$$sublevel,$$version,$$level,$$sublevel,$$extra);' \ - -e 'printf ("SRCDIR:=$(DIR)\n");' > $(obj)/.version + -e 'print "OUTDIR:=$$o\n" if($$o);' \ + -e 'print "SRCDIR:=$$d\n";' > $(obj)/.version @cat .version|grep KERNELRELEASE:|sed s,'KERNELRELEASE:=','Forcing compiling to version ', @if [ ! -f $(DIR)/scripts/kallsyms ]; then \ @@ -249,10 +252,10 @@ oss: ln -sf . oss config-compat.h:: $(obj)/.version .myconfig - perl scripts/make_config_compat.pl $(KDIR) $(obj)/.myconfig $(obj)/config-compat.h + perl scripts/make_config_compat.pl $(SRCDIR) $(obj)/.myconfig $(obj)/config-compat.h kernel-links makelinks:: - cd ..; v4l/scripts/makelinks.sh $(KDIR) + cd ..; v4l/scripts/makelinks.sh $(SRCDIR) ################################################# # Cardlist updating rule @@ -297,19 +300,19 @@ debug:: # Configuration rules # Kernel config programs -QCONF := $(KDIR_OBJ)/scripts/kconfig/qconf -GCONF := $(KDIR_OBJ)/scripts/kconfig/gconf -MCONF := $(KDIR_OBJ)/scripts/kconfig/mconf -CONF := $(KDIR_OBJ)/scripts/kconfig/conf +QCONF := $(OUTDIR)/scripts/kconfig/qconf +GCONF := $(OUTDIR)/scripts/kconfig/gconf +MCONF := $(OUTDIR)/scripts/kconfig/mconf +CONF := $(OUTDIR)/scripts/kconfig/conf # lxdialog can be in either scripts/lxdialog or scripts/kconfig/lxdialog -LXDIALOG_DIR := $(shell if [ -d $(KDIR)/scripts/kconfig/lxdialog ]; then echo kconfig/ ; fi) +LXDIALOG_DIR := $(shell if [ -d $(OUTDIR)/scripts/kconfig/lxdialog ]; then echo kconfig/ ; fi) # lxdialog might not be a separate program that needs to be built, check # for lxdialog/Makefile to find out. -ifneq ($(wildcard $(KDIR)/scripts/$(LXDIALOG_DIR)lxdialog/Makefile),) +ifneq ($(wildcard $(SRCDIR)/scripts/$(LXDIALOG_DIR)lxdialog/Makefile),) # lxdialog must be built LXDIALOG_LNK := $(if $(LXDIALOG_DIR),scripts/kconfig,scripts/lxdialog) - LXDIALOG := $(KDIR)/scripts/$(LXDIALOG_DIR)lxdialog/lxdialog + LXDIALOG := $(OUTDIR)/scripts/$(LXDIALOG_DIR)lxdialog/lxdialog endif # Ideally, some kind of oldconfig process would be used to update .config @@ -319,10 +322,10 @@ endif $(obj)/.config: $(obj)/.version @echo Updating/Creating .config @if [ -e $(obj)/.config ]; then touch $(obj)/.config ; else \ - ./scripts/make_kconfig.pl $(KDIR_OBJ) ; fi + ./scripts/make_kconfig.pl $(OUTDIR) $(SRCDIR); fi $(obj)/Kconfig: $(obj)/.version - ./scripts/make_kconfig.pl $(KDIR_OBJ) + ./scripts/make_kconfig.pl $(OUTDIR) $(SRCDIR) # With make -j, it's possible that both the .config and Kconfig rules # will run at the same time, running make_kconfig.pl twice. There @@ -342,12 +345,12 @@ menuconfig:: $(MCONF) lxdialog $(obj)/Kconfig $(MCONF) $(obj)/Kconfig allyesconfig allmodconfig:: $(obj)/.version - ./scripts/make_kconfig.pl $(KDIR_OBJ) 1 + ./scripts/make_kconfig.pl $(OUTDIR) $(SRCDIR) 1 # rule to build kernel conf programs -KMAKEVARS := config-targets=1 mixed-targets=0 dot-config=0 +KMAKEVARS := config-targets=1 mixed-targets=0 dot-config=0 SRCDIR=$(SRCDIR) $(QCONF) $(GCONF) $(MCONF) $(CONF): - $(MAKE) -C $(KDIR_OBJ) -f $(PWD)/Makefile.kernel $(KMAKEVARS) v4l-$(notdir $@) + $(MAKE) -C $(OUTDIR) -f $(PWD)/Makefile.kernel $(KMAKEVARS) v4l-$(notdir $@) # lxdialog has two parts, a symlink and the actual binary .PHONY: lxdialog @@ -355,10 +358,10 @@ lxdialog: $(LXDIALOG) $(LXDIALOG_LNK) ifdef LXDIALOG $(LXDIALOG_LNK): - ln -snf $(KDIR)/$(LXDIALOG_LNK) $(LXDIALOG_LNK) + ln -snf $(OUTDIR)/$(LXDIALOG_LNK) $(LXDIALOG_LNK) $(LXDIALOG): - $(MAKE) -C $(KDIR) -f $(PWD)/Makefile.kernel $(KMAKEVARS) v4l-$(LXDIALOG) + $(MAKE) -C $(SRCDIR) -f $(PWD)/Makefile.kernel $(KMAKEVARS) v4l-$(LXDIALOG) endif cx88-ivtv:: @@ -414,8 +417,3 @@ snapshot snap tarball:: update distclean (cd ..; tar czf $(snapdir)/$(snap)-$(date).tar.gz .) hg history --style scripts/map-changelog > /$(snapdir)/$(snap)-ChangeLog-$(date) $(MAKE) -C $(snapdir) - -init: - make -C $(KDIR) init - -$(KDIR)/include/linux/autoconf.h: init diff --git a/v4l/Makefile.kernel b/v4l/Makefile.kernel index 7229c6e91..275652609 100644 --- a/v4l/Makefile.kernel +++ b/v4l/Makefile.kernel @@ -19,7 +19,8 @@ # mixed-targets := 0 # dot-config := 0 -include Makefile +KBUILD_SRC := $(SRCDIR) +include $(SRCDIR)/Makefile # Used by the config target v4l-conf: scripts_basic diff --git a/v4l/scripts/make_kconfig.pl b/v4l/scripts/make_kconfig.pl index 7cb258d86..e228d38b4 100755 --- a/v4l/scripts/make_kconfig.pl +++ b/v4l/scripts/make_kconfig.pl @@ -14,6 +14,7 @@ my %depmods = (); my ($version, $level, $sublevel, $kernver); my $kernel = shift; +my $kernsrc = shift; my $force_kconfig = shift; my $debug=0; @@ -542,7 +543,7 @@ disable_config('DVB_FE_CUSTOMISE'); disable_config('VIDEO_HELPER_CHIPS_AUTO'); # ACI needs some kernel includes that might not be there -disable_config('SOUND_ACI_MIXER') if (! -e "$kernel/sound/oss/sound_config.h"); +disable_config('SOUND_ACI_MIXER') if (! -e "$kernsrc/sound/oss/sound_config.h"); # Check dependencies my %newconfig = checkdeps(); @@ -595,7 +596,7 @@ if ($force_kconfig==1 || !-e '.config') { # Check for full kernel sources and print a warning sub kernelcheck() { - my $fullkernel="$kernel/fs/fcntl.c"; + my $fullkernel="$kernsrc/fs/fcntl.c"; if (! -e $fullkernel) { print <<"EOF2"; -- cgit v1.2.3 From e39e8aabd46f449e897905a4c2e20d2aebe9b35c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 13 Oct 2007 22:52:16 -0700 Subject: cx88: Only include the blackbird fields if blackbird is selected From: Trent Piepho Add some ifdefs around fields only used for blackbird support, similar to the way the dvb fields are only included with dvb support. Signed-off-by: Trent Piepho Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-mpeg.c | 8 ++++++-- linux/drivers/media/video/cx88/cx88.h | 10 ++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index e709221ba..fee9fde89 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -99,7 +99,8 @@ static int cx8802_start_dma(struct cx8802_dev *dev, { struct cx88_core *core = dev->core; - dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); + dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", + buf->vb.width, buf->vb.height, buf->vb.field); /* setup fifo + format */ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], @@ -630,6 +631,8 @@ int cx8802_resume_common(struct pci_dev *pci_dev) return 0; } +#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ + defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) struct cx8802_dev * cx8802_get_device(struct inode *inode) { int minor = iminor(inode); @@ -644,6 +647,8 @@ struct cx8802_dev * cx8802_get_device(struct inode *inode) return NULL; } +EXPORT_SYMBOL(cx8802_get_device); +#endif struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) { @@ -964,7 +969,6 @@ EXPORT_SYMBOL(cx8802_fini_common); EXPORT_SYMBOL(cx8802_register_driver); EXPORT_SYMBOL(cx8802_unregister_driver); -EXPORT_SYMBOL(cx8802_get_device); EXPORT_SYMBOL(cx8802_get_driver); #if 0 EXPORT_SYMBOL(cx8802_suspend_common); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 3d80c259b..cd0645d5f 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -486,11 +486,17 @@ struct cx8802_dev { /* for blackbird only */ struct list_head devlist; +#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ + defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) struct video_device *mpeg_dev; u32 mailbox; int width; int height; + /* mpeg params */ + struct cx2341x_mpeg_params params; +#endif + #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) /* for dvb only */ struct videobuf_dvb dvb; @@ -500,13 +506,9 @@ struct cx8802_dev { /* for switching modulation types */ unsigned char ts_gen_cntrl; - /* mpeg params */ - struct cx2341x_mpeg_params params; - /* List of attached drivers */ struct cx8802_driver drvlist; struct work_struct request_module_wk; - }; /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 9f65c5d8edfc6c6fa30a61b3e2b29b479b0fb6fe Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 13 Oct 2007 22:52:16 -0700 Subject: cx88: Change void* card_priv to struct vp3054_i2c_state From: Trent Piepho card_priv was only used to store a pointer to the vp3054 state struct. There's no need to use a void * since it doesn't have multiple types. Make the field conditional on VP3045 support. It was already conditional on DVB support, but it's only used if VP3045 support is on, so that makes for a better option to check. Signed-off-by: Trent Piepho Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-dvb.c | 3 ++- linux/drivers/media/video/cx88/cx88-vp3054-i2c.c | 16 ++++++++-------- linux/drivers/media/video/cx88/cx88.h | 6 +++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 5eae5dec2..c4e9177f3 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -476,8 +476,9 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) + /* MT352 is on a secondary I2C bus made from some GPIO lines */ dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, - &((struct vp3054_i2c_state *)dev->card_priv)->adap); + &dev->vp3054->adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, DVB_PLL_FMD1216ME); diff --git a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c index c4a895db7..84bb59175 100644 --- a/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -44,7 +44,7 @@ static void vp3054_bit_setscl(void *data, int state) { struct cx8802_dev *dev = data; struct cx88_core *core = dev->core; - struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; if (state) { vp3054_i2c->state |= 0x0001; /* SCL high */ @@ -61,7 +61,7 @@ static void vp3054_bit_setsda(void *data, int state) { struct cx8802_dev *dev = data; struct cx88_core *core = dev->core; - struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; if (state) { vp3054_i2c->state |= 0x0002; /* SDA high */ @@ -116,10 +116,10 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) return 0; - dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); - if (dev->card_priv == NULL) + vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); + if (vp3054_i2c == NULL) return -ENOMEM; - vp3054_i2c = dev->card_priv; + dev->vp3054 = vp3054_i2c; memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); @@ -148,8 +148,8 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) if (0 != rc) { printk("%s: vp3054_i2c register FAILED\n", core->name); - kfree(dev->card_priv); - dev->card_priv = NULL; + kfree(dev->vp3054); + dev->vp3054 = NULL; } return rc; @@ -157,7 +157,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) void vp3054_i2c_remove(struct cx8802_dev *dev) { - struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; if (vp3054_i2c == NULL || dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index cd0645d5f..9abe3064f 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -500,8 +500,12 @@ struct cx8802_dev { #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) /* for dvb only */ struct videobuf_dvb dvb; +#endif - void *card_priv; +#if defined(CONFIG_VIDEO_CX88_VP3054) || \ + defined(CONFIG_VIDEO_CX88_VP3054_MODULE) + /* For VP3045 secondary I2C bus support */ + struct vp3054_i2c_state *vp3054; #endif /* for switching modulation types */ unsigned char ts_gen_cntrl; -- cgit v1.2.3 From 8acc33b86c1347822d4ec6dcbc39c2d9e4b07a54 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 13 Oct 2007 22:52:17 -0700 Subject: cx88: Change (struct cx8802_dev)->drvlist to a list_head and fix bugs From: Trent Piepho It was a struct cx8802_driver for no apparent reason. Nothing uses a cx8802_driver in the cx8802_dev struct. The only field that was used was devlist, a list_head. The code in cx8802_remove() that removed any loaded sub-drivers was broken. It would delete the current list entry, but didn't use list_for_each_safe. It also called list_del() on the list _head_ inside the list_for_each loop? It would crash if it was run, which I don't think can ever happen. Since the cx8802 sub-drivers use the cx8802 driver, they have to be unloaded first. So there isn't any way for a sub-driver to still be loaded when cx8802_remove() is called... Except maybe with PCI hot-plug, if one removes the PCI card while the drivers are loaded? So I left some code in to handle that if it's actually possible. It will remove the sub-drivers from the device cx8802_remove() was called on, and only that device. If one has two DVB cards and unplugs one, there is no reason to unload the DVB drivers for both cards. I have no way to test this, but it can't be worse than what was there before. cx8802_get_driver() is passed a cx8802_dev pointer and looks for the requested driver on that device. It first loops over the cx8802 device list looking for the device it was passed, which is pointless. It doesn't need to find the device pointer in the list, as it already has the pointer. The list_head in the cx8802_driver struct, which joins all the _drivers_ attached to a device, was named devlist. Changed that to drvlist, since the devlist is used for a list of _devices_ in other cx8802 structs. Signed-off-by: Trent Piepho Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-mpeg.c | 60 +++++++++++++++--------------- linux/drivers/media/video/cx88/cx88.h | 8 ++-- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index fee9fde89..0ab8e2c21 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -652,24 +652,14 @@ EXPORT_SYMBOL(cx8802_get_device); struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) { - struct cx8802_dev *h = NULL; - struct cx8802_driver *d = NULL; + struct cx8802_driver *d; struct list_head *list; - struct list_head *list2; - - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - if (h != dev) - continue; - list_for_each(list2, &h->drvlist.devlist) { - d = list_entry(list2, struct cx8802_driver, devlist); + list_for_each(list, &dev->drvlist) { + d = list_entry(list, struct cx8802_driver, drvlist); - /* only unregister the correct driver type */ - if (d->type_id == btype) { - return d; - } - } + if (d->type_id == btype) + return d; } return NULL; @@ -775,7 +765,7 @@ int cx8802_register_driver(struct cx8802_driver *drv) if (err == 0) { i++; mutex_lock(&drv->core->lock); - list_add_tail(&driver->devlist,&h->drvlist.devlist); + list_add_tail(&driver->drvlist, &h->drvlist); mutex_unlock(&drv->core->lock); } else { printk(KERN_ERR @@ -815,8 +805,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) h->pci->subsystem_device, h->core->board.name, h->core->boardnr); - list_for_each_safe(list2, q, &h->drvlist.devlist) { - d = list_entry(list2, struct cx8802_driver, devlist); + list_for_each_safe(list2, q, &h->drvlist) { + d = list_entry(list2, struct cx8802_driver, drvlist); /* only unregister the correct driver type */ if (d->type_id != drv->type_id) @@ -830,7 +820,6 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) } else printk(KERN_ERR "%s/2: cx8802 driver remove " "failed (%d)\n", h->core->name, err); - } } @@ -868,7 +857,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, if (err != 0) goto fail_free; - INIT_LIST_HEAD(&dev->drvlist.devlist); + INIT_LIST_HEAD(&dev->drvlist); list_add_tail(&dev->devlist,&cx8802_devlist); /* Maintain a reference so cx88-video can query the 8802 device. */ @@ -888,23 +877,32 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, static void __devexit cx8802_remove(struct pci_dev *pci_dev) { struct cx8802_dev *dev; - struct cx8802_driver *h; - struct list_head *list; dev = pci_get_drvdata(pci_dev); dprintk( 1, "%s\n", __FUNCTION__); - list_for_each(list,&dev->drvlist.devlist) { - h = list_entry(list, struct cx8802_driver, devlist); - dprintk( 1, " ->driver\n"); - if (h->remove == NULL) { - printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); - continue; + if (!list_empty(&dev->drvlist)) { + struct list_head *list, *tmp; + struct cx8802_driver *drv; + int err; + + printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver " + "while cx8802 sub-drivers still loaded?!\n", + dev->core->name); + + list_for_each_safe(list, tmp, &dev->drvlist) { + drv = list_entry(list, struct cx8802_driver, drvlist); + + err = drv->remove(drv); + if (err == 0) { + mutex_lock(&drv->core->lock); + list_del(list); + mutex_unlock(&drv->core->lock); + } else + printk(KERN_ERR "%s/2: cx8802 driver remove " + "failed (%d)\n", dev->core->name, err); } - printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id); - cx8802_unregister_driver(h); - list_del(&dev->drvlist.devlist); } /* Destroy any 8802 reference. */ diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 9abe3064f..4ed19fb37 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -441,7 +441,9 @@ struct cx8802_suspend_state { struct cx8802_driver { struct cx88_core *core; - struct list_head devlist; + + /* List of drivers attached to device */ + struct list_head drvlist; /* Type of driver and access required */ enum cx88_board_type type_id; @@ -511,8 +513,8 @@ struct cx8802_dev { unsigned char ts_gen_cntrl; /* List of attached drivers */ - struct cx8802_driver drvlist; - struct work_struct request_module_wk; + struct list_head drvlist; + struct work_struct request_module_wk; }; /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 73d8a897cbf675d80f30d15f981ea23c16d3b900 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 13 Oct 2007 22:52:17 -0700 Subject: cx8802: Replace list_for_each+list_entry with list_for_each_entry From: Trent Piepho Less code and more efficient. Got ride of a variable that counted the number of devices in cx8802_unregister_driver() but was never used. Looked leftover from a cut&paste. Signed-off-by: Trent Piepho Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-mpeg.c | 85 ++++++++++-------------------- 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 0ab8e2c21..c4f5b8dab 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -210,7 +210,6 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, struct cx88_dmaqueue *q) { struct cx88_buffer *buf; - struct list_head *item; dprintk( 1, "cx8802_restart_queue\n" ); if (list_empty(&q->active)) @@ -256,10 +255,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, dprintk(2,"restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); cx8802_start_dma(dev, q, buf); - list_for_each(item,&q->active) { - buf = list_entry(item, struct cx88_buffer, vb.queue); + list_for_each_entry(buf, &q->active, vb.queue) buf->count = q->count++; - } mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); return 0; } @@ -636,14 +633,11 @@ int cx8802_resume_common(struct pci_dev *pci_dev) struct cx8802_dev * cx8802_get_device(struct inode *inode) { int minor = iminor(inode); - struct cx8802_dev *h = NULL; - struct list_head *list; + struct cx8802_dev *dev; - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - if (h->mpeg_dev && h->mpeg_dev->minor == minor) - return h; - } + list_for_each_entry(dev, &cx8802_devlist, devlist) + if (dev->mpeg_dev && dev->mpeg_dev->minor == minor) + return dev; return NULL; } @@ -653,14 +647,10 @@ EXPORT_SYMBOL(cx8802_get_device); struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) { struct cx8802_driver *d; - struct list_head *list; - - list_for_each(list, &dev->drvlist) { - d = list_entry(list, struct cx8802_driver, drvlist); + list_for_each_entry(d, &dev->drvlist, drvlist) if (d->type_id == btype) return d; - } return NULL; } @@ -724,10 +714,9 @@ static int cx8802_check_driver(struct cx8802_driver *drv) int cx8802_register_driver(struct cx8802_driver *drv) { - struct cx8802_dev *h; + struct cx8802_dev *dev; struct cx8802_driver *driver; - struct list_head *list; - int err = 0, i = 0; + int err, i = 0; printk(KERN_INFO "cx88/2: registering cx8802 driver, type: %s access: %s\n", @@ -739,14 +728,12 @@ int cx8802_register_driver(struct cx8802_driver *drv) return err; } - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - + list_for_each_entry(dev, &cx8802_devlist, devlist) { printk(KERN_INFO "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name, h->pci->subsystem_vendor, - h->pci->subsystem_device, h->core->board.name, - h->core->boardnr); + dev->core->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, dev->core->board.name, + dev->core->boardnr); /* Bring up a new struct for each driver instance */ driver = kzalloc(sizeof(*drv),GFP_KERNEL); @@ -754,7 +741,7 @@ int cx8802_register_driver(struct cx8802_driver *drv) return -ENOMEM; /* Snapshot of the driver registration data */ - drv->core = h->core; + drv->core = dev->core; drv->suspend = cx8802_suspend_common; drv->resume = cx8802_resume_common; drv->request_acquire = cx8802_request_acquire; @@ -765,49 +752,38 @@ int cx8802_register_driver(struct cx8802_driver *drv) if (err == 0) { i++; mutex_lock(&drv->core->lock); - list_add_tail(&driver->drvlist, &h->drvlist); + list_add_tail(&driver->drvlist, &dev->drvlist); mutex_unlock(&drv->core->lock); } else { printk(KERN_ERR "%s/2: cx8802 probe failed, err = %d\n", - h->core->name, err); + dev->core->name, err); } } - if (i == 0) - err = -ENODEV; - else - err = 0; - return err; + return i ? 0 : -ENODEV; } int cx8802_unregister_driver(struct cx8802_driver *drv) { - struct cx8802_dev *h; - struct cx8802_driver *d; - struct list_head *list; - struct list_head *list2, *q; - int err = 0, i = 0; + struct cx8802_dev *dev; + struct cx8802_driver *d, *dtmp; + int err = 0; printk(KERN_INFO "cx88/2: unregistering cx8802 driver, type: %s access: %s\n", drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); - list_for_each(list,&cx8802_devlist) { - i++; - h = list_entry(list, struct cx8802_dev, devlist); - + list_for_each_entry(dev, &cx8802_devlist, devlist) { printk(KERN_INFO "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name, h->pci->subsystem_vendor, - h->pci->subsystem_device, h->core->board.name, - h->core->boardnr); - - list_for_each_safe(list2, q, &h->drvlist) { - d = list_entry(list2, struct cx8802_driver, drvlist); + dev->core->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, dev->core->board.name, + dev->core->boardnr); + list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { /* only unregister the correct driver type */ if (d->type_id != drv->type_id) continue; @@ -815,11 +791,11 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) err = d->remove(d); if (err == 0) { mutex_lock(&drv->core->lock); - list_del(list2); + list_del(&d->drvlist); mutex_unlock(&drv->core->lock); } else printk(KERN_ERR "%s/2: cx8802 driver remove " - "failed (%d)\n", h->core->name, err); + "failed (%d)\n", dev->core->name, err); } } @@ -883,21 +859,18 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) dprintk( 1, "%s\n", __FUNCTION__); if (!list_empty(&dev->drvlist)) { - struct list_head *list, *tmp; - struct cx8802_driver *drv; + struct cx8802_driver *drv, *tmp; int err; printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver " "while cx8802 sub-drivers still loaded?!\n", dev->core->name); - list_for_each_safe(list, tmp, &dev->drvlist) { - drv = list_entry(list, struct cx8802_driver, drvlist); - + list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { err = drv->remove(drv); if (err == 0) { mutex_lock(&drv->core->lock); - list_del(list); + list_del(&drv->drvlist); mutex_unlock(&drv->core->lock); } else printk(KERN_ERR "%s/2: cx8802 driver remove " -- cgit v1.2.3 From 7f367712814cef0e1e132c2c39363cb0c6adb557 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 5 Oct 2007 07:28:09 -0700 Subject: cx8802: Plug memory leak when unregistering a driver When a cx8802 sub-driver was unregistered, the struct cx8802_driver, which was kmalloc()ed by cx8802_register_driver(), was deleted from the list of drivers, but never freed. Signed-off-by: Trent Piepho Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-mpeg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index c4f5b8dab..339992afd 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -793,6 +793,7 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) mutex_lock(&drv->core->lock); list_del(&d->drvlist); mutex_unlock(&drv->core->lock); + kfree(d); } else printk(KERN_ERR "%s/2: cx8802 driver remove " "failed (%d)\n", dev->core->name, err); @@ -875,6 +876,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) } else printk(KERN_ERR "%s/2: cx8802 driver remove " "failed (%d)\n", dev->core->name, err); + kfree(drv); } } -- cgit v1.2.3