From 8c5ba809cf6f22ce8c88daae05bd5c7e7938ec84 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 20 Aug 2006 21:49:29 -0400 Subject: [PATCH] --- yaml --- r: 33428 b: refs/heads/master c: da547d775fa9ba8d9dcaee7bc4e960540e2be576 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/.gitignore | 5 + trunk/Documentation/DocBook/kernel-api.tmpl | 9 +- trunk/Documentation/SubmittingPatches | 10 +- .../accounting/delay-accounting.txt | 10 +- trunk/Documentation/cpu-freq/user-guide.txt | 5 +- trunk/Documentation/cpu-hotplug.txt | 12 +- trunk/Documentation/devices.txt | 8 +- trunk/Documentation/fb/imacfb.txt | 31 ++ .../feature-removal-schedule.txt | 16 + trunk/Documentation/infiniband/ipoib.txt | 2 - trunk/Documentation/initrd.txt | 16 + trunk/Documentation/kbuild/makefiles.txt | 14 + trunk/Documentation/kernel-parameters.txt | 4 +- trunk/Documentation/kobject.txt | 2 +- trunk/Documentation/networking/ip-sysctl.txt | 6 +- .../powerpc/booting-without-of.txt | 10 +- trunk/Documentation/sysctl/kernel.txt | 5 +- trunk/Documentation/usb/proc_usb_info.txt | 2 +- trunk/Documentation/usb/usb-help.txt | 3 +- trunk/Documentation/x86_64/boot-options.txt | 7 + trunk/MAINTAINERS | 50 ++- trunk/Makefile | 35 +- trunk/arch/alpha/kernel/err_ev7.c | 8 +- trunk/arch/alpha/kernel/osf_sys.c | 4 +- trunk/arch/alpha/kernel/setup.c | 50 ++- trunk/arch/alpha/kernel/sys_ruffian.c | 8 +- trunk/arch/alpha/kernel/time.c | 2 +- trunk/arch/arm/common/gic.c | 3 +- trunk/arch/arm/common/locomo.c | 15 +- trunk/arch/arm/common/rtctime.c | 1 + trunk/arch/arm/common/sa1111.c | 6 +- trunk/arch/arm/common/vic.c | 3 +- trunk/arch/arm/configs/ep93xx_defconfig | 15 +- trunk/arch/arm/kernel/ecard.c | 3 +- trunk/arch/arm/kernel/head.S | 6 +- trunk/arch/arm/kernel/irq.c | 1 + trunk/arch/arm/kernel/traps.c | 5 +- trunk/arch/arm/mach-at91rm9200/gpio.c | 3 +- trunk/arch/arm/mach-at91rm9200/irq.c | 3 +- trunk/arch/arm/mach-footbridge/cats-hw.c | 2 +- trunk/arch/arm/mach-imx/irq.c | 6 +- .../arch/arm/mach-integrator/integrator_ap.c | 3 +- .../arch/arm/mach-integrator/integrator_cp.c | 9 +- trunk/arch/arm/mach-iop3xx/iop321-irq.c | 3 +- trunk/arch/arm/mach-iop3xx/iop331-irq.c | 6 +- trunk/arch/arm/mach-ixp4xx/common-pci.c | 2 - trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c | 7 +- trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c | 3 +- trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 3 +- trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c | 3 +- trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c | 6 +- trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c | 12 +- trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 3 +- trunk/arch/arm/mach-omap1/fpga.c | 6 +- trunk/arch/arm/mach-omap1/irq.c | 3 +- trunk/arch/arm/mach-omap2/irq.c | 3 +- trunk/arch/arm/mach-pxa/irq.c | 12 +- trunk/arch/arm/mach-pxa/lpd270.c | 3 +- trunk/arch/arm/mach-pxa/lubbock.c | 3 +- trunk/arch/arm/mach-pxa/mainstone.c | 3 +- trunk/arch/arm/mach-s3c2410/mach-anubis.c | 49 +-- trunk/arch/arm/mach-s3c2410/mach-osiris.c | 20 +- trunk/arch/arm/mach-sa1100/irq.c | 9 +- trunk/arch/arm/mach-shark/irq.c | 3 +- trunk/arch/arm/mach-versatile/core.c | 3 +- trunk/arch/arm/mm/ioremap.c | 2 + trunk/arch/arm/mm/proc-syms.c | 8 + trunk/arch/arm/mm/proc-xscale.S | 30 +- trunk/arch/arm/plat-omap/gpio.c | 8 +- trunk/arch/i386/Kconfig | 2 +- trunk/arch/i386/kernel/Makefile | 3 +- trunk/arch/i386/kernel/acpi/boot.c | 2 +- trunk/arch/i386/kernel/acpi/wakeup.S | 5 +- trunk/arch/i386/kernel/cpu/cpufreq/Kconfig | 3 +- .../i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 3 +- trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c | 221 +++++----- trunk/arch/i386/kernel/cpu/intel_cacheinfo.c | 2 +- trunk/arch/i386/kernel/cpu/mcheck/mce.h | 2 +- trunk/arch/i386/kernel/entry.S | 2 +- trunk/arch/i386/kernel/kprobes.c | 9 +- trunk/arch/i386/kernel/machine_kexec.c | 13 +- trunk/arch/i386/kernel/nmi.c | 1 + trunk/arch/i386/kernel/process.c | 4 +- trunk/arch/i386/kernel/smpboot.c | 62 +-- trunk/arch/i386/kernel/time.c | 2 +- trunk/arch/i386/kernel/traps.c | 27 +- trunk/arch/i386/kernel/vsyscall.lds.S | 1 + trunk/arch/ia64/configs/sn2_defconfig | 2 +- trunk/arch/ia64/defconfig | 2 +- trunk/arch/ia64/hp/sim/simscsi.c | 4 +- trunk/arch/ia64/kernel/Makefile | 3 +- trunk/arch/ia64/kernel/acpi.c | 2 +- trunk/arch/ia64/kernel/efi.c | 6 +- trunk/arch/ia64/kernel/gate.lds.S | 1 + trunk/arch/ia64/kernel/head.S | 2 - trunk/arch/ia64/kernel/ia64_ksyms.c | 2 +- trunk/arch/ia64/kernel/kprobes.c | 9 + trunk/arch/ia64/kernel/pal.S | 18 +- trunk/arch/ia64/kernel/palinfo.c | 47 +-- trunk/arch/ia64/kernel/topology.c | 2 +- trunk/arch/ia64/kernel/traps.c | 5 +- trunk/arch/ia64/kernel/uncached.c | 86 ++-- trunk/arch/ia64/lib/Makefile | 2 +- trunk/arch/ia64/mm/contig.c | 16 +- trunk/arch/ia64/mm/discontig.c | 68 +-- trunk/arch/ia64/mm/init.c | 55 +++ trunk/arch/ia64/mm/ioremap.c | 6 +- trunk/arch/ia64/sn/kernel/xpc_main.c | 2 +- trunk/arch/ia64/sn/pci/tioce_provider.c | 6 +- trunk/arch/parisc/kernel/vmlinux.lds.S | 1 + trunk/arch/powerpc/Kconfig | 9 +- trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts | 339 +++++++++++++++ trunk/arch/powerpc/configs/g5_defconfig | 122 ++++-- trunk/arch/powerpc/configs/iseries_defconfig | 78 +++- trunk/arch/powerpc/configs/pmac32_defconfig | 112 ++++- trunk/arch/powerpc/configs/pseries_defconfig | 78 +++- trunk/arch/powerpc/kernel/Makefile | 4 +- trunk/arch/powerpc/kernel/cpu_setup_power4.S | 2 + trunk/arch/powerpc/kernel/crash.c | 11 + trunk/arch/powerpc/kernel/head_64.S | 35 +- trunk/arch/powerpc/kernel/irq.c | 2 +- trunk/arch/powerpc/kernel/kprobes.c | 2 + trunk/arch/powerpc/kernel/legacy_serial.c | 13 +- trunk/arch/powerpc/kernel/machine_kexec.c | 56 +++ trunk/arch/powerpc/kernel/machine_kexec_64.c | 57 --- trunk/arch/powerpc/kernel/misc_64.S | 2 +- trunk/arch/powerpc/kernel/prom_init.c | 36 ++ trunk/arch/powerpc/kernel/rtas.c | 21 + trunk/arch/powerpc/kernel/smp.c | 24 +- trunk/arch/powerpc/kernel/sysfs.c | 4 +- trunk/arch/powerpc/kernel/traps.c | 24 +- trunk/arch/powerpc/kernel/udbg_16550.c | 6 +- trunk/arch/powerpc/kernel/vdso32/Makefile | 3 +- trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S | 1 + trunk/arch/powerpc/kernel/vdso64/Makefile | 3 +- trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S | 1 + trunk/arch/powerpc/mm/lmb.c | 3 +- trunk/arch/powerpc/platforms/chrp/setup.c | 12 +- trunk/arch/powerpc/platforms/maple/setup.c | 17 +- .../powerpc/platforms/powermac/backlight.c | 58 ++- .../powerpc/platforms/powermac/bootx_init.c | 35 +- .../powerpc/platforms/powermac/cpufreq_64.c | 78 ++-- trunk/arch/powerpc/platforms/pseries/setup.c | 8 +- trunk/arch/powerpc/platforms/pseries/xics.c | 6 +- trunk/arch/powerpc/sysdev/fsl_soc.c | 12 +- trunk/arch/ppc/kernel/vmlinux.lds.S | 1 + trunk/arch/s390/appldata/appldata_base.c | 8 +- trunk/arch/s390/defconfig | 44 +- trunk/arch/s390/mm/init.c | 6 +- trunk/arch/sh/kernel/cpu/sh4/sq.c | 10 +- trunk/arch/sparc/kernel/time.c | 74 ++-- trunk/arch/sparc64/mm/fault.c | 3 + trunk/arch/um/kernel/dyn.lds.S | 1 + trunk/arch/v850/kernel/setup.c | 6 +- trunk/arch/v850/kernel/v850_ksyms.c | 16 - trunk/arch/x86_64/defconfig | 9 +- trunk/arch/x86_64/ia32/Makefile | 1 + trunk/arch/x86_64/ia32/ia32entry.S | 2 +- trunk/arch/x86_64/ia32/vsyscall.lds | 1 + trunk/arch/x86_64/kernel/entry.S | 18 +- trunk/arch/x86_64/kernel/machine_kexec.c | 13 +- trunk/arch/x86_64/kernel/mce.c | 12 +- trunk/arch/x86_64/kernel/mce_amd.c | 19 +- trunk/arch/x86_64/kernel/pci-calgary.c | 77 ++-- trunk/arch/x86_64/kernel/pci-nommu.c | 2 + trunk/arch/x86_64/kernel/pci-swiotlb.c | 5 +- trunk/arch/x86_64/kernel/smp.c | 2 +- trunk/arch/x86_64/kernel/tce.c | 4 +- trunk/arch/x86_64/kernel/time.c | 18 +- trunk/arch/x86_64/kernel/traps.c | 24 +- trunk/arch/x86_64/pci/k8-bus.c | 10 +- trunk/arch/xtensa/kernel/traps.c | 6 +- trunk/block/blktrace.c | 2 +- trunk/block/cfq-iosched.c | 2 +- trunk/drivers/acpi/ac.c | 2 + trunk/drivers/acpi/acpi_memhotplug.c | 21 +- trunk/drivers/acpi/battery.c | 3 + trunk/drivers/acpi/bus.c | 11 +- trunk/drivers/acpi/dock.c | 13 +- trunk/drivers/acpi/hotkey.c | 281 ++++++------- trunk/drivers/acpi/i2c_ec.c | 2 +- trunk/drivers/acpi/osl.c | 10 + trunk/drivers/acpi/sbs.c | 3 + trunk/drivers/acpi/scan.c | 12 +- trunk/drivers/acpi/utils.c | 2 +- trunk/drivers/base/topology.c | 2 +- trunk/drivers/block/cciss.c | 86 ++-- trunk/drivers/block/nbd.c | 19 +- trunk/drivers/block/pktcdvd.c | 6 +- trunk/drivers/char/hvsi.c | 8 +- trunk/drivers/char/hw_random/geode-rng.c | 6 +- trunk/drivers/char/hw_random/intel-rng.c | 2 +- trunk/drivers/char/hw_random/omap-rng.c | 51 ++- trunk/drivers/char/keyboard.c | 139 ++++--- trunk/drivers/char/pc8736x_gpio.c | 1 - trunk/drivers/char/snsc.c | 7 +- trunk/drivers/char/watchdog/Kconfig | 8 +- trunk/drivers/connector/cn_proc.c | 20 +- trunk/drivers/cpufreq/cpufreq.c | 115 ++++-- trunk/drivers/cpufreq/cpufreq_conservative.c | 2 - trunk/drivers/cpufreq/cpufreq_ondemand.c | 4 +- trunk/drivers/cpufreq/cpufreq_userspace.c | 3 + trunk/drivers/edac/edac_mc.h | 1 + trunk/drivers/i2c/busses/scx200_acb.c | 7 +- trunk/drivers/ide/Kconfig | 15 +- trunk/drivers/ide/ide-disk.c | 2 +- trunk/drivers/ide/ide-dma.c | 2 +- trunk/drivers/ide/ide-iops.c | 2 + trunk/drivers/ide/ide.c | 5 +- trunk/drivers/ide/pci/generic.c | 30 ++ trunk/drivers/ide/pci/it821x.c | 11 +- trunk/drivers/ieee1394/sbp2.c | 3 + trunk/drivers/infiniband/core/addr.c | 30 +- trunk/drivers/infiniband/core/cm.c | 4 +- trunk/drivers/infiniband/core/uverbs.h | 2 + trunk/drivers/infiniband/core/uverbs_main.c | 8 +- .../infiniband/hw/mthca/mthca_allocator.c | 15 +- trunk/drivers/infiniband/ulp/ipoib/Kconfig | 3 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 19 +- trunk/drivers/input/evdev.c | 10 +- trunk/drivers/input/gameport/fm801-gp.c | 4 +- trunk/drivers/input/gameport/gameport.c | 66 ++- trunk/drivers/input/input.c | 57 ++- .../input/joystick/iforce/iforce-main.c | 19 +- trunk/drivers/input/joystick/spaceball.c | 2 +- trunk/drivers/input/keyboard/atkbd.c | 103 +++-- trunk/drivers/input/misc/wistron_btns.c | 20 +- trunk/drivers/input/mouse/logips2pp.c | 3 +- trunk/drivers/input/mouse/trackpoint.c | 52 ++- trunk/drivers/input/serio/libps2.c | 5 + trunk/drivers/input/serio/serio.c | 65 ++- trunk/drivers/isdn/hardware/eicon/divasync.h | 1 - trunk/drivers/macintosh/Kconfig | 13 +- trunk/drivers/macintosh/adbhid.c | 14 +- trunk/drivers/macintosh/therm_pm72.c | 218 +++++++++- trunk/drivers/macintosh/therm_pm72.h | 33 +- trunk/drivers/macintosh/via-pmu-backlight.c | 68 ++- trunk/drivers/macintosh/via-pmu-led.c | 2 +- trunk/drivers/macintosh/via-pmu.c | 39 +- trunk/drivers/md/dm-mpath.c | 3 +- trunk/drivers/md/linear.c | 6 +- trunk/drivers/media/dvb/bt8xx/dst.c | 58 ++- trunk/drivers/media/dvb/dvb-core/Makefile | 6 +- .../drivers/media/dvb/dvb-core/dvb_frontend.c | 15 +- trunk/drivers/media/dvb/frontends/dvb-pll.c | 24 +- trunk/drivers/media/dvb/ttpci/av7110.c | 4 +- trunk/drivers/media/dvb/ttpci/av7110_v4l.c | 12 +- trunk/drivers/media/dvb/ttpci/budget-av.c | 3 + trunk/drivers/media/dvb/ttpci/budget-ci.c | 2 + trunk/drivers/media/dvb/ttpci/budget-core.c | 57 ++- trunk/drivers/media/dvb/ttpci/budget-patch.c | 2 + trunk/drivers/media/dvb/ttpci/budget.c | 5 +- trunk/drivers/media/dvb/ttpci/budget.h | 7 +- trunk/drivers/media/radio/Kconfig | 12 +- trunk/drivers/media/radio/Makefile | 1 + .../drivers/media/{video => radio}/dsbr100.c | 0 trunk/drivers/media/video/Kconfig | 16 +- trunk/drivers/media/video/Makefile | 2 +- trunk/drivers/media/video/bt8xx/Kconfig | 2 +- trunk/drivers/media/video/bt8xx/bttv-driver.c | 15 +- trunk/drivers/media/video/bt8xx/bttv-vbi.c | 15 +- trunk/drivers/media/video/compat_ioctl32.c | 54 ++- trunk/drivers/media/video/cpia2/Kconfig | 2 +- .../media/video/cx25840/cx25840-core.c | 4 +- trunk/drivers/media/video/cx88/cx88-input.c | 2 +- trunk/drivers/media/video/cx88/cx88-video.c | 5 +- trunk/drivers/media/video/msp3400-driver.c | 10 +- trunk/drivers/media/video/msp3400-kthreads.c | 4 +- .../drivers/media/video/pvrusb2/pvrusb2-hdw.c | 8 +- .../drivers/media/video/pvrusb2/pvrusb2-io.c | 9 +- .../drivers/media/video/pvrusb2/pvrusb2-io.h | 2 + .../media/video/pvrusb2/pvrusb2-ioread.c | 5 +- .../media/video/pvrusb2/pvrusb2-sysfs.c | 85 +++- trunk/drivers/media/video/pwc/Kconfig | 2 +- trunk/drivers/media/video/pwc/pwc-if.c | 1 + .../media/video/saa7134/saa7134-alsa.c | 10 +- .../media/video/saa7134/saa7134-core.c | 16 +- .../drivers/media/video/saa7134/saa7134-oss.c | 10 +- .../media/video/saa7134/saa7134-video.c | 6 +- trunk/drivers/media/video/saa7134/saa7134.h | 4 +- trunk/drivers/media/video/stradis.c | 1 - trunk/drivers/media/video/tuner-core.c | 31 +- trunk/drivers/media/video/tuner-simple.c | 19 +- trunk/drivers/media/video/tuner-types.c | 14 +- trunk/drivers/media/video/usbvideo/Kconfig | 8 +- trunk/drivers/media/video/v4l1-compat.c | 4 + trunk/drivers/media/video/v4l2-common.c | 24 +- trunk/drivers/media/video/videodev.c | 29 +- trunk/drivers/media/video/vivi.c | 4 +- trunk/drivers/mmc/mmc_queue.c | 3 +- trunk/drivers/mmc/wbsd.c | 9 +- trunk/drivers/net/appletalk/Kconfig | 2 +- trunk/drivers/net/bnx2.c | 49 +-- trunk/drivers/net/bnx2.h | 12 +- trunk/drivers/net/e1000/e1000_main.c | 11 +- trunk/drivers/net/myri10ge/myri10ge.c | 28 +- trunk/drivers/net/phy/phy.c | 8 +- trunk/drivers/net/ppp_generic.c | 30 +- trunk/drivers/net/s2io.c | 386 ++++++++--------- trunk/drivers/net/s2io.h | 10 + trunk/drivers/net/skge.c | 5 +- trunk/drivers/net/sunlance.c | 8 +- trunk/drivers/net/tg3.c | 169 +++++--- trunk/drivers/net/tg3.h | 8 +- trunk/drivers/net/via-velocity.c | 17 +- trunk/drivers/net/wireless/Kconfig | 1 + .../net/wireless/bcm43xx/bcm43xx_main.c | 2 +- trunk/drivers/net/wireless/orinoco.c | 4 +- trunk/drivers/net/wireless/zd1201.c | 2 + trunk/drivers/net/wireless/zd1211rw/zd_chip.c | 4 +- trunk/drivers/net/wireless/zd1211rw/zd_chip.h | 10 +- trunk/drivers/net/wireless/zd1211rw/zd_mac.c | 16 +- trunk/drivers/net/wireless/zd1211rw/zd_usb.c | 7 +- trunk/drivers/pci/hotplug/Kconfig | 9 +- trunk/drivers/pci/hotplug/acpiphp_core.c | 3 +- trunk/drivers/pci/hotplug/acpiphp_glue.c | 2 +- trunk/drivers/pci/hotplug/pciehp.h | 5 + trunk/drivers/pci/hotplug/pciehp_hpc.c | 4 - trunk/drivers/pci/pcie/portdrv_pci.c | 38 +- trunk/drivers/pci/quirks.c | 7 + trunk/drivers/pci/search.c | 48 ++- trunk/drivers/pcmcia/pcmcia_ioctl.c | 16 +- trunk/drivers/pcmcia/pcmcia_resource.c | 15 +- trunk/drivers/pnp/interface.c | 12 +- trunk/drivers/pnp/pnpacpi/rsparser.c | 8 + trunk/drivers/pnp/pnpbios/core.c | 2 +- trunk/drivers/s390/block/dasd.c | 2 +- trunk/drivers/s390/block/dasd_devmap.c | 84 ++-- trunk/drivers/s390/block/dasd_eckd.c | 8 +- trunk/drivers/s390/block/xpram.c | 25 +- trunk/drivers/s390/char/tape_class.c | 2 +- trunk/drivers/s390/cio/ccwgroup.c | 10 +- trunk/drivers/s390/cio/device_fsm.c | 4 +- trunk/drivers/s390/cio/device_ops.c | 3 + trunk/drivers/scsi/NCR53C9x.c | 16 +- trunk/drivers/scsi/ahci.c | 10 +- trunk/drivers/scsi/aic7xxx/aicasm/Makefile | 2 + trunk/drivers/scsi/arm/Kconfig | 3 + trunk/drivers/scsi/arm/fas216.c | 2 +- trunk/drivers/scsi/arm/scsi.h | 2 +- trunk/drivers/scsi/ata_piix.c | 5 +- trunk/drivers/scsi/esp.c | 12 +- trunk/drivers/scsi/libata-core.c | 34 +- trunk/drivers/scsi/libata-eh.c | 69 ++-- trunk/drivers/scsi/libata-scsi.c | 13 + trunk/drivers/scsi/sata_promise.c | 7 + trunk/drivers/scsi/sata_sil24.c | 1 - trunk/drivers/scsi/scsi_ioctl.c | 5 +- trunk/drivers/usb/Kconfig | 2 +- trunk/drivers/usb/core/devio.c | 20 +- trunk/drivers/usb/core/file.c | 13 +- trunk/drivers/usb/gadget/Kconfig | 2 +- trunk/drivers/usb/gadget/at91_udc.c | 176 +++++--- trunk/drivers/usb/gadget/at91_udc.h | 1 + trunk/drivers/usb/gadget/dummy_hcd.c | 6 +- trunk/drivers/usb/host/ehci-hcd.c | 2 +- trunk/drivers/usb/host/ohci-at91.c | 88 ++-- trunk/drivers/usb/host/ohci-au1xxx.c | 1 - trunk/drivers/usb/host/ohci-hcd.c | 3 +- trunk/drivers/usb/host/uhci-q.c | 4 +- trunk/drivers/usb/input/appletouch.c | 2 +- trunk/drivers/usb/input/ati_remote.c | 174 ++++---- trunk/drivers/usb/input/hid-input.c | 3 +- trunk/drivers/usb/input/hiddev.c | 72 ++-- trunk/drivers/usb/misc/cypress_cy7c63.c | 9 +- trunk/drivers/usb/misc/usbtest.c | 5 +- trunk/drivers/usb/net/rtl8150.c | 83 +++- trunk/drivers/usb/serial/Kconfig | 24 +- trunk/drivers/usb/serial/Makefile | 1 - trunk/drivers/usb/serial/anydata.c | 123 ------ trunk/drivers/usb/serial/ftdi_sio.c | 3 + trunk/drivers/usb/serial/ftdi_sio.h | 10 + trunk/drivers/usb/serial/ipaq.c | 3 + trunk/drivers/usb/serial/option.c | 76 +--- trunk/drivers/usb/serial/pl2303.c | 1 + trunk/drivers/usb/serial/pl2303.h | 4 + trunk/drivers/usb/storage/unusual_devs.h | 39 +- trunk/drivers/usb/storage/usb.c | 13 +- trunk/drivers/video/Kconfig | 40 +- trunk/drivers/video/Makefile | 1 + trunk/drivers/video/aty/aty128fb.c | 13 +- trunk/drivers/video/aty/atyfb_base.c | 4 +- trunk/drivers/video/aty/radeon_base.c | 18 +- trunk/drivers/video/aty/radeon_pm.c | 146 ++++++- trunk/drivers/video/aty/radeonfb.h | 6 +- trunk/drivers/video/au1100fb.c | 18 +- trunk/drivers/video/backlight/Kconfig | 4 +- trunk/drivers/video/console/mdacon.c | 4 +- trunk/drivers/video/fb_notify.c | 46 +++ trunk/drivers/video/fbmem.c | 54 +-- trunk/drivers/video/imacfb.c | 49 ++- trunk/drivers/video/nvidia/nvidia.c | 9 +- trunk/drivers/video/offb.c | 307 +++++++------- trunk/drivers/video/riva/fbdev.c | 7 +- trunk/fs/9p/conv.c | 6 +- trunk/fs/9p/vfs_inode.c | 6 +- trunk/fs/adfs/super.c | 2 +- trunk/fs/befs/linuxvfs.c | 11 +- trunk/fs/buffer.c | 7 +- trunk/fs/coda/file.c | 4 +- trunk/fs/efs/symlink.c | 3 +- trunk/fs/ext3/inode.c | 19 +- trunk/fs/ext3/namei.c | 15 +- trunk/fs/freevxfs/vxfs_lookup.c | 2 + trunk/fs/fuse/control.c | 4 +- trunk/fs/fuse/dir.c | 47 ++- trunk/fs/fuse/file.c | 10 +- trunk/fs/fuse/fuse_i.h | 2 +- trunk/fs/fuse/inode.c | 2 +- trunk/fs/inotify_user.c | 2 +- trunk/fs/jfs/inode.c | 16 +- trunk/fs/jfs/jfs_inode.h | 1 + trunk/fs/jfs/super.c | 118 +++++- trunk/fs/lockd/svclock.c | 12 +- trunk/fs/locks.c | 6 +- trunk/fs/namei.c | 8 +- trunk/fs/nfs/namespace.c | 4 +- trunk/fs/nfs/read.c | 2 +- trunk/fs/nfs/write.c | 2 +- trunk/fs/nfsd/nfsfh.c | 20 +- trunk/fs/ocfs2/dlm/dlmmaster.c | 1 - trunk/fs/ocfs2/dlm/dlmunlock.c | 43 +- trunk/fs/ocfs2/localalloc.c | 8 + trunk/fs/ocfs2/ocfs2.h | 2 +- trunk/fs/ocfs2/suballoc.c | 261 ++++++++++-- trunk/fs/ocfs2/suballoc.h | 2 + trunk/fs/ocfs2/super.c | 8 +- trunk/fs/partitions/Kconfig | 2 +- trunk/fs/reiserfs/file.c | 2 +- trunk/fs/reiserfs/inode.c | 26 +- trunk/fs/reiserfs/ioctl.c | 2 +- trunk/fs/udf/ialloc.c | 11 +- trunk/fs/udf/super.c | 7 + trunk/fs/ufs/balloc.c | 2 +- trunk/fs/ufs/namei.c | 3 +- trunk/fs/ufs/util.c | 17 +- trunk/fs/xfs/linux-2.6/xfs_buf.h | 4 +- trunk/fs/xfs/linux-2.6/xfs_super.c | 7 + trunk/fs/xfs/quota/xfs_qm_bhv.c | 19 +- trunk/fs/xfs/xfs_alloc.c | 103 ++--- trunk/fs/xfs/xfs_inode.c | 17 +- trunk/fs/xfs/xfs_log.c | 12 +- trunk/fs/xfs/xfs_vfsops.c | 2 +- .../include/asm-arm/arch-iop3xx/iop331-irqs.h | 4 - trunk/include/asm-arm/arch-omap/clock.h | 2 - trunk/include/asm-i386/kprobes.h | 1 + trunk/include/asm-ia64/kprobes.h | 1 + trunk/include/asm-ia64/meminit.h | 7 +- trunk/include/asm-ia64/pal.h | 7 +- trunk/include/asm-ia64/sn/xpc.h | 4 +- trunk/include/asm-ia64/system.h | 2 +- trunk/include/asm-powerpc/backlight.h | 4 + trunk/include/asm-powerpc/kexec.h | 3 +- trunk/include/asm-powerpc/kprobes.h | 1 + trunk/include/asm-powerpc/rtas.h | 1 + trunk/include/asm-sparc/signal.h | 2 +- trunk/include/asm-sparc64/kprobes.h | 1 + trunk/include/asm-sparc64/pgtable.h | 2 +- trunk/include/asm-sparc64/sfp-machine.h | 2 +- trunk/include/asm-x86_64/calgary.h | 5 - trunk/include/asm-x86_64/kprobes.h | 1 + trunk/include/asm-x86_64/page.h | 2 +- trunk/include/asm-x86_64/swiotlb.h | 2 + trunk/include/linux/audit.h | 43 +- trunk/include/linux/cn_proc.h | 3 +- trunk/include/linux/cpufreq.h | 3 - trunk/include/linux/debug_locks.h | 2 + trunk/include/linux/delayacct.h | 6 +- trunk/include/linux/ext3_fs.h | 9 + trunk/include/linux/fb.h | 4 +- trunk/include/linux/fsnotify.h | 6 +- trunk/include/linux/futex.h | 3 +- trunk/include/linux/ide.h | 1 + trunk/include/linux/if_vlan.h | 5 + trunk/include/linux/input.h | 24 +- trunk/include/linux/irq.h | 5 +- trunk/include/linux/jiffies.h | 4 +- trunk/include/linux/kernel.h | 1 + trunk/include/linux/kobject.h | 2 - trunk/include/linux/libata.h | 4 +- trunk/include/linux/lockd/lockd.h | 1 - trunk/include/linux/mm.h | 1 + trunk/include/linux/netdevice.h | 27 ++ trunk/include/linux/netfilter_bridge.h | 3 +- trunk/include/linux/nfs_fs.h | 6 +- trunk/include/linux/pci_ids.h | 1 + trunk/include/linux/pmu.h | 3 +- trunk/include/linux/sched.h | 8 + trunk/include/linux/security.h | 40 +- trunk/include/linux/skbuff.h | 52 ++- trunk/include/linux/sunrpc/xprt.h | 2 +- trunk/include/linux/usb.h | 7 +- trunk/include/linux/usb_usual.h | 4 +- trunk/include/linux/videodev.h | 7 +- trunk/include/linux/videodev2.h | 2 +- trunk/include/linux/vmstat.h | 8 +- trunk/include/media/v4l2-dev.h | 9 +- trunk/include/net/af_unix.h | 6 +- trunk/include/net/ip6_route.h | 12 +- trunk/include/net/ipv6.h | 3 + trunk/include/net/netdma.h | 2 +- trunk/include/net/netevent.h | 33 ++ trunk/include/net/red.h | 2 +- trunk/include/net/scm.h | 29 +- trunk/include/net/tcp.h | 3 + trunk/ipc/msg.c | 389 +++++++++--------- trunk/kernel/audit.c | 4 +- trunk/kernel/auditfilter.c | 26 ++ trunk/kernel/auditsc.c | 117 ++++-- trunk/kernel/delayacct.c | 8 +- trunk/kernel/fork.c | 4 +- trunk/kernel/futex.c | 138 +++++-- trunk/kernel/futex_compat.c | 34 +- trunk/kernel/hrtimer.c | 6 +- trunk/kernel/irq/manage.c | 28 +- trunk/kernel/kprobes.c | 1 + trunk/kernel/panic.c | 1 + trunk/kernel/power/process.c | 26 +- trunk/kernel/printk.c | 4 +- trunk/kernel/rcupdate.c | 4 +- trunk/kernel/resource.c | 9 +- trunk/kernel/rtmutex.c | 2 + trunk/kernel/sched.c | 22 +- trunk/kernel/signal.c | 25 +- trunk/kernel/softirq.c | 22 +- trunk/kernel/softlockup.c | 4 +- trunk/kernel/taskstats.c | 32 +- trunk/kernel/timer.c | 49 +-- trunk/kernel/workqueue.c | 91 +++- trunk/lib/kobject_uevent.c | 4 - trunk/lib/spinlock_debug.c | 10 +- trunk/lib/zlib_inflate/inflate.c | 5 +- trunk/mm/fadvise.c | 3 +- trunk/mm/filemap.c | 2 - trunk/mm/memory_hotplug.c | 44 +- trunk/mm/slab.c | 4 +- trunk/mm/swap.c | 20 + trunk/net/atm/proc.c | 2 +- trunk/net/bridge/br_if.c | 7 +- trunk/net/bridge/br_netfilter.c | 5 + trunk/net/bridge/br_netlink.c | 2 +- trunk/net/bridge/netfilter/ebt_ulog.c | 3 + trunk/net/core/Makefile | 2 +- trunk/net/core/dev.c | 56 +-- trunk/net/core/dst.c | 3 +- trunk/net/core/neighbour.c | 14 +- trunk/net/core/netevent.c | 69 ++++ trunk/net/core/pktgen.c | 4 + trunk/net/core/rtnetlink.c | 15 +- trunk/net/core/skbuff.c | 47 ++- trunk/net/core/utils.c | 7 +- trunk/net/core/wireless.c | 24 +- trunk/net/dccp/ipv6.c | 4 +- trunk/net/decnet/dn_route.c | 9 +- trunk/net/ieee80211/Kconfig | 1 + .../ieee80211/softmac/ieee80211softmac_auth.c | 28 +- trunk/net/ipv4/fib_semantics.c | 12 +- trunk/net/ipv4/igmp.c | 38 +- trunk/net/ipv4/ip_input.c | 2 +- trunk/net/ipv4/ip_output.c | 11 +- trunk/net/ipv4/ip_sockglue.c | 9 +- trunk/net/ipv4/ipmr.c | 19 +- trunk/net/ipv4/netfilter/arp_tables.c | 27 +- .../ipv4/netfilter/ip_conntrack_helper_h323.c | 2 +- .../net/ipv4/netfilter/ip_conntrack_netlink.c | 17 +- trunk/net/ipv4/netfilter/ip_conntrack_sip.c | 2 +- .../ipv4/netfilter/ip_conntrack_standalone.c | 4 +- trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c | 4 +- trunk/net/ipv4/netfilter/ip_tables.c | 36 +- trunk/net/ipv4/netfilter/ipt_ULOG.c | 5 + trunk/net/ipv4/netfilter/ipt_hashlimit.c | 14 +- trunk/net/ipv4/raw.c | 1 + trunk/net/ipv4/route.c | 10 +- trunk/net/ipv4/tcp.c | 5 +- trunk/net/ipv4/tcp_input.c | 3 +- trunk/net/ipv4/tcp_ipv4.c | 2 - trunk/net/ipv4/tcp_minisocks.c | 4 +- trunk/net/ipv4/tcp_output.c | 12 +- trunk/net/ipv4/tcp_probe.c | 5 +- trunk/net/ipv6/addrconf.c | 174 +++++++- trunk/net/ipv6/af_inet6.c | 2 +- trunk/net/ipv6/icmp.c | 13 + trunk/net/ipv6/inet6_connection_sock.c | 2 +- trunk/net/ipv6/ip6_input.c | 2 + trunk/net/ipv6/ip6_output.c | 131 ++++-- trunk/net/ipv6/mcast.c | 10 +- trunk/net/ipv6/netfilter/ip6_tables.c | 34 +- trunk/net/ipv6/raw.c | 1 + trunk/net/ipv6/route.c | 7 + trunk/net/ipv6/tcp_ipv6.c | 6 +- trunk/net/ipv6/udp.c | 2 +- trunk/net/ipv6/xfrm6_output.c | 2 +- trunk/net/ipx/af_ipx.c | 10 +- trunk/net/lapb/lapb_iface.c | 12 +- trunk/net/llc/af_llc.c | 20 +- trunk/net/llc/llc_sap.c | 7 +- trunk/net/netfilter/Kconfig | 4 +- trunk/net/netfilter/nf_conntrack_netlink.c | 17 +- trunk/net/netfilter/nf_conntrack_standalone.c | 4 +- trunk/net/netfilter/nf_queue.c | 9 +- trunk/net/netfilter/nfnetlink_log.c | 3 + trunk/net/netfilter/xt_SECMARK.c | 2 + trunk/net/netfilter/xt_physdev.c | 16 + trunk/net/netfilter/xt_pkttype.c | 12 +- trunk/net/netfilter/xt_string.c | 7 +- trunk/net/sched/cls_u32.c | 2 +- trunk/net/sched/sch_api.c | 2 +- trunk/net/sunrpc/cache.c | 6 +- trunk/net/sunrpc/clnt.c | 52 +-- trunk/net/sunrpc/rpc_pipe.c | 6 +- trunk/net/sunrpc/xprt.c | 21 +- trunk/net/sunrpc/xprtsock.c | 29 +- trunk/net/unix/af_unix.c | 17 +- trunk/net/xfrm/xfrm_policy.c | 27 +- trunk/scripts/Kbuild.include | 10 +- trunk/scripts/Makefile.modpost | 2 +- trunk/scripts/kconfig/confdata.c | 2 +- trunk/scripts/kernel-doc | 1 + trunk/scripts/mod/file2alias.c | 64 ++- trunk/security/dummy.c | 14 +- trunk/security/selinux/hooks.c | 38 +- trunk/security/selinux/ss/policydb.c | 12 +- trunk/security/selinux/ss/services.c | 4 +- trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c | 17 +- trunk/sound/aoa/core/snd-aoa-gpio-feature.c | 7 +- trunk/sound/aoa/core/snd-aoa-gpio-pmf.c | 2 +- trunk/sound/core/oss/mixer_oss.c | 3 +- trunk/sound/core/oss/pcm_oss.c | 2 + trunk/sound/core/seq/seq_device.c | 3 +- trunk/sound/core/sgbuf.c | 9 +- trunk/sound/drivers/vx/vx_pcm.c | 7 +- trunk/sound/oss/Kconfig | 6 +- trunk/sound/pci/Kconfig | 70 ++-- trunk/sound/pci/echoaudio/echoaudio.c | 4 +- trunk/sound/pci/emu10k1/emu10k1_main.c | 11 + trunk/sound/pci/emu10k1/irq.c | 6 +- trunk/sound/ppc/awacs.c | 3 +- trunk/sound/ppc/daca.c | 3 +- trunk/sound/ppc/keywest.c | 3 +- trunk/sound/ppc/powermac.c | 13 +- trunk/sound/ppc/tumbler.c | 3 +- trunk/sound/usb/usbaudio.c | 6 +- trunk/usr/Makefile | 3 + 644 files changed, 8068 insertions(+), 4381 deletions(-) create mode 100644 trunk/Documentation/fb/imacfb.txt create mode 100644 trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts rename trunk/drivers/media/{video => radio}/dsbr100.c (100%) delete mode 100644 trunk/drivers/usb/serial/anydata.c create mode 100644 trunk/drivers/video/fb_notify.c create mode 100644 trunk/include/net/netevent.h create mode 100644 trunk/net/core/netevent.c diff --git a/[refs] b/[refs] index 601146bd402e..8a2275bea002 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 16a74744231e57e354253567490ab9e4ccd2d605 +refs/heads/master: da547d775fa9ba8d9dcaee7bc4e960540e2be576 diff --git a/trunk/.gitignore b/trunk/.gitignore index 27fd37621255..b1f5b9df2ae1 100644 --- a/trunk/.gitignore +++ b/trunk/.gitignore @@ -30,6 +30,11 @@ include/config include/linux/autoconf.h include/linux/compile.h include/linux/version.h +include/linux/utsrelease.h # stgit generated dirs patches-* + +# quilt's files +patches +series diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 1ae4dc0fd856..f8fe882e33dc 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -58,6 +58,9 @@ !Iinclude/linux/ktime.h !Iinclude/linux/hrtimer.h !Ekernel/hrtimer.c + + Workqueues and Kevents +!Ekernel/workqueue.c Internal Functions !Ikernel/exit.c @@ -300,7 +303,7 @@ X!Ekernel/module.c Resources Management -!Ekernel/resource.c +!Ikernel/resource.c MTRR Handling @@ -312,9 +315,7 @@ X!Ekernel/module.c !Edrivers/pci/pci-driver.c !Edrivers/pci/remove.c !Edrivers/pci/pci-acpi.c - +!Edrivers/pci/search.c !Edrivers/pci/msi.c !Edrivers/pci/bus.c size-4096 slab */ @@ -3708,7 +3708,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, #define E1000_CB_LENGTH 256 if (length < E1000_CB_LENGTH) { struct sk_buff *new_skb = - dev_alloc_skb(length + NET_IP_ALIGN); + netdev_alloc_skb(netdev, length + NET_IP_ALIGN); if (new_skb) { skb_reserve(new_skb, NET_IP_ALIGN); new_skb->dev = netdev; @@ -3979,7 +3979,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, while (cleaned_count--) { if (!(skb = buffer_info->skb)) - skb = dev_alloc_skb(bufsz); + skb = netdev_alloc_skb(netdev, bufsz); else { skb_trim(skb, 0); goto map_skb; @@ -3997,7 +3997,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " "at %p\n", bufsz, skb->data); /* Try again, without freeing the previous */ - skb = dev_alloc_skb(bufsz); + skb = netdev_alloc_skb(netdev, bufsz); /* Failed allocation, critical failure */ if (!skb) { dev_kfree_skb(oldskb); @@ -4121,7 +4121,8 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc->read.buffer_addr[j+1] = ~0; } - skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); + skb = netdev_alloc_skb(netdev, + adapter->rx_ps_bsize0 + NET_IP_ALIGN); if (unlikely(!skb)) { adapter->alloc_rx_buff_failed++; diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 07ca9480a6fe..9bdd43ab3573 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -177,6 +177,7 @@ struct myri10ge_priv { struct work_struct watchdog_work; struct timer_list watchdog_timer; int watchdog_tx_done; + int watchdog_tx_req; int watchdog_resets; int tx_linearized; int pause; @@ -448,6 +449,7 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) struct mcp_gen_header *hdr; size_t hdr_offset; int status; + unsigned i; if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { dev_err(dev, "Unable to load %s firmware image via hotplug\n", @@ -479,18 +481,12 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) goto abort_with_fw; crc = crc32(~0, fw->data, fw->size); - if (mgp->tx.boundary == 2048) { - /* Avoid PCI burst on chipset with unaligned completions. */ - int i; - __iomem u32 *ptr = (__iomem u32 *) (mgp->sram + - MYRI10GE_FW_OFFSET); - for (i = 0; i < fw->size / 4; i++) { - __raw_writel(((u32 *) fw->data)[i], ptr + i); - wmb(); - } - } else { - myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data, - fw->size); + for (i = 0; i < fw->size; i += 256) { + myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i, + fw->data + i, + min(256U, (unsigned)(fw->size - i))); + mb(); + readb(mgp->sram); } /* corruption checking is good for parity recovery and buggy chipset */ memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size); @@ -620,7 +616,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) return -ENXIO; } dev_info(&mgp->pdev->dev, "handoff confirmed\n"); - myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); + myri10ge_dummy_rdma(mgp, 1); return 0; } @@ -2429,7 +2425,7 @@ static int myri10ge_resume(struct pci_dev *pdev) } myri10ge_reset(mgp); - myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); + myri10ge_dummy_rdma(mgp, 1); /* Save configuration space to be restored if the * nic resets due to a parity error */ @@ -2547,7 +2543,8 @@ static void myri10ge_watchdog_timer(unsigned long arg) mgp = (struct myri10ge_priv *)arg; if (mgp->tx.req != mgp->tx.done && - mgp->tx.done == mgp->watchdog_tx_done) + mgp->tx.done == mgp->watchdog_tx_done && + mgp->watchdog_tx_req != mgp->watchdog_tx_done) /* nic seems like it might be stuck.. */ schedule_work(&mgp->watchdog_work); else @@ -2556,6 +2553,7 @@ static void myri10ge_watchdog_timer(unsigned long arg) jiffies + myri10ge_watchdog_timeout * HZ); mgp->watchdog_tx_done = mgp->tx.done; + mgp->watchdog_tx_req = mgp->tx.req; } static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index 7d5c2233c252..f5aad77288f9 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -419,9 +419,8 @@ void phy_start_machine(struct phy_device *phydev, /* phy_stop_machine * - * description: Stops the state machine timer, sets the state to - * UP (unless it wasn't up yet), and then frees the interrupt, - * if it is in use. This function must be called BEFORE + * description: Stops the state machine timer, sets the state to UP + * (unless it wasn't up yet). This function must be called BEFORE * phy_detach. */ void phy_stop_machine(struct phy_device *phydev) @@ -433,9 +432,6 @@ void phy_stop_machine(struct phy_device *phydev) phydev->state = PHY_UP; spin_unlock(&phydev->lock); - if (phydev->irq != PHY_POLL) - phy_stop_interrupts(phydev); - phydev->adjust_state = NULL; } diff --git a/trunk/drivers/net/ppp_generic.c b/trunk/drivers/net/ppp_generic.c index 0ec6e9d57b94..c872f7c6cce3 100644 --- a/trunk/drivers/net/ppp_generic.c +++ b/trunk/drivers/net/ppp_generic.c @@ -192,7 +192,7 @@ struct cardmap { void *ptr[CARDMAP_WIDTH]; }; static void *cardmap_get(struct cardmap *map, unsigned int nr); -static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr); +static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr); static unsigned int cardmap_find_first_free(struct cardmap *map); static void cardmap_destroy(struct cardmap **map); @@ -1995,10 +1995,9 @@ ppp_register_channel(struct ppp_channel *chan) { struct channel *pch; - pch = kmalloc(sizeof(struct channel), GFP_KERNEL); + pch = kzalloc(sizeof(struct channel), GFP_KERNEL); if (pch == 0) return -ENOMEM; - memset(pch, 0, sizeof(struct channel)); pch->ppp = NULL; pch->chan = chan; chan->ppp = pch; @@ -2408,13 +2407,12 @@ ppp_create_interface(int unit, int *retp) int ret = -ENOMEM; int i; - ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL); + ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL); if (!ppp) goto out; dev = alloc_netdev(0, "", ppp_setup); if (!dev) goto out1; - memset(ppp, 0, sizeof(struct ppp)); ppp->mru = PPP_MRU; init_ppp_file(&ppp->file, INTERFACE); @@ -2454,11 +2452,16 @@ ppp_create_interface(int unit, int *retp) } atomic_inc(&ppp_unit_count); - cardmap_set(&all_ppp_units, unit, ppp); + ret = cardmap_set(&all_ppp_units, unit, ppp); + if (ret != 0) + goto out3; + mutex_unlock(&all_ppp_mutex); *retp = 0; return ppp; +out3: + atomic_dec(&ppp_unit_count); out2: mutex_unlock(&all_ppp_mutex); free_netdev(dev); @@ -2695,7 +2698,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr) return NULL; } -static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) +static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) { struct cardmap *p; int i; @@ -2704,8 +2707,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) { do { /* need a new top level */ - struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); - memset(np, 0, sizeof(*np)); + struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL); + if (!np) + goto enomem; np->ptr[0] = p; if (p != NULL) { np->shift = p->shift + CARDMAP_ORDER; @@ -2719,8 +2723,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) while (p->shift > 0) { i = (nr >> p->shift) & CARDMAP_MASK; if (p->ptr[i] == NULL) { - struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); - memset(np, 0, sizeof(*np)); + struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL); + if (!np) + goto enomem; np->shift = p->shift - CARDMAP_ORDER; np->parent = p; p->ptr[i] = np; @@ -2735,6 +2740,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) set_bit(i, &p->inuse); else clear_bit(i, &p->inuse); + return 0; + enomem: + return -ENOMEM; } static unsigned int cardmap_find_first_free(struct cardmap *map) diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index e1fe3a0a7b0b..132ed32bce1a 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -76,7 +76,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.14.2" +#define DRV_VERSION "2.0.15.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -370,38 +370,50 @@ static const u64 fix_mac[] = { END_SIGN }; +MODULE_AUTHOR("Raghavendra Koushik "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + + /* Module Loadable parameters. */ -static unsigned int tx_fifo_num = 1; -static unsigned int tx_fifo_len[MAX_TX_FIFOS] = - {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; -static unsigned int rx_ring_num = 1; -static unsigned int rx_ring_sz[MAX_RX_RINGS] = - {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; -static unsigned int rts_frm_len[MAX_RX_RINGS] = - {[0 ...(MAX_RX_RINGS - 1)] = 0 }; -static unsigned int rx_ring_mode = 1; -static unsigned int use_continuous_tx_intrs = 1; -static unsigned int rmac_pause_time = 0x100; -static unsigned int mc_pause_threshold_q0q3 = 187; -static unsigned int mc_pause_threshold_q4q7 = 187; -static unsigned int shared_splits; -static unsigned int tmac_util_period = 5; -static unsigned int rmac_util_period = 5; -static unsigned int bimodal = 0; -static unsigned int l3l4hdr_size = 128; -#ifndef CONFIG_S2IO_NAPI -static unsigned int indicate_max_pkts; -#endif +S2IO_PARM_INT(tx_fifo_num, 1); +S2IO_PARM_INT(rx_ring_num, 1); + + +S2IO_PARM_INT(rx_ring_mode, 1); +S2IO_PARM_INT(use_continuous_tx_intrs, 1); +S2IO_PARM_INT(rmac_pause_time, 0x100); +S2IO_PARM_INT(mc_pause_threshold_q0q3, 187); +S2IO_PARM_INT(mc_pause_threshold_q4q7, 187); +S2IO_PARM_INT(shared_splits, 0); +S2IO_PARM_INT(tmac_util_period, 5); +S2IO_PARM_INT(rmac_util_period, 5); +S2IO_PARM_INT(bimodal, 0); +S2IO_PARM_INT(l3l4hdr_size, 128); /* Frequency of Rx desc syncs expressed as power of 2 */ -static unsigned int rxsync_frequency = 3; +S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ -static unsigned int intr_type = 0; +S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ -static unsigned int lro = 0; +S2IO_PARM_INT(lro, 0); /* Max pkts to be aggregated by LRO at one time. If not specified, * aggregation happens until we hit max IP pkt size(64K) */ -static unsigned int lro_max_pkts = 0xFFFF; +S2IO_PARM_INT(lro_max_pkts, 0xFFFF); +#ifndef CONFIG_S2IO_NAPI +S2IO_PARM_INT(indicate_max_pkts, 0); +#endif + +static unsigned int tx_fifo_len[MAX_TX_FIFOS] = + {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; +static unsigned int rx_ring_sz[MAX_RX_RINGS] = + {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; +static unsigned int rts_frm_len[MAX_RX_RINGS] = + {[0 ...(MAX_RX_RINGS - 1)] = 0 }; + +module_param_array(tx_fifo_len, uint, NULL, 0); +module_param_array(rx_ring_sz, uint, NULL, 0); +module_param_array(rts_frm_len, uint, NULL, 0); /* * S2IO device table. @@ -464,10 +476,9 @@ static int init_shared_mem(struct s2io_nic *nic) size += config->tx_cfg[i].fifo_len; } if (size > MAX_AVAILABLE_TXDS) { - DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ", - __FUNCTION__); + DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); - return FAILURE; + return -EINVAL; } lst_size = (sizeof(TxD_t) * config->max_txds); @@ -547,6 +558,7 @@ static int init_shared_mem(struct s2io_nic *nic) nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); if (!nic->ufo_in_band_v) return -ENOMEM; + memset(nic->ufo_in_band_v, 0, size); /* Allocation and initialization of RXDs in Rings */ size = 0; @@ -1213,7 +1225,7 @@ static int init_nic(struct s2io_nic *nic) break; } - /* Enable Tx FIFO partition 0. */ + /* Enable all configured Tx FIFO partitions */ val64 = readq(&bar0->tx_fifo_partition_0); val64 |= (TX_FIFO_PARTITION_EN); writeq(val64, &bar0->tx_fifo_partition_0); @@ -1650,7 +1662,7 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) writeq(temp64, &bar0->general_int_mask); /* * If Hercules adapter enable GPIO otherwise - * disabled all PCIX, Flash, MDIO, IIC and GPIO + * disable all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ @@ -2119,7 +2131,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } - txdlp->Host_Control = 0; + memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); return(skb); } @@ -2371,9 +2383,14 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb->tail = (void *) (unsigned long)tmp; - ((RxD3_t*)rxdp)->Buffer0_ptr = - pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, + if (!(((RxD3_t*)rxdp)->Buffer0_ptr)) + ((RxD3_t*)rxdp)->Buffer0_ptr = + pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); + else + pci_dma_sync_single_for_device(nic->pdev, + (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2386,10 +2403,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer not used */ - ((RxD3_t*)rxdp)->Buffer1_ptr = - pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); + /* Buffer-1 will be dummy buffer. Not used */ + if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) { + ((RxD3_t*)rxdp)->Buffer1_ptr = + pci_map_single(nic->pdev, + ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); + } rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); @@ -2614,23 +2634,23 @@ static int s2io_poll(struct net_device *dev, int *budget) } #endif +#ifdef CONFIG_NET_POLL_CONTROLLER /** - * s2io_netpoll - Rx interrupt service handler for netpoll support + * s2io_netpoll - netpoll event handler entry point * @dev : pointer to the device structure. * Description: - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. + * This function will be called by upper layer to check for events on the + * interface in situations where interrupts are disabled. It is used for + * specific in-kernel networking tasks, such as remote consoles and kernel + * debugging over the network (example netdump in RedHat). */ - -#ifdef CONFIG_NET_POLL_CONTROLLER static void s2io_netpoll(struct net_device *dev) { nic_t *nic = dev->priv; mac_info_t *mac_control; struct config_param *config; XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64; + u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; disable_irq(dev->irq); @@ -2639,9 +2659,17 @@ static void s2io_netpoll(struct net_device *dev) mac_control = &nic->mac_control; config = &nic->config; - val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); + writeq(val64, &bar0->tx_traffic_int); + /* we need to free up the transmitted skbufs or else netpoll will + * run out of skbs and will fail and eventually netpoll application such + * as netdump will fail. + */ + for (i = 0; i < config->tx_fifo_num; i++) + tx_intr_handler(&mac_control->fifos[i]); + + /* check for received packet and indicate up to network */ for (i = 0; i < config->rx_ring_num; i++) rx_intr_handler(&mac_control->rings[i]); @@ -2708,7 +2736,7 @@ static void rx_intr_handler(ring_info_t *ring_data) /* If your are next to put index then it's FIFO full condition */ if ((get_block == put_block) && (get_info.offset + 1) == put_info.offset) { - DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name); + DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); @@ -2728,18 +2756,15 @@ static void rx_intr_handler(ring_info_t *ring_data) HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { - pci_unmap_single(nic->pdev, (dma_addr_t) + pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) - ((RxD3_t*)rxdp)->Buffer1_ptr, - BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); } else { - pci_unmap_single(nic->pdev, (dma_addr_t) + pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) @@ -3327,7 +3352,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { - /* Clear parity err detect bit */ + /* Clear "detected parity error" bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ @@ -3528,7 +3553,7 @@ static void restore_xmsi_data(nic_t *nic) u64 val64; int i; - for (i=0; i< nic->avail_msix_vectors; i++) { + for (i=0; i < MAX_REQUESTED_MSI_X; i++) { writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6)); @@ -3547,7 +3572,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ - for (i=0; i< nic->avail_msix_vectors; i++) { + for (i=0; i < MAX_REQUESTED_MSI_X; i++) { val64 = (BIT(15) | vBIT(i, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, i)) { @@ -3808,13 +3833,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) TxD_t *txdp; TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; -#ifdef NETIF_F_TSO - int mss; -#endif u16 vlan_tag = 0; int vlan_priority = 0; mac_info_t *mac_control; struct config_param *config; + int offload_type; mac_control = &sp->mac_control; config = &sp->config; @@ -3862,13 +3885,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - txdp->Control_1 = 0; - txdp->Control_2 = 0; + offload_type = s2io_offload_type(skb); #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->gso_size; - if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; - txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); + txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); } #endif if (skb->ip_summed == CHECKSUM_HW) { @@ -3886,10 +3907,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { + if (offload_type == SKB_GSO_UDP) { int ufo_size; - ufo_size = skb_shinfo(skb)->gso_size; + ufo_size = s2io_udp_mss(skb); ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3906,16 +3927,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); txdp++; - txdp->Control_1 = 0; - txdp->Control_2 = 0; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3930,12 +3948,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3944,13 +3962,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | TX_FIFO_LAST_LIST); - -#ifdef NETIF_F_TSO - if (mss) - val64 |= TX_FIFO_SPECIAL_FUNC; -#endif - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type) val64 |= TX_FIFO_SPECIAL_FUNC; + writeq(val64, &tx_fifo->List_Control); mmiowb(); @@ -3984,13 +3998,41 @@ s2io_alarm_handle(unsigned long data) mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } +static int s2io_chk_rx_buffers(nic_t *sp, int rng_n) +{ + int rxb_size, level; + + if (!sp->lro) { + rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); + level = rx_buffer_level(sp, rxb_size, rng_n); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + int ret; + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "Out of memory in %s", + __FUNCTION__); + clear_bit(0, (&sp->tasklet_status)); + return -1; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) + tasklet_schedule(&sp->task); + + } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + } + return 0; +} + static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; int i; - int ret; mac_info_t *mac_control; struct config_param *config; @@ -4012,35 +4054,8 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) * reallocate the buffers from the interrupt handler itself, * else schedule a tasklet to reallocate the buffers. */ - for (i = 0; i < config->rx_ring_num; i++) { - if (!sp->lro) { - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", - dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); - clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, i) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - break; - } - } + for (i = 0; i < config->rx_ring_num; i++) + s2io_chk_rx_buffers(sp, i); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; @@ -4051,39 +4066,13 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs) { ring_info_t *ring = (ring_info_t *)dev_id; nic_t *sp = ring->nic; - struct net_device *dev = (struct net_device *) dev_id; - int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); - rx_intr_handler(ring); - - rng_n = ring->ring_no; - if (!sp->lro) { - rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); - level = rx_buffer_level(sp, rxb_size, rng_n); - if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "Out of memory in %s", - __FUNCTION__); - clear_bit(0, (&sp->tasklet_status)); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - } + rx_intr_handler(ring); + s2io_chk_rx_buffers(sp, ring->ring_no); atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; } @@ -4248,37 +4237,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) * else schedule a tasklet to reallocate the buffers. */ #ifndef CONFIG_S2IO_NAPI - for (i = 0; i < config->rx_ring_num; i++) { - if (!sp->lro) { - int ret; - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", - dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); - clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - writeq(org_mask, &bar0->general_int_mask); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, i) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); - break; - } - } + for (i = 0; i < config->rx_ring_num; i++) + s2io_chk_rx_buffers(sp, i); #endif writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); @@ -4308,6 +4268,8 @@ static void s2io_updt_stats(nic_t *sp) if (cnt == 5) break; /* Updt failed */ } while(1); + } else { + memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t)); } } @@ -4942,7 +4904,8 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } static void s2io_vpd_read(nic_t *nic) { - u8 vpd_data[256],data; + u8 *vpd_data; + u8 data; int i=0, cnt, fail = 0; int vpd_addr = 0x80; @@ -4955,6 +4918,10 @@ static void s2io_vpd_read(nic_t *nic) vpd_addr = 0x50; } + vpd_data = kmalloc(256, GFP_KERNEL); + if (!vpd_data) + return; + for (i = 0; i < 256; i +=4 ) { pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); pci_read_config_byte(nic->pdev, (vpd_addr + 2), &data); @@ -4977,6 +4944,7 @@ static void s2io_vpd_read(nic_t *nic) memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } + kfree(vpd_data); } /** @@ -5295,7 +5263,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) else *data = 0; - return 0; + return *data; } /** @@ -5753,6 +5721,19 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) return 0; } +static u32 s2io_ethtool_op_get_tso(struct net_device *dev) +{ + return (dev->features & NETIF_F_TSO) != 0; +} +static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); + else + dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + + return 0; +} static struct ethtool_ops netdev_ethtool_ops = { .get_settings = s2io_ethtool_gset, @@ -5773,8 +5754,8 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, + .get_tso = s2io_ethtool_op_get_tso, + .set_tso = s2io_ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, @@ -6337,7 +6318,7 @@ static int s2io_card_up(nic_t * sp) s2io_set_multicast(dev); if (sp->lro) { - /* Initialize max aggregatable pkts based on MTU */ + /* Initialize max aggregatable pkts per session based on MTU */ sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; /* Check if we can use(if specified) user provided value */ if (lro_max_pkts < sp->lro_max_aggr_per_sess) @@ -6438,7 +6419,7 @@ static void s2io_tx_watchdog(struct net_device *dev) * @cksum : FCS checksum of the frame. * @ring_no : the ring from which this RxD was extracted. * Description: - * This function is called by the Tx interrupt serivce routine to perform + * This function is called by the Rx interrupt serivce routine to perform * some OS related operations on the SKB before passing it to the upper * layers. It mainly checks if the checksum is OK, if so adds it to the * SKBs cksum variable, increments the Rx packet count and passes the SKB @@ -6698,33 +6679,6 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); } -MODULE_AUTHOR("Raghavendra Koushik "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(tx_fifo_num, int, 0); -module_param(rx_ring_num, int, 0); -module_param(rx_ring_mode, int, 0); -module_param_array(tx_fifo_len, uint, NULL, 0); -module_param_array(rx_ring_sz, uint, NULL, 0); -module_param_array(rts_frm_len, uint, NULL, 0); -module_param(use_continuous_tx_intrs, int, 1); -module_param(rmac_pause_time, int, 0); -module_param(mc_pause_threshold_q0q3, int, 0); -module_param(mc_pause_threshold_q4q7, int, 0); -module_param(shared_splits, int, 0); -module_param(tmac_util_period, int, 0); -module_param(rmac_util_period, int, 0); -module_param(bimodal, bool, 0); -module_param(l3l4hdr_size, int , 0); -#ifndef CONFIG_S2IO_NAPI -module_param(indicate_max_pkts, int, 0); -#endif -module_param(rxsync_frequency, int, 0); -module_param(intr_type, int, 0); -module_param(lro, int, 0); -module_param(lro_max_pkts, int, 0); - static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) { if ( tx_fifo_num > 8) { @@ -6832,8 +6786,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"), - pci_disable_device(pdev); + DBG_PRINT(ERR_DBG, "Request Regions failed\n"); + pci_disable_device(pdev); return -ENODEV; } } @@ -6957,7 +6911,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* initialize the shared memory used by the NIC and the host */ if (init_shared_mem(sp)) { DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", - __FUNCTION__); + dev->name); ret = -ENOMEM; goto mem_alloc_failed; } @@ -7094,6 +7048,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->addr_len = ETH_ALEN; memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); + /* reset Nic and bring it to known state */ + s2io_reset(sp); + /* * Initialize the tasklet status and link state flags * and the card state parameter @@ -7131,11 +7088,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } s2io_vpd_read(sp); - DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); - DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", - get_xena_rev_id(sp->pdev), - s2io_driver_version); DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n"); + DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, + sp->product_name, get_xena_rev_id(sp->pdev)); + DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, + s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, sp->def_mac_addr[0].mac_addr[0], @@ -7436,8 +7393,13 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, if (ip->ihl != 5) /* IP has options */ return -1; + /* If we see CE codepoint in IP header, packet is not mergeable */ + if (INET_ECN_is_ce(ipv4_get_dsfield(ip))) + return -1; + + /* If we see ECE or CWR flags in TCP header, packet is not mergeable */ if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin || - !tcp->ack) { + tcp->ece || tcp->cwr || !tcp->ack) { /* * Currently recognize only the ack control word and * any other control field being set would result in @@ -7591,18 +7553,16 @@ static void queue_rx_frame(struct sk_buff *skb) static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { - struct sk_buff *tmp, *first = lro->parent; + struct sk_buff *first = lro->parent; first->len += tcp_len; first->data_len = lro->frags_len; skb_pull(skb, (skb->len - tcp_len)); - if ((tmp = skb_shinfo(first)->frag_list)) { - while (tmp->next) - tmp = tmp->next; - tmp->next = skb; - } + if (skb_shinfo(first)->frag_list) + lro->last_frag->next = skb; else skb_shinfo(first)->frag_list = skb; + lro->last_frag = skb; sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; } diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index 217097bc22f1..5ed49c3be1e9 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -719,6 +719,7 @@ struct msix_info_st { /* Data structure to represent a LRO session */ typedef struct lro { struct sk_buff *parent; + struct sk_buff *last_frag; u8 *l2h; struct iphdr *iph; struct tcphdr *tcph; @@ -1011,4 +1012,13 @@ static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); + +#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size +#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size +#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type + +#define S2IO_PARM_INT(X, def_val) \ + static unsigned int X = def_val;\ + module_param(X , uint, 0); + #endif /* _S2IO_H */ diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index 82200bfaa8ed..7de9a07b2ac2 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -516,10 +516,7 @@ static int skge_set_pauseparam(struct net_device *dev, /* Chip internal frequency for clock calculations */ static inline u32 hwkhz(const struct skge_hw *hw) { - if (hw->chip_id == CHIP_ID_GENESIS) - return 53215; /* or: 53.125 MHz */ - else - return 78215; /* or: 78.125 MHz */ + return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125; } /* Chip HZ to microseconds */ diff --git a/trunk/drivers/net/sunlance.c b/trunk/drivers/net/sunlance.c index 1ef9fd39a79a..0e3fdf7c6dd3 100644 --- a/trunk/drivers/net/sunlance.c +++ b/trunk/drivers/net/sunlance.c @@ -1537,7 +1537,7 @@ static int __init sparc_lance_init(void) { if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset(&sun4_sdev, 0, sizeof(sdev)); + memset(&sun4_sdev, 0, sizeof(struct sbus_dev)); sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; sun4_sdev.irqs[0] = 6; return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); @@ -1547,16 +1547,16 @@ static int __init sparc_lance_init(void) static int __exit sunlance_sun4_remove(void) { - struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev); + struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); struct net_device *net_dev = lp->dev; unregister_netdevice(net_dev); - lance_free_hwresources(root_lance_dev); + lance_free_hwresources(lp); free_netdev(net_dev); - dev_set_drvdata(&sun4_sdev->dev, NULL); + dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL); return 0; } diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index ce6f3be86da0..eafabb253f08 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.62" -#define DRV_MODULE_RELDATE "June 30, 2006" +#define DRV_MODULE_VERSION "3.65" +#define DRV_MODULE_RELDATE "August 07, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -123,9 +123,6 @@ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) -#define TX_BUFFS_AVAIL(TP) \ - ((TP)->tx_pending - \ - (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1))) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) @@ -2987,6 +2984,13 @@ static void tg3_tx_recover(struct tg3 *tp) spin_unlock(&tp->lock); } +static inline u32 tg3_tx_avail(struct tg3 *tp) +{ + smp_mb(); + return (tp->tx_pending - + ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1))); +} + /* Tigon3 never reports partial packet sends. So we do not * need special logic to handle SKBs that have not had all * of their frags sent yet, like SunGEM does. @@ -3038,12 +3042,20 @@ static void tg3_tx(struct tg3 *tp) tp->tx_cons = sw_idx; - if (unlikely(netif_queue_stopped(tp->dev))) { - spin_lock(&tp->tx_lock); + /* Need to make the tx_cons update visible to tg3_start_xmit() + * before checking for netif_queue_stopped(). Without the + * memory barrier, there is a small possibility that tg3_start_xmit() + * will miss it and cause the queue to be stopped forever. + */ + smp_mb(); + + if (unlikely(netif_queue_stopped(tp->dev) && + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { + netif_tx_lock(tp->dev); if (netif_queue_stopped(tp->dev) && - (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); + netif_tx_unlock(tp->dev); } } @@ -3097,11 +3109,10 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. */ - skb = dev_alloc_skb(skb_size); + skb = netdev_alloc_skb(tp->dev, skb_size); if (skb == NULL) return -ENOMEM; - skb->dev = tp->dev; skb_reserve(skb, tp->rx_offset); mapping = pci_map_single(tp->pdev, skb->data, @@ -3270,11 +3281,10 @@ static int tg3_rx(struct tg3 *tp, int budget) tg3_recycle_rx(tp, opaque_key, desc_idx, *post_ptr); - copy_skb = dev_alloc_skb(len + 2); + copy_skb = netdev_alloc_skb(tp->dev, len + 2); if (copy_skb == NULL) goto drop_it_no_recycle; - copy_skb->dev = tp->dev; skb_reserve(copy_skb, 2); skb_put(copy_skb, len); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); @@ -3590,6 +3600,28 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, static int tg3_init_hw(struct tg3 *, int); static int tg3_halt(struct tg3 *, int, int); +/* Restart hardware after configuration changes, self-test, etc. + * Invoked with tp->lock held. + */ +static int tg3_restart_hw(struct tg3 *tp, int reset_phy) +{ + int err; + + err = tg3_init_hw(tp, reset_phy); + if (err) { + printk(KERN_ERR PFX "%s: Failed to re-initialize device, " + "aborting.\n", tp->dev->name); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + tg3_full_unlock(tp); + del_timer_sync(&tp->timer); + tp->irq_sync = 0; + netif_poll_enable(tp->dev); + dev_close(tp->dev); + tg3_full_lock(tp, 0); + } + return err; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void tg3_poll_controller(struct net_device *dev) { @@ -3630,13 +3662,15 @@ static void tg3_reset_task(void *_data) } tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); - tg3_init_hw(tp, 1); + if (tg3_init_hw(tp, 1)) + goto out; tg3_netif_start(tp); if (restart_timer) mod_timer(&tp->timer, jiffies + 1); +out: tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); @@ -3773,7 +3807,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3869,12 +3903,10 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { - spin_lock(&tp->tx_lock); + if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); } out_unlock: @@ -3896,7 +3928,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) struct sk_buff *segs, *nskb; /* Estimate the number of fragments in the worst case */ - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { netif_stop_queue(tp->dev); return NETDEV_TX_BUSY; } @@ -3936,7 +3968,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -4086,12 +4118,10 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { - spin_lock(&tp->tx_lock); + if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); } out_unlock: @@ -4124,6 +4154,7 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, static int tg3_change_mtu(struct net_device *dev, int new_mtu) { struct tg3 *tp = netdev_priv(dev); + int err; if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) return -EINVAL; @@ -4144,13 +4175,14 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_set_mtu(dev, tp, new_mtu); - tg3_init_hw(tp, 0); + err = tg3_restart_hw(tp, 0); - tg3_netif_start(tp); + if (!err) + tg3_netif_start(tp); tg3_full_unlock(tp); - return 0; + return err; } /* Free up pending packets in all rx/tx rings. @@ -4232,7 +4264,7 @@ static void tg3_free_rings(struct tg3 *tp) * end up in the driver. tp->{tx,}lock are held and thus * we may not sleep. */ -static void tg3_init_rings(struct tg3 *tp) +static int tg3_init_rings(struct tg3 *tp) { u32 i; @@ -4281,18 +4313,38 @@ static void tg3_init_rings(struct tg3 *tp) /* Now allocate fresh SKBs for each rx ring. */ for (i = 0; i < tp->rx_pending; i++) { - if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, - -1, i) < 0) + if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, -1, i) < 0) { + printk(KERN_WARNING PFX + "%s: Using a smaller RX standard ring, " + "only %d out of %d buffers were allocated " + "successfully.\n", + tp->dev->name, i, tp->rx_pending); + if (i == 0) + return -ENOMEM; + tp->rx_pending = i; break; + } } if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { for (i = 0; i < tp->rx_jumbo_pending; i++) { if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, - -1, i) < 0) + -1, i) < 0) { + printk(KERN_WARNING PFX + "%s: Using a smaller RX jumbo ring, " + "only %d out of %d buffers were " + "allocated successfully.\n", + tp->dev->name, i, tp->rx_jumbo_pending); + if (i == 0) { + tg3_free_rings(tp); + return -ENOMEM; + } + tp->rx_jumbo_pending = i; break; + } } } + return 0; } /* @@ -5815,6 +5867,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) { struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; + int err = 0; if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; @@ -5832,9 +5885,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_init_hw(tp, 0); - - tg3_netif_start(tp); + err = tg3_restart_hw(tp, 0); + if (!err) + tg3_netif_start(tp); tg3_full_unlock(tp); } else { spin_lock_bh(&tp->lock); @@ -5842,7 +5895,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) spin_unlock_bh(&tp->lock); } - return 0; + return err; } /* tp->lock is held. */ @@ -5942,7 +5995,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) * can only do this after the hardware has been * successfully reset. */ - tg3_init_rings(tp); + err = tg3_init_rings(tp); + if (err) + return err; /* This value is determined during the probe time DMA * engine test, tg3_test_dma. @@ -7956,7 +8011,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct tg3 *tp = netdev_priv(dev); - int irq_sync = 0; + int irq_sync = 0, err = 0; if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || @@ -7980,13 +8035,14 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_init_hw(tp, 1); - tg3_netif_start(tp); + err = tg3_restart_hw(tp, 1); + if (!err) + tg3_netif_start(tp); } tg3_full_unlock(tp); - return 0; + return err; } static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) @@ -8001,7 +8057,7 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct tg3 *tp = netdev_priv(dev); - int irq_sync = 0; + int irq_sync = 0, err = 0; if (netif_running(dev)) { tg3_netif_stop(tp); @@ -8025,13 +8081,14 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_init_hw(tp, 1); - tg3_netif_start(tp); + err = tg3_restart_hw(tp, 1); + if (!err) + tg3_netif_start(tp); } tg3_full_unlock(tp); - return 0; + return err; } static u32 tg3_get_rx_csum(struct net_device *dev) @@ -8567,7 +8624,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) err = -EIO; tx_len = 1514; - skb = dev_alloc_skb(tx_len); + skb = netdev_alloc_skb(tp->dev, tx_len); if (!skb) return -ENOMEM; @@ -8666,7 +8723,9 @@ static int tg3_test_loopback(struct tg3 *tp) if (!netif_running(tp->dev)) return TG3_LOOPBACK_FAILED; - tg3_reset_hw(tp, 1); + err = tg3_reset_hw(tp, 1); + if (err) + return TG3_LOOPBACK_FAILED; if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; @@ -8740,8 +8799,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp, 1); - tg3_netif_start(tp); + if (!tg3_restart_hw(tp, 1)) + tg3_netif_start(tp); } tg3_full_unlock(tp); @@ -11421,7 +11480,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA; #endif spin_lock_init(&tp->lock); - spin_lock_init(&tp->tx_lock); spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); @@ -11699,7 +11757,8 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) tg3_full_lock(tp, 0); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp, 1); + if (tg3_restart_hw(tp, 1)) + goto out; tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); @@ -11707,6 +11766,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_attach(dev); tg3_netif_start(tp); +out: tg3_full_unlock(tp); } @@ -11733,16 +11793,19 @@ static int tg3_resume(struct pci_dev *pdev) tg3_full_lock(tp, 0); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp, 1); + err = tg3_restart_hw(tp, 1); + if (err) + goto out; tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); tg3_netif_start(tp); +out: tg3_full_unlock(tp); - return 0; + return err; } static struct pci_driver tg3_driver = { diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index ba2c98711c88..3ecf356cfb08 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2079,9 +2079,9 @@ struct tg3 { * lock: Held during reset, PHY access, timer, and when * updating tg3_flags and tg3_flags2. * - * tx_lock: Held during tg3_start_xmit and tg3_tx only - * when calling netif_[start|stop]_queue. - * tg3_start_xmit is protected by netif_tx_lock. + * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds + * netif_tx_lock when it needs to call + * netif_wake_queue. * * Both of these locks are to be held with BH safety. * @@ -2118,8 +2118,6 @@ struct tg3 { u32 tx_cons; u32 tx_pending; - spinlock_t tx_lock; - struct tg3_tx_buffer_desc *tx_ring; struct tx_ring_info *tx_buffers; dma_addr_t tx_desc_mapping; diff --git a/trunk/drivers/net/via-velocity.c b/trunk/drivers/net/via-velocity.c index f5b0078eb4ad..aa9cd92f46b2 100644 --- a/trunk/drivers/net/via-velocity.c +++ b/trunk/drivers/net/via-velocity.c @@ -2742,7 +2742,7 @@ static u32 check_connection_type(struct mac_regs __iomem * regs) if (PHYSR0 & PHYSR0_SPDG) status |= VELOCITY_SPEED_1000; - if (PHYSR0 & PHYSR0_SPD10) + else if (PHYSR0 & PHYSR0_SPD10) status |= VELOCITY_SPEED_10; else status |= VELOCITY_SPEED_100; @@ -2851,8 +2851,17 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd u32 status; status = check_connection_type(vptr->mac_regs); - cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; - if (status & VELOCITY_SPEED_100) + cmd->supported = SUPPORTED_TP | + SUPPORTED_Autoneg | + SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full; + if (status & VELOCITY_SPEED_1000) + cmd->speed = SPEED_1000; + else if (status & VELOCITY_SPEED_100) cmd->speed = SPEED_100; else cmd->speed = SPEED_10; @@ -2896,7 +2905,7 @@ static u32 velocity_get_link(struct net_device *dev) { struct velocity_info *vptr = netdev_priv(dev); struct mac_regs __iomem * regs = vptr->mac_regs; - return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 0 : 1; + return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 1 : 0; } static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index fa9d2c4edc93..2e8ac995d56f 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -447,6 +447,7 @@ config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) select CRYPTO + select CRYPTO_AES ---help--- This is the standard Linux driver to support Cisco/Aironet PCMCIA 802.11 wireless cards. This driver is the same as the Aironet diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3889f79e7128..df317c1e12a8 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3701,7 +3701,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, } if (sec->flags & SEC_AUTH_MODE) { secinfo->auth_mode = sec->auth_mode; - dprintk(", .auth_mode = %d\n", sec->auth_mode); + dprintk(", .auth_mode = %d", sec->auth_mode); } dprintk("\n"); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index d6ed5781b93a..317ace7f9aae 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -2875,7 +2875,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - if (erq->pointer) { + if (erq->length > 0) { if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) index = priv->tx_key; @@ -2918,7 +2918,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (erq->flags & IW_ENCODE_RESTRICTED) restricted = 1; - if (erq->pointer) { + if (erq->pointer && erq->length > 0) { priv->keys[index].len = cpu_to_le16(xlen); memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); diff --git a/trunk/drivers/net/wireless/zd1201.c b/trunk/drivers/net/wireless/zd1201.c index 662ecc8a33ff..c52e9bcf8d02 100644 --- a/trunk/drivers/net/wireless/zd1201.c +++ b/trunk/drivers/net/wireless/zd1201.c @@ -1820,6 +1820,8 @@ static int zd1201_probe(struct usb_interface *interface, zd->dev->name); usb_set_intfdata(interface, zd); + zd1201_enable(zd); /* zd1201 likes to startup enabled, */ + zd1201_disable(zd); /* interfering with all the wifis in range */ return 0; err_net: diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index efc9c4bd826f..da9d06bdb818 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -797,7 +797,7 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_ZD1211_RETRY_MAX, 0x2 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, AP_RX_FILTER }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, @@ -844,7 +844,7 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, { CR_ZD1211B_TXOP, 0x01800824 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, AP_RX_FILTER }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index 805121093ab5..069d2b467339 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -461,10 +461,15 @@ #define CR_RX_FILTER CTL_REG(0x068c) #define RX_FILTER_ASSOC_RESPONSE 0x0002 +#define RX_FILTER_REASSOC_RESPONSE 0x0008 #define RX_FILTER_PROBE_RESPONSE 0x0020 #define RX_FILTER_BEACON 0x0100 +#define RX_FILTER_DISASSOC 0x0400 #define RX_FILTER_AUTH 0x0800 -/* Sniff modus sets filter to 0xfffff */ +#define AP_RX_FILTER 0x0400feff +#define STA_RX_FILTER 0x0000ffff + +/* Monitor mode sets filter to 0xfffff */ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) @@ -546,9 +551,6 @@ #define CR_ZD1211B_TXOP CTL_REG(0x0b20) #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) -#define AP_RX_FILTER 0x0400feff -#define STA_RX_FILTER 0x0000ffff - #define CWIN_SIZE 0x007f043f diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index 3bdc54d128d0..d6f3e02a0b54 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -108,7 +108,9 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) if (r) goto disable_int; - r = zd_set_encryption_type(chip, NO_WEP); + /* We must inform the device that we are doing encryption/decryption in + * software at the moment. */ + r = zd_set_encryption_type(chip, ENC_SNIFFER); if (r) goto disable_int; @@ -136,10 +138,8 @@ static int reset_mode(struct zd_mac *mac) { struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); struct zd_ioreq32 ioreqs[3] = { - { CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE| - RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_SNIFFER_ON, 0U }, - { CR_ENCRYPTION_TYPE, NO_WEP }, }; if (ieee->iw_mode == IW_MODE_MONITOR) { @@ -713,10 +713,10 @@ static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) struct zd_rt_hdr { struct ieee80211_radiotap_header rt_hdr; u8 rt_flags; + u8 rt_rate; u16 rt_channel; u16 rt_chbitmask; - u16 rt_rate; -}; +} __attribute__((packed)); static void fill_rt_header(void *buffer, struct zd_mac *mac, const struct ieee80211_rx_stats *stats, @@ -735,14 +735,14 @@ static void fill_rt_header(void *buffer, struct zd_mac *mac, if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; + hdr->rt_rate = stats->rate / 5; + /* FIXME: 802.11a */ hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( _zd_chip_get_channel(&mac->chip))); hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); - - hdr->rt_rate = stats->rate / 5; } /* Returns 1 if the data packet is for us and 0 otherwise. */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 72f90525bf68..6320984126c7 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -323,7 +323,6 @@ static void disable_read_regs_int(struct zd_usb *usb) { struct zd_usb_interrupt *intr = &usb->intr; - ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); intr->read_regs_enabled = 0; spin_unlock(&intr->lock); @@ -545,11 +544,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, * be padded. Unaligned access might also happen if the length_info * structure is not present. */ - if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) { + if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG)) + { unsigned int l, k, n; for (i = 0, l = 0;; i++) { - k = le16_to_cpu(get_unaligned( - &length_info->length[i])); + k = le16_to_cpu(get_unaligned(&length_info->length[i])); n = l+k; if (n > length) return; diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index 3fae77ffb2fa..8a60f391ffcf 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -76,7 +76,7 @@ config HOTPLUG_PCI_IBM config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on ACPI_DOCK && HOTPLUG_PCI + depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI) help Say Y here if you have a system that supports PCI Hotplug using ACPI. @@ -153,13 +153,6 @@ config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE When in doubt, say N. -config HOTPLUG_PCI_SHPC_PHPRM_LEGACY - bool "For AMD SHPC only: Use $HRT for resource/configuration" - depends on HOTPLUG_PCI_SHPC && !ACPI - help - Say Y here for AMD SHPC. You have to select this option if you are - using this driver on platform with AMD SHPC. - config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE diff --git a/trunk/drivers/pci/hotplug/acpiphp_core.c b/trunk/drivers/pci/hotplug/acpiphp_core.c index 34de5697983d..e2fef60c2d06 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_core.c +++ b/trunk/drivers/pci/hotplug/acpiphp_core.c @@ -27,8 +27,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to , - * + * Send feedback to * */ diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index ef95d12fb32c..ae67a8f55ba1 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -26,7 +26,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ diff --git a/trunk/drivers/pci/hotplug/pciehp.h b/trunk/drivers/pci/hotplug/pciehp.h index ce89f5815861..eaea9d36a1bb 100644 --- a/trunk/drivers/pci/hotplug/pciehp.h +++ b/trunk/drivers/pci/hotplug/pciehp.h @@ -279,6 +279,11 @@ struct hpc_ops { #ifdef CONFIG_ACPI +#include +#include +#include +#include + #define pciehp_get_hp_hw_control_from_firmware(dev) \ pciehp_acpi_get_hp_hw_control_from_firmware(dev) static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index 0d8fb6e607a1..6ab3b6cd2b54 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -38,10 +38,6 @@ #include "../pci.h" #include "pciehp.h" -#include -#include -#include -#include #ifdef DEBUG #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ diff --git a/trunk/drivers/pci/pcie/portdrv_pci.c b/trunk/drivers/pci/pcie/portdrv_pci.c index 50bfc1b2f3bf..478d0d28f7ad 100644 --- a/trunk/drivers/pci/pcie/portdrv_pci.c +++ b/trunk/drivers/pci/pcie/portdrv_pci.c @@ -30,23 +30,6 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; -static int pcie_portdrv_save_config(struct pci_dev *dev) -{ - return pci_save_state(dev); -} - -static int pcie_portdrv_restore_config(struct pci_dev *dev) -{ - int retval; - - pci_restore_state(dev); - retval = pci_enable_device(dev); - if (retval) - return retval; - pci_set_master(dev); - return 0; -} - /* * pcie_portdrv_probe - Probe PCI-Express port devices * @dev: PCI-Express port device being probed @@ -73,8 +56,10 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", __FUNCTION__, dev->device, dev->vendor); } - if (pcie_port_device_register(dev)) + if (pcie_port_device_register(dev)) { + pci_disable_device(dev); return -ENOMEM; + } return 0; } @@ -86,6 +71,23 @@ static void pcie_portdrv_remove (struct pci_dev *dev) } #ifdef CONFIG_PM +static int pcie_portdrv_save_config(struct pci_dev *dev) +{ + return pci_save_state(dev); +} + +static int pcie_portdrv_restore_config(struct pci_dev *dev) +{ + int retval; + + pci_restore_state(dev); + retval = pci_enable_device(dev); + if (retval) + return retval; + pci_set_master(dev); + return 0; +} + static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 5ca1e94887be..04618d4d7d74 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -990,6 +990,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x8070: /* P4G8X Deluxe */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) + switch (dev->subsystem_device) { + case 0x80c9: /* PU-DLS */ + asus_hides_smbus = 1; + } if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch (dev->subsystem_device) { case 0x1751: /* M2N notebook */ @@ -1058,6 +1063,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge ); @@ -1081,6 +1087,7 @@ static void __init asus_hides_smbus_lpc(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); diff --git a/trunk/drivers/pci/search.c b/trunk/drivers/pci/search.c index 622b3f8ba820..d529462d1b53 100644 --- a/trunk/drivers/pci/search.c +++ b/trunk/drivers/pci/search.c @@ -41,7 +41,7 @@ pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) * in the global list of PCI buses. If the bus is found, a pointer to its * data structure is returned. If no bus is found, %NULL is returned. */ -struct pci_bus * __devinit pci_find_bus(int domain, int busnr) +struct pci_bus * pci_find_bus(int domain, int busnr) { struct pci_bus *bus = NULL; struct pci_bus *tmp_bus; @@ -61,7 +61,7 @@ struct pci_bus * __devinit pci_find_bus(int domain, int busnr) * @from: Previous PCI bus found, or %NULL for new search. * * Iterates through the list of known PCI busses. A new search is - * initiated by passing %NULL to the @from argument. Otherwise if + * initiated by passing %NULL as the @from argument. Otherwise if * @from is not %NULL, searches continue from next device on the * global list. */ @@ -148,13 +148,14 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its - * device structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device on the global list. + * found with a matching @vendor, @device, @ss_vendor and @ss_device, a + * pointer to its device structure is returned. Otherwise, %NULL is returned. + * A new search is initiated by passing %NULL as the @from argument. + * Otherwise if @from is not %NULL, searches continue from next device + * on the global list. * - * NOTE: Do not use this function anymore, use pci_get_subsys() instead, as - * the pci device returned by this function can disappear at any moment in + * NOTE: Do not use this function any more; use pci_get_subsys() instead, as + * the PCI device returned by this function can disappear at any moment in * time. */ static struct pci_dev * pci_find_subsys(unsigned int vendor, @@ -191,14 +192,15 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor and @device, a pointer to its device structure is + * Iterates through the list of known PCI devices. If a PCI device is found + * with a matching @vendor and @device, a pointer to its device structure is * returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device on the global list. + * A new search is initiated by passing %NULL as the @from argument. + * Otherwise if @from is not %NULL, searches continue from next device + * on the global list. * - * NOTE: Do not use this function anymore, use pci_get_device() instead, as - * the pci device returned by this function can disappear at any moment in + * NOTE: Do not use this function any more; use pci_get_device() instead, as + * the PCI device returned by this function can disappear at any moment in * time. */ struct pci_dev * @@ -215,11 +217,11 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev * * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its + * Iterates through the list of known PCI devices. If a PCI device is found + * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its * device structure is returned, and the reference count to the device is * incremented. Otherwise, %NULL is returned. A new search is initiated by - * passing %NULL to the @from argument. Otherwise if @from is not %NULL, + * passing %NULL as the @from argument. Otherwise if @from is not %NULL, * searches continue from next device on the global list. * The reference count for @from is always decremented if it is not %NULL. */ @@ -262,7 +264,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, * found with a matching @vendor and @device, the reference count to the * device is incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. A new search is initiated by passing %NULL - * to the @from argument. Otherwise if @from is not %NULL, searches continue + * as the @from argument. Otherwise if @from is not %NULL, searches continue * from next device on the global list. The reference count for @from is * always decremented if it is not %NULL. */ @@ -279,11 +281,13 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices in the reverse order of pci_find_device(). + * Iterates through the list of known PCI devices in the reverse order of + * pci_find_device(). * If a PCI device is found with a matching @vendor and @device, a pointer to * its device structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. - * Otherwise if @from is not %NULL, searches continue from previous device on the global list. + * A new search is initiated by passing %NULL as the @from argument. + * Otherwise if @from is not %NULL, searches continue from previous device + * on the global list. */ struct pci_dev * pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from) @@ -317,7 +321,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p * found with a matching @class, the reference count to the device is * incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. + * A new search is initiated by passing %NULL as the @from argument. * Otherwise if @from is not %NULL, searches continue from next device * on the global list. The reference count for @from is always decremented * if it is not %NULL. diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c index 738b1ef595a3..9ad18e62658d 100644 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ b/trunk/drivers/pcmcia/pcmcia_ioctl.c @@ -601,12 +601,8 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = CS_BAD_ARGS; else { struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function); - if (p_dev == NULL) - ret = CS_BAD_ARGS; - else { - ret = pccard_get_configuration_info(s, p_dev, &buf->config); - pcmcia_put_dev(p_dev); - } + ret = pccard_get_configuration_info(s, p_dev, &buf->config); + pcmcia_put_dev(p_dev); } break; case DS_GET_FIRST_TUPLE: @@ -636,12 +632,8 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = CS_BAD_ARGS; else { struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function); - if (p_dev == NULL) - ret = CS_BAD_ARGS; - else { - ret = pccard_get_status(s, p_dev, &buf->status); - pcmcia_put_dev(p_dev); - } + ret = pccard_get_status(s, p_dev, &buf->status); + pcmcia_put_dev(p_dev); } break; case DS_VALIDATE_CIS: diff --git a/trunk/drivers/pcmcia/pcmcia_resource.c b/trunk/drivers/pcmcia/pcmcia_resource.c index 7bf25b88ea31..c8323399e9e4 100644 --- a/trunk/drivers/pcmcia/pcmcia_resource.c +++ b/trunk/drivers/pcmcia/pcmcia_resource.c @@ -245,10 +245,17 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, return CS_SUCCESS; } - /* !!! This is a hack !!! */ - memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); - config->Attributes |= CONF_VALID_CLIENT; - config->CardValues = c->CardValues; + config->Attributes = c->Attributes | CONF_VALID_CLIENT; + config->Vcc = s->socket.Vcc; + config->Vpp1 = config->Vpp2 = s->socket.Vpp; + config->IntType = c->IntType; + config->ConfigBase = c->ConfigBase; + config->Status = c->Status; + config->Pin = c->Pin; + config->Copy = c->Copy; + config->Option = c->Option; + config->ExtStatus = c->ExtStatus; + config->Present = config->CardValues = c->CardValues; config->IRQAttributes = c->irq.Attributes; config->AssignedIRQ = s->irq.AssignedIRQ; config->BasePort1 = c->io.BasePort1; diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c index 3163e3d73da1..9d8b415eca79 100644 --- a/trunk/drivers/pnp/interface.c +++ b/trunk/drivers/pnp/interface.c @@ -265,8 +265,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - pnp_port_start(dev, i), - pnp_port_end(dev, i)); + (unsigned long long)pnp_port_start(dev, i), + (unsigned long long)pnp_port_end(dev, i)); } } for (i = 0; i < PNP_MAX_MEM; i++) { @@ -276,8 +276,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - pnp_mem_start(dev, i), - pnp_mem_end(dev, i)); + (unsigned long long)pnp_mem_start(dev, i), + (unsigned long long)pnp_mem_end(dev, i)); } } for (i = 0; i < PNP_MAX_IRQ; i++) { @@ -287,7 +287,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - pnp_irq(dev, i)); + (unsigned long long)pnp_irq(dev, i)); } } for (i = 0; i < PNP_MAX_DMA; i++) { @@ -297,7 +297,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - pnp_dma(dev, i)); + (unsigned long long)pnp_dma(dev, i)); } } ret = (buffer->curr - buf); diff --git a/trunk/drivers/pnp/pnpacpi/rsparser.c b/trunk/drivers/pnp/pnpacpi/rsparser.c index 212268881857..dc79b0a0059f 100644 --- a/trunk/drivers/pnp/pnpacpi/rsparser.c +++ b/trunk/drivers/pnp/pnpacpi/rsparser.c @@ -173,6 +173,9 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, return; } + if (p->producer_consumer == ACPI_PRODUCER) + return; + if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(res_table, p->minimum, p->address_length); @@ -252,9 +255,14 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) + return AE_OK; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) + return AE_OK; + for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, res->data.extended_irq.interrupts[i], diff --git a/trunk/drivers/pnp/pnpbios/core.c b/trunk/drivers/pnp/pnpbios/core.c index b154b3f52cbe..551f58e29810 100644 --- a/trunk/drivers/pnp/pnpbios/core.c +++ b/trunk/drivers/pnp/pnpbios/core.c @@ -346,7 +346,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) dev->flags = node->flags; if (!(dev->flags & PNPBIOS_NO_CONFIG)) dev->capabilities |= PNP_CONFIGURABLE; - if (!(dev->flags & PNPBIOS_NO_DISABLE)) + if (!(dev->flags & PNPBIOS_NO_DISABLE) && pnpbios_is_dynamic(dev)) dev->capabilities |= PNP_DISABLE; dev->capabilities |= PNP_READ; if (pnpbios_is_dynamic(dev)) diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index 4bf03fb67f8d..d8e9b95f0a1a 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -1730,8 +1730,8 @@ dasd_flush_request_queue(struct dasd_device * device) req = elv_next_request(device->request_queue); if (req == NULL) break; - dasd_end_request(req, 0); blkdev_dequeue_request(req); + dasd_end_request(req, 0); } spin_unlock_irq(&device->request_queue_lock); } diff --git a/trunk/drivers/s390/block/dasd_devmap.c b/trunk/drivers/s390/block/dasd_devmap.c index 7f6fdac74706..9d0c6e1a0e66 100644 --- a/trunk/drivers/s390/block/dasd_devmap.c +++ b/trunk/drivers/s390/block/dasd_devmap.c @@ -48,18 +48,20 @@ struct dasd_devmap { }; /* - * dasd_servermap is used to store the server_id of all storage servers - * accessed by DASD device driver. + * dasd_server_ssid_map contains a globally unique storage server subsystem ID. + * dasd_server_ssid_list contains the list of all subsystem IDs accessed by + * the DASD device driver. */ -struct dasd_servermap { +struct dasd_server_ssid_map { struct list_head list; struct server_id { char vendor[4]; char serial[15]; } sid; + __u16 ssid; }; -static struct list_head dasd_serverlist; +static struct list_head dasd_server_ssid_list; /* * Parameter parsing functions for dasd= parameter. The syntax is: @@ -89,7 +91,7 @@ static char *dasd[256]; module_param_array(dasd, charp, NULL, 0); /* - * Single spinlock to protect devmap structures and lists. + * Single spinlock to protect devmap and servermap structures and lists. */ static DEFINE_SPINLOCK(dasd_devmap_lock); @@ -264,8 +266,9 @@ dasd_parse_keyword( char *parsestring ) { if (dasd_page_cache) return residual_str; dasd_page_cache = - kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0, - SLAB_CACHE_DMA, NULL, NULL ); + kmem_cache_create("dasd_page_cache", PAGE_SIZE, + PAGE_SIZE, SLAB_CACHE_DMA, + NULL, NULL ); if (!dasd_page_cache) MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " "fixed buffer mode disabled."); @@ -858,39 +861,6 @@ static struct attribute_group dasd_attr_group = { .attrs = dasd_attrs, }; -/* - * Check if the related storage server is already contained in the - * dasd_serverlist. If server is not contained, create new entry. - * Return 0 if server was already in serverlist, - * 1 if the server was added successfully - * <0 in case of error. - */ -static int -dasd_add_server(struct dasd_uid *uid) -{ - struct dasd_servermap *new, *tmp; - - /* check if server is already contained */ - list_for_each_entry(tmp, &dasd_serverlist, list) - // normale cmp? - if (strncmp(tmp->sid.vendor, uid->vendor, - sizeof(tmp->sid.vendor)) == 0 - && strncmp(tmp->sid.serial, uid->serial, - sizeof(tmp->sid.serial)) == 0) - return 0; - - new = (struct dasd_servermap *) - kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); - if (!new) - return -ENOMEM; - - strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); - strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); - list_add(&new->list, &dasd_serverlist); - return 1; -} - - /* * Return copy of the device unique identifier. */ @@ -910,6 +880,9 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) /* * Register the given device unique identifier into devmap struct. + * In addition check if the related storage server subsystem ID is already + * contained in the dasd_server_ssid_list. If subsystem ID is not contained, + * create new entry. * Return 0 if server was already in serverlist, * 1 if the server was added successful * <0 in case of error. @@ -918,16 +891,39 @@ int dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) { struct dasd_devmap *devmap; - int rc; + struct dasd_server_ssid_map *srv, *tmp; devmap = dasd_find_busid(cdev->dev.bus_id); if (IS_ERR(devmap)) return PTR_ERR(devmap); + + /* generate entry for server_ssid_map */ + srv = (struct dasd_server_ssid_map *) + kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL); + if (!srv) + return -ENOMEM; + strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); + strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); + srv->ssid = uid->ssid; + + /* server is already contained ? */ spin_lock(&dasd_devmap_lock); devmap->uid = *uid; - rc = dasd_add_server(uid); + list_for_each_entry(tmp, &dasd_server_ssid_list, list) { + if (!memcmp(&srv->sid, &tmp->sid, + sizeof(struct dasd_server_ssid_map))) { + kfree(srv); + srv = NULL; + break; + } + } + + /* add servermap to serverlist */ + if (srv) + list_add(&srv->list, &dasd_server_ssid_list); spin_unlock(&dasd_devmap_lock); - return rc; + + return (srv ? 1 : 0); } EXPORT_SYMBOL_GPL(dasd_set_uid); @@ -995,7 +991,7 @@ dasd_devmap_init(void) INIT_LIST_HEAD(&dasd_hashlists[i]); /* Initialize servermap structure. */ - INIT_LIST_HEAD(&dasd_serverlist); + INIT_LIST_HEAD(&dasd_server_ssid_list); return 0; } diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 39c2281371b5..957ed5db98e4 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -468,11 +468,11 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) return -ENODEV; memset(uid, 0, sizeof(struct dasd_uid)); - strncpy(uid->vendor, confdata->ned1.HDA_manufacturer, - sizeof(uid->vendor) - 1); + memcpy(uid->vendor, confdata->ned1.HDA_manufacturer, + sizeof(uid->vendor) - 1); EBCASC(uid->vendor, sizeof(uid->vendor) - 1); - strncpy(uid->serial, confdata->ned1.HDA_location, - sizeof(uid->serial) - 1); + memcpy(uid->serial, confdata->ned1.HDA_location, + sizeof(uid->serial) - 1); EBCASC(uid->serial, sizeof(uid->serial) - 1); uid->ssid = confdata->neq.subsystemID; if (confdata->ned2.sneq.flags == 0x40) { diff --git a/trunk/drivers/s390/block/xpram.c b/trunk/drivers/s390/block/xpram.c index 1140302ff11d..ca7d51f7eccc 100644 --- a/trunk/drivers/s390/block/xpram.c +++ b/trunk/drivers/s390/block/xpram.c @@ -48,15 +48,6 @@ #define PRINT_ERR(x...) printk(KERN_ERR XPRAM_NAME " error:" x) -static struct sysdev_class xpram_sysclass = { - set_kset_name("xpram"), -}; - -static struct sys_device xpram_sys_device = { - .id = 0, - .cls = &xpram_sysclass, -}; - typedef struct { unsigned int size; /* size of xpram segment in pages */ unsigned int offset; /* start page of xpram segment */ @@ -451,8 +442,6 @@ static void __exit xpram_exit(void) } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); blk_cleanup_queue(xpram_queue); - sysdev_unregister(&xpram_sys_device); - sysdev_class_unregister(&xpram_sysclass); } static int __init xpram_init(void) @@ -470,19 +459,7 @@ static int __init xpram_init(void) rc = xpram_setup_sizes(xpram_pages); if (rc) return rc; - rc = sysdev_class_register(&xpram_sysclass); - if (rc) - return rc; - - rc = sysdev_register(&xpram_sys_device); - if (rc) { - sysdev_class_unregister(&xpram_sysclass); - return rc; - } - rc = xpram_setup_blkdev(); - if (rc) - sysdev_unregister(&xpram_sys_device); - return rc; + return xpram_setup_blkdev(); } module_init(xpram_init); diff --git a/trunk/drivers/s390/char/tape_class.c b/trunk/drivers/s390/char/tape_class.c index 643b6d078563..56b87618b100 100644 --- a/trunk/drivers/s390/char/tape_class.c +++ b/trunk/drivers/s390/char/tape_class.c @@ -76,7 +76,7 @@ struct tape_class_device *register_tape_dev( device, "%s", tcd->device_name ); - rc = PTR_ERR(tcd->class_device); + rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0; if (rc) goto fail_with_cdev; rc = sysfs_create_link( diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index f26a2ee3aad8..3cba6c9fab11 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -152,7 +152,6 @@ ccwgroup_create(struct device *root, struct ccwgroup_device *gdev; int i; int rc; - int del_drvdata; if (argc > 256) /* disallow dumb users */ return -EINVAL; @@ -163,7 +162,6 @@ ccwgroup_create(struct device *root, atomic_set(&gdev->onoff, 0); - del_drvdata = 0; for (i = 0; i < argc; i++) { gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); @@ -180,10 +178,8 @@ ccwgroup_create(struct device *root, rc = -EINVAL; goto free_dev; } - } - for (i = 0; i < argc; i++) gdev->cdev[i]->dev.driver_data = gdev; - del_drvdata = 1; + } gdev->creator_id = creator_id; gdev->count = argc; @@ -226,9 +222,9 @@ ccwgroup_create(struct device *root, free_dev: for (i = 0; i < argc; i++) if (gdev->cdev[i]) { - put_device(&gdev->cdev[i]->dev); - if (del_drvdata) + if (gdev->cdev[i]->dev.driver_data == gdev) gdev->cdev[i]->dev.driver_data = NULL; + put_device(&gdev->cdev[i]->dev); } kfree(gdev); return rc; diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index ac6e0c7e43d9..6d91c2eb205b 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -152,7 +152,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) if (cdev->private->iretry) { cdev->private->iretry--; ret = cio_halt(sch); - return (ret == 0) ? -EBUSY : ret; + if (ret != -EBUSY) + return (ret == 0) ? -EBUSY : ret; } /* halt io unsuccessful. */ cdev->private->iretry = 255; /* 255 clear retries. */ @@ -771,6 +772,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) stsch(sch->schid, &sch->schib); if (sch->schib.scsw.actl != 0 || + (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) || (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) { /* * No final status yet or final status not yet delivered diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index a60124264bee..9e3de0bd59b5 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -263,6 +263,9 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) /* Abuse intparm for error reporting. */ if (IS_ERR(irb)) cdev->private->intparm = -EIO; + else if (irb->scsw.cc == 1) + /* Retry for deferred condition code. */ + cdev->private->intparm = -EAGAIN; else if ((irb->scsw.dstat != (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) || (irb->scsw.cstat != 0)) { diff --git a/trunk/drivers/scsi/NCR53C9x.c b/trunk/drivers/scsi/NCR53C9x.c index 085db4826e0e..bdc6bb262bce 100644 --- a/trunk/drivers/scsi/NCR53C9x.c +++ b/trunk/drivers/scsi/NCR53C9x.c @@ -2152,29 +2152,23 @@ static int esp_do_data_finale(struct NCR_ESP *esp, */ static int esp_should_clear_sync(Scsi_Cmnd *sp) { - unchar cmd1 = sp->cmnd[0]; - unchar cmd2 = sp->data_cmnd[0]; + unchar cmd = sp->cmnd[0]; /* These cases are for spinning up a disk and * waiting for that spinup to complete. */ - if(cmd1 == START_STOP || - cmd2 == START_STOP) + if(cmd == START_STOP) return 0; - if(cmd1 == TEST_UNIT_READY || - cmd2 == TEST_UNIT_READY) + if(cmd == TEST_UNIT_READY) return 0; /* One more special case for SCSI tape drives, * this is what is used to probe the device for * completion of a rewind or tape load operation. */ - if(sp->device->type == TYPE_TAPE) { - if(cmd1 == MODE_SENSE || - cmd2 == MODE_SENSE) - return 0; - } + if(sp->device->type == TYPE_TAPE && cmd == MODE_SENSE) + return 0; return 1; } diff --git a/trunk/drivers/scsi/ahci.c b/trunk/drivers/scsi/ahci.c index 77e7202a0eba..904c25fb4ba4 100644 --- a/trunk/drivers/scsi/ahci.c +++ b/trunk/drivers/scsi/ahci.c @@ -940,14 +940,8 @@ static void ahci_host_intr(struct ata_port *ap) return; /* ignore interim PIO setup fis interrupts */ - if (ata_tag_valid(ap->active_tag)) { - struct ata_queued_cmd *qc = - ata_qc_from_tag(ap, ap->active_tag); - - if (qc && qc->tf.protocol == ATA_PROT_PIO && - (status & PORT_IRQ_PIOS_FIS)) - return; - } + if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) + return; if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " diff --git a/trunk/drivers/scsi/aic7xxx/aicasm/Makefile b/trunk/drivers/scsi/aic7xxx/aicasm/Makefile index 8c91fda6482c..b98c5c1056c3 100644 --- a/trunk/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/trunk/drivers/scsi/aic7xxx/aicasm/Makefile @@ -14,6 +14,8 @@ LIBS= -ldb clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG) # Override default kernel CFLAGS. This is a userland app. AICASM_CFLAGS:= -I/usr/include -I. +LEX= flex +YACC= bison YFLAGS= -d NOMAN= noman diff --git a/trunk/drivers/scsi/arm/Kconfig b/trunk/drivers/scsi/arm/Kconfig index 06d7601cdf56..d006a8cb4a74 100644 --- a/trunk/drivers/scsi/arm/Kconfig +++ b/trunk/drivers/scsi/arm/Kconfig @@ -69,6 +69,7 @@ comment "The following drivers are not fully supported" config SCSI_CUMANA_1 tristate "CumanaSCSI I support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI + select SCSI_SPI_ATTRS help This enables support for the Cumana SCSI I card. If you have an Acorn system with one of these, say Y. If unsure, say N. @@ -76,6 +77,7 @@ config SCSI_CUMANA_1 config SCSI_ECOSCSI tristate "EcoScsi support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI + select SCSI_SPI_ATTRS help This enables support for the EcoSCSI card -- a small card that sits in the Econet socket. If you have an Acorn system with one of these, @@ -84,6 +86,7 @@ config SCSI_ECOSCSI config SCSI_OAK1 tristate "Oak SCSI support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI + select SCSI_SPI_ATTRS help This enables support for the Oak SCSI card. If you have an Acorn system with one of these, say Y. If unsure, say N. diff --git a/trunk/drivers/scsi/arm/fas216.c b/trunk/drivers/scsi/arm/fas216.c index 3e1053f111dc..4cf7afc31cc7 100644 --- a/trunk/drivers/scsi/arm/fas216.c +++ b/trunk/drivers/scsi/arm/fas216.c @@ -2427,7 +2427,7 @@ int fas216_eh_abort(Scsi_Cmnd *SCpnt) info->stats.aborts += 1; printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no); - __scsi_print_command(SCpnt->data_cmnd); + __scsi_print_command(SCpnt->cmnd); print_debug_list(); fas216_dumpstate(info); diff --git a/trunk/drivers/scsi/arm/scsi.h b/trunk/drivers/scsi/arm/scsi.h index 6dd544a5eb56..8c2600ffc6af 100644 --- a/trunk/drivers/scsi/arm/scsi.h +++ b/trunk/drivers/scsi/arm/scsi.h @@ -74,7 +74,7 @@ static inline void init_SCp(Scsi_Cmnd *SCpnt) unsigned long len = 0; int buf; - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; + SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; SCpnt->SCp.ptr = (char *) (page_address(SCpnt->SCp.buffer->page) + diff --git a/trunk/drivers/scsi/ata_piix.c b/trunk/drivers/scsi/ata_piix.c index 19745a31072b..5e8afc876980 100644 --- a/trunk/drivers/scsi/ata_piix.c +++ b/trunk/drivers/scsi/ata_piix.c @@ -567,8 +567,8 @@ static int piix_sata_prereset(struct ata_port *ap) present = 1; } - DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", - ap->id, pcs, present_mask); + DPRINTK("ata%u: LEAVE, pcs=0x%x present=0x%x\n", + ap->id, pcs, present); if (!present) { ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); @@ -828,6 +828,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, case IDE: WARN_ON((i & 1) || map[i + 1] != IDE); pinfo[i / 2] = piix_port_info[ich5_pata]; + pinfo[i / 2].private_data = hpriv; i++; printk(" IDE IDE"); break; diff --git a/trunk/drivers/scsi/esp.c b/trunk/drivers/scsi/esp.c index eaf64c7e54e7..98bd22714d0d 100644 --- a/trunk/drivers/scsi/esp.c +++ b/trunk/drivers/scsi/esp.c @@ -2754,18 +2754,15 @@ static int esp_do_data_finale(struct esp *esp) */ static int esp_should_clear_sync(struct scsi_cmnd *sp) { - u8 cmd1 = sp->cmnd[0]; - u8 cmd2 = sp->data_cmnd[0]; + u8 cmd = sp->cmnd[0]; /* These cases are for spinning up a disk and * waiting for that spinup to complete. */ - if (cmd1 == START_STOP || - cmd2 == START_STOP) + if (cmd == START_STOP) return 0; - if (cmd1 == TEST_UNIT_READY || - cmd2 == TEST_UNIT_READY) + if (cmd == TEST_UNIT_READY) return 0; /* One more special case for SCSI tape drives, @@ -2773,8 +2770,7 @@ static int esp_should_clear_sync(struct scsi_cmnd *sp) * completion of a rewind or tape load operation. */ if (sp->device->type == TYPE_TAPE) { - if (cmd1 == MODE_SENSE || - cmd2 == MODE_SENSE) + if (cmd == MODE_SENSE) return 0; } diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 386e5f21e191..16fc2dd8f2f7 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -5185,28 +5185,6 @@ void ata_host_stop (struct ata_host_set *host_set) iounmap(host_set->mmio_base); } - -/** - * ata_host_remove - Unregister SCSI host structure with upper layers - * @ap: Port to unregister - * @do_unregister: 1 if we fully unregister, 0 to just stop the port - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) -{ - struct Scsi_Host *sh = ap->host; - - DPRINTK("ENTER\n"); - - if (do_unregister) - scsi_remove_host(sh); - - ap->ops->port_stop(ap); -} - /** * ata_dev_init - Initialize an ata_device structure * @dev: Device structure to initialize @@ -5532,8 +5510,11 @@ int ata_device_add(const struct ata_probe_ent *ent) err_out: for (i = 0; i < count; i++) { - ata_host_remove(host_set->ports[i], 1); - scsi_host_put(host_set->ports[i]->host); + struct ata_port *ap = host_set->ports[i]; + if (ap) { + ap->ops->port_stop(ap); + scsi_host_put(ap->host); + } } err_free_ret: kfree(host_set); @@ -5558,7 +5539,7 @@ void ata_port_detach(struct ata_port *ap) int i; if (!ap->ops->error_handler) - return; + goto skip_eh; /* tell EH we're leaving & flush EH */ spin_lock_irqsave(ap->lock, flags); @@ -5594,6 +5575,7 @@ void ata_port_detach(struct ata_port *ap) cancel_delayed_work(&ap->hotplug_task); flush_workqueue(ata_aux_wq); + skip_eh: /* remove the associated SCSI host */ scsi_remove_host(ap->host); } @@ -5662,7 +5644,7 @@ int ata_scsi_release(struct Scsi_Host *host) DPRINTK("ENTER\n"); ap->ops->port_disable(ap); - ata_host_remove(ap, 0); + ap->ops->port_stop(ap); DPRINTK("EXIT\n"); return 1; diff --git a/trunk/drivers/scsi/libata-eh.c b/trunk/drivers/scsi/libata-eh.c index 4b6aa30f4d68..29f59345305d 100644 --- a/trunk/drivers/scsi/libata-eh.c +++ b/trunk/drivers/scsi/libata-eh.c @@ -764,12 +764,27 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, unsigned int action) { unsigned long flags; + struct ata_eh_info *ehi = &ap->eh_info; + struct ata_eh_context *ehc = &ap->eh_context; spin_lock_irqsave(ap->lock, flags); - ata_eh_clear_action(dev, &ap->eh_info, action); + /* Reset is represented by combination of actions and EHI + * flags. Suck in all related bits before clearing eh_info to + * avoid losing requested action. + */ + if (action & ATA_EH_RESET_MASK) { + ehc->i.action |= ehi->action & ATA_EH_RESET_MASK; + ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK; + + /* make sure all reset actions are cleared & clear EHI flags */ + action |= ATA_EH_RESET_MASK; + ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK; + } + + ata_eh_clear_action(dev, ehi, action); - if (!(ap->eh_context.i.flags & ATA_EHI_QUIET)) + if (!(ehc->i.flags & ATA_EHI_QUIET)) ap->pflags |= ATA_PFLAG_RECOVERED; spin_unlock_irqrestore(ap->lock, flags); @@ -790,6 +805,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, unsigned int action) { + /* if reset is complete, clear all reset actions & reset modifier */ + if (action & ATA_EH_RESET_MASK) { + action |= ATA_EH_RESET_MASK; + ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK; + } + ata_eh_clear_action(dev, &ap->eh_context.i, action); } @@ -1276,8 +1297,6 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io, static void ata_eh_autopsy(struct ata_port *ap) { struct ata_eh_context *ehc = &ap->eh_context; - unsigned int action = ehc->i.action; - struct ata_device *failed_dev = NULL; unsigned int all_err_mask = 0; int tag, is_io = 0; u32 serror; @@ -1294,7 +1313,7 @@ static void ata_eh_autopsy(struct ata_port *ap) ehc->i.serror |= serror; ata_eh_analyze_serror(ap); } else if (rc != -EOPNOTSUPP) - action |= ATA_EH_HARDRESET; + ehc->i.action |= ATA_EH_HARDRESET; /* analyze NCQ failure */ ata_eh_analyze_ncq_error(ap); @@ -1315,7 +1334,7 @@ static void ata_eh_autopsy(struct ata_port *ap) qc->err_mask |= ehc->i.err_mask; /* analyze TF */ - action |= ata_eh_analyze_tf(qc, &qc->result_tf); + ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf); /* DEV errors are probably spurious in case of ATA_BUS error */ if (qc->err_mask & AC_ERR_ATA_BUS) @@ -1329,11 +1348,11 @@ static void ata_eh_autopsy(struct ata_port *ap) /* SENSE_VALID trumps dev/unknown error and revalidation */ if (qc->flags & ATA_QCFLAG_SENSE_VALID) { qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); - action &= ~ATA_EH_REVALIDATE; + ehc->i.action &= ~ATA_EH_REVALIDATE; } /* accumulate error info */ - failed_dev = qc->dev; + ehc->i.dev = qc->dev; all_err_mask |= qc->err_mask; if (qc->flags & ATA_QCFLAG_IO) is_io = 1; @@ -1342,25 +1361,22 @@ static void ata_eh_autopsy(struct ata_port *ap) /* enforce default EH actions */ if (ap->pflags & ATA_PFLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) - action |= ATA_EH_SOFTRESET; + ehc->i.action |= ATA_EH_SOFTRESET; else if (all_err_mask) - action |= ATA_EH_REVALIDATE; + ehc->i.action |= ATA_EH_REVALIDATE; /* if we have offending qcs and the associated failed device */ - if (failed_dev) { + if (ehc->i.dev) { /* speed down */ - action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); + ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, + all_err_mask); /* perform per-dev EH action only on the offending device */ - ehc->i.dev_action[failed_dev->devno] |= - action & ATA_EH_PERDEV_MASK; - action &= ~ATA_EH_PERDEV_MASK; + ehc->i.dev_action[ehc->i.dev->devno] |= + ehc->i.action & ATA_EH_PERDEV_MASK; + ehc->i.action &= ~ATA_EH_PERDEV_MASK; } - /* record autopsy result */ - ehc->i.dev = failed_dev; - ehc->i.action |= action; - DPRINTK("EXIT\n"); } @@ -1483,6 +1499,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify, ata_reset_fn_t reset; int i, did_followup_srst, rc; + /* about to reset */ + ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); + /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ @@ -1531,8 +1550,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, ata_port_printk(ap, KERN_INFO, "%s resetting port\n", reset == softreset ? "soft" : "hard"); - /* reset */ - ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); + /* mark that this EH session started with reset */ ehc->i.flags |= ATA_EHI_DID_RESET; rc = ata_do_reset(ap, reset, classes); @@ -1595,7 +1613,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, postreset(ap, classes); /* reset successful, schedule revalidation */ - ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); + ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); ehc->i.action |= ATA_EH_REVALIDATE; } @@ -1848,15 +1866,16 @@ static int ata_eh_skip_recovery(struct ata_port *ap) for (i = 0; i < ata_port_max_devices(ap); i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_absent(dev) || ata_dev_ready(dev)) + if (!(dev->flags & ATA_DFLAG_SUSPENDED)) break; } if (i == ata_port_max_devices(ap)) return 1; - /* always thaw frozen port and recover failed devices */ - if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap)) + /* thaw frozen port, resume link and recover failed devices */ + if ((ap->pflags & ATA_PFLAG_FROZEN) || + (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap)) return 0; /* skip if class codes for all vacant slots are ATA_DEV_NONE */ diff --git a/trunk/drivers/scsi/libata-scsi.c b/trunk/drivers/scsi/libata-scsi.c index 7ced41ecde86..e92c31d698ff 100644 --- a/trunk/drivers/scsi/libata-scsi.c +++ b/trunk/drivers/scsi/libata-scsi.c @@ -2353,6 +2353,19 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) ata_gen_ata_desc_sense(qc); } + /* SCSI EH automatically locks door if sdev->locked is + * set. Sometimes door lock request continues to + * fail, for example, when no media is present. This + * creates a loop - SCSI EH issues door lock which + * fails and gets invoked again to acquire sense data + * for the failed command. + * + * If door lock fails, always clear sdev->locked to + * avoid this infinite loop. + */ + if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL) + qc->dev->sdev->locked = 0; + qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; qc->scsidone(cmd); ata_qc_free(qc); diff --git a/trunk/drivers/scsi/sata_promise.c b/trunk/drivers/scsi/sata_promise.c index 64631bd38952..4776f4e55839 100644 --- a/trunk/drivers/scsi/sata_promise.c +++ b/trunk/drivers/scsi/sata_promise.c @@ -269,8 +269,15 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20619 }, +/* TODO: remove all associated board_20771 code, as it completely + * duplicates board_2037x code, unless reason for separation can be + * divined. + */ +#if 0 { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20771 }, +#endif + { } /* terminate list */ }; diff --git a/trunk/drivers/scsi/sata_sil24.c b/trunk/drivers/scsi/sata_sil24.c index 2e0f4a4076af..3f368c7d3ef9 100644 --- a/trunk/drivers/scsi/sata_sil24.c +++ b/trunk/drivers/scsi/sata_sil24.c @@ -1106,7 +1106,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; - probe_ent->mmio_base = port_base; probe_ent->private_data = hpriv; hpriv->host_base = host_base; diff --git a/trunk/drivers/scsi/scsi_ioctl.c b/trunk/drivers/scsi/scsi_ioctl.c index a89c4115cfba..32293f451669 100644 --- a/trunk/drivers/scsi/scsi_ioctl.c +++ b/trunk/drivers/scsi/scsi_ioctl.c @@ -110,11 +110,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ - if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { - printk(KERN_INFO "Device not ready. Make sure" - " there is a disc in the drive.\n"); + if (sdev->removable) break; - } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index 2ee742d40c43..005043197527 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_S3C2410 default y if PXA27x default y if ARCH_EP93XX - default y if ARCH_AT91RM9200 + default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index f7bdd94b3aa8..218621b9958e 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -517,19 +517,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig static struct usb_device *usbdev_lookup_minor(int minor) { - struct device *device; - struct usb_device *udev = NULL; + struct class_device *class_dev; + struct usb_device *dev = NULL; down(&usb_device_class->sem); - list_for_each_entry(device, &usb_device_class->devices, node) { - if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - udev = device->platform_data; + list_for_each_entry(class_dev, &usb_device_class->children, node) { + if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + dev = class_dev->class_data; break; } } up(&usb_device_class->sem); - return udev; + return dev; }; /* @@ -1580,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->usbfs_dev = device_create(usb_device_class, &dev->dev, - MKDEV(USB_DEVICE_MAJOR, minor), + dev->class_dev = class_device_create(usb_device_class, NULL, + MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, "usbdev%d.%d", dev->bus->busnum, dev->devnum); - dev->usbfs_dev->platform_data = dev; + dev->class_dev->class_data = dev; } static void usbdev_remove(struct usb_device *dev) { - device_unregister(dev->usbfs_dev); + class_device_unregister(dev->class_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, diff --git a/trunk/drivers/usb/core/file.c b/trunk/drivers/usb/core/file.c index abee0f5b6a66..8de4f8c99d61 100644 --- a/trunk/drivers/usb/core/file.c +++ b/trunk/drivers/usb/core/file.c @@ -194,13 +194,14 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), "%s", temp); - if (IS_ERR(intf->usb_dev)) { + intf->class_dev = class_device_create(usb_class->class, NULL, + MKDEV(USB_MAJOR, minor), + &intf->dev, "%s", temp); + if (IS_ERR(intf->class_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->usb_dev); + retval = PTR_ERR(intf->class_dev); } exit: return retval; @@ -241,8 +242,8 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); - intf->usb_dev = NULL; + class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->class_dev = NULL; intf->minor = -1; destroy_usb_class(); } diff --git a/trunk/drivers/usb/gadget/Kconfig b/trunk/drivers/usb/gadget/Kconfig index 363b2ad74ae6..1a32d96774b4 100644 --- a/trunk/drivers/usb/gadget/Kconfig +++ b/trunk/drivers/usb/gadget/Kconfig @@ -207,7 +207,7 @@ config USB_AT91 config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" - depends on USB && EXPERIMENTAL + depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL select USB_GADGET_DUALSPEED help This host controller driver emulates USB, looping all data transfer diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index 1c459ff037ce..cfebca05ead5 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -57,19 +57,23 @@ /* * This controller is simple and PIO-only. It's used in many AT91-series - * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU), - * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions. + * full speed USB controllers, including the at91rm9200 (arm920T, with MMU), + * at91sam926x (arm926ejs, with MMU), and several no-mmu versions. * * This driver expects the board has been wired with two GPIOs suppporting * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the - * testing hasn't covered such cases.) The pullup is most important; it + * testing hasn't covered such cases.) + * + * The pullup is most important (so it's integrated on sam926x parts). It * provides software control over whether the host enumerates the device. + * * The VBUS sensing helps during enumeration, and allows both USB clocks * (and the transceiver) to stay gated off until they're necessary, saving - * power. During USB suspend, the 48 MHz clock is gated off. + * power. During USB suspend, the 48 MHz clock is gated off in hardware; + * it may also be gated off by software during some Linux sleep states. */ -#define DRIVER_VERSION "8 March 2005" +#define DRIVER_VERSION "3 May 2006" static const char driver_name [] = "at91_udc"; static const char ep0name[] = "ep0"; @@ -316,9 +320,15 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status) * * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE * that shouldn't normally be changed. + * + * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains, + * implying a need to wait for one write to complete (test relevant bits) + * before starting the next write. This shouldn't be an issue given how + * infrequently we write, except maybe for write-then-read idioms. */ #define SET_FX (AT91_UDP_TXPKTRDY) -#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) +#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \ + | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) /* pull OUT packet data from the endpoint's fifo */ static int read_fifo (struct at91_ep *ep, struct at91_request *req) @@ -472,7 +482,8 @@ static void nuke(struct at91_ep *ep, int status) /*-------------------------------------------------------------------------*/ -static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +static int at91_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); struct at91_udc *dev = ep->udc; @@ -582,11 +593,12 @@ static int at91_ep_disable (struct usb_ep * _ep) * interesting for request or buffer allocation. */ -static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) +static struct usb_request * +at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) { struct at91_request *req; - req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); + req = kcalloc(1, sizeof (struct at91_request), gfp_flags); if (!req) return NULL; @@ -862,6 +874,7 @@ static void stop_activity(struct at91_udc *udc) if (udc->gadget.speed == USB_SPEED_UNKNOWN) driver = NULL; udc->gadget.speed = USB_SPEED_UNKNOWN; + udc->suspended = 0; for (i = 0; i < NUM_ENDPOINTS; i++) { struct at91_ep *ep = &udc->ep[i]; @@ -889,8 +902,8 @@ static void clk_off(struct at91_udc *udc) return; udc->clocked = 0; udc->gadget.speed = USB_SPEED_UNKNOWN; - clk_disable(udc->iclk); clk_disable(udc->fclk); + clk_disable(udc->iclk); } /* @@ -911,9 +924,6 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); at91_set_gpio_value(udc->board.pullup_pin, 0); clk_off(udc); - - // REVISIT: with transceiver disabled, will D- float - // so that a host would falsely detect a device? } } @@ -1290,7 +1300,8 @@ static void handle_ep0(struct at91_udc *udc) if (udc->wait_for_addr_ack) { u32 tmp; - at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); + at91_udp_write(AT91_UDP_FADDR, + AT91_UDP_FEN | udc->addr); tmp = at91_udp_read(AT91_UDP_GLB_STAT); tmp &= ~AT91_UDP_FADDEN; if (udc->addr) @@ -1361,9 +1372,10 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) u32 rescans = 5; while (rescans--) { - u32 status = at91_udp_read(AT91_UDP_ISR); + u32 status; - status &= at91_udp_read(AT91_UDP_IMR); + status = at91_udp_read(AT91_UDP_ISR) + & at91_udp_read(AT91_UDP_IMR); if (!status) break; @@ -1379,18 +1391,17 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) stop_activity(udc); /* enable ep0 */ - at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); + at91_udp_write(AT91_UDP_CSR(0), + AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); udc->gadget.speed = USB_SPEED_FULL; udc->suspended = 0; at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); /* * NOTE: this driver keeps clocks off unless the - * USB host is present. That saves power, and also - * eliminates IRQs (reset, resume, suspend) that can - * otherwise flood from the controller. If your - * board doesn't support VBUS detection, suspend and - * resume irq logic may need more attention... + * USB host is present. That saves power, but for + * boards that don't support VBUS detection, both + * clocks need to be active most of the time. */ /* host initiated suspend (3+ms bus idle) */ @@ -1452,13 +1463,19 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) /*-------------------------------------------------------------------------*/ +static void nop_release(struct device *dev) +{ + /* nothing to free */ +} + static struct at91_udc controller = { .gadget = { - .ops = &at91_udc_ops, - .ep0 = &controller.ep[0].ep, - .name = driver_name, - .dev = { - .bus_id = "gadget" + .ops = &at91_udc_ops, + .ep0 = &controller.ep[0].ep, + .name = driver_name, + .dev = { + .bus_id = "gadget", + .release = nop_release, } }, .ep[0] = { @@ -1468,7 +1485,8 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(0)), .int_mask = 1 << 0, }, .ep[1] = { @@ -1479,7 +1497,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(1)), .int_mask = 1 << 1, }, .ep[2] = { @@ -1490,7 +1509,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(2)), .int_mask = 1 << 2, }, .ep[3] = { @@ -1501,7 +1521,8 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(3)), .int_mask = 1 << 3, }, .ep[4] = { @@ -1512,7 +1533,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(4)), .int_mask = 1 << 4, }, .ep[5] = { @@ -1523,10 +1545,11 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(5)), .int_mask = 1 << 5, }, - /* ep6 and ep7 are also reserved */ + /* ep6 and ep7 are also reserved (custom silicon might use them) */ }; static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) @@ -1593,6 +1616,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) local_irq_disable(); udc->enabled = 0; + at91_udp_write(AT91_UDP_IDR, ~0); pullup(udc, 0); local_irq_enable(); @@ -1624,6 +1648,16 @@ static int __devinit at91udc_probe(struct platform_device *pdev) return -ENODEV; } + if (pdev->num_resources != 2) { + DBG("invalid num_resources"); + return -ENODEV; + } + if ((pdev->resource[0].flags != IORESOURCE_MEM) + || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + DBG("invalid resource type"); + return -ENODEV; + } + if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { DBG("someone's using UDC memory\n"); return -EBUSY; @@ -1649,19 +1683,26 @@ static int __devinit at91udc_probe(struct platform_device *pdev) if (retval < 0) goto fail0; - /* disable everything until there's a gadget driver and vbus */ - pullup(udc, 0); + /* don't do anything until we have both gadget driver and VBUS */ + clk_enable(udc->iclk); + at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + at91_udp_write(AT91_UDP_IDR, 0xffffffff); + clk_disable(udc->iclk); /* request UDC and maybe VBUS irqs */ - if (request_irq(AT91_ID_UDP, at91_udc_irq, IRQF_DISABLED, driver_name, udc)) { - DBG("request irq %d failed\n", AT91_ID_UDP); + udc->udp_irq = platform_get_irq(pdev, 0); + if (request_irq(udc->udp_irq, at91_udc_irq, + IRQF_DISABLED, driver_name, udc)) { + DBG("request irq %d failed\n", udc->udp_irq); retval = -EBUSY; goto fail1; } if (udc->board.vbus_pin > 0) { - if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) { - DBG("request vbus irq %d failed\n", udc->board.vbus_pin); - free_irq(AT91_ID_UDP, udc); + if (request_irq(udc->board.vbus_pin, at91_vbus_irq, + IRQF_DISABLED, driver_name, udc)) { + DBG("request vbus irq %d failed\n", + udc->board.vbus_pin); + free_irq(udc->udp_irq, udc); retval = -EBUSY; goto fail1; } @@ -1670,6 +1711,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) udc->vbus = 1; } dev_set_drvdata(dev, udc); + device_init_wakeup(dev, 1); create_debug_file(udc); INFO("%s version %s\n", driver_name, DRIVER_VERSION); @@ -1678,14 +1720,14 @@ static int __devinit at91udc_probe(struct platform_device *pdev) fail1: device_unregister(&udc->gadget.dev); fail0: - release_mem_region(AT91_VA_BASE_UDP, SZ_16K); + release_mem_region(AT91_BASE_UDP, SZ_16K); DBG("%s probe failed, %d\n", driver_name, retval); return retval; } -static int __devexit at91udc_remove(struct platform_device *dev) +static int __devexit at91udc_remove(struct platform_device *pdev) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); DBG("remove\n"); @@ -1694,10 +1736,11 @@ static int __devexit at91udc_remove(struct platform_device *dev) if (udc->driver != 0) usb_gadget_unregister_driver(udc->driver); + device_init_wakeup(&pdev->dev, 0); remove_debug_file(udc); if (udc->board.vbus_pin > 0) free_irq(udc->board.vbus_pin, udc); - free_irq(AT91_ID_UDP, udc); + free_irq(udc->udp_irq, udc); device_unregister(&udc->gadget.dev); release_mem_region(AT91_BASE_UDP, SZ_16K); @@ -1708,31 +1751,36 @@ static int __devexit at91udc_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg) +static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); + int wake = udc->driver && device_may_wakeup(&pdev->dev); - /* - * The "safe" suspend transitions are opportunistic ... e.g. when - * the USB link is suspended (48MHz clock autogated off), or when - * it's disconnected (programmatically gated off, elsewhere). - * Then we can suspend, and the chip can enter slow clock mode. - * - * The problem case is some component (user mode?) suspending this - * device while it's active, with the 48 MHz clock in use. There - * are two basic approaches: (a) veto suspend levels involving slow - * clock mode, (b) disconnect, so 48 MHz will no longer be in use - * and we can enter slow clock mode. This uses (b) for now, since - * it's simplest until AT91 PM exists and supports the other option. + /* Unless we can act normally to the host (letting it wake us up + * whenever it has work for us) force disconnect. Wakeup requires + * PLLB for USB events (signaling for reset, wakeup, or incoming + * tokens) and VBUS irqs (on systems which support them). */ - if (udc->vbus && !udc->suspended) + if ((!udc->suspended && udc->addr) + || !wake + || at91_suspend_entering_slow_clock()) { pullup(udc, 0); + disable_irq_wake(udc->udp_irq); + } else + enable_irq_wake(udc->udp_irq); + + if (udc->board.vbus_pin > 0) { + if (wake) + enable_irq_wake(udc->board.vbus_pin); + else + disable_irq_wake(udc->board.vbus_pin); + } return 0; } -static int at91udc_resume(struct platform_device *dev) +static int at91udc_resume(struct platform_device *pdev) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); /* maybe reconnect to host; if so, clocks on */ pullup(udc, 1); @@ -1748,7 +1796,7 @@ static struct platform_driver at91_udc = { .remove = __devexit_p(at91udc_remove), .shutdown = at91udc_shutdown, .suspend = at91udc_suspend, - .resume = at91udc_resume, + .resume = at91udc_resume, .driver = { .name = (char *) driver_name, .owner = THIS_MODULE, @@ -1767,6 +1815,6 @@ static void __devexit udc_exit_module(void) } module_exit(udc_exit_module); -MODULE_DESCRIPTION("AT91RM9200 udc driver"); +MODULE_DESCRIPTION("AT91 udc driver"); MODULE_AUTHOR("Thomas Rathbone, David Brownell"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/gadget/at91_udc.h b/trunk/drivers/usb/gadget/at91_udc.h index 5a4799cedd19..882af42e86cc 100644 --- a/trunk/drivers/usb/gadget/at91_udc.h +++ b/trunk/drivers/usb/gadget/at91_udc.h @@ -141,6 +141,7 @@ struct at91_udc { struct clk *iclk, *fclk; struct platform_device *pdev; struct proc_dir_entry *pde; + int udp_irq; }; static inline struct at91_udc *to_udc(struct usb_gadget *g) diff --git a/trunk/drivers/usb/gadget/dummy_hcd.c b/trunk/drivers/usb/gadget/dummy_hcd.c index 4be47195bd38..7d1c22c34957 100644 --- a/trunk/drivers/usb/gadget/dummy_hcd.c +++ b/trunk/drivers/usb/gadget/dummy_hcd.c @@ -609,7 +609,8 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) if (!dum->driver) return -ESHUTDOWN; - spin_lock_irqsave (&dum->lock, flags); + local_irq_save (flags); + spin_lock (&dum->lock); list_for_each_entry (req, &ep->queue, queue) { if (&req->req == _req) { list_del_init (&req->queue); @@ -618,7 +619,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) break; } } - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock (&dum->lock); if (retval == 0) { dev_dbg (udc_dev(dum), @@ -626,6 +627,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) req, _ep->name, _req->length, _req->buf); _req->complete (_ep, _req); } + local_irq_restore (flags); return retval; } diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 85b0b4ad4c16..d63177a8eaea 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -892,7 +892,7 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ehci_pci_driver #endif -#ifdef CONFIG_PPC_83xx +#ifdef CONFIG_MPC834x #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver #endif diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index cdbafb710000..85cc059705a6 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -4,7 +4,7 @@ * Copyright (C) 2004 SAN People (Pty) Ltd. * Copyright (C) 2005 Thibaut VARENE * - * AT91RM9200 Bus Glue + * AT91 Bus Glue * * Based on fragments of 2.4 driver by Rick Bronson. * Based on ohci-omap.c @@ -19,12 +19,13 @@ #include #include -#ifndef CONFIG_ARCH_AT91RM9200 -#error "CONFIG_ARCH_AT91RM9200 must be defined." +#ifndef CONFIG_ARCH_AT91 +#error "CONFIG_ARCH_AT91 must be defined." #endif /* interface and function clocks */ static struct clk *iclk, *fclk; +static int clocked; extern int usb_disabled(void); @@ -35,13 +36,14 @@ static void at91_start_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); + dev_dbg(&pdev->dev, "start\n"); /* * Start the USB clocks. */ clk_enable(iclk); clk_enable(fclk); + clocked = 1; /* * The USB host controller must remain in reset. @@ -54,7 +56,7 @@ static void at91_stop_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); + dev_dbg(&pdev->dev, "stop\n"); /* * Put the USB host controller into reset. @@ -66,6 +68,7 @@ static void at91_stop_hc(struct platform_device *pdev) */ clk_disable(fclk); clk_disable(iclk); + clocked = 0; } @@ -78,14 +81,15 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /** - * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs + * usb_hcd_at91_probe - initialize AT91-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) +static int usb_hcd_at91_probe(const struct hc_driver *driver, + struct platform_device *pdev) { int retval; struct usb_hcd *hcd = NULL; @@ -95,12 +99,13 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device * return -ENODEV; } - if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + if ((pdev->resource[0].flags != IORESOURCE_MEM) + || (pdev->resource[1].flags != IORESOURCE_IRQ)) { pr_debug("hcd probe: invalid resource type\n"); return -ENODEV; } - hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); + hcd = usb_create_hcd(driver, &pdev->dev, "at91"); if (!hcd) return -ENOMEM; hcd->rsrc_start = pdev->resource[0].start; @@ -149,21 +154,23 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device * /* may be called with controller, bus, and devices active */ /** - * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs + * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_at91_probe(), first invoking * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. + * context, "rmmod" or something similar. * */ -static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) +static int usb_hcd_at91_remove(struct usb_hcd *hcd, + struct platform_device *pdev) { usb_remove_hcd(hcd); at91_stop_hc(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + disable_irq_wake(hcd->irq); clk_put(fclk); clk_put(iclk); @@ -178,19 +185,21 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde static int __devinit ohci_at91_start (struct usb_hcd *hcd) { -// struct at91_ohci_data *board = hcd->self.controller->platform_data; + struct at91_usbh_data *board = hcd->self.controller->platform_data; struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct usb_device *root = hcd->self.root_hub; int ret; if ((ret = ohci_init(ohci)) < 0) return ret; + root->maxchild = board->ports; + if ((ret = ohci_run(ohci)) < 0) { err("can't start %s", hcd->self.bus_name); ohci_stop(hcd); return ret; } -// hcd->self.root_hub->maxchild = board->ports; return 0; } @@ -198,7 +207,7 @@ ohci_at91_start (struct usb_hcd *hcd) static const struct hc_driver ohci_at91_hc_driver = { .description = hcd_name, - .product_desc = "AT91RM9200 OHCI", + .product_desc = "AT91 OHCI", .hcd_priv_size = sizeof(struct ohci_hcd), /* @@ -240,33 +249,54 @@ static const struct hc_driver ohci_at91_hc_driver = { /*-------------------------------------------------------------------------*/ -static int ohci_hcd_at91_drv_probe(struct platform_device *dev) +static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) { - return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); + device_init_wakeup(&pdev->dev, 1); + return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } -static int ohci_hcd_at91_drv_remove(struct platform_device *dev) +static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) { - return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); + device_init_wakeup(&pdev->dev, 0); + return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); } #ifdef CONFIG_PM -/* REVISIT suspend/resume look "too" simple here */ - static int -ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg) +ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) { - clk_disable(fclk); - clk_disable(iclk); + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(hcd->irq); + else + disable_irq_wake(hcd->irq); + + /* + * The integrated transceivers seem unable to notice disconnect, + * reconnect, or wakeup without the 48 MHz clock active. so for + * correctness, always discard connection state (using reset). + * + * REVISIT: some boards will be able to turn VBUS off... + */ + if (at91_suspend_entering_slow_clock()) { + ohci_usb_reset (ohci); + clk_disable(fclk); + clk_disable(iclk); + clocked = 0; + } return 0; } -static int ohci_hcd_at91_drv_resume(struct platform_device *dev) +static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) { - clk_enable(iclk); - clk_enable(fclk); + if (!clocked) { + clk_enable(iclk); + clk_enable(fclk); + } return 0; } @@ -275,7 +305,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev) #define ohci_hcd_at91_drv_resume NULL #endif -MODULE_ALIAS("at91rm9200-ohci"); +MODULE_ALIAS("at91_ohci"); static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, @@ -283,7 +313,7 @@ static struct platform_driver ohci_hcd_at91_driver = { .suspend = ohci_hcd_at91_drv_suspend, .resume = ohci_hcd_at91_drv_resume, .driver = { - .name = "at91rm9200-ohci", + .name = "at91_ohci", .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index 822914e2f43b..f7a975d5db09 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -110,7 +110,6 @@ static void au1xxx_start_ohc(struct platform_device *dev) printk(KERN_DEBUG __FILE__ ": Clock to USB host has been enabled \n"); -#endif } static void au1xxx_stop_ohc(struct platform_device *dev) diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index afef5ac35b4a..94d8cf4b36c1 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -913,7 +913,7 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif -#ifdef CONFIG_ARCH_AT91RM9200 +#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) #include "ohci-at91.c" #endif @@ -927,6 +927,7 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ || defined (CONFIG_ARCH_AT91RM9200) \ + || defined (CONFIG_ARCH_AT91SAM9261) \ ) #error "missing bus glue for ohci-hcd" #endif diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index c9d72ac0a1d7..66c3f61bc9d1 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -943,7 +943,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) /* We received a short packet */ if (urb->transfer_flags & URB_SHORT_NOT_OK) ret = -EREMOTEIO; - else if (ctrlstat & TD_CTRL_SPD) + + /* Fixup needed only if this isn't the URB's last TD */ + else if (&td->list != urbp->td_list.prev) ret = 1; } diff --git a/trunk/drivers/usb/input/appletouch.c b/trunk/drivers/usb/input/appletouch.c index 9e3f13903371..044faa07e297 100644 --- a/trunk/drivers/usb/input/appletouch.c +++ b/trunk/drivers/usb/input/appletouch.c @@ -597,9 +597,9 @@ static void atp_disconnect(struct usb_interface *iface) if (dev) { usb_kill_urb(dev->urb); input_unregister_device(dev->input); - usb_free_urb(dev->urb); usb_buffer_free(dev->udev, dev->datalen, dev->data, dev->urb->transfer_dma); + usb_free_urb(dev->urb); kfree(dev); } printk(KERN_INFO "input: appletouch disconnected\n"); diff --git a/trunk/drivers/usb/input/ati_remote.c b/trunk/drivers/usb/input/ati_remote.c index 05d2d6012eb2..3719fcb04b8f 100644 --- a/trunk/drivers/usb/input/ati_remote.c +++ b/trunk/drivers/usb/input/ati_remote.c @@ -111,14 +111,28 @@ #define NAME_BUFSIZE 80 /* size of product name, path buffers */ #define DATA_BUFSIZE 63 /* size of URB data buffers */ +/* + * Duplicate event filtering time. + * Sequential, identical KIND_FILTERED inputs with less than + * FILTER_TIME milliseconds between them are considered as repeat + * events. The hardware generates 5 events for the first keypress + * and we have to take this into account for an accurate repeat + * behaviour. + */ +#define FILTER_TIME 60 /* msec */ + static unsigned long channel_mask; -module_param(channel_mask, ulong, 0444); +module_param(channel_mask, ulong, 0644); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug; -module_param(debug, int, 0444); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); +static int repeat_filter = FILTER_TIME; +module_param(repeat_filter, int, 0644); +MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); + #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) @@ -143,19 +157,6 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; -/* Acceleration curve for directional control pad */ -static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - -/* Duplicate event filtering time. - * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME jiffies between them are considered as repeat - * events. The hardware generates 5 events for the first keypress - * and we have to take this into account for an accurate repeat - * behaviour. - * (HZ / 20) == 50 ms and works well for me. - */ -#define FILTER_TIME (HZ / 20) - struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -412,6 +413,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) return -1; } +/* + * ati_remote_compute_accel + * + * Implements acceleration curve for directional control pad + * If elapsed time since last event is > 1/4 second, user "stopped", + * so reset acceleration. Otherwise, user is probably holding the control + * pad down, so we increase acceleration, ramping up over two seconds to + * a maximum speed. + */ +static int ati_remote_compute_accel(struct ati_remote *ati_remote) +{ + static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; + unsigned long now = jiffies; + int acc; + + if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { + acc = 1; + ati_remote->acc_jiffies = now; + } + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) + acc = accel[0]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) + acc = accel[1]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) + acc = accel[2]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) + acc = accel[3]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) + acc = accel[4]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) + acc = accel[5]; + else + acc = accel[6]; + + return acc; +} + /* * ati_remote_report_input */ @@ -465,9 +503,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* Filter duplicate events which happen "too close" together. */ - if ((ati_remote->old_data[0] == data[1]) && - (ati_remote->old_data[1] == data[2]) && - time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) { + if (ati_remote->old_data[0] == data[1] && + ati_remote->old_data[1] == data[2] && + time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; @@ -477,75 +515,61 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; - if ((ati_remote->repeat_count > 0) - && (ati_remote->repeat_count < 5)) + if (ati_remote->repeat_count > 0 && + ati_remote->repeat_count < 5) return; input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 1); + input_sync(dev); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 0); input_sync(dev); - return; - } + } else { - /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. - * - * If elapsed time since last event is > 1/4 second, user "stopped", - * so reset acceleration. Otherwise, user is probably holding the control - * pad down, so we increase acceleration, ramping up over two seconds to - * a maximum speed. The acceleration curve is #defined above. - */ - if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { - acc = 1; - ati_remote->acc_jiffies = jiffies; - } - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; - else acc = accel[6]; - - input_regs(dev, regs); - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); + /* + * Other event kinds are from the directional control pad, and have an + * acceleration factor applied to them. Without this acceleration, the + * control pad is mostly unusable. + */ + acc = ati_remote_compute_accel(ati_remote); + + input_regs(dev, regs); + switch (ati_remote_tbl[index].kind) { + case KIND_ACCEL: + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value * acc); + break; + case KIND_LU: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_RU: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_LD: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, acc); + break; + case KIND_RD: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, acc); + break; + default: + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); + } + input_sync(dev); - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + ati_remote->old_jiffies = jiffies; + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; + } } /* diff --git a/trunk/drivers/usb/input/hid-input.c b/trunk/drivers/usb/input/hid-input.c index 028e1ad89f5d..7208839f2dbf 100644 --- a/trunk/drivers/usb/input/hid-input.c +++ b/trunk/drivers/usb/input/hid-input.c @@ -607,7 +607,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } - if (usage->hat_min < usage->hat_max || usage->hat_dir) { + if (usage->type == EV_ABS && + (usage->hat_min < usage->hat_max || usage->hat_dir)) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { input_set_abs_params(input, i, -1, 1, 0, 0); diff --git a/trunk/drivers/usb/input/hiddev.c b/trunk/drivers/usb/input/hiddev.c index 70477f02cc29..f6b839c257a7 100644 --- a/trunk/drivers/usb/input/hiddev.c +++ b/trunk/drivers/usb/input/hiddev.c @@ -49,7 +49,7 @@ struct hiddev { int open; wait_queue_head_t wait; struct hid_device *hid; - struct hiddev_list *list; + struct list_head list; }; struct hiddev_list { @@ -59,7 +59,7 @@ struct hiddev_list { unsigned flags; struct fasync_struct *fasync; struct hiddev *hiddev; - struct hiddev_list *next; + struct list_head node; }; static struct hiddev *hiddev_table[HIDDEV_MINORS]; @@ -73,12 +73,15 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS]; static struct hid_report * hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) { - unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; struct hid_report_enum *report_enum; + struct hid_report *report; struct list_head *list; if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; + rinfo->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (rinfo->report_type - HID_REPORT_TYPE_MIN); @@ -88,21 +91,25 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) break; case HID_REPORT_ID_FIRST: - list = report_enum->report_list.next; - if (list == &report_enum->report_list) + if (list_empty(&report_enum->report_list)) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + list = report_enum->report_list.next; + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; case HID_REPORT_ID_NEXT: - list = (struct list_head *) - report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; - if (list == NULL) + report = report_enum->report_id_hash[rid]; + if (!report) return NULL; - list = list->next; + + list = report->list.next; if (list == &report_enum->report_list) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; default: @@ -125,12 +132,13 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) struct hid_field *field; if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) return NULL; + uref->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (uref->report_type - HID_REPORT_TYPE_MIN); - list_for_each_entry(report, &report_enum->report_list, list) + list_for_each_entry(report, &report_enum->report_list, list) { for (i = 0; i < report->maxfield; i++) { field = report->field[i]; for (j = 0; j < field->maxusage; j++) { @@ -142,6 +150,7 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) } } } + } return NULL; } @@ -150,9 +159,9 @@ static void hiddev_send_event(struct hid_device *hid, struct hiddev_usage_ref *uref) { struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list = hiddev->list; + struct hiddev_list *list; - while (list) { + list_for_each_entry(list, &hiddev->list, node) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { list->buffer[list->head] = *uref; @@ -160,8 +169,6 @@ static void hiddev_send_event(struct hid_device *hid, (HIDDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } - - list = list->next; } wake_up_interruptible(&hiddev->wait); @@ -180,7 +187,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = field->report->id; uref.field_index = field->index; uref.usage_index = (usage - field->usage); @@ -200,7 +207,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = report->id; uref.field_index = HID_FIELD_INDEX_NONE; @@ -213,7 +220,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) { int retval; struct hiddev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } @@ -224,14 +233,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; - struct hiddev_list **listptr; - listptr = &list->hiddev->list; hiddev_fasync(-1, file, 0); - - while (*listptr && (*listptr != list)) - listptr = &((*listptr)->next); - *listptr = (*listptr)->next; + list_del(&list->node); if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -248,7 +252,8 @@ static int hiddev_release(struct inode * inode, struct file * file) /* * open file op */ -static int hiddev_open(struct inode * inode, struct file * file) { +static int hiddev_open(struct inode *inode, struct file *file) +{ struct hiddev_list *list; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -260,9 +265,7 @@ static int hiddev_open(struct inode * inode, struct file * file) { return -ENOMEM; list->hiddev = hiddev_table[i]; - list->next = hiddev_table[i]->list; - hiddev_table[i]->list = list; - + list_add_tail(&list->node, &hiddev_table[i]->list); file->private_data = list; if (!list->hiddev->open++) @@ -362,6 +365,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun static unsigned int hiddev_poll(struct file *file, poll_table *wait) { struct hiddev_list *list = file->private_data; + poll_wait(file, &list->hiddev->wait, wait); if (list->head != list->tail) return POLLIN | POLLRDNORM; @@ -382,7 +386,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; - struct hiddev_usage_ref_multi *uref_multi=NULL; + struct hiddev_usage_ref_multi *uref_multi = NULL; struct hiddev_usage_ref *uref; struct hiddev_devinfo dinfo; struct hid_report *report; @@ -764,15 +768,15 @@ int hiddev_connect(struct hid_device *hid) } init_waitqueue_head(&hiddev->wait); - - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; - + INIT_LIST_HEAD(&hiddev->list); hiddev->hid = hid; hiddev->exist = 1; hid->minor = hid->intf->minor; hid->hiddev = hiddev; + hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + return 0; } diff --git a/trunk/drivers/usb/misc/cypress_cy7c63.c b/trunk/drivers/usb/misc/cypress_cy7c63.c index e091d327bd9e..a4062a6adbb8 100644 --- a/trunk/drivers/usb/misc/cypress_cy7c63.c +++ b/trunk/drivers/usb/misc/cypress_cy7c63.c @@ -12,8 +12,13 @@ * the single I/O ports of the device. * * Supported vendors: AK Modul-Bus Computer GmbH -* Supported devices: CY7C63001A-PC (to be continued...) -* Supported functions: Read/Write Ports (to be continued...) +* (Firmware "Port-Chip") +* +* Supported devices: CY7C63001A-PC +* CY7C63001C-PXC +* CY7C63001C-SXC +* +* Supported functions: Read/Write Ports * * * This program is free software; you can redistribute it and/or diff --git a/trunk/drivers/usb/misc/usbtest.c b/trunk/drivers/usb/misc/usbtest.c index 786e1dbe88ec..983e104dd452 100644 --- a/trunk/drivers/usb/misc/usbtest.c +++ b/trunk/drivers/usb/misc/usbtest.c @@ -1242,11 +1242,12 @@ static int halt_simple (struct usbtest_dev *dev) static int ctrl_out (struct usbtest_dev *dev, unsigned count, unsigned length, unsigned vary) { - unsigned i, j, len, retval; + unsigned i, j, len; + int retval; u8 *buf; char *what = "?"; struct usb_device *udev; - + if (length < 1 || length > 0xffff || vary >= length) return -EINVAL; diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index e5e6e4f3ef87..bd09232ce13c 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -175,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); static void rtl8150_disconnect(struct usb_interface *intf); static int rtl8150_probe(struct usb_interface *intf, const struct usb_device_id *id); +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); +static int rtl8150_resume(struct usb_interface *intf); static const char driver_name [] = "rtl8150"; @@ -183,6 +185,8 @@ static struct usb_driver rtl8150_driver = { .probe = rtl8150_probe, .disconnect = rtl8150_disconnect, .id_table = rtl8150_table, + .suspend = rtl8150_suspend, + .resume = rtl8150_resume }; /* @@ -238,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) usb_fill_control_urb(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, &dev->rx_creg, size, ctrl_callback, dev); - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) + if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(dev->netdev); err("control request submission failed: %d", ret); - else + } else set_bit(RX_REG_SET, &dev->flags); return ret; @@ -416,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) struct sk_buff *skb; struct net_device *netdev; u16 rx_stat; + int status; dev = urb->context; if (!dev) @@ -465,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goon: usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto resched; } else { @@ -481,6 +491,7 @@ static void rx_fixup(unsigned long data) { rtl8150_t *dev; struct sk_buff *skb; + int status; dev = (rtl8150_t *)data; @@ -499,10 +510,13 @@ static void rx_fixup(unsigned long data) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); try_again: - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) { + netif_device_detach(dev->netdev); + } else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto tlsched; - } else { + } else { clear_bit(RX_URB_FAIL, &dev->flags); } @@ -574,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) resubmit: status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) err ("can't resubmit intr, %s-%s/input0, status %d", dev->udev->bus->bus_name, dev->udev->devpath, status); } +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_detach(dev->netdev); + + if (netif_running(dev->netdev)) { + usb_kill_urb(dev->rx_urb); + usb_kill_urb(dev->intr_urb); + } + return 0; +} + +static int rtl8150_resume(struct usb_interface *intf) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_attach(dev->netdev); + if (netif_running(dev->netdev)) { + dev->rx_urb->status = 0; + dev->rx_urb->actual_length = 0; + read_bulk_callback(dev->rx_urb, NULL); + + dev->intr_urb->status = 0; + dev->intr_urb->actual_length = 0; + intr_callback(dev->intr_urb, NULL); + } + return 0; +} /* ** @@ -690,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), skb->data, count, write_bulk_callback, dev); if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { - warn("failed tx_urb %d\n", res); - dev->stats.tx_errors++; - netif_start_queue(netdev); + /* Can we get/handle EPIPE here? */ + if (res == -ENODEV) + netif_device_detach(dev->netdev); + else { + warn("failed tx_urb %d\n", res); + dev->stats.tx_errors++; + netif_start_queue(netdev); + } } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -729,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); + return res; + } usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), dev->intr_buff, INTBUFSIZE, intr_callback, dev, dev->intr_interval); - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); - netif_start_queue(netdev); + usb_kill_urb(dev->rx_urb); + return res; + } enable_net_traffic(dev); set_carrier(netdev); + netif_start_queue(netdev); return res; } diff --git a/trunk/drivers/usb/serial/Kconfig b/trunk/drivers/usb/serial/Kconfig index ac33bd47cfce..f5b9438c94f0 100644 --- a/trunk/drivers/usb/serial/Kconfig +++ b/trunk/drivers/usb/serial/Kconfig @@ -62,15 +62,6 @@ config USB_SERIAL_AIRPRIME To compile this driver as a module, choose M here: the module will be called airprime. -config USB_SERIAL_ANYDATA - tristate "USB AnyData CDMA Wireless Driver" - depends on USB_SERIAL - help - Say Y here if you want to use a AnyData CDMA device. - - To compile this driver as a module, choose M here: the - module will be called anydata. - config USB_SERIAL_ARK3116 tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL @@ -502,15 +493,18 @@ config USB_SERIAL_XIRCOM module will be called keyspan_pda. config USB_SERIAL_OPTION - tristate "USB driver for GSM modems" + tristate "USB driver for GSM and CDMA modems" depends on USB_SERIAL help - Say Y here if you have an "Option" GSM PCMCIA card - (or an OEM version: branded Huawei, Audiovox, or Novatel). + Say Y here if you have a GSM or CDMA modem that's connected to USB. + + This driver also supports several PCMCIA cards which have a + built-in OHCI-USB adapter and an internally-connected GSM modem. + The USB bus on these cards is not accessible externally. - These cards feature a built-in OHCI-USB adapter and an - internally-connected GSM modem. The USB bus is not - accessible externally. + Supported devices include (some of?) those made by: + Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or + Anydata. To compile this driver as a module, choose M here: the module will be called option. diff --git a/trunk/drivers/usb/serial/Makefile b/trunk/drivers/usb/serial/Makefile index 35d4acc7f1d3..8efed2ce1ba3 100644 --- a/trunk/drivers/usb/serial/Makefile +++ b/trunk/drivers/usb/serial/Makefile @@ -12,7 +12,6 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o -obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o diff --git a/trunk/drivers/usb/serial/anydata.c b/trunk/drivers/usb/serial/anydata.c deleted file mode 100644 index 01843ef8c11e..000000000000 --- a/trunk/drivers/usb/serial/anydata.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * AnyData CDMA Serial USB driver - * - * Copyright (C) 2005 Greg Kroah-Hartman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -static struct usb_device_id id_table [] = { - { USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */ - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* if overridden by the user, then use their value for the size of the - * read and write urbs */ -static int buffer_size; -static int debug; - -static struct usb_driver anydata_driver = { - .name = "anydata", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - -static int anydata_open(struct usb_serial_port *port, struct file *filp) -{ - char *buffer; - int result = 0; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (buffer_size) { - /* override the default buffer sizes */ - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&port->dev, "%s - out of memory.\n", - __FUNCTION__); - return -ENOMEM; - } - kfree (port->read_urb->transfer_buffer); - port->read_urb->transfer_buffer = buffer; - port->read_urb->transfer_buffer_length = buffer_size; - - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&port->dev, "%s - out of memory.\n", - __FUNCTION__); - return -ENOMEM; - } - kfree (port->write_urb->transfer_buffer); - port->write_urb->transfer_buffer = buffer; - port->write_urb->transfer_buffer_length = buffer_size; - port->bulk_out_size = buffer_size; - } - - /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - usb_serial_generic_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __FUNCTION__, result); - - return result; -} - -static struct usb_serial_driver anydata_device = { - .driver = { - .owner = THIS_MODULE, - .name = "anydata", - }, - .id_table = id_table, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, - .open = anydata_open, -}; - -static int __init anydata_init(void) -{ - int retval; - - retval = usb_serial_register(&anydata_device); - if (retval) - return retval; - retval = usb_register(&anydata_driver); - if (retval) - usb_serial_deregister(&anydata_device); - return retval; -} - -static void __exit anydata_exit(void) -{ - usb_deregister(&anydata_driver); - usb_serial_deregister(&anydata_device); -} - -module_init(anydata_init); -module_exit(anydata_exit); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -module_param(buffer_size, int, 0); -MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index b458aedc5fb6..15945e806f03 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -306,6 +306,8 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { static struct usb_device_id id_table_combined [] = { + { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, @@ -337,6 +339,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, diff --git a/trunk/drivers/usb/serial/ftdi_sio.h b/trunk/drivers/usb/serial/ftdi_sio.h index 04ef90fcb876..8888cd80a491 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.h +++ b/trunk/drivers/usb/serial/ftdi_sio.h @@ -32,6 +32,12 @@ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ +/* www.canusb.com Lawicel CANUSB device */ +#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ + +/* AlphaMicro Components AMC-232USB01 device */ +#define FTDI_AMC232_PID 0xFF00 /* Product Id */ + /* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ #define FTDI_ACTZWAVE_PID 0xF2D0 @@ -182,6 +188,10 @@ /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ #define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ +/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ + +#define FTDI_TNC_X_PID 0xEBE0 + /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). * All of these devices use FTDI's vendor ID (0x0403). diff --git a/trunk/drivers/usb/serial/ipaq.c b/trunk/drivers/usb/serial/ipaq.c index 59c5d999009a..9840bade79f9 100644 --- a/trunk/drivers/usb/serial/ipaq.c +++ b/trunk/drivers/usb/serial/ipaq.c @@ -250,6 +250,9 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ + { USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */ + { USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */ + { USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */ { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index f0530c1d7b7a..c856e6f40e22 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -9,40 +9,14 @@ Portions copied from the Keyspan driver by Hugh Blemings - History: - - 2005-05-19 v0.1 Initial version, based on incomplete docs - and analysis of misbehavior with the standard driver - 2005-05-20 v0.2 Extended the input buffer to avoid losing - random 64-byte chunks of data - 2005-05-21 v0.3 implemented chars_in_buffer() - turned on low_latency - simplified the code somewhat - 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load - removed some dead code - added sponsor notice - coding style clean-up - 2005-06-20 v0.4.1 add missing braces :-/ - killed end-of-line whitespace - 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 - 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard - 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes - wants to send >2000 bytes. - 2006-04-10 v0.5 fixed two array overrun errors :-/ - 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 - 2006-05-15 v0.6 re-enable multi-port support - 2006-06-01 v0.6.1 add COBRA - 2006-06-01 v0.6.2 add backwards-compatibility stuff - 2006-06-01 v0.6.3 add Novatel Wireless - 2006-06-01 v0.7 Option => GSM - 2006-06-01 v0.7.1 add COBRA2 + History: see the git log. Work sponsored by: Sigos GmbH, Germany This driver exists because the "normal" serial driver doesn't work too well with GSM modems. Issues: - data loss -- one single Receive URB is not nearly enough - - nonstandard flow (Option devices) and multiplex (Sierra) control + - nonstandard flow (Option devices) control - controlling the baud rate doesn't make sense This driver is named "option" because the most common device it's @@ -96,8 +70,8 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_VENDOR_ID 0x0AF0 #define HUAWEI_VENDOR_ID 0x12D1 #define AUDIOVOX_VENDOR_ID 0x0F3D -#define SIERRAWIRELESS_VENDOR_ID 0x1199 #define NOVATELWIRELESS_VENDOR_ID 0x1410 +#define ANYDATA_VENDOR_ID 0x16d5 #define OPTION_PRODUCT_OLD 0x5000 #define OPTION_PRODUCT_FUSION 0x6000 @@ -106,8 +80,8 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_PRODUCT_COBRA2 0x6600 #define HUAWEI_PRODUCT_E600 0x1001 #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 -#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 #define NOVATELWIRELESS_PRODUCT_U740 0x1400 +#define ANYDATA_PRODUCT_ID 0x6501 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, @@ -117,8 +91,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, - { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -131,10 +105,7 @@ static struct usb_device_id option_ids1[] = { { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, - { } /* Terminating entry */ -}; -static struct usb_device_id option_ids3[] = { - { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -151,37 +122,11 @@ static struct usb_driver option_driver = { /* The card has three separate interfaces, which the serial driver * recognizes separately, thus num_port=1. */ -static struct usb_serial_driver option_3port_device = { - .driver = { - .owner = THIS_MODULE, - .name = "option", - }, - .description = "GSM modem (3-port)", - .id_table = option_ids3, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 3, - .open = option_open, - .close = option_close, - .write = option_write, - .write_room = option_write_room, - .chars_in_buffer = option_chars_in_buffer, - .throttle = option_rx_throttle, - .unthrottle = option_rx_unthrottle, - .set_termios = option_set_termios, - .break_ctl = option_break_ctl, - .tiocmget = option_tiocmget, - .tiocmset = option_tiocmset, - .attach = option_startup, - .shutdown = option_shutdown, - .read_int_callback = option_instat_callback, -}; static struct usb_serial_driver option_1port_device = { .driver = { .owner = THIS_MODULE, - .name = "option", + .name = "option1", }, .description = "GSM modem (1-port)", .id_table = option_ids1, @@ -245,9 +190,6 @@ static int __init option_init(void) retval = usb_serial_register(&option_1port_device); if (retval) goto failed_1port_device_register; - retval = usb_serial_register(&option_3port_device); - if (retval) - goto failed_3port_device_register; retval = usb_register(&option_driver); if (retval) goto failed_driver_register; @@ -257,8 +199,6 @@ static int __init option_init(void) return 0; failed_driver_register: - usb_serial_deregister (&option_3port_device); -failed_3port_device_register: usb_serial_deregister (&option_1port_device); failed_1port_device_register: return retval; @@ -267,7 +207,6 @@ static int __init option_init(void) static void __exit option_exit(void) { usb_deregister (&option_driver); - usb_serial_deregister (&option_3port_device); usb_serial_deregister (&option_1port_device); } @@ -656,7 +595,6 @@ static void option_setup_urbs(struct usb_serial *serial) dbg("%s", __FUNCTION__); - for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 259db31b65c1..efbbc0adb89a 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -81,6 +81,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, { USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) }, { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, + { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/trunk/drivers/usb/serial/pl2303.h b/trunk/drivers/usb/serial/pl2303.h index d9c1e6e0b4b3..a692ac66ca6c 100644 --- a/trunk/drivers/usb/serial/pl2303.h +++ b/trunk/drivers/usb/serial/pl2303.h @@ -89,3 +89,7 @@ /* DATAPILOT Universal-2 Phone Cable */ #define DATAPILOT_U2_VENDOR_ID 0x0731 #define DATAPILOT_U2_PRODUCT_ID 0x2003 + +/* Belkin "F5U257" Serial Adapter */ +#define BELKIN_VENDOR_ID 0x050d +#define BELKIN_PRODUCT_ID 0x0257 diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index a5ca449f6e64..fd158e063c06 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -145,6 +145,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Mario Rettig */ +UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, + "Nokia", + "Nokia 3250", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), + /* Reported by Sumedha Swamy and * Einar Th. Einarsson */ UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, @@ -627,18 +634,6 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Digital Camera EX-20 DSC", US_SC_8070, US_PR_DEVICE, NULL, 0 ), -/* The entry was here before I took over, and had US_SC_RBC. It turns - * out that isn't needed. Additionally, Torsten Eriksson - * is able to use his device fine - * without this entry at all - but I don't suspect that will be true - * for all users (the protocol is likely needed), so is staying at - * this time. - Phil Dibowitz - */ -UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, - "LaCie", - "USB Hard Disk", - US_SC_DEVICE, US_PR_CB, NULL, 0 ), - /* Submitted by Joel Bourquard * Some versions of this device need the SubClass and Protocol overrides * while others don't. @@ -1106,7 +1101,15 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, "Optio S/S4", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + +/* This is a virtual windows driver CD, which the zd1211rw driver automatically + * converts into a WLAN device. */ +UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, + "ZyXEL", + "G-220F USB-WLAN Install", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", @@ -1237,6 +1240,16 @@ UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64), +/* David Kuehling : + * for MP3-Player AVOX WSX-300ER (bought in Japan). Reports lots of SCSI + * errors when trying to write. + */ +UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, + "C-MEX", + "A-VOX", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Michael Stattmann */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index 5ee19be52f65..8d7bdcb5924d 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -483,7 +483,7 @@ static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) } /* Get the unusual_devs entries and the string descriptors */ -static void get_device_info(struct us_data *us, const struct usb_device_id *id) +static int get_device_info(struct us_data *us, const struct usb_device_id *id) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = @@ -500,6 +500,11 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) unusual_dev->useTransport; us->flags = USB_US_ORIG_FLAGS(id->driver_info); + if (us->flags & US_FL_IGNORE_DEVICE) { + printk(KERN_INFO USB_STORAGE "device ignored\n"); + return -ENODEV; + } + /* * This flag is only needed when we're in high-speed, so let's * disable it if we're in full-speed @@ -541,6 +546,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) msgs[msg], UTS_RELEASE); } + + return 0; } /* Get the transport settings */ @@ -969,7 +976,9 @@ static int storage_probe(struct usb_interface *intf, * of the match from the usb_device_id table, so we can find the * corresponding entry in the private table. */ - get_device_info(us, id); + result = get_device_info(us, id); + if (result) + goto BadDevice; /* Get the transport, protocol, and pipe settings */ result = get_transport(us); diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 6533b0f39231..702eb933cf88 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -86,9 +86,11 @@ config FB_MACMODES default n config FB_BACKLIGHT - bool - depends on FB - default n + bool + depends on FB + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default n config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" @@ -420,7 +422,7 @@ config FB_OF config FB_CONTROL bool "Apple \"control\" display support" - depends on (FB = y) && PPC_PMAC + depends on (FB = y) && PPC_PMAC && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -431,7 +433,7 @@ config FB_CONTROL config FB_PLATINUM bool "Apple \"platinum\" display support" - depends on (FB = y) && PPC_PMAC + depends on (FB = y) && PPC_PMAC && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -442,7 +444,7 @@ config FB_PLATINUM config FB_VALKYRIE bool "Apple \"valkyrie\" display support" - depends on (FB = y) && (MAC || PPC_PMAC) + depends on (FB = y) && (MAC || (PPC_PMAC && PPC32)) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -453,7 +455,7 @@ config FB_VALKYRIE config FB_CT65550 bool "Chips 65550 display support" - depends on (FB = y) && PPC + depends on (FB = y) && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -552,7 +554,7 @@ config FB_VESA config FB_IMAC bool "Intel-based Macintosh Framebuffer Support" - depends on (FB = y) && X86 + depends on (FB = y) && X86 && EFI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -721,10 +723,8 @@ config FB_NVIDIA_I2C config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" - depends on FB_NVIDIA && PPC_PMAC + depends on FB_NVIDIA && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -769,10 +769,8 @@ config FB_RIVA_DEBUG config FB_RIVA_BACKLIGHT bool "Support for backlight control" - depends on FB_RIVA && PPC_PMAC + depends on FB_RIVA && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1025,10 +1023,8 @@ config FB_RADEON_I2C config FB_RADEON_BACKLIGHT bool "Support for backlight control" - depends on FB_RADEON && PPC_PMAC + depends on FB_RADEON && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1059,10 +1055,8 @@ config FB_ATY128 config FB_ATY128_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY128 && PPC_PMAC + depends on FB_ATY128 && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1111,10 +1105,8 @@ config FB_ATY_GX config FB_ATY_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY && PPC_PMAC + depends on FB_ATY && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1620,7 +1612,7 @@ if FB || SGI_NEWPORT_CONSOLE source "drivers/video/logo/Kconfig" endif -if FB && SYSFS +if SYSFS source "drivers/video/backlight/Kconfig" endif diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 95563c9c6b9c..481c6c9695f8 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-y += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ modedb.o fbcvt.o diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index c64a717e2d4b..3e827e04a2aa 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -455,7 +455,10 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_idle(struct aty128fb_par *par); static u32 depth_to_dst(u32 depth); + +#ifdef CONFIG_FB_ATY128_BACKLIGHT static void aty128_bl_set_power(struct fb_info *info, int power); +#endif #define BIOS_IN8(v) (readb(bios + (v))) #define BIOS_IN16(v) (readb(bios + (v)) | \ @@ -1910,9 +1913,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u8 chip_rev; u32 dac; - if (!par->vram_size) /* may have already been probed */ - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; - /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; @@ -2025,9 +2025,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_init_engine(par); - if (register_framebuffer(info) < 0) - return 0; - par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; @@ -2037,6 +2034,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_bl_init(par); #endif + if (register_framebuffer(info) < 0) + return 0; + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -2086,7 +2086,6 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ par = info->par; info->pseudo_palette = par->pseudo_palette; - info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 1507d19f481f..053ff63365b7 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -2812,7 +2812,7 @@ static int atyfb_blank(int blank, struct fb_info *info) if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_PMAC_BACKLIGHT +#ifdef CONFIG_FB_ATY_BACKLIGHT if (machine_is(powermac) && blank > FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_POWERDOWN); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) @@ -2844,7 +2844,7 @@ static int atyfb_blank(int blank, struct fb_info *info) } aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); -#ifdef CONFIG_PMAC_BACKLIGHT +#ifdef CONFIG_FB_ATY_BACKLIGHT if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_UNBLANK); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) diff --git a/trunk/drivers/video/aty/radeon_base.c b/trunk/drivers/video/aty/radeon_base.c index 8d85fc58142e..8e3400d5dd21 100644 --- a/trunk/drivers/video/aty/radeon_base.c +++ b/trunk/drivers/video/aty/radeon_base.c @@ -266,6 +266,8 @@ static int force_measure_pll = 0; #ifdef CONFIG_MTRR static int nomtrr = 0; #endif +static int force_sleep; +static int ignore_devlist; /* * prototypes @@ -2327,9 +2329,9 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, /* -2 is special: means ON on mobility chips and do not * change on others */ - radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); + radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep); } else - radeonfb_pm_init(rinfo, default_dynclk); + radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep); pci_set_drvdata(pdev, info); @@ -2477,6 +2479,12 @@ static int __init radeonfb_setup (char *options) force_measure_pll = 1; } else if (!strncmp(this_opt, "ignore_edid", 11)) { ignore_edid = 1; +#if defined(CONFIG_PM) && defined(CONFIG_X86) + } else if (!strncmp(this_opt, "force_sleep", 11)) { + force_sleep = 1; + } else if (!strncmp(this_opt, "ignore_devlist", 14)) { + ignore_devlist = 1; +#endif } else mode_option = this_opt; } @@ -2532,3 +2540,9 @@ module_param(panel_yres, int, 0); MODULE_PARM_DESC(panel_yres, "int: set panel yres"); module_param(mode_option, charp, 0); MODULE_PARM_DESC(mode_option, "Specify resolution as \"x[-][@]\" "); +#if defined(CONFIG_PM) && defined(CONFIG_X86) +module_param(force_sleep, bool, 0); +MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware"); +module_param(ignore_devlist, bool, 0); +MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops"); +#endif diff --git a/trunk/drivers/video/aty/radeon_pm.c b/trunk/drivers/video/aty/radeon_pm.c index c7091761cef4..f31e606a2ded 100644 --- a/trunk/drivers/video/aty/radeon_pm.c +++ b/trunk/drivers/video/aty/radeon_pm.c @@ -27,6 +27,99 @@ #include "ati_ids.h" +static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); + +/* + * Workarounds for bugs in PC laptops: + * - enable D2 sleep in some IBM Thinkpads + * - special case for Samsung P35 + * + * Whitelist by subsystem vendor/device because + * its the subsystem vendor's fault! + */ + +#if defined(CONFIG_PM) && defined(CONFIG_X86) +struct radeon_device_id { + const char *ident; /* (arbitrary) Name */ + const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ + const unsigned short subsystem_device; /* Subsystem Device ID */ + const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */ + const reinit_function_ptr new_reinit_func; /* changed reinit_func */ +}; + +#define BUGFIX(model, sv, sd, pm, fn) { \ + .ident = model, \ + .subsystem_vendor = sv, \ + .subsystem_device = sd, \ + .pm_mode_modifier = pm, \ + .new_reinit_func = fn \ +} + +static struct radeon_device_id radeon_workaround_list[] = { + BUGFIX("IBM Thinkpad R32", + PCI_VENDOR_ID_IBM, 0x1905, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R40", + PCI_VENDOR_ID_IBM, 0x0526, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R40", + PCI_VENDOR_ID_IBM, 0x0527, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R50/R51/T40/T41", + PCI_VENDOR_ID_IBM, 0x0531, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R51/T40/T41/T42", + PCI_VENDOR_ID_IBM, 0x0530, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T30", + PCI_VENDOR_ID_IBM, 0x0517, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T40p", + PCI_VENDOR_ID_IBM, 0x054d, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T42", + PCI_VENDOR_ID_IBM, 0x0550, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad X31/X32", + PCI_VENDOR_ID_IBM, 0x052f, + radeon_pm_d2, NULL), + BUGFIX("Samsung P35", + PCI_VENDOR_ID_SAMSUNG, 0xc00c, + radeon_pm_off, radeon_reinitialize_M10), + { .ident = NULL } +}; + +static int radeon_apply_workarounds(struct radeonfb_info *rinfo) +{ + struct radeon_device_id *id; + + for (id = radeon_workaround_list; id->ident != NULL; id++ ) + if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) && + (id->subsystem_device == rinfo->pdev->subsystem_device )) { + + /* we found a device that requires workaround */ + printk(KERN_DEBUG "radeonfb: %s detected" + ", enabling workaround\n", id->ident); + + rinfo->pm_mode |= id->pm_mode_modifier; + + if (id->new_reinit_func != NULL) + rinfo->reinit_func = id->new_reinit_func; + + return 1; + } + return 0; /* not found */ +} + +#else /* defined(CONFIG_PM) && defined(CONFIG_X86) */ +static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo) +{ + return 0; +} +#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */ + + + static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) { u32 tmp; @@ -852,18 +945,26 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; OUTPLL( pllMCLK_MISC, tmp); - - /* AGP PLL control */ - if (rinfo->family <= CHIP_FAMILY_RV280) { - OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); - OUTREG(BUS_CNTL1, - (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) - | (2<family <= CHIP_FAMILY_RV280) { + OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); + OUTREG(BUS_CNTL1, + (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) + | (2<pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); @@ -2729,22 +2830,13 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) } #if defined(CONFIG_PM) +#if defined(CONFIG_PPC_PMAC) /* Check if we can power manage on suspend/resume. We can do * D2 on M6, M7 and M9, and we can resume from D3 cold a few other * "Mac" cards, but that's all. We need more infos about what the * BIOS does tho. Right now, all this PM stuff is pmac-only for that * reason. --BenH */ - /* Special case for Samsung P35 laptops - */ - if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) && - (rinfo->pdev->device == PCI_CHIP_RV350_NP) && - (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) && - (rinfo->pdev->subsystem_device == 0xc00c)) { - rinfo->reinit_func = radeon_reinitialize_M10; - rinfo->pm_mode |= radeon_pm_off; - } -#if defined(CONFIG_PPC_PMAC) if (machine_is(powermac) && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) @@ -2790,6 +2882,18 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) } #endif /* defined(CONFIG_PPC_PMAC) */ #endif /* defined(CONFIG_PM) */ + + if (ignore_devlist) + printk(KERN_DEBUG + "radeonfb: skipping test for device workarounds\n"); + else + radeon_apply_workarounds(rinfo); + + if (force_sleep) { + printk(KERN_DEBUG + "radeonfb: forcefully enabling D2 sleep mode\n"); + rinfo->pm_mode |= radeon_pm_d2; + } } void radeonfb_pm_exit(struct radeonfb_info *rinfo) diff --git a/trunk/drivers/video/aty/radeonfb.h b/trunk/drivers/video/aty/radeonfb.h index 38657b2d10eb..d5ff224a6258 100644 --- a/trunk/drivers/video/aty/radeonfb.h +++ b/trunk/drivers/video/aty/radeonfb.h @@ -273,6 +273,8 @@ enum radeon_pm_mode { radeon_pm_off = 0x00000002, /* Can resume from D3 cold */ }; +typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo); + struct radeonfb_info { struct fb_info *info; @@ -338,7 +340,7 @@ struct radeonfb_info { int dynclk; int no_schedule; enum radeon_pm_mode pm_mode; - void (*reinit_func)(struct radeonfb_info *rinfo); + reinit_function_ptr reinit_func; /* Lock on register access */ spinlock_t reg_lock; @@ -600,7 +602,7 @@ extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 /* PM Functions */ extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); extern int radeonfb_pci_resume(struct pci_dev *pdev); -extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk); +extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep); extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); /* Monitor probe functions */ diff --git a/trunk/drivers/video/au1100fb.c b/trunk/drivers/video/au1100fb.c index a92a91fef16f..f25d5d648333 100644 --- a/trunk/drivers/video/au1100fb.c +++ b/trunk/drivers/video/au1100fb.c @@ -156,7 +156,7 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ - } + } } else { /* mono */ info->fix.visual = FB_VISUAL_MONO10; @@ -164,20 +164,16 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) } info->screen_size = info->fix.line_length * info->var.yres_virtual; + info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \ + >> LCD_CONTROL_SM_BIT) * 90; /* Determine BPP mode and format */ - fbdev->regs->lcd_control = fbdev->panel->control_base | - ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); - - fbdev->regs->lcd_intenable = 0; - fbdev->regs->lcd_intstatus = 0; - + fbdev->regs->lcd_control = fbdev->panel->control_base; fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; - fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; - fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; - + fbdev->regs->lcd_intenable = 0; + fbdev->regs->lcd_intstatus = 0; fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); if (panel_is_dual(fbdev->panel)) { @@ -206,6 +202,8 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) /* Resume controller */ fbdev->regs->lcd_control |= LCD_CONTROL_GO; + mdelay(10); + au1100fb_fb_blank(VESA_NO_BLANKING, info); return 0; } diff --git a/trunk/drivers/video/backlight/Kconfig b/trunk/drivers/video/backlight/Kconfig index 022f9d3473f5..02f15297a021 100644 --- a/trunk/drivers/video/backlight/Kconfig +++ b/trunk/drivers/video/backlight/Kconfig @@ -10,7 +10,7 @@ menuconfig BACKLIGHT_LCD_SUPPORT config BACKLIGHT_CLASS_DEVICE tristate "Lowlevel Backlight controls" - depends on BACKLIGHT_LCD_SUPPORT && FB + depends on BACKLIGHT_LCD_SUPPORT default m help This framework adds support for low-level control of the LCD @@ -26,7 +26,7 @@ config BACKLIGHT_DEVICE config LCD_CLASS_DEVICE tristate "Lowlevel LCD controls" - depends on BACKLIGHT_LCD_SUPPORT && FB + depends on BACKLIGHT_LCD_SUPPORT default m help This framework adds support for low-level control of LCD. diff --git a/trunk/drivers/video/console/mdacon.c b/trunk/drivers/video/console/mdacon.c index 52ed12b12acc..eb4d03fa5391 100644 --- a/trunk/drivers/video/console/mdacon.c +++ b/trunk/drivers/video/console/mdacon.c @@ -197,7 +197,7 @@ static int __init mdacon_setup(char *str) __setup("mdacon=", mdacon_setup); #endif -static int __init mda_detect(void) +static int mda_detect(void) { int count=0; u16 *p, p_save; @@ -282,7 +282,7 @@ static int __init mda_detect(void) return 1; } -static void __init mda_initialize(void) +static void mda_initialize(void) { write_mda_b(97, 0x00); /* horizontal total */ write_mda_b(80, 0x01); /* horizontal displayed */ diff --git a/trunk/drivers/video/fb_notify.c b/trunk/drivers/video/fb_notify.c new file mode 100644 index 000000000000..8c020389e4fa --- /dev/null +++ b/trunk/drivers/video/fb_notify.c @@ -0,0 +1,46 @@ +/* + * linux/drivers/video/fb_notify.c + * + * Copyright (C) 2006 Antonino Daplas + * + * 2001 - Documented with DocBook + * - Brad Douglas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ +#include +#include + +static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); + +/** + * fb_register_client - register a client notifier + * @nb: notifier block to callback on events + */ +int fb_register_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_register_client); + +/** + * fb_unregister_client - unregister a client notifier + * @nb: notifier block to callback on events + */ +int fb_unregister_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_unregister_client); + +/** + * fb_notifier_call_chain - notify clients of fb_events + * + */ +int fb_notifier_call_chain(unsigned long val, void *v) +{ + return blocking_notifier_call_chain(&fb_notifier_list, val, v); +} +EXPORT_SYMBOL_GPL(fb_notifier_call_chain); diff --git a/trunk/drivers/video/fbmem.c b/trunk/drivers/video/fbmem.c index 4fc9df426c1a..17961e3ecaa0 100644 --- a/trunk/drivers/video/fbmem.c +++ b/trunk/drivers/video/fbmem.c @@ -52,7 +52,6 @@ #define FBPIXMAPSIZE (1024 * 8) -static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; @@ -791,8 +790,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) event.info = info; event.data = &mode1; - ret = blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_MODE_DELETE, &event); + ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); } if (!ret) @@ -837,8 +835,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) info->flags &= ~FBINFO_MISC_USEREVENT; event.info = info; - blocking_notifier_call_chain(&fb_notifier_list, - evnt, &event); + fb_notifier_call_chain(evnt, &event); } } } @@ -861,8 +858,7 @@ fb_blank(struct fb_info *info, int blank) event.info = info; event.data = ␣ - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_BLANK, &event); + fb_notifier_call_chain(FB_EVENT_BLANK, &event); } return ret; @@ -933,8 +929,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, con2fb.framebuffer = -1; event.info = info; event.data = &con2fb; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_GET_CONSOLE_MAP, &event); + fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; case FBIOPUT_CON2FBMAP: @@ -952,9 +947,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; event.info = info; event.data = &con2fb; - return blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_SET_CONSOLE_MAP, - &event); + return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, + &event); case FBIOBLANK: acquire_console_sem(); info->flags |= FBINFO_MISC_USEREVENT; @@ -1330,8 +1324,7 @@ register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_FB_REGISTERED, &event); + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); return 0; } @@ -1365,29 +1358,10 @@ unregister_framebuffer(struct fb_info *fb_info) fb_cleanup_class_device(fb_info); class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_FB_UNREGISTERED, &event); + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); return 0; } -/** - * fb_register_client - register a client notifier - * @nb: notifier block to callback on events - */ -int fb_register_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&fb_notifier_list, nb); -} - -/** - * fb_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int fb_unregister_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&fb_notifier_list, nb); -} - /** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected @@ -1403,13 +1377,11 @@ void fb_set_suspend(struct fb_info *info, int state) event.info = info; if (state) { - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_SUSPEND, &event); + fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); info->state = FBINFO_STATE_SUSPENDED; } else { info->state = FBINFO_STATE_RUNNING; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_RESUME, &event); + fb_notifier_call_chain(FB_EVENT_RESUME, &event); } } @@ -1480,9 +1452,7 @@ int fb_new_modelist(struct fb_info *info) if (!list_empty(&info->modelist)) { event.info = info; - err = blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_NEW_MODELIST, - &event); + err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); } return err; @@ -1594,8 +1564,6 @@ EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_pan_display); EXPORT_SYMBOL(fb_get_buffer_offset); EXPORT_SYMBOL(fb_set_suspend); -EXPORT_SYMBOL(fb_register_client); -EXPORT_SYMBOL(fb_unregister_client); EXPORT_SYMBOL(fb_get_options); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/video/imacfb.c b/trunk/drivers/video/imacfb.c index ff233b84dec4..b485bece5fc9 100644 --- a/trunk/drivers/video/imacfb.c +++ b/trunk/drivers/video/imacfb.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include @@ -28,7 +30,7 @@ typedef enum _MAC_TYPE { M_I20, M_MINI, M_MACBOOK, - M_NEW + M_UNKNOWN } MAC_TYPE; /* --------------------------------------------------------------------- */ @@ -52,10 +54,36 @@ static struct fb_fix_screeninfo imacfb_fix __initdata = { }; static int inverse; -static int model = M_NEW; +static int model = M_UNKNOWN; static int manual_height; static int manual_width; +static int set_system(struct dmi_system_id *id) +{ + printk(KERN_INFO "imacfb: %s detected - set system to %ld\n", + id->ident, (long)id->driver_data); + + model = (long)id->driver_data; + + return 0; +} + +static struct dmi_system_id __initdata dmi_system_table[] = { + { set_system, "iMac4,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_BIOS_VERSION,"iMac4,1") }, (void*)M_I17}, + { set_system, "MacBookPro1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_BIOS_VERSION,"MacBookPro1,1") }, (void*)M_I17}, + { set_system, "MacBook1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK}, + { set_system, "Macmini1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI}, + {}, +}; + #define DEFAULT_FB_MEM 1024*1024*16 /* --------------------------------------------------------------------- */ @@ -149,7 +177,6 @@ static int __init imacfb_probe(struct platform_device *dev) screen_info.lfb_linelength = 1472 * 4; screen_info.lfb_base = 0x80010000; break; - case M_NEW: case M_I20: screen_info.lfb_width = 1680; screen_info.lfb_height = 1050; @@ -207,6 +234,10 @@ static int __init imacfb_probe(struct platform_device *dev) size_remap = size_total; imacfb_fix.smem_len = size_remap; +#ifndef __i386__ + screen_info.imacpm_seg = 0; +#endif + if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { printk(KERN_WARNING "imacfb: cannot reserve video memory at 0x%lx\n", @@ -324,8 +355,16 @@ static int __init imacfb_init(void) int ret; char *option = NULL; - /* ignore error return of fb_get_options */ - fb_get_options("imacfb", &option); + if (!efi_enabled) + return -ENODEV; + if (!dmi_check_system(dmi_system_table)) + return -ENODEV; + if (model == M_UNKNOWN) + return -ENODEV; + + if (fb_get_options("imacfb", &option)) + return -ENODEV; + imacfb_setup(option); ret = platform_driver_register(&imacfb_driver); diff --git a/trunk/drivers/video/nvidia/nvidia.c b/trunk/drivers/video/nvidia/nvidia.c index 9f2066f0745a..d4f850117874 100644 --- a/trunk/drivers/video/nvidia/nvidia.c +++ b/trunk/drivers/video/nvidia/nvidia.c @@ -34,10 +34,6 @@ #include "nv_proto.h" #include "nv_dma.h" -#ifndef CONFIG_PCI /* sanity check */ -#error This driver requires PCI support. -#endif - #undef CONFIG_FB_NVIDIA_DEBUG #ifdef CONFIG_FB_NVIDIA_DEBUG #define NVTRACE printk @@ -1303,20 +1299,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, nvidia_save_vga(par, &par->SavedReg); + pci_set_drvdata(pd, info); + nvidia_bl_init(par); if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering nVidia framebuffer\n"); goto err_out_iounmap_fb; } - pci_set_drvdata(pd, info); printk(KERN_INFO PFX "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); - nvidia_bl_init(par); - NVTRACE_LEAVE(); return 0; diff --git a/trunk/drivers/video/offb.c b/trunk/drivers/video/offb.c index ce5f3031b99b..0013311e0564 100644 --- a/trunk/drivers/video/offb.c +++ b/trunk/drivers/video/offb.c @@ -62,8 +62,6 @@ struct offb_par default_par; * Interface used by the world */ -int offb_init(void); - static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int offb_blank(int blank, struct fb_info *info); @@ -72,11 +70,6 @@ static int offb_blank(int blank, struct fb_info *info); extern boot_infos_t *boot_infos; #endif -static void offb_init_nodriver(struct device_node *); -static void offb_init_fb(const char *name, const char *full_name, - int width, int height, int depth, int pitch, - unsigned long address, struct device_node *dp); - static struct fb_ops offb_ops = { .owner = THIS_MODULE, .fb_setcolreg = offb_setcolreg, @@ -229,123 +222,17 @@ static int offb_blank(int blank, struct fb_info *info) return 0; } - /* - * Initialisation - */ -int __init offb_init(void) +static void __iomem *offb_map_reg(struct device_node *np, int index, + unsigned long offset, unsigned long size) { - struct device_node *dp = NULL, *boot_disp = NULL; - - if (fb_get_options("offb", NULL)) - return -ENODEV; + struct resource r; - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - get_property(dp, "linux,boot-display", NULL)) { - boot_disp = dp; - offb_init_nodriver(dp); - } - } - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - dp != boot_disp) - offb_init_nodriver(dp); - } - - return 0; -} - - -static void __init offb_init_nodriver(struct device_node *dp) -{ - unsigned int len; - int i, width = 640, height = 480, depth = 8, pitch = 640; - unsigned int flags, rsize, addr_prop = 0; - unsigned long max_size = 0; - u64 rstart, address = OF_BAD_ADDR; - u32 *pp, *addrp, *up; - u64 asize; - - pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "depth", &len); - if (pp && len == sizeof(u32)) - depth = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-width", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "width", &len); - if (pp && len == sizeof(u32)) - width = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-height", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "height", &len); - if (pp && len == sizeof(u32)) - height = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "linebytes", &len); - if (pp && len == sizeof(u32)) - pitch = *pp; - else - pitch = width * ((depth + 7) / 8); - - rsize = (unsigned long)pitch * (unsigned long)height; - - /* Ok, now we try to figure out the address of the framebuffer. - * - * Unfortunately, Open Firmware doesn't provide a standard way to do - * so. All we can do is a dodgy heuristic that happens to work in - * practice. On most machines, the "address" property contains what - * we need, though not on Matrox cards found in IBM machines. What I've - * found that appears to give good results is to go through the PCI - * ranges and pick one that is both big enough and if possible encloses - * the "address" property. If none match, we pick the biggest - */ - up = (u32 *)get_property(dp, "linux,bootx-addr", &len); - if (up == NULL) - up = (u32 *)get_property(dp, "address", &len); - if (up && len == sizeof(u32)) - addr_prop = *up; - - for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) - != NULL; i++) { - int match_addrp = 0; - - if (!(flags & IORESOURCE_MEM)) - continue; - if (asize < rsize) - continue; - rstart = of_translate_address(dp, addrp); - if (rstart == OF_BAD_ADDR) - continue; - if (addr_prop && (rstart <= addr_prop) && - ((rstart + asize) >= (addr_prop + rsize))) - match_addrp = 1; - if (match_addrp) { - address = addr_prop; - break; - } - if (rsize > max_size) { - max_size = rsize; - address = OF_BAD_ADDR; - } - - if (address == OF_BAD_ADDR) - address = rstart; - } - if (address == OF_BAD_ADDR && addr_prop) - address = (u64)addr_prop; - if (address != OF_BAD_ADDR) { - /* kludge for valkyrie */ - if (strcmp(dp->name, "valkyrie") == 0) - address += 0x1000; - offb_init_fb(dp->name, dp->full_name, width, height, depth, - pitch, address, dp); - } + if (of_address_to_resource(np, index, &r)) + return 0; + if ((r.start + offset + size) > r.end) + return 0; + return ioremap(r.start + offset, size); } static void __init offb_init_fb(const char *name, const char *full_name, @@ -402,45 +289,39 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { - /* Palette hacks disabled for now */ -#if 0 if (dp && !strncmp(name, "ATY,Rage128", 11)) { - unsigned long regbase = dp->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_r128; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_r128; } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) || !strncmp(name, "ATY,RageM3p12A", 14))) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3A; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_M3A; } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3B; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_M3B; } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { - unsigned long regbase = dp->addrs[1].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_radeon; + par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_radeon; } else if (!strncmp(name, "ATY,", 4)) { unsigned long base = address & 0xff000000UL; par->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (device_is_compatible(dp, "pci1014,b7")) { - unsigned long regbase = dp->addrs[0].address; - par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); - par->cmap_type = cmap_gxt2000; + } else if (dp && device_is_compatible(dp, "pci1014,b7")) { + par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); + if (par->cmap_adr) + par->cmap_type = cmap_gxt2000; } -#endif - fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_STATIC_PSEUDOCOLOR; + fix->visual = (par->cmap_type != cmap_unknown) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; } else - fix->visual = /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR - : */ FB_VISUAL_TRUECOLOR; + fix->visual = FB_VISUAL_TRUECOLOR; var->xoffset = var->yoffset = 0; switch (depth) { @@ -520,5 +401,139 @@ static void __init offb_init_fb(const char *name, const char *full_name, info->node, full_name); } + +static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) +{ + unsigned int len; + int i, width = 640, height = 480, depth = 8, pitch = 640; + unsigned int flags, rsize, addr_prop = 0; + unsigned long max_size = 0; + u64 rstart, address = OF_BAD_ADDR; + u32 *pp, *addrp, *up; + u64 asize; + + pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "depth", &len); + if (pp && len == sizeof(u32)) + depth = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-width", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "width", &len); + if (pp && len == sizeof(u32)) + width = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-height", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "height", &len); + if (pp && len == sizeof(u32)) + height = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "linebytes", &len); + if (pp && len == sizeof(u32)) + pitch = *pp; + else + pitch = width * ((depth + 7) / 8); + + rsize = (unsigned long)pitch * (unsigned long)height; + + /* Ok, now we try to figure out the address of the framebuffer. + * + * Unfortunately, Open Firmware doesn't provide a standard way to do + * so. All we can do is a dodgy heuristic that happens to work in + * practice. On most machines, the "address" property contains what + * we need, though not on Matrox cards found in IBM machines. What I've + * found that appears to give good results is to go through the PCI + * ranges and pick one that is both big enough and if possible encloses + * the "address" property. If none match, we pick the biggest + */ + up = (u32 *)get_property(dp, "linux,bootx-addr", &len); + if (up == NULL) + up = (u32 *)get_property(dp, "address", &len); + if (up && len == sizeof(u32)) + addr_prop = *up; + + /* Hack for when BootX is passing us */ + if (no_real_node) + goto skip_addr; + + for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) + != NULL; i++) { + int match_addrp = 0; + + if (!(flags & IORESOURCE_MEM)) + continue; + if (asize < rsize) + continue; + rstart = of_translate_address(dp, addrp); + if (rstart == OF_BAD_ADDR) + continue; + if (addr_prop && (rstart <= addr_prop) && + ((rstart + asize) >= (addr_prop + rsize))) + match_addrp = 1; + if (match_addrp) { + address = addr_prop; + break; + } + if (rsize > max_size) { + max_size = rsize; + address = OF_BAD_ADDR; + } + + if (address == OF_BAD_ADDR) + address = rstart; + } + skip_addr: + if (address == OF_BAD_ADDR && addr_prop) + address = (u64)addr_prop; + if (address != OF_BAD_ADDR) { + /* kludge for valkyrie */ + if (strcmp(dp->name, "valkyrie") == 0) + address += 0x1000; + offb_init_fb(no_real_node ? "bootx" : dp->name, + no_real_node ? "display" : dp->full_name, + width, height, depth, pitch, address, + no_real_node ? dp : NULL); + } +} + +static int __init offb_init(void) +{ + struct device_node *dp = NULL, *boot_disp = NULL; + + if (fb_get_options("offb", NULL)) + return -ENODEV; + + /* Check if we have a MacOS display without a node spec */ + if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { + /* The old code tried to work out which node was the MacOS + * display based on the address. I'm dropping that since the + * lack of a node spec only happens with old BootX versions + * (users can update) and with this code, they'll still get + * a display (just not the palette hacks). + */ + offb_init_nodriver(of_chosen, 1); + } + + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + get_property(dp, "linux,boot-display", NULL)) { + boot_disp = dp; + offb_init_nodriver(dp, 0); + } + } + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + dp != boot_disp) + offb_init_nodriver(dp, 0); + } + + return 0; +} + + module_init(offb_init); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/video/riva/fbdev.c b/trunk/drivers/video/riva/fbdev.c index 33dddbae5420..76fc9d355eb7 100644 --- a/trunk/drivers/video/riva/fbdev.c +++ b/trunk/drivers/video/riva/fbdev.c @@ -2132,6 +2132,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, fb_destroy_modedb(info->monspecs.modedb); info->monspecs.modedb = NULL; + + pci_set_drvdata(pd, info); + riva_bl_init(info->par); ret = register_framebuffer(info); if (ret < 0) { printk(KERN_ERR PFX @@ -2139,8 +2142,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd, goto err_iounmap_screen_base; } - pci_set_drvdata(pd, info); - printk(KERN_INFO PFX "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n", info->fix.id, @@ -2148,8 +2149,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->fix.smem_len / (1024 * 1024), info->fix.smem_start); - riva_bl_init(info->par); - NVTRACE_LEAVE(); return 0; diff --git a/trunk/fs/9p/conv.c b/trunk/fs/9p/conv.c index 1e898144eb7c..56d88c1a09c5 100644 --- a/trunk/fs/9p/conv.c +++ b/trunk/fs/9p/conv.c @@ -673,8 +673,10 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, struct cbuf *bufp = &buffer; size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ - if (extended && extension!=NULL) - size += 2 + strlen(extension); /* extension[s] */ + if (extended) { + size += 2 + /* extension[s] */ + (extension == NULL ? 0 : strlen(extension)); + } fc = v9fs_create_common(bufp, size, TCREATE); if (IS_ERR(fc)) diff --git a/trunk/fs/9p/vfs_inode.c b/trunk/fs/9p/vfs_inode.c index 2f580a197b8d..eae50c9d6dc4 100644 --- a/trunk/fs/9p/vfs_inode.c +++ b/trunk/fs/9p/vfs_inode.c @@ -434,11 +434,11 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) result = v9fs_t_remove(v9ses, fid, &fcall); if (result < 0) { PRINT_FCALL_ERROR("remove fails", fcall); - } else { - v9fs_put_idpool(fid, &v9ses->fidpool); - v9fs_fid_destroy(v9fid); } + v9fs_put_idpool(fid, &v9ses->fidpool); + v9fs_fid_destroy(v9fid); + kfree(fcall); return result; } diff --git a/trunk/fs/adfs/super.c b/trunk/fs/adfs/super.c index ba1c88af49fe..82011019494c 100644 --- a/trunk/fs/adfs/super.c +++ b/trunk/fs/adfs/super.c @@ -308,7 +308,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di if (adfs_checkmap(sb, dm)) return dm; - adfs_error(sb, NULL, "map corrupted"); + adfs_error(sb, "map corrupted"); error_free: while (--zone >= 0) diff --git a/trunk/fs/befs/linuxvfs.c b/trunk/fs/befs/linuxvfs.c index fcaeead9696b..50cfca5c7efd 100644 --- a/trunk/fs/befs/linuxvfs.c +++ b/trunk/fs/befs/linuxvfs.c @@ -512,7 +512,11 @@ befs_utf2nls(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - int maxlen = in_len; /* The utf8->nls conversion can't make more chars */ + /* The utf8->nls conversion won't make the final nls string bigger + * than the utf one, but if the string is pure ascii they'll have the + * same width and an extra char is needed to save the additional \0 + */ + int maxlen = in_len + 1; befs_debug(sb, "---> utf2nls()"); @@ -588,7 +592,10 @@ befs_nls2utf(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - int maxlen = 3 * in_len; + /* There're nls characters that will translate to 3-chars-wide UTF-8 + * characters, a additional byte is needed to save the final \0 + * in special cases */ + int maxlen = (3 * in_len) + 1; befs_debug(sb, "---> nls2utf()\n"); diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 3660dcb97591..71649ef9b658 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -470,13 +470,18 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) pass does the actual I/O. */ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { + struct address_space *mapping = bdev->bd_inode->i_mapping; + + if (mapping->nrpages == 0) + return; + invalidate_bh_lrus(); /* * FIXME: what about destroy_dirty_buffers? * We really want to use invalidate_inode_pages2() for * that, but not until that's cleaned up. */ - invalidate_inode_pages(bdev->bd_inode->i_mapping); + invalidate_inode_pages(mapping); } /* diff --git a/trunk/fs/coda/file.c b/trunk/fs/coda/file.c index cc66c681bd11..dbfbcfa5b3c0 100644 --- a/trunk/fs/coda/file.c +++ b/trunk/fs/coda/file.c @@ -136,10 +136,8 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) coda_vfs_stat.open++; cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL); - if (!cfi) { - unlock_kernel(); + if (!cfi) return -ENOMEM; - } lock_kernel(); diff --git a/trunk/fs/efs/symlink.c b/trunk/fs/efs/symlink.c index e249cf733a6b..1d30d2ff440f 100644 --- a/trunk/fs/efs/symlink.c +++ b/trunk/fs/efs/symlink.c @@ -22,7 +22,7 @@ static int efs_symlink_readpage(struct file *file, struct page *page) err = -ENAMETOOLONG; if (size > 2 * EFS_BLOCKSIZE) - goto fail; + goto fail_notlocked; lock_kernel(); /* read first 512 bytes of link target */ @@ -47,6 +47,7 @@ static int efs_symlink_readpage(struct file *file, struct page *page) return 0; fail: unlock_kernel(); +fail_notlocked: SetPageError(page); kunmap(page); unlock_page(page); diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index f804d5e9d60c..c5ee9f0691e3 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -1158,7 +1158,7 @@ static int ext3_prepare_write(struct file *file, struct page *page, ret = PTR_ERR(handle); goto out; } - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_prepare_write(page, from, to, ext3_get_block); else ret = block_prepare_write(page, from, to, ext3_get_block); @@ -1244,7 +1244,7 @@ static int ext3_writeback_commit_write(struct file *file, struct page *page, if (new_i_size > EXT3_I(inode)->i_disksize) EXT3_I(inode)->i_disksize = new_i_size; - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_commit_write(file, page, from, to); else ret = generic_commit_write(file, page, from, to); @@ -1494,7 +1494,7 @@ static int ext3_writeback_writepage(struct page *page, goto out_fail; } - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_writepage(page, ext3_get_block, wbc); else ret = block_write_full_page(page, ext3_get_block, wbc); @@ -2402,14 +2402,15 @@ static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb, struct buffer_head *bh; struct ext3_group_desc * gdp; - - if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO && - ino != EXT3_RESIZE_INO && ino < EXT3_FIRST_INO(sb)) || - ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) { - ext3_error(sb, "ext3_get_inode_block", - "bad inode number: %lu", ino); + if (!ext3_valid_inum(sb, ino)) { + /* + * This error is already checked for in namei.c unless we are + * looking at an NFS filehandle, in which case no error + * report is needed + */ return 0; } + block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); if (block_group >= EXT3_SB(sb)->s_groups_count) { ext3_error(sb,"ext3_get_inode_block","group >= groups count"); diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index d9176dba3698..2aa7101b27cd 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -1000,7 +1000,12 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (bh) { unsigned long ino = le32_to_cpu(de->inode); brelse (bh); - inode = iget(dir->i_sb, ino); + if (!ext3_valid_inum(dir->i_sb, ino)) { + ext3_error(dir->i_sb, "ext3_lookup", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); @@ -1028,7 +1033,13 @@ struct dentry *ext3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); brelse(bh); - inode = iget(child->d_inode->i_sb, ino); + + if (!ext3_valid_inum(child->d_inode->i_sb, ino)) { + ext3_error(child->d_inode->i_sb, "ext3_get_parent", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(child->d_inode->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); diff --git a/trunk/fs/freevxfs/vxfs_lookup.c b/trunk/fs/freevxfs/vxfs_lookup.c index 29cce456c7ce..43886fa00a2a 100644 --- a/trunk/fs/freevxfs/vxfs_lookup.c +++ b/trunk/fs/freevxfs/vxfs_lookup.c @@ -246,6 +246,8 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) u_long page, npages, block, pblocks, nblocks, offset; loff_t pos; + lock_kernel(); + switch ((long)fp->f_pos) { case 0: if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) diff --git a/trunk/fs/fuse/control.c b/trunk/fs/fuse/control.c index a3bce3a77253..46fe60b2da23 100644 --- a/trunk/fs/fuse/control.c +++ b/trunk/fs/fuse/control.c @@ -105,7 +105,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, /* * Add a connection to the control filesystem (if it exists). Caller - * must host fuse_mutex + * must hold fuse_mutex */ int fuse_ctl_add_conn(struct fuse_conn *fc) { @@ -139,7 +139,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc) /* * Remove a connection from the control filesystem (if it exists). - * Caller must host fuse_mutex + * Caller must hold fuse_mutex */ void fuse_ctl_remove_conn(struct fuse_conn *fc) { diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 72a74cde6de8..409ce6a7cca4 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -14,6 +14,33 @@ #include #include +#if BITS_PER_LONG >= 64 +static inline void fuse_dentry_settime(struct dentry *entry, u64 time) +{ + entry->d_time = time; +} + +static inline u64 fuse_dentry_time(struct dentry *entry) +{ + return entry->d_time; +} +#else +/* + * On 32 bit archs store the high 32 bits of time in d_fsdata + */ +static void fuse_dentry_settime(struct dentry *entry, u64 time) +{ + entry->d_time = time; + entry->d_fsdata = (void *) (unsigned long) (time >> 32); +} + +static u64 fuse_dentry_time(struct dentry *entry) +{ + return (u64) entry->d_time + + ((u64) (unsigned long) entry->d_fsdata << 32); +} +#endif + /* * FUSE caches dentries and attributes with separate timeout. The * time in jiffies until the dentry/attributes are valid is stored in @@ -23,10 +50,13 @@ /* * Calculate the time in jiffies until a dentry/attributes are valid */ -static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) +static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) { - struct timespec ts = {sec, nsec}; - return jiffies + timespec_to_jiffies(&ts); + if (sec || nsec) { + struct timespec ts = {sec, nsec}; + return get_jiffies_64() + timespec_to_jiffies(&ts); + } else + return 0; } /* @@ -35,7 +65,8 @@ static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) */ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) { - entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec); + fuse_dentry_settime(entry, + time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); if (entry->d_inode) get_fuse_inode(entry->d_inode)->i_time = time_to_jiffies(o->attr_valid, o->attr_valid_nsec); @@ -47,7 +78,7 @@ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) */ void fuse_invalidate_attr(struct inode *inode) { - get_fuse_inode(inode)->i_time = jiffies - 1; + get_fuse_inode(inode)->i_time = 0; } /* @@ -60,7 +91,7 @@ void fuse_invalidate_attr(struct inode *inode) */ static void fuse_invalidate_entry_cache(struct dentry *entry) { - entry->d_time = jiffies - 1; + fuse_dentry_settime(entry, 0); } /* @@ -102,7 +133,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) if (inode && is_bad_inode(inode)) return 0; - else if (time_after(jiffies, entry->d_time)) { + else if (fuse_dentry_time(entry) < get_jiffies_64()) { int err; struct fuse_entry_out outarg; struct fuse_conn *fc; @@ -666,7 +697,7 @@ static int fuse_revalidate(struct dentry *entry) if (!fuse_allow_task(fc, current)) return -EACCES; if (get_node_id(inode) != FUSE_ROOT_ID && - time_before_eq(jiffies, fi->i_time)) + fi->i_time >= get_jiffies_64()) return 0; return fuse_do_getattr(inode); diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index 63614ed16336..5c4fcd1dbf59 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -395,14 +395,16 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, struct fuse_readpages_data data; int err; + err = -EIO; if (is_bad_inode(inode)) - return -EIO; + goto clean_pages_up; data.file = file; data.inode = inode; data.req = fuse_get_req(fc); + err = PTR_ERR(data.req); if (IS_ERR(data.req)) - return PTR_ERR(data.req); + goto clean_pages_up; err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { @@ -412,6 +414,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, fuse_put_request(fc, data.req); } return err; + +clean_pages_up: + put_pages_list(pages); + return err; } static size_t fuse_send_write(struct fuse_req *req, struct file *file, diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index 0dbf96621841..69c7750d55b8 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -59,7 +59,7 @@ struct fuse_inode { struct fuse_req *forget_req; /** Time in jiffies until the file attributes are valid */ - unsigned long i_time; + u64 i_time; }; /** FUSE specific file data */ diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index dcaaabd3b9c4..7d25092262ae 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -51,7 +51,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) return NULL; fi = get_fuse_inode(inode); - fi->i_time = jiffies - 1; + fi->i_time = 0; fi->nodeid = 0; fi->nlookup = 0; fi->forget_req = fuse_request_alloc(); diff --git a/trunk/fs/inotify_user.c b/trunk/fs/inotify_user.c index f2386442adee..017cb0f134d6 100644 --- a/trunk/fs/inotify_user.c +++ b/trunk/fs/inotify_user.c @@ -187,7 +187,7 @@ static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, { struct inotify_kernel_event *kevent; - kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL); + kevent = kmem_cache_alloc(event_cachep, GFP_NOFS); if (unlikely(!kevent)) return NULL; diff --git a/trunk/fs/jfs/inode.c b/trunk/fs/jfs/inode.c index 43e3f566aad6..a223cf4faa9b 100644 --- a/trunk/fs/jfs/inode.c +++ b/trunk/fs/jfs/inode.c @@ -168,16 +168,15 @@ void jfs_dirty_inode(struct inode *inode) set_cflag(COMMIT_Dirty, inode); } -static int -jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, - struct buffer_head *bh_result, int create) +int jfs_get_block(struct inode *ip, sector_t lblock, + struct buffer_head *bh_result, int create) { s64 lblock64 = lblock; int rc = 0; xad_t xad; s64 xaddr; int xflag; - s32 xlen = max_blocks; + s32 xlen = bh_result->b_size >> ip->i_blkbits; /* * Take appropriate lock on inode @@ -188,7 +187,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, IREAD_LOCK(ip); if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && - (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) && + (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && xaddr) { if (xflag & XAD_NOTRECORDED) { if (!create) @@ -255,13 +254,6 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, return rc; } -static int jfs_get_block(struct inode *ip, sector_t lblock, - struct buffer_head *bh_result, int create) -{ - return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits, - bh_result, create); -} - static int jfs_writepage(struct page *page, struct writeback_control *wbc) { return nobh_writepage(page, jfs_get_block, wbc); diff --git a/trunk/fs/jfs/jfs_inode.h b/trunk/fs/jfs/jfs_inode.h index b5c7da6190dc..1fc48df670c8 100644 --- a/trunk/fs/jfs/jfs_inode.h +++ b/trunk/fs/jfs/jfs_inode.h @@ -32,6 +32,7 @@ extern void jfs_truncate_nolock(struct inode *, loff_t); extern void jfs_free_zero_link(struct inode *); extern struct dentry *jfs_get_parent(struct dentry *dentry); extern void jfs_set_inode_flags(struct inode *); +extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern const struct address_space_operations jfs_aops; extern struct inode_operations jfs_dir_inode_operations; diff --git a/trunk/fs/jfs/super.c b/trunk/fs/jfs/super.c index 4f6cfebc82db..143bcd1d5eaa 100644 --- a/trunk/fs/jfs/super.c +++ b/trunk/fs/jfs/super.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -298,7 +299,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, break; } -#if defined(CONFIG_QUOTA) +#ifdef CONFIG_QUOTA case Opt_quota: case Opt_usrquota: *flag |= JFS_USRQUOTA; @@ -597,7 +598,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) if (sbi->flag & JFS_NOINTEGRITY) seq_puts(seq, ",nointegrity"); -#if defined(CONFIG_QUOTA) +#ifdef CONFIG_QUOTA if (sbi->flag & JFS_USRQUOTA) seq_puts(seq, ",usrquota"); @@ -608,6 +609,113 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) return 0; } +#ifdef CONFIG_QUOTA + +/* Read data from quotafile - avoid pagecache and such because we cannot afford + * acquiring the locks... As quota files are never truncated and quota code + * itself serializes the operations (and noone else should touch the files) + * we don't have to be afraid of races */ +static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, + size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + sector_t blk = off >> sb->s_blocksize_bits; + int err = 0; + int offset = off & (sb->s_blocksize - 1); + int tocopy; + size_t toread; + struct buffer_head tmp_bh; + struct buffer_head *bh; + loff_t i_size = i_size_read(inode); + + if (off > i_size) + return 0; + if (off+len > i_size) + len = i_size-off; + toread = len; + while (toread > 0) { + tocopy = sb->s_blocksize - offset < toread ? + sb->s_blocksize - offset : toread; + + tmp_bh.b_state = 0; + tmp_bh.b_size = 1 << inode->i_blkbits; + err = jfs_get_block(inode, blk, &tmp_bh, 0); + if (err) + return err; + if (!buffer_mapped(&tmp_bh)) /* A hole? */ + memset(data, 0, tocopy); + else { + bh = sb_bread(sb, tmp_bh.b_blocknr); + if (!bh) + return -EIO; + memcpy(data, bh->b_data+offset, tocopy); + brelse(bh); + } + offset = 0; + toread -= tocopy; + data += tocopy; + blk++; + } + return len; +} + +/* Write to quotafile */ +static ssize_t jfs_quota_write(struct super_block *sb, int type, + const char *data, size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + sector_t blk = off >> sb->s_blocksize_bits; + int err = 0; + int offset = off & (sb->s_blocksize - 1); + int tocopy; + size_t towrite = len; + struct buffer_head tmp_bh; + struct buffer_head *bh; + + mutex_lock(&inode->i_mutex); + while (towrite > 0) { + tocopy = sb->s_blocksize - offset < towrite ? + sb->s_blocksize - offset : towrite; + + tmp_bh.b_state = 0; + tmp_bh.b_size = 1 << inode->i_blkbits; + err = jfs_get_block(inode, blk, &tmp_bh, 1); + if (err) + goto out; + if (offset || tocopy != sb->s_blocksize) + bh = sb_bread(sb, tmp_bh.b_blocknr); + else + bh = sb_getblk(sb, tmp_bh.b_blocknr); + if (!bh) { + err = -EIO; + goto out; + } + lock_buffer(bh); + memcpy(bh->b_data+offset, data, tocopy); + flush_dcache_page(bh->b_page); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + brelse(bh); + offset = 0; + towrite -= tocopy; + data += tocopy; + blk++; + } +out: + if (len == towrite) + return err; + if (inode->i_size < off+len-towrite) + i_size_write(inode, off+len-towrite); + inode->i_version++; + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + mutex_unlock(&inode->i_mutex); + return len - towrite; +} + +#endif + static struct super_operations jfs_super_operations = { .alloc_inode = jfs_alloc_inode, .destroy_inode = jfs_destroy_inode, @@ -621,7 +729,11 @@ static struct super_operations jfs_super_operations = { .unlockfs = jfs_unlockfs, .statfs = jfs_statfs, .remount_fs = jfs_remount, - .show_options = jfs_show_options + .show_options = jfs_show_options, +#ifdef CONFIG_QUOTA + .quota_read = jfs_quota_read, + .quota_write = jfs_quota_write, +#endif }; static struct export_operations jfs_export_operations = { diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index baf5ae513481..c9d419703cf3 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -638,9 +638,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) if (task->tk_status < 0) { /* RPC error: Re-insert for retransmission */ timeout = 10 * HZ; - } else if (block->b_done) { - /* Block already removed, kill it for real */ - timeout = 0; } else { /* Call was successful, now wait for client callback */ timeout = 60 * HZ; @@ -709,13 +706,10 @@ nlmsvc_retry_blocked(void) break; if (time_after(block->b_when,jiffies)) break; - dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", - block, block->b_when, block->b_done); + dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", + block, block->b_when); kref_get(&block->b_count); - if (block->b_done) - nlmsvc_unlink_block(block); - else - nlmsvc_grant_blocked(block); + nlmsvc_grant_blocked(block); nlmsvc_release_block(block); } diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index b0b41a64e10b..d7c53392cac1 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -1421,8 +1421,9 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) if (!leases_enable) goto out; - error = lease_alloc(filp, arg, &fl); - if (error) + error = -ENOMEM; + fl = locks_alloc_lock(); + if (fl == NULL) goto out; locks_copy_lock(fl, lease); @@ -1430,6 +1431,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) locks_insert_lock(before, fl); *flp = fl; + error = 0; out: return error; } diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index e01070d7bf58..55a131230f94 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -159,7 +159,7 @@ char * getname(const char __user * filename) #ifdef CONFIG_AUDITSYSCALL void putname(const char *name) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) audit_putname(name); else __putname(name); @@ -1125,7 +1125,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, retval = link_path_walk(name, nd); out: if (likely(retval == 0)) { - if (unlikely(current->audit_context && nd && nd->dentry && + if (unlikely(!audit_dummy_context() && nd && nd->dentry && nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode); } @@ -1357,7 +1357,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) return -ENOENT; BUG_ON(victim->d_parent->d_inode != dir); - audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino); + audit_inode_child(victim->d_name.name, victim->d_inode, dir); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); if (error) @@ -1659,6 +1659,7 @@ int open_namei(int dfd, const char *pathname, int flag, * It already exists. */ mutex_unlock(&dir->d_inode->i_mutex); + audit_inode_update(path.dentry->d_inode); error = -EEXIST; if (flag & O_EXCL) @@ -1669,6 +1670,7 @@ int open_namei(int dfd, const char *pathname, int flag, if (flag & O_NOFOLLOW) goto exit_dput; } + error = -ENOENT; if (!path.dentry->d_inode) goto exit_dput; diff --git a/trunk/fs/nfs/namespace.c b/trunk/fs/nfs/namespace.c index 19b98ca468eb..86b3169c8cac 100644 --- a/trunk/fs/nfs/namespace.c +++ b/trunk/fs/nfs/namespace.c @@ -51,7 +51,7 @@ char *nfs_path(const char *base, const struct dentry *dentry, namelen = dentry->d_name.len; buflen -= namelen + 1; if (buflen < 0) - goto Elong; + goto Elong_unlock; end -= namelen; memcpy(end, dentry->d_name.name, namelen); *--end = '/'; @@ -68,6 +68,8 @@ char *nfs_path(const char *base, const struct dentry *dentry, end -= namelen; memcpy(end, base, namelen); return end; +Elong_unlock: + spin_unlock(&dcache_lock); Elong: return ERR_PTR(-ENAMETOOLONG); } diff --git a/trunk/fs/nfs/read.c b/trunk/fs/nfs/read.c index 52bf634260a1..65c0c5b32351 100644 --- a/trunk/fs/nfs/read.c +++ b/trunk/fs/nfs/read.c @@ -63,7 +63,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) return p; } -void nfs_readdata_free(struct nfs_read_data *p) +static void nfs_readdata_free(struct nfs_read_data *p) { if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 86bac6a5008e..50774991f8d5 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -137,7 +137,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) return p; } -void nfs_writedata_free(struct nfs_write_data *p) +static void nfs_writedata_free(struct nfs_write_data *p) { if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); diff --git a/trunk/fs/nfsd/nfsfh.c b/trunk/fs/nfsd/nfsfh.c index ecc439d2565f..501d83884530 100644 --- a/trunk/fs/nfsd/nfsfh.c +++ b/trunk/fs/nfsd/nfsfh.c @@ -187,6 +187,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) goto out; } + /* Set user creds for this exportpoint */ + error = nfserrno(nfsd_setuser(rqstp, exp)); + if (error) + goto out; + /* * Look up the dentry using the NFS file handle. */ @@ -241,16 +246,17 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) dprintk("nfsd: fh_verify - just checking\n"); dentry = fhp->fh_dentry; exp = fhp->fh_export; + /* Set user creds for this exportpoint; necessary even + * in the "just checking" case because this may be a + * filehandle that was created by fh_compose, and that + * is about to be used in another nfsv4 compound + * operation */ + error = nfserrno(nfsd_setuser(rqstp, exp)); + if (error) + goto out; } cache_get(&exp->h); - /* Set user creds for this exportpoint; necessary even in the "just - * checking" case because this may be a filehandle that was created by - * fh_compose, and that is about to be used in another nfsv4 compound - * operation */ - error = nfserrno(nfsd_setuser(rqstp, exp)); - if (error) - goto out; error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); if (error) diff --git a/trunk/fs/ocfs2/dlm/dlmmaster.c b/trunk/fs/ocfs2/dlm/dlmmaster.c index 1b8346dd0572..9503240ef0e5 100644 --- a/trunk/fs/ocfs2/dlm/dlmmaster.c +++ b/trunk/fs/ocfs2/dlm/dlmmaster.c @@ -2375,7 +2375,6 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, mlog(0, "returning %d\n", ret); return ret; } -EXPORT_SYMBOL_GPL(dlm_migrate_lockres); int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock) { diff --git a/trunk/fs/ocfs2/dlm/dlmunlock.c b/trunk/fs/ocfs2/dlm/dlmunlock.c index b0c3134f4f70..37be4b2e0d4a 100644 --- a/trunk/fs/ocfs2/dlm/dlmunlock.c +++ b/trunk/fs/ocfs2/dlm/dlmunlock.c @@ -155,7 +155,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, else status = dlm_get_unlock_actions(dlm, res, lock, lksb, &actions); - if (status != DLM_NORMAL) + if (status != DLM_NORMAL && (status != DLM_CANCELGRANT || !master_node)) goto leave; /* By now this has been masked out of cancel requests. */ @@ -183,8 +183,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, spin_lock(&lock->spinlock); /* if the master told us the lock was already granted, * let the ast handle all of these actions */ - if (status == DLM_NORMAL && - lksb->status == DLM_CANCELGRANT) { + if (status == DLM_CANCELGRANT) { actions &= ~(DLM_UNLOCK_REMOVE_LOCK| DLM_UNLOCK_REGRANT_LOCK| DLM_UNLOCK_CLEAR_CONVERT_TYPE); @@ -349,14 +348,9 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, vec, veclen, owner, &status); if (tmpret >= 0) { // successfully sent and received - if (status == DLM_CANCELGRANT) - ret = DLM_NORMAL; - else if (status == DLM_FORWARD) { + if (status == DLM_FORWARD) mlog(0, "master was in-progress. retry\n"); - ret = DLM_FORWARD; - } else - ret = status; - lksb->status = status; + ret = status; } else { mlog_errno(tmpret); if (dlm_is_host_down(tmpret)) { @@ -372,7 +366,6 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, /* something bad. this will BUG in ocfs2 */ ret = dlm_err_to_dlm_status(tmpret); } - lksb->status = ret; } return ret; @@ -483,6 +476,10 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data) /* lock was found on queue */ lksb = lock->lksb; + if (flags & (LKM_VALBLK|LKM_PUT_LVB) && + lock->ml.type != LKM_EXMODE) + flags &= ~(LKM_VALBLK|LKM_PUT_LVB); + /* unlockast only called on originating node */ if (flags & LKM_PUT_LVB) { lksb->flags |= DLM_LKSB_PUT_LVB; @@ -507,11 +504,8 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data) "cookie=%u:%llu\n", dlm_get_lock_cookie_node(unlock->cookie), dlm_get_lock_cookie_seq(unlock->cookie)); - else { - /* send the lksb->status back to the other node */ - status = lksb->status; + else dlm_lock_put(lock); - } leave: if (res) @@ -533,26 +527,22 @@ static enum dlm_status dlm_get_cancel_actions(struct dlm_ctxt *dlm, if (dlm_lock_on_list(&res->blocked, lock)) { /* cancel this outright */ - lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_CALL_AST | DLM_UNLOCK_REMOVE_LOCK); } else if (dlm_lock_on_list(&res->converting, lock)) { /* cancel the request, put back on granted */ - lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_CALL_AST | DLM_UNLOCK_REMOVE_LOCK | DLM_UNLOCK_REGRANT_LOCK | DLM_UNLOCK_CLEAR_CONVERT_TYPE); } else if (dlm_lock_on_list(&res->granted, lock)) { - /* too late, already granted. DLM_CANCELGRANT */ - lksb->status = DLM_CANCELGRANT; - status = DLM_NORMAL; + /* too late, already granted. */ + status = DLM_CANCELGRANT; *actions = DLM_UNLOCK_CALL_AST; } else { mlog(ML_ERROR, "lock to cancel is not on any list!\n"); - lksb->status = DLM_IVLOCKID; status = DLM_IVLOCKID; *actions = 0; } @@ -569,13 +559,11 @@ static enum dlm_status dlm_get_unlock_actions(struct dlm_ctxt *dlm, /* unlock request */ if (!dlm_lock_on_list(&res->granted, lock)) { - lksb->status = DLM_DENIED; status = DLM_DENIED; dlm_error(status); *actions = 0; } else { /* unlock granted lock */ - lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_FREE_LOCK | DLM_UNLOCK_CALL_AST | @@ -632,6 +620,8 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, spin_lock(&res->spinlock); is_master = (res->owner == dlm->node_num); + if (flags & LKM_VALBLK && lock->ml.type != LKM_EXMODE) + flags &= ~LKM_VALBLK; spin_unlock(&res->spinlock); if (is_master) { @@ -665,7 +655,7 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, } if (call_ast) { - mlog(0, "calling unlockast(%p, %d)\n", data, lksb->status); + mlog(0, "calling unlockast(%p, %d)\n", data, status); if (is_master) { /* it is possible that there is one last bast * pending. make sure it is flushed, then @@ -677,9 +667,12 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, wait_event(dlm->ast_wq, dlm_lock_basts_flushed(dlm, lock)); } - (*unlockast)(data, lksb->status); + (*unlockast)(data, status); } + if (status == DLM_CANCELGRANT) + status = DLM_NORMAL; + if (status == DLM_NORMAL) { mlog(0, "kicking the thread\n"); dlm_kick_thread(dlm, res); diff --git a/trunk/fs/ocfs2/localalloc.c b/trunk/fs/ocfs2/localalloc.c index 0d1973ea32b0..1f17a4d08287 100644 --- a/trunk/fs/ocfs2/localalloc.c +++ b/trunk/fs/ocfs2/localalloc.c @@ -840,6 +840,12 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, mlog(0, "Allocating %u clusters for a new window.\n", ocfs2_local_alloc_window_bits(osb)); + + /* Instruct the allocation code to try the most recently used + * cluster group. We'll re-record the group used this pass + * below. */ + ac->ac_last_group = osb->la_last_gd; + /* we used the generic suballoc reserve function, but we set * everything up nicely, so there's no reason why we can't use * the more specific cluster api to claim bits. */ @@ -852,6 +858,8 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, goto bail; } + osb->la_last_gd = ac->ac_last_group; + la->la_bm_off = cpu_to_le32(cluster_off); alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count); /* just in case... In the future when we find space ourselves, diff --git a/trunk/fs/ocfs2/ocfs2.h b/trunk/fs/ocfs2/ocfs2.h index cd4a6f253d13..0462a7f4e21b 100644 --- a/trunk/fs/ocfs2/ocfs2.h +++ b/trunk/fs/ocfs2/ocfs2.h @@ -197,7 +197,6 @@ struct ocfs2_super struct ocfs2_node_map recovery_map; struct ocfs2_node_map umount_map; - u32 num_clusters; u64 root_blkno; u64 system_dir_blkno; u64 bitmap_blkno; @@ -237,6 +236,7 @@ struct ocfs2_super enum ocfs2_local_alloc_state local_alloc_state; struct buffer_head *local_alloc_bh; + u64 la_last_gd; /* Next two fields are for local node slot recovery during * mount. */ diff --git a/trunk/fs/ocfs2/suballoc.c b/trunk/fs/ocfs2/suballoc.c index 195523090c87..9d91e66f51a9 100644 --- a/trunk/fs/ocfs2/suballoc.c +++ b/trunk/fs/ocfs2/suballoc.c @@ -70,12 +70,6 @@ static int ocfs2_block_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u16 *bit_off, u16 *bits_found); -static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, - u32 bits_wanted, - u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 *bg_blkno); static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, u32 bits_wanted, @@ -85,11 +79,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, u64 *bg_blkno); static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr); -static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, - struct buffer_head *bg_bh, - unsigned int bits_wanted, - u16 *bit_off, - u16 *bits_found); static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, @@ -143,6 +132,64 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc); } +/* somewhat more expensive than our other checks, so use sparingly. */ +static int ocfs2_check_group_descriptor(struct super_block *sb, + struct ocfs2_dinode *di, + struct ocfs2_group_desc *gd) +{ + unsigned int max_bits; + + if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { + OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd); + return -EIO; + } + + if (di->i_blkno != gd->bg_parent_dinode) { + ocfs2_error(sb, "Group descriptor # %llu has bad parent " + "pointer (%llu, expected %llu)", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + (unsigned long long)le64_to_cpu(gd->bg_parent_dinode), + (unsigned long long)le64_to_cpu(di->i_blkno)); + return -EIO; + } + + max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc); + if (le16_to_cpu(gd->bg_bits) > max_bits) { + ocfs2_error(sb, "Group descriptor # %llu has bit count of %u", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits)); + return -EIO; + } + + if (le16_to_cpu(gd->bg_chain) >= + le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) { + ocfs2_error(sb, "Group descriptor # %llu has bad chain %u", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_chain)); + return -EIO; + } + + if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) { + ocfs2_error(sb, "Group descriptor # %llu has bit count %u but " + "claims that %u are free", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits), + le16_to_cpu(gd->bg_free_bits_count)); + return -EIO; + } + + if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) { + ocfs2_error(sb, "Group descriptor # %llu has bit count %u but " + "max bitmap bits of %u", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits), + 8 * le16_to_cpu(gd->bg_size)); + return -EIO; + } + + return 0; +} + static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, @@ -663,6 +710,7 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, struct buffer_head *bg_bh, unsigned int bits_wanted, + unsigned int total_bits, u16 *bit_off, u16 *bits_found) { @@ -679,10 +727,8 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, found = start = best_offset = best_size = 0; bitmap = bg->bg_bitmap; - while((offset = ocfs2_find_next_zero_bit(bitmap, - le16_to_cpu(bg->bg_bits), - start)) != -1) { - if (offset == le16_to_cpu(bg->bg_bits)) + while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) { + if (offset == total_bits) break; if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) { @@ -911,14 +957,35 @@ static int ocfs2_cluster_group_search(struct inode *inode, { int search = -ENOSPC; int ret; - struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data; + struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data; u16 tmp_off, tmp_found; + unsigned int max_bits, gd_cluster_off; BUG_ON(!ocfs2_is_cluster_bitmap(inode)); - if (bg->bg_free_bits_count) { + if (gd->bg_free_bits_count) { + max_bits = le16_to_cpu(gd->bg_bits); + + /* Tail groups in cluster bitmaps which aren't cpg + * aligned are prone to partial extention by a failed + * fs resize. If the file system resize never got to + * update the dinode cluster count, then we don't want + * to trust any clusters past it, regardless of what + * the group descriptor says. */ + gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb, + le64_to_cpu(gd->bg_blkno)); + if ((gd_cluster_off + max_bits) > + OCFS2_I(inode)->ip_clusters) { + max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off; + mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n", + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits), + OCFS2_I(inode)->ip_clusters, max_bits); + } + ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, + max_bits, &tmp_off, &tmp_found); if (ret) return ret; @@ -951,17 +1018,109 @@ static int ocfs2_block_group_search(struct inode *inode, if (bg->bg_free_bits_count) ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, + le16_to_cpu(bg->bg_bits), bit_off, bits_found); return ret; } +static int ocfs2_alloc_dinode_update_counts(struct inode *inode, + struct ocfs2_journal_handle *handle, + struct buffer_head *di_bh, + u32 num_bits, + u16 chain) +{ + int ret; + u32 tmp_used; + struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; + struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain; + + ret = ocfs2_journal_access(handle, inode, di_bh, + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + + tmp_used = le32_to_cpu(di->id1.bitmap1.i_used); + di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used); + le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits); + + ret = ocfs2_journal_dirty(handle, di_bh); + if (ret < 0) + mlog_errno(ret); + +out: + return ret; +} + +static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, + u32 bits_wanted, + u32 min_bits, + u16 *bit_off, + unsigned int *num_bits, + u64 gd_blkno, + u16 *bits_left) +{ + int ret; + u16 found; + struct buffer_head *group_bh = NULL; + struct ocfs2_group_desc *gd; + struct inode *alloc_inode = ac->ac_inode; + struct ocfs2_journal_handle *handle = ac->ac_handle; + + ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno, + &group_bh, OCFS2_BH_CACHED, alloc_inode); + if (ret < 0) { + mlog_errno(ret); + return ret; + } + + gd = (struct ocfs2_group_desc *) group_bh->b_data; + if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { + OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd); + ret = -EIO; + goto out; + } + + ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits, + bit_off, &found); + if (ret < 0) { + if (ret != -ENOSPC) + mlog_errno(ret); + goto out; + } + + *num_bits = found; + + ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, + *num_bits, + le16_to_cpu(gd->bg_chain)); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + + ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh, + *bit_off, *num_bits); + if (ret < 0) + mlog_errno(ret); + + *bits_left = le16_to_cpu(gd->bg_free_bits_count); + +out: + brelse(group_bh); + + return ret; +} + static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, u32 bits_wanted, u32 min_bits, u16 *bit_off, unsigned int *num_bits, - u64 *bg_blkno) + u64 *bg_blkno, + u16 *bits_left) { int status; u16 chain, tmp_bits; @@ -988,9 +1147,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } bg = (struct ocfs2_group_desc *) group_bh->b_data; - if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { - OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); - status = -EIO; + status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg); + if (status) { + mlog_errno(status); goto bail; } @@ -1018,9 +1177,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } bg = (struct ocfs2_group_desc *) group_bh->b_data; - if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { - OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); - status = -EIO; + status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg); + if (status) { + mlog_errno(status); goto bail; } } @@ -1099,6 +1258,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, (unsigned long long)fe->i_blkno); *bg_blkno = le64_to_cpu(bg->bg_blkno); + *bits_left = le16_to_cpu(bg->bg_free_bits_count); bail: if (group_bh) brelse(group_bh); @@ -1120,6 +1280,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, { int status; u16 victim, i; + u16 bits_left = 0; + u64 hint_blkno = ac->ac_last_group; struct ocfs2_chain_list *cl; struct ocfs2_dinode *fe; @@ -1146,6 +1308,28 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, goto bail; } + if (hint_blkno) { + /* Attempt to short-circuit the usual search mechanism + * by jumping straight to the most recently used + * allocation group. This helps us mantain some + * contiguousness across allocations. */ + status = ocfs2_search_one_group(ac, bits_wanted, min_bits, + bit_off, num_bits, + hint_blkno, &bits_left); + if (!status) { + /* Be careful to update *bg_blkno here as the + * caller is expecting it to be filled in, and + * ocfs2_search_one_group() won't do that for + * us. */ + *bg_blkno = hint_blkno; + goto set_hint; + } + if (status < 0 && status != -ENOSPC) { + mlog_errno(status); + goto bail; + } + } + cl = (struct ocfs2_chain_list *) &fe->id2.i_chain; victim = ocfs2_find_victim_chain(cl); @@ -1153,9 +1337,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_allow_chain_relink = 1; status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off, - num_bits, bg_blkno); + num_bits, bg_blkno, &bits_left); if (!status) - goto bail; + goto set_hint; if (status < 0 && status != -ENOSPC) { mlog_errno(status); goto bail; @@ -1177,8 +1361,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_chain = i; status = ocfs2_search_chain(ac, bits_wanted, min_bits, - bit_off, num_bits, - bg_blkno); + bit_off, num_bits, bg_blkno, + &bits_left); if (!status) break; if (status < 0 && status != -ENOSPC) { @@ -1186,8 +1370,19 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, goto bail; } } -bail: +set_hint: + if (status != -ENOSPC) { + /* If the next search of this group is not likely to + * yield a suitable extent, then we reset the last + * group hint so as to not waste a disk read */ + if (bits_left < min_bits) + ac->ac_last_group = 0; + else + ac->ac_last_group = *bg_blkno; + } + +bail: mlog_exit(status); return status; } @@ -1341,7 +1536,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, { int status; unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; - u64 bg_blkno; + u64 bg_blkno = 0; u16 bg_bit_off; mlog_entry_void(); @@ -1494,9 +1689,9 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, } group = (struct ocfs2_group_desc *) group_bh->b_data; - if (!OCFS2_IS_VALID_GROUP_DESC(group)) { - OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group); - status = -EIO; + status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group); + if (status) { + mlog_errno(status); goto bail; } BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits)); diff --git a/trunk/fs/ocfs2/suballoc.h b/trunk/fs/ocfs2/suballoc.h index a76c82a7ceac..c787838d1052 100644 --- a/trunk/fs/ocfs2/suballoc.h +++ b/trunk/fs/ocfs2/suballoc.h @@ -49,6 +49,8 @@ struct ocfs2_alloc_context { u16 ac_chain; int ac_allow_chain_relink; group_search_t *ac_group_search; + + u64 ac_last_group; }; void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac); diff --git a/trunk/fs/ocfs2/super.c b/trunk/fs/ocfs2/super.c index 382706a67ffd..d17e33e66a1e 100644 --- a/trunk/fs/ocfs2/super.c +++ b/trunk/fs/ocfs2/super.c @@ -1442,8 +1442,13 @@ static int ocfs2_initialize_super(struct super_block *sb, osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno; + /* We don't have a cluster lock on the bitmap here because + * we're only interested in static information and the extra + * complexity at mount time isn't worht it. Don't pass the + * inode in to the read function though as we don't want it to + * be put in the cache. */ status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0, - inode); + NULL); iput(inode); if (status < 0) { mlog_errno(status); @@ -1452,7 +1457,6 @@ static int ocfs2_initialize_super(struct super_block *sb, di = (struct ocfs2_dinode *) bitmap_bh->b_data; osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg); - osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total); brelse(bitmap_bh); mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n", (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg); diff --git a/trunk/fs/partitions/Kconfig b/trunk/fs/partitions/Kconfig index c9a478099281..e478f1941831 100644 --- a/trunk/fs/partitions/Kconfig +++ b/trunk/fs/partitions/Kconfig @@ -99,7 +99,7 @@ config IBM_PARTITION config MAC_PARTITION bool "Macintosh partition map support" if PARTITION_ADVANCED - default y if MAC + default y if (MAC || PPC_PMAC) help Say Y here if you would like to use hard disks under Linux which were partitioned on a Macintosh. diff --git a/trunk/fs/reiserfs/file.c b/trunk/fs/reiserfs/file.c index f318b58510fd..1627edd50810 100644 --- a/trunk/fs/reiserfs/file.c +++ b/trunk/fs/reiserfs/file.c @@ -48,8 +48,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) return 0; } - reiserfs_write_lock(inode->i_sb); mutex_lock(&inode->i_mutex); + reiserfs_write_lock(inode->i_sb); /* freeing preallocation only involves relogging blocks that * are already in the current transaction. preallocation gets * freed at the end of each transaction, so it is impossible for diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index 12dfdcfbee3d..52f1e2136546 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -39,14 +39,10 @@ void reiserfs_delete_inode(struct inode *inode) /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ - mutex_lock(&inode->i_mutex); - reiserfs_delete_xattrs(inode); - if (journal_begin(&th, inode->i_sb, jbegin_count)) { - mutex_unlock(&inode->i_mutex); + if (journal_begin(&th, inode->i_sb, jbegin_count)) goto out; - } reiserfs_update_inode_transaction(inode); err = reiserfs_delete_object(&th, inode); @@ -57,12 +53,8 @@ void reiserfs_delete_inode(struct inode *inode) if (!err) DQUOT_FREE_INODE(inode); - if (journal_end(&th, inode->i_sb, jbegin_count)) { - mutex_unlock(&inode->i_mutex); + if (journal_end(&th, inode->i_sb, jbegin_count)) goto out; - } - - mutex_unlock(&inode->i_mutex); /* check return value from reiserfs_delete_object after * ending the transaction @@ -2348,6 +2340,7 @@ static int reiserfs_write_full_page(struct page *page, unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT; int error = 0; unsigned long block; + sector_t last_block; struct buffer_head *head, *bh; int partial = 0; int nr = 0; @@ -2395,10 +2388,19 @@ static int reiserfs_write_full_page(struct page *page, } bh = head; block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits); + last_block = (i_size_read(inode) - 1) >> inode->i_blkbits; /* first map all the buffers, logging any direct items we find */ do { - if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) || - (buffer_mapped(bh) + if (block > last_block) { + /* + * This can happen when the block size is less than + * the page size. The corresponding bytes in the page + * were zero filled above + */ + clear_buffer_dirty(bh); + set_buffer_uptodate(bh); + } else if ((checked || buffer_dirty(bh)) && + (!buffer_mapped(bh) || (buffer_mapped(bh) && bh->b_blocknr == 0))) { /* not mapped yet, or it points to a direct item, search diff --git a/trunk/fs/reiserfs/ioctl.c b/trunk/fs/reiserfs/ioctl.c index 745c88100895..a986b5e1e288 100644 --- a/trunk/fs/reiserfs/ioctl.c +++ b/trunk/fs/reiserfs/ioctl.c @@ -116,12 +116,12 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp) if (REISERFS_I(inode)->i_flags & i_nopack_mask) { return 0; } - reiserfs_write_lock(inode->i_sb); /* we need to make sure nobody is changing the file size beneath ** us */ mutex_lock(&inode->i_mutex); + reiserfs_write_lock(inode->i_sb); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ diff --git a/trunk/fs/udf/ialloc.c b/trunk/fs/udf/ialloc.c index 3873c672cb4c..33323473e3c4 100644 --- a/trunk/fs/udf/ialloc.c +++ b/trunk/fs/udf/ialloc.c @@ -75,6 +75,12 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) } *err = -ENOSPC; + UDF_I_UNIQUE(inode) = 0; + UDF_I_LENEXTENTS(inode) = 0; + UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; + UDF_I_NEXT_ALLOC_GOAL(inode) = 0; + UDF_I_STRAT4096(inode) = 0; + block = udf_new_block(dir->i_sb, NULL, UDF_I_LOCATION(dir).partitionReferenceNum, start, err); if (*err) @@ -84,11 +90,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) } mutex_lock(&sbi->s_alloc_mutex); - UDF_I_UNIQUE(inode) = 0; - UDF_I_LENEXTENTS(inode) = 0; - UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; - UDF_I_NEXT_ALLOC_GOAL(inode) = 0; - UDF_I_STRAT4096(inode) = 0; if (UDF_SB_LVIDBH(sb)) { struct logicalVolHeaderDesc *lvhd; diff --git a/trunk/fs/udf/super.c b/trunk/fs/udf/super.c index 4df822c881b6..7de172efa084 100644 --- a/trunk/fs/udf/super.c +++ b/trunk/fs/udf/super.c @@ -115,6 +115,13 @@ static struct inode *udf_alloc_inode(struct super_block *sb) ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL); if (!ei) return NULL; + + ei->i_unique = 0; + ei->i_lenExtents = 0; + ei->i_next_alloc_block = 0; + ei->i_next_alloc_goal = 0; + ei->i_strat4096 = 0; + return &ei->vfs_inode; } diff --git a/trunk/fs/ufs/balloc.c b/trunk/fs/ufs/balloc.c index b01804baa120..b82381475779 100644 --- a/trunk/fs/ufs/balloc.c +++ b/trunk/fs/ufs/balloc.c @@ -248,7 +248,7 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, if (likely(cur_index != index)) { page = ufs_get_locked_page(mapping, index); - if (IS_ERR(page)) + if (!page || IS_ERR(page)) /* it was truncated or EIO */ continue; } else page = locked_page; diff --git a/trunk/fs/ufs/namei.c b/trunk/fs/ufs/namei.c index abd5f23a426d..d344b411e261 100644 --- a/trunk/fs/ufs/namei.c +++ b/trunk/fs/ufs/namei.c @@ -129,7 +129,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, struct inode * inode; if (l > sb->s_blocksize) - goto out; + goto out_notlocked; lock_kernel(); inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); @@ -155,6 +155,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, err = ufs_add_nondir(dentry, inode); out: unlock_kernel(); +out_notlocked: return err; out_fail: diff --git a/trunk/fs/ufs/util.c b/trunk/fs/ufs/util.c index 337cf2c46d10..22f820a9b15c 100644 --- a/trunk/fs/ufs/util.c +++ b/trunk/fs/ufs/util.c @@ -251,12 +251,12 @@ struct page *ufs_get_locked_page(struct address_space *mapping, { struct page *page; -try_again: page = find_lock_page(mapping, index); if (!page) { page = read_cache_page(mapping, index, (filler_t*)mapping->a_ops->readpage, NULL); + if (IS_ERR(page)) { printk(KERN_ERR "ufs_change_blocknr: " "read_cache_page error: ino %lu, index: %lu\n", @@ -266,6 +266,14 @@ struct page *ufs_get_locked_page(struct address_space *mapping, lock_page(page); + if (unlikely(page->mapping == NULL)) { + /* Truncate got there first */ + unlock_page(page); + page_cache_release(page); + page = NULL; + goto out; + } + if (!PageUptodate(page) || PageError(page)) { unlock_page(page); page_cache_release(page); @@ -275,15 +283,8 @@ struct page *ufs_get_locked_page(struct address_space *mapping, mapping->host->i_ino, index); page = ERR_PTR(-EIO); - goto out; } } - - if (unlikely(!page->mapping || !page_has_buffers(page))) { - unlock_page(page); - page_cache_release(page); - goto try_again;/*we really need these buffers*/ - } out: return page; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.h b/trunk/fs/xfs/linux-2.6/xfs_buf.h index ceda3a2859d2..7858703ed84c 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.h +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.h @@ -246,8 +246,8 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); #define BUF_BUSY XBF_DONT_BLOCK #define XFS_BUF_BFLAGS(bp) ((bp)->b_flags) -#define XFS_BUF_ZEROFLAGS(bp) \ - ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI)) +#define XFS_BUF_ZEROFLAGS(bp) ((bp)->b_flags &= \ + ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI|XBF_ORDERED)) #define XFS_BUF_STALE(bp) ((bp)->b_flags |= XFS_B_STALE) #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XFS_B_STALE) diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 9bdef9d51900..4754f342a5d3 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -314,6 +314,13 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) return; } + if (xfs_readonly_buftarg(mp->m_ddev_targp)) { + xfs_fs_cmn_err(CE_NOTE, mp, + "Disabling barriers, underlying device is readonly"); + mp->m_flags &= ~XFS_MOUNT_BARRIER; + return; + } + error = xfs_barrier_test(mp); if (error) { xfs_fs_cmn_err(CE_NOTE, mp, diff --git a/trunk/fs/xfs/quota/xfs_qm_bhv.c b/trunk/fs/xfs/quota/xfs_qm_bhv.c index e95e99f7168f..f137856c3261 100644 --- a/trunk/fs/xfs/quota/xfs_qm_bhv.c +++ b/trunk/fs/xfs/quota/xfs_qm_bhv.c @@ -217,17 +217,24 @@ xfs_qm_statvfs( return 0; dp = &dqp->q_core; - limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit; + limit = dp->d_blk_softlimit ? + be64_to_cpu(dp->d_blk_softlimit) : + be64_to_cpu(dp->d_blk_hardlimit); if (limit && statp->f_blocks > limit) { statp->f_blocks = limit; - statp->f_bfree = (statp->f_blocks > dp->d_bcount) ? - (statp->f_blocks - dp->d_bcount) : 0; + statp->f_bfree = + (statp->f_blocks > be64_to_cpu(dp->d_bcount)) ? + (statp->f_blocks - be64_to_cpu(dp->d_bcount)) : 0; } - limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit; + + limit = dp->d_ino_softlimit ? + be64_to_cpu(dp->d_ino_softlimit) : + be64_to_cpu(dp->d_ino_hardlimit); if (limit && statp->f_files > limit) { statp->f_files = limit; - statp->f_ffree = (statp->f_files > dp->d_icount) ? - (statp->f_ffree - dp->d_icount) : 0; + statp->f_ffree = + (statp->f_files > be64_to_cpu(dp->d_icount)) ? + (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0; } xfs_qm_dqput(dqp); diff --git a/trunk/fs/xfs/xfs_alloc.c b/trunk/fs/xfs/xfs_alloc.c index eef6763f3a67..d2bbcd882a69 100644 --- a/trunk/fs/xfs/xfs_alloc.c +++ b/trunk/fs/xfs/xfs_alloc.c @@ -1835,40 +1835,47 @@ xfs_alloc_fix_freelist( &agbp))) return error; if (!pag->pagf_init) { + ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); + ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); args->agbp = NULL; return 0; } } else agbp = NULL; - /* If this is a metadata preferred pag and we are user data + /* + * If this is a metadata preferred pag and we are user data * then try somewhere else if we are not being asked to * try harder at this point */ - if (pag->pagf_metadata && args->userdata && flags) { + if (pag->pagf_metadata && args->userdata && + (flags & XFS_ALLOC_FLAG_TRYLOCK)) { + ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); args->agbp = NULL; return 0; } - need = XFS_MIN_FREELIST_PAG(pag, mp); - delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; - /* - * If it looks like there isn't a long enough extent, or enough - * total blocks, reject it. - */ - longest = (pag->pagf_longest > delta) ? - (pag->pagf_longest - delta) : - (pag->pagf_flcount > 0 || pag->pagf_longest > 0); - if (args->minlen + args->alignment + args->minalignslop - 1 > longest || - (!(flags & XFS_ALLOC_FLAG_FREEING) && - (int)(pag->pagf_freeblks + pag->pagf_flcount - - need - args->total) < - (int)args->minleft)) { - if (agbp) - xfs_trans_brelse(tp, agbp); - args->agbp = NULL; - return 0; + if (!(flags & XFS_ALLOC_FLAG_FREEING)) { + need = XFS_MIN_FREELIST_PAG(pag, mp); + delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; + /* + * If it looks like there isn't a long enough extent, or enough + * total blocks, reject it. + */ + longest = (pag->pagf_longest > delta) ? + (pag->pagf_longest - delta) : + (pag->pagf_flcount > 0 || pag->pagf_longest > 0); + if ((args->minlen + args->alignment + args->minalignslop - 1) > + longest || + ((int)(pag->pagf_freeblks + pag->pagf_flcount - + need - args->total) < (int)args->minleft)) { + if (agbp) + xfs_trans_brelse(tp, agbp); + args->agbp = NULL; + return 0; + } } + /* * Get the a.g. freespace buffer. * Can fail if we're not blocking on locks, and it's held. @@ -1878,6 +1885,8 @@ xfs_alloc_fix_freelist( &agbp))) return error; if (agbp == NULL) { + ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); + ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); args->agbp = NULL; return 0; } @@ -1887,22 +1896,24 @@ xfs_alloc_fix_freelist( */ agf = XFS_BUF_TO_AGF(agbp); need = XFS_MIN_FREELIST(agf, mp); - delta = need > be32_to_cpu(agf->agf_flcount) ? - (need - be32_to_cpu(agf->agf_flcount)) : 0; /* * If there isn't enough total or single-extent, reject it. */ - longest = be32_to_cpu(agf->agf_longest); - longest = (longest > delta) ? (longest - delta) : - (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); - if (args->minlen + args->alignment + args->minalignslop - 1 > longest || - (!(flags & XFS_ALLOC_FLAG_FREEING) && - (int)(be32_to_cpu(agf->agf_freeblks) + - be32_to_cpu(agf->agf_flcount) - need - args->total) < - (int)args->minleft)) { - xfs_trans_brelse(tp, agbp); - args->agbp = NULL; - return 0; + if (!(flags & XFS_ALLOC_FLAG_FREEING)) { + delta = need > be32_to_cpu(agf->agf_flcount) ? + (need - be32_to_cpu(agf->agf_flcount)) : 0; + longest = be32_to_cpu(agf->agf_longest); + longest = (longest > delta) ? (longest - delta) : + (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); + if ((args->minlen + args->alignment + args->minalignslop - 1) > + longest || + ((int)(be32_to_cpu(agf->agf_freeblks) + + be32_to_cpu(agf->agf_flcount) - need - args->total) < + (int)args->minleft)) { + xfs_trans_brelse(tp, agbp); + args->agbp = NULL; + return 0; + } } /* * Make the freelist shorter if it's too long. @@ -1950,12 +1961,11 @@ xfs_alloc_fix_freelist( * on a completely full ag. */ if (targs.agbno == NULLAGBLOCK) { - if (!(flags & XFS_ALLOC_FLAG_FREEING)) { - xfs_trans_brelse(tp, agflbp); - args->agbp = NULL; - return 0; - } - break; + if (flags & XFS_ALLOC_FLAG_FREEING) + break; + xfs_trans_brelse(tp, agflbp); + args->agbp = NULL; + return 0; } /* * Put each allocated block on the list. @@ -2442,31 +2452,26 @@ xfs_free_extent( xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len) /* length of extent */ { -#ifdef DEBUG - xfs_agf_t *agf; /* a.g. freespace header */ -#endif - xfs_alloc_arg_t args; /* allocation argument structure */ + xfs_alloc_arg_t args; int error; ASSERT(len != 0); + memset(&args, 0, sizeof(xfs_alloc_arg_t)); args.tp = tp; args.mp = tp->t_mountp; args.agno = XFS_FSB_TO_AGNO(args.mp, bno); ASSERT(args.agno < args.mp->m_sb.sb_agcount); args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); - args.alignment = 1; - args.minlen = args.minleft = args.minalignslop = 0; down_read(&args.mp->m_peraglock); args.pag = &args.mp->m_perag[args.agno]; if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) goto error0; #ifdef DEBUG ASSERT(args.agbp != NULL); - agf = XFS_BUF_TO_AGF(args.agbp); - ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length)); + ASSERT((args.agbno + len) <= + be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)); #endif - error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, - len, 0); + error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); error0: up_read(&args.mp->m_peraglock); return error; diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 86c1bf0bba9e..1f8ecff8553a 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -334,10 +334,9 @@ xfs_itobp( #if !defined(__KERNEL__) ni = 0; #elif defined(DEBUG) - ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : - (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); + ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog; #else /* usual case */ - ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; + ni = 1; #endif for (i = 0; i < ni; i++) { @@ -348,11 +347,15 @@ xfs_itobp( (i << mp->m_sb.sb_inodelog)); di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC && XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT)); - if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, - XFS_RANDOM_ITOBP_INOTOBP))) { + if (unlikely(XFS_TEST_ERROR(!di_ok, mp, + XFS_ERRTAG_ITOBP_INOTOBP, + XFS_RANDOM_ITOBP_INOTOBP))) { + if (imap_flags & XFS_IMAP_BULKSTAT) { + xfs_trans_brelse(tp, bp); + return XFS_ERROR(EINVAL); + } #ifdef DEBUG - if (!(imap_flags & XFS_IMAP_BULKSTAT)) - cmn_err(CE_ALERT, + cmn_err(CE_ALERT, "Device %s - bad inode magic/vsn " "daddr %lld #%d (magic=%x)", XFS_BUFTARG_NAME(mp->m_ddev_targp), diff --git a/trunk/fs/xfs/xfs_log.c b/trunk/fs/xfs/xfs_log.c index e730328636c3..21ac1a67e3e0 100644 --- a/trunk/fs/xfs/xfs_log.c +++ b/trunk/fs/xfs/xfs_log.c @@ -1413,7 +1413,7 @@ xlog_sync(xlog_t *log, ops = iclog->ic_header.h_num_logops; INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops); - bp = iclog->ic_bp; + bp = iclog->ic_bp; ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1); XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2); XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT))); @@ -1430,15 +1430,14 @@ xlog_sync(xlog_t *log, } XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count); XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */ + XFS_BUF_ZEROFLAGS(bp); XFS_BUF_BUSY(bp); XFS_BUF_ASYNC(bp); /* * Do an ordered write for the log block. - * - * It may not be needed to flush the first split block in the log wrap - * case, but do it anyways to be safe -AK + * Its unnecessary to flush the first split block in the log wrap case. */ - if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) + if (!split && (log->l_mp->m_flags & XFS_MOUNT_BARRIER)) XFS_BUF_ORDERED(bp); ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); @@ -1460,7 +1459,7 @@ xlog_sync(xlog_t *log, return error; } if (split) { - bp = iclog->ic_log->l_xbuf; + bp = iclog->ic_log->l_xbuf; ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1); XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2); @@ -1468,6 +1467,7 @@ xlog_sync(xlog_t *log, XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+ (__psint_t)count), split); XFS_BUF_SET_FSPRIVATE(bp, iclog); + XFS_BUF_ZEROFLAGS(bp); XFS_BUF_BUSY(bp); XFS_BUF_ASYNC(bp); if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) diff --git a/trunk/fs/xfs/xfs_vfsops.c b/trunk/fs/xfs/xfs_vfsops.c index 6c96391f3f1a..b427d220a169 100644 --- a/trunk/fs/xfs/xfs_vfsops.c +++ b/trunk/fs/xfs/xfs_vfsops.c @@ -515,7 +515,7 @@ xfs_mount( if (error) goto error2; - if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY)) + if (mp->m_flags & XFS_MOUNT_BARRIER) xfs_mountfs_check_barriers(mp); error = XFS_IOINIT(vfsp, args, flags); diff --git a/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h b/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h index 8ff73d487222..7135ad7e335e 100644 --- a/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h +++ b/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h @@ -91,7 +91,6 @@ #define NR_IRQS NR_IOP331_IRQS -#if defined(CONFIG_ARCH_IQ80331) /* * Interrupts available on the IQ80331 board */ @@ -111,7 +110,6 @@ #define IRQ_IQ80331_INTC IRQ_IOP331_XINT2 #define IRQ_IQ80331_INTD IRQ_IOP331_XINT3 -#elif defined(CONFIG_MACH_IQ80332) /* * Interrupts available on the IQ80332 board */ @@ -131,6 +129,4 @@ #define IRQ_IQ80332_INTC IRQ_IOP331_XINT2 #define IRQ_IQ80332_INTD IRQ_IOP331_XINT3 -#endif - #endif // _IOP331_IRQ_H_ diff --git a/trunk/include/asm-arm/arch-omap/clock.h b/trunk/include/asm-arm/arch-omap/clock.h index 3c4eb9fbe48a..f83003f5287b 100644 --- a/trunk/include/asm-arm/arch-omap/clock.h +++ b/trunk/include/asm-arm/arch-omap/clock.h @@ -48,8 +48,6 @@ struct clk_functions { }; extern unsigned int mpurate; -extern struct list_head clocks; -extern spinlock_t clockfw_lock; extern int clk_init(struct clk_functions * custom_clocks); extern int clk_register(struct clk *clk); diff --git a/trunk/include/asm-i386/kprobes.h b/trunk/include/asm-i386/kprobes.h index 0730a20f6db8..8774d06689da 100644 --- a/trunk/include/asm-i386/kprobes.h +++ b/trunk/include/asm-i386/kprobes.h @@ -45,6 +45,7 @@ typedef u8 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES #define ARCH_INACTIVE_KPROBE_COUNT 0 +#define flush_insn_slot(p) do { } while (0) void arch_remove_kprobe(struct kprobe *p); void kretprobe_trampoline(void); diff --git a/trunk/include/asm-ia64/kprobes.h b/trunk/include/asm-ia64/kprobes.h index 2418a787c405..938904910115 100644 --- a/trunk/include/asm-ia64/kprobes.h +++ b/trunk/include/asm-ia64/kprobes.h @@ -125,5 +125,6 @@ static inline void jprobe_return(void) } extern void invalidate_stacked_regs(void); extern void flush_register_stack(void); +extern void flush_insn_slot(struct kprobe *p); #endif /* _ASM_KPROBES_H */ diff --git a/trunk/include/asm-ia64/meminit.h b/trunk/include/asm-ia64/meminit.h index 894bc4d89dc0..6a33a07b3f1d 100644 --- a/trunk/include/asm-ia64/meminit.h +++ b/trunk/include/asm-ia64/meminit.h @@ -56,6 +56,11 @@ extern void efi_memmap_init(unsigned long *, unsigned long *); extern struct page *vmem_map; extern int find_largest_hole (u64 start, u64 end, void *arg); extern int create_mem_map_page_table (u64 start, u64 end, void *arg); + extern int vmemmap_find_next_valid_pfn(int, int); +#else +static inline int vmemmap_find_next_valid_pfn(int node, int i) +{ + return i + 1; +} #endif - #endif /* meminit_h */ diff --git a/trunk/include/asm-ia64/pal.h b/trunk/include/asm-ia64/pal.h index 37e52a2836b0..20a8d618c845 100644 --- a/trunk/include/asm-ia64/pal.h +++ b/trunk/include/asm-ia64/pal.h @@ -1433,7 +1433,12 @@ typedef union pal_version_u { } pal_version_u_t; -/* Return PAL version information */ +/* + * Return PAL version information. While the documentation states that + * PAL_VERSION can be called in either physical or virtual mode, some + * implementations only allow physical calls. We don't call it very often, + * so the overhead isn't worth eliminating. + */ static inline s64 ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version) { diff --git a/trunk/include/asm-ia64/sn/xpc.h b/trunk/include/asm-ia64/sn/xpc.h index 8406f1ef4caf..b72af597878d 100644 --- a/trunk/include/asm-ia64/sn/xpc.h +++ b/trunk/include/asm-ia64/sn/xpc.h @@ -1124,8 +1124,8 @@ xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag, #define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff)) #define XPC_SET_IPI_FLAGS(_amo, _c, _f) (_amo) |= ((u64) (_f) << ((_c) * 8)) -#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f) -#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & 0x1010101010101010) +#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x0f0f0f0f0f0f0f0f)) +#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x1010101010101010)) static inline void diff --git a/trunk/include/asm-ia64/system.h b/trunk/include/asm-ia64/system.h index fc9677bc87ee..384fbf7f2a0f 100644 --- a/trunk/include/asm-ia64/system.h +++ b/trunk/include/asm-ia64/system.h @@ -24,7 +24,7 @@ * 0xa000000000000000+2*PERCPU_PAGE_SIZE * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page) */ -#define KERNEL_START (GATE_ADDR+0x100000000) +#define KERNEL_START (GATE_ADDR+__IA64_UL_CONST(0x100000000)) #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/trunk/include/asm-powerpc/backlight.h b/trunk/include/asm-powerpc/backlight.h index 58d4b6f8d827..8cf5c37c3817 100644 --- a/trunk/include/asm-powerpc/backlight.h +++ b/trunk/include/asm-powerpc/backlight.h @@ -30,8 +30,12 @@ static inline void pmac_backlight_key_down(void) pmac_backlight_key(1); } +extern void pmac_backlight_set_legacy_brightness_pmu(int brightness); extern int pmac_backlight_set_legacy_brightness(int brightness); extern int pmac_backlight_get_legacy_brightness(void); +extern void pmac_backlight_enable(void); +extern void pmac_backlight_disable(void); + #endif /* __KERNEL__ */ #endif diff --git a/trunk/include/asm-powerpc/kexec.h b/trunk/include/asm-powerpc/kexec.h index 8f7fd5cfec34..11cbdf81fd2e 100644 --- a/trunk/include/asm-powerpc/kexec.h +++ b/trunk/include/asm-powerpc/kexec.h @@ -32,6 +32,7 @@ #endif #ifndef __ASSEMBLY__ +#include #ifdef CONFIG_KEXEC @@ -109,7 +110,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs, #define MAX_NOTE_BYTES 1024 -#ifdef __powerpc64__ extern void kexec_smp_wait(void); /* get and clear naca physid, wait for master to copy new code to 0 */ extern int crashing_cpu; @@ -119,7 +119,6 @@ static inline int kexec_sr_activated(int cpu) { return cpu_isset(cpu,cpus_in_sr); } -#endif /* __powerpc64 __ */ struct kimage; struct pt_regs; diff --git a/trunk/include/asm-powerpc/kprobes.h b/trunk/include/asm-powerpc/kprobes.h index 2d0af52c823d..34e1f89a5fa0 100644 --- a/trunk/include/asm-powerpc/kprobes.h +++ b/trunk/include/asm-powerpc/kprobes.h @@ -51,6 +51,7 @@ typedef unsigned int kprobe_opcode_t; #define ARCH_SUPPORTS_KRETPROBES #define ARCH_INACTIVE_KPROBE_COUNT 1 +#define flush_insn_slot(p) do { } while (0) void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); diff --git a/trunk/include/asm-powerpc/rtas.h b/trunk/include/asm-powerpc/rtas.h index a33c6acffa61..82a27e9a041f 100644 --- a/trunk/include/asm-powerpc/rtas.h +++ b/trunk/include/asm-powerpc/rtas.h @@ -170,6 +170,7 @@ extern int rtas_get_sensor(int sensor, int index, int *state); extern int rtas_get_power_level(int powerdomain, int *level); extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); extern int rtas_set_indicator(int indicator, int index, int new_value); +extern int rtas_set_indicator_fast(int indicator, int index, int new_value); extern void rtas_progress(char *s, unsigned short hex); extern void rtas_initialize(void); diff --git a/trunk/include/asm-sparc/signal.h b/trunk/include/asm-sparc/signal.h index 0ae5084c427b..d03a21c97abb 100644 --- a/trunk/include/asm-sparc/signal.h +++ b/trunk/include/asm-sparc/signal.h @@ -168,7 +168,7 @@ struct sigstack { * statically allocated data.. which is NOT GOOD. * */ -#define SA_STATIC_ALLOC 0x80 +#define SA_STATIC_ALLOC 0x8000 #endif #include diff --git a/trunk/include/asm-sparc64/kprobes.h b/trunk/include/asm-sparc64/kprobes.h index 15065af566c2..c9f5c34d318c 100644 --- a/trunk/include/asm-sparc64/kprobes.h +++ b/trunk/include/asm-sparc64/kprobes.h @@ -13,6 +13,7 @@ typedef u32 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define arch_remove_kprobe(p) do {} while (0) #define ARCH_INACTIVE_KPROBE_COUNT 0 +#define flush_insn_slot(p) do { } while (0) /* Architecture specific copy of original instruction*/ struct arch_specific_insn { diff --git a/trunk/include/asm-sparc64/pgtable.h b/trunk/include/asm-sparc64/pgtable.h index 03f5bc9b6bec..1ba19eb34ce3 100644 --- a/trunk/include/asm-sparc64/pgtable.h +++ b/trunk/include/asm-sparc64/pgtable.h @@ -339,7 +339,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot) " .section .sun4v_2insn_patch, \"ax\"\n" " .word 661b\n" " andn %0, %4, %0\n" - " or %0, %3, %0\n" + " or %0, %5, %0\n" " .previous\n" : "=r" (val) : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U), diff --git a/trunk/include/asm-sparc64/sfp-machine.h b/trunk/include/asm-sparc64/sfp-machine.h index 5015bb8d6c32..89d42431efb5 100644 --- a/trunk/include/asm-sparc64/sfp-machine.h +++ b/trunk/include/asm-sparc64/sfp-machine.h @@ -34,7 +34,7 @@ #define _FP_MUL_MEAT_D(R,X,Y) \ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) #define _FP_MUL_MEAT_Q(R,X,Y) \ - _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) diff --git a/trunk/include/asm-x86_64/calgary.h b/trunk/include/asm-x86_64/calgary.h index fbfb50136edb..4e3919524240 100644 --- a/trunk/include/asm-x86_64/calgary.h +++ b/trunk/include/asm-x86_64/calgary.h @@ -60,9 +60,4 @@ static inline int calgary_iommu_init(void) { return 1; } static inline void detect_calgary(void) { return; } #endif -static inline unsigned int bus_to_phb(unsigned char busno) -{ - return ((busno % 15 == 0) ? 0 : busno / 2 + 1); -} - #endif /* _ASM_X86_64_CALGARY_H */ diff --git a/trunk/include/asm-x86_64/kprobes.h b/trunk/include/asm-x86_64/kprobes.h index d36febd9bb18..cf5317898fb0 100644 --- a/trunk/include/asm-x86_64/kprobes.h +++ b/trunk/include/asm-x86_64/kprobes.h @@ -47,6 +47,7 @@ typedef u8 kprobe_opcode_t; void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); +#define flush_insn_slot(p) do { } while (0) /* Architecture specific copy of original instruction*/ struct arch_specific_insn { diff --git a/trunk/include/asm-x86_64/page.h b/trunk/include/asm-x86_64/page.h index f7bf875aae40..10f346165cab 100644 --- a/trunk/include/asm-x86_64/page.h +++ b/trunk/include/asm-x86_64/page.h @@ -19,7 +19,7 @@ #define EXCEPTION_STACK_ORDER 0 #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) -#define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER +#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) #define IRQSTACK_ORDER 2 diff --git a/trunk/include/asm-x86_64/swiotlb.h b/trunk/include/asm-x86_64/swiotlb.h index 5f9a01805821..ba94ab3d2673 100644 --- a/trunk/include/asm-x86_64/swiotlb.h +++ b/trunk/include/asm-x86_64/swiotlb.h @@ -42,6 +42,8 @@ extern void swiotlb_free_coherent (struct device *hwdev, size_t size, extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); extern void swiotlb_init(void); +extern int swiotlb_force; + #ifdef CONFIG_SWIOTLB extern int swiotlb; #else diff --git a/trunk/include/linux/audit.h b/trunk/include/linux/audit.h index b27d7debc5a1..64f9f9e56ac5 100644 --- a/trunk/include/linux/audit.h +++ b/trunk/include/linux/audit.h @@ -327,21 +327,31 @@ extern void __audit_getname(const char *name); extern void audit_putname(const char *name); extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode_child(const char *dname, const struct inode *inode, - unsigned long pino); + const struct inode *parent); +extern void __audit_inode_update(const struct inode *inode); +static inline int audit_dummy_context(void) +{ + void *p = current->audit_context; + return !p || *(int *)p; +} static inline void audit_getname(const char *name) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) __audit_getname(name); } static inline void audit_inode(const char *name, const struct inode *inode) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) __audit_inode(name, inode); } static inline void audit_inode_child(const char *dname, - const struct inode *inode, - unsigned long pino) { - if (unlikely(current->audit_context)) - __audit_inode_child(dname, inode, pino); + const struct inode *inode, + const struct inode *parent) { + if (unlikely(!audit_dummy_context())) + __audit_inode_child(dname, inode, parent); +} +static inline void audit_inode_update(const struct inode *inode) { + if (unlikely(!audit_dummy_context())) + __audit_inode_update(inode); } /* Private API (for audit.c only) */ @@ -365,57 +375,61 @@ extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_ipc_obj(ipcp); return 0; } static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_ipc_set_perm(qbytes, uid, gid, mode); return 0; } static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_mq_open(oflag, mode, u_attr); return 0; } static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); return 0; } static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); return 0; } static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_mq_notify(mqdes, u_notification); return 0; } static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) { - if (unlikely(current->audit_context)) + if (unlikely(!audit_dummy_context())) return __audit_mq_getsetattr(mqdes, mqstat); return 0; } +extern int audit_n_rules; #else #define audit_alloc(t) ({ 0; }) #define audit_free(t) do { ; } while (0) #define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0) #define audit_syscall_exit(f,r) do { ; } while (0) +#define audit_dummy_context() 1 #define audit_getname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0) #define __audit_inode(n,i) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0) +#define __audit_inode_update(i) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0) +#define audit_inode_update(i) do { ; } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) #define audit_get_loginuid(c) ({ -1; }) #define audit_ipc_obj(i) ({ 0; }) @@ -430,6 +444,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) #define audit_mq_timedreceive(d,l,p,t) ({ 0; }) #define audit_mq_notify(d,n) ({ 0; }) #define audit_mq_getsetattr(d,s) ({ 0; }) +#define audit_n_rules 0 #endif #ifdef CONFIG_AUDIT diff --git a/trunk/include/linux/cn_proc.h b/trunk/include/linux/cn_proc.h index dbb7769009be..1c86d65bc4b9 100644 --- a/trunk/include/linux/cn_proc.h +++ b/trunk/include/linux/cn_proc.h @@ -57,7 +57,8 @@ struct proc_event { PROC_EVENT_EXIT = 0x80000000 } what; __u32 cpu; - struct timespec timestamp; + __u64 __attribute__((aligned(8))) timestamp_ns; + /* Number of nano seconds since system boot */ union { /* must be last field of proc_event struct */ struct { __u32 err; diff --git a/trunk/include/linux/cpufreq.h b/trunk/include/linux/cpufreq.h index 35e137636b0b..4ea39fee99c7 100644 --- a/trunk/include/linux/cpufreq.h +++ b/trunk/include/linux/cpufreq.h @@ -172,9 +172,6 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation); -/* pass an event to the cpufreq governor */ -int cpufreq_governor(unsigned int cpu, unsigned int event); - int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); diff --git a/trunk/include/linux/debug_locks.h b/trunk/include/linux/debug_locks.h index 6a7047851e48..88dafa246d87 100644 --- a/trunk/include/linux/debug_locks.h +++ b/trunk/include/linux/debug_locks.h @@ -1,6 +1,8 @@ #ifndef __LINUX_DEBUG_LOCKING_H #define __LINUX_DEBUG_LOCKING_H +struct task_struct; + extern int debug_locks; extern int debug_locks_silent; diff --git a/trunk/include/linux/delayacct.h b/trunk/include/linux/delayacct.h index 7e8b6011b8f3..11487b6e7127 100644 --- a/trunk/include/linux/delayacct.h +++ b/trunk/include/linux/delayacct.h @@ -55,7 +55,7 @@ static inline void delayacct_tsk_init(struct task_struct *tsk) { /* reinitialize in case parent's non-null pointer was dup'ed*/ tsk->delays = NULL; - if (unlikely(delayacct_on)) + if (delayacct_on) __delayacct_tsk_init(tsk); } @@ -80,9 +80,7 @@ static inline void delayacct_blkio_end(void) static inline int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) { - if (likely(!delayacct_on)) - return -EINVAL; - if (!tsk->delays) + if (!delayacct_on || !tsk->delays) return 0; return __delayacct_add_tsk(d, tsk); } diff --git a/trunk/include/linux/ext3_fs.h b/trunk/include/linux/ext3_fs.h index 5607e6457a65..9f9cce7bd86d 100644 --- a/trunk/include/linux/ext3_fs.h +++ b/trunk/include/linux/ext3_fs.h @@ -492,6 +492,15 @@ static inline struct ext3_inode_info *EXT3_I(struct inode *inode) { return container_of(inode, struct ext3_inode_info, vfs_inode); } + +static inline int ext3_valid_inum(struct super_block *sb, unsigned long ino) +{ + return ino == EXT3_ROOT_INO || + ino == EXT3_JOURNAL_INO || + ino == EXT3_RESIZE_INO || + (ino >= EXT3_FIRST_INO(sb) && + ino <= le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)); +} #else /* Assume that user mode programs are passing in an ext3fs superblock, not * a kernel struct super_block. This will allow us to call the feature-test diff --git a/trunk/include/linux/fb.h b/trunk/include/linux/fb.h index 405f44e44e5d..2f335e966011 100644 --- a/trunk/include/linux/fb.h +++ b/trunk/include/linux/fb.h @@ -1,7 +1,6 @@ #ifndef _LINUX_FB_H #define _LINUX_FB_H -#include #include /* Definitions of frame buffers */ @@ -381,6 +380,7 @@ struct fb_cursor { #include #include #include +#include #include struct vm_area_struct; @@ -524,7 +524,7 @@ struct fb_event { extern int fb_register_client(struct notifier_block *nb); extern int fb_unregister_client(struct notifier_block *nb); - +extern int fb_notifier_call_chain(unsigned long val, void *v); /* * Pixmap structure definition * diff --git a/trunk/include/linux/fsnotify.h b/trunk/include/linux/fsnotify.h index cc5dec70c32c..d4f219ffaa5d 100644 --- a/trunk/include/linux/fsnotify.h +++ b/trunk/include/linux/fsnotify.h @@ -67,7 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, if (source) { inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); } - audit_inode_child(new_name, source, new_dir->i_ino); + audit_inode_child(new_name, source, new_dir); } /* @@ -98,7 +98,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); + audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); } /* @@ -109,7 +109,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); + audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); } /* diff --git a/trunk/include/linux/futex.h b/trunk/include/linux/futex.h index 34c3a215f2cd..d097b5b72bc6 100644 --- a/trunk/include/linux/futex.h +++ b/trunk/include/linux/futex.h @@ -96,7 +96,8 @@ struct robust_list_head { long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, u32 __user *uaddr2, u32 val2, u32 val3); -extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr); +extern int +handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi); #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index dc7abef10965..99620451d958 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -571,6 +571,7 @@ typedef struct ide_drive_s { u8 waiting_for_dma; /* dma currently in progress */ u8 unmask; /* okay to unmask other irqs */ u8 bswap; /* byte swap data */ + u8 noflush; /* don't attempt flushes */ u8 dsc_overlap; /* DSC overlap */ u8 nice1; /* give potential excess bandwidth */ diff --git a/trunk/include/linux/if_vlan.h b/trunk/include/linux/if_vlan.h index 383627ad328f..ab2740832742 100644 --- a/trunk/include/linux/if_vlan.h +++ b/trunk/include/linux/if_vlan.h @@ -155,6 +155,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, { struct net_device_stats *stats; + if (skb_bond_should_drop(skb)) { + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK]; if (skb->dev == NULL) { dev_kfree_skb_any(skb); diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index 56f1e0e1e598..b3253ab72ff7 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -893,7 +893,6 @@ struct input_dev { int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); - int (*accept)(struct input_dev *dev, struct file *file); int (*flush)(struct input_dev *dev, struct file *file); int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect); @@ -961,6 +960,26 @@ struct input_dev { struct input_handle; +/** + * struct input_handler - implements one of interfaces for input devices + * @private: driver-specific data + * @event: event handler + * @connect: called when attaching a handler to an input device + * @disconnect: disconnects a handler from input device + * @start: starts handler for given handle. This function is called by + * input core right after connect() method and also when a process + * that "grabbed" a device releases it + * @fops: file operations this driver implements + * @minor: beginning of range of 32 minors for devices this driver + * can provide + * @name: name of the handler, to be shown in /proc/bus/input/handlers + * @id_table: pointer to a table of input_device_ids this driver can + * handle + * @blacklist: prointer to a table of input_device_ids this driver should + * ignore even if they match @id_table + * @h_list: list of input handles associated with the handler + * @node: for placing the driver onto input_handler_list + */ struct input_handler { void *private; @@ -968,6 +987,7 @@ struct input_handler { void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); void (*disconnect)(struct input_handle *handle); + void (*start)(struct input_handle *handle); const struct file_operations *fops; int minor; @@ -1030,10 +1050,10 @@ void input_release_device(struct input_handle *); int input_open_device(struct input_handle *); void input_close_device(struct input_handle *); -int input_accept_process(struct input_handle *handle, struct file *file); int input_flush_device(struct input_handle* handle, struct file* file); void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); +void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); static inline void input_report_key(struct input_dev *dev, unsigned int code, int value) { diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index b48eae32dc61..fbf6d901e9c2 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -47,8 +47,8 @@ #define IRQ_WAITING 0x00200000 /* IRQ not yet seen - for autodetection */ #define IRQ_LEVEL 0x00400000 /* IRQ level triggered */ #define IRQ_MASKED 0x00800000 /* IRQ masked - shouldn't be seen again */ +#define IRQ_PER_CPU 0x01000000 /* IRQ is per CPU */ #ifdef CONFIG_IRQ_PER_CPU -# define IRQ_PER_CPU 0x01000000 /* IRQ is per CPU */ # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) #else # define CHECK_IRQ_PER_CPU(var) 0 @@ -58,6 +58,7 @@ #define IRQ_NOREQUEST 0x04000000 /* IRQ cannot be requested */ #define IRQ_NOAUTOEN 0x08000000 /* IRQ will not be enabled on request irq */ #define IRQ_DELAYED_DISABLE 0x10000000 /* IRQ disable (masking) happens delayed. */ +#define IRQ_WAKEUP 0x20000000 /* IRQ triggers system wakeup */ struct proc_dir_entry; @@ -124,6 +125,7 @@ struct irq_chip { * @action: the irq action chain * @status: status information * @depth: disable-depth, for nested irq_disable() calls + * @wake_depth: enable depth, for multiple set_irq_wake() callers * @irq_count: stats field to detect stalled irqs * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP @@ -147,6 +149,7 @@ struct irq_desc { unsigned int status; /* IRQ status */ unsigned int depth; /* nested irq disables */ + unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ unsigned int irqs_unhandled; spinlock_t lock; diff --git a/trunk/include/linux/jiffies.h b/trunk/include/linux/jiffies.h index 043376920f51..329ebcffa106 100644 --- a/trunk/include/linux/jiffies.h +++ b/trunk/include/linux/jiffies.h @@ -47,8 +47,8 @@ * - (NOM / DEN) fits in (32 - LSH) bits. * - (NOM % DEN) fits in (32 - LSH) bits. */ -#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \ - + (((NOM % DEN) << LSH) + DEN / 2) / DEN) +#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index 181c69cad4e3..851aa1bcfc1a 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -210,6 +210,7 @@ extern enum system_states { extern void dump_stack(void); #ifdef DEBUG +/* If you are writing a driver, please use dev_dbg instead */ #define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt,##arg) #else diff --git a/trunk/include/linux/kobject.h b/trunk/include/linux/kobject.h index 0503b2ed8bae..2d229327959e 100644 --- a/trunk/include/linux/kobject.h +++ b/trunk/include/linux/kobject.h @@ -46,8 +46,6 @@ enum kobject_action { KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ - KOBJ_UNDOCK = (__force kobject_action_t) 0x08, /* undocking */ - KOBJ_DOCK = (__force kobject_action_t) 0x09, /* dock */ }; struct kobject { diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index 6cc497a2b6da..66c3100c2b94 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -265,12 +265,14 @@ enum { /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ - ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */ + ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ + ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, + /* max repeat if error condition is still set after ->error_handler */ ATA_EH_MAX_REPEAT = 5, diff --git a/trunk/include/linux/lockd/lockd.h b/trunk/include/linux/lockd/lockd.h index aa4fe905bb4d..0d92c468d55a 100644 --- a/trunk/include/linux/lockd/lockd.h +++ b/trunk/include/linux/lockd/lockd.h @@ -123,7 +123,6 @@ struct nlm_block { unsigned int b_id; /* block id */ unsigned char b_queued; /* re-queued */ unsigned char b_granted; /* VFS granted lock */ - unsigned char b_done; /* callback complete */ struct nlm_file * b_file; /* file in question */ }; diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 990957e0929f..f0b135cd86da 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -336,6 +336,7 @@ static inline void init_page_count(struct page *page) } void put_page(struct page *page); +void put_pages_list(struct list_head *pages); void split_page(struct page *page, unsigned int order); diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 75f02d8c6ed3..50a4719512ed 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -320,6 +320,9 @@ struct net_device #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) + /* List of features with software fallbacks. */ +#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6) + #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) @@ -1012,6 +1015,30 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) unlikely(skb->ip_summed != CHECKSUM_HW)); } +/* On bonding slaves other than the currently active slave, suppress + * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast. + */ +static inline int skb_bond_should_drop(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + struct net_device *master = dev->master; + + if (master && + (dev->priv_flags & IFF_SLAVE_INACTIVE)) { + if (master->priv_flags & IFF_MASTER_ALB) { + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + return 0; + } + if (master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __constant_htons(ETH_P_SLOW)) + return 0; + + return 1; + } + return 0; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */ diff --git a/trunk/include/linux/netfilter_bridge.h b/trunk/include/linux/netfilter_bridge.h index 87764022cc67..10c13dc4665b 100644 --- a/trunk/include/linux/netfilter_bridge.h +++ b/trunk/include/linux/netfilter_bridge.h @@ -6,7 +6,6 @@ #include #if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER) -#include #include #endif @@ -79,6 +78,8 @@ struct bridge_skb_cb { __u32 ipv4; } daddr; }; + +extern int brnf_deferred_hooks; #endif /* CONFIG_BRIDGE_NETFILTER */ #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 55ea853d57bc..247434553ae8 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -476,10 +476,9 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page) } /* - * Allocate and free nfs_write_data structures + * Allocate nfs_write_data structures */ extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); -extern void nfs_writedata_free(struct nfs_write_data *p); /* * linux/fs/nfs/read.c @@ -491,10 +490,9 @@ extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *); extern void nfs_readdata_release(void *data); /* - * Allocate and free nfs_read_data structures + * Allocate nfs_read_data structures */ extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); -extern void nfs_readdata_free(struct nfs_read_data *p); /* * linux/fs/nfs3proc.c diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index c09396d2c77b..4eae06b08cf2 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -2142,6 +2142,7 @@ #define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 #define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 +#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c #define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 #define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 #define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 diff --git a/trunk/include/linux/pmu.h b/trunk/include/linux/pmu.h index 2ed807ddc08c..783177387ac6 100644 --- a/trunk/include/linux/pmu.h +++ b/trunk/include/linux/pmu.h @@ -231,7 +231,6 @@ extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; extern unsigned int pmu_power_flags; /* Backlight */ -extern int disable_kernel_backlight; -extern void pmu_backlight_init(struct device_node*); +extern void pmu_backlight_init(void); #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 6afa72e080cb..6674fc1e51bf 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -1557,6 +1557,14 @@ static inline void freeze(struct task_struct *p) p->flags |= PF_FREEZE; } +/* + * Sometimes we may need to cancel the previous 'freeze' request + */ +static inline void do_not_freeze(struct task_struct *p) +{ + p->flags &= ~PF_FREEZE; +} + /* * Wake up a frozen process */ diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index f75303831d09..6bc2aad494ff 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -1109,6 +1109,16 @@ struct swap_info_struct; * @name contains the name of the security module being unstacked. * @ops contains a pointer to the struct security_operations of the module to unstack. * + * @secid_to_secctx: + * Convert secid to security context. + * @secid contains the security ID. + * @secdata contains the pointer that stores the converted security context. + * + * @release_secctx: + * Release the security context. + * @secdata contains the security context. + * @seclen contains the length of the security context. + * * This is the main security structure. */ struct security_operations { @@ -1289,6 +1299,8 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); + int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK int (*unix_stream_connect) (struct socket * sock, @@ -1317,7 +1329,7 @@ struct security_operations { int (*socket_shutdown) (struct socket * sock, int how); int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb); int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); - int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, u32 *seclen); + int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); void (*sk_free_security) (struct sock *sk); unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); @@ -2059,6 +2071,16 @@ static inline int security_netlink_recv(struct sk_buff * skb, int cap) return security_ops->netlink_recv(skb, cap); } +static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + return security_ops->secid_to_secctx(secid, secdata, seclen); +} + +static inline void security_release_secctx(char *secdata, u32 seclen) +{ + return security_ops->release_secctx(secdata, seclen); +} + /* prototypes */ extern int security_init (void); extern int register_security (struct security_operations *ops); @@ -2725,6 +2747,14 @@ static inline void securityfs_remove(struct dentry *dentry) { } +static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + return -EOPNOTSUPP; +} + +static inline void security_release_secctx(char *secdata, u32 seclen) +{ +} #endif /* CONFIG_SECURITY */ #ifdef CONFIG_SECURITY_NETWORK @@ -2840,10 +2870,9 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __ return security_ops->socket_getpeersec_stream(sock, optval, optlen, len); } -static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, - u32 *seclen) +static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { - return security_ops->socket_getpeersec_dgram(skb, secdata, seclen); + return security_ops->socket_getpeersec_dgram(sock, skb, secid); } static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) @@ -2968,8 +2997,7 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __ return -ENOPROTOOPT; } -static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, - u32 *seclen) +static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { return -ENOPROTOOPT; } diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 4307e764ef0a..755e9cddac47 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -604,12 +604,17 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_) return list_->qlen; } -extern struct lock_class_key skb_queue_lock_key; - +/* + * This function creates a split out lock class for each invocation; + * this is needed for now since a whole lot of users of the skb-queue + * infrastructure in drivers have different locking usage (in hardirq) + * than the networking core (in softirq only). In the long run either the + * network layer or drivers should need annotation to consolidate the + * main types of usage into 3 classes. + */ static inline void skb_queue_head_init(struct sk_buff_head *list) { spin_lock_init(&list->lock); - lockdep_set_class(&list->lock, &skb_queue_lock_key); list->prev = list->next = (struct sk_buff *)list; list->qlen = 0; } @@ -1034,6 +1039,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len) return (len < skb->len) ? __pskb_trim(skb, len) : 0; } +/** + * pskb_trim_unique - remove end from a paged unique (not cloned) buffer + * @skb: buffer to alter + * @len: new length + * + * This is identical to pskb_trim except that the caller knows that + * the skb is not cloned so we should never get an error due to out- + * of-memory. + */ +static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len) +{ + int err = pskb_trim(skb, len); + BUG_ON(err); +} + /** * skb_orphan - orphan a buffer * @skb: buffer to orphan @@ -1076,7 +1096,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) * the headroom they think they need without accounting for the * built in space. The built in space is used for optimisations. * - * %NULL is returned in there is no free memory. + * %NULL is returned if there is no free memory. */ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, gfp_t gfp_mask) @@ -1096,7 +1116,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, * the headroom they think they need without accounting for the * built in space. The built in space is used for optimisations. * - * %NULL is returned in there is no free memory. Although this function + * %NULL is returned if there is no free memory. Although this function * allocates memory it can be called from an interrupt. */ static inline struct sk_buff *dev_alloc_skb(unsigned int length) @@ -1104,6 +1124,28 @@ static inline struct sk_buff *dev_alloc_skb(unsigned int length) return __dev_alloc_skb(length, GFP_ATOMIC); } +extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev, + unsigned int length, gfp_t gfp_mask); + +/** + * netdev_alloc_skb - allocate an skbuff for rx on a specific device + * @dev: network device to receive on + * @length: length to allocate + * + * Allocate a new &sk_buff and assign it a usage count of one. The + * buffer has unspecified headroom built in. Users should allocate + * the headroom they think they need without accounting for the + * built in space. The built in space is used for optimisations. + * + * %NULL is returned if there is no free memory. Although this function + * allocates memory it can be called from an interrupt. + */ +static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev, + unsigned int length) +{ + return __netdev_alloc_skb(dev, length, GFP_ATOMIC); +} + /** * skb_cow - copy header of skb when it is required * @skb: buffer to cow diff --git a/trunk/include/linux/sunrpc/xprt.h b/trunk/include/linux/sunrpc/xprt.h index e8bbe8118de8..840e47a4ccc5 100644 --- a/trunk/include/linux/sunrpc/xprt.h +++ b/trunk/include/linux/sunrpc/xprt.h @@ -229,7 +229,7 @@ int xprt_reserve_xprt(struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); -void xprt_abort_transmit(struct rpc_task *task); +void xprt_end_transmit(struct rpc_task *task); int xprt_adjust_timeout(struct rpc_rqst *req); void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index c944e8f06a4a..d2bd0c8e0154 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -103,8 +103,7 @@ enum usb_interface_condition { * @condition: binding state of the interface: not bound, binding * (in probe()), bound to a driver, or unbinding (in disconnect()) * @dev: driver model's view of this device - * @usb_dev: if an interface is bound to the USB major, this will point - * to the sysfs representation for that device. + * @class_dev: driver model's class view of this device. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -144,7 +143,7 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ struct device dev; /* interface specific device info */ - struct device *usb_dev; /* pointer to the usb class's device, if any */ + struct class_device *class_dev; }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) #define interface_to_usbdev(intf) \ @@ -361,7 +360,7 @@ struct usb_device { char *serial; /* iSerialNumber string, if present */ struct list_head filelist; - struct device *usbfs_dev; + struct class_device *class_dev; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ /* diff --git a/trunk/include/linux/usb_usual.h b/trunk/include/linux/usb_usual.h index f38f43f20fae..e7fc5fed5b98 100644 --- a/trunk/include/linux/usb_usual.h +++ b/trunk/include/linux/usb_usual.h @@ -44,7 +44,9 @@ US_FLAG(NO_WP_DETECT, 0x00000200) \ /* Don't check for write-protect */ \ US_FLAG(MAX_SECTORS_64, 0x00000400) \ - /* Sets max_sectors to 64 */ + /* Sets max_sectors to 64 */ \ + US_FLAG(IGNORE_DEVICE, 0x00000800) \ + /* Don't claim device */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; diff --git a/trunk/include/linux/videodev.h b/trunk/include/linux/videodev.h index 41bc7e9603cd..518c7a32175e 100644 --- a/trunk/include/linux/videodev.h +++ b/trunk/include/linux/videodev.h @@ -12,10 +12,11 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H -#define HAVE_V4L1 1 - #include +#ifdef CONFIG_VIDEO_V4L1_COMPAT +#define HAVE_V4L1 1 + struct video_capability { char name[32]; @@ -336,6 +337,8 @@ struct video_code #define VID_HARDWARE_SN9C102 38 #define VID_HARDWARE_ARV 39 +#endif /* CONFIG_VIDEO_V4L1_COMPAT */ + #endif /* __LINUX_VIDEODEV_H */ /* diff --git a/trunk/include/linux/videodev2.h b/trunk/include/linux/videodev2.h index a62673dad76e..b7146956a929 100644 --- a/trunk/include/linux/videodev2.h +++ b/trunk/include/linux/videodev2.h @@ -716,7 +716,7 @@ struct v4l2_ext_control __s64 value64; void *reserved; }; -}; +} __attribute__ ((packed)); struct v4l2_ext_controls { diff --git a/trunk/include/linux/vmstat.h b/trunk/include/linux/vmstat.h index 1ab806c47514..2d9b1b60798a 100644 --- a/trunk/include/linux/vmstat.h +++ b/trunk/include/linux/vmstat.h @@ -41,23 +41,23 @@ DECLARE_PER_CPU(struct vm_event_state, vm_event_states); static inline void __count_vm_event(enum vm_event_item item) { - __get_cpu_var(vm_event_states.event[item])++; + __get_cpu_var(vm_event_states).event[item]++; } static inline void count_vm_event(enum vm_event_item item) { - get_cpu_var(vm_event_states.event[item])++; + get_cpu_var(vm_event_states).event[item]++; put_cpu(); } static inline void __count_vm_events(enum vm_event_item item, long delta) { - __get_cpu_var(vm_event_states.event[item]) += delta; + __get_cpu_var(vm_event_states).event[item] += delta; } static inline void count_vm_events(enum vm_event_item item, long delta) { - get_cpu_var(vm_event_states.event[item]) += delta; + get_cpu_var(vm_event_states).event[item] += delta; put_cpu(); } diff --git a/trunk/include/media/v4l2-dev.h b/trunk/include/media/v4l2-dev.h index 62dae1a8c441..600d61d7d2ab 100644 --- a/trunk/include/media/v4l2-dev.h +++ b/trunk/include/media/v4l2-dev.h @@ -16,7 +16,7 @@ #include #include #include /* need __user */ -#ifdef CONFIG_VIDEO_V4L1 +#ifdef CONFIG_VIDEO_V4L1_COMPAT #include #else #include @@ -341,11 +341,14 @@ extern int video_usercopy(struct inode *inode, struct file *file, extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) -static inline void +static inline int video_device_create_file(struct video_device *vfd, struct class_device_attribute *attr) { - class_device_create_file(&vfd->class_dev, attr); + int ret = class_device_create_file(&vfd->class_dev, attr); + if (ret < 0) + printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); + return ret; } static inline void video_device_remove_file(struct video_device *vfd, diff --git a/trunk/include/net/af_unix.h b/trunk/include/net/af_unix.h index 2fec827c8801..c0398f5a8cb9 100644 --- a/trunk/include/net/af_unix.h +++ b/trunk/include/net/af_unix.h @@ -54,15 +54,13 @@ struct unix_skb_parms { struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK - char *secdata; /* Security context */ - u32 seclen; /* Security length */ + u32 secid; /* Security ID */ #endif }; #define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb)) #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) -#define UNIXSECDATA(skb) (&UNIXCB((skb)).secdata) -#define UNIXSECLEN(skb) (&UNIXCB((skb)).seclen) +#define UNIXSID(skb) (&UNIXCB((skb)).secid) #define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock) #define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock) diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index ab29dafb1a6a..96b0e66406ec 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -139,16 +139,22 @@ extern rwlock_t rt6_lock; /* * Store a destination cache entry in a socket */ -static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, - struct in6_addr *daddr) +static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, + struct in6_addr *daddr) { struct ipv6_pinfo *np = inet6_sk(sk); struct rt6_info *rt = (struct rt6_info *) dst; - write_lock(&sk->sk_dst_lock); sk_setup_caps(sk, dst); np->daddr_cache = daddr; np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; +} + +static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, + struct in6_addr *daddr) +{ + write_lock(&sk->sk_dst_lock); + __ip6_dst_store(sk, dst, daddr); write_unlock(&sk->sk_dst_lock); } diff --git a/trunk/include/net/ipv6.h b/trunk/include/net/ipv6.h index a8fdf7970b37..ece7e8a84ffd 100644 --- a/trunk/include/net/ipv6.h +++ b/trunk/include/net/ipv6.h @@ -468,6 +468,9 @@ extern void ip6_flush_pending_frames(struct sock *sk); extern int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl); +extern int ip6_sk_dst_lookup(struct sock *sk, + struct dst_entry **dst, + struct flowi *fl); /* * skb processing functions diff --git a/trunk/include/net/netdma.h b/trunk/include/net/netdma.h index ceae5ee85c04..7f53cd1d8b1e 100644 --- a/trunk/include/net/netdma.h +++ b/trunk/include/net/netdma.h @@ -29,7 +29,7 @@ static inline struct dma_chan *get_softnet_dma(void) { struct dma_chan *chan; rcu_read_lock(); - chan = rcu_dereference(__get_cpu_var(softnet_data.net_dma)); + chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma); if (chan) dma_chan_get(chan); rcu_read_unlock(); diff --git a/trunk/include/net/netevent.h b/trunk/include/net/netevent.h new file mode 100644 index 000000000000..e5d216241423 --- /dev/null +++ b/trunk/include/net/netevent.h @@ -0,0 +1,33 @@ +#ifndef _NET_EVENT_H +#define _NET_EVENT_H + +/* + * Generic netevent notifiers + * + * Authors: + * Tom Tucker + * Steve Wise + * + * Changes: + */ +#ifdef __KERNEL__ + +#include + +struct netevent_redirect { + struct dst_entry *old; + struct dst_entry *new; +}; + +enum netevent_notif_type { + NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */ + NETEVENT_PMTU_UPDATE, /* arg is struct dst_entry ptr */ + NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */ +}; + +extern int register_netevent_notifier(struct notifier_block *nb); +extern int unregister_netevent_notifier(struct notifier_block *nb); +extern int call_netevent_notifiers(unsigned long val, void *v); + +#endif +#endif diff --git a/trunk/include/net/red.h b/trunk/include/net/red.h index 5ccdbb3d4722..a4eb37946f2c 100644 --- a/trunk/include/net/red.h +++ b/trunk/include/net/red.h @@ -212,7 +212,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) * Seems, it is the best solution to * problem of too coarse exponent tabulation. */ - us_idle = (p->qavg * us_idle) >> p->Scell_log; + us_idle = (p->qavg * (u64)us_idle) >> p->Scell_log; if (us_idle < (p->qavg >> 1)) return p->qavg - us_idle; diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 02daa097cdcd..5637d5e22d5f 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -3,6 +3,7 @@ #include #include +#include /* Well, we should have at least one descriptor open * to accept passed FDs 8) @@ -20,8 +21,7 @@ struct scm_cookie struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK - char *secdata; /* Security context */ - u32 seclen; /* Security length */ + u32 secid; /* Passed security ID */ #endif unsigned long seq; /* Connection seqno */ }; @@ -32,6 +32,16 @@ extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie extern void __scm_destroy(struct scm_cookie *scm); extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); +#ifdef CONFIG_SECURITY_NETWORK +static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) +{ + security_socket_getpeersec_dgram(sock, NULL, &scm->secid); +} +#else +static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) +{ } +#endif /* CONFIG_SECURITY_NETWORK */ + static __inline__ void scm_destroy(struct scm_cookie *scm) { if (scm && scm->fp) @@ -47,6 +57,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, scm->creds.pid = p->tgid; scm->fp = NULL; scm->seq = 0; + unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; return __scm_send(sock, msg, scm); @@ -55,8 +66,18 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, #ifdef CONFIG_SECURITY_NETWORK static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) { - if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL) - put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, scm->secdata); + char *secdata; + u32 seclen; + int err; + + if (test_bit(SOCK_PASSSEC, &sock->flags)) { + err = security_secid_to_secctx(scm->secid, &secdata, &seclen); + + if (!err) { + put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); + security_release_secctx(secdata, seclen); + } + } } #else static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 0720bddff1e9..7a093d0aa0fe 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -914,6 +914,9 @@ static inline void tcp_set_state(struct sock *sk, int state) static inline void tcp_done(struct sock *sk) { + if(sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); + tcp_set_state(sk, TCP_CLOSE); tcp_clear_xmit_timers(sk); diff --git a/trunk/ipc/msg.c b/trunk/ipc/msg.c index cd92d342953e..2b4fccf8ea55 100644 --- a/trunk/ipc/msg.c +++ b/trunk/ipc/msg.c @@ -1,6 +1,6 @@ /* * linux/ipc/msg.c - * Copyright (C) 1992 Krishna Balasubramanian + * Copyright (C) 1992 Krishna Balasubramanian * * Removed all the remaining kerneld mess * Catch the -EFAULT stuff properly @@ -41,22 +41,24 @@ int msg_ctlmax = MSGMAX; int msg_ctlmnb = MSGMNB; int msg_ctlmni = MSGMNI; -/* one msg_receiver structure for each sleeping receiver */ +/* + * one msg_receiver structure for each sleeping receiver: + */ struct msg_receiver { - struct list_head r_list; - struct task_struct* r_tsk; + struct list_head r_list; + struct task_struct *r_tsk; - int r_mode; - long r_msgtype; - long r_maxsize; + int r_mode; + long r_msgtype; + long r_maxsize; - struct msg_msg* volatile r_msg; + volatile struct msg_msg *r_msg; }; /* one msg_sender for each sleeping sender */ struct msg_sender { - struct list_head list; - struct task_struct* tsk; + struct list_head list; + struct task_struct *tsk; }; #define SEARCH_ANY 1 @@ -64,45 +66,42 @@ struct msg_sender { #define SEARCH_NOTEQUAL 3 #define SEARCH_LESSEQUAL 4 -static atomic_t msg_bytes = ATOMIC_INIT(0); -static atomic_t msg_hdrs = ATOMIC_INIT(0); +static atomic_t msg_bytes = ATOMIC_INIT(0); +static atomic_t msg_hdrs = ATOMIC_INIT(0); static struct ipc_ids msg_ids; -#define msg_lock(id) ((struct msg_queue*)ipc_lock(&msg_ids,id)) -#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) -#define msg_rmid(id) ((struct msg_queue*)ipc_rmid(&msg_ids,id)) -#define msg_checkid(msq, msgid) \ - ipc_checkid(&msg_ids,&msq->q_perm,msgid) -#define msg_buildid(id, seq) \ - ipc_buildid(&msg_ids, id, seq) +#define msg_lock(id) ((struct msg_queue *)ipc_lock(&msg_ids, id)) +#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) +#define msg_rmid(id) ((struct msg_queue *)ipc_rmid(&msg_ids, id)) +#define msg_checkid(msq, msgid) ipc_checkid(&msg_ids, &msq->q_perm, msgid) +#define msg_buildid(id, seq) ipc_buildid(&msg_ids, id, seq) -static void freeque (struct msg_queue *msq, int id); -static int newque (key_t key, int msgflg); +static void freeque(struct msg_queue *msq, int id); +static int newque(key_t key, int msgflg); #ifdef CONFIG_PROC_FS static int sysvipc_msg_proc_show(struct seq_file *s, void *it); #endif -void __init msg_init (void) +void __init msg_init(void) { - ipc_init_ids(&msg_ids,msg_ctlmni); + ipc_init_ids(&msg_ids, msg_ctlmni); ipc_init_proc_interface("sysvipc/msg", " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", &msg_ids, sysvipc_msg_proc_show); } -static int newque (key_t key, int msgflg) +static int newque(key_t key, int msgflg) { - int id; - int retval; struct msg_queue *msq; + int id, retval; - msq = ipc_rcu_alloc(sizeof(*msq)); - if (!msq) + msq = ipc_rcu_alloc(sizeof(*msq)); + if (!msq) return -ENOMEM; - msq->q_perm.mode = (msgflg & S_IRWXUGO); + msq->q_perm.mode = msgflg & S_IRWXUGO; msq->q_perm.key = key; msq->q_perm.security = NULL; @@ -113,13 +112,13 @@ static int newque (key_t key, int msgflg) } id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni); - if(id == -1) { + if (id == -1) { security_msg_queue_free(msq); ipc_rcu_putref(msq); return -ENOSPC; } - msq->q_id = msg_buildid(id,msq->q_perm.seq); + msq->q_id = msg_buildid(id, msq->q_perm.seq); msq->q_stime = msq->q_rtime = 0; msq->q_ctime = get_seconds(); msq->q_cbytes = msq->q_qnum = 0; @@ -133,44 +132,44 @@ static int newque (key_t key, int msgflg) return msq->q_id; } -static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss) +static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) { - mss->tsk=current; - current->state=TASK_INTERRUPTIBLE; - list_add_tail(&mss->list,&msq->q_senders); + mss->tsk = current; + current->state = TASK_INTERRUPTIBLE; + list_add_tail(&mss->list, &msq->q_senders); } -static inline void ss_del(struct msg_sender* mss) +static inline void ss_del(struct msg_sender *mss) { - if(mss->list.next != NULL) + if (mss->list.next != NULL) list_del(&mss->list); } -static void ss_wakeup(struct list_head* h, int kill) +static void ss_wakeup(struct list_head *h, int kill) { struct list_head *tmp; tmp = h->next; while (tmp != h) { - struct msg_sender* mss; - - mss = list_entry(tmp,struct msg_sender,list); + struct msg_sender *mss; + + mss = list_entry(tmp, struct msg_sender, list); tmp = tmp->next; - if(kill) - mss->list.next=NULL; + if (kill) + mss->list.next = NULL; wake_up_process(mss->tsk); } } -static void expunge_all(struct msg_queue* msq, int res) +static void expunge_all(struct msg_queue *msq, int res) { struct list_head *tmp; tmp = msq->q_receivers.next; while (tmp != &msq->q_receivers) { - struct msg_receiver* msr; - - msr = list_entry(tmp,struct msg_receiver,r_list); + struct msg_receiver *msr; + + msr = list_entry(tmp, struct msg_receiver, r_list); tmp = tmp->next; msr->r_msg = NULL; wake_up_process(msr->r_tsk); @@ -178,26 +177,28 @@ static void expunge_all(struct msg_queue* msq, int res) msr->r_msg = ERR_PTR(res); } } -/* - * freeque() wakes up waiters on the sender and receiver waiting queue, - * removes the message queue from message queue ID + +/* + * freeque() wakes up waiters on the sender and receiver waiting queue, + * removes the message queue from message queue ID * array, and cleans up all the messages associated with this queue. * * msg_ids.mutex and the spinlock for this message queue is hold * before freeque() is called. msg_ids.mutex remains locked on exit. */ -static void freeque (struct msg_queue *msq, int id) +static void freeque(struct msg_queue *msq, int id) { struct list_head *tmp; - expunge_all(msq,-EIDRM); - ss_wakeup(&msq->q_senders,1); + expunge_all(msq, -EIDRM); + ss_wakeup(&msq->q_senders, 1); msq = msg_rmid(id); msg_unlock(msq); - + tmp = msq->q_messages.next; - while(tmp != &msq->q_messages) { - struct msg_msg* msg = list_entry(tmp,struct msg_msg,m_list); + while (tmp != &msq->q_messages) { + struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list); + tmp = tmp->next; atomic_dec(&msg_hdrs); free_msg(msg); @@ -207,10 +208,10 @@ static void freeque (struct msg_queue *msq, int id) ipc_rcu_putref(msq); } -asmlinkage long sys_msgget (key_t key, int msgflg) +asmlinkage long sys_msgget(key_t key, int msgflg) { - int id, ret = -EPERM; struct msg_queue *msq; + int id, ret = -EPERM; mutex_lock(&msg_ids.mutex); if (key == IPC_PRIVATE) @@ -224,31 +225,34 @@ asmlinkage long sys_msgget (key_t key, int msgflg) ret = -EEXIST; } else { msq = msg_lock(id); - BUG_ON(msq==NULL); + BUG_ON(msq == NULL); if (ipcperms(&msq->q_perm, msgflg)) ret = -EACCES; else { int qid = msg_buildid(id, msq->q_perm.seq); - ret = security_msg_queue_associate(msq, msgflg); + + ret = security_msg_queue_associate(msq, msgflg); if (!ret) ret = qid; } msg_unlock(msq); } mutex_unlock(&msg_ids.mutex); + return ret; } -static inline unsigned long copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) +static inline unsigned long +copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) { switch(version) { case IPC_64: - return copy_to_user (buf, in, sizeof(*in)); + return copy_to_user(buf, in, sizeof(*in)); case IPC_OLD: - { + { struct msqid_ds out; - memset(&out,0,sizeof(out)); + memset(&out, 0, sizeof(out)); ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm); @@ -256,18 +260,18 @@ static inline unsigned long copy_msqid_to_user(void __user *buf, struct msqid64_ out.msg_rtime = in->msg_rtime; out.msg_ctime = in->msg_ctime; - if(in->msg_cbytes > USHRT_MAX) + if (in->msg_cbytes > USHRT_MAX) out.msg_cbytes = USHRT_MAX; else out.msg_cbytes = in->msg_cbytes; out.msg_lcbytes = in->msg_cbytes; - if(in->msg_qnum > USHRT_MAX) + if (in->msg_qnum > USHRT_MAX) out.msg_qnum = USHRT_MAX; else out.msg_qnum = in->msg_qnum; - if(in->msg_qbytes > USHRT_MAX) + if (in->msg_qbytes > USHRT_MAX) out.msg_qbytes = USHRT_MAX; else out.msg_qbytes = in->msg_qbytes; @@ -276,8 +280,8 @@ static inline unsigned long copy_msqid_to_user(void __user *buf, struct msqid64_ out.msg_lspid = in->msg_lspid; out.msg_lrpid = in->msg_lrpid; - return copy_to_user (buf, &out, sizeof(out)); - } + return copy_to_user(buf, &out, sizeof(out)); + } default: return -EINVAL; } @@ -290,14 +294,15 @@ struct msq_setbuf { mode_t mode; }; -static inline unsigned long copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version) +static inline unsigned long +copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version) { switch(version) { case IPC_64: - { + { struct msqid64_ds tbuf; - if (copy_from_user (&tbuf, buf, sizeof (tbuf))) + if (copy_from_user(&tbuf, buf, sizeof(tbuf))) return -EFAULT; out->qbytes = tbuf.msg_qbytes; @@ -306,60 +311,61 @@ static inline unsigned long copy_msqid_from_user(struct msq_setbuf *out, void __ out->mode = tbuf.msg_perm.mode; return 0; - } + } case IPC_OLD: - { + { struct msqid_ds tbuf_old; - if (copy_from_user (&tbuf_old, buf, sizeof (tbuf_old))) + if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old))) return -EFAULT; out->uid = tbuf_old.msg_perm.uid; out->gid = tbuf_old.msg_perm.gid; out->mode = tbuf_old.msg_perm.mode; - if(tbuf_old.msg_qbytes == 0) + if (tbuf_old.msg_qbytes == 0) out->qbytes = tbuf_old.msg_lqbytes; else out->qbytes = tbuf_old.msg_qbytes; return 0; - } + } default: return -EINVAL; } } -asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) +asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) { - int err, version; - struct msg_queue *msq; - struct msq_setbuf setbuf; struct kern_ipc_perm *ipcp; - + struct msq_setbuf setbuf; + struct msg_queue *msq; + int err, version; + if (msqid < 0 || cmd < 0) return -EINVAL; version = ipc_parse_version(&cmd); switch (cmd) { - case IPC_INFO: - case MSG_INFO: - { + case IPC_INFO: + case MSG_INFO: + { struct msginfo msginfo; int max_id; + if (!buf) return -EFAULT; - /* We must not return kernel stack data. + /* + * We must not return kernel stack data. * due to padding, it's not enough * to set all member fields. */ - err = security_msg_queue_msgctl(NULL, cmd); if (err) return err; - memset(&msginfo,0,sizeof(msginfo)); + memset(&msginfo, 0, sizeof(msginfo)); msginfo.msgmni = msg_ctlmni; msginfo.msgmax = msg_ctlmax; msginfo.msgmnb = msg_ctlmnb; @@ -377,36 +383,37 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) } max_id = msg_ids.max_id; mutex_unlock(&msg_ids.mutex); - if (copy_to_user (buf, &msginfo, sizeof(struct msginfo))) + if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) return -EFAULT; - return (max_id < 0) ? 0: max_id; + return (max_id < 0) ? 0 : max_id; } case MSG_STAT: case IPC_STAT: { struct msqid64_ds tbuf; int success_return; + if (!buf) return -EFAULT; - if(cmd == MSG_STAT && msqid >= msg_ids.entries->size) + if (cmd == MSG_STAT && msqid >= msg_ids.entries->size) return -EINVAL; - memset(&tbuf,0,sizeof(tbuf)); + memset(&tbuf, 0, sizeof(tbuf)); msq = msg_lock(msqid); if (msq == NULL) return -EINVAL; - if(cmd == MSG_STAT) { + if (cmd == MSG_STAT) { success_return = msg_buildid(msqid, msq->q_perm.seq); } else { err = -EIDRM; - if (msg_checkid(msq,msqid)) + if (msg_checkid(msq, msqid)) goto out_unlock; success_return = 0; } err = -EACCES; - if (ipcperms (&msq->q_perm, S_IRUGO)) + if (ipcperms(&msq->q_perm, S_IRUGO)) goto out_unlock; err = security_msg_queue_msgctl(msq, cmd); @@ -430,7 +437,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) case IPC_SET: if (!buf) return -EFAULT; - if (copy_msqid_from_user (&setbuf, buf, version)) + if (copy_msqid_from_user(&setbuf, buf, version)) return -EFAULT; break; case IPC_RMID: @@ -441,12 +448,12 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) mutex_lock(&msg_ids.mutex); msq = msg_lock(msqid); - err=-EINVAL; + err = -EINVAL; if (msq == NULL) goto out_up; err = -EIDRM; - if (msg_checkid(msq,msqid)) + if (msg_checkid(msq, msqid)) goto out_unlock_up; ipcp = &msq->q_perm; @@ -454,15 +461,16 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) if (err) goto out_unlock_up; if (cmd==IPC_SET) { - err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode); + err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, + setbuf.mode); if (err) goto out_unlock_up; } err = -EPERM; - if (current->euid != ipcp->cuid && + if (current->euid != ipcp->cuid && current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) - /* We _could_ check for CAP_CHOWN above, but we don't */ + /* We _could_ check for CAP_CHOWN above, but we don't */ goto out_unlock_up; err = security_msg_queue_msgctl(msq, cmd); @@ -480,22 +488,22 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) ipcp->uid = setbuf.uid; ipcp->gid = setbuf.gid; - ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | - (S_IRWXUGO & setbuf.mode); + ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | + (S_IRWXUGO & setbuf.mode); msq->q_ctime = get_seconds(); /* sleeping receivers might be excluded by * stricter permissions. */ - expunge_all(msq,-EAGAIN); + expunge_all(msq, -EAGAIN); /* sleeping senders might be able to send * due to a larger queue size. */ - ss_wakeup(&msq->q_senders,0); + ss_wakeup(&msq->q_senders, 0); msg_unlock(msq); break; } case IPC_RMID: - freeque (msq, msqid); + freeque(msq, msqid); break; } err = 0; @@ -510,41 +518,44 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) return err; } -static int testmsg(struct msg_msg* msg,long type,int mode) +static int testmsg(struct msg_msg *msg, long type, int mode) { switch(mode) { case SEARCH_ANY: return 1; case SEARCH_LESSEQUAL: - if(msg->m_type <=type) + if (msg->m_type <=type) return 1; break; case SEARCH_EQUAL: - if(msg->m_type == type) + if (msg->m_type == type) return 1; break; case SEARCH_NOTEQUAL: - if(msg->m_type != type) + if (msg->m_type != type) return 1; break; } return 0; } -static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg) +static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) { - struct list_head* tmp; + struct list_head *tmp; tmp = msq->q_receivers.next; while (tmp != &msq->q_receivers) { - struct msg_receiver* msr; - msr = list_entry(tmp,struct msg_receiver,r_list); + struct msg_receiver *msr; + + msr = list_entry(tmp, struct msg_receiver, r_list); tmp = tmp->next; - if(testmsg(msg,msr->r_msgtype,msr->r_mode) && - !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) { + if (testmsg(msg, msr->r_msgtype, msr->r_mode) && + !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, + msr->r_msgtype, msr->r_mode)) { + list_del(&msr->r_list); - if(msr->r_maxsize < msg->m_ts) { + if (msr->r_maxsize < msg->m_ts) { msr->r_msg = NULL; wake_up_process(msr->r_tsk); smp_mb(); @@ -556,6 +567,7 @@ static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg) wake_up_process(msr->r_tsk); smp_mb(); msr->r_msg = msg; + return 1; } } @@ -563,40 +575,41 @@ static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg) return 0; } -asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) +asmlinkage long +sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) { struct msg_queue *msq; struct msg_msg *msg; long mtype; int err; - + if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0) return -EINVAL; if (get_user(mtype, &msgp->mtype)) - return -EFAULT; + return -EFAULT; if (mtype < 1) return -EINVAL; msg = load_msg(msgp->mtext, msgsz); - if(IS_ERR(msg)) + if (IS_ERR(msg)) return PTR_ERR(msg); msg->m_type = mtype; msg->m_ts = msgsz; msq = msg_lock(msqid); - err=-EINVAL; - if(msq==NULL) + err = -EINVAL; + if (msq == NULL) goto out_free; err= -EIDRM; - if (msg_checkid(msq,msqid)) + if (msg_checkid(msq, msqid)) goto out_unlock_free; for (;;) { struct msg_sender s; - err=-EACCES; + err = -EACCES; if (ipcperms(&msq->q_perm, S_IWUGO)) goto out_unlock_free; @@ -604,14 +617,14 @@ asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, if (err) goto out_unlock_free; - if(msgsz + msq->q_cbytes <= msq->q_qbytes && + if (msgsz + msq->q_cbytes <= msq->q_qbytes && 1 + msq->q_qnum <= msq->q_qbytes) { break; } /* queue full, wait: */ - if(msgflg&IPC_NOWAIT) { - err=-EAGAIN; + if (msgflg & IPC_NOWAIT) { + err = -EAGAIN; goto out_unlock_free; } ss_add(msq, &s); @@ -626,9 +639,9 @@ asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, goto out_unlock_free; } ss_del(&s); - + if (signal_pending(current)) { - err=-ERESTARTNOHAND; + err = -ERESTARTNOHAND; goto out_unlock_free; } } @@ -636,47 +649,47 @@ asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, msq->q_lspid = current->tgid; msq->q_stime = get_seconds(); - if(!pipelined_send(msq,msg)) { + if (!pipelined_send(msq, msg)) { /* noone is waiting for this message, enqueue it */ - list_add_tail(&msg->m_list,&msq->q_messages); + list_add_tail(&msg->m_list, &msq->q_messages); msq->q_cbytes += msgsz; msq->q_qnum++; - atomic_add(msgsz,&msg_bytes); + atomic_add(msgsz, &msg_bytes); atomic_inc(&msg_hdrs); } - + err = 0; msg = NULL; out_unlock_free: msg_unlock(msq); out_free: - if(msg!=NULL) + if (msg != NULL) free_msg(msg); return err; } -static inline int convert_mode(long* msgtyp, int msgflg) +static inline int convert_mode(long *msgtyp, int msgflg) { - /* + /* * find message of correct type. * msgtyp = 0 => get first. * msgtyp > 0 => get first message of matching type. - * msgtyp < 0 => get message with least type must be < abs(msgtype). + * msgtyp < 0 => get message with least type must be < abs(msgtype). */ - if(*msgtyp==0) + if (*msgtyp == 0) return SEARCH_ANY; - if(*msgtyp<0) { - *msgtyp=-(*msgtyp); + if (*msgtyp < 0) { + *msgtyp = -*msgtyp; return SEARCH_LESSEQUAL; } - if(msgflg & MSG_EXCEPT) + if (msgflg & MSG_EXCEPT) return SEARCH_NOTEQUAL; return SEARCH_EQUAL; } -asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, - long msgtyp, int msgflg) +asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, + long msgtyp, int msgflg) { struct msg_queue *msq; struct msg_msg *msg; @@ -684,44 +697,51 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, if (msqid < 0 || (long) msgsz < 0) return -EINVAL; - mode = convert_mode(&msgtyp,msgflg); + mode = convert_mode(&msgtyp, msgflg); msq = msg_lock(msqid); - if(msq==NULL) + if (msq == NULL) return -EINVAL; msg = ERR_PTR(-EIDRM); - if (msg_checkid(msq,msqid)) + if (msg_checkid(msq, msqid)) goto out_unlock; for (;;) { struct msg_receiver msr_d; - struct list_head* tmp; + struct list_head *tmp; msg = ERR_PTR(-EACCES); - if (ipcperms (&msq->q_perm, S_IRUGO)) + if (ipcperms(&msq->q_perm, S_IRUGO)) goto out_unlock; msg = ERR_PTR(-EAGAIN); tmp = msq->q_messages.next; while (tmp != &msq->q_messages) { struct msg_msg *walk_msg; - walk_msg = list_entry(tmp,struct msg_msg,m_list); - if(testmsg(walk_msg,msgtyp,mode) && - !security_msg_queue_msgrcv(msq, walk_msg, current, msgtyp, mode)) { + + walk_msg = list_entry(tmp, struct msg_msg, m_list); + if (testmsg(walk_msg, msgtyp, mode) && + !security_msg_queue_msgrcv(msq, walk_msg, current, + msgtyp, mode)) { + msg = walk_msg; - if(mode == SEARCH_LESSEQUAL && walk_msg->m_type != 1) { - msg=walk_msg; - msgtyp=walk_msg->m_type-1; + if (mode == SEARCH_LESSEQUAL && + walk_msg->m_type != 1) { + msg = walk_msg; + msgtyp = walk_msg->m_type - 1; } else { - msg=walk_msg; + msg = walk_msg; break; } } tmp = tmp->next; } - if(!IS_ERR(msg)) { - /* Found a suitable message. Unlink it from the queue. */ + if (!IS_ERR(msg)) { + /* + * Found a suitable message. + * Unlink it from the queue. + */ if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { msg = ERR_PTR(-E2BIG); goto out_unlock; @@ -731,9 +751,9 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, msq->q_rtime = get_seconds(); msq->q_lrpid = current->tgid; msq->q_cbytes -= msg->m_ts; - atomic_sub(msg->m_ts,&msg_bytes); + atomic_sub(msg->m_ts, &msg_bytes); atomic_dec(&msg_hdrs); - ss_wakeup(&msq->q_senders,0); + ss_wakeup(&msq->q_senders, 0); msg_unlock(msq); break; } @@ -742,13 +762,13 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, msg = ERR_PTR(-ENOMSG); goto out_unlock; } - list_add_tail(&msr_d.r_list,&msq->q_receivers); + list_add_tail(&msr_d.r_list, &msq->q_receivers); msr_d.r_tsk = current; msr_d.r_msgtype = msgtyp; msr_d.r_mode = mode; - if(msgflg & MSG_NOERROR) + if (msgflg & MSG_NOERROR) msr_d.r_maxsize = INT_MAX; - else + else msr_d.r_maxsize = msgsz; msr_d.r_msg = ERR_PTR(-EAGAIN); current->state = TASK_INTERRUPTIBLE; @@ -773,17 +793,17 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, * wake_up_process(). There is a race with exit(), see * ipc/mqueue.c for the details. */ - msg = (struct msg_msg*) msr_d.r_msg; + msg = (struct msg_msg*)msr_d.r_msg; while (msg == NULL) { cpu_relax(); - msg = (struct msg_msg*) msr_d.r_msg; + msg = (struct msg_msg *)msr_d.r_msg; } /* Lockless receive, part 3: * If there is a message or an error then accept it without * locking. */ - if(msg != ERR_PTR(-EAGAIN)) { + if (msg != ERR_PTR(-EAGAIN)) { rcu_read_unlock(); break; } @@ -798,7 +818,7 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, * Repeat test after acquiring the spinlock. */ msg = (struct msg_msg*)msr_d.r_msg; - if(msg != ERR_PTR(-EAGAIN)) + if (msg != ERR_PTR(-EAGAIN)) goto out_unlock; list_del(&msr_d.r_list); @@ -810,14 +830,15 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, } } if (IS_ERR(msg)) - return PTR_ERR(msg); + return PTR_ERR(msg); msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; if (put_user (msg->m_type, &msgp->mtype) || store_msg(msgp->mtext, msg, msgsz)) { - msgsz = -EFAULT; + msgsz = -EFAULT; } free_msg(msg); + return msgsz; } @@ -827,20 +848,20 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it) struct msg_queue *msq = it; return seq_printf(s, - "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", - msq->q_perm.key, - msq->q_id, - msq->q_perm.mode, - msq->q_cbytes, - msq->q_qnum, - msq->q_lspid, - msq->q_lrpid, - msq->q_perm.uid, - msq->q_perm.gid, - msq->q_perm.cuid, - msq->q_perm.cgid, - msq->q_stime, - msq->q_rtime, - msq->q_ctime); + "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", + msq->q_perm.key, + msq->q_id, + msq->q_perm.mode, + msq->q_cbytes, + msq->q_qnum, + msq->q_lspid, + msq->q_lrpid, + msq->q_perm.uid, + msq->q_perm.gid, + msq->q_perm.cuid, + msq->q_perm.cgid, + msq->q_stime, + msq->q_rtime, + msq->q_ctime); } #endif diff --git a/trunk/kernel/audit.c b/trunk/kernel/audit.c index d417ca1db79b..0a36091ed712 100644 --- a/trunk/kernel/audit.c +++ b/trunk/kernel/audit.c @@ -690,9 +690,7 @@ static const struct inotify_operations audit_inotify_ops = { /* Initialize audit support at boot time. */ static int __init audit_init(void) { -#ifdef CONFIG_AUDITSYSCALL int i; -#endif printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); @@ -717,10 +715,10 @@ static int __init audit_init(void) audit_ih = inotify_init(&audit_inotify_ops); if (IS_ERR(audit_ih)) audit_panic("cannot initialize inotify handle"); +#endif for (i = 0; i < AUDIT_INODE_BUCKETS; i++) INIT_LIST_HEAD(&audit_inode_hash[i]); -#endif return 0; } diff --git a/trunk/kernel/auditfilter.c b/trunk/kernel/auditfilter.c index 5b4e16276ca0..6a9a5c5a4e7d 100644 --- a/trunk/kernel/auditfilter.c +++ b/trunk/kernel/auditfilter.c @@ -442,6 +442,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_EQUAL: break; default: + err = -EINVAL; goto exit_free; } } @@ -579,6 +580,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_EQUAL: break; default: + err = -EINVAL; goto exit_free; } } @@ -1134,6 +1136,14 @@ static inline int audit_add_rule(struct audit_entry *entry, struct audit_watch *watch = entry->rule.watch; struct nameidata *ndp, *ndw; int h, err, putnd_needed = 0; +#ifdef CONFIG_AUDITSYSCALL + int dont_count = 0; + + /* If either of these, don't count towards total */ + if (entry->rule.listnr == AUDIT_FILTER_USER || + entry->rule.listnr == AUDIT_FILTER_TYPE) + dont_count = 1; +#endif if (inode_f) { h = audit_hash_ino(inode_f->val); @@ -1174,6 +1184,10 @@ static inline int audit_add_rule(struct audit_entry *entry, } else { list_add_tail_rcu(&entry->list, list); } +#ifdef CONFIG_AUDITSYSCALL + if (!dont_count) + audit_n_rules++; +#endif mutex_unlock(&audit_filter_mutex); if (putnd_needed) @@ -1198,6 +1212,14 @@ static inline int audit_del_rule(struct audit_entry *entry, struct audit_watch *watch, *tmp_watch = entry->rule.watch; LIST_HEAD(inotify_list); int h, ret = 0; +#ifdef CONFIG_AUDITSYSCALL + int dont_count = 0; + + /* If either of these, don't count towards total */ + if (entry->rule.listnr == AUDIT_FILTER_USER || + entry->rule.listnr == AUDIT_FILTER_TYPE) + dont_count = 1; +#endif if (inode_f) { h = audit_hash_ino(inode_f->val); @@ -1235,6 +1257,10 @@ static inline int audit_del_rule(struct audit_entry *entry, list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); +#ifdef CONFIG_AUDITSYSCALL + if (!dont_count) + audit_n_rules--; +#endif mutex_unlock(&audit_filter_mutex); if (!list_empty(&inotify_list)) diff --git a/trunk/kernel/auditsc.c b/trunk/kernel/auditsc.c index ae40ac8c39e7..efc1b74bebf3 100644 --- a/trunk/kernel/auditsc.c +++ b/trunk/kernel/auditsc.c @@ -85,6 +85,9 @@ extern int audit_enabled; /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 +/* number of audit rules */ +int audit_n_rules; + /* When fs/namei.c:getname() is called, we store the pointer in name and * we don't let putname() free it (instead we free all of the saved * pointers at syscall exit time). @@ -174,6 +177,7 @@ struct audit_aux_data_path { /* The per-task audit context. */ struct audit_context { + int dummy; /* must be the first element */ int in_syscall; /* 1 if task is in a syscall */ enum audit_state state; unsigned int serial; /* serial number for record */ @@ -514,7 +518,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, context->return_valid = return_valid; context->return_code = return_code; - if (context->in_syscall && !context->auditable) { + if (context->in_syscall && !context->dummy && !context->auditable) { enum audit_state state; state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); @@ -530,17 +534,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, } get_context: - context->pid = tsk->pid; - context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ - context->uid = tsk->uid; - context->gid = tsk->gid; - context->euid = tsk->euid; - context->suid = tsk->suid; - context->fsuid = tsk->fsuid; - context->egid = tsk->egid; - context->sgid = tsk->sgid; - context->fsgid = tsk->fsgid; - context->personality = tsk->personality; + tsk->audit_context = NULL; return context; } @@ -749,6 +743,17 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts const char *tty; /* tsk == current */ + context->pid = tsk->pid; + context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ + context->uid = tsk->uid; + context->gid = tsk->gid; + context->euid = tsk->euid; + context->suid = tsk->suid; + context->fsuid = tsk->fsuid; + context->egid = tsk->egid; + context->sgid = tsk->sgid; + context->fsgid = tsk->fsgid; + context->personality = tsk->personality; ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); if (!ab) @@ -1066,7 +1071,8 @@ void audit_syscall_entry(int arch, int major, context->argv[3] = a4; state = context->state; - if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) + context->dummy = !audit_n_rules; + if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); if (likely(state == AUDIT_DISABLED)) return; @@ -1199,14 +1205,18 @@ void audit_putname(const char *name) #endif } -static void audit_inode_context(int idx, const struct inode *inode) +/* Copy inode data into an audit_names. */ +static void audit_copy_inode(struct audit_names *name, const struct inode *inode) { - struct audit_context *context = current->audit_context; - - selinux_get_inode_sid(inode, &context->names[idx].osid); + name->ino = inode->i_ino; + name->dev = inode->i_sb->s_dev; + name->mode = inode->i_mode; + name->uid = inode->i_uid; + name->gid = inode->i_gid; + name->rdev = inode->i_rdev; + selinux_get_inode_sid(inode, &name->osid); } - /** * audit_inode - store the inode and device from a lookup * @name: name being audited @@ -1240,20 +1250,14 @@ void __audit_inode(const char *name, const struct inode *inode) ++context->ino_count; #endif } - context->names[idx].ino = inode->i_ino; - context->names[idx].dev = inode->i_sb->s_dev; - context->names[idx].mode = inode->i_mode; - context->names[idx].uid = inode->i_uid; - context->names[idx].gid = inode->i_gid; - context->names[idx].rdev = inode->i_rdev; - audit_inode_context(idx, inode); + audit_copy_inode(&context->names[idx], inode); } /** * audit_inode_child - collect inode info for created/removed objects * @dname: inode's dentry name * @inode: inode being audited - * @pino: inode number of dentry parent + * @parent: inode of dentry parent * * For syscalls that create or remove filesystem objects, audit_inode * can only collect information for the filesystem object's parent. @@ -1264,7 +1268,7 @@ void __audit_inode(const char *name, const struct inode *inode) * unsuccessful attempts. */ void __audit_inode_child(const char *dname, const struct inode *inode, - unsigned long pino) + const struct inode *parent) { int idx; struct audit_context *context = current->audit_context; @@ -1278,7 +1282,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, if (!dname) goto update_context; for (idx = 0; idx < context->name_count; idx++) - if (context->names[idx].ino == pino) { + if (context->names[idx].ino == parent->i_ino) { const char *name = context->names[idx].name; if (!name) @@ -1302,16 +1306,47 @@ void __audit_inode_child(const char *dname, const struct inode *inode, context->names[idx].name_len = AUDIT_NAME_FULL; context->names[idx].name_put = 0; /* don't call __putname() */ - if (inode) { - context->names[idx].ino = inode->i_ino; - context->names[idx].dev = inode->i_sb->s_dev; - context->names[idx].mode = inode->i_mode; - context->names[idx].uid = inode->i_uid; - context->names[idx].gid = inode->i_gid; - context->names[idx].rdev = inode->i_rdev; - audit_inode_context(idx, inode); - } else - context->names[idx].ino = (unsigned long)-1; + if (!inode) + context->names[idx].ino = (unsigned long)-1; + else + audit_copy_inode(&context->names[idx], inode); + + /* A parent was not found in audit_names, so copy the inode data for the + * provided parent. */ + if (!found_name) { + idx = context->name_count++; +#if AUDIT_DEBUG + context->ino_count++; +#endif + audit_copy_inode(&context->names[idx], parent); + } +} + +/** + * audit_inode_update - update inode info for last collected name + * @inode: inode being audited + * + * When open() is called on an existing object with the O_CREAT flag, the inode + * data audit initially collects is incorrect. This additional hook ensures + * audit has the inode data for the actual object to be opened. + */ +void __audit_inode_update(const struct inode *inode) +{ + struct audit_context *context = current->audit_context; + int idx; + + if (!context->in_syscall || !inode) + return; + + if (context->name_count == 0) { + context->name_count++; +#if AUDIT_DEBUG + context->ino_count++; +#endif + } + idx = context->name_count - 1; + + audit_copy_inode(&context->names[idx], inode); } /** @@ -1642,7 +1677,7 @@ int audit_bprm(struct linux_binprm *bprm) unsigned long p, next; void *to; - if (likely(!audit_enabled || !context)) + if (likely(!audit_enabled || !context || context->dummy)) return 0; ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, @@ -1680,7 +1715,7 @@ int audit_socketcall(int nargs, unsigned long *args) struct audit_aux_data_socketcall *ax; struct audit_context *context = current->audit_context; - if (likely(!context)) + if (likely(!context || context->dummy)) return 0; ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); @@ -1708,7 +1743,7 @@ int audit_sockaddr(int len, void *a) struct audit_aux_data_sockaddr *ax; struct audit_context *context = current->audit_context; - if (likely(!context)) + if (likely(!context || context->dummy)) return 0; ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); diff --git a/trunk/kernel/delayacct.c b/trunk/kernel/delayacct.c index f05392d64267..57ca3730205d 100644 --- a/trunk/kernel/delayacct.c +++ b/trunk/kernel/delayacct.c @@ -19,15 +19,15 @@ #include #include -int delayacct_on __read_mostly; /* Delay accounting turned on/off */ +int delayacct_on __read_mostly = 1; /* Delay accounting turned on/off */ kmem_cache_t *delayacct_cache; -static int __init delayacct_setup_enable(char *str) +static int __init delayacct_setup_disable(char *str) { - delayacct_on = 1; + delayacct_on = 0; return 1; } -__setup("delayacct", delayacct_setup_enable); +__setup("nodelayacct", delayacct_setup_disable); void delayacct_init(void) { diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 1b0f7b1e0881..aa36c43783cc 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -1387,8 +1387,10 @@ long do_fork(unsigned long clone_flags, if (clone_flags & CLONE_VFORK) { wait_for_completion(&vfork); - if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) + if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) { + current->ptrace_message = nr; ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); + } } } else { free_pid(pid); diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index cf0c8e21d1ab..d4633c588f33 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -297,7 +297,7 @@ static int futex_handle_fault(unsigned long address, int attempt) struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - if (attempt >= 2 || !(vma = find_vma(mm, address)) || + if (attempt > 2 || !(vma = find_vma(mm, address)) || vma->vm_start > address || !(vma->vm_flags & VM_WRITE)) return -EFAULT; @@ -415,15 +415,15 @@ static struct task_struct * futex_find_get_task(pid_t pid) */ void exit_pi_state_list(struct task_struct *curr) { - struct futex_hash_bucket *hb; struct list_head *next, *head = &curr->pi_state_list; struct futex_pi_state *pi_state; + struct futex_hash_bucket *hb; union futex_key key; /* * We are a ZOMBIE and nobody can enqueue itself on * pi_state_list anymore, but we have to be careful - * versus waiters unqueueing themselfs + * versus waiters unqueueing themselves: */ spin_lock_irq(&curr->pi_lock); while (!list_empty(head)) { @@ -431,21 +431,24 @@ void exit_pi_state_list(struct task_struct *curr) next = head->next; pi_state = list_entry(next, struct futex_pi_state, list); key = pi_state->key; + hb = hash_futex(&key); spin_unlock_irq(&curr->pi_lock); - hb = hash_futex(&key); spin_lock(&hb->lock); spin_lock_irq(&curr->pi_lock); + /* + * We dropped the pi-lock, so re-check whether this + * task still owns the PI-state: + */ if (head->next != next) { spin_unlock(&hb->lock); continue; } - list_del_init(&pi_state->list); - WARN_ON(pi_state->owner != curr); - + WARN_ON(list_empty(&pi_state->list)); + list_del_init(&pi_state->list); pi_state->owner = NULL; spin_unlock_irq(&curr->pi_lock); @@ -470,7 +473,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) head = &hb->chain; list_for_each_entry_safe(this, next, head, list) { - if (match_futex (&this->key, &me->key)) { + if (match_futex(&this->key, &me->key)) { /* * Another waiter already exists - bump up * the refcount and return its pi_state: @@ -482,6 +485,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) if (unlikely(!pi_state)) return -EINVAL; + WARN_ON(!atomic_read(&pi_state->refcount)); + atomic_inc(&pi_state->refcount); me->pi_state = pi_state; @@ -490,10 +495,13 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) } /* - * We are the first waiter - try to look up the real owner and - * attach the new pi_state to it: + * We are the first waiter - try to look up the real owner and attach + * the new pi_state to it, but bail out when the owner died bit is set + * and TID = 0: */ pid = uval & FUTEX_TID_MASK; + if (!pid && (uval & FUTEX_OWNER_DIED)) + return -ESRCH; p = futex_find_get_task(pid); if (!p) return -ESRCH; @@ -510,6 +518,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) pi_state->key = me->key; spin_lock_irq(&p->pi_lock); + WARN_ON(!list_empty(&pi_state->list)); list_add(&pi_state->list, &p->pi_state_list); pi_state->owner = p; spin_unlock_irq(&p->pi_lock); @@ -573,20 +582,29 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) * kept enabled while there is PI state around. We must also * preserve the owner died bit.) */ - newval = (uval & FUTEX_OWNER_DIED) | FUTEX_WAITERS | new_owner->pid; + if (!(uval & FUTEX_OWNER_DIED)) { + newval = FUTEX_WAITERS | new_owner->pid; - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); + inc_preempt_count(); + curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); + dec_preempt_count(); + if (curval == -EFAULT) + return -EFAULT; + if (curval != uval) + return -EINVAL; + } - if (curval == -EFAULT) - return -EFAULT; - if (curval != uval) - return -EINVAL; + spin_lock_irq(&pi_state->owner->pi_lock); + WARN_ON(list_empty(&pi_state->list)); + list_del_init(&pi_state->list); + spin_unlock_irq(&pi_state->owner->pi_lock); - list_del_init(&pi_state->owner->pi_state_list); + spin_lock_irq(&new_owner->pi_lock); + WARN_ON(!list_empty(&pi_state->list)); list_add(&pi_state->list, &new_owner->pi_state_list); pi_state->owner = new_owner; + spin_unlock_irq(&new_owner->pi_lock); + rt_mutex_unlock(&pi_state->pi_mutex); return 0; @@ -729,8 +747,10 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, */ if (attempt++) { if (futex_handle_fault((unsigned long)uaddr2, - attempt)) + attempt)) { + ret = -EFAULT; goto out; + } goto retry; } @@ -930,6 +950,7 @@ static int unqueue_me(struct futex_q *q) /* In the common case we don't take the spinlock, which is nice. */ retry: lock_ptr = q->lock_ptr; + barrier(); if (lock_ptr != 0) { spin_lock(lock_ptr); /* @@ -1236,6 +1257,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, /* Owner died? */ if (q.pi_state->owner != NULL) { spin_lock_irq(&q.pi_state->owner->pi_lock); + WARN_ON(list_empty(&q.pi_state->list)); list_del_init(&q.pi_state->list); spin_unlock_irq(&q.pi_state->owner->pi_lock); } else @@ -1244,6 +1266,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, q.pi_state->owner = current; spin_lock_irq(¤t->pi_lock); + WARN_ON(!list_empty(&q.pi_state->list)); list_add(&q.pi_state->list, ¤t->pi_state_list); spin_unlock_irq(¤t->pi_lock); @@ -1301,9 +1324,10 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, * still holding the mmap_sem. */ if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) + if (futex_handle_fault((unsigned long)uaddr, attempt)) { + ret = -EFAULT; goto out_unlock_release_sem; - + } goto retry_locked; } @@ -1427,9 +1451,11 @@ static int futex_unlock_pi(u32 __user *uaddr) * again. If it succeeds then we can return without waking * anyone else up: */ - inc_preempt_count(); - uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); - dec_preempt_count(); + if (!(uval & FUTEX_OWNER_DIED)) { + inc_preempt_count(); + uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); + dec_preempt_count(); + } if (unlikely(uval == -EFAULT)) goto pi_faulted; @@ -1462,9 +1488,11 @@ static int futex_unlock_pi(u32 __user *uaddr) /* * No waiters - kernel unlocks the futex: */ - ret = unlock_futex_pi(uaddr, uval); - if (ret == -EFAULT) - goto pi_faulted; + if (!(uval & FUTEX_OWNER_DIED)) { + ret = unlock_futex_pi(uaddr, uval); + if (ret == -EFAULT) + goto pi_faulted; + } out_unlock: spin_unlock(&hb->lock); @@ -1481,9 +1509,10 @@ static int futex_unlock_pi(u32 __user *uaddr) * still holding the mmap_sem. */ if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) + if (futex_handle_fault((unsigned long)uaddr, attempt)) { + ret = -EFAULT; goto out_unlock; - + } goto retry_locked; } @@ -1683,9 +1712,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, * Process a futex-list entry, check whether it's owned by the * dying task, and do notification if so: */ -int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) +int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) { - u32 uval, nval; + u32 uval, nval, mval; retry: if (get_user(uval, uaddr)) @@ -1702,20 +1731,44 @@ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) * thread-death.) The rest of the cleanup is done in * userspace. */ - nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, - uval | FUTEX_OWNER_DIED); + mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; + nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval); + if (nval == -EFAULT) return -1; if (nval != uval) goto retry; - if (uval & FUTEX_WAITERS) - futex_wake(uaddr, 1); + /* + * Wake robust non-PI futexes here. The wakeup of + * PI futexes happens in exit_pi_state(): + */ + if (!pi) { + if (uval & FUTEX_WAITERS) + futex_wake(uaddr, 1); + } } return 0; } +/* + * Fetch a robust-list pointer. Bit 0 signals PI futexes: + */ +static inline int fetch_robust_entry(struct robust_list __user **entry, + struct robust_list __user **head, int *pi) +{ + unsigned long uentry; + + if (get_user(uentry, (unsigned long *)head)) + return -EFAULT; + + *entry = (void *)(uentry & ~1UL); + *pi = uentry & 1; + + return 0; +} + /* * Walk curr->robust_list (very carefully, it's a userspace list!) * and mark any locks found there dead, and notify any waiters. @@ -1726,14 +1779,14 @@ void exit_robust_list(struct task_struct *curr) { struct robust_list_head __user *head = curr->robust_list; struct robust_list __user *entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT; + unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; unsigned long futex_offset; /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): */ - if (get_user(entry, &head->list.next)) + if (fetch_robust_entry(&entry, &head->list.next, &pi)) return; /* * Fetch the relative futex offset: @@ -1744,10 +1797,11 @@ void exit_robust_list(struct task_struct *curr) * Fetch any possibly pending lock-add first, and handle it * if it exists: */ - if (get_user(pending, &head->list_op_pending)) + if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) return; + if (pending) - handle_futex_death((void *)pending + futex_offset, curr); + handle_futex_death((void *)pending + futex_offset, curr, pip); while (entry != &head->list) { /* @@ -1756,12 +1810,12 @@ void exit_robust_list(struct task_struct *curr) */ if (entry != pending) if (handle_futex_death((void *)entry + futex_offset, - curr)) + curr, pi)) return; /* * Fetch the next entry in the list: */ - if (get_user(entry, &entry->next)) + if (fetch_robust_entry(&entry, &entry->next, &pi)) return; /* * Avoid excessively long or circular lists: diff --git a/trunk/kernel/futex_compat.c b/trunk/kernel/futex_compat.c index d1d92b441fb7..c5cca3f65cb7 100644 --- a/trunk/kernel/futex_compat.c +++ b/trunk/kernel/futex_compat.c @@ -12,6 +12,23 @@ #include + +/* + * Fetch a robust-list pointer. Bit 0 signals PI futexes: + */ +static inline int +fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, + compat_uptr_t *head, int *pi) +{ + if (get_user(*uentry, head)) + return -EFAULT; + + *entry = compat_ptr((*uentry) & ~1); + *pi = (unsigned int)(*uentry) & 1; + + return 0; +} + /* * Walk curr->robust_list (very carefully, it's a userspace list!) * and mark any locks found there dead, and notify any waiters. @@ -22,17 +39,16 @@ void compat_exit_robust_list(struct task_struct *curr) { struct compat_robust_list_head __user *head = curr->compat_robust_list; struct robust_list __user *entry, *pending; + unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; compat_uptr_t uentry, upending; - unsigned int limit = ROBUST_LIST_LIMIT; compat_long_t futex_offset; /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): */ - if (get_user(uentry, &head->list.next)) + if (fetch_robust_entry(&uentry, &entry, &head->list.next, &pi)) return; - entry = compat_ptr(uentry); /* * Fetch the relative futex offset: */ @@ -42,11 +58,11 @@ void compat_exit_robust_list(struct task_struct *curr) * Fetch any possibly pending lock-add first, and handle it * if it exists: */ - if (get_user(upending, &head->list_op_pending)) + if (fetch_robust_entry(&upending, &pending, + &head->list_op_pending, &pip)) return; - pending = compat_ptr(upending); if (upending) - handle_futex_death((void *)pending + futex_offset, curr); + handle_futex_death((void *)pending + futex_offset, curr, pip); while (compat_ptr(uentry) != &head->list) { /* @@ -55,15 +71,15 @@ void compat_exit_robust_list(struct task_struct *curr) */ if (entry != pending) if (handle_futex_death((void *)entry + futex_offset, - curr)) + curr, pi)) return; /* * Fetch the next entry in the list: */ - if (get_user(uentry, (compat_uptr_t *)&entry->next)) + if (fetch_robust_entry(&uentry, &entry, + (compat_uptr_t *)&entry->next, &pi)) return; - entry = compat_ptr(uentry); /* * Avoid excessively long or circular lists: */ diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index d17766d40dab..21c38a7e666b 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -187,7 +187,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base) { struct hrtimer_base *new_base; - new_base = &__get_cpu_var(hrtimer_bases[base->index]); + new_base = &__get_cpu_var(hrtimer_bases)[base->index]; if (base != new_base) { /* @@ -835,7 +835,7 @@ static void migrate_hrtimers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit hrtimer_cpu_notify(struct notifier_block *self, +static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -859,7 +859,7 @@ static int __devinit hrtimer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata hrtimers_nb = { +static struct notifier_block __cpuinitdata hrtimers_nb = { .notifier_call = hrtimer_cpu_notify, }; diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 4e461438e48b..92be519eff26 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -137,16 +137,40 @@ EXPORT_SYMBOL(enable_irq); * @irq: interrupt to control * @on: enable/disable power management wakeup * - * Enable/disable power management wakeup mode + * Enable/disable power management wakeup mode, which is + * disabled by default. Enables and disables must match, + * just as they match for non-wakeup mode support. + * + * Wakeup mode lets this IRQ wake the system from sleep + * states like "suspend to RAM". */ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_desc + irq; unsigned long flags; int ret = -ENXIO; + int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake; + /* wakeup-capable irqs can be shared between drivers that + * don't need to have the same sleep mode behaviors. + */ spin_lock_irqsave(&desc->lock, flags); - if (desc->chip->set_wake) + if (on) { + if (desc->wake_depth++ == 0) + desc->status |= IRQ_WAKEUP; + else + set_wake = NULL; + } else { + if (desc->wake_depth == 0) { + printk(KERN_WARNING "Unbalanced IRQ %d " + "wake disable\n", irq); + WARN_ON(1); + } else if (--desc->wake_depth == 0) + desc->status &= ~IRQ_WAKEUP; + else + set_wake = NULL; + } + if (set_wake) ret = desc->chip->set_wake(irq, on); spin_unlock_irqrestore(&desc->lock, flags); return ret; diff --git a/trunk/kernel/kprobes.c b/trunk/kernel/kprobes.c index 64aab081153b..3f57dfdc8f92 100644 --- a/trunk/kernel/kprobes.c +++ b/trunk/kernel/kprobes.c @@ -393,6 +393,7 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) { copy_kprobe(p, ap); + flush_insn_slot(ap); ap->addr = p->addr; ap->pre_handler = aggr_pre_handler; ap->fault_handler = aggr_fault_handler; diff --git a/trunk/kernel/panic.c b/trunk/kernel/panic.c index d8a0bca21233..9b8dcfd1ca93 100644 --- a/trunk/kernel/panic.c +++ b/trunk/kernel/panic.c @@ -18,6 +18,7 @@ #include #include #include +#include int panic_on_oops; int tainted; diff --git a/trunk/kernel/power/process.c b/trunk/kernel/power/process.c index b2a5f671d6cd..72e72d2c61e6 100644 --- a/trunk/kernel/power/process.c +++ b/trunk/kernel/power/process.c @@ -66,13 +66,25 @@ static inline void freeze_process(struct task_struct *p) } } +static void cancel_freezing(struct task_struct *p) +{ + unsigned long flags; + + if (freezing(p)) { + pr_debug(" clean up: %s\n", p->comm); + do_not_freeze(p); + spin_lock_irqsave(&p->sighand->siglock, flags); + recalc_sigpending_tsk(p); + spin_unlock_irqrestore(&p->sighand->siglock, flags); + } +} + /* 0 = success, else # of processes that we failed to stop */ int freeze_processes(void) { int todo, nr_user, user_frozen; unsigned long start_time; struct task_struct *g, *p; - unsigned long flags; printk( "Stopping tasks: " ); start_time = jiffies; @@ -85,6 +97,10 @@ int freeze_processes(void) continue; if (frozen(p)) continue; + if (p->state == TASK_TRACED && frozen(p->parent)) { + cancel_freezing(p); + continue; + } if (p->mm && !(p->flags & PF_BORROWED_MM)) { /* The task is a user-space one. * Freeze it unless there's a vfork completion @@ -126,13 +142,7 @@ int freeze_processes(void) do_each_thread(g, p) { if (freezeable(p) && !frozen(p)) printk(KERN_ERR " %s\n", p->comm); - if (freezing(p)) { - pr_debug(" clean up: %s\n", p->comm); - p->flags &= ~PF_FREEZE; - spin_lock_irqsave(&p->sighand->siglock, flags); - recalc_sigpending_tsk(p); - spin_unlock_irqrestore(&p->sighand->siglock, flags); - } + cancel_freezing(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); return todo; diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 65ca0688f86f..1149365e989e 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -799,6 +799,9 @@ void release_console_sem(void) up(&secondary_console_sem); return; } + + console_may_schedule = 0; + for ( ; ; ) { spin_lock_irqsave(&logbuf_lock, flags); wake_klogd |= log_start - log_end; @@ -812,7 +815,6 @@ void release_console_sem(void) local_irq_restore(flags); } console_locked = 0; - console_may_schedule = 0; up(&console_sem); spin_unlock_irqrestore(&logbuf_lock, flags); if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) { diff --git a/trunk/kernel/rcupdate.c b/trunk/kernel/rcupdate.c index 759805c9859a..436ab35f6fa7 100644 --- a/trunk/kernel/rcupdate.c +++ b/trunk/kernel/rcupdate.c @@ -548,7 +548,7 @@ static void __devinit rcu_online_cpu(int cpu) tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL); } -static int __devinit rcu_cpu_notify(struct notifier_block *self, +static int __cpuinit rcu_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -565,7 +565,7 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata rcu_nb = { +static struct notifier_block __cpuinitdata rcu_nb = { .notifier_call = rcu_cpu_notify, }; diff --git a/trunk/kernel/resource.c b/trunk/kernel/resource.c index 0dd3a857579e..46286434af80 100644 --- a/trunk/kernel/resource.c +++ b/trunk/kernel/resource.c @@ -244,6 +244,7 @@ int find_next_system_ram(struct resource *res) start = res->start; end = res->end; + BUG_ON(start >= end); read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { @@ -254,15 +255,17 @@ int find_next_system_ram(struct resource *res) p = NULL; break; } - if (p->start >= start) + if ((p->end >= start) && (p->start < end)) break; } read_unlock(&resource_lock); if (!p) return -1; /* copy data */ - res->start = p->start; - res->end = p->end; + if (res->start < p->start) + res->start = p->start; + if (res->end > p->end) + res->end = p->end; return 0; } #endif diff --git a/trunk/kernel/rtmutex.c b/trunk/kernel/rtmutex.c index d2ef13b485e7..3e13a1e5856f 100644 --- a/trunk/kernel/rtmutex.c +++ b/trunk/kernel/rtmutex.c @@ -7,6 +7,8 @@ * Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner * Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt * Copyright (C) 2006 Esben Nielsen + * + * See Documentation/rt-mutex-design.txt for details. */ #include #include diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index b44b9a43b0fc..a2be2d055299 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -4456,9 +4456,9 @@ asmlinkage long sys_sched_yield(void) return 0; } -static inline int __resched_legal(void) +static inline int __resched_legal(int expected_preempt_count) { - if (unlikely(preempt_count())) + if (unlikely(preempt_count() != expected_preempt_count)) return 0; if (unlikely(system_state != SYSTEM_RUNNING)) return 0; @@ -4484,7 +4484,7 @@ static void __cond_resched(void) int __sched cond_resched(void) { - if (need_resched() && __resched_legal()) { + if (need_resched() && __resched_legal(0)) { __cond_resched(); return 1; } @@ -4510,7 +4510,7 @@ int cond_resched_lock(spinlock_t *lock) ret = 1; spin_lock(lock); } - if (need_resched() && __resched_legal()) { + if (need_resched() && __resched_legal(1)) { spin_release(&lock->dep_map, 1, _THIS_IP_); _raw_spin_unlock(lock); preempt_enable_no_resched(); @@ -4526,7 +4526,7 @@ int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched() && __resched_legal()) { + if (need_resched() && __resched_legal(0)) { raw_local_irq_disable(); _local_bh_enable(); raw_local_irq_enable(); @@ -6494,7 +6494,12 @@ static int build_sched_domains(const cpumask_t *cpu_map) for (i = 0; i < MAX_NUMNODES; i++) init_numa_sched_groups_power(sched_group_nodes[i]); - init_numa_sched_groups_power(sched_group_allnodes); + if (sched_group_allnodes) { + int group = cpu_to_allnodes_group(first_cpu(*cpu_map)); + struct sched_group *sg = &sched_group_allnodes[group]; + + init_numa_sched_groups_power(sg); + } #endif /* Attach the domains */ @@ -6761,6 +6766,11 @@ void __init sched_init(void) } set_load_weight(&init_task); + +#ifdef CONFIG_RT_MUTEXES + plist_head_init(&init_task.pi_waiters, &init_task.pi_lock); +#endif + /* * The boot idle thread does lazy MMU switching as well: */ diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 7fe874d12fae..bfdb5686fa3e 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -791,22 +791,31 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) /* * Force a signal that the process can't ignore: if necessary * we unblock the signal and change any SIG_IGN to SIG_DFL. + * + * Note: If we unblock the signal, we always reset it to SIG_DFL, + * since we do not want to have a signal handler that was blocked + * be invoked when user space had explicitly blocked it. + * + * We don't want to have recursive SIGSEGV's etc, for example. */ - int force_sig_info(int sig, struct siginfo *info, struct task_struct *t) { unsigned long int flags; - int ret; + int ret, blocked, ignored; + struct k_sigaction *action; spin_lock_irqsave(&t->sighand->siglock, flags); - if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { - t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; - } - if (sigismember(&t->blocked, sig)) { - sigdelset(&t->blocked, sig); + action = &t->sighand->action[sig-1]; + ignored = action->sa.sa_handler == SIG_IGN; + blocked = sigismember(&t->blocked, sig); + if (blocked || ignored) { + action->sa.sa_handler = SIG_DFL; + if (blocked) { + sigdelset(&t->blocked, sig); + recalc_sigpending_tsk(t); + } } - recalc_sigpending_tsk(t); ret = specific_send_sig_info(sig, info, t); spin_unlock_irqrestore(&t->sighand->siglock, flags); diff --git a/trunk/kernel/softirq.c b/trunk/kernel/softirq.c index 0f08a84ae307..3789ca98197c 100644 --- a/trunk/kernel/softirq.c +++ b/trunk/kernel/softirq.c @@ -65,6 +65,7 @@ static inline void wakeup_softirqd(void) * This one is for softirq.c-internal use, * where hardirqs are disabled legitimately: */ +#ifdef CONFIG_TRACE_IRQFLAGS static void __local_bh_disable(unsigned long ip) { unsigned long flags; @@ -80,6 +81,13 @@ static void __local_bh_disable(unsigned long ip) trace_softirqs_off(ip); raw_local_irq_restore(flags); } +#else /* !CONFIG_TRACE_IRQFLAGS */ +static inline void __local_bh_disable(unsigned long ip) +{ + add_preempt_count(SOFTIRQ_OFFSET); + barrier(); +} +#endif /* CONFIG_TRACE_IRQFLAGS */ void local_bh_disable(void) { @@ -121,12 +129,16 @@ EXPORT_SYMBOL(_local_bh_enable); void local_bh_enable(void) { +#ifdef CONFIG_TRACE_IRQFLAGS unsigned long flags; WARN_ON_ONCE(in_irq()); +#endif WARN_ON_ONCE(irqs_disabled()); +#ifdef CONFIG_TRACE_IRQFLAGS local_irq_save(flags); +#endif /* * Are softirqs going to be turned on now: */ @@ -142,18 +154,22 @@ void local_bh_enable(void) do_softirq(); dec_preempt_count(); +#ifdef CONFIG_TRACE_IRQFLAGS local_irq_restore(flags); +#endif preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable); void local_bh_enable_ip(unsigned long ip) { +#ifdef CONFIG_TRACE_IRQFLAGS unsigned long flags; WARN_ON_ONCE(in_irq()); local_irq_save(flags); +#endif /* * Are softirqs going to be turned on now: */ @@ -169,7 +185,9 @@ void local_bh_enable_ip(unsigned long ip) do_softirq(); dec_preempt_count(); +#ifdef CONFIG_TRACE_IRQFLAGS local_irq_restore(flags); +#endif preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable_ip); @@ -547,7 +565,7 @@ static void takeover_tasklets(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit cpu_callback(struct notifier_block *nfb, +static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -587,7 +605,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __devinitdata cpu_nfb = { +static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/softlockup.c b/trunk/kernel/softlockup.c index 6b76caa22981..03e6a2b0b787 100644 --- a/trunk/kernel/softlockup.c +++ b/trunk/kernel/softlockup.c @@ -104,7 +104,7 @@ static int watchdog(void * __bind_cpu) /* * Create/destroy watchdog threads as CPUs come and go: */ -static int __devinit +static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -142,7 +142,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __devinitdata cpu_nfb = { +static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/taskstats.c b/trunk/kernel/taskstats.c index f45179ce028e..e78187657330 100644 --- a/trunk/kernel/taskstats.c +++ b/trunk/kernel/taskstats.c @@ -121,46 +121,45 @@ static int send_reply(struct sk_buff *skb, pid_t pid) /* * Send taskstats data in @skb to listeners registered for @cpu's exit data */ -static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) +static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) { struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); struct listener_list *listeners; struct listener *s, *tmp; struct sk_buff *skb_next, *skb_cur = skb; void *reply = genlmsg_data(genlhdr); - int rc, ret, delcount = 0; + int rc, delcount = 0; rc = genlmsg_end(skb, reply); if (rc < 0) { nlmsg_free(skb); - return rc; + return; } rc = 0; listeners = &per_cpu(listener_array, cpu); down_read(&listeners->sem); - list_for_each_entry_safe(s, tmp, &listeners->list, list) { + list_for_each_entry(s, &listeners->list, list) { skb_next = NULL; if (!list_is_last(&s->list, &listeners->list)) { skb_next = skb_clone(skb_cur, GFP_KERNEL); - if (!skb_next) { - nlmsg_free(skb_cur); - rc = -ENOMEM; + if (!skb_next) break; - } } - ret = genlmsg_unicast(skb_cur, s->pid); - if (ret == -ECONNREFUSED) { + rc = genlmsg_unicast(skb_cur, s->pid); + if (rc == -ECONNREFUSED) { s->valid = 0; delcount++; - rc = ret; } skb_cur = skb_next; } up_read(&listeners->sem); + if (skb_cur) + nlmsg_free(skb_cur); + if (!delcount) - return rc; + return; /* Delete invalidated entries */ down_write(&listeners->sem); @@ -171,13 +170,12 @@ static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) } } up_write(&listeners->sem); - return rc; } static int fill_pid(pid_t pid, struct task_struct *pidtsk, struct taskstats *stats) { - int rc; + int rc = 0; struct task_struct *tsk = pidtsk; if (!pidtsk) { @@ -196,12 +194,10 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk, * Each accounting subsystem adds calls to its functions to * fill in relevant parts of struct taskstsats as follows * - * rc = per-task-foo(stats, tsk); - * if (rc) - * goto err; + * per-task-foo(stats, tsk); */ - rc = delayacct_add_tsk(stats, tsk); + delayacct_add_tsk(stats, tsk); stats->version = TASKSTATS_VERSION; /* Define err: label here if needed */ diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 05809c2e2fd6..1d7dd6267c2d 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -84,7 +84,7 @@ typedef struct tvec_t_base_s tvec_base_t; tvec_base_t boot_tvec_bases; EXPORT_SYMBOL(boot_tvec_bases); -static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases }; +static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases; static inline void set_running_timer(tvec_base_t *base, struct timer_list *timer) @@ -408,7 +408,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index) * This function cascades all vectors and executes all expired timer * vectors. */ -#define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK +#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) static inline void __run_timers(tvec_base_t *base) { @@ -1324,46 +1324,19 @@ asmlinkage long sys_getpid(void) } /* - * Accessing ->group_leader->real_parent is not SMP-safe, it could - * change from under us. However, rather than getting any lock - * we can use an optimistic algorithm: get the parent - * pid, and go back and check that the parent is still - * the same. If it has changed (which is extremely unlikely - * indeed), we just try again.. - * - * NOTE! This depends on the fact that even if we _do_ - * get an old value of "parent", we can happily dereference - * the pointer (it was and remains a dereferencable kernel pointer - * no matter what): we just can't necessarily trust the result - * until we know that the parent pointer is valid. - * - * NOTE2: ->group_leader never changes from under us. + * Accessing ->real_parent is not SMP-safe, it could + * change from under us. However, we can use a stale + * value of ->real_parent under rcu_read_lock(), see + * release_task()->call_rcu(delayed_put_task_struct). */ asmlinkage long sys_getppid(void) { int pid; - struct task_struct *me = current; - struct task_struct *parent; - parent = me->group_leader->real_parent; - for (;;) { - pid = parent->tgid; -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) -{ - struct task_struct *old = parent; + rcu_read_lock(); + pid = rcu_dereference(current->real_parent)->tgid; + rcu_read_unlock(); - /* - * Make sure we read the pid before re-reading the - * parent pointer: - */ - smp_rmb(); - parent = me->group_leader->real_parent; - if (old != parent) - continue; -} -#endif - break; - } return pid; } @@ -1688,7 +1661,7 @@ static void __devinit migrate_timers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit timer_cpu_notify(struct notifier_block *self, +static int __cpuinit timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1708,7 +1681,7 @@ static int __devinit timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata timers_nb = { +static struct notifier_block __cpuinitdata timers_nb = { .notifier_call = timer_cpu_notify, }; diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index eebb1d839235..835fe28b87a8 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -68,7 +68,7 @@ struct workqueue_struct { /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove threads to each one as cpus come/go. */ -static DEFINE_SPINLOCK(workqueue_lock); +static DEFINE_MUTEX(workqueue_mutex); static LIST_HEAD(workqueues); static int singlethread_cpu; @@ -93,9 +93,12 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, spin_unlock_irqrestore(&cwq->lock, flags); } -/* - * Queue work on a workqueue. Return non-zero if it was successfully - * added. +/** + * queue_work - queue work on a workqueue + * @wq: workqueue to use + * @work: work to queue + * + * Returns non-zero if it was successfully added. * * We queue the work to the CPU it was submitted, but there is no * guarantee that it will be processed by that CPU. @@ -128,6 +131,14 @@ static void delayed_work_timer_fn(unsigned long __data) __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); } +/** + * queue_delayed_work - queue work on a workqueue after delay + * @wq: workqueue to use + * @work: work to queue + * @delay: number of jiffies to wait before queueing + * + * Returns non-zero if it was successfully added. + */ int fastcall queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) { @@ -150,6 +161,15 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, } EXPORT_SYMBOL_GPL(queue_delayed_work); +/** + * queue_delayed_work_on - queue work on specific CPU after delay + * @cpu: CPU number to execute work on + * @wq: workqueue to use + * @work: work to queue + * @delay: number of jiffies to wait before queueing + * + * Returns non-zero if it was successfully added. + */ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) { @@ -275,8 +295,9 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) } } -/* +/** * flush_workqueue - ensure that any scheduled work has run to completion. + * @wq: workqueue to flush * * Forces execution of the workqueue and blocks until its completion. * This is typically used in driver shutdown handlers. @@ -299,10 +320,10 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) } else { int cpu; - lock_cpu_hotplug(); + mutex_lock(&workqueue_mutex); for_each_online_cpu(cpu) flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); - unlock_cpu_hotplug(); + mutex_unlock(&workqueue_mutex); } } EXPORT_SYMBOL_GPL(flush_workqueue); @@ -350,8 +371,7 @@ struct workqueue_struct *__create_workqueue(const char *name, } wq->name = name; - /* We don't need the distraction of CPUs appearing and vanishing. */ - lock_cpu_hotplug(); + mutex_lock(&workqueue_mutex); if (singlethread) { INIT_LIST_HEAD(&wq->list); p = create_workqueue_thread(wq, singlethread_cpu); @@ -360,9 +380,7 @@ struct workqueue_struct *__create_workqueue(const char *name, else wake_up_process(p); } else { - spin_lock(&workqueue_lock); list_add(&wq->list, &workqueues); - spin_unlock(&workqueue_lock); for_each_online_cpu(cpu) { p = create_workqueue_thread(wq, cpu); if (p) { @@ -372,7 +390,7 @@ struct workqueue_struct *__create_workqueue(const char *name, destroy = 1; } } - unlock_cpu_hotplug(); + mutex_unlock(&workqueue_mutex); /* * Was there any error during startup? If yes then clean up: @@ -400,6 +418,12 @@ static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu) kthread_stop(p); } +/** + * destroy_workqueue - safely terminate a workqueue + * @wq: target workqueue + * + * Safely destroy a workqueue. All work currently pending will be done first. + */ void destroy_workqueue(struct workqueue_struct *wq) { int cpu; @@ -407,17 +431,15 @@ void destroy_workqueue(struct workqueue_struct *wq) flush_workqueue(wq); /* We don't need the distraction of CPUs appearing and vanishing. */ - lock_cpu_hotplug(); + mutex_lock(&workqueue_mutex); if (is_single_threaded(wq)) cleanup_workqueue_thread(wq, singlethread_cpu); else { for_each_online_cpu(cpu) cleanup_workqueue_thread(wq, cpu); - spin_lock(&workqueue_lock); list_del(&wq->list); - spin_unlock(&workqueue_lock); } - unlock_cpu_hotplug(); + mutex_unlock(&workqueue_mutex); free_percpu(wq->cpu_wq); kfree(wq); } @@ -425,18 +447,41 @@ EXPORT_SYMBOL_GPL(destroy_workqueue); static struct workqueue_struct *keventd_wq; +/** + * schedule_work - put work task in global workqueue + * @work: job to be done + * + * This puts a job in the kernel-global workqueue. + */ int fastcall schedule_work(struct work_struct *work) { return queue_work(keventd_wq, work); } EXPORT_SYMBOL(schedule_work); +/** + * schedule_delayed_work - put work task in global workqueue after delay + * @work: job to be done + * @delay: number of jiffies to wait + * + * After waiting for a given time this puts a job in the kernel-global + * workqueue. + */ int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) { return queue_delayed_work(keventd_wq, work, delay); } EXPORT_SYMBOL(schedule_delayed_work); +/** + * schedule_delayed_work_on - queue work in global workqueue on CPU after delay + * @cpu: cpu to use + * @work: job to be done + * @delay: number of jiffies to wait + * + * After waiting for a given time this puts a job in the kernel-global + * workqueue on the specified CPU. + */ int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay) { @@ -465,11 +510,13 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info) if (!works) return -ENOMEM; + mutex_lock(&workqueue_mutex); for_each_online_cpu(cpu) { INIT_WORK(per_cpu_ptr(works, cpu), func, info); __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), per_cpu_ptr(works, cpu)); } + mutex_unlock(&workqueue_mutex); flush_workqueue(keventd_wq); free_percpu(works); return 0; @@ -585,6 +632,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: + mutex_lock(&workqueue_mutex); /* Create a new workqueue thread for it. */ list_for_each_entry(wq, &workqueues, list) { if (!create_workqueue_thread(wq, hotcpu)) { @@ -603,6 +651,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, kthread_bind(cwq->thread, hotcpu); wake_up_process(cwq->thread); } + mutex_unlock(&workqueue_mutex); break; case CPU_UP_CANCELED: @@ -614,6 +663,15 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, any_online_cpu(cpu_online_map)); cleanup_workqueue_thread(wq, hotcpu); } + mutex_unlock(&workqueue_mutex); + break; + + case CPU_DOWN_PREPARE: + mutex_lock(&workqueue_mutex); + break; + + case CPU_DOWN_FAILED: + mutex_unlock(&workqueue_mutex); break; case CPU_DEAD: @@ -621,6 +679,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, cleanup_workqueue_thread(wq, hotcpu); list_for_each_entry(wq, &workqueues, list) take_over_work(wq, hotcpu); + mutex_unlock(&workqueue_mutex); break; } diff --git a/trunk/lib/kobject_uevent.c b/trunk/lib/kobject_uevent.c index 2b1530fc573b..7f20e7b857cb 100644 --- a/trunk/lib/kobject_uevent.c +++ b/trunk/lib/kobject_uevent.c @@ -50,10 +50,6 @@ static char *action_to_string(enum kobject_action action) return "offline"; case KOBJ_ONLINE: return "online"; - case KOBJ_DOCK: - return "dock"; - case KOBJ_UNDOCK: - return "undock"; default: return NULL; } diff --git a/trunk/lib/spinlock_debug.c b/trunk/lib/spinlock_debug.c index 3d9c4dc965ed..58c577dd82e5 100644 --- a/trunk/lib/spinlock_debug.c +++ b/trunk/lib/spinlock_debug.c @@ -162,6 +162,7 @@ static void rwlock_bug(rwlock_t *lock, const char *msg) #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) +#if 0 /* __write_lock_debug() can lock up - maybe this can too? */ static void __read_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -184,12 +185,12 @@ static void __read_lock_debug(rwlock_t *lock) } } } +#endif void _raw_read_lock(rwlock_t *lock) { RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); - if (unlikely(!__raw_read_trylock(&lock->raw_lock))) - __read_lock_debug(lock); + __raw_read_lock(&lock->raw_lock); } int _raw_read_trylock(rwlock_t *lock) @@ -235,6 +236,7 @@ static inline void debug_write_unlock(rwlock_t *lock) lock->owner_cpu = -1; } +#if 0 /* This can cause lockups */ static void __write_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -257,12 +259,12 @@ static void __write_lock_debug(rwlock_t *lock) } } } +#endif void _raw_write_lock(rwlock_t *lock) { debug_write_lock_before(lock); - if (unlikely(!__raw_write_trylock(&lock->raw_lock))) - __write_lock_debug(lock); + __raw_write_lock(&lock->raw_lock); debug_write_lock_after(lock); } diff --git a/trunk/lib/zlib_inflate/inflate.c b/trunk/lib/zlib_inflate/inflate.c index 7f922dccf1a5..fceb97c3aff7 100644 --- a/trunk/lib/zlib_inflate/inflate.c +++ b/trunk/lib/zlib_inflate/inflate.c @@ -347,7 +347,10 @@ int zlib_inflate(z_streamp strm, int flush) static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == NULL || strm->state == NULL || strm->next_out == NULL || + /* Do not check for strm->next_out == NULL here as ppc zImage + inflates to strm->next_out = 0 */ + + if (strm == NULL || strm->state == NULL || (strm->next_in == NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; diff --git a/trunk/mm/fadvise.c b/trunk/mm/fadvise.c index 60a5d55e51d9..168c78a121bb 100644 --- a/trunk/mm/fadvise.c +++ b/trunk/mm/fadvise.c @@ -73,7 +73,6 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) file->f_ra.ra_pages = bdi->ra_pages * 2; break; case POSIX_FADV_WILLNEED: - case POSIX_FADV_NOREUSE: if (!mapping->a_ops->readpage) { ret = -EINVAL; break; @@ -94,6 +93,8 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) if (ret > 0) ret = 0; break; + case POSIX_FADV_NOREUSE: + break; case POSIX_FADV_DONTNEED: if (!bdi_write_congested(mapping->backing_dev_info)) filemap_flush(mapping); diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index d087fc3d3281..b9a60c43b61a 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -849,8 +849,6 @@ static void shrink_readahead_size_eio(struct file *filp, return; ra->ra_pages /= 4; - printk(KERN_WARNING "Reducing readahead size to %luK\n", - ra->ra_pages << (PAGE_CACHE_SHIFT - 10)); } /** diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index 01c9fb97c619..c37319542b70 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -52,6 +52,9 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn) int nr_pages = PAGES_PER_SECTION; int ret; + if (pfn_valid(phys_start_pfn)) + return -EEXIST; + ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); if (ret < 0) @@ -76,15 +79,22 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn, { unsigned long i; int err = 0; + int start_sec, end_sec; + /* during initialize mem_map, align hot-added range to section */ + start_sec = pfn_to_section_nr(phys_start_pfn); + end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1); - for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) { - err = __add_section(zone, phys_start_pfn + i); + for (i = start_sec; i <= end_sec; i++) { + err = __add_section(zone, i << PFN_SECTION_SHIFT); - /* We want to keep adding the rest of the - * sections if the first ones already exist + /* + * EEXIST is finally dealed with by ioresource collision + * check. see add_memory() => register_memory_resource() + * Warning will be printed if there is collision. */ if (err && (err != -EEXIST)) break; + err = 0; } return err; @@ -156,7 +166,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) res.flags = IORESOURCE_MEM; /* we just need system ram */ section_end = res.end; - while (find_next_system_ram(&res) >= 0) { + while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { start_pfn = (unsigned long)(res.start >> PAGE_SHIFT); nr_pages = (unsigned long) ((res.end + 1 - res.start) >> PAGE_SHIFT); @@ -213,10 +223,9 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat) } /* add this memory to iomem resource */ -static void register_memory_resource(u64 start, u64 size) +static struct resource *register_memory_resource(u64 start, u64 size) { struct resource *res; - res = kzalloc(sizeof(struct resource), GFP_KERNEL); BUG_ON(!res); @@ -228,7 +237,18 @@ static void register_memory_resource(u64 start, u64 size) printk("System RAM resource %llx - %llx cannot be added\n", (unsigned long long)res->start, (unsigned long long)res->end); kfree(res); + res = NULL; } + return res; +} + +static void release_memory_resource(struct resource *res) +{ + if (!res) + return; + release_resource(res); + kfree(res); + return; } @@ -237,8 +257,13 @@ int add_memory(int nid, u64 start, u64 size) { pg_data_t *pgdat = NULL; int new_pgdat = 0; + struct resource *res; int ret; + res = register_memory_resource(start, size); + if (!res) + return -EEXIST; + if (!node_online(nid)) { pgdat = hotadd_new_pgdat(nid, start); if (!pgdat) @@ -268,14 +293,13 @@ int add_memory(int nid, u64 start, u64 size) BUG_ON(ret); } - /* register this memory as resource */ - register_memory_resource(start, size); - return ret; error: /* rollback pgdat allocation and others */ if (new_pgdat) rollback_node_hotadd(nid, pgdat); + if (res) + release_memory_resource(res); return ret; } diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index 0f20843beffd..21ba06035700 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -1106,7 +1106,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) #endif -static int __devinit cpuup_callback(struct notifier_block *nfb, +static int __cpuinit cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -3224,7 +3224,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) EXPORT_SYMBOL(kmem_cache_alloc); /** - * kmem_cache_alloc - Allocate an object. The memory is set to zero. + * kmem_cache_zalloc - Allocate an object. The memory is set to zero. * @cache: The cache to allocate from. * @flags: See kmalloc(). * diff --git a/trunk/mm/swap.c b/trunk/mm/swap.c index 8fd095c4ae51..687686a61f7c 100644 --- a/trunk/mm/swap.c +++ b/trunk/mm/swap.c @@ -54,6 +54,26 @@ void put_page(struct page *page) } EXPORT_SYMBOL(put_page); +/** + * put_pages_list(): release a list of pages + * + * Release a list of pages which are strung together on page.lru. Currently + * used by read_cache_pages() and related error recovery code. + * + * @pages: list of pages threaded on page->lru + */ +void put_pages_list(struct list_head *pages) +{ + while (!list_empty(pages)) { + struct page *victim; + + victim = list_entry(pages->prev, struct page, lru); + list_del(&victim->lru); + page_cache_release(victim); + } +} +EXPORT_SYMBOL(put_pages_list); + /* * Writeback is about to end against a page which has been marked for immediate * reclaim. If it still appears to be reclaimable, move it to the tail of the diff --git a/trunk/net/atm/proc.c b/trunk/net/atm/proc.c index 3f95b0886a6a..91fe5f53ff11 100644 --- a/trunk/net/atm/proc.c +++ b/trunk/net/atm/proc.c @@ -507,7 +507,7 @@ int __init atm_proc_init(void) goto out; } -void __exit atm_proc_exit(void) +void atm_proc_exit(void) { atm_proc_dirs_remove(); } diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index f55ef682ef84..b1211d5342f6 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -386,12 +386,17 @@ void br_features_recompute(struct net_bridge *br) checksum = 0; if (feature & NETIF_F_GSO) - feature |= NETIF_F_TSO; + feature |= NETIF_F_GSO_SOFTWARE; feature |= NETIF_F_GSO; features &= feature; } + if (!(checksum & NETIF_F_ALL_CSUM)) + features &= ~NETIF_F_SG; + if (!(features & NETIF_F_SG)) + features &= ~NETIF_F_GSO_MASK; + br->dev->features = features | checksum | NETIF_F_LLTX | NETIF_F_GSO_ROBUST; } diff --git a/trunk/net/bridge/br_netfilter.c b/trunk/net/bridge/br_netfilter.c index cbc8a389a0a8..05b3de888243 100644 --- a/trunk/net/bridge/br_netfilter.c +++ b/trunk/net/bridge/br_netfilter.c @@ -61,6 +61,9 @@ static int brnf_filter_vlan_tagged = 1; #define brnf_filter_vlan_tagged 1 #endif +int brnf_deferred_hooks; +EXPORT_SYMBOL_GPL(brnf_deferred_hooks); + static __be16 inline vlan_proto(const struct sk_buff *skb) { return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; @@ -890,6 +893,8 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, return NF_ACCEPT; else if (ip->version == 6 && !brnf_call_ip6tables) return NF_ACCEPT; + else if (!brnf_deferred_hooks) + return NF_ACCEPT; #endif if (hook == NF_IP_POST_ROUTING) return NF_ACCEPT; diff --git a/trunk/net/bridge/br_netlink.c b/trunk/net/bridge/br_netlink.c index 06abb6634f5b..53086fb75089 100644 --- a/trunk/net/bridge/br_netlink.c +++ b/trunk/net/bridge/br_netlink.c @@ -85,7 +85,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) goto err_out; err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); - if (err) + if (err < 0) goto err_kfree; NETLINK_CB(skb).dst_group = RTNLGRP_LINK; diff --git a/trunk/net/bridge/netfilter/ebt_ulog.c b/trunk/net/bridge/netfilter/ebt_ulog.c index 02693a230dc1..9f950db3b76f 100644 --- a/trunk/net/bridge/netfilter/ebt_ulog.c +++ b/trunk/net/bridge/netfilter/ebt_ulog.c @@ -74,6 +74,9 @@ static void ulog_send(unsigned int nlgroup) if (timer_pending(&ub->timer)) del_timer(&ub->timer); + if (!ub->skb) + return; + /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/trunk/net/core/Makefile b/trunk/net/core/Makefile index e9bd2467d5a9..2645ba428d48 100644 --- a/trunk/net/core/Makefile +++ b/trunk/net/core/Makefile @@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o -obj-y += dev.o ethtool.o dev_mcast.o dst.o \ +obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o obj-$(CONFIG_XFRM) += flow.o diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 4d2b5167d7f5..d4a1ec3bded5 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -116,6 +116,7 @@ #include #include #include +#include /* * The list of packet types we will receive (as opposed to discard) @@ -632,14 +633,22 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas * @name: name string * * Network device names need to be valid file names to - * to allow sysfs to work + * to allow sysfs to work. We also disallow any kind of + * whitespace. */ int dev_valid_name(const char *name) { - return !(*name == '\0' - || !strcmp(name, ".") - || !strcmp(name, "..") - || strchr(name, '/')); + if (*name == '\0') + return 0; + if (!strcmp(name, ".") || !strcmp(name, "..")) + return 0; + + while (*name) { + if (*name == '/' || isspace(*name)) + return 0; + name++; + } + return 1; } /** @@ -1166,11 +1175,6 @@ int skb_checksum_help(struct sk_buff *skb, int inward) goto out_set_summed; if (unlikely(skb_shinfo(skb)->gso_size)) { - static int warned; - - WARN_ON(!warned); - warned = 1; - /* Let GSO fix up the checksum. */ goto out_set_summed; } @@ -1220,11 +1224,6 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) __skb_pull(skb, skb->mac_len); if (unlikely(skb->ip_summed != CHECKSUM_HW)) { - static int warned; - - WARN_ON(!warned); - warned = 1; - if (skb_header_cloned(skb) && (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) return ERR_PTR(err); @@ -1629,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) struct net_device *dev = skb->dev; if (dev->master) { - /* - * On bonding slaves other than the currently active - * slave, suppress duplicates except for 802.3ad - * ETH_P_SLOW and alb non-mcast/bcast. - */ - if (dev->priv_flags & IFF_SLAVE_INACTIVE) { - if (dev->master->priv_flags & IFF_MASTER_ALB) { - if (skb->pkt_type != PACKET_BROADCAST && - skb->pkt_type != PACKET_MULTICAST) - goto keep; - } - - if (dev->master->priv_flags & IFF_MASTER_8023AD && - skb->protocol == __constant_htons(ETH_P_SLOW)) - goto keep; - + if (skb_bond_should_drop(skb)) { kfree_skb(skb); return NULL; } -keep: skb->dev = dev->master; } @@ -3429,12 +3412,9 @@ static void net_dma_rebalance(void) unsigned int cpu, i, n; struct dma_chan *chan; - lock_cpu_hotplug(); - if (net_dma_count == 0) { for_each_online_cpu(cpu) - rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL); - unlock_cpu_hotplug(); + rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); return; } @@ -3447,15 +3427,13 @@ static void net_dma_rebalance(void) + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); while(n) { - per_cpu(softnet_data.net_dma, cpu) = chan; + per_cpu(softnet_data, cpu).net_dma = chan; cpu = next_cpu(cpu, cpu_online_map); n--; } i++; } rcu_read_unlock(); - - unlock_cpu_hotplug(); } /** diff --git a/trunk/net/core/dst.c b/trunk/net/core/dst.c index 470c05bc4cb2..1a5e49da0e77 100644 --- a/trunk/net/core/dst.c +++ b/trunk/net/core/dst.c @@ -95,12 +95,11 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc = DST_GC_INC; dst_gc_timer_expires = DST_GC_MIN; } - dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 printk("dst_total: %d/%d %ld\n", atomic_read(&dst_total), delayed, dst_gc_timer_expires); #endif - add_timer(&dst_gc_timer); + mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires); out: spin_unlock(&dst_lock); diff --git a/trunk/net/core/neighbour.c b/trunk/net/core/neighbour.c index 7ad681f5e712..5130d2efdbbe 100644 --- a/trunk/net/core/neighbour.c +++ b/trunk/net/core/neighbour.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -754,6 +755,7 @@ static void neigh_timer_handler(unsigned long arg) neigh->nud_state = NUD_STALE; neigh->updated = jiffies; neigh_suspect(neigh); + notify = 1; } } else if (state & NUD_DELAY) { if (time_before_eq(now, @@ -762,6 +764,7 @@ static void neigh_timer_handler(unsigned long arg) neigh->nud_state = NUD_REACHABLE; neigh->updated = jiffies; neigh_connect(neigh); + notify = 1; next = neigh->confirmed + neigh->parms->reachable_time; } else { NEIGH_PRINTK2("neigh %p is probed.\n", neigh); @@ -819,6 +822,8 @@ static void neigh_timer_handler(unsigned long arg) out: write_unlock(&neigh->lock); } + if (notify) + call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh); #ifdef CONFIG_ARPD if (notify && neigh->parms->app_probes) @@ -926,9 +931,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, { u8 old; int err; -#ifdef CONFIG_ARPD int notify = 0; -#endif struct net_device *dev; int update_isrouter = 0; @@ -948,9 +951,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, neigh_suspect(neigh); neigh->nud_state = new; err = 0; -#ifdef CONFIG_ARPD notify = old & NUD_VALID; -#endif goto out; } @@ -1022,9 +1023,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, if (!(new & NUD_CONNECTED)) neigh->confirmed = jiffies - (neigh->parms->base_reachable_time << 1); -#ifdef CONFIG_ARPD notify = 1; -#endif } if (new == old) goto out; @@ -1056,6 +1055,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, (neigh->flags & ~NTF_ROUTER); } write_unlock_bh(&neigh->lock); + + if (notify) + call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh); #ifdef CONFIG_ARPD if (notify && neigh->parms->app_probes) neigh_app_notify(neigh); diff --git a/trunk/net/core/netevent.c b/trunk/net/core/netevent.c new file mode 100644 index 000000000000..35d02c38554e --- /dev/null +++ b/trunk/net/core/netevent.c @@ -0,0 +1,69 @@ +/* + * Network event notifiers + * + * Authors: + * Tom Tucker + * Steve Wise + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + * Fixes: + */ + +#include +#include + +static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain); + +/** + * register_netevent_notifier - register a netevent notifier block + * @nb: notifier + * + * Register a notifier to be called when a netevent occurs. + * The notifier passed is linked into the kernel structures and must + * not be reused until it has been unregistered. A negative errno code + * is returned on a failure. + */ +int register_netevent_notifier(struct notifier_block *nb) +{ + int err; + + err = atomic_notifier_chain_register(&netevent_notif_chain, nb); + return err; +} + +/** + * netevent_unregister_notifier - unregister a netevent notifier block + * @nb: notifier + * + * Unregister a notifier previously registered by + * register_neigh_notifier(). The notifier is unlinked into the + * kernel structures and may then be reused. A negative errno code + * is returned on a failure. + */ + +int unregister_netevent_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&netevent_notif_chain, nb); +} + +/** + * call_netevent_notifiers - call all netevent notifier blocks + * @val: value passed unmodified to notifier function + * @v: pointer passed unmodified to notifier function + * + * Call all neighbour notifier blocks. Parameters and return value + * are as for notifier_call_chain(). + */ + +int call_netevent_notifiers(unsigned long val, void *v) +{ + return atomic_notifier_call_chain(&netevent_notif_chain, val, v); +} + +EXPORT_SYMBOL_GPL(register_netevent_notifier); +EXPORT_SYMBOL_GPL(unregister_netevent_notifier); +EXPORT_SYMBOL_GPL(call_netevent_notifiers); diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index 67ed14ddabd2..6a7320b39ed0 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -2149,6 +2149,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); skb->dev = odev; skb->pkt_type = PACKET_HOST; + skb->nh.iph = iph; + skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); @@ -2460,6 +2462,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, skb->protocol = protocol; skb->dev = odev; skb->pkt_type = PACKET_HOST; + skb->nh.ipv6h = iph; + skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 20e5bb73f147..30cc1ba6ed5c 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -394,6 +394,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) } if (ida[IFLA_ADDRESS - 1]) { + struct sockaddr *sa; + int len; + if (!dev->set_mac_address) { err = -EOPNOTSUPP; goto out; @@ -405,7 +408,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) goto out; - err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); + len = sizeof(sa_family_t) + dev->addr_len; + sa = kmalloc(len, GFP_KERNEL); + if (!sa) { + err = -ENOMEM; + goto out; + } + sa->sa_family = dev->type; + memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]), + dev->addr_len); + err = dev->set_mac_address(dev, sa); + kfree(sa); if (err) goto out; send_addr_notify = 1; diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 476aa3978504..c54f3664bce5 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -70,13 +70,6 @@ static kmem_cache_t *skbuff_head_cache __read_mostly; static kmem_cache_t *skbuff_fclone_cache __read_mostly; -/* - * lockdep: lock class key used by skb_queue_head_init(): - */ -struct lock_class_key skb_queue_lock_key; - -EXPORT_SYMBOL(skb_queue_lock_key); - /* * Keep out-of-line to prevent kernel bloat. * __builtin_return_address is not used because it is not always @@ -256,6 +249,31 @@ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, goto out; } +/** + * __netdev_alloc_skb - allocate an skbuff for rx on a specific device + * @dev: network device to receive on + * @length: length to allocate + * @gfp_mask: get_free_pages mask, passed to alloc_skb + * + * Allocate a new &sk_buff and assign it a usage count of one. The + * buffer has unspecified headroom built in. Users should allocate + * the headroom they think they need without accounting for the + * built in space. The built in space is used for optimisations. + * + * %NULL is returned if there is no free memory. + */ +struct sk_buff *__netdev_alloc_skb(struct net_device *dev, + unsigned int length, gfp_t gfp_mask) +{ + struct sk_buff *skb; + + skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); + if (likely(skb)) { + skb_reserve(skb, NET_SKB_PAD); + skb->dev = dev; + } + return skb; +} static void skb_drop_list(struct sk_buff **listp) { @@ -846,7 +864,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) return err; - for (i = 0; i < nfrags; i++) { + i = 0; + if (offset >= len) + goto drop_pages; + + for (; i < nfrags; i++) { int end = offset + skb_shinfo(skb)->frags[i].size; if (end < len) { @@ -854,9 +876,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) continue; } - if (len > offset) - skb_shinfo(skb)->frags[i++].size = len - offset; + skb_shinfo(skb)->frags[i++].size = len - offset; +drop_pages: skb_shinfo(skb)->nr_frags = i; for (; i < nfrags; i++) @@ -864,7 +886,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) if (skb_shinfo(skb)->frag_list) skb_drop_fraglist(skb); - break; + goto done; } for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); @@ -879,6 +901,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) return -ENOMEM; nfrag->next = frag->next; + kfree_skb(frag); frag = nfrag; *fragp = frag; } @@ -897,6 +920,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) break; } +done: if (len > skb_headlen(skb)) { skb->data_len -= skb->len - len; skb->len = len; @@ -2042,6 +2066,7 @@ EXPORT_SYMBOL(__kfree_skb); EXPORT_SYMBOL(kfree_skb); EXPORT_SYMBOL(__pskb_pull_tail); EXPORT_SYMBOL(__alloc_skb); +EXPORT_SYMBOL(__netdev_alloc_skb); EXPORT_SYMBOL(pskb_copy); EXPORT_SYMBOL(pskb_expand_head); EXPORT_SYMBOL(skb_checksum); diff --git a/trunk/net/core/utils.c b/trunk/net/core/utils.c index 4f96f389243d..e31c90e05594 100644 --- a/trunk/net/core/utils.c +++ b/trunk/net/core/utils.c @@ -130,12 +130,13 @@ void __init net_random_init(void) static int net_random_reseed(void) { int i; - unsigned long seed[NR_CPUS]; + unsigned long seed; - get_random_bytes(seed, sizeof(seed)); for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); - __net_srandom(state, seed[i]); + + get_random_bytes(&seed, sizeof(seed)); + __net_srandom(state, seed); } return 0; } diff --git a/trunk/net/core/wireless.c b/trunk/net/core/wireless.c index d2bc72d318f7..de0bde4b51dd 100644 --- a/trunk/net/core/wireless.c +++ b/trunk/net/core/wireless.c @@ -82,6 +82,7 @@ #include /* for __init */ #include /* ARPHRD_ETHER */ #include /* compare_ether_addr */ +#include #include /* Pretty obvious */ #include /* New driver API */ @@ -1842,6 +1843,18 @@ int wireless_rtnetlink_set(struct net_device * dev, */ #ifdef WE_EVENT_RTNETLINK +static struct sk_buff_head wireless_nlevent_queue; + +static void wireless_nlevent_process(unsigned long data) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&wireless_nlevent_queue))) + netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); +} + +static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); + /* ---------------------------------------------------------------- */ /* * Fill a rtnetlink message with our event data. @@ -1904,8 +1917,17 @@ static inline void rtmsg_iwinfo(struct net_device * dev, return; } NETLINK_CB(skb).dst_group = RTNLGRP_LINK; - netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); + skb_queue_tail(&wireless_nlevent_queue, skb); + tasklet_schedule(&wireless_nlevent_tasklet); +} + +static int __init wireless_nlevent_init(void) +{ + skb_queue_head_init(&wireless_nlevent_queue); + return 0; } + +subsys_initcall(wireless_nlevent_init); #endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index 9f3d4d7cd0bf..610c722ac27f 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -230,7 +230,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ipv6_addr_copy(&np->saddr, saddr); inet->rcv_saddr = LOOPBACK4_IPV6; - ip6_dst_store(sk, dst, NULL); + __ip6_dst_store(sk, dst, NULL); icsk->icsk_ext_hdr_len = 0; if (np->opt != NULL) @@ -863,7 +863,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, * comment in that function for the gory details. -acme */ - ip6_dst_store(newsk, dst, NULL); + __ip6_dst_store(newsk, dst, NULL); newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | NETIF_F_TSO); newdp6 = (struct dccp6_sock *)newsk; diff --git a/trunk/net/decnet/dn_route.c b/trunk/net/decnet/dn_route.c index 1355614ec11b..743e9fcf7c5a 100644 --- a/trunk/net/decnet/dn_route.c +++ b/trunk/net/decnet/dn_route.c @@ -925,8 +925,13 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old for(dev_out = dev_base; dev_out; dev_out = dev_out->next) { if (!dev_out->dn_ptr) continue; - if (dn_dev_islocal(dev_out, oldflp->fld_src)) - break; + if (!dn_dev_islocal(dev_out, oldflp->fld_src)) + continue; + if ((dev_out->flags & IFF_LOOPBACK) && + oldflp->fld_dst && + !dn_dev_islocal(dev_out, oldflp->fld_dst)) + continue; + break; } read_unlock(&dev_base_lock); if (dev_out == NULL) diff --git a/trunk/net/ieee80211/Kconfig b/trunk/net/ieee80211/Kconfig index dbb08528ddf5..f7e84e9d13ad 100644 --- a/trunk/net/ieee80211/Kconfig +++ b/trunk/net/ieee80211/Kconfig @@ -58,6 +58,7 @@ config IEEE80211_CRYPT_TKIP depends on IEEE80211 && NET_RADIO select CRYPTO select CRYPTO_MICHAEL_MIC + select CRC32 ---help--- Include software based cipher suites in support of IEEE 802.11i (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c b/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c index ebc33ca6e692..4cef39e171d0 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -116,6 +116,16 @@ ieee80211softmac_auth_queue(void *data) kfree(auth); } +/* Sends a response to an auth challenge (for shared key auth). */ +static void +ieee80211softmac_auth_challenge_response(void *_aq) +{ + struct ieee80211softmac_auth_queue_item *aq = _aq; + + /* Send our response */ + ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); +} + /* Handle the auth response from the AP * This should be registered with ieee80211 as handle_auth */ @@ -197,24 +207,30 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: /* Check to make sure we have a challenge IE */ data = (u8 *)auth->info_element; - if(*data++ != MFIE_TYPE_CHALLENGE){ + if (*data++ != MFIE_TYPE_CHALLENGE) { printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); break; } /* Save the challenge */ spin_lock_irqsave(&mac->lock, flags); net->challenge_len = *data++; - if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) + if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - if(net->challenge != NULL) + if (net->challenge != NULL) kfree(net->challenge); net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); memcpy(net->challenge, data, net->challenge_len); aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; - spin_unlock_irqrestore(&mac->lock, flags); - /* Send our response */ - ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); + /* We reuse the work struct from the auth request here. + * It is safe to do so as each one is per-request, and + * at this point (dealing with authentication response) + * we have obviously already sent the initial auth + * request. */ + cancel_delayed_work(&aq->work); + INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq); + schedule_work(&aq->work); + spin_unlock_irqrestore(&mac->lock, flags); return 0; case IEEE80211SOFTMAC_AUTH_SHARED_PASS: kfree(net->challenge); diff --git a/trunk/net/ipv4/fib_semantics.c b/trunk/net/ipv4/fib_semantics.c index 9be53a8e72c3..51738000f3dc 100644 --- a/trunk/net/ipv4/fib_semantics.c +++ b/trunk/net/ipv4/fib_semantics.c @@ -159,7 +159,7 @@ void free_fib_info(struct fib_info *fi) void fib_release_info(struct fib_info *fi) { - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); if (fi && --fi->fib_treeref == 0) { hlist_del(&fi->fib_hash); if (fi->fib_prefsrc) @@ -172,7 +172,7 @@ void fib_release_info(struct fib_info *fi) fi->fib_dead = 1; fib_info_put(fi); } - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); } static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) @@ -598,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, unsigned int old_size = fib_hash_size; unsigned int i, bytes; - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); old_info_hash = fib_info_hash; old_laddrhash = fib_info_laddrhash; fib_hash_size = new_size; @@ -639,7 +639,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, } fib_info_laddrhash = new_laddrhash; - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); bytes = old_size * sizeof(struct hlist_head *); fib_hash_free(old_info_hash, bytes); @@ -820,7 +820,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta, fi->fib_treeref++; atomic_inc(&fi->fib_clntref); - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); hlist_add_head(&fi->fib_hash, &fib_info_hash[fib_info_hashfn(fi)]); if (fi->fib_prefsrc) { @@ -839,7 +839,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta, head = &fib_info_devhash[hash]; hlist_add_head(&nh->nh_hash, head); } endfor_nexthops(fi) - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); return fi; err_inval: diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index 9f4b752f5a33..8e8117c19e4d 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) struct in_device *in_dev; u32 group = imr->imr_multiaddr.s_addr; u32 ifindex; + int ret = -EADDRNOTAVAIL; rtnl_lock(); in_dev = ip_mc_find_dev(imr); - if (!in_dev) { - rtnl_unlock(); - return -ENODEV; - } ifindex = imr->imr_ifindex; for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { - if (iml->multi.imr_multiaddr.s_addr == group && - iml->multi.imr_ifindex == ifindex) { - (void) ip_mc_leave_src(sk, iml, in_dev); + if (iml->multi.imr_multiaddr.s_addr != group) + continue; + if (ifindex) { + if (iml->multi.imr_ifindex != ifindex) + continue; + } else if (imr->imr_address.s_addr && imr->imr_address.s_addr != + iml->multi.imr_address.s_addr) + continue; + + (void) ip_mc_leave_src(sk, iml, in_dev); - *imlp = iml->next; + *imlp = iml->next; + if (in_dev) ip_mc_dec_group(in_dev, group); - rtnl_unlock(); - sock_kfree_s(sk, iml, sizeof(*iml)); - return 0; - } + rtnl_unlock(); + sock_kfree_s(sk, iml, sizeof(*iml)); + return 0; } + if (!in_dev) + ret = -ENODEV; rtnl_unlock(); - return -EADDRNOTAVAIL; + return ret; } int ip_mc_source(int add, int omode, struct sock *sk, struct @@ -2199,13 +2205,13 @@ void ip_mc_drop_socket(struct sock *sk) struct in_device *in_dev; inet->mc_list = iml->next; - if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) { - (void) ip_mc_leave_src(sk, iml, in_dev); + in_dev = inetdev_by_index(iml->multi.imr_ifindex); + (void) ip_mc_leave_src(sk, iml, in_dev); + if (in_dev != NULL) { ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); in_dev_put(in_dev); } sock_kfree_s(sk, iml, sizeof(*iml)); - } rtnl_unlock(); } diff --git a/trunk/net/ipv4/ip_input.c b/trunk/net/ipv4/ip_input.c index 184c78ca79e6..212734ca238f 100644 --- a/trunk/net/ipv4/ip_input.c +++ b/trunk/net/ipv4/ip_input.c @@ -429,7 +429,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, } /* Remove any debris in the socket control block */ - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 7c9f9a6421b8..4c20f5546893 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -526,6 +526,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) err = output(skb); + if (!err) + IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); if (err || !frag) break; @@ -649,9 +651,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) /* * Put this fragment into the sending queue. */ - - IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); - iph->tot_len = htons(len + hlen); ip_send_check(iph); @@ -659,6 +658,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) err = output(skb2); if (err) goto fail; + + IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); } kfree_skb(skb); IP_INC_STATS(IPSTATS_MIB_FRAGOKS); @@ -946,7 +947,7 @@ int ip_append_data(struct sock *sk, skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; @@ -1141,7 +1142,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, data, fraggap, 0); skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } /* diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index 84f43a3c9098..2d05c4133d3e 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -112,14 +112,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) { char *secdata; - u32 seclen; + u32 seclen, secid; int err; - err = security_socket_getpeersec_dgram(skb, &secdata, &seclen); + err = security_socket_getpeersec_dgram(NULL, skb, &secid); + if (err) + return; + + err = security_secid_to_secctx(secid, &secdata, &seclen); if (err) return; put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); + security_release_secctx(secdata, seclen); } diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index 9ccacf57f08b..85893eef6b16 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -1578,6 +1578,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); if (cache==NULL) { + struct sk_buff *skb2; struct net_device *dev; int vif; @@ -1591,12 +1592,18 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) read_unlock(&mrt_lock); return -ENODEV; } - skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); - skb->nh.iph->ihl = sizeof(struct iphdr)>>2; - skb->nh.iph->saddr = rt->rt_src; - skb->nh.iph->daddr = rt->rt_dst; - skb->nh.iph->version = 0; - err = ipmr_cache_unresolved(vif, skb); + skb2 = skb_clone(skb, GFP_ATOMIC); + if (!skb2) { + read_unlock(&mrt_lock); + return -ENOMEM; + } + + skb2->nh.raw = skb_push(skb2, sizeof(struct iphdr)); + skb2->nh.iph->ihl = sizeof(struct iphdr)>>2; + skb2->nh.iph->saddr = rt->rt_src; + skb2->nh.iph->daddr = rt->rt_dst; + skb2->nh.iph->version = 0; + err = ipmr_cache_unresolved(vif, skb2); read_unlock(&mrt_lock); return err; } diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index 80c73ca90116..df4854cf598b 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -1170,21 +1170,34 @@ static int __init arp_tables_init(void) { int ret; - xt_proto_init(NF_ARP); + ret = xt_proto_init(NF_ARP); + if (ret < 0) + goto err1; /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(&arpt_standard_target); - xt_register_target(&arpt_error_target); + ret = xt_register_target(&arpt_standard_target); + if (ret < 0) + goto err2; + ret = xt_register_target(&arpt_error_target); + if (ret < 0) + goto err3; /* Register setsockopt */ ret = nf_register_sockopt(&arpt_sockopts); - if (ret < 0) { - duprintf("Unable to register sockopts.\n"); - return ret; - } + if (ret < 0) + goto err4; printk("arp_tables: (C) 2002 David S. Miller\n"); return 0; + +err4: + xt_unregister_target(&arpt_error_target); +err3: + xt_unregister_target(&arpt_standard_target); +err2: + xt_proto_fini(NF_ARP); +err1: + return ret; } static void __exit arp_tables_fini(void) diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c index af35235672d5..9a39e2969712 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -1200,7 +1200,7 @@ static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct, tuple.dst.protonum = IPPROTO_TCP; exp = __ip_conntrack_expect_find(&tuple); - if (exp->master == ct) + if (exp && exp->master == ct) return exp; return NULL; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c index 33891bb1fde4..0d4cc92391fa 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -415,21 +415,18 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[0], *id); read_lock_bh(&ip_conntrack_lock); + last = (struct ip_conntrack *)cb->args[1]; for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { restart: - last = (struct ip_conntrack *)cb->args[1]; list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { h = (struct ip_conntrack_tuple_hash *) i; if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = tuplehash_to_ctrack(h); - if (last != NULL) { - if (ct == last) { - ip_conntrack_put(last); - cb->args[1] = 0; - last = NULL; - } else + if (cb->args[1]) { + if (ct != last) continue; + cb->args[1] = 0; } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, @@ -440,17 +437,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) goto out; } } - if (last != NULL) { - ip_conntrack_put(last); + if (cb->args[1]) { cb->args[1] = 0; goto restart; } } out: read_unlock_bh(&ip_conntrack_lock); + if (last) + ip_conntrack_put(last); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); - return skb->len; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_sip.c b/trunk/net/ipv4/netfilter/ip_conntrack_sip.c index fc87ce0da40d..4f222d6be009 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_sip.c @@ -442,7 +442,7 @@ static int __init init(void) sip[i].tuple.src.u.udp.port = htons(ports[i]); sip[i].mask.src.u.udp.port = 0xFFFF; sip[i].mask.dst.protonum = 0xFF; - sip[i].max_expected = 1; + sip[i].max_expected = 2; sip[i].timeout = 3 * 60; /* 3 minutes */ sip[i].me = THIS_MODULE; sip[i].help = sip_help; diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c index 7bd3c22003a2..7a9fa04a467a 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -534,6 +534,8 @@ static struct nf_hook_ops ip_conntrack_ops[] = { /* Sysctl support */ +int ip_conntrack_checksum = 1; + #ifdef CONFIG_SYSCTL /* From ip_conntrack_core.c */ @@ -568,8 +570,6 @@ extern unsigned int ip_ct_generic_timeout; static int log_invalid_proto_min = 0; static int log_invalid_proto_max = 255; -int ip_conntrack_checksum = 1; - static struct ctl_table_header *ip_ct_sysctl_header; static ctl_table ip_ct_sysctl_table[] = { diff --git a/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c b/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c index 0b1b416759cc..18b7fbdccb61 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -1255,9 +1255,9 @@ static int help(struct sk_buff **pskb, struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); /* SNMP replies and originating SNMP traps get mangled */ - if (udph->source == ntohs(SNMP_PORT) && dir != IP_CT_DIR_REPLY) + if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY) return NF_ACCEPT; - if (udph->dest == ntohs(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL) + if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL) return NF_ACCEPT; /* No NAT? */ diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index fc5bdd5eb7d3..048514f15f2f 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -230,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ipt_entry *e, *back; - struct xt_table_info *private = table->private; + struct xt_table_info *private; /* Initialization */ ip = (*pskb)->nh.iph; @@ -247,6 +247,7 @@ ipt_do_table(struct sk_buff **pskb, read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); + private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); @@ -2239,22 +2240,39 @@ static int __init ip_tables_init(void) { int ret; - xt_proto_init(AF_INET); + ret = xt_proto_init(AF_INET); + if (ret < 0) + goto err1; /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(&ipt_standard_target); - xt_register_target(&ipt_error_target); - xt_register_match(&icmp_matchstruct); + ret = xt_register_target(&ipt_standard_target); + if (ret < 0) + goto err2; + ret = xt_register_target(&ipt_error_target); + if (ret < 0) + goto err3; + ret = xt_register_match(&icmp_matchstruct); + if (ret < 0) + goto err4; /* Register setsockopt */ ret = nf_register_sockopt(&ipt_sockopts); - if (ret < 0) { - duprintf("Unable to register sockopts.\n"); - return ret; - } + if (ret < 0) + goto err5; printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; + +err5: + xt_unregister_match(&icmp_matchstruct); +err4: + xt_unregister_target(&ipt_error_target); +err3: + xt_unregister_target(&ipt_standard_target); +err2: + xt_proto_fini(AF_INET); +err1: + return ret; } static void __exit ip_tables_fini(void) diff --git a/trunk/net/ipv4/netfilter/ipt_ULOG.c b/trunk/net/ipv4/netfilter/ipt_ULOG.c index d7dd7fe7051c..d46fd677fa11 100644 --- a/trunk/net/ipv4/netfilter/ipt_ULOG.c +++ b/trunk/net/ipv4/netfilter/ipt_ULOG.c @@ -115,6 +115,11 @@ static void ulog_send(unsigned int nlgroupnum) del_timer(&ub->timer); } + if (!ub->skb) { + DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); + return; + } + /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/trunk/net/ipv4/netfilter/ipt_hashlimit.c b/trunk/net/ipv4/netfilter/ipt_hashlimit.c index 92980ab8ce48..3bd2368e1fc9 100644 --- a/trunk/net/ipv4/netfilter/ipt_hashlimit.c +++ b/trunk/net/ipv4/netfilter/ipt_hashlimit.c @@ -454,15 +454,12 @@ hashlimit_match(const struct sk_buff *skb, dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * hinfo->cfg.burst); dh->rateinfo.cost = user2credits(hinfo->cfg.avg); - - spin_unlock_bh(&hinfo->lock); - return 1; + } else { + /* update expiration timeout */ + dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); + rateinfo_recalc(dh, now); } - /* update expiration timeout */ - dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); - - rateinfo_recalc(dh, now); if (dh->rateinfo.credit >= dh->rateinfo.cost) { /* We're underlimit. */ dh->rateinfo.credit -= dh->rateinfo.cost; @@ -508,6 +505,9 @@ hashlimit_checkentry(const char *tablename, if (!r->cfg.expire) return 0; + if (r->name[sizeof(r->name) - 1] != '\0') + return 0; + /* This is the best we've got: We cannot release and re-grab lock, * since checkentry() is called before ip_tables.c grabs ipt_mutex. * We also cannot grab the hashtable spinlock, since htable_create will diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index bd221ec3f81e..62b2762a2420 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -609,6 +609,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (sin) { sin->sin_family = AF_INET; sin->sin_addr.s_addr = skb->nh.iph->saddr; + sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); } if (inet->cmsg_flags) diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 2dc6dbb28467..b873cbcdd0b8 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -104,6 +104,7 @@ #include #include #include +#include #ifdef CONFIG_SYSCTL #include #endif @@ -1125,6 +1126,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, struct rtable *rth, **rthp; u32 skeys[2] = { saddr, 0 }; int ikeys[2] = { dev->ifindex, 0 }; + struct netevent_redirect netevent; if (!in_dev) return; @@ -1216,6 +1218,11 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, rt_drop(rt); goto do_next; } + + netevent.old = &rth->u.dst; + netevent.new = &rt->u.dst; + call_netevent_notifiers(NETEVENT_REDIRECT, + &netevent); rt_del(hash, rth); if (!rt_intern_hash(hash, rt, &rt)) @@ -1452,6 +1459,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } dst->metrics[RTAX_MTU-1] = mtu; dst_set_expires(dst, ip_rt_mtu_expires); + call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); } } @@ -3149,7 +3157,7 @@ int __init ip_rt_init(void) rhash_entries, (num_physpages >= 128 * 1024) ? 15 : 17, - HASH_HIGHMEM, + 0, &rt_hash_log, &rt_hash_mask, 0); diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index f6a2d9223d07..934396bb1376 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -1132,7 +1132,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, tp->ucopy.dma_chan = NULL; preempt_disable(); if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && - !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) { + !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) { preempt_enable_no_resched(); tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); } else @@ -1659,7 +1659,8 @@ void tcp_close(struct sock *sk, long timeout) const int tmo = tcp_fin_time(sk); if (tmo > TCP_TIMEWAIT_LEN) { - inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk)); + inet_csk_reset_keepalive_timer(sk, + tmo - TCP_TIMEWAIT_LEN); } else { tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 738dad9f7d49..104af5d5bcbc 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -3541,7 +3541,8 @@ void tcp_cwnd_application_limited(struct sock *sk) if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open && sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { /* Limited by application or receiver window. */ - u32 win_used = max(tp->snd_cwnd_used, 2U); + u32 init_win = tcp_init_cwnd(tp, __sk_dst_get(sk)); + u32 win_used = max(tp->snd_cwnd_used, init_win); if (win_used < tp->snd_cwnd) { tp->snd_ssthresh = tcp_current_ssthresh(sk); tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1; diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index f6f39e814291..4b04c3edd4a9 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -438,7 +438,6 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) It can f.e. if SYNs crossed. */ if (!sock_owned_by_user(sk)) { - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); sk->sk_err = err; sk->sk_error_report(sk); @@ -874,7 +873,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) drop_and_free: reqsk_free(req); drop: - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); return 0; } diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 0ccb7cb22b15..624e2b2c7f53 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -589,8 +589,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, /* RFC793: "second check the RST bit" and * "fourth, check the SYN bit" */ - if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) + if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); goto embryonic_reset; + } /* ACK sequence verified above, just make sure ACK is * set. If ACK not set, just silently drop the packet. diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index 5c08ea20a18d..507adefbc17c 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -466,7 +466,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (skb->len != tcp_header_size) tcp_event_data_sent(tp, skb, sk); - TCP_INC_STATS(TCP_MIB_OUTSEGS); + if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) + TCP_INC_STATS(TCP_MIB_OUTSEGS); err = icsk->icsk_af_ops->queue_xmit(skb, 0); if (likely(err <= 0)) @@ -2157,10 +2158,9 @@ int tcp_connect(struct sock *sk) skb_shinfo(buff)->gso_size = 0; skb_shinfo(buff)->gso_type = 0; buff->csum = 0; + tp->snd_nxt = tp->write_seq; TCP_SKB_CB(buff)->seq = tp->write_seq++; TCP_SKB_CB(buff)->end_seq = tp->write_seq; - tp->snd_nxt = tp->write_seq; - tp->pushed_seq = tp->write_seq; /* Send it off. */ TCP_SKB_CB(buff)->when = tcp_time_stamp; @@ -2170,6 +2170,12 @@ int tcp_connect(struct sock *sk) sk_charge_skb(sk, buff); tp->packets_out += tcp_skb_pcount(buff); tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); + + /* We change tp->snd_nxt after the tcp_transmit_skb() call + * in order to make this packet get counted in tcpOutSegs. + */ + tp->snd_nxt = tp->write_seq; + tp->pushed_seq = tp->write_seq; TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); /* Timer for repeating the SYN until an answer. */ diff --git a/trunk/net/ipv4/tcp_probe.c b/trunk/net/ipv4/tcp_probe.c index d7d517a3a238..dab37d2f65fc 100644 --- a/trunk/net/ipv4/tcp_probe.c +++ b/trunk/net/ipv4/tcp_probe.c @@ -114,7 +114,7 @@ static int tcpprobe_open(struct inode * inode, struct file * file) static ssize_t tcpprobe_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - int error = 0, cnt; + int error = 0, cnt = 0; unsigned char *tbuf; if (!buf || len < 0) @@ -130,11 +130,12 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf, error = wait_event_interruptible(tcpw.wait, __kfifo_len(tcpw.fifo) != 0); if (error) - return error; + goto out_free; cnt = kfifo_get(tcpw.fifo, tbuf, len); error = copy_to_user(buf, tbuf, cnt); +out_free: vfree(tbuf); return error ? error : cnt; diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 2316a4315a18..0c5042e7380d 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -1869,15 +1869,21 @@ int addrconf_set_dstaddr(void __user *arg) /* * Manual configuration of address on an interface */ -static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) +static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, + __u32 prefered_lft, __u32 valid_lft) { struct inet6_ifaddr *ifp; struct inet6_dev *idev; struct net_device *dev; + __u8 ifa_flags = 0; int scope; ASSERT_RTNL(); + /* check the lifetime */ + if (!valid_lft || prefered_lft > valid_lft) + return -EINVAL; + if ((dev = __dev_get_by_index(ifindex)) == NULL) return -ENODEV; @@ -1889,10 +1895,29 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) scope = ipv6_addr_scope(pfx); - ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); + if (valid_lft == INFINITY_LIFE_TIME) + ifa_flags |= IFA_F_PERMANENT; + else if (valid_lft >= 0x7FFFFFFF/HZ) + valid_lft = 0x7FFFFFFF/HZ; + + if (prefered_lft == 0) + ifa_flags |= IFA_F_DEPRECATED; + else if ((prefered_lft >= 0x7FFFFFFF/HZ) && + (prefered_lft != INFINITY_LIFE_TIME)) + prefered_lft = 0x7FFFFFFF/HZ; + + ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); + if (!IS_ERR(ifp)) { + spin_lock_bh(&ifp->lock); + ifp->valid_lft = valid_lft; + ifp->prefered_lft = prefered_lft; + ifp->tstamp = jiffies; + spin_unlock_bh(&ifp->lock); + addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); + addrconf_verify(0); return 0; } @@ -1945,7 +1970,8 @@ int addrconf_add_ifaddr(void __user *arg) return -EFAULT; rtnl_lock(); - err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); + err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, + INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); rtnl_unlock(); return err; } @@ -2771,12 +2797,16 @@ static void addrconf_verify(unsigned long foo) ifp->idev->nd_parms->retrans_time / HZ; #endif - if (age >= ifp->valid_lft) { + if (ifp->valid_lft != INFINITY_LIFE_TIME && + age >= ifp->valid_lft) { spin_unlock(&ifp->lock); in6_ifa_hold(ifp); read_unlock(&addrconf_hash_lock); ipv6_del_addr(ifp); goto restart; + } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { + spin_unlock(&ifp->lock); + continue; } else if (age >= ifp->prefered_lft) { /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ int deprecate = 0; @@ -2853,7 +2883,8 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) pfx = RTA_DATA(rta[IFA_ADDRESS-1]); } if (rta[IFA_LOCAL-1]) { - if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) + if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) || + (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))) return -EINVAL; pfx = RTA_DATA(rta[IFA_LOCAL-1]); } @@ -2863,12 +2894,62 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); } +static int +inet6_addr_modify(int ifindex, struct in6_addr *pfx, + __u32 prefered_lft, __u32 valid_lft) +{ + struct inet6_ifaddr *ifp = NULL; + struct net_device *dev; + int ifa_flags = 0; + + if ((dev = __dev_get_by_index(ifindex)) == NULL) + return -ENODEV; + + if (!(dev->flags&IFF_UP)) + return -ENETDOWN; + + if (!valid_lft || (prefered_lft > valid_lft)) + return -EINVAL; + + ifp = ipv6_get_ifaddr(pfx, dev, 1); + if (ifp == NULL) + return -ENOENT; + + if (valid_lft == INFINITY_LIFE_TIME) + ifa_flags = IFA_F_PERMANENT; + else if (valid_lft >= 0x7FFFFFFF/HZ) + valid_lft = 0x7FFFFFFF/HZ; + + if (prefered_lft == 0) + ifa_flags = IFA_F_DEPRECATED; + else if ((prefered_lft >= 0x7FFFFFFF/HZ) && + (prefered_lft != INFINITY_LIFE_TIME)) + prefered_lft = 0x7FFFFFFF/HZ; + + spin_lock_bh(&ifp->lock); + ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags; + + ifp->tstamp = jiffies; + ifp->valid_lft = valid_lft; + ifp->prefered_lft = prefered_lft; + + spin_unlock_bh(&ifp->lock); + if (!(ifp->flags&IFA_F_TENTATIVE)) + ipv6_ifa_notify(0, ifp); + in6_ifa_put(ifp); + + addrconf_verify(0); + + return 0; +} + static int inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct rtattr **rta = arg; struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in6_addr *pfx; + __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME; pfx = NULL; if (rta[IFA_ADDRESS-1]) { @@ -2877,14 +2958,34 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) pfx = RTA_DATA(rta[IFA_ADDRESS-1]); } if (rta[IFA_LOCAL-1]) { - if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) + if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) || + (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))) return -EINVAL; pfx = RTA_DATA(rta[IFA_LOCAL-1]); } if (pfx == NULL) return -EINVAL; - return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); + if (rta[IFA_CACHEINFO-1]) { + struct ifa_cacheinfo *ci; + if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci)) + return -EINVAL; + ci = RTA_DATA(rta[IFA_CACHEINFO-1]); + valid_lft = ci->ifa_valid; + prefered_lft = ci->ifa_prefered; + } + + if (nlh->nlmsg_flags & NLM_F_REPLACE) { + int ret; + ret = inet6_addr_modify(ifm->ifa_index, pfx, + prefered_lft, valid_lft); + if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) + return ret; + } + + return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, + prefered_lft, valid_lft); + } /* Maximum length of ifa_cacheinfo attributes */ @@ -3121,6 +3222,62 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) return inet6_dump_addr(skb, cb, type); } +static int inet6_rtm_getaddr(struct sk_buff *in_skb, + struct nlmsghdr* nlh, void *arg) +{ + struct rtattr **rta = arg; + struct ifaddrmsg *ifm = NLMSG_DATA(nlh); + struct in6_addr *addr = NULL; + struct net_device *dev = NULL; + struct inet6_ifaddr *ifa; + struct sk_buff *skb; + int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); + int err; + + if (rta[IFA_ADDRESS-1]) { + if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr)) + return -EINVAL; + addr = RTA_DATA(rta[IFA_ADDRESS-1]); + } + if (rta[IFA_LOCAL-1]) { + if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) || + (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr)))) + return -EINVAL; + addr = RTA_DATA(rta[IFA_LOCAL-1]); + } + if (addr == NULL) + return -EINVAL; + + if (ifm->ifa_index) + dev = __dev_get_by_index(ifm->ifa_index); + + if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) + return -EADDRNOTAVAIL; + + if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) { + err = -ENOBUFS; + goto out; + } + + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, + nlh->nlmsg_seq, RTM_NEWADDR, 0); + if (err < 0) { + err = -EMSGSIZE; + goto out_free; + } + + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + in6_ifa_put(ifa); + return err; +out_free: + kfree_skb(skb); + goto out; +} + static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) { struct sk_buff *skb; @@ -3363,7 +3520,8 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, - [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, }, + [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr, + .dumpit = inet6_dump_ifaddr, }, [RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, }, [RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, }, [RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, }, diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index 5a0ba58b86cc..ac85e9c532c2 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -658,7 +658,7 @@ int inet6_sk_rebuild_header(struct sock *sk) return err; } - ip6_dst_store(sk, dst, NULL); + __ip6_dst_store(sk, dst, NULL); } return 0; diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index 1044b6fce0d5..3d6e9a351150 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -712,6 +712,11 @@ static int icmpv6_rcv(struct sk_buff **pskb) return 0; } +/* + * Special lock-class for __icmpv6_socket: + */ +static struct lock_class_key icmpv6_socket_sk_dst_lock_key; + int __init icmpv6_init(struct net_proto_family *ops) { struct sock *sk; @@ -730,6 +735,14 @@ int __init icmpv6_init(struct net_proto_family *ops) sk = per_cpu(__icmpv6_socket, i)->sk; sk->sk_allocation = GFP_ATOMIC; + /* + * Split off their lock-class, because sk->sk_dst_lock + * gets used from softirqs, which is safe for + * __icmpv6_socket (because those never get directly used + * via userspace syscalls), but unsafe for normal sockets. + */ + lockdep_set_class(&sk->sk_dst_lock, + &icmpv6_socket_sk_dst_lock_key); /* Enough space for 2 64K ICMP packets, including * sk_buff struct overhead. diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index 5c950cc79d80..bf491077b822 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) return err; } - ip6_dst_store(sk, dst, NULL); + __ip6_dst_store(sk, dst, NULL); } skb->dst = dst_clone(dst); diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index df8f051c0fce..25c2a9e03895 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -71,6 +71,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt goto out; } + memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); + /* * Store incoming device index. When the packet will * be queued, we cannot refer to skb->dev anymore. diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 3bc74ce78800..4fb47a252913 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -356,6 +356,7 @@ int ip6_forward(struct sk_buff *skb) skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); + IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -ETIMEDOUT; @@ -595,6 +596,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } err = output(skb); + if(!err) + IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + if (err || !frag) break; @@ -706,12 +710,11 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) /* * Put this fragment into the sending queue. */ - - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); - err = output(frag); if (err) goto fail; + + IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); } kfree_skb(skb); IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); @@ -723,48 +726,51 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) return err; } -int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) +static struct dst_entry *ip6_sk_dst_check(struct sock *sk, + struct dst_entry *dst, + struct flowi *fl) { - int err = 0; + struct ipv6_pinfo *np = inet6_sk(sk); + struct rt6_info *rt = (struct rt6_info *)dst; - *dst = NULL; - if (sk) { - struct ipv6_pinfo *np = inet6_sk(sk); - - *dst = sk_dst_check(sk, np->dst_cookie); - if (*dst) { - struct rt6_info *rt = (struct rt6_info*)*dst; - - /* Yes, checking route validity in not connected - * case is not very simple. Take into account, - * that we do not support routing by source, TOS, - * and MSG_DONTROUTE --ANK (980726) - * - * 1. If route was host route, check that - * cached destination is current. - * If it is network route, we still may - * check its validity using saved pointer - * to the last used address: daddr_cache. - * We do not want to save whole address now, - * (because main consumer of this service - * is tcp, which has not this problem), - * so that the last trick works only on connected - * sockets. - * 2. oif also should be the same. - */ - if (((rt->rt6i_dst.plen != 128 || - !ipv6_addr_equal(&fl->fl6_dst, - &rt->rt6i_dst.addr)) - && (np->daddr_cache == NULL || - !ipv6_addr_equal(&fl->fl6_dst, - np->daddr_cache))) - || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { - dst_release(*dst); - *dst = NULL; - } - } + if (!dst) + goto out; + + /* Yes, checking route validity in not connected + * case is not very simple. Take into account, + * that we do not support routing by source, TOS, + * and MSG_DONTROUTE --ANK (980726) + * + * 1. If route was host route, check that + * cached destination is current. + * If it is network route, we still may + * check its validity using saved pointer + * to the last used address: daddr_cache. + * We do not want to save whole address now, + * (because main consumer of this service + * is tcp, which has not this problem), + * so that the last trick works only on connected + * sockets. + * 2. oif also should be the same. + */ + if (((rt->rt6i_dst.plen != 128 || + !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr)) + && (np->daddr_cache == NULL || + !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache))) + || (fl->oif && fl->oif != dst->dev->ifindex)) { + dst_release(dst); + dst = NULL; } +out: + return dst; +} + +static int ip6_dst_lookup_tail(struct sock *sk, + struct dst_entry **dst, struct flowi *fl) +{ + int err; + if (*dst == NULL) *dst = ip6_route_output(sk, fl); @@ -773,7 +779,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) if (ipv6_addr_any(&fl->fl6_src)) { err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); - if (err) goto out_err_release; } @@ -786,8 +791,48 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) return err; } +/** + * ip6_dst_lookup - perform route lookup on flow + * @sk: socket which provides route info + * @dst: pointer to dst_entry * for result + * @fl: flow to lookup + * + * This function performs a route lookup on the given flow. + * + * It returns zero on success, or a standard errno code on error. + */ +int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) +{ + *dst = NULL; + return ip6_dst_lookup_tail(sk, dst, fl); +} EXPORT_SYMBOL_GPL(ip6_dst_lookup); +/** + * ip6_sk_dst_lookup - perform socket cached route lookup on flow + * @sk: socket which provides the dst cache and route info + * @dst: pointer to dst_entry * for result + * @fl: flow to lookup + * + * This function performs a route lookup on the given flow with the + * possibility of using the cached route in the socket if it is valid. + * It will take the socket dst lock when operating on the dst cache. + * As a result, this function can only be used in process context. + * + * It returns zero on success, or a standard errno code on error. + */ +int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) +{ + *dst = NULL; + if (sk) { + *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); + *dst = ip6_sk_dst_check(sk, *dst, fl); + } + + return ip6_dst_lookup_tail(sk, dst, fl); +} +EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); + static inline int ip6_ufo_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), @@ -1050,7 +1095,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; if (copy < 0) { diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 9d697d4dcffc..639eb20c9f1f 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -268,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { struct inet6_dev *idev = in6_dev_get(dev); + (void) ip6_mc_leave_src(sk, mc_lst, idev); if (idev) { - (void) ip6_mc_leave_src(sk,mc_lst,idev); __ipv6_dev_mc_dec(idev, &mc_lst->addr); in6_dev_put(idev); } dev_put(dev); - } + } else + (void) ip6_mc_leave_src(sk, mc_lst, NULL); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return 0; } @@ -334,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk) if (dev) { struct inet6_dev *idev = in6_dev_get(dev); + (void) ip6_mc_leave_src(sk, mc_lst, idev); if (idev) { - (void) ip6_mc_leave_src(sk, mc_lst, idev); __ipv6_dev_mc_dec(idev, &mc_lst->addr); in6_dev_put(idev); } dev_put(dev); - } + } else + (void) ip6_mc_leave_src(sk, mc_lst, NULL); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index f26898b00347..c9d6b23cd3f7 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -1398,23 +1398,39 @@ static int __init ip6_tables_init(void) { int ret; - xt_proto_init(AF_INET6); + ret = xt_proto_init(AF_INET6); + if (ret < 0) + goto err1; /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(&ip6t_standard_target); - xt_register_target(&ip6t_error_target); - xt_register_match(&icmp6_matchstruct); + ret = xt_register_target(&ip6t_standard_target); + if (ret < 0) + goto err2; + ret = xt_register_target(&ip6t_error_target); + if (ret < 0) + goto err3; + ret = xt_register_match(&icmp6_matchstruct); + if (ret < 0) + goto err4; /* Register setsockopt */ ret = nf_register_sockopt(&ip6t_sockopts); - if (ret < 0) { - duprintf("Unable to register sockopts.\n"); - xt_proto_fini(AF_INET6); - return ret; - } + if (ret < 0) + goto err5; printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; + +err5: + xt_unregister_match(&icmp6_matchstruct); +err4: + xt_unregister_target(&ip6t_error_target); +err3: + xt_unregister_target(&ip6t_standard_target); +err2: + xt_proto_fini(AF_INET6); +err1: + return ret; } static void __exit ip6_tables_fini(void) diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index fa1ce0ae123e..d57e61ce4a7d 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -411,6 +411,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, /* Copy the address. */ if (sin6) { sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); sin6->sin6_flowinfo = 0; sin6->sin6_scope_id = 0; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 87c39c978cd0..4b163711f3a8 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -742,6 +743,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; } dst->metrics[RTAX_MTU-1] = mtu; + call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); } } @@ -1155,6 +1157,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, struct rt6_info *rt, *nrt = NULL; int strict; struct fib6_node *fn; + struct netevent_redirect netevent; /* * Get the "current" route for this destination and @@ -1252,6 +1255,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, if (ip6_ins_rt(nrt, NULL, NULL, NULL)) goto out; + netevent.old = &rt->u.dst; + netevent.new = &nrt->u.dst; + call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); + if (rt->rt6i_flags&RTF_CACHE) { ip6_del_rt(rt, NULL, NULL, NULL); return; diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 923989d0520d..b843a650be71 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -270,7 +270,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, inet->rcv_saddr = LOOPBACK4_IPV6; sk->sk_gso_type = SKB_GSO_TCPV6; - ip6_dst_store(sk, dst, NULL); + __ip6_dst_store(sk, dst, NULL); icsk->icsk_ext_hdr_len = 0; if (np->opt) @@ -427,7 +427,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case TCP_SYN_RECV: /* Cannot happen. It can, it SYNs are crossed. --ANK */ if (!sock_owned_by_user(sk)) { - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); sk->sk_err = err; sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */ @@ -831,7 +830,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (req) reqsk_free(req); - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); return 0; /* don't send reset */ } @@ -947,7 +945,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, */ sk->sk_gso_type = SKB_GSO_TCPV6; - ip6_dst_store(newsk, dst, NULL); + __ip6_dst_store(newsk, dst, NULL); newtcp6sk = (struct tcp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index ccc57f434cd3..3d54f246411e 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -782,7 +782,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, connected = 0; } - err = ip6_dst_lookup(sk, &dst, fl); + err = ip6_sk_dst_lookup(sk, &dst, fl); if (err) goto out; if (final_p) diff --git a/trunk/net/ipv6/xfrm6_output.c b/trunk/net/ipv6/xfrm6_output.c index 0eea60ea9ebc..c8c8b44a0f58 100644 --- a/trunk/net/ipv6/xfrm6_output.c +++ b/trunk/net/ipv6/xfrm6_output.c @@ -125,7 +125,7 @@ static int xfrm6_output_finish(struct sk_buff *skb) if (!skb_is_gso(skb)) return xfrm6_output_finish2(skb); - skb->protocol = htons(ETH_P_IP); + skb->protocol = htons(ETH_P_IPV6); segs = skb_gso_segment(skb, 0); kfree_skb(skb); if (unlikely(IS_ERR(segs))) diff --git a/trunk/net/ipx/af_ipx.c b/trunk/net/ipx/af_ipx.c index aa34ff4b707c..bef3f61569f7 100644 --- a/trunk/net/ipx/af_ipx.c +++ b/trunk/net/ipx/af_ipx.c @@ -1642,13 +1642,17 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; - ipx = ipx_hdr(skb); - ipx_pktsize = ntohs(ipx->ipx_pktsize); + if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) + goto drop; + + ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) + if (ipx_pktsize < sizeof(struct ipxhdr) || + !pskb_may_pull(skb, ipx_pktsize)) goto drop; + ipx = ipx_hdr(skb); if (ipx->ipx_checksum != IPX_NO_CHECKSUM && ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) goto drop; diff --git a/trunk/net/lapb/lapb_iface.c b/trunk/net/lapb/lapb_iface.c index d504eed416f6..7e6bc41eeb21 100644 --- a/trunk/net/lapb/lapb_iface.c +++ b/trunk/net/lapb/lapb_iface.c @@ -238,11 +238,13 @@ int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms) goto out_put; if (lapb->state == LAPB_STATE_0) { - if (((parms->mode & LAPB_EXTENDED) && - (parms->window < 1 || parms->window > 127)) || - (parms->window < 1 || parms->window > 7)) - goto out_put; - + if (parms->mode & LAPB_EXTENDED) { + if (parms->window < 1 || parms->window > 127) + goto out_put; + } else { + if (parms->window < 1 || parms->window > 7) + goto out_put; + } lapb->mode = parms->mode; lapb->window = parms->window; } diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index d6cfe84d521b..2652ead96c64 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -784,24 +784,20 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, copied += used; len -= used; - if (used + offset < skb->len) - continue; - if (!(flags & MSG_PEEK)) { sk_eat_skb(sk, skb, 0); *seq = 0; } + + /* For non stream protcols we get one packet per recvmsg call */ + if (sk->sk_type != SOCK_STREAM) + goto copy_uaddr; + + /* Partial read */ + if (used + offset < skb->len) + continue; } while (len > 0); - /* - * According to UNIX98, msg_name/msg_namelen are ignored - * on connected socket. -ANK - * But... af_llc still doesn't have separate sets of methods for - * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will - * eventually fix this tho :-) -acme - */ - if (sk->sk_type == SOCK_DGRAM) - goto copy_uaddr; out: release_sock(sk); return copied; diff --git a/trunk/net/llc/llc_sap.c b/trunk/net/llc/llc_sap.c index 20c4eb5c1ac6..61cb8cf7d153 100644 --- a/trunk/net/llc/llc_sap.c +++ b/trunk/net/llc/llc_sap.c @@ -51,10 +51,10 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) { struct sockaddr_llc *addr; - if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */ - return; /* save primitive for use by the user. */ addr = llc_ui_skb_cb(skb); + + memset(addr, 0, sizeof(*addr)); addr->sllc_family = sk->sk_family; addr->sllc_arphrd = skb->dev->type; addr->sllc_test = prim == LLC_TEST_PRIM; @@ -330,6 +330,9 @@ static void llc_sap_mcast(struct llc_sap *sap, if (llc->laddr.lsap != laddr->lsap) continue; + if (llc->dev != skb->dev) + continue; + skb1 = skb_clone(skb, GFP_ATOMIC); if (!skb1) break; diff --git a/trunk/net/netfilter/Kconfig b/trunk/net/netfilter/Kconfig index 42a178aa30f9..a9894ddfd72a 100644 --- a/trunk/net/netfilter/Kconfig +++ b/trunk/net/netfilter/Kconfig @@ -386,8 +386,8 @@ config NETFILTER_XT_MATCH_REALM . If unsure, say `N'. config NETFILTER_XT_MATCH_SCTP - tristate '"sctp" protocol match support' - depends on NETFILTER_XTABLES + tristate '"sctp" protocol match support (EXPERIMENTAL)' + depends on NETFILTER_XTABLES && EXPERIMENTAL help With this option enabled, you will be able to use the `sctp' match in order to match on SCTP source/destination ports diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index af4845971f70..6527d4e048d8 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[0], *id); read_lock_bh(&nf_conntrack_lock); + last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: - last = (struct nf_conn *)cb->args[1]; list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { h = (struct nf_conntrack_tuple_hash *) i; if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) @@ -442,13 +442,10 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) * then dump everything. */ if (l3proto && L3PROTO(ct) != l3proto) continue; - if (last != NULL) { - if (ct == last) { - nf_ct_put(last); - cb->args[1] = 0; - last = NULL; - } else + if (cb->args[1]) { + if (ct != last) continue; + cb->args[1] = 0; } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, @@ -459,17 +456,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) goto out; } } - if (last != NULL) { - nf_ct_put(last); + if (cb->args[1]) { cb->args[1] = 0; goto restart; } } out: read_unlock_bh(&nf_conntrack_lock); + if (last) + nf_ct_put(last); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); - return skb->len; } diff --git a/trunk/net/netfilter/nf_conntrack_standalone.c b/trunk/net/netfilter/nf_conntrack_standalone.c index 5fcab2ef231f..4ef836699962 100644 --- a/trunk/net/netfilter/nf_conntrack_standalone.c +++ b/trunk/net/netfilter/nf_conntrack_standalone.c @@ -428,6 +428,8 @@ static struct file_operations ct_cpu_seq_fops = { /* Sysctl support */ +int nf_conntrack_checksum = 1; + #ifdef CONFIG_SYSCTL /* From nf_conntrack_core.c */ @@ -459,8 +461,6 @@ extern unsigned int nf_ct_generic_timeout; static int log_invalid_proto_min = 0; static int log_invalid_proto_max = 255; -int nf_conntrack_checksum = 1; - static struct ctl_table_header *nf_ct_sysctl_header; static ctl_table nf_ct_sysctl_table[] = { diff --git a/trunk/net/netfilter/nf_queue.c b/trunk/net/netfilter/nf_queue.c index bb6fcee452ca..662a869593bf 100644 --- a/trunk/net/netfilter/nf_queue.c +++ b/trunk/net/netfilter/nf_queue.c @@ -219,21 +219,20 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, switch (verdict & NF_VERDICT_MASK) { case NF_ACCEPT: + case NF_STOP: info->okfn(skb); + case NF_STOLEN: break; - case NF_QUEUE: if (!nf_queue(&skb, elem, info->pf, info->hook, info->indev, info->outdev, info->okfn, verdict >> NF_VERDICT_BITS)) goto next_hook; break; + default: + kfree_skb(skb); } rcu_read_unlock(); - - if (verdict == NF_DROP) - kfree_skb(skb); - kfree(info); return; } diff --git a/trunk/net/netfilter/nfnetlink_log.c b/trunk/net/netfilter/nfnetlink_log.c index 61cdda4e5d3b..b59d3b2bde21 100644 --- a/trunk/net/netfilter/nfnetlink_log.c +++ b/trunk/net/netfilter/nfnetlink_log.c @@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *inst) if (timer_pending(&inst->timer)) del_timer(&inst->timer); + if (!inst->skb) + return 0; + if (inst->qlen > 1) inst->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/trunk/net/netfilter/xt_SECMARK.c b/trunk/net/netfilter/xt_SECMARK.c index c2ce9c4011cc..de9537ad9a7c 100644 --- a/trunk/net/netfilter/xt_SECMARK.c +++ b/trunk/net/netfilter/xt_SECMARK.c @@ -57,6 +57,8 @@ static int checkentry_selinux(struct xt_secmark_target_info *info) { int err; struct xt_secmark_target_selinux_info *sel = &info->u.sel; + + sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0'; err = selinux_string_to_sid(sel->selctx, &sel->selsid); if (err) { diff --git a/trunk/net/netfilter/xt_physdev.c b/trunk/net/netfilter/xt_physdev.c index 5fe4c9df17f5..63a965467465 100644 --- a/trunk/net/netfilter/xt_physdev.c +++ b/trunk/net/netfilter/xt_physdev.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -113,6 +114,21 @@ checkentry(const char *tablename, if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || info->bitmask & ~XT_PHYSDEV_OP_MASK) return 0; + if (brnf_deferred_hooks == 0 && + info->bitmask & XT_PHYSDEV_OP_OUT && + (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || + info->invert & XT_PHYSDEV_OP_BRIDGED) && + hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | + (1 << NF_IP_POST_ROUTING))) { + printk(KERN_WARNING "physdev match: using --physdev-out in the " + "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " + "traffic is deprecated and breaks other things, it will " + "be removed in January 2007. See Documentation/" + "feature-removal-schedule.txt for details. This doesn't " + "affect you in case you're using it for purely bridged " + "traffic.\n"); + brnf_deferred_hooks = 1; + } return 1; } diff --git a/trunk/net/netfilter/xt_pkttype.c b/trunk/net/netfilter/xt_pkttype.c index 3ac703b5cb8f..d2f5320a80bf 100644 --- a/trunk/net/netfilter/xt_pkttype.c +++ b/trunk/net/netfilter/xt_pkttype.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -28,9 +30,17 @@ static int match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { + u_int8_t type; const struct xt_pkttype_info *info = matchinfo; - return (skb->pkt_type == info->pkttype) ^ info->invert; + if (skb->pkt_type == PACKET_LOOPBACK) + type = (MULTICAST(skb->nh.iph->daddr) + ? PACKET_MULTICAST + : PACKET_BROADCAST); + else + type = skb->pkt_type; + + return (type == info->pkttype) ^ info->invert; } static struct xt_match pkttype_match = { diff --git a/trunk/net/netfilter/xt_string.c b/trunk/net/netfilter/xt_string.c index 0ebb6ac2c8c7..275330fcdaaa 100644 --- a/trunk/net/netfilter/xt_string.c +++ b/trunk/net/netfilter/xt_string.c @@ -37,7 +37,7 @@ static int match(const struct sk_buff *skb, return (skb_find_text((struct sk_buff *)skb, conf->from_offset, conf->to_offset, conf->config, &state) - != UINT_MAX) && !conf->invert; + != UINT_MAX) ^ conf->invert; } #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) @@ -55,7 +55,10 @@ static int checkentry(const char *tablename, /* Damn, can't handle this case properly with iptables... */ if (conf->from_offset > conf->to_offset) return 0; - + if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') + return 0; + if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) + return 0; ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, GFP_KERNEL, TS_AUTOLOAD); if (IS_ERR(ts_conf)) diff --git a/trunk/net/sched/cls_u32.c b/trunk/net/sched/cls_u32.c index eea366966740..0a6cfa0005be 100644 --- a/trunk/net/sched/cls_u32.c +++ b/trunk/net/sched/cls_u32.c @@ -796,7 +796,7 @@ static int __init init_u32(void) { printk("u32 classifier\n"); #ifdef CONFIG_CLS_U32_PERF - printk(" Perfomance counters on\n"); + printk(" Performance counters on\n"); #endif #ifdef CONFIG_NET_CLS_POLICE printk(" OLD policer on \n"); diff --git a/trunk/net/sched/sch_api.c b/trunk/net/sched/sch_api.c index c7844bacbbcb..a19eff12cf78 100644 --- a/trunk/net/sched/sch_api.c +++ b/trunk/net/sched/sch_api.c @@ -430,7 +430,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) } #endif - err = -EINVAL; + err = -ENOENT; if (ops == NULL) goto err_out; diff --git a/trunk/net/sunrpc/cache.c b/trunk/net/sunrpc/cache.c index 7026b0866b7b..00cb388ece03 100644 --- a/trunk/net/sunrpc/cache.c +++ b/trunk/net/sunrpc/cache.c @@ -71,7 +71,12 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, new = detail->alloc(); if (!new) return NULL; + /* must fully initialise 'new', else + * we might get lose if we need to + * cache_put it soon. + */ cache_init(new); + detail->init(new, key); write_lock(&detail->hash_lock); @@ -85,7 +90,6 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, return tmp; } } - detail->init(new, key); new->next = *head; *head = new; detail->entries++; diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index 4ba271f892c8..d6409e757219 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task) task->tk_status = xprt_prepare_transmit(task); if (task->tk_status != 0) return; + task->tk_action = call_transmit_status; /* Encode here so that rpcsec_gss can use correct sequence number. */ if (rpc_task_need_encode(task)) { - task->tk_rqstp->rq_bytes_sent = 0; + BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); call_encode(task); /* Did the encode result in an error condition? */ if (task->tk_status != 0) - goto out_nosend; + return; } - task->tk_action = call_transmit_status; xprt_transmit(task); if (task->tk_status < 0) return; - if (!task->tk_msg.rpc_proc->p_decode) { - task->tk_action = rpc_exit_task; - rpc_wake_up_task(task); - } - return; -out_nosend: - /* release socket write lock before attempting to handle error */ - xprt_abort_transmit(task); + /* + * On success, ensure that we call xprt_end_transmit() before sleeping + * in order to allow access to the socket to other RPC requests. + */ + call_transmit_status(task); + if (task->tk_msg.rpc_proc->p_decode != NULL) + return; + task->tk_action = rpc_exit_task; + rpc_wake_up_task(task); +} + +/* + * 5a. Handle cleanup after a transmission + */ +static void +call_transmit_status(struct rpc_task *task) +{ + task->tk_action = call_status; + /* + * Special case: if we've been waiting on the socket's write_space() + * callback, then don't call xprt_end_transmit(). + */ + if (task->tk_status == -EAGAIN) + return; + xprt_end_transmit(task); rpc_task_force_reencode(task); } @@ -992,18 +1009,7 @@ call_status(struct rpc_task *task) } /* - * 6a. Handle transmission errors. - */ -static void -call_transmit_status(struct rpc_task *task) -{ - if (task->tk_status != -EAGAIN) - rpc_task_force_reencode(task); - call_status(task); -} - -/* - * 6b. Handle RPC timeout + * 6a. Handle RPC timeout * We do not release the request slot, so we keep using the * same XID for all retransmits. */ diff --git a/trunk/net/sunrpc/rpc_pipe.c b/trunk/net/sunrpc/rpc_pipe.c index dc6cb93c8830..a3bd2db2e024 100644 --- a/trunk/net/sunrpc/rpc_pipe.c +++ b/trunk/net/sunrpc/rpc_pipe.c @@ -667,10 +667,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) RPCAUTH_info, RPCAUTH_EOF); if (error) goto err_depopulate; + dget(dentry); out: mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); - return dget(dentry); + return dentry; err_depopulate: rpc_depopulate(dentry); __rpc_rmdir(dir, dentry); @@ -731,10 +732,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) rpci->flags = flags; rpci->ops = ops; inode_dir_notify(dir, DN_CREATE); + dget(dentry); out: mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); - return dget(dentry); + return dentry; err_dput: dput(dentry); dentry = ERR_PTR(-ENOMEM); diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index 313b68d892c6..e8c2bc4977f3 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -707,12 +707,9 @@ int xprt_prepare_transmit(struct rpc_task *task) return err; } -void -xprt_abort_transmit(struct rpc_task *task) +void xprt_end_transmit(struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; - - xprt_release_write(xprt, task); + xprt_release_write(task->tk_xprt, task); } /** @@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task) task->tk_status = -ENOTCONN; else if (!req->rq_received) rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); - - xprt->ops->release_xprt(xprt, task); spin_unlock_bh(&xprt->transport_lock); return; } @@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task) * schedq, and being picked up by a parallel run of rpciod(). */ task->tk_status = status; - - switch (status) { - case -ECONNREFUSED: + if (status == -ECONNREFUSED) rpc_sleep_on(&xprt->sending, task, NULL, NULL); - case -EAGAIN: - case -ENOTCONN: - return; - default: - break; - } - xprt_release_write(xprt, task); - return; } static inline void do_xprt_reserve(struct rpc_task *task) diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index ee678ed13b6f..441bd53f5eca 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -413,6 +413,33 @@ static int xs_tcp_send_request(struct rpc_task *task) return status; } +/** + * xs_tcp_release_xprt - clean up after a tcp transmission + * @xprt: transport + * @task: rpc task + * + * This cleans up if an error causes us to abort the transmission of a request. + * In this case, the socket may need to be reset in order to avoid confusing + * the server. + */ +static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) +{ + struct rpc_rqst *req; + + if (task != xprt->snd_task) + return; + if (task == NULL) + goto out_release; + req = task->tk_rqstp; + if (req->rq_bytes_sent == 0) + goto out_release; + if (req->rq_bytes_sent == req->rq_snd_buf.len) + goto out_release; + set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state); +out_release: + xprt_release_xprt(xprt, task); +} + /** * xs_close - close a socket * @xprt: transport @@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, - .release_xprt = xprt_release_xprt, + .release_xprt = xs_tcp_release_xprt, .set_port = xs_set_port, .connect = xs_connect, .buf_alloc = rpc_malloc, diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index 6f2909279268..de6ec519272e 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -128,23 +128,17 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0); #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) #ifdef CONFIG_SECURITY_NETWORK -static void unix_get_peersec_dgram(struct sk_buff *skb) +static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) { - int err; - - err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb), - UNIXSECLEN(skb)); - if (err) - *(UNIXSECDATA(skb)) = NULL; + memcpy(UNIXSID(skb), &scm->secid, sizeof(u32)); } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) { - scm->secdata = *UNIXSECDATA(skb); - scm->seclen = *UNIXSECLEN(skb); + scm->secid = *UNIXSID(skb); } #else -static inline void unix_get_peersec_dgram(struct sk_buff *skb) +static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) { } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) @@ -1322,8 +1316,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); if (siocb->scm->fp) unix_attach_fds(siocb->scm, skb); - - unix_get_peersec_dgram(skb); + unix_get_secdata(siocb->scm, skb); skb->h.raw = skb->data; err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index f35bc676128c..3da67ca2c3ce 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -1134,12 +1134,33 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) } EXPORT_SYMBOL(__xfrm_route_forward); +/* Optimize later using cookies and generation ids. */ + static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) { - /* If it is marked obsolete, which is how we even get here, - * then we have purged it from the policy bundle list and we - * did that for a good reason. + /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete + * to "-1" to force all XFRM destinations to get validated by + * dst_ops->check on every use. We do this because when a + * normal route referenced by an XFRM dst is obsoleted we do + * not go looking around for all parent referencing XFRM dsts + * so that we can invalidate them. It is just too much work. + * Instead we make the checks here on every use. For example: + * + * XFRM dst A --> IPv4 dst X + * + * X is the "xdst->route" of A (X is also the "dst->path" of A + * in this example). If X is marked obsolete, "A" will not + * notice. That's what we are validating here via the + * stale_bundle() check. + * + * When a policy's bundle is pruned, we dst_free() the XFRM + * dst which causes it's ->obsolete field to be set to a + * positive non-zero integer. If an XFRM dst has been pruned + * like this, we want to force a new route lookup. */ + if (dst->obsolete < 0 && !stale_bundle(dst)) + return dst; + return NULL; } diff --git a/trunk/scripts/Kbuild.include b/trunk/scripts/Kbuild.include index 2180c88cfe89..bb19c1561f1e 100644 --- a/trunk/scripts/Kbuild.include +++ b/trunk/scripts/Kbuild.include @@ -77,14 +77,20 @@ cc-option-align = $(subst -functions=0,,\ # cc-version # Usage gcc-ver := $(call cc-version, $(CC)) -cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ - $(if $(1), $(1), $(CC))) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) # cc-ifversion # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \ echo $(3); fi;) +# ld-option +# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both) +ld-option = $(shell if $(CC) $(1) \ + -nostdlib -o ldtest$$$$.out -xc /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi; \ + rm -f ldtest$$$$.out) + ### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: diff --git a/trunk/scripts/Makefile.modpost b/trunk/scripts/Makefile.modpost index a49550205dcc..0a64688c2b5d 100644 --- a/trunk/scripts/Makefile.modpost +++ b/trunk/scripts/Makefile.modpost @@ -40,7 +40,7 @@ include scripts/Kbuild.include include scripts/Makefile.lib kernelsymfile := $(objtree)/Module.symvers -modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers +modulesymfile := $(KBUILD_EXTMOD)/Module.symvers # Step 1), find all modules listed in $(MODVERDIR)/ __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) diff --git a/trunk/scripts/kconfig/confdata.c b/trunk/scripts/kconfig/confdata.c index 2ee48c377b66..a69d8acbf274 100644 --- a/trunk/scripts/kconfig/confdata.c +++ b/trunk/scripts/kconfig/confdata.c @@ -357,7 +357,7 @@ int conf_read(const char *name) for (e = prop->expr; e; e = e->left.expr) if (e->right.sym->visible != no) flags &= e->right.sym->flags; - sym->flags |= flags & SYMBOL_DEF_USER; + sym->flags &= flags | ~SYMBOL_DEF_USER; } sym_change_count += conf_warnings || conf_unsaved; diff --git a/trunk/scripts/kernel-doc b/trunk/scripts/kernel-doc index f9460a6218de..c9ca0c23bd91 100755 --- a/trunk/scripts/kernel-doc +++ b/trunk/scripts/kernel-doc @@ -1518,6 +1518,7 @@ sub dump_function($$) { $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; + $prototype =~ s/__devinit +//; $prototype =~ s/^#define +//; #ak added $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//; diff --git a/trunk/scripts/mod/file2alias.c b/trunk/scripts/mod/file2alias.c index 37f67c23e11b..e2de650d3dbf 100644 --- a/trunk/scripts/mod/file2alias.c +++ b/trunk/scripts/mod/file2alias.c @@ -52,6 +52,23 @@ do { \ sprintf(str + strlen(str), "*"); \ } while(0) +/** + * Check that sizeof(device_id type) are consistent with size of section + * in .o file. If in-consistent then userspace and kernel does not agree + * on actual size which is a bug. + **/ +static void device_id_size_check(const char *modname, const char *device_id, + unsigned long size, unsigned long id_size) +{ + if (size % id_size || size < id_size) { + fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " + "of the size of section __mod_%s_device_table=%lu.\n" + "Fix definition of struct %s_device_id " + "in mod_devicetable.h\n", + modname, device_id, id_size, device_id, size, device_id); + } +} + /* USB is special because the bcdDevice can be matched against a numeric range */ /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ static void do_usb_entry(struct usb_device_id *id, @@ -152,10 +169,8 @@ static void do_usb_table(void *symval, unsigned long size, unsigned int i; const unsigned long id_size = sizeof(struct usb_device_id); - if (size % id_size || size < id_size) { - warn("%s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); - } + device_id_size_check(mod->name, "usb", size, id_size); + /* Leave last one: it's the terminator. */ size -= id_size; @@ -376,7 +391,7 @@ static void do_input(char *alias, unsigned int i; for (i = min; i < max; i++) - if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) + if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) sprintf(alias + strlen(alias), "%X,*", i); } @@ -434,6 +449,7 @@ static inline int sym_is(const char *symbol, const char *name) static void do_table(void *symval, unsigned long size, unsigned long id_size, + const char *device_id, void *function, struct module *mod) { @@ -441,10 +457,7 @@ static void do_table(void *symval, unsigned long size, char alias[500]; int (*do_entry)(const char *, void *entry, char *alias) = function; - if (size % id_size || size < id_size) { - warn("%s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); - } + device_id_size_check(mod->name, device_id, size, id_size); /* Leave last one: it's the terminator. */ size -= id_size; @@ -476,40 +489,51 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + sym->st_value; if (sym_is(symname, "__mod_pci_device_table")) - do_table(symval, sym->st_size, sizeof(struct pci_device_id), + do_table(symval, sym->st_size, + sizeof(struct pci_device_id), "pci", do_pci_entry, mod); else if (sym_is(symname, "__mod_usb_device_table")) /* special case to handle bcdDevice ranges */ do_usb_table(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_ieee1394_device_table")) - do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), + do_table(symval, sym->st_size, + sizeof(struct ieee1394_device_id), "ieee1394", do_ieee1394_entry, mod); else if (sym_is(symname, "__mod_ccw_device_table")) - do_table(symval, sym->st_size, sizeof(struct ccw_device_id), + do_table(symval, sym->st_size, + sizeof(struct ccw_device_id), "ccw", do_ccw_entry, mod); else if (sym_is(symname, "__mod_serio_device_table")) - do_table(symval, sym->st_size, sizeof(struct serio_device_id), + do_table(symval, sym->st_size, + sizeof(struct serio_device_id), "serio", do_serio_entry, mod); else if (sym_is(symname, "__mod_pnp_device_table")) - do_table(symval, sym->st_size, sizeof(struct pnp_device_id), + do_table(symval, sym->st_size, + sizeof(struct pnp_device_id), "pnp", do_pnp_entry, mod); else if (sym_is(symname, "__mod_pnp_card_device_table")) - do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), + do_table(symval, sym->st_size, + sizeof(struct pnp_card_device_id), "pnp_card", do_pnp_card_entry, mod); else if (sym_is(symname, "__mod_pcmcia_device_table")) - do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id), + do_table(symval, sym->st_size, + sizeof(struct pcmcia_device_id), "pcmcia", do_pcmcia_entry, mod); else if (sym_is(symname, "__mod_of_device_table")) - do_table(symval, sym->st_size, sizeof(struct of_device_id), + do_table(symval, sym->st_size, + sizeof(struct of_device_id), "of", do_of_entry, mod); else if (sym_is(symname, "__mod_vio_device_table")) - do_table(symval, sym->st_size, sizeof(struct vio_device_id), + do_table(symval, sym->st_size, + sizeof(struct vio_device_id), "vio", do_vio_entry, mod); else if (sym_is(symname, "__mod_i2c_device_table")) - do_table(symval, sym->st_size, sizeof(struct i2c_device_id), + do_table(symval, sym->st_size, + sizeof(struct i2c_device_id), "i2c", do_i2c_entry, mod); else if (sym_is(symname, "__mod_input_device_table")) - do_table(symval, sym->st_size, sizeof(struct input_device_id), + do_table(symval, sym->st_size, + sizeof(struct input_device_id), "input", do_input_entry, mod); } diff --git a/trunk/security/dummy.c b/trunk/security/dummy.c index bbbfda70e131..58c6d399c844 100644 --- a/trunk/security/dummy.c +++ b/trunk/security/dummy.c @@ -791,8 +791,7 @@ static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optv return -ENOPROTOOPT; } -static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, - u32 *seclen) +static int dummy_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { return -ENOPROTOOPT; } @@ -876,6 +875,15 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz return -EINVAL; } +static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + return -EOPNOTSUPP; +} + +static void dummy_release_secctx(char *secdata, u32 seclen) +{ +} + #ifdef CONFIG_KEYS static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, unsigned long flags) @@ -1028,6 +1036,8 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, d_instantiate); set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); + set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); set_to_dummy_if_null(ops, unix_may_send); diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index a91c961ba38b..5d1b8c733199 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -3524,25 +3524,21 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op return err; } -static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) +static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { + u32 peer_secid = SECSID_NULL; int err = 0; - u32 peer_sid; - if (skb->sk->sk_family == PF_UNIX) - selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket), - &peer_sid); - else - peer_sid = selinux_socket_getpeer_dgram(skb); - - if (peer_sid == SECSID_NULL) - return -EINVAL; + if (sock && (sock->sk->sk_family == PF_UNIX)) + selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); + else if (skb) + peer_secid = selinux_socket_getpeer_dgram(skb); - err = security_sid_to_context(peer_sid, secdata, seclen); - if (err) - return err; + if (peer_secid == SECSID_NULL) + err = -EINVAL; + *secid = peer_secid; - return 0; + return err; } static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) @@ -4407,6 +4403,17 @@ static int selinux_setprocattr(struct task_struct *p, return size; } +static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + return security_sid_to_context(secid, secdata, seclen); +} + +static void selinux_release_secctx(char *secdata, u32 seclen) +{ + if (secdata) + kfree(secdata); +} + #ifdef CONFIG_KEYS static int selinux_key_alloc(struct key *k, struct task_struct *tsk, @@ -4587,6 +4594,9 @@ static struct security_operations selinux_ops = { .getprocattr = selinux_getprocattr, .setprocattr = selinux_setprocattr, + .secid_to_secctx = selinux_secid_to_secctx, + .release_secctx = selinux_release_secctx, + .unix_stream_connect = selinux_socket_unix_stream_connect, .unix_may_send = selinux_socket_unix_may_send, diff --git a/trunk/security/selinux/ss/policydb.c b/trunk/security/selinux/ss/policydb.c index 0111990ba837..f03960e697ce 100644 --- a/trunk/security/selinux/ss/policydb.c +++ b/trunk/security/selinux/ss/policydb.c @@ -644,10 +644,18 @@ void policydb_destroy(struct policydb *p) kfree(lra); for (rt = p->range_tr; rt; rt = rt -> next) { - kfree(lrt); + if (lrt) { + ebitmap_destroy(&lrt->range.level[0].cat); + ebitmap_destroy(&lrt->range.level[1].cat); + kfree(lrt); + } lrt = rt; } - kfree(lrt); + if (lrt) { + ebitmap_destroy(&lrt->range.level[0].cat); + ebitmap_destroy(&lrt->range.level[1].cat); + kfree(lrt); + } if (p->type_attr_map) { for (i = 0; i < p->p_types.nprim; i++) diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index d2e80e62ff0c..85e429884393 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -833,6 +833,8 @@ static int security_compute_sid(u32 ssid, goto out; } + context_init(&newcontext); + POLICY_RDLOCK; scontext = sidtab_search(&sidtab, ssid); @@ -850,8 +852,6 @@ static int security_compute_sid(u32 ssid, goto out_unlock; } - context_init(&newcontext); - /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: diff --git a/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c b/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c index bcc555647e79..3c7d1d8a9a6f 100644 --- a/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c +++ b/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c @@ -51,6 +51,13 @@ static struct transfer_info toonie_transfers[] = { {} }; +static int toonie_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + return 1; +} + #ifdef CONFIG_PM static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) { @@ -69,6 +76,7 @@ static struct codec_info toonie_codec_info = { .sysclock_factor = 256, .bus_factor = 64, .owner = THIS_MODULE, + .usable = toonie_usable, #ifdef CONFIG_PM .suspend = toonie_suspend, .resume = toonie_resume, @@ -79,19 +87,20 @@ static int toonie_init_codec(struct aoa_codec *codec) { struct toonie *toonie = codec_to_toonie(codec); + /* nothing connected? what a joke! */ + if (toonie->codec.connected != 1) + return -ENOTCONN; + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { printk(KERN_ERR PFX "failed to create toonie snd device!\n"); return -ENODEV; } - /* nothing connected? what a joke! */ - if (toonie->codec.connected != 1) - return -ENOTCONN; - if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, aoa_get_card(), &toonie_codec_info, toonie)) { printk(KERN_ERR PFX "error creating toonie pcm\n"); + snd_device_free(aoa_get_card(), toonie); return -ENODEV; } diff --git a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c index 7ae0c0bdfad8..f69d33357a28 100644 --- a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c @@ -112,7 +112,10 @@ static struct device_node *get_gpio(char *name, static void get_irq(struct device_node * np, int *irqptr) { - *irqptr = irq_of_parse_and_map(np, 0); + if (np) + *irqptr = irq_of_parse_and_map(np, 0); + else + *irqptr = NO_IRQ; } /* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ @@ -322,7 +325,7 @@ static int ftr_set_notify(struct gpio_runtime *rt, return -EINVAL; } - if (irq == -1) + if (irq == NO_IRQ) return -ENODEV; mutex_lock(¬if->mutex); diff --git a/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c b/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c index 3d57fd1aec4b..2836c3218391 100644 --- a/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c +++ b/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -18,7 +18,7 @@ static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ \ if (unlikely(!rt)) return; \ rc = pmf_call_function(rt->node, #name "-mute", &args); \ - if (rc) \ + if (rc && rc != -ENODEV) \ printk(KERN_WARNING "pmf_gpio_set_" #name \ " failed, rc: %d\n", rc); \ rt->implementation_private &= ~(1<index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { struct snd_ctl_elem_info *uinfo; - uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); + uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); if (! uinfo) { up_read(&mixer->card->controls_rwsem); return -ENOMEM; } - memset(uinfo, 0, sizeof(*uinfo)); if (kctl->info(kctl, uinfo)) { up_read(&mixer->card->controls_rwsem); return 0; diff --git a/trunk/sound/core/oss/pcm_oss.c b/trunk/sound/core/oss/pcm_oss.c index f5ff4f4a16ee..472fce0ee0e8 100644 --- a/trunk/sound/core/oss/pcm_oss.c +++ b/trunk/sound/core/oss/pcm_oss.c @@ -2228,6 +2228,8 @@ static int snd_pcm_oss_open_file(struct file *file, for (idx = 0; idx < 2; idx++) { if (setup[idx].disable) continue; + if (! pcm->streams[idx].substream_count) + continue; /* no matching substream */ if (idx == SNDRV_PCM_STREAM_PLAYBACK) { if (! (f_mode & FMODE_WRITE)) continue; diff --git a/trunk/sound/core/seq/seq_device.c b/trunk/sound/core/seq/seq_device.c index 4260de90f36f..102ff548ce69 100644 --- a/trunk/sound/core/seq/seq_device.c +++ b/trunk/sound/core/seq/seq_device.c @@ -372,10 +372,9 @@ static struct ops_list * create_driver(char *id) { struct ops_list *ops; - ops = kmalloc(sizeof(*ops), GFP_KERNEL); + ops = kzalloc(sizeof(*ops), GFP_KERNEL); if (ops == NULL) return ops; - memset(ops, 0, sizeof(*ops)); /* set up driver entry */ strlcpy(ops->id, id, sizeof(ops->id)); diff --git a/trunk/sound/core/sgbuf.c b/trunk/sound/core/sgbuf.c index 6e4d4ab34632..c30669f14ac0 100644 --- a/trunk/sound/core/sgbuf.c +++ b/trunk/sound/core/sgbuf.c @@ -68,21 +68,18 @@ void *snd_malloc_sgbuf_pages(struct device *device, dmab->area = NULL; dmab->addr = 0; - dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL); + dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); if (! sgbuf) return NULL; - memset(sgbuf, 0, sizeof(*sgbuf)); sgbuf->dev = device; pages = snd_sgbuf_aligned_pages(size); sgbuf->tblsize = sgbuf_align_table(pages); - sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL); + sgbuf->table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->table), GFP_KERNEL); if (! sgbuf->table) goto _failed; - memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize); - sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize, GFP_KERNEL); + sgbuf->page_table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->page_table), GFP_KERNEL); if (! sgbuf->page_table) goto _failed; - memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize); /* allocate each page */ for (i = 0; i < pages; i++) { diff --git a/trunk/sound/drivers/vx/vx_pcm.c b/trunk/sound/drivers/vx/vx_pcm.c index c4af84995d05..7e65a103fbb2 100644 --- a/trunk/sound/drivers/vx/vx_pcm.c +++ b/trunk/sound/drivers/vx/vx_pcm.c @@ -1252,18 +1252,15 @@ static int vx_init_audio_io(struct vx_core *chip) chip->audio_info = rmh.Stat[1]; /* allocate pipes */ - chip->playback_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_outs, GFP_KERNEL); + chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); if (!chip->playback_pipes) return -ENOMEM; - chip->capture_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_ins, GFP_KERNEL); + chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); if (!chip->capture_pipes) { kfree(chip->playback_pipes); return -ENOMEM; } - memset(chip->playback_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_outs); - memset(chip->capture_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_ins); - preferred = chip->ibl.size; chip->ibl.size = 0; vx_set_ibl(chip, &chip->ibl); /* query the info */ diff --git a/trunk/sound/oss/Kconfig b/trunk/sound/oss/Kconfig index f4980ca5c05c..1b7c3dfc2b41 100644 --- a/trunk/sound/oss/Kconfig +++ b/trunk/sound/oss/Kconfig @@ -31,7 +31,7 @@ config SOUND_EMU10K1 For more information on this driver and the degree of support for the different card models please check: - + It is now possible to load dsp microcode patches into the EMU10K1 chip. These patches are used to implement real time sound @@ -140,7 +140,7 @@ config SOUND_TRIDENT system support" and "Sysctl support", and after the /proc file system has been mounted, executing the command - command what is enabled + command what is enabled echo 0>/proc/ALi5451 pcm out is also set to S/PDIF out. (Default). @@ -838,7 +838,7 @@ config SOUND_WAVEARTIST config SOUND_TVMIXER tristate "TV card (bt848) mixer support" - depends on SOUND_PRIME && I2C + depends on SOUND_PRIME && I2C && VIDEO_V4L1 help Support for audio mixer facilities on the BT848 TV frame-grabber card. diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index d7ad32f514da..e49c0fe21b0d 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -16,16 +16,16 @@ config SND_AD1889 will be called snd-ad1889. config SND_ALS300 - tristate "Avance Logic ALS300/ALS300+" - depends on SND - select SND_PCM - select SND_AC97_CODEC - select SND_OPL3_LIB - help - Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ + tristate "Avance Logic ALS300/ALS300+" + depends on SND + select SND_PCM + select SND_AC97_CODEC + select SND_OPL3_LIB + help + Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ - To compile this driver as a module, choose M here: the module - will be called snd-als300 + To compile this driver as a module, choose M here: the module + will be called snd-als300 config SND_ALS4000 tristate "Avance Logic ALS4000" @@ -78,49 +78,49 @@ config SND_ATIIXP_MODEM will be called snd-atiixp-modem. config SND_AU8810 - tristate "Aureal Advantage" - depends on SND + tristate "Aureal Advantage" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Advantage soundcards. Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . + 3D support code is in place, but not yet useable. For more info, + email the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8810. - + config SND_AU8820 - tristate "Aureal Vortex" - depends on SND + tristate "Aureal Vortex" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Vortex soundcards. - Supported features: Hardware Mixer and SRC. For more info, email - the ALSA developer list, or . + Supported features: Hardware Mixer and SRC. For more info, email + the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8820. - + config SND_AU8830 - tristate "Aureal Vortex 2" - depends on SND + tristate "Aureal Vortex 2" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Vortex 2 soundcards. - Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . + Supported features: Hardware Mixer, SRC, EQ and SPDIF output. + 3D support code is in place, but not yet useable. For more info, + email the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8830. - + config SND_AZT3328 tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)" depends on SND && EXPERIMENTAL @@ -135,10 +135,10 @@ config SND_AZT3328 will be called snd-azt3328. config SND_BT87X - tristate "Bt87x Audio Capture" - depends on SND + tristate "Bt87x Audio Capture" + depends on SND select SND_PCM - help + help If you want to record audio from TV cards based on Brooktree Bt878/Bt879 chips, say Y here and read . @@ -209,7 +209,7 @@ config SND_CS46XX config SND_CS46XX_NEW_DSP bool "Cirrus Logic (Sound Fusion) New DSP support" depends on SND_CS46XX - default y + default y help Say Y here to use a new DSP image for SPDIF and dual codecs. @@ -225,7 +225,7 @@ config SND_CS5535AUDIO referred to as NS CS5535 IO or AMD CS5535 IO companion in various literature. This driver also supports the CS5536 audio device. However, for both chips, on certain boards, you may - need to use ac97_quirk=hp_only if your board has physically + need to use ac97_quirk=hp_only if your board has physically mapped headphone out to master output. If that works for you, send lspci -vvv output to the mailing list so that your board can be identified in the quirks list. @@ -468,11 +468,13 @@ config SND_FM801_TEA575X_BOOL FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media Forte SF256-PCS-02) into the snd-fm801 driver. + This will enable support for the old V4L1 API. + config SND_FM801_TEA575X tristate depends on SND_FM801_TEA575X_BOOL default SND_FM801 - select VIDEO_DEV + select VIDEO_V4L1 config SND_HDA_INTEL tristate "Intel HD Audio" diff --git a/trunk/sound/pci/echoaudio/echoaudio.c b/trunk/sound/pci/echoaudio/echoaudio.c index 27a8dbe6f6a8..c3dafa29054f 100644 --- a/trunk/sound/pci/echoaudio/echoaudio.c +++ b/trunk/sound/pci/echoaudio/echoaudio.c @@ -236,9 +236,9 @@ static int pcm_open(struct snd_pcm_substream *substream, chip = snd_pcm_substream_chip(substream); runtime = substream->runtime; - if (!(pipe = kmalloc(sizeof(struct audiopipe), GFP_KERNEL))) + pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL); + if (!pipe) return -ENOMEM; - memset(pipe, 0, sizeof(struct audiopipe)); pipe->index = -1; /* Not configured yet */ /* Set up hw capabilities and contraints */ diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c index f9b5c3dc3b34..79f24cdf5fbf 100644 --- a/trunk/sound/pci/emu10k1/emu10k1_main.c +++ b/trunk/sound/pci/emu10k1/emu10k1_main.c @@ -936,6 +936,17 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0151_chip = 1, .spk71 = 1, .spdif_bug = 1} , + /* Dell OEM/Creative Labs Audigy 2 ZS */ + /* See ALSA bug#1365 */ + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, + .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", .id = "Audigy2", diff --git a/trunk/sound/pci/emu10k1/irq.c b/trunk/sound/pci/emu10k1/irq.c index a8b31286b6db..1076af4c3669 100644 --- a/trunk/sound/pci/emu10k1/irq.c +++ b/trunk/sound/pci/emu10k1/irq.c @@ -37,9 +37,13 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) int handled = 0; while ((status = inl(emu->port + IPR)) != 0) { - //printk("emu10k1 irq - status = 0x%x\n", status); + //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); orig_status = status; handled = 1; + if ((status & 0xffffffff) == 0xffffffff) { + snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); + break; + } if (status & IPR_PCIERROR) { snd_printk(KERN_ERR "interrupt: PCI error\n"); snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); diff --git a/trunk/sound/ppc/awacs.c b/trunk/sound/ppc/awacs.c index 82d791be7499..05dabe454658 100644 --- a/trunk/sound/ppc/awacs.c +++ b/trunk/sound/ppc/awacs.c @@ -801,11 +801,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip) chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf; #ifdef PMAC_AMP_AVAIL if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) { - struct awacs_amp *amp = kmalloc(sizeof(*amp), GFP_KERNEL); + struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL); if (! amp) return -ENOMEM; chip->mixer_data = amp; - memset(amp, 0, sizeof(*amp)); chip->mixer_free = awacs_amp_free; awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */ awacs_amp_set_vol(amp, 1, 63, 63, 0); diff --git a/trunk/sound/ppc/daca.c b/trunk/sound/ppc/daca.c index 46eebf5610e3..57202b0f033e 100644 --- a/trunk/sound/ppc/daca.c +++ b/trunk/sound/ppc/daca.c @@ -258,10 +258,9 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip) request_module("i2c-powermac"); #endif /* CONFIG_KMOD */ - mix = kmalloc(sizeof(*mix), GFP_KERNEL); + mix = kzalloc(sizeof(*mix), GFP_KERNEL); if (! mix) return -ENOMEM; - memset(mix, 0, sizeof(*mix)); chip->mixer_data = mix; chip->mixer_free = daca_cleanup; mix->amp_on = 1; /* default on */ diff --git a/trunk/sound/ppc/keywest.c b/trunk/sound/ppc/keywest.c index fb05938dcbd9..59482a4cd446 100644 --- a/trunk/sound/ppc/keywest.c +++ b/trunk/sound/ppc/keywest.c @@ -64,11 +64,10 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) if (strncmp(i2c_device_name(adapter), "mac-io", 6)) return 0; /* ignored */ - new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (! new_client) return -ENOMEM; - memset(new_client, 0, sizeof(*new_client)); new_client->addr = keywest_ctx->addr; i2c_set_clientdata(new_client, keywest_ctx); new_client->adapter = adapter; diff --git a/trunk/sound/ppc/powermac.c b/trunk/sound/ppc/powermac.c index fa9a44ab487e..2264574fa06b 100644 --- a/trunk/sound/ppc/powermac.c +++ b/trunk/sound/ppc/powermac.c @@ -181,21 +181,14 @@ static int __init alsa_card_pmac_init(void) if ((err = platform_driver_register(&snd_pmac_driver)) < 0) return err; device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); - if (!IS_ERR(device)) { - if (platform_get_drvdata(device)) - return 0; - platform_device_unregister(device); - err = -ENODEV; - } else - err = PTR_ERR(device); - platform_driver_unregister(&snd_pmac_driver); - return err; + return 0; } static void __exit alsa_card_pmac_exit(void) { - platform_device_unregister(device); + if (!IS_ERR(device)) + platform_device_unregister(device); platform_driver_unregister(&snd_pmac_driver); } diff --git a/trunk/sound/ppc/tumbler.c b/trunk/sound/ppc/tumbler.c index 692c61177678..84f6b19c07ca 100644 --- a/trunk/sound/ppc/tumbler.c +++ b/trunk/sound/ppc/tumbler.c @@ -1316,10 +1316,9 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) request_module("i2c-powermac"); #endif /* CONFIG_KMOD */ - mix = kmalloc(sizeof(*mix), GFP_KERNEL); + mix = kzalloc(sizeof(*mix), GFP_KERNEL); if (! mix) return -ENOMEM; - memset(mix, 0, sizeof(*mix)); mix->headphone_irq = -1; chip->mixer_data = mix; diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index d32d83d970cc..1b7f499c549d 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -2260,10 +2260,9 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud } /* create a new pcm */ - as = kmalloc(sizeof(*as), GFP_KERNEL); + as = kzalloc(sizeof(*as), GFP_KERNEL); if (! as) return -ENOMEM; - memset(as, 0, sizeof(*as)); as->pcm_index = chip->pcm_devs; as->chip = chip; as->fmt_type = fp->fmt_type; @@ -2633,13 +2632,12 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) csep = NULL; } - fp = kmalloc(sizeof(*fp), GFP_KERNEL); + fp = kzalloc(sizeof(*fp), GFP_KERNEL); if (! fp) { snd_printk(KERN_ERR "cannot malloc\n"); return -ENOMEM; } - memset(fp, 0, sizeof(*fp)); fp->iface = iface_no; fp->altsetting = altno; fp->altset_idx = i; diff --git a/trunk/usr/Makefile b/trunk/usr/Makefile index e93824269da2..5b31c0b61c76 100644 --- a/trunk/usr/Makefile +++ b/trunk/usr/Makefile @@ -35,6 +35,9 @@ quiet_cmd_initfs = GEN $@ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) targets := initramfs_data.cpio.gz +# do not try to update files included in initramfs +$(deps_initramfs): ; + $(deps_initramfs): klibcdirs # We rebuild initramfs_data.cpio.gz if: # 1) Any included file is newer then initramfs_data.cpio.gz